1a498c595SRoopa Prabhu // SPDX-License-Identifier: GPL-2.0-only
2a498c595SRoopa Prabhu /*
3a498c595SRoopa Prabhu  *	Vxlan multicast group handling
4a498c595SRoopa Prabhu  *
5a498c595SRoopa Prabhu  */
6a498c595SRoopa Prabhu #include <linux/kernel.h>
7a498c595SRoopa Prabhu #include <net/net_namespace.h>
8a498c595SRoopa Prabhu #include <net/sock.h>
9a498c595SRoopa Prabhu #include <linux/igmp.h>
10a498c595SRoopa Prabhu #include <net/vxlan.h>
11a498c595SRoopa Prabhu 
12a498c595SRoopa Prabhu #include "vxlan_private.h"
13a498c595SRoopa Prabhu 
14a498c595SRoopa Prabhu /* Update multicast group membership when first VNI on
15a498c595SRoopa Prabhu  * multicast address is brought up
16a498c595SRoopa Prabhu  */
vxlan_igmp_join(struct vxlan_dev * vxlan,union vxlan_addr * rip,int rifindex)17a498c595SRoopa Prabhu int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
18a498c595SRoopa Prabhu 		    int rifindex)
19a498c595SRoopa Prabhu {
20a498c595SRoopa Prabhu 	union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
21a498c595SRoopa Prabhu 	int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
22a498c595SRoopa Prabhu 	int ret = -EINVAL;
23a498c595SRoopa Prabhu 	struct sock *sk;
24a498c595SRoopa Prabhu 
25a498c595SRoopa Prabhu 	if (ip->sa.sa_family == AF_INET) {
26a498c595SRoopa Prabhu 		struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
27a498c595SRoopa Prabhu 		struct ip_mreqn mreq = {
28a498c595SRoopa Prabhu 			.imr_multiaddr.s_addr	= ip->sin.sin_addr.s_addr,
29a498c595SRoopa Prabhu 			.imr_ifindex		= ifindex,
30a498c595SRoopa Prabhu 		};
31a498c595SRoopa Prabhu 
32a498c595SRoopa Prabhu 		sk = sock4->sock->sk;
33a498c595SRoopa Prabhu 		lock_sock(sk);
34a498c595SRoopa Prabhu 		ret = ip_mc_join_group(sk, &mreq);
35a498c595SRoopa Prabhu 		release_sock(sk);
36a498c595SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
37a498c595SRoopa Prabhu 	} else {
38a498c595SRoopa Prabhu 		struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
39a498c595SRoopa Prabhu 
40a498c595SRoopa Prabhu 		sk = sock6->sock->sk;
41a498c595SRoopa Prabhu 		lock_sock(sk);
42a498c595SRoopa Prabhu 		ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
43a498c595SRoopa Prabhu 						   &ip->sin6.sin6_addr);
44a498c595SRoopa Prabhu 		release_sock(sk);
45a498c595SRoopa Prabhu #endif
46a498c595SRoopa Prabhu 	}
47a498c595SRoopa Prabhu 
48a498c595SRoopa Prabhu 	return ret;
49a498c595SRoopa Prabhu }
50a498c595SRoopa Prabhu 
vxlan_igmp_leave(struct vxlan_dev * vxlan,union vxlan_addr * rip,int rifindex)51a498c595SRoopa Prabhu int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
52a498c595SRoopa Prabhu 		     int rifindex)
53a498c595SRoopa Prabhu {
54a498c595SRoopa Prabhu 	union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
55a498c595SRoopa Prabhu 	int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
56a498c595SRoopa Prabhu 	int ret = -EINVAL;
57a498c595SRoopa Prabhu 	struct sock *sk;
58a498c595SRoopa Prabhu 
59a498c595SRoopa Prabhu 	if (ip->sa.sa_family == AF_INET) {
60a498c595SRoopa Prabhu 		struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
61a498c595SRoopa Prabhu 		struct ip_mreqn mreq = {
62a498c595SRoopa Prabhu 			.imr_multiaddr.s_addr	= ip->sin.sin_addr.s_addr,
63a498c595SRoopa Prabhu 			.imr_ifindex		= ifindex,
64a498c595SRoopa Prabhu 		};
65a498c595SRoopa Prabhu 
66a498c595SRoopa Prabhu 		sk = sock4->sock->sk;
67a498c595SRoopa Prabhu 		lock_sock(sk);
68a498c595SRoopa Prabhu 		ret = ip_mc_leave_group(sk, &mreq);
69a498c595SRoopa Prabhu 		release_sock(sk);
70a498c595SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
71a498c595SRoopa Prabhu 	} else {
72a498c595SRoopa Prabhu 		struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
73a498c595SRoopa Prabhu 
74a498c595SRoopa Prabhu 		sk = sock6->sock->sk;
75a498c595SRoopa Prabhu 		lock_sock(sk);
76a498c595SRoopa Prabhu 		ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
77a498c595SRoopa Prabhu 						   &ip->sin6.sin6_addr);
78a498c595SRoopa Prabhu 		release_sock(sk);
79a498c595SRoopa Prabhu #endif
80a498c595SRoopa Prabhu 	}
81a498c595SRoopa Prabhu 
82a498c595SRoopa Prabhu 	return ret;
83a498c595SRoopa Prabhu }
84a498c595SRoopa Prabhu 
vxlan_group_used_match(union vxlan_addr * ip,int ifindex,union vxlan_addr * rip,int rifindex)85*f9c4bb0bSRoopa Prabhu static bool vxlan_group_used_match(union vxlan_addr *ip, int ifindex,
86*f9c4bb0bSRoopa Prabhu 				   union vxlan_addr *rip, int rifindex)
87*f9c4bb0bSRoopa Prabhu {
88*f9c4bb0bSRoopa Prabhu 	if (!vxlan_addr_multicast(rip))
89*f9c4bb0bSRoopa Prabhu 		return false;
90*f9c4bb0bSRoopa Prabhu 
91*f9c4bb0bSRoopa Prabhu 	if (!vxlan_addr_equal(rip, ip))
92*f9c4bb0bSRoopa Prabhu 		return false;
93*f9c4bb0bSRoopa Prabhu 
94*f9c4bb0bSRoopa Prabhu 	if (rifindex != ifindex)
95*f9c4bb0bSRoopa Prabhu 		return false;
96*f9c4bb0bSRoopa Prabhu 
97*f9c4bb0bSRoopa Prabhu 	return true;
98*f9c4bb0bSRoopa Prabhu }
99*f9c4bb0bSRoopa Prabhu 
vxlan_group_used_by_vnifilter(struct vxlan_dev * vxlan,union vxlan_addr * ip,int ifindex)100*f9c4bb0bSRoopa Prabhu static bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan,
101*f9c4bb0bSRoopa Prabhu 					  union vxlan_addr *ip, int ifindex)
102*f9c4bb0bSRoopa Prabhu {
103*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
104*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_node *v, *tmp;
105*f9c4bb0bSRoopa Prabhu 
106*f9c4bb0bSRoopa Prabhu 	if (vxlan_group_used_match(ip, ifindex,
107*f9c4bb0bSRoopa Prabhu 				   &vxlan->default_dst.remote_ip,
108*f9c4bb0bSRoopa Prabhu 				   vxlan->default_dst.remote_ifindex))
109*f9c4bb0bSRoopa Prabhu 		return true;
110*f9c4bb0bSRoopa Prabhu 
111*f9c4bb0bSRoopa Prabhu 	list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
112*f9c4bb0bSRoopa Prabhu 		if (!vxlan_addr_multicast(&v->remote_ip))
113*f9c4bb0bSRoopa Prabhu 			continue;
114*f9c4bb0bSRoopa Prabhu 
115*f9c4bb0bSRoopa Prabhu 		if (vxlan_group_used_match(ip, ifindex,
116*f9c4bb0bSRoopa Prabhu 					   &v->remote_ip,
117*f9c4bb0bSRoopa Prabhu 					   vxlan->default_dst.remote_ifindex))
118*f9c4bb0bSRoopa Prabhu 			return true;
119*f9c4bb0bSRoopa Prabhu 	}
120*f9c4bb0bSRoopa Prabhu 
121*f9c4bb0bSRoopa Prabhu 	return false;
122*f9c4bb0bSRoopa Prabhu }
123*f9c4bb0bSRoopa Prabhu 
124a498c595SRoopa Prabhu /* See if multicast group is already in use by other ID */
vxlan_group_used(struct vxlan_net * vn,struct vxlan_dev * dev,__be32 vni,union vxlan_addr * rip,int rifindex)125a498c595SRoopa Prabhu bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
126*f9c4bb0bSRoopa Prabhu 		      __be32 vni, union vxlan_addr *rip, int rifindex)
127a498c595SRoopa Prabhu {
128a498c595SRoopa Prabhu 	union vxlan_addr *ip = (rip ? : &dev->default_dst.remote_ip);
129a498c595SRoopa Prabhu 	int ifindex = (rifindex ? : dev->default_dst.remote_ifindex);
130a498c595SRoopa Prabhu 	struct vxlan_dev *vxlan;
131a498c595SRoopa Prabhu 	struct vxlan_sock *sock4;
132a498c595SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
133a498c595SRoopa Prabhu 	struct vxlan_sock *sock6;
134a498c595SRoopa Prabhu #endif
135a498c595SRoopa Prabhu 	unsigned short family = dev->default_dst.remote_ip.sa.sa_family;
136a498c595SRoopa Prabhu 
137a498c595SRoopa Prabhu 	sock4 = rtnl_dereference(dev->vn4_sock);
138a498c595SRoopa Prabhu 
139a498c595SRoopa Prabhu 	/* The vxlan_sock is only used by dev, leaving group has
140a498c595SRoopa Prabhu 	 * no effect on other vxlan devices.
141a498c595SRoopa Prabhu 	 */
142a498c595SRoopa Prabhu 	if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1)
143a498c595SRoopa Prabhu 		return false;
144a498c595SRoopa Prabhu 
145a498c595SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
146a498c595SRoopa Prabhu 	sock6 = rtnl_dereference(dev->vn6_sock);
147a498c595SRoopa Prabhu 	if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1)
148a498c595SRoopa Prabhu 		return false;
149a498c595SRoopa Prabhu #endif
150a498c595SRoopa Prabhu 
151a498c595SRoopa Prabhu 	list_for_each_entry(vxlan, &vn->vxlan_list, next) {
152a498c595SRoopa Prabhu 		if (!netif_running(vxlan->dev) || vxlan == dev)
153a498c595SRoopa Prabhu 			continue;
154a498c595SRoopa Prabhu 
155a498c595SRoopa Prabhu 		if (family == AF_INET &&
156a498c595SRoopa Prabhu 		    rtnl_dereference(vxlan->vn4_sock) != sock4)
157a498c595SRoopa Prabhu 			continue;
158a498c595SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
159a498c595SRoopa Prabhu 		if (family == AF_INET6 &&
160a498c595SRoopa Prabhu 		    rtnl_dereference(vxlan->vn6_sock) != sock6)
161a498c595SRoopa Prabhu 			continue;
162a498c595SRoopa Prabhu #endif
163*f9c4bb0bSRoopa Prabhu 		if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
164*f9c4bb0bSRoopa Prabhu 			if (!vxlan_group_used_by_vnifilter(vxlan, ip, ifindex))
165a498c595SRoopa Prabhu 				continue;
166*f9c4bb0bSRoopa Prabhu 		} else {
167*f9c4bb0bSRoopa Prabhu 			if (!vxlan_group_used_match(ip, ifindex,
168*f9c4bb0bSRoopa Prabhu 						    &vxlan->default_dst.remote_ip,
169*f9c4bb0bSRoopa Prabhu 						    vxlan->default_dst.remote_ifindex))
170a498c595SRoopa Prabhu 				continue;
171*f9c4bb0bSRoopa Prabhu 		}
172a498c595SRoopa Prabhu 
173a498c595SRoopa Prabhu 		return true;
174a498c595SRoopa Prabhu 	}
175a498c595SRoopa Prabhu 
176a498c595SRoopa Prabhu 	return false;
177a498c595SRoopa Prabhu }
178*f9c4bb0bSRoopa Prabhu 
vxlan_multicast_join_vnigrp(struct vxlan_dev * vxlan)179*f9c4bb0bSRoopa Prabhu static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
180*f9c4bb0bSRoopa Prabhu {
181*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
182*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_node *v, *tmp, *vgood = NULL;
183*f9c4bb0bSRoopa Prabhu 	int ret = 0;
184*f9c4bb0bSRoopa Prabhu 
185*f9c4bb0bSRoopa Prabhu 	list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
186*f9c4bb0bSRoopa Prabhu 		if (!vxlan_addr_multicast(&v->remote_ip))
187*f9c4bb0bSRoopa Prabhu 			continue;
188*f9c4bb0bSRoopa Prabhu 		/* skip if address is same as default address */
189*f9c4bb0bSRoopa Prabhu 		if (vxlan_addr_equal(&v->remote_ip,
190*f9c4bb0bSRoopa Prabhu 				     &vxlan->default_dst.remote_ip))
191*f9c4bb0bSRoopa Prabhu 			continue;
192*f9c4bb0bSRoopa Prabhu 		ret = vxlan_igmp_join(vxlan, &v->remote_ip, 0);
193*f9c4bb0bSRoopa Prabhu 		if (ret == -EADDRINUSE)
194*f9c4bb0bSRoopa Prabhu 			ret = 0;
195*f9c4bb0bSRoopa Prabhu 		if (ret)
196*f9c4bb0bSRoopa Prabhu 			goto out;
197*f9c4bb0bSRoopa Prabhu 		vgood = v;
198*f9c4bb0bSRoopa Prabhu 	}
199*f9c4bb0bSRoopa Prabhu out:
200*f9c4bb0bSRoopa Prabhu 	if (ret) {
201*f9c4bb0bSRoopa Prabhu 		list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
202*f9c4bb0bSRoopa Prabhu 			if (!vxlan_addr_multicast(&v->remote_ip))
203*f9c4bb0bSRoopa Prabhu 				continue;
204*f9c4bb0bSRoopa Prabhu 			if (vxlan_addr_equal(&v->remote_ip,
205*f9c4bb0bSRoopa Prabhu 					     &vxlan->default_dst.remote_ip))
206*f9c4bb0bSRoopa Prabhu 				continue;
207*f9c4bb0bSRoopa Prabhu 			vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
208*f9c4bb0bSRoopa Prabhu 			if (v == vgood)
209*f9c4bb0bSRoopa Prabhu 				break;
210*f9c4bb0bSRoopa Prabhu 		}
211*f9c4bb0bSRoopa Prabhu 	}
212*f9c4bb0bSRoopa Prabhu 
213*f9c4bb0bSRoopa Prabhu 	return ret;
214*f9c4bb0bSRoopa Prabhu }
215*f9c4bb0bSRoopa Prabhu 
vxlan_multicast_leave_vnigrp(struct vxlan_dev * vxlan)216*f9c4bb0bSRoopa Prabhu static int vxlan_multicast_leave_vnigrp(struct vxlan_dev *vxlan)
217*f9c4bb0bSRoopa Prabhu {
218*f9c4bb0bSRoopa Prabhu 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
219*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
220*f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_node *v, *tmp;
221*f9c4bb0bSRoopa Prabhu 	int last_err = 0, ret;
222*f9c4bb0bSRoopa Prabhu 
223*f9c4bb0bSRoopa Prabhu 	list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
224*f9c4bb0bSRoopa Prabhu 		if (vxlan_addr_multicast(&v->remote_ip) &&
225*f9c4bb0bSRoopa Prabhu 		    !vxlan_group_used(vn, vxlan, v->vni, &v->remote_ip,
226*f9c4bb0bSRoopa Prabhu 				      0)) {
227*f9c4bb0bSRoopa Prabhu 			ret = vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
228*f9c4bb0bSRoopa Prabhu 			if (ret)
229*f9c4bb0bSRoopa Prabhu 				last_err = ret;
230*f9c4bb0bSRoopa Prabhu 		}
231*f9c4bb0bSRoopa Prabhu 	}
232*f9c4bb0bSRoopa Prabhu 
233*f9c4bb0bSRoopa Prabhu 	return last_err;
234*f9c4bb0bSRoopa Prabhu }
235*f9c4bb0bSRoopa Prabhu 
vxlan_multicast_join(struct vxlan_dev * vxlan)236*f9c4bb0bSRoopa Prabhu int vxlan_multicast_join(struct vxlan_dev *vxlan)
237*f9c4bb0bSRoopa Prabhu {
238*f9c4bb0bSRoopa Prabhu 	int ret = 0;
239*f9c4bb0bSRoopa Prabhu 
240*f9c4bb0bSRoopa Prabhu 	if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
241*f9c4bb0bSRoopa Prabhu 		ret = vxlan_igmp_join(vxlan, &vxlan->default_dst.remote_ip,
242*f9c4bb0bSRoopa Prabhu 				      vxlan->default_dst.remote_ifindex);
243*f9c4bb0bSRoopa Prabhu 		if (ret == -EADDRINUSE)
244*f9c4bb0bSRoopa Prabhu 			ret = 0;
245*f9c4bb0bSRoopa Prabhu 		if (ret)
246*f9c4bb0bSRoopa Prabhu 			return ret;
247*f9c4bb0bSRoopa Prabhu 	}
248*f9c4bb0bSRoopa Prabhu 
249*f9c4bb0bSRoopa Prabhu 	if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
250*f9c4bb0bSRoopa Prabhu 		return vxlan_multicast_join_vnigrp(vxlan);
251*f9c4bb0bSRoopa Prabhu 
252*f9c4bb0bSRoopa Prabhu 	return 0;
253*f9c4bb0bSRoopa Prabhu }
254*f9c4bb0bSRoopa Prabhu 
vxlan_multicast_leave(struct vxlan_dev * vxlan)255*f9c4bb0bSRoopa Prabhu int vxlan_multicast_leave(struct vxlan_dev *vxlan)
256*f9c4bb0bSRoopa Prabhu {
257*f9c4bb0bSRoopa Prabhu 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
258*f9c4bb0bSRoopa Prabhu 	int ret = 0;
259*f9c4bb0bSRoopa Prabhu 
260*f9c4bb0bSRoopa Prabhu 	if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
261*f9c4bb0bSRoopa Prabhu 	    !vxlan_group_used(vn, vxlan, 0, NULL, 0)) {
262*f9c4bb0bSRoopa Prabhu 		ret = vxlan_igmp_leave(vxlan, &vxlan->default_dst.remote_ip,
263*f9c4bb0bSRoopa Prabhu 				       vxlan->default_dst.remote_ifindex);
264*f9c4bb0bSRoopa Prabhu 		if (ret)
265*f9c4bb0bSRoopa Prabhu 			return ret;
266*f9c4bb0bSRoopa Prabhu 	}
267*f9c4bb0bSRoopa Prabhu 
268*f9c4bb0bSRoopa Prabhu 	if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
269*f9c4bb0bSRoopa Prabhu 		return vxlan_multicast_leave_vnigrp(vxlan);
270*f9c4bb0bSRoopa Prabhu 
271*f9c4bb0bSRoopa Prabhu 	return 0;
272*f9c4bb0bSRoopa Prabhu }
273