diff options
author | James Chapman <jchapman@katalix.com> | 2012-04-29 17:48:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-01 09:30:55 -0400 |
commit | 5dac94e109263e75ab7fe4e66ef88e9b49f500bf (patch) | |
tree | d87a313b3078911e612e7b18d99853be282b7700 /net/l2tp | |
parent | a32e0eec7042b21ccb52896cf715e3e2641fed93 (diff) |
l2tp: let iproute2 create L2TPv3 IP tunnels using IPv6
The netlink API lets users create unmanaged L2TPv3 tunnels using
iproute2. Until now, a request to create an unmanaged L2TPv3 IP
encapsulation tunnel over IPv6 would be rejected with
EPROTONOSUPPORT. Now that l2tp_ip6 implements sockets for L2TP IP
encapsulation over IPv6, we can add support for that tunnel type.
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.c | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 55fc569c8170..456b52d8f6d8 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1368,6 +1368,7 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
1368 | struct sockaddr_in udp_addr; | 1368 | struct sockaddr_in udp_addr; |
1369 | #if IS_ENABLED(CONFIG_IPV6) | 1369 | #if IS_ENABLED(CONFIG_IPV6) |
1370 | struct sockaddr_in6 udp6_addr; | 1370 | struct sockaddr_in6 udp6_addr; |
1371 | struct sockaddr_l2tpip6 ip6_addr; | ||
1371 | #endif | 1372 | #endif |
1372 | struct sockaddr_l2tpip ip_addr; | 1373 | struct sockaddr_l2tpip ip_addr; |
1373 | struct socket *sock = NULL; | 1374 | struct socket *sock = NULL; |
@@ -1437,32 +1438,59 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
1437 | case L2TP_ENCAPTYPE_IP: | 1438 | case L2TP_ENCAPTYPE_IP: |
1438 | #if IS_ENABLED(CONFIG_IPV6) | 1439 | #if IS_ENABLED(CONFIG_IPV6) |
1439 | if (cfg->local_ip6 && cfg->peer_ip6) { | 1440 | if (cfg->local_ip6 && cfg->peer_ip6) { |
1440 | /* IP encap over IPv6 not yet supported */ | 1441 | err = sock_create(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP, |
1441 | err = -EPROTONOSUPPORT; | 1442 | sockp); |
1442 | goto out; | 1443 | if (err < 0) |
1443 | } | 1444 | goto out; |
1444 | #endif | ||
1445 | err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp); | ||
1446 | if (err < 0) | ||
1447 | goto out; | ||
1448 | 1445 | ||
1449 | sock = *sockp; | 1446 | sock = *sockp; |
1450 | 1447 | ||
1451 | memset(&ip_addr, 0, sizeof(ip_addr)); | 1448 | memset(&ip6_addr, 0, sizeof(ip6_addr)); |
1452 | ip_addr.l2tp_family = AF_INET; | 1449 | ip6_addr.l2tp_family = AF_INET6; |
1453 | ip_addr.l2tp_addr = cfg->local_ip; | 1450 | memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6, |
1454 | ip_addr.l2tp_conn_id = tunnel_id; | 1451 | sizeof(ip6_addr.l2tp_addr)); |
1455 | err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr)); | 1452 | ip6_addr.l2tp_conn_id = tunnel_id; |
1456 | if (err < 0) | 1453 | err = kernel_bind(sock, (struct sockaddr *) &ip6_addr, |
1457 | goto out; | 1454 | sizeof(ip6_addr)); |
1455 | if (err < 0) | ||
1456 | goto out; | ||
1458 | 1457 | ||
1459 | ip_addr.l2tp_family = AF_INET; | 1458 | ip6_addr.l2tp_family = AF_INET6; |
1460 | ip_addr.l2tp_addr = cfg->peer_ip; | 1459 | memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6, |
1461 | ip_addr.l2tp_conn_id = peer_tunnel_id; | 1460 | sizeof(ip6_addr.l2tp_addr)); |
1462 | err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0); | 1461 | ip6_addr.l2tp_conn_id = peer_tunnel_id; |
1463 | if (err < 0) | 1462 | err = kernel_connect(sock, |
1464 | goto out; | 1463 | (struct sockaddr *) &ip6_addr, |
1464 | sizeof(ip6_addr), 0); | ||
1465 | if (err < 0) | ||
1466 | goto out; | ||
1467 | } else | ||
1468 | #endif | ||
1469 | { | ||
1470 | err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, | ||
1471 | sockp); | ||
1472 | if (err < 0) | ||
1473 | goto out; | ||
1465 | 1474 | ||
1475 | sock = *sockp; | ||
1476 | |||
1477 | memset(&ip_addr, 0, sizeof(ip_addr)); | ||
1478 | ip_addr.l2tp_family = AF_INET; | ||
1479 | ip_addr.l2tp_addr = cfg->local_ip; | ||
1480 | ip_addr.l2tp_conn_id = tunnel_id; | ||
1481 | err = kernel_bind(sock, (struct sockaddr *) &ip_addr, | ||
1482 | sizeof(ip_addr)); | ||
1483 | if (err < 0) | ||
1484 | goto out; | ||
1485 | |||
1486 | ip_addr.l2tp_family = AF_INET; | ||
1487 | ip_addr.l2tp_addr = cfg->peer_ip; | ||
1488 | ip_addr.l2tp_conn_id = peer_tunnel_id; | ||
1489 | err = kernel_connect(sock, (struct sockaddr *) &ip_addr, | ||
1490 | sizeof(ip_addr), 0); | ||
1491 | if (err < 0) | ||
1492 | goto out; | ||
1493 | } | ||
1466 | break; | 1494 | break; |
1467 | 1495 | ||
1468 | default: | 1496 | default: |