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

Commit a43a9ef6 authored by Jiri Benc's avatar Jiri Benc Committed by David S. Miller
Browse files

vxlan: do not receive IPv4 packets on IPv6 socket



By default (subject to the sysctl settings), IPv6 sockets listen also for
IPv4 traffic. Vxlan is not prepared for that and expects IPv6 header in
packets received through an IPv6 socket.

In addition, it's currently not possible to have both IPv4 and IPv6 vxlan
tunnel on the same port (unless bindv6only sysctl is enabled), as it's not
possible to create and bind both IPv4 and IPv6 vxlan interfaces and there's
no way to specify both IPv4 and IPv6 remote/group IP addresses.

Set IPV6_V6ONLY on vxlan sockets to fix both of these issues. This is not
done globally in udp_tunnel, as l2tp and tipc seems to work okay when
receiving IPv4 packets on IPv6 socket and people may rely on this behavior.
The other tunnels (geneve and fou) do not support IPv6.

Signed-off-by: default avatarJiri Benc <jbenc@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9b6695c
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -2530,6 +2530,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
		udp_conf.family = AF_INET6;
		udp_conf.family = AF_INET6;
		udp_conf.use_udp6_rx_checksums =
		udp_conf.use_udp6_rx_checksums =
		    !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
		    !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
		udp_conf.ipv6_v6only = 1;
	} else {
	} else {
		udp_conf.family = AF_INET;
		udp_conf.family = AF_INET;
	}
	}
+2 −1
Original line number Original line Diff line number Diff line
@@ -31,7 +31,8 @@ struct udp_port_cfg {
	__be16			peer_udp_port;
	__be16			peer_udp_port;
	unsigned int		use_udp_checksums:1,
	unsigned int		use_udp_checksums:1,
				use_udp6_tx_checksums:1,
				use_udp6_tx_checksums:1,
				use_udp6_rx_checksums:1;
				use_udp6_rx_checksums:1,
				ipv6_v6only:1;
};
};


int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
+9 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,15 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
	if (err < 0)
	if (err < 0)
		goto error;
		goto error;


	if (cfg->ipv6_v6only) {
		int val = 1;

		err = kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
					(char *) &val, sizeof(val));
		if (err < 0)
			goto error;
	}

	udp6_addr.sin6_family = AF_INET6;
	udp6_addr.sin6_family = AF_INET6;
	memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
	memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
	       sizeof(udp6_addr.sin6_addr));
	       sizeof(udp6_addr.sin6_addr));