Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+50 −22
Original line number Original line Diff line number Diff line
@@ -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,12 +1438,37 @@ 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);
			if (err < 0)
				goto out;
				goto out;
		}

			sock = *sockp;

			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;

			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
#endif
		err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
		{
			err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP,
					  sockp);
			if (err < 0)
			if (err < 0)
				goto out;
				goto out;


@@ -1452,17 +1478,19 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t
			ip_addr.l2tp_family = AF_INET;
			ip_addr.l2tp_family = AF_INET;
			ip_addr.l2tp_addr = cfg->local_ip;
			ip_addr.l2tp_addr = cfg->local_ip;
			ip_addr.l2tp_conn_id = tunnel_id;
			ip_addr.l2tp_conn_id = tunnel_id;
		err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr));
			err = kernel_bind(sock, (struct sockaddr *) &ip_addr,
					  sizeof(ip_addr));
			if (err < 0)
			if (err < 0)
				goto out;
				goto out;


			ip_addr.l2tp_family = AF_INET;
			ip_addr.l2tp_family = AF_INET;
			ip_addr.l2tp_addr = cfg->peer_ip;
			ip_addr.l2tp_addr = cfg->peer_ip;
			ip_addr.l2tp_conn_id = peer_tunnel_id;
			ip_addr.l2tp_conn_id = peer_tunnel_id;
		err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0);
			err = kernel_connect(sock, (struct sockaddr *) &ip_addr,
					     sizeof(ip_addr), 0);
			if (err < 0)
			if (err < 0)
				goto out;
				goto out;

		}
		break;
		break;


	default:
	default: