aboutsummaryrefslogtreecommitdiffstats
path: root/net/l2tp
diff options
context:
space:
mode:
authorChris Elston <celston@katalix.com>2012-04-29 17:48:52 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-01 09:30:55 -0400
commitf9bac8df908d7c0a36960265c92f3445623b19d1 (patch)
tree58bc4af4f65eed62a01027d2358b713b1a060e37 /net/l2tp
parent2121c3f571f08bd723f449f2477f1582709f5a2a (diff)
l2tp: netlink api for l2tpv3 ipv6 unmanaged tunnels
This patch adds support for unmanaged L2TPv3 tunnels over IPv6 using the netlink API. We already support unmanaged L2TPv3 tunnels over IPv4. A patch to iproute2 to make use of this feature will be submitted separately. Signed-off-by: Chris Elston <celston@katalix.com> Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp')
-rw-r--r--net/l2tp/l2tp_core.c78
-rw-r--r--net/l2tp/l2tp_core.h4
-rw-r--r--net/l2tp/l2tp_netlink.c48
3 files changed, 109 insertions, 21 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index f1bfae3e1ba6..55fc569c8170 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1366,31 +1366,68 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
1366{ 1366{
1367 int err = -EINVAL; 1367 int err = -EINVAL;
1368 struct sockaddr_in udp_addr; 1368 struct sockaddr_in udp_addr;
1369#if IS_ENABLED(CONFIG_IPV6)
1370 struct sockaddr_in6 udp6_addr;
1371#endif
1369 struct sockaddr_l2tpip ip_addr; 1372 struct sockaddr_l2tpip ip_addr;
1370 struct socket *sock = NULL; 1373 struct socket *sock = NULL;
1371 1374
1372 switch (cfg->encap) { 1375 switch (cfg->encap) {
1373 case L2TP_ENCAPTYPE_UDP: 1376 case L2TP_ENCAPTYPE_UDP:
1374 err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp); 1377#if IS_ENABLED(CONFIG_IPV6)
1375 if (err < 0) 1378 if (cfg->local_ip6 && cfg->peer_ip6) {
1376 goto out; 1379 err = sock_create(AF_INET6, SOCK_DGRAM, 0, sockp);
1380 if (err < 0)
1381 goto out;
1377 1382
1378 sock = *sockp; 1383 sock = *sockp;
1379 1384
1380 memset(&udp_addr, 0, sizeof(udp_addr)); 1385 memset(&udp6_addr, 0, sizeof(udp6_addr));
1381 udp_addr.sin_family = AF_INET; 1386 udp6_addr.sin6_family = AF_INET6;
1382 udp_addr.sin_addr = cfg->local_ip; 1387 memcpy(&udp6_addr.sin6_addr, cfg->local_ip6,
1383 udp_addr.sin_port = htons(cfg->local_udp_port); 1388 sizeof(udp6_addr.sin6_addr));
1384 err = kernel_bind(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr)); 1389 udp6_addr.sin6_port = htons(cfg->local_udp_port);
1385 if (err < 0) 1390 err = kernel_bind(sock, (struct sockaddr *) &udp6_addr,
1386 goto out; 1391 sizeof(udp6_addr));
1392 if (err < 0)
1393 goto out;
1387 1394
1388 udp_addr.sin_family = AF_INET; 1395 udp6_addr.sin6_family = AF_INET6;
1389 udp_addr.sin_addr = cfg->peer_ip; 1396 memcpy(&udp6_addr.sin6_addr, cfg->peer_ip6,
1390 udp_addr.sin_port = htons(cfg->peer_udp_port); 1397 sizeof(udp6_addr.sin6_addr));
1391 err = kernel_connect(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr), 0); 1398 udp6_addr.sin6_port = htons(cfg->peer_udp_port);
1392 if (err < 0) 1399 err = kernel_connect(sock,
1393 goto out; 1400 (struct sockaddr *) &udp6_addr,
1401 sizeof(udp6_addr), 0);
1402 if (err < 0)
1403 goto out;
1404 } else
1405#endif
1406 {
1407 err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp);
1408 if (err < 0)
1409 goto out;
1410
1411 sock = *sockp;
1412
1413 memset(&udp_addr, 0, sizeof(udp_addr));
1414 udp_addr.sin_family = AF_INET;
1415 udp_addr.sin_addr = cfg->local_ip;
1416 udp_addr.sin_port = htons(cfg->local_udp_port);
1417 err = kernel_bind(sock, (struct sockaddr *) &udp_addr,
1418 sizeof(udp_addr));
1419 if (err < 0)
1420 goto out;
1421
1422 udp_addr.sin_family = AF_INET;
1423 udp_addr.sin_addr = cfg->peer_ip;
1424 udp_addr.sin_port = htons(cfg->peer_udp_port);
1425 err = kernel_connect(sock,
1426 (struct sockaddr *) &udp_addr,
1427 sizeof(udp_addr), 0);
1428 if (err < 0)
1429 goto out;
1430 }
1394 1431
1395 if (!cfg->use_udp_checksums) 1432 if (!cfg->use_udp_checksums)
1396 sock->sk->sk_no_check = UDP_CSUM_NOXMIT; 1433 sock->sk->sk_no_check = UDP_CSUM_NOXMIT;
@@ -1398,6 +1435,13 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
1398 break; 1435 break;
1399 1436
1400 case L2TP_ENCAPTYPE_IP: 1437 case L2TP_ENCAPTYPE_IP:
1438#if IS_ENABLED(CONFIG_IPV6)
1439 if (cfg->local_ip6 && cfg->peer_ip6) {
1440 /* IP encap over IPv6 not yet supported */
1441 err = -EPROTONOSUPPORT;
1442 goto out;
1443 }
1444#endif
1401 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp); 1445 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
1402 if (err < 0) 1446 if (err < 0)
1403 goto out; 1447 goto out;
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index a8c943bf4140..0bf60fc88bb7 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -151,6 +151,10 @@ struct l2tp_tunnel_cfg {
151 /* Used only for kernel-created sockets */ 151 /* Used only for kernel-created sockets */
152 struct in_addr local_ip; 152 struct in_addr local_ip;
153 struct in_addr peer_ip; 153 struct in_addr peer_ip;
154#if IS_ENABLED(CONFIG_IPV6)
155 struct in6_addr *local_ip6;
156 struct in6_addr *peer_ip6;
157#endif
154 u16 local_udp_port; 158 u16 local_udp_port;
155 u16 peer_udp_port; 159 u16 peer_udp_port;
156 unsigned int use_udp_checksums:1; 160 unsigned int use_udp_checksums:1;
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 1dbb9772fc45..24edad0fd9ba 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -133,10 +133,25 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
133 if (info->attrs[L2TP_ATTR_FD]) { 133 if (info->attrs[L2TP_ATTR_FD]) {
134 fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]); 134 fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
135 } else { 135 } else {
136 if (info->attrs[L2TP_ATTR_IP_SADDR]) 136#if IS_ENABLED(CONFIG_IPV6)
137 cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]); 137 if (info->attrs[L2TP_ATTR_IP6_SADDR] &&
138 if (info->attrs[L2TP_ATTR_IP_DADDR]) 138 info->attrs[L2TP_ATTR_IP6_DADDR]) {
139 cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]); 139 cfg.local_ip6 = nla_data(
140 info->attrs[L2TP_ATTR_IP6_SADDR]);
141 cfg.peer_ip6 = nla_data(
142 info->attrs[L2TP_ATTR_IP6_DADDR]);
143 } else
144#endif
145 if (info->attrs[L2TP_ATTR_IP_SADDR] &&
146 info->attrs[L2TP_ATTR_IP_DADDR]) {
147 cfg.local_ip.s_addr = nla_get_be32(
148 info->attrs[L2TP_ATTR_IP_SADDR]);
149 cfg.peer_ip.s_addr = nla_get_be32(
150 info->attrs[L2TP_ATTR_IP_DADDR]);
151 } else {
152 ret = -EINVAL;
153 goto out;
154 }
140 if (info->attrs[L2TP_ATTR_UDP_SPORT]) 155 if (info->attrs[L2TP_ATTR_UDP_SPORT])
141 cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]); 156 cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
142 if (info->attrs[L2TP_ATTR_UDP_DPORT]) 157 if (info->attrs[L2TP_ATTR_UDP_DPORT])
@@ -225,6 +240,9 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
225 struct nlattr *nest; 240 struct nlattr *nest;
226 struct sock *sk = NULL; 241 struct sock *sk = NULL;
227 struct inet_sock *inet; 242 struct inet_sock *inet;
243#if IS_ENABLED(CONFIG_IPV6)
244 struct ipv6_pinfo *np = NULL;
245#endif
228 struct l2tp_stats stats; 246 struct l2tp_stats stats;
229 unsigned int start; 247 unsigned int start;
230 248
@@ -273,6 +291,11 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
273 if (!sk) 291 if (!sk)
274 goto out; 292 goto out;
275 293
294#if IS_ENABLED(CONFIG_IPV6)
295 if (sk->sk_family == AF_INET6)
296 np = inet6_sk(sk);
297#endif
298
276 inet = inet_sk(sk); 299 inet = inet_sk(sk);
277 300
278 switch (tunnel->encap) { 301 switch (tunnel->encap) {
@@ -284,6 +307,15 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
284 goto nla_put_failure; 307 goto nla_put_failure;
285 /* NOBREAK */ 308 /* NOBREAK */
286 case L2TP_ENCAPTYPE_IP: 309 case L2TP_ENCAPTYPE_IP:
310#if IS_ENABLED(CONFIG_IPV6)
311 if (np) {
312 if (nla_put(skb, L2TP_ATTR_IP6_SADDR, sizeof(np->saddr),
313 &np->saddr) ||
314 nla_put(skb, L2TP_ATTR_IP6_DADDR, sizeof(np->daddr),
315 &np->daddr))
316 goto nla_put_failure;
317 } else
318#endif
287 if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) || 319 if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) ||
288 nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr)) 320 nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr))
289 goto nla_put_failure; 321 goto nla_put_failure;
@@ -752,6 +784,14 @@ static struct nla_policy l2tp_nl_policy[L2TP_ATTR_MAX + 1] = {
752 [L2TP_ATTR_MTU] = { .type = NLA_U16, }, 784 [L2TP_ATTR_MTU] = { .type = NLA_U16, },
753 [L2TP_ATTR_MRU] = { .type = NLA_U16, }, 785 [L2TP_ATTR_MRU] = { .type = NLA_U16, },
754 [L2TP_ATTR_STATS] = { .type = NLA_NESTED, }, 786 [L2TP_ATTR_STATS] = { .type = NLA_NESTED, },
787 [L2TP_ATTR_IP6_SADDR] = {
788 .type = NLA_BINARY,
789 .len = sizeof(struct in6_addr),
790 },
791 [L2TP_ATTR_IP6_DADDR] = {
792 .type = NLA_BINARY,
793 .len = sizeof(struct in6_addr),
794 },
755 [L2TP_ATTR_IFNAME] = { 795 [L2TP_ATTR_IFNAME] = {
756 .type = NLA_NUL_STRING, 796 .type = NLA_NUL_STRING,
757 .len = IFNAMSIZ - 1, 797 .len = IFNAMSIZ - 1,