1146515Sru// SPDX-License-Identifier: GPL-2.0-only 2146515Sru/* 356160Sru * Vxlan multicast group handling 456160Sru * 556160Sru */ 656160Sru#include <linux/kernel.h> 793139Sru#include <net/net_namespace.h> 856160Sru#include <net/sock.h> 993139Sru#include <linux/igmp.h> 1093139Sru#include <net/vxlan.h> 1193139Sru 1256160Sru#include "vxlan_private.h" 1393139Sru 1493139Sru/* Update multicast group membership when first VNI on 1556160Sru * multicast address is brought up 1693139Sru */ 1793139Sruint vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip, 1856160Sru int rifindex) 1993139Sru{ 2093139Sru union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip); 2193139Sru int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex); 2293139Sru int ret = -EINVAL; 23146515Sru struct sock *sk; 2493139Sru 2593139Sru if (ip->sa.sa_family == AF_INET) { 2693139Sru struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock); 2793139Sru struct ip_mreqn mreq = { 2893139Sru .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, 2993139Sru .imr_ifindex = ifindex, 3093139Sru }; 3193139Sru 3293139Sru sk = sock4->sock->sk; 3393139Sru lock_sock(sk); 3493139Sru ret = ip_mc_join_group(sk, &mreq); 3593139Sru release_sock(sk); 3693139Sru#if IS_ENABLED(CONFIG_IPV6) 3793139Sru } else { 3893139Sru struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock); 39146515Sru 4093139Sru sk = sock6->sock->sk; 4193139Sru lock_sock(sk); 4293139Sru ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex, 4393139Sru &ip->sin6.sin6_addr); 4493139Sru release_sock(sk); 45114472Sru#endif 46146515Sru } 47146515Sru 48146515Sru return ret; 4993139Sru} 5093139Sru 5156160Sruint vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip, 52146515Sru int rifindex) 5393139Sru{ 5456160Sru union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip); 55100513Sru int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex); 56100513Sru int ret = -EINVAL; 57100513Sru struct sock *sk; 58100513Sru 59100513Sru if (ip->sa.sa_family == AF_INET) { 60100513Sru struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock); 6193139Sru struct ip_mreqn mreq = { 6293139Sru .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, 6393139Sru .imr_ifindex = ifindex, 6456160Sru }; 6593139Sru 6693139Sru sk = sock4->sock->sk; 6793139Sru lock_sock(sk); 6893139Sru ret = ip_mc_leave_group(sk, &mreq); 6993139Sru release_sock(sk); 7093139Sru#if IS_ENABLED(CONFIG_IPV6) 7193139Sru } else { 7293139Sru struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock); 7393139Sru 7493139Sru sk = sock6->sock->sk; 7593139Sru lock_sock(sk); 7656160Sru ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, 7756160Sru &ip->sin6.sin6_addr); 7856160Sru release_sock(sk); 7956160Sru#endif 8093139Sru } 8193139Sru 8293139Sru return ret; 8356160Sru} 8493139Sru 8556160Srustatic bool vxlan_group_used_match(union vxlan_addr *ip, int ifindex, 8693139Sru union vxlan_addr *rip, int rifindex) 8793139Sru{ 8893139Sru if (!vxlan_addr_multicast(rip)) 8993139Sru return false; 9056160Sru 9193139Sru if (!vxlan_addr_equal(rip, ip)) 92116525Sru return false; 93116525Sru 94116525Sru if (rifindex != ifindex) 95116525Sru return false; 96116525Sru 97146515Sru return true; 98146515Sru} 99146515Sru 100146515Srustatic bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan, 101146515Sru union vxlan_addr *ip, int ifindex) 102146515Sru{ 10393139Sru struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp); 10456160Sru struct vxlan_vni_node *v, *tmp; 10593139Sru 10693139Sru if (vxlan_group_used_match(ip, ifindex, 10756160Sru &vxlan->default_dst.remote_ip, 10893139Sru vxlan->default_dst.remote_ifindex)) 10993139Sru return true; 11093139Sru 11156160Sru list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) { 11256160Sru if (!vxlan_addr_multicast(&v->remote_ip)) 11356160Sru continue; 11493139Sru 11593139Sru if (vxlan_group_used_match(ip, ifindex, 11693139Sru &v->remote_ip, 11793139Sru vxlan->default_dst.remote_ifindex)) 11893139Sru return true; 11993139Sru } 12093139Sru 121146515Sru return false; 122146515Sru} 123146515Sru 124146515Sru/* See if multicast group is already in use by other ID */ 12556160Srubool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev, 12693139Sru __be32 vni, union vxlan_addr *rip, int rifindex) 12756160Sru{ 12856160Sru union vxlan_addr *ip = (rip ? : &dev->default_dst.remote_ip); 129100513Sru int ifindex = (rifindex ? : dev->default_dst.remote_ifindex); 13056160Sru struct vxlan_dev *vxlan; 131100513Sru struct vxlan_sock *sock4; 132100513Sru#if IS_ENABLED(CONFIG_IPV6) 133100513Sru struct vxlan_sock *sock6; 13456160Sru#endif 135100513Sru unsigned short family = dev->default_dst.remote_ip.sa.sa_family; 13656160Sru 137114472Sru sock4 = rtnl_dereference(dev->vn4_sock); 138114472Sru 139114472Sru /* The vxlan_sock is only used by dev, leaving group has 140146515Sru * no effect on other vxlan devices. 141146515Sru */ 142146515Sru if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1) 14356160Sru return false; 14456160Sru 14556160Sru#if IS_ENABLED(CONFIG_IPV6) 14656160Sru sock6 = rtnl_dereference(dev->vn6_sock); 14756160Sru if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1) 14856160Sru return false; 149100513Sru#endif 150100513Sru 151100513Sru list_for_each_entry(vxlan, &vn->vxlan_list, next) { 15256160Sru if (!netif_running(vxlan->dev) || vxlan == dev) 15356160Sru continue; 154114472Sru 155114472Sru if (family == AF_INET && 156114472Sru rtnl_dereference(vxlan->vn4_sock) != sock4) 15756160Sru continue; 158146515Sru#if IS_ENABLED(CONFIG_IPV6) 159146515Sru if (family == AF_INET6 && 16056160Sru rtnl_dereference(vxlan->vn6_sock) != sock6) 16156160Sru continue; 162100513Sru#endif 163100513Sru if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) { 164116525Sru if (!vxlan_group_used_by_vnifilter(vxlan, ip, ifindex)) 16556160Sru continue; 16656160Sru } else { 16756160Sru if (!vxlan_group_used_match(ip, ifindex, 16856160Sru &vxlan->default_dst.remote_ip, 16956160Sru vxlan->default_dst.remote_ifindex)) 17056160Sru continue; 171100513Sru } 17256160Sru 173100513Sru return true; 174114472Sru } 17556160Sru 176100513Sru return false; 177100513Sru} 17856160Sru 179100513Srustatic int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan) 180100513Sru{ 181100513Sru struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp); 182100513Sru struct vxlan_vni_node *v, *tmp, *vgood = NULL; 183100513Sru int ret = 0; 184100513Sru 18556160Sru list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) { 186146515Sru if (!vxlan_addr_multicast(&v->remote_ip)) 187146515Sru continue; 188100513Sru /* skip if address is same as default address */ 18993139Sru if (vxlan_addr_equal(&v->remote_ip, 190146515Sru &vxlan->default_dst.remote_ip)) 19193139Sru continue; 19293139Sru ret = vxlan_igmp_join(vxlan, &v->remote_ip, 0); 19393139Sru if (ret == -EADDRINUSE) 19456160Sru ret = 0; 19556160Sru if (ret) 19656160Sru goto out; 19756160Sru vgood = v; 19856160Sru } 19956160Sruout: 20056160Sru if (ret) { 20156160Sru list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) { 20256160Sru if (!vxlan_addr_multicast(&v->remote_ip)) 20356160Sru continue; 20456160Sru if (vxlan_addr_equal(&v->remote_ip, 20556160Sru &vxlan->default_dst.remote_ip)) 206 continue; 207 vxlan_igmp_leave(vxlan, &v->remote_ip, 0); 208 if (v == vgood) 209 break; 210 } 211 } 212 213 return ret; 214} 215 216static int vxlan_multicast_leave_vnigrp(struct vxlan_dev *vxlan) 217{ 218 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); 219 struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp); 220 struct vxlan_vni_node *v, *tmp; 221 int last_err = 0, ret; 222 223 list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) { 224 if (vxlan_addr_multicast(&v->remote_ip) && 225 !vxlan_group_used(vn, vxlan, v->vni, &v->remote_ip, 226 0)) { 227 ret = vxlan_igmp_leave(vxlan, &v->remote_ip, 0); 228 if (ret) 229 last_err = ret; 230 } 231 } 232 233 return last_err; 234} 235 236int vxlan_multicast_join(struct vxlan_dev *vxlan) 237{ 238 int ret = 0; 239 240 if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { 241 ret = vxlan_igmp_join(vxlan, &vxlan->default_dst.remote_ip, 242 vxlan->default_dst.remote_ifindex); 243 if (ret == -EADDRINUSE) 244 ret = 0; 245 if (ret) 246 return ret; 247 } 248 249 if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) 250 return vxlan_multicast_join_vnigrp(vxlan); 251 252 return 0; 253} 254 255int vxlan_multicast_leave(struct vxlan_dev *vxlan) 256{ 257 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); 258 int ret = 0; 259 260 if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && 261 !vxlan_group_used(vn, vxlan, 0, NULL, 0)) { 262 ret = vxlan_igmp_leave(vxlan, &vxlan->default_dst.remote_ip, 263 vxlan->default_dst.remote_ifindex); 264 if (ret) 265 return ret; 266 } 267 268 if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) 269 return vxlan_multicast_leave_vnigrp(vxlan); 270 271 return 0; 272} 273