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 | |
| 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>
| -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: |
