aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Chapman <jchapman@katalix.com>2010-04-02 02:19:40 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-03 17:56:08 -0400
commit789a4a2c61d843df67988d69e7c3f3a4bca97e8e (patch)
tree9f98e9903e34b9a583fa5f8ff03551c77d194c43
parent0ad6614048cf722e4d27909665b4846805357f1b (diff)
l2tp: Add support for static unmanaged L2TPv3 tunnels
This patch adds support for static (unmanaged) L2TPv3 tunnels, where the tunnel socket is created by the kernel rather than being created by userspace. This means L2TP tunnels and sessions can be created manually, without needing an L2TP control protocol implemented in userspace. This might be useful where the user wants a simple ethernet over IP tunnel. A patch to iproute2 adds a new command set under "ip l2tp" to make use of this feature. This will be submitted separately. Signed-off-by: James Chapman <jchapman@katalix.com> Reviewed-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/l2tp/l2tp_core.c115
-rw-r--r--net/l2tp/l2tp_core.h7
-rw-r--r--net/l2tp/l2tp_netlink.c18
3 files changed, 126 insertions, 14 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 473cf2d63905..13ed85baf4e9 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1218,6 +1218,82 @@ void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
1218} 1218}
1219EXPORT_SYMBOL_GPL(l2tp_tunnel_free); 1219EXPORT_SYMBOL_GPL(l2tp_tunnel_free);
1220 1220
1221/* Create a socket for the tunnel, if one isn't set up by
1222 * userspace. This is used for static tunnels where there is no
1223 * managing L2TP daemon.
1224 */
1225static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct socket **sockp)
1226{
1227 int err = -EINVAL;
1228 struct sockaddr_in udp_addr;
1229 struct sockaddr_l2tpip ip_addr;
1230 struct socket *sock;
1231
1232 switch (cfg->encap) {
1233 case L2TP_ENCAPTYPE_UDP:
1234 err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp);
1235 if (err < 0)
1236 goto out;
1237
1238 sock = *sockp;
1239
1240 memset(&udp_addr, 0, sizeof(udp_addr));
1241 udp_addr.sin_family = AF_INET;
1242 udp_addr.sin_addr = cfg->local_ip;
1243 udp_addr.sin_port = htons(cfg->local_udp_port);
1244 err = kernel_bind(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
1245 if (err < 0)
1246 goto out;
1247
1248 udp_addr.sin_family = AF_INET;
1249 udp_addr.sin_addr = cfg->peer_ip;
1250 udp_addr.sin_port = htons(cfg->peer_udp_port);
1251 err = kernel_connect(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr), 0);
1252 if (err < 0)
1253 goto out;
1254
1255 if (!cfg->use_udp_checksums)
1256 sock->sk->sk_no_check = UDP_CSUM_NOXMIT;
1257
1258 break;
1259
1260 case L2TP_ENCAPTYPE_IP:
1261 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
1262 if (err < 0)
1263 goto out;
1264
1265 sock = *sockp;
1266
1267 memset(&ip_addr, 0, sizeof(ip_addr));
1268 ip_addr.l2tp_family = AF_INET;
1269 ip_addr.l2tp_addr = cfg->local_ip;
1270 ip_addr.l2tp_conn_id = tunnel_id;
1271 err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr));
1272 if (err < 0)
1273 goto out;
1274
1275 ip_addr.l2tp_family = AF_INET;
1276 ip_addr.l2tp_addr = cfg->peer_ip;
1277 ip_addr.l2tp_conn_id = peer_tunnel_id;
1278 err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0);
1279 if (err < 0)
1280 goto out;
1281
1282 break;
1283
1284 default:
1285 goto out;
1286 }
1287
1288out:
1289 if ((err < 0) && sock) {
1290 sock_release(sock);
1291 *sockp = NULL;
1292 }
1293
1294 return err;
1295}
1296
1221int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) 1297int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
1222{ 1298{
1223 struct l2tp_tunnel *tunnel = NULL; 1299 struct l2tp_tunnel *tunnel = NULL;
@@ -1228,14 +1304,21 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1228 enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; 1304 enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
1229 1305
1230 /* Get the tunnel socket from the fd, which was opened by 1306 /* Get the tunnel socket from the fd, which was opened by
1231 * the userspace L2TP daemon. 1307 * the userspace L2TP daemon. If not specified, create a
1308 * kernel socket.
1232 */ 1309 */
1233 err = -EBADF; 1310 if (fd < 0) {
1234 sock = sockfd_lookup(fd, &err); 1311 err = l2tp_tunnel_sock_create(tunnel_id, peer_tunnel_id, cfg, &sock);
1235 if (!sock) { 1312 if (err < 0)
1236 printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n", 1313 goto err;
1237 tunnel_id, fd, err); 1314 } else {
1238 goto err; 1315 err = -EBADF;
1316 sock = sockfd_lookup(fd, &err);
1317 if (!sock) {
1318 printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
1319 tunnel_id, fd, err);
1320 goto err;
1321 }
1239 } 1322 }
1240 1323
1241 sk = sock->sk; 1324 sk = sock->sk;
@@ -1329,7 +1412,10 @@ err:
1329 if (tunnelp) 1412 if (tunnelp)
1330 *tunnelp = tunnel; 1413 *tunnelp = tunnel;
1331 1414
1332 if (sock) 1415 /* If tunnel's socket was created by the kernel, it doesn't
1416 * have a file.
1417 */
1418 if (sock && sock->file)
1333 sockfd_put(sock); 1419 sockfd_put(sock);
1334 1420
1335 return err; 1421 return err;
@@ -1341,13 +1427,22 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
1341int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) 1427int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
1342{ 1428{
1343 int err = 0; 1429 int err = 0;
1430 struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL;
1344 1431
1345 /* Force the tunnel socket to close. This will eventually 1432 /* Force the tunnel socket to close. This will eventually
1346 * cause the tunnel to be deleted via the normal socket close 1433 * cause the tunnel to be deleted via the normal socket close
1347 * mechanisms when userspace closes the tunnel socket. 1434 * mechanisms when userspace closes the tunnel socket.
1348 */ 1435 */
1349 if ((tunnel->sock != NULL) && (tunnel->sock->sk_socket != NULL)) 1436 if (sock != NULL) {
1350 err = inet_shutdown(tunnel->sock->sk_socket, 2); 1437 err = inet_shutdown(sock, 2);
1438
1439 /* If the tunnel's socket was created by the kernel,
1440 * close the socket here since the socket was not
1441 * created by userspace.
1442 */
1443 if (sock->file == NULL)
1444 err = inet_release(sock);
1445 }
1351 1446
1352 return err; 1447 return err;
1353} 1448}
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 571335530c6f..a961c77e0867 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -146,6 +146,13 @@ struct l2tp_tunnel_cfg {
146 int debug; /* bitmask of debug message 146 int debug; /* bitmask of debug message
147 * categories */ 147 * categories */
148 enum l2tp_encap_type encap; 148 enum l2tp_encap_type encap;
149
150 /* Used only for kernel-created sockets */
151 struct in_addr local_ip;
152 struct in_addr peer_ip;
153 u16 local_udp_port;
154 u16 peer_udp_port;
155 int use_udp_checksums:1;
149}; 156};
150 157
151struct l2tp_tunnel { 158struct l2tp_tunnel {
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 3d0f7f6f7488..12341a6cc70e 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -129,11 +129,21 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
129 } 129 }
130 cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]); 130 cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]);
131 131
132 if (!info->attrs[L2TP_ATTR_FD]) { 132 fd = -1;
133 ret = -EINVAL; 133 if (info->attrs[L2TP_ATTR_FD]) {
134 goto out; 134 fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
135 } else {
136 if (info->attrs[L2TP_ATTR_IP_SADDR])
137 cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]);
138 if (info->attrs[L2TP_ATTR_IP_DADDR])
139 cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]);
140 if (info->attrs[L2TP_ATTR_UDP_SPORT])
141 cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
142 if (info->attrs[L2TP_ATTR_UDP_DPORT])
143 cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
144 if (info->attrs[L2TP_ATTR_UDP_CSUM])
145 cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
135 } 146 }
136 fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
137 147
138 if (info->attrs[L2TP_ATTR_DEBUG]) 148 if (info->attrs[L2TP_ATTR_DEBUG])
139 cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); 149 cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);