Commit 5dac94e1 authored by James Chapman's avatar James Chapman Committed by David S. Miller

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: default avatarJames Chapman <jchapman@katalix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a32e0eec
...@@ -1368,6 +1368,7 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t ...@@ -1368,6 +1368,7 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
struct sockaddr_in udp_addr; struct sockaddr_in udp_addr;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
struct sockaddr_in6 udp6_addr; struct sockaddr_in6 udp6_addr;
struct sockaddr_l2tpip6 ip6_addr;
#endif #endif
struct sockaddr_l2tpip ip_addr; struct sockaddr_l2tpip ip_addr;
struct socket *sock = NULL; struct socket *sock = NULL;
...@@ -1437,32 +1438,59 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t ...@@ -1437,32 +1438,59 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
case L2TP_ENCAPTYPE_IP: case L2TP_ENCAPTYPE_IP:
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (cfg->local_ip6 && cfg->peer_ip6) { if (cfg->local_ip6 && cfg->peer_ip6) {
/* IP encap over IPv6 not yet supported */ err = sock_create(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP,
err = -EPROTONOSUPPORT; sockp);
goto out; if (err < 0)
} goto out;
#endif
err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
if (err < 0)
goto out;
sock = *sockp; sock = *sockp;
memset(&ip_addr, 0, sizeof(ip_addr)); memset(&ip6_addr, 0, sizeof(ip6_addr));
ip_addr.l2tp_family = AF_INET; ip6_addr.l2tp_family = AF_INET6;
ip_addr.l2tp_addr = cfg->local_ip; memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
ip_addr.l2tp_conn_id = tunnel_id; sizeof(ip6_addr.l2tp_addr));
err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr)); ip6_addr.l2tp_conn_id = tunnel_id;
if (err < 0) err = kernel_bind(sock, (struct sockaddr *) &ip6_addr,
goto out; sizeof(ip6_addr));
if (err < 0)
goto out;
ip_addr.l2tp_family = AF_INET; ip6_addr.l2tp_family = AF_INET6;
ip_addr.l2tp_addr = cfg->peer_ip; memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6,
ip_addr.l2tp_conn_id = peer_tunnel_id; sizeof(ip6_addr.l2tp_addr));
err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0); ip6_addr.l2tp_conn_id = peer_tunnel_id;
if (err < 0) err = kernel_connect(sock,
goto out; (struct sockaddr *) &ip6_addr,
sizeof(ip6_addr), 0);
if (err < 0)
goto out;
} else
#endif
{
err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP,
sockp);
if (err < 0)
goto out;
sock = *sockp;
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.l2tp_family = AF_INET;
ip_addr.l2tp_addr = cfg->local_ip;
ip_addr.l2tp_conn_id = tunnel_id;
err = kernel_bind(sock, (struct sockaddr *) &ip_addr,
sizeof(ip_addr));
if (err < 0)
goto out;
ip_addr.l2tp_family = AF_INET;
ip_addr.l2tp_addr = cfg->peer_ip;
ip_addr.l2tp_conn_id = peer_tunnel_id;
err = kernel_connect(sock, (struct sockaddr *) &ip_addr,
sizeof(ip_addr), 0);
if (err < 0)
goto out;
}
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment