Skip to content

Commit

Permalink
l2tp: let iproute2 create L2TPv3 IP tunnels using IPv6
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Chapman authored and David S. Miller committed May 1, 2012
1 parent a32e0ee commit 5dac94e
Showing 1 changed file with 50 additions and 22 deletions.
72 changes: 50 additions & 22 deletions net/l2tp/l2tp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,7 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
struct sockaddr_in udp_addr;
#if IS_ENABLED(CONFIG_IPV6)
struct sockaddr_in6 udp6_addr;
struct sockaddr_l2tpip6 ip6_addr;
#endif
struct sockaddr_l2tpip ip_addr;
struct socket *sock = NULL;
Expand Down Expand Up @@ -1437,32 +1438,59 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
case L2TP_ENCAPTYPE_IP:
#if IS_ENABLED(CONFIG_IPV6)
if (cfg->local_ip6 && cfg->peer_ip6) {
/* IP encap over IPv6 not yet supported */
err = -EPROTONOSUPPORT;
goto out;
}
#endif
err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
if (err < 0)
goto out;
err = sock_create(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP,
sockp);
if (err < 0)
goto out;

sock = *sockp;
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;
memset(&ip6_addr, 0, sizeof(ip6_addr));
ip6_addr.l2tp_family = AF_INET6;
memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
sizeof(ip6_addr.l2tp_addr));
ip6_addr.l2tp_conn_id = tunnel_id;
err = kernel_bind(sock, (struct sockaddr *) &ip6_addr,
sizeof(ip6_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;
ip6_addr.l2tp_family = AF_INET6;
memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6,
sizeof(ip6_addr.l2tp_addr));
ip6_addr.l2tp_conn_id = peer_tunnel_id;
err = kernel_connect(sock,
(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;

default:
Expand Down

0 comments on commit 5dac94e

Please sign in to comment.