blob: af0e2ce8d38ee2e2e4d921bd7db0cebbfb4e3a2d [file] [log] [blame]
Sven Eckelmann7db7d9f2017-11-19 15:05:11 +01001// SPDX-License-Identifier: GPL-2.0
Sven Eckelmann7a79d712018-12-31 23:59:59 +01002/* Copyright (C) 2014-2019 B.A.T.M.A.N. contributors:
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01003 *
4 * Linus Lüssing
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01005 */
6
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01007#include "multicast.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +02008#include "main.h"
9
10#include <linux/atomic.h>
Linus Lüssing9c936e32015-06-16 17:10:25 +020011#include <linux/bitops.h>
Linus Lüssing8a4023c2015-06-16 17:10:26 +020012#include <linux/bug.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020013#include <linux/byteorder/generic.h>
14#include <linux/errno.h>
15#include <linux/etherdevice.h>
Sven Eckelmannb92b94a2017-11-19 17:12:02 +010016#include <linux/gfp.h>
Linus Lüssingbd2a9792016-05-10 18:41:24 +020017#include <linux/icmpv6.h>
Linus Lüssing687937a2016-05-10 18:41:25 +020018#include <linux/if_bridge.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020019#include <linux/if_ether.h>
Linus Lüssingbd2a9792016-05-10 18:41:24 +020020#include <linux/igmp.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020021#include <linux/in.h>
Linus Lüssingbd2a9792016-05-10 18:41:24 +020022#include <linux/in6.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020023#include <linux/ip.h>
24#include <linux/ipv6.h>
Linus Lüssingcbebd362016-08-06 22:23:16 +020025#include <linux/jiffies.h>
Linus Lüssing72f7b2d2016-05-10 18:41:26 +020026#include <linux/kernel.h>
Sven Eckelmann7c124392016-01-16 10:29:56 +010027#include <linux/kref.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020028#include <linux/list.h>
Sven Eckelmann2c72d652015-06-21 14:45:14 +020029#include <linux/lockdep.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020030#include <linux/netdevice.h>
Linus Lüssing53dd9a62018-03-13 11:41:13 +010031#include <linux/netlink.h>
Linus Lüssing687937a2016-05-10 18:41:25 +020032#include <linux/printk.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020033#include <linux/rculist.h>
34#include <linux/rcupdate.h>
Linus Lüssing4e3e8232016-05-10 18:41:27 +020035#include <linux/seq_file.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020036#include <linux/skbuff.h>
37#include <linux/slab.h>
38#include <linux/spinlock.h>
39#include <linux/stddef.h>
40#include <linux/string.h>
41#include <linux/types.h>
Linus Lüssingcbebd362016-08-06 22:23:16 +020042#include <linux/workqueue.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020043#include <net/addrconf.h>
Linus Lüssing53dd9a62018-03-13 11:41:13 +010044#include <net/genetlink.h>
Linus Lüssing687937a2016-05-10 18:41:25 +020045#include <net/if_inet6.h>
46#include <net/ip.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020047#include <net/ipv6.h>
Linus Lüssing53dd9a62018-03-13 11:41:13 +010048#include <net/netlink.h>
49#include <net/sock.h>
Sven Eckelmannfec149f2017-12-21 10:17:41 +010050#include <uapi/linux/batadv_packet.h>
Linus Lüssing53dd9a62018-03-13 11:41:13 +010051#include <uapi/linux/batman_adv.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020052
Linus Lüssing4e3e8232016-05-10 18:41:27 +020053#include "hard-interface.h"
54#include "hash.h"
Sven Eckelmannba412082016-05-15 23:48:31 +020055#include "log.h"
Linus Lüssing53dd9a62018-03-13 11:41:13 +010056#include "netlink.h"
Linus Lüssing32e72742019-03-23 05:47:41 +010057#include "send.h"
Linus Lüssing53dd9a62018-03-13 11:41:13 +010058#include "soft-interface.h"
Linus Lüssingc5caf4e2014-02-15 17:47:49 +010059#include "translation-table.h"
Markus Pargmann1f8dce42016-05-15 11:07:43 +020060#include "tvlv.h"
Linus Lüssingc5caf4e2014-02-15 17:47:49 +010061
Linus Lüssingcbebd362016-08-06 22:23:16 +020062static void batadv_mcast_mla_update(struct work_struct *work);
63
64/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +010065 * batadv_mcast_start_timer() - schedule the multicast periodic worker
Linus Lüssingcbebd362016-08-06 22:23:16 +020066 * @bat_priv: the bat priv with all the soft interface information
67 */
68static void batadv_mcast_start_timer(struct batadv_priv *bat_priv)
69{
70 queue_delayed_work(batadv_event_workqueue, &bat_priv->mcast.work,
71 msecs_to_jiffies(BATADV_MCAST_WORK_PERIOD));
72}
73
Linus Lüssingc5caf4e2014-02-15 17:47:49 +010074/**
Linus Lüssing6bc45442019-05-07 06:08:26 +020075 * batadv_mcast_has_bridge() - check whether the soft-iface is bridged
76 * @bat_priv: the bat priv with all the soft interface information
77 *
78 * Checks whether there is a bridge on top of our soft interface.
79 *
80 * Return: true if there is a bridge, false otherwise.
81 */
82static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
83{
84 struct net_device *upper = bat_priv->soft_iface;
85
86 rcu_read_lock();
87 do {
88 upper = netdev_master_upper_dev_get_rcu(upper);
89 } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
90 rcu_read_unlock();
91
92 return upper;
93}
94
95/**
96 * batadv_mcast_mla_flags_get() - get the new multicast flags
97 * @bat_priv: the bat priv with all the soft interface information
98 *
99 * Return: A set of flags for the current/next TVLV, querier and
100 * bridge state.
101 */
102static struct batadv_mcast_mla_flags
103batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
104{
105 struct net_device *dev = bat_priv->soft_iface;
106 struct batadv_mcast_querier_state *qr4, *qr6;
107 struct batadv_mcast_mla_flags mla_flags;
108
109 memset(&mla_flags, 0, sizeof(mla_flags));
110 mla_flags.enabled = 1;
111
112 if (!batadv_mcast_has_bridge(bat_priv))
113 return mla_flags;
114
115 mla_flags.bridged = 1;
116 qr4 = &mla_flags.querier_ipv4;
117 qr6 = &mla_flags.querier_ipv6;
118
119 if (!IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING))
120 pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n");
121
122 qr4->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
123 qr4->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
124
125 qr6->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6);
126 qr6->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6);
127
128 mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES;
129
130 /* 1) If no querier exists at all, then multicast listeners on
131 * our local TT clients behind the bridge will keep silent.
132 * 2) If the selected querier is on one of our local TT clients,
133 * behind the bridge, then this querier might shadow multicast
134 * listeners on our local TT clients, behind this bridge.
135 *
136 * In both cases, we will signalize other batman nodes that
137 * we need all multicast traffic of the according protocol.
138 */
139 if (!qr4->exists || qr4->shadowing)
140 mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV4;
141
142 if (!qr6->exists || qr6->shadowing)
143 mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV6;
144
145 return mla_flags;
146}
147
148/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100149 * batadv_mcast_get_bridge() - get the bridge on top of the softif if it exists
Linus Lüssing687937a2016-05-10 18:41:25 +0200150 * @soft_iface: netdev struct of the mesh interface
151 *
152 * If the given soft interface has a bridge on top then the refcount
153 * of the according net device is increased.
154 *
155 * Return: NULL if no such bridge exists. Otherwise the net device of the
156 * bridge.
157 */
158static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface)
159{
160 struct net_device *upper = soft_iface;
161
162 rcu_read_lock();
163 do {
164 upper = netdev_master_upper_dev_get_rcu(upper);
165 } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
166
167 if (upper)
168 dev_hold(upper);
169 rcu_read_unlock();
170
171 return upper;
172}
173
174/**
Linus Lüssing6b253602018-03-04 21:02:18 +0100175 * batadv_mcast_addr_is_ipv4() - check if multicast MAC is IPv4
176 * @addr: the MAC address to check
177 *
178 * Return: True, if MAC address is one reserved for IPv4 multicast, false
179 * otherwise.
180 */
181static bool batadv_mcast_addr_is_ipv4(const u8 *addr)
182{
183 static const u8 prefix[] = {0x01, 0x00, 0x5E};
184
185 return memcmp(prefix, addr, sizeof(prefix)) == 0;
186}
187
188/**
189 * batadv_mcast_addr_is_ipv6() - check if multicast MAC is IPv6
190 * @addr: the MAC address to check
191 *
192 * Return: True, if MAC address is one reserved for IPv6 multicast, false
193 * otherwise.
194 */
195static bool batadv_mcast_addr_is_ipv6(const u8 *addr)
196{
197 static const u8 prefix[] = {0x33, 0x33};
198
199 return memcmp(prefix, addr, sizeof(prefix)) == 0;
200}
201
202/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100203 * batadv_mcast_mla_softif_get() - get softif multicast listeners
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100204 * @dev: the device to collect multicast addresses from
205 * @mcast_list: a list to put found addresses into
Linus Lüssing6bc45442019-05-07 06:08:26 +0200206 * @flags: flags indicating the new multicast state
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100207 *
Linus Lüssing687937a2016-05-10 18:41:25 +0200208 * Collects multicast addresses of multicast listeners residing
209 * on this kernel on the given soft interface, dev, in
210 * the given mcast_list. In general, multicast listeners provided by
211 * your multicast receiving applications run directly on this node.
212 *
213 * If there is a bridge interface on top of dev, collects from that one
214 * instead. Just like with IP addresses and routes, multicast listeners
215 * will(/should) register to the bridge interface instead of an
216 * enslaved bat0.
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100217 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200218 * Return: -ENOMEM on memory allocation error or the number of
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100219 * items added to the mcast_list otherwise.
220 */
Linus Lüssing6bc45442019-05-07 06:08:26 +0200221static int
222batadv_mcast_mla_softif_get(struct net_device *dev,
223 struct hlist_head *mcast_list,
224 struct batadv_mcast_mla_flags *flags)
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100225{
Linus Lüssing6bc45442019-05-07 06:08:26 +0200226 bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
227 bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
Linus Lüssing687937a2016-05-10 18:41:25 +0200228 struct net_device *bridge = batadv_mcast_get_bridge(dev);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100229 struct netdev_hw_addr *mc_list_entry;
230 struct batadv_hw_addr *new;
231 int ret = 0;
232
Linus Lüssing687937a2016-05-10 18:41:25 +0200233 netif_addr_lock_bh(bridge ? bridge : dev);
234 netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) {
Linus Lüssing6b253602018-03-04 21:02:18 +0100235 if (all_ipv4 && batadv_mcast_addr_is_ipv4(mc_list_entry->addr))
236 continue;
237
238 if (all_ipv6 && batadv_mcast_addr_is_ipv6(mc_list_entry->addr))
239 continue;
240
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100241 new = kmalloc(sizeof(*new), GFP_ATOMIC);
242 if (!new) {
243 ret = -ENOMEM;
244 break;
245 }
246
247 ether_addr_copy(new->addr, mc_list_entry->addr);
248 hlist_add_head(&new->list, mcast_list);
249 ret++;
250 }
Linus Lüssing687937a2016-05-10 18:41:25 +0200251 netif_addr_unlock_bh(bridge ? bridge : dev);
252
253 if (bridge)
254 dev_put(bridge);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100255
256 return ret;
257}
258
259/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100260 * batadv_mcast_mla_is_duplicate() - check whether an address is in a list
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100261 * @mcast_addr: the multicast address to check
262 * @mcast_list: the list with multicast addresses to search in
263 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200264 * Return: true if the given address is already in the given list.
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100265 * Otherwise returns false.
266 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200267static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr,
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100268 struct hlist_head *mcast_list)
269{
270 struct batadv_hw_addr *mcast_entry;
271
272 hlist_for_each_entry(mcast_entry, mcast_list, list)
273 if (batadv_compare_eth(mcast_entry->addr, mcast_addr))
274 return true;
275
276 return false;
277}
278
279/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100280 * batadv_mcast_mla_br_addr_cpy() - copy a bridge multicast address
Linus Lüssing687937a2016-05-10 18:41:25 +0200281 * @dst: destination to write to - a multicast MAC address
282 * @src: source to read from - a multicast IP address
283 *
284 * Converts a given multicast IPv4/IPv6 address from a bridge
285 * to its matching multicast MAC address and copies it into the given
286 * destination buffer.
287 *
288 * Caller needs to make sure the destination buffer can hold
289 * at least ETH_ALEN bytes.
290 */
291static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src)
292{
293 if (src->proto == htons(ETH_P_IP))
294 ip_eth_mc_map(src->u.ip4, dst);
295#if IS_ENABLED(CONFIG_IPV6)
296 else if (src->proto == htons(ETH_P_IPV6))
297 ipv6_eth_mc_map(&src->u.ip6, dst);
298#endif
299 else
300 eth_zero_addr(dst);
301}
302
303/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100304 * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners
Linus Lüssing687937a2016-05-10 18:41:25 +0200305 * @dev: a bridge slave whose bridge to collect multicast addresses from
306 * @mcast_list: a list to put found addresses into
Linus Lüssing6bc45442019-05-07 06:08:26 +0200307 * @flags: flags indicating the new multicast state
Linus Lüssing687937a2016-05-10 18:41:25 +0200308 *
309 * Collects multicast addresses of multicast listeners residing
310 * on foreign, non-mesh devices which we gave access to our mesh via
311 * a bridge on top of the given soft interface, dev, in the given
312 * mcast_list.
313 *
314 * Return: -ENOMEM on memory allocation error or the number of
315 * items added to the mcast_list otherwise.
316 */
Linus Lüssing6bc45442019-05-07 06:08:26 +0200317static int batadv_mcast_mla_bridge_get(struct net_device *dev,
318 struct hlist_head *mcast_list,
319 struct batadv_mcast_mla_flags *flags)
Linus Lüssing687937a2016-05-10 18:41:25 +0200320{
321 struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
Linus Lüssing6bc45442019-05-07 06:08:26 +0200322 bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
323 bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
Linus Lüssing687937a2016-05-10 18:41:25 +0200324 struct br_ip_list *br_ip_entry, *tmp;
325 struct batadv_hw_addr *new;
326 u8 mcast_addr[ETH_ALEN];
327 int ret;
328
329 /* we don't need to detect these devices/listeners, the IGMP/MLD
330 * snooping code of the Linux bridge already does that for us
331 */
332 ret = br_multicast_list_adjacent(dev, &bridge_mcast_list);
333 if (ret < 0)
334 goto out;
335
336 list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) {
Linus Lüssing6b253602018-03-04 21:02:18 +0100337 if (all_ipv4 && br_ip_entry->addr.proto == htons(ETH_P_IP))
338 continue;
339
340 if (all_ipv6 && br_ip_entry->addr.proto == htons(ETH_P_IPV6))
341 continue;
342
Linus Lüssing687937a2016-05-10 18:41:25 +0200343 batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr);
344 if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
345 continue;
346
347 new = kmalloc(sizeof(*new), GFP_ATOMIC);
348 if (!new) {
349 ret = -ENOMEM;
350 break;
351 }
352
353 ether_addr_copy(new->addr, mcast_addr);
354 hlist_add_head(&new->list, mcast_list);
355 }
356
357out:
358 list_for_each_entry_safe(br_ip_entry, tmp, &bridge_mcast_list, list) {
359 list_del(&br_ip_entry->list);
360 kfree(br_ip_entry);
361 }
362
363 return ret;
364}
365
366/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100367 * batadv_mcast_mla_list_free() - free a list of multicast addresses
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100368 * @mcast_list: the list to free
369 *
370 * Removes and frees all items in the given mcast_list.
371 */
Linus Lüssingb7769762016-08-06 22:23:15 +0200372static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100373{
374 struct batadv_hw_addr *mcast_entry;
375 struct hlist_node *tmp;
376
377 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
378 hlist_del(&mcast_entry->list);
379 kfree(mcast_entry);
380 }
381}
382
383/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100384 * batadv_mcast_mla_tt_retract() - clean up multicast listener announcements
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100385 * @bat_priv: the bat priv with all the soft interface information
386 * @mcast_list: a list of addresses which should _not_ be removed
387 *
388 * Retracts the announcement of any multicast listener from the
389 * translation table except the ones listed in the given mcast_list.
390 *
391 * If mcast_list is NULL then all are retracted.
392 */
393static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
394 struct hlist_head *mcast_list)
395{
396 struct batadv_hw_addr *mcast_entry;
397 struct hlist_node *tmp;
398
399 hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
400 list) {
401 if (mcast_list &&
402 batadv_mcast_mla_is_duplicate(mcast_entry->addr,
403 mcast_list))
404 continue;
405
406 batadv_tt_local_remove(bat_priv, mcast_entry->addr,
407 BATADV_NO_FLAGS,
408 "mcast TT outdated", false);
409
410 hlist_del(&mcast_entry->list);
411 kfree(mcast_entry);
412 }
413}
414
415/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100416 * batadv_mcast_mla_tt_add() - add multicast listener announcements
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100417 * @bat_priv: the bat priv with all the soft interface information
418 * @mcast_list: a list of addresses which are going to get added
419 *
420 * Adds multicast listener announcements from the given mcast_list to the
421 * translation table if they have not been added yet.
422 */
423static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
424 struct hlist_head *mcast_list)
425{
426 struct batadv_hw_addr *mcast_entry;
427 struct hlist_node *tmp;
428
429 if (!mcast_list)
430 return;
431
432 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
433 if (batadv_mcast_mla_is_duplicate(mcast_entry->addr,
434 &bat_priv->mcast.mla_list))
435 continue;
436
437 if (!batadv_tt_local_add(bat_priv->soft_iface,
438 mcast_entry->addr, BATADV_NO_FLAGS,
439 BATADV_NULL_IFINDEX, BATADV_NO_MARK))
440 continue;
441
442 hlist_del(&mcast_entry->list);
443 hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list);
444 }
445}
446
447/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100448 * batadv_mcast_querier_log() - debug output regarding the querier status on
449 * link
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200450 * @bat_priv: the bat priv with all the soft interface information
451 * @str_proto: a string for the querier protocol (e.g. "IGMP" or "MLD")
452 * @old_state: the previous querier state on our link
453 * @new_state: the new querier state on our link
454 *
455 * Outputs debug messages to the logging facility with log level 'mcast'
456 * regarding changes to the querier status on the link which are relevant
457 * to our multicast optimizations.
458 *
459 * Usually this is about whether a querier appeared or vanished in
460 * our mesh or whether the querier is in the suboptimal position of being
461 * behind our local bridge segment: Snooping switches will directly
462 * forward listener reports to the querier, therefore batman-adv and
463 * the bridge will potentially not see these listeners - the querier is
464 * potentially shadowing listeners from us then.
465 *
466 * This is only interesting for nodes with a bridge on top of their
467 * soft interface.
468 */
469static void
470batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
471 struct batadv_mcast_querier_state *old_state,
472 struct batadv_mcast_querier_state *new_state)
473{
474 if (!old_state->exists && new_state->exists)
475 batadv_info(bat_priv->soft_iface, "%s Querier appeared\n",
476 str_proto);
477 else if (old_state->exists && !new_state->exists)
478 batadv_info(bat_priv->soft_iface,
479 "%s Querier disappeared - multicast optimizations disabled\n",
480 str_proto);
Linus Lüssing6bc45442019-05-07 06:08:26 +0200481 else if (!bat_priv->mcast.mla_flags.bridged && !new_state->exists)
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200482 batadv_info(bat_priv->soft_iface,
483 "No %s Querier present - multicast optimizations disabled\n",
484 str_proto);
485
486 if (new_state->exists) {
487 if ((!old_state->shadowing && new_state->shadowing) ||
488 (!old_state->exists && new_state->shadowing))
489 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
490 "%s Querier is behind our bridged segment: Might shadow listeners\n",
491 str_proto);
492 else if (old_state->shadowing && !new_state->shadowing)
493 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
494 "%s Querier is not behind our bridged segment\n",
495 str_proto);
496 }
497}
498
499/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100500 * batadv_mcast_bridge_log() - debug output for topology changes in bridged
501 * setups
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200502 * @bat_priv: the bat priv with all the soft interface information
Linus Lüssing6bc45442019-05-07 06:08:26 +0200503 * @new_flags: flags indicating the new multicast state
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200504 *
505 * If no bridges are ever used on this node, then this function does nothing.
506 *
507 * Otherwise this function outputs debug information to the 'mcast' log level
508 * which might be relevant to our multicast optimizations.
509 *
510 * More precisely, it outputs information when a bridge interface is added or
511 * removed from a soft interface. And when a bridge is present, it further
512 * outputs information about the querier state which is relevant for the
513 * multicast flags this node is going to set.
514 */
515static void
Linus Lüssing6bc45442019-05-07 06:08:26 +0200516batadv_mcast_bridge_log(struct batadv_priv *bat_priv,
517 struct batadv_mcast_mla_flags *new_flags)
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200518{
Linus Lüssing6bc45442019-05-07 06:08:26 +0200519 struct batadv_mcast_mla_flags *old_flags = &bat_priv->mcast.mla_flags;
520
521 if (!old_flags->bridged && new_flags->bridged)
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200522 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
523 "Bridge added: Setting Unsnoopables(U)-flag\n");
Linus Lüssing6bc45442019-05-07 06:08:26 +0200524 else if (old_flags->bridged && !new_flags->bridged)
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200525 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
526 "Bridge removed: Unsetting Unsnoopables(U)-flag\n");
527
Linus Lüssing6bc45442019-05-07 06:08:26 +0200528 if (new_flags->bridged) {
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200529 batadv_mcast_querier_log(bat_priv, "IGMP",
Linus Lüssing6bc45442019-05-07 06:08:26 +0200530 &old_flags->querier_ipv4,
531 &new_flags->querier_ipv4);
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200532 batadv_mcast_querier_log(bat_priv, "MLD",
Linus Lüssing6bc45442019-05-07 06:08:26 +0200533 &old_flags->querier_ipv6,
534 &new_flags->querier_ipv6);
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200535 }
536}
537
538/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100539 * batadv_mcast_flags_logs() - output debug information about mcast flag changes
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200540 * @bat_priv: the bat priv with all the soft interface information
Linus Lüssing6bc45442019-05-07 06:08:26 +0200541 * @flags: TVLV flags indicating the new multicast state
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200542 *
Linus Lüssing6bc45442019-05-07 06:08:26 +0200543 * Whenever the multicast TVLV flags this nodes announces change this notifies
544 * userspace via the 'mcast' log level.
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200545 */
546static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
547{
Linus Lüssing6bc45442019-05-07 06:08:26 +0200548 bool old_enabled = bat_priv->mcast.mla_flags.enabled;
549 u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags;
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200550 char str_old_flags[] = "[...]";
551
552 sprintf(str_old_flags, "[%c%c%c]",
553 (old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
554 (old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
555 (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
556
557 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
558 "Changing multicast flags from '%s' to '[%c%c%c]'\n",
Linus Lüssing6bc45442019-05-07 06:08:26 +0200559 old_enabled ? str_old_flags : "<undefined>",
Linus Lüssing72f7b2d2016-05-10 18:41:26 +0200560 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
561 (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
562 (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
563}
564
565/**
Linus Lüssing6bc45442019-05-07 06:08:26 +0200566 * batadv_mcast_mla_flags_update() - update multicast flags
Linus Lüssing60432d72014-02-15 17:47:51 +0100567 * @bat_priv: the bat priv with all the soft interface information
Linus Lüssing6bc45442019-05-07 06:08:26 +0200568 * @flags: flags indicating the new multicast state
Linus Lüssing60432d72014-02-15 17:47:51 +0100569 *
570 * Updates the own multicast tvlv with our current multicast related settings,
571 * capabilities and inabilities.
Linus Lüssing60432d72014-02-15 17:47:51 +0100572 */
Linus Lüssing6bc45442019-05-07 06:08:26 +0200573static void
574batadv_mcast_mla_flags_update(struct batadv_priv *bat_priv,
575 struct batadv_mcast_mla_flags *flags)
Linus Lüssing60432d72014-02-15 17:47:51 +0100576{
577 struct batadv_tvlv_mcast_data mcast_data;
578
Linus Lüssing6bc45442019-05-07 06:08:26 +0200579 if (!memcmp(flags, &bat_priv->mcast.mla_flags, sizeof(*flags)))
580 return;
581
582 batadv_mcast_bridge_log(bat_priv, flags);
583 batadv_mcast_flags_log(bat_priv, flags->tvlv_flags);
584
585 mcast_data.flags = flags->tvlv_flags;
Linus Lüssing60432d72014-02-15 17:47:51 +0100586 memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
587
Linus Lüssing6bc45442019-05-07 06:08:26 +0200588 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2,
589 &mcast_data, sizeof(mcast_data));
Linus Lüssing687937a2016-05-10 18:41:25 +0200590
Linus Lüssing6bc45442019-05-07 06:08:26 +0200591 bat_priv->mcast.mla_flags = *flags;
Linus Lüssing60432d72014-02-15 17:47:51 +0100592}
593
594/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100595 * __batadv_mcast_mla_update() - update the own MLAs
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100596 * @bat_priv: the bat priv with all the soft interface information
597 *
Linus Lüssing60432d72014-02-15 17:47:51 +0100598 * Updates the own multicast listener announcements in the translation
599 * table as well as the own, announced multicast tvlv container.
Linus Lüssingcbebd362016-08-06 22:23:16 +0200600 *
601 * Note that non-conflicting reads and writes to bat_priv->mcast.mla_list
602 * in batadv_mcast_mla_tt_retract() and batadv_mcast_mla_tt_add() are
603 * ensured by the non-parallel execution of the worker this function
604 * belongs to.
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100605 */
Linus Lüssingcbebd362016-08-06 22:23:16 +0200606static void __batadv_mcast_mla_update(struct batadv_priv *bat_priv)
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100607{
608 struct net_device *soft_iface = bat_priv->soft_iface;
609 struct hlist_head mcast_list = HLIST_HEAD_INIT;
Linus Lüssing6bc45442019-05-07 06:08:26 +0200610 struct batadv_mcast_mla_flags flags;
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100611 int ret;
612
Linus Lüssing6bc45442019-05-07 06:08:26 +0200613 flags = batadv_mcast_mla_flags_get(bat_priv);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100614
Linus Lüssing6bc45442019-05-07 06:08:26 +0200615 ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list, &flags);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100616 if (ret < 0)
617 goto out;
618
Linus Lüssing6bc45442019-05-07 06:08:26 +0200619 ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list, &flags);
Linus Lüssing687937a2016-05-10 18:41:25 +0200620 if (ret < 0)
621 goto out;
622
Linus Lüssing6bc45442019-05-07 06:08:26 +0200623 spin_lock(&bat_priv->mcast.mla_lock);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100624 batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
625 batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
Linus Lüssing6bc45442019-05-07 06:08:26 +0200626 batadv_mcast_mla_flags_update(bat_priv, &flags);
627 spin_unlock(&bat_priv->mcast.mla_lock);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100628
629out:
Linus Lüssingb7769762016-08-06 22:23:15 +0200630 batadv_mcast_mla_list_free(&mcast_list);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100631}
632
633/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100634 * batadv_mcast_mla_update() - update the own MLAs
Linus Lüssingcbebd362016-08-06 22:23:16 +0200635 * @work: kernel work struct
636 *
637 * Updates the own multicast listener announcements in the translation
638 * table as well as the own, announced multicast tvlv container.
639 *
640 * In the end, reschedules the work timer.
641 */
642static void batadv_mcast_mla_update(struct work_struct *work)
643{
644 struct delayed_work *delayed_work;
645 struct batadv_priv_mcast *priv_mcast;
646 struct batadv_priv *bat_priv;
647
648 delayed_work = to_delayed_work(work);
649 priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
650 bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);
651
652 __batadv_mcast_mla_update(bat_priv);
653 batadv_mcast_start_timer(bat_priv);
654}
655
656/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100657 * batadv_mcast_is_report_ipv4() - check for IGMP reports
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200658 * @skb: the ethernet frame destined for the mesh
659 *
660 * This call might reallocate skb data.
661 *
662 * Checks whether the given frame is a valid IGMP report.
663 *
664 * Return: If so then true, otherwise false.
665 */
666static bool batadv_mcast_is_report_ipv4(struct sk_buff *skb)
667{
Linus Lüssingba5ea6142019-01-21 07:26:25 +0100668 if (ip_mc_check_igmp(skb) < 0)
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200669 return false;
670
671 switch (igmp_hdr(skb)->type) {
672 case IGMP_HOST_MEMBERSHIP_REPORT:
673 case IGMPV2_HOST_MEMBERSHIP_REPORT:
674 case IGMPV3_HOST_MEMBERSHIP_REPORT:
675 return true;
676 }
677
678 return false;
679}
680
681/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100682 * batadv_mcast_forw_mode_check_ipv4() - check for optimized forwarding
683 * potential
Linus Lüssingab498862014-02-15 17:47:53 +0100684 * @bat_priv: the bat priv with all the soft interface information
685 * @skb: the IPv4 packet to check
686 * @is_unsnoopable: stores whether the destination is snoopable
687 *
688 * Checks whether the given IPv4 packet has the potential to be forwarded with a
689 * mode more optimal than classic flooding.
690 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200691 * Return: If so then 0. Otherwise -EINVAL or -ENOMEM in case of memory
692 * allocation failure.
Linus Lüssingab498862014-02-15 17:47:53 +0100693 */
694static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv,
695 struct sk_buff *skb,
696 bool *is_unsnoopable)
697{
698 struct iphdr *iphdr;
699
700 /* We might fail due to out-of-memory -> drop it */
701 if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr)))
702 return -ENOMEM;
703
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200704 if (batadv_mcast_is_report_ipv4(skb))
705 return -EINVAL;
706
Linus Lüssingab498862014-02-15 17:47:53 +0100707 iphdr = ip_hdr(skb);
708
709 /* TODO: Implement Multicast Router Discovery (RFC4286),
710 * then allow scope > link local, too
711 */
712 if (!ipv4_is_local_multicast(iphdr->daddr))
713 return -EINVAL;
714
715 /* link-local multicast listeners behind a bridge are
716 * not snoopable (see RFC4541, section 2.1.2.2)
717 */
718 *is_unsnoopable = true;
719
720 return 0;
721}
722
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200723/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100724 * batadv_mcast_is_report_ipv6() - check for MLD reports
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200725 * @skb: the ethernet frame destined for the mesh
726 *
727 * This call might reallocate skb data.
728 *
729 * Checks whether the given frame is a valid MLD report.
730 *
731 * Return: If so then true, otherwise false.
732 */
733static bool batadv_mcast_is_report_ipv6(struct sk_buff *skb)
734{
Linus Lüssingba5ea6142019-01-21 07:26:25 +0100735 if (ipv6_mc_check_mld(skb) < 0)
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200736 return false;
737
738 switch (icmp6_hdr(skb)->icmp6_type) {
739 case ICMPV6_MGM_REPORT:
740 case ICMPV6_MLD2_REPORT:
741 return true;
742 }
743
744 return false;
745}
746
Linus Lüssingab498862014-02-15 17:47:53 +0100747/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100748 * batadv_mcast_forw_mode_check_ipv6() - check for optimized forwarding
749 * potential
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100750 * @bat_priv: the bat priv with all the soft interface information
751 * @skb: the IPv6 packet to check
Linus Lüssingab498862014-02-15 17:47:53 +0100752 * @is_unsnoopable: stores whether the destination is snoopable
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100753 *
754 * Checks whether the given IPv6 packet has the potential to be forwarded with a
755 * mode more optimal than classic flooding.
756 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200757 * Return: If so then 0. Otherwise -EINVAL is or -ENOMEM if we are out of memory
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100758 */
759static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
Linus Lüssingab498862014-02-15 17:47:53 +0100760 struct sk_buff *skb,
761 bool *is_unsnoopable)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100762{
763 struct ipv6hdr *ip6hdr;
764
765 /* We might fail due to out-of-memory -> drop it */
766 if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr)))
767 return -ENOMEM;
768
Linus Lüssingbd2a9792016-05-10 18:41:24 +0200769 if (batadv_mcast_is_report_ipv6(skb))
770 return -EINVAL;
771
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100772 ip6hdr = ipv6_hdr(skb);
773
774 /* TODO: Implement Multicast Router Discovery (RFC4286),
775 * then allow scope > link local, too
776 */
777 if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
778 return -EINVAL;
779
780 /* link-local-all-nodes multicast listeners behind a bridge are
781 * not snoopable (see RFC4541, section 3, paragraph 3)
782 */
783 if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
Linus Lüssingab498862014-02-15 17:47:53 +0100784 *is_unsnoopable = true;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100785
786 return 0;
787}
788
789/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100790 * batadv_mcast_forw_mode_check() - check for optimized forwarding potential
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100791 * @bat_priv: the bat priv with all the soft interface information
792 * @skb: the multicast frame to check
Linus Lüssingab498862014-02-15 17:47:53 +0100793 * @is_unsnoopable: stores whether the destination is snoopable
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100794 *
795 * Checks whether the given multicast ethernet frame has the potential to be
796 * forwarded with a mode more optimal than classic flooding.
797 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200798 * Return: If so then 0. Otherwise -EINVAL is or -ENOMEM if we are out of memory
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100799 */
800static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
Linus Lüssingab498862014-02-15 17:47:53 +0100801 struct sk_buff *skb,
802 bool *is_unsnoopable)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100803{
804 struct ethhdr *ethhdr = eth_hdr(skb);
805
806 if (!atomic_read(&bat_priv->multicast_mode))
807 return -EINVAL;
808
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100809 switch (ntohs(ethhdr->h_proto)) {
Linus Lüssingab498862014-02-15 17:47:53 +0100810 case ETH_P_IP:
811 return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb,
812 is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100813 case ETH_P_IPV6:
Sven Eckelmannc1bacea2017-02-22 17:16:39 +0100814 if (!IS_ENABLED(CONFIG_IPV6))
815 return -EINVAL;
816
Linus Lüssingab498862014-02-15 17:47:53 +0100817 return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb,
818 is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100819 default:
820 return -EINVAL;
821 }
822}
823
824/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100825 * batadv_mcast_forw_want_all_ip_count() - count nodes with unspecific mcast
Antonio Quartulli6d030de2016-03-11 16:36:19 +0100826 * interest
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100827 * @bat_priv: the bat priv with all the soft interface information
828 * @ethhdr: ethernet header of a packet
829 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200830 * Return: the number of nodes which want all IPv4 multicast traffic if the
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100831 * given ethhdr is from an IPv4 packet or the number of nodes which want all
832 * IPv6 traffic if it matches an IPv6 packet.
833 */
834static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv,
835 struct ethhdr *ethhdr)
836{
837 switch (ntohs(ethhdr->h_proto)) {
838 case ETH_P_IP:
839 return atomic_read(&bat_priv->mcast.num_want_all_ipv4);
840 case ETH_P_IPV6:
841 return atomic_read(&bat_priv->mcast.num_want_all_ipv6);
842 default:
843 /* we shouldn't be here... */
844 return 0;
845 }
846}
847
848/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100849 * batadv_mcast_forw_tt_node_get() - get a multicast tt node
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100850 * @bat_priv: the bat priv with all the soft interface information
851 * @ethhdr: the ether header containing the multicast destination
852 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200853 * Return: an orig_node matching the multicast address provided by ethhdr
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100854 * via a translation table lookup. This increases the returned nodes refcount.
855 */
856static struct batadv_orig_node *
857batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
858 struct ethhdr *ethhdr)
859{
Linus Lüssingf8fb3412018-03-20 03:13:27 +0100860 return batadv_transtable_search(bat_priv, NULL, ethhdr->h_dest,
861 BATADV_NO_FLAGS);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100862}
863
864/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100865 * batadv_mcast_forw_ipv4_node_get() - get a node with an ipv4 flag
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100866 * @bat_priv: the bat priv with all the soft interface information
867 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200868 * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100869 * increases its refcount.
870 */
871static struct batadv_orig_node *
872batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
873{
874 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
875
876 rcu_read_lock();
877 hlist_for_each_entry_rcu(tmp_orig_node,
878 &bat_priv->mcast.want_all_ipv4_list,
879 mcast_want_all_ipv4_node) {
Sven Eckelmann7c124392016-01-16 10:29:56 +0100880 if (!kref_get_unless_zero(&tmp_orig_node->refcount))
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100881 continue;
882
883 orig_node = tmp_orig_node;
884 break;
885 }
886 rcu_read_unlock();
887
888 return orig_node;
889}
890
891/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100892 * batadv_mcast_forw_ipv6_node_get() - get a node with an ipv6 flag
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100893 * @bat_priv: the bat priv with all the soft interface information
894 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200895 * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100896 * and increases its refcount.
897 */
898static struct batadv_orig_node *
899batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
900{
901 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
902
903 rcu_read_lock();
904 hlist_for_each_entry_rcu(tmp_orig_node,
905 &bat_priv->mcast.want_all_ipv6_list,
906 mcast_want_all_ipv6_node) {
Sven Eckelmann7c124392016-01-16 10:29:56 +0100907 if (!kref_get_unless_zero(&tmp_orig_node->refcount))
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100908 continue;
909
910 orig_node = tmp_orig_node;
911 break;
912 }
913 rcu_read_unlock();
914
915 return orig_node;
916}
917
918/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100919 * batadv_mcast_forw_ip_node_get() - get a node with an ipv4/ipv6 flag
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100920 * @bat_priv: the bat priv with all the soft interface information
921 * @ethhdr: an ethernet header to determine the protocol family from
922 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200923 * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100924 * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and
925 * increases its refcount.
926 */
927static struct batadv_orig_node *
928batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv,
929 struct ethhdr *ethhdr)
930{
931 switch (ntohs(ethhdr->h_proto)) {
932 case ETH_P_IP:
933 return batadv_mcast_forw_ipv4_node_get(bat_priv);
934 case ETH_P_IPV6:
935 return batadv_mcast_forw_ipv6_node_get(bat_priv);
936 default:
937 /* we shouldn't be here... */
938 return NULL;
939 }
940}
941
942/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100943 * batadv_mcast_forw_unsnoop_node_get() - get a node with an unsnoopable flag
Linus Lüssingab498862014-02-15 17:47:53 +0100944 * @bat_priv: the bat priv with all the soft interface information
945 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200946 * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag
Linus Lüssingab498862014-02-15 17:47:53 +0100947 * set and increases its refcount.
948 */
949static struct batadv_orig_node *
950batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
951{
952 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
953
954 rcu_read_lock();
955 hlist_for_each_entry_rcu(tmp_orig_node,
956 &bat_priv->mcast.want_all_unsnoopables_list,
957 mcast_want_all_unsnoopables_node) {
Sven Eckelmann7c124392016-01-16 10:29:56 +0100958 if (!kref_get_unless_zero(&tmp_orig_node->refcount))
Linus Lüssingab498862014-02-15 17:47:53 +0100959 continue;
960
961 orig_node = tmp_orig_node;
962 break;
963 }
964 rcu_read_unlock();
965
966 return orig_node;
967}
968
969/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100970 * batadv_mcast_forw_mode() - check on how to forward a multicast packet
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100971 * @bat_priv: the bat priv with all the soft interface information
972 * @skb: The multicast packet to check
973 * @orig: an originator to be set to forward the skb to
974 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200975 * Return: the forwarding mode as enum batadv_forw_mode and in case of
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100976 * BATADV_FORW_SINGLE set the orig to the single originator the skb
977 * should be forwarded to.
978 */
979enum batadv_forw_mode
980batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
981 struct batadv_orig_node **orig)
982{
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100983 int ret, tt_count, ip_count, unsnoop_count, total_count;
Linus Lüssingab498862014-02-15 17:47:53 +0100984 bool is_unsnoopable = false;
Linus Lüssing32e72742019-03-23 05:47:41 +0100985 unsigned int mcast_fanout;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100986 struct ethhdr *ethhdr;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100987
Linus Lüssingab498862014-02-15 17:47:53 +0100988 ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100989 if (ret == -ENOMEM)
990 return BATADV_FORW_NONE;
991 else if (ret < 0)
992 return BATADV_FORW_ALL;
993
994 ethhdr = eth_hdr(skb);
995
996 tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
997 BATADV_NO_FLAGS);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100998 ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
Linus Lüssingab498862014-02-15 17:47:53 +0100999 unsnoop_count = !is_unsnoopable ? 0 :
1000 atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001001
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001002 total_count = tt_count + ip_count + unsnoop_count;
Linus Lüssingab498862014-02-15 17:47:53 +01001003
1004 switch (total_count) {
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001005 case 1:
Linus Lüssingab498862014-02-15 17:47:53 +01001006 if (tt_count)
1007 *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001008 else if (ip_count)
1009 *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr);
Linus Lüssingab498862014-02-15 17:47:53 +01001010 else if (unsnoop_count)
1011 *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv);
1012
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001013 if (*orig)
1014 return BATADV_FORW_SINGLE;
1015
1016 /* fall through */
1017 case 0:
1018 return BATADV_FORW_NONE;
1019 default:
Linus Lüssing32e72742019-03-23 05:47:41 +01001020 mcast_fanout = atomic_read(&bat_priv->multicast_fanout);
1021
1022 if (!unsnoop_count && total_count <= mcast_fanout)
1023 return BATADV_FORW_SOME;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001024 }
Linus Lüssing32e72742019-03-23 05:47:41 +01001025
1026 return BATADV_FORW_ALL;
1027}
1028
1029/**
1030 * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
1031 * @bat_priv: the bat priv with all the soft interface information
1032 * @skb: the multicast packet to transmit
1033 * @vid: the vlan identifier
1034 *
1035 * Sends copies of a frame with multicast destination to any multicast
1036 * listener registered in the translation table. A transmission is performed
1037 * via a batman-adv unicast packet for each such destination node.
1038 *
1039 * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1040 * otherwise.
1041 */
1042static int
1043batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
1044 unsigned short vid)
1045{
1046 int ret = NET_XMIT_SUCCESS;
1047 struct sk_buff *newskb;
1048
1049 struct batadv_tt_orig_list_entry *orig_entry;
1050
1051 struct batadv_tt_global_entry *tt_global;
1052 const u8 *addr = eth_hdr(skb)->h_dest;
1053
1054 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
1055 if (!tt_global)
1056 goto out;
1057
1058 rcu_read_lock();
1059 hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) {
1060 newskb = skb_copy(skb, GFP_ATOMIC);
1061 if (!newskb) {
1062 ret = NET_XMIT_DROP;
1063 break;
1064 }
1065
1066 batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
1067 orig_entry->orig_node, vid);
1068 }
1069 rcu_read_unlock();
1070
1071 batadv_tt_global_entry_put(tt_global);
1072
1073out:
1074 return ret;
1075}
1076
1077/**
1078 * batadv_mcast_forw_want_all_ipv4() - forward to nodes with want-all-ipv4
1079 * @bat_priv: the bat priv with all the soft interface information
1080 * @skb: the multicast packet to transmit
1081 * @vid: the vlan identifier
1082 *
1083 * Sends copies of a frame with multicast destination to any node with a
1084 * BATADV_MCAST_WANT_ALL_IPV4 flag set. A transmission is performed via a
1085 * batman-adv unicast packet for each such destination node.
1086 *
1087 * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1088 * otherwise.
1089 */
1090static int
1091batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
1092 struct sk_buff *skb, unsigned short vid)
1093{
1094 struct batadv_orig_node *orig_node;
1095 int ret = NET_XMIT_SUCCESS;
1096 struct sk_buff *newskb;
1097
1098 rcu_read_lock();
1099 hlist_for_each_entry_rcu(orig_node,
1100 &bat_priv->mcast.want_all_ipv4_list,
1101 mcast_want_all_ipv4_node) {
1102 newskb = skb_copy(skb, GFP_ATOMIC);
1103 if (!newskb) {
1104 ret = NET_XMIT_DROP;
1105 break;
1106 }
1107
1108 batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
1109 orig_node, vid);
1110 }
1111 rcu_read_unlock();
1112 return ret;
1113}
1114
1115/**
1116 * batadv_mcast_forw_want_all_ipv6() - forward to nodes with want-all-ipv6
1117 * @bat_priv: the bat priv with all the soft interface information
1118 * @skb: The multicast packet to transmit
1119 * @vid: the vlan identifier
1120 *
1121 * Sends copies of a frame with multicast destination to any node with a
1122 * BATADV_MCAST_WANT_ALL_IPV6 flag set. A transmission is performed via a
1123 * batman-adv unicast packet for each such destination node.
1124 *
1125 * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1126 * otherwise.
1127 */
1128static int
1129batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
1130 struct sk_buff *skb, unsigned short vid)
1131{
1132 struct batadv_orig_node *orig_node;
1133 int ret = NET_XMIT_SUCCESS;
1134 struct sk_buff *newskb;
1135
1136 rcu_read_lock();
1137 hlist_for_each_entry_rcu(orig_node,
1138 &bat_priv->mcast.want_all_ipv6_list,
1139 mcast_want_all_ipv6_node) {
1140 newskb = skb_copy(skb, GFP_ATOMIC);
1141 if (!newskb) {
1142 ret = NET_XMIT_DROP;
1143 break;
1144 }
1145
1146 batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
1147 orig_node, vid);
1148 }
1149 rcu_read_unlock();
1150 return ret;
1151}
1152
1153/**
1154 * batadv_mcast_forw_want_all() - forward packet to nodes in a want-all list
1155 * @bat_priv: the bat priv with all the soft interface information
1156 * @skb: the multicast packet to transmit
1157 * @vid: the vlan identifier
1158 *
1159 * Sends copies of a frame with multicast destination to any node with a
1160 * BATADV_MCAST_WANT_ALL_IPV4 or BATADV_MCAST_WANT_ALL_IPV6 flag set. A
1161 * transmission is performed via a batman-adv unicast packet for each such
1162 * destination node.
1163 *
1164 * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
1165 * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
1166 */
1167static int
1168batadv_mcast_forw_want_all(struct batadv_priv *bat_priv,
1169 struct sk_buff *skb, unsigned short vid)
1170{
1171 switch (ntohs(eth_hdr(skb)->h_proto)) {
1172 case ETH_P_IP:
1173 return batadv_mcast_forw_want_all_ipv4(bat_priv, skb, vid);
1174 case ETH_P_IPV6:
1175 return batadv_mcast_forw_want_all_ipv6(bat_priv, skb, vid);
1176 default:
1177 /* we shouldn't be here... */
1178 return NET_XMIT_DROP;
1179 }
1180}
1181
1182/**
1183 * batadv_mcast_forw_send() - send packet to any detected multicast recpient
1184 * @bat_priv: the bat priv with all the soft interface information
1185 * @skb: the multicast packet to transmit
1186 * @vid: the vlan identifier
1187 *
1188 * Sends copies of a frame with multicast destination to any node that signaled
1189 * interest in it, that is either via the translation table or the according
1190 * want-all flags. A transmission is performed via a batman-adv unicast packet
1191 * for each such destination node.
1192 *
1193 * The given skb is consumed/freed.
1194 *
1195 * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
1196 * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
1197 */
1198int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
1199 unsigned short vid)
1200{
1201 int ret;
1202
1203 ret = batadv_mcast_forw_tt(bat_priv, skb, vid);
1204 if (ret != NET_XMIT_SUCCESS) {
1205 kfree_skb(skb);
1206 return ret;
1207 }
1208
1209 ret = batadv_mcast_forw_want_all(bat_priv, skb, vid);
1210 if (ret != NET_XMIT_SUCCESS) {
1211 kfree_skb(skb);
1212 return ret;
1213 }
1214
1215 consume_skb(skb);
1216 return ret;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001217}
1218
1219/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001220 * batadv_mcast_want_unsnoop_update() - update unsnoop counter and list
Linus Lüssingab498862014-02-15 17:47:53 +01001221 * @bat_priv: the bat priv with all the soft interface information
1222 * @orig: the orig_node which multicast state might have changed of
1223 * @mcast_flags: flags indicating the new multicast state
1224 *
1225 * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator,
1226 * orig, has toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001227 *
1228 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssingab498862014-02-15 17:47:53 +01001229 */
1230static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
1231 struct batadv_orig_node *orig,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001232 u8 mcast_flags)
Linus Lüssingab498862014-02-15 17:47:53 +01001233{
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001234 struct hlist_node *node = &orig->mcast_want_all_unsnoopables_node;
1235 struct hlist_head *head = &bat_priv->mcast.want_all_unsnoopables_list;
1236
Sven Eckelmann5274cd62015-06-21 14:45:15 +02001237 lockdep_assert_held(&orig->mcast_handler_lock);
1238
Linus Lüssingab498862014-02-15 17:47:53 +01001239 /* switched from flag unset to set */
1240 if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
1241 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) {
1242 atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables);
1243
1244 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001245 /* flag checks above + mcast_handler_lock prevents this */
1246 WARN_ON(!hlist_unhashed(node));
1247
1248 hlist_add_head_rcu(node, head);
Linus Lüssingab498862014-02-15 17:47:53 +01001249 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1250 /* switched from flag set to unset */
1251 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) &&
1252 orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) {
1253 atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables);
1254
1255 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001256 /* flag checks above + mcast_handler_lock prevents this */
1257 WARN_ON(hlist_unhashed(node));
1258
1259 hlist_del_init_rcu(node);
Linus Lüssingab498862014-02-15 17:47:53 +01001260 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1261 }
1262}
1263
1264/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001265 * batadv_mcast_want_ipv4_update() - update want-all-ipv4 counter and list
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001266 * @bat_priv: the bat priv with all the soft interface information
1267 * @orig: the orig_node which multicast state might have changed of
1268 * @mcast_flags: flags indicating the new multicast state
1269 *
1270 * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has
1271 * toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001272 *
1273 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001274 */
1275static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
1276 struct batadv_orig_node *orig,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001277 u8 mcast_flags)
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001278{
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001279 struct hlist_node *node = &orig->mcast_want_all_ipv4_node;
1280 struct hlist_head *head = &bat_priv->mcast.want_all_ipv4_list;
1281
Sven Eckelmann5274cd62015-06-21 14:45:15 +02001282 lockdep_assert_held(&orig->mcast_handler_lock);
1283
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001284 /* switched from flag unset to set */
1285 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 &&
1286 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) {
1287 atomic_inc(&bat_priv->mcast.num_want_all_ipv4);
1288
1289 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001290 /* flag checks above + mcast_handler_lock prevents this */
1291 WARN_ON(!hlist_unhashed(node));
1292
1293 hlist_add_head_rcu(node, head);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001294 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1295 /* switched from flag set to unset */
1296 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) &&
1297 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) {
1298 atomic_dec(&bat_priv->mcast.num_want_all_ipv4);
1299
1300 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001301 /* flag checks above + mcast_handler_lock prevents this */
1302 WARN_ON(hlist_unhashed(node));
1303
1304 hlist_del_init_rcu(node);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001305 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1306 }
1307}
1308
1309/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001310 * batadv_mcast_want_ipv6_update() - update want-all-ipv6 counter and list
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001311 * @bat_priv: the bat priv with all the soft interface information
1312 * @orig: the orig_node which multicast state might have changed of
1313 * @mcast_flags: flags indicating the new multicast state
1314 *
1315 * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has
1316 * toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001317 *
1318 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001319 */
1320static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
1321 struct batadv_orig_node *orig,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001322 u8 mcast_flags)
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001323{
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001324 struct hlist_node *node = &orig->mcast_want_all_ipv6_node;
1325 struct hlist_head *head = &bat_priv->mcast.want_all_ipv6_list;
1326
Sven Eckelmann5274cd62015-06-21 14:45:15 +02001327 lockdep_assert_held(&orig->mcast_handler_lock);
1328
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001329 /* switched from flag unset to set */
1330 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 &&
1331 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) {
1332 atomic_inc(&bat_priv->mcast.num_want_all_ipv6);
1333
1334 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001335 /* flag checks above + mcast_handler_lock prevents this */
1336 WARN_ON(!hlist_unhashed(node));
1337
1338 hlist_add_head_rcu(node, head);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001339 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1340 /* switched from flag set to unset */
1341 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) &&
1342 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) {
1343 atomic_dec(&bat_priv->mcast.num_want_all_ipv6);
1344
1345 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001346 /* flag checks above + mcast_handler_lock prevents this */
1347 WARN_ON(hlist_unhashed(node));
1348
1349 hlist_del_init_rcu(node);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001350 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1351 }
1352}
1353
1354/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001355 * batadv_mcast_tvlv_ogm_handler() - process incoming multicast tvlv container
Linus Lüssing60432d72014-02-15 17:47:51 +01001356 * @bat_priv: the bat priv with all the soft interface information
1357 * @orig: the orig_node of the ogm
1358 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
1359 * @tvlv_value: tvlv buffer containing the multicast data
1360 * @tvlv_value_len: tvlv buffer length
1361 */
Linus Lüssingbd2a9792016-05-10 18:41:24 +02001362static void batadv_mcast_tvlv_ogm_handler(struct batadv_priv *bat_priv,
1363 struct batadv_orig_node *orig,
1364 u8 flags,
1365 void *tvlv_value,
1366 u16 tvlv_value_len)
Linus Lüssing60432d72014-02-15 17:47:51 +01001367{
1368 bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001369 u8 mcast_flags = BATADV_NO_FLAGS;
Linus Lüssing60432d72014-02-15 17:47:51 +01001370
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001371 if (orig_mcast_enabled && tvlv_value &&
Sven Eckelmann825ffe12017-08-23 21:52:13 +02001372 tvlv_value_len >= sizeof(mcast_flags))
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001373 mcast_flags = *(u8 *)tvlv_value;
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001374
Linus Lüssingf26e4e92018-03-25 00:32:04 +01001375 if (!orig_mcast_enabled) {
1376 mcast_flags |= BATADV_MCAST_WANT_ALL_IPV4;
1377 mcast_flags |= BATADV_MCAST_WANT_ALL_IPV6;
1378 }
Linus Lüssing60432d72014-02-15 17:47:51 +01001379
Linus Lüssingf26e4e92018-03-25 00:32:04 +01001380 spin_lock_bh(&orig->mcast_handler_lock);
1381
Linus Lüssing60432d72014-02-15 17:47:51 +01001382 if (orig_mcast_enabled &&
Linus Lüssing9c936e32015-06-16 17:10:25 +02001383 !test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities)) {
Linus Lüssing9c936e32015-06-16 17:10:25 +02001384 set_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities);
Linus Lüssing60432d72014-02-15 17:47:51 +01001385 } else if (!orig_mcast_enabled &&
Linus Lüssingf26e4e92018-03-25 00:32:04 +01001386 test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities)) {
Linus Lüssing9c936e32015-06-16 17:10:25 +02001387 clear_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities);
Linus Lüssing60432d72014-02-15 17:47:51 +01001388 }
1389
Linus Lüssing9c936e32015-06-16 17:10:25 +02001390 set_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capa_initialized);
Linus Lüssing60432d72014-02-15 17:47:51 +01001391
Linus Lüssingab498862014-02-15 17:47:53 +01001392 batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001393 batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags);
1394 batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
Linus Lüssingab498862014-02-15 17:47:53 +01001395
Linus Lüssing60432d72014-02-15 17:47:51 +01001396 orig->mcast_flags = mcast_flags;
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001397 spin_unlock_bh(&orig->mcast_handler_lock);
Linus Lüssing60432d72014-02-15 17:47:51 +01001398}
1399
1400/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001401 * batadv_mcast_init() - initialize the multicast optimizations structures
Linus Lüssing60432d72014-02-15 17:47:51 +01001402 * @bat_priv: the bat priv with all the soft interface information
1403 */
1404void batadv_mcast_init(struct batadv_priv *bat_priv)
1405{
Linus Lüssingbd2a9792016-05-10 18:41:24 +02001406 batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler,
1407 NULL, BATADV_TVLV_MCAST, 2,
Linus Lüssing60432d72014-02-15 17:47:51 +01001408 BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
Linus Lüssingcbebd362016-08-06 22:23:16 +02001409
1410 INIT_DELAYED_WORK(&bat_priv->mcast.work, batadv_mcast_mla_update);
1411 batadv_mcast_start_timer(bat_priv);
Linus Lüssing60432d72014-02-15 17:47:51 +01001412}
1413
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001414#ifdef CONFIG_BATMAN_ADV_DEBUGFS
Linus Lüssing60432d72014-02-15 17:47:51 +01001415/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001416 * batadv_mcast_flags_print_header() - print own mcast flags to debugfs table
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001417 * @bat_priv: the bat priv with all the soft interface information
1418 * @seq: debugfs table seq_file struct
1419 *
1420 * Prints our own multicast flags including a more specific reason why
1421 * they are set, that is prints the bridge and querier state too, to
1422 * the debugfs table specified via @seq.
1423 */
1424static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv,
1425 struct seq_file *seq)
1426{
Linus Lüssing6bc45442019-05-07 06:08:26 +02001427 struct batadv_mcast_mla_flags *mla_flags = &bat_priv->mcast.mla_flags;
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001428 char querier4, querier6, shadowing4, shadowing6;
Linus Lüssing6bc45442019-05-07 06:08:26 +02001429 bool bridged = mla_flags->bridged;
1430 u8 flags = mla_flags->tvlv_flags;
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001431
1432 if (bridged) {
Linus Lüssing6bc45442019-05-07 06:08:26 +02001433 querier4 = mla_flags->querier_ipv4.exists ? '.' : '4';
1434 querier6 = mla_flags->querier_ipv6.exists ? '.' : '6';
1435 shadowing4 = mla_flags->querier_ipv4.shadowing ? '4' : '.';
1436 shadowing6 = mla_flags->querier_ipv6.shadowing ? '6' : '.';
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001437 } else {
1438 querier4 = '?';
1439 querier6 = '?';
1440 shadowing4 = '?';
1441 shadowing6 = '?';
1442 }
1443
1444 seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n",
1445 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
1446 (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
1447 (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
1448 seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? 'U' : '.');
1449 seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n",
1450 querier4, querier6);
1451 seq_printf(seq, "* Shadowing IGMP/MLD Querier [4/6]:\t%c/%c\n",
1452 shadowing4, shadowing6);
1453 seq_puts(seq, "-------------------------------------------\n");
1454 seq_printf(seq, " %-10s %s\n", "Originator", "Flags");
1455}
1456
1457/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001458 * batadv_mcast_flags_seq_print_text() - print the mcast flags of other nodes
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001459 * @seq: seq file to print on
1460 * @offset: not used
1461 *
1462 * This prints a table of (primary) originators and their according
1463 * multicast flags, including (in the header) our own.
1464 *
1465 * Return: always 0
1466 */
1467int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
1468{
1469 struct net_device *net_dev = (struct net_device *)seq->private;
1470 struct batadv_priv *bat_priv = netdev_priv(net_dev);
1471 struct batadv_hard_iface *primary_if;
1472 struct batadv_hashtable *hash = bat_priv->orig_hash;
1473 struct batadv_orig_node *orig_node;
1474 struct hlist_head *head;
1475 u8 flags;
1476 u32 i;
1477
1478 primary_if = batadv_seq_print_text_primary_if_get(seq);
1479 if (!primary_if)
1480 return 0;
1481
1482 batadv_mcast_flags_print_header(bat_priv, seq);
1483
1484 for (i = 0; i < hash->size; i++) {
1485 head = &hash->table[i];
1486
1487 rcu_read_lock();
1488 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1489 if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1490 &orig_node->capa_initialized))
1491 continue;
1492
1493 if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1494 &orig_node->capabilities)) {
1495 seq_printf(seq, "%pM -\n", orig_node->orig);
1496 continue;
1497 }
1498
1499 flags = orig_node->mcast_flags;
1500
1501 seq_printf(seq, "%pM [%c%c%c]\n", orig_node->orig,
1502 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)
1503 ? 'U' : '.',
1504 (flags & BATADV_MCAST_WANT_ALL_IPV4)
1505 ? '4' : '.',
1506 (flags & BATADV_MCAST_WANT_ALL_IPV6)
1507 ? '6' : '.');
1508 }
1509 rcu_read_unlock();
1510 }
1511
1512 batadv_hardif_put(primary_if);
1513
1514 return 0;
1515}
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001516#endif
Linus Lüssing4e3e8232016-05-10 18:41:27 +02001517
1518/**
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001519 * batadv_mcast_mesh_info_put() - put multicast info into a netlink message
1520 * @msg: buffer for the message
1521 * @bat_priv: the bat priv with all the soft interface information
1522 *
1523 * Return: 0 or error code.
1524 */
1525int batadv_mcast_mesh_info_put(struct sk_buff *msg,
1526 struct batadv_priv *bat_priv)
1527{
Linus Lüssing6bc45442019-05-07 06:08:26 +02001528 u32 flags = bat_priv->mcast.mla_flags.tvlv_flags;
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001529 u32 flags_priv = BATADV_NO_FLAGS;
1530
Linus Lüssing6bc45442019-05-07 06:08:26 +02001531 if (bat_priv->mcast.mla_flags.bridged) {
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001532 flags_priv |= BATADV_MCAST_FLAGS_BRIDGED;
1533
Linus Lüssing6bc45442019-05-07 06:08:26 +02001534 if (bat_priv->mcast.mla_flags.querier_ipv4.exists)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001535 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS;
Linus Lüssing6bc45442019-05-07 06:08:26 +02001536 if (bat_priv->mcast.mla_flags.querier_ipv6.exists)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001537 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS;
Linus Lüssing6bc45442019-05-07 06:08:26 +02001538 if (bat_priv->mcast.mla_flags.querier_ipv4.shadowing)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001539 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING;
Linus Lüssing6bc45442019-05-07 06:08:26 +02001540 if (bat_priv->mcast.mla_flags.querier_ipv6.shadowing)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001541 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING;
1542 }
1543
1544 if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS, flags) ||
1545 nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS_PRIV, flags_priv))
1546 return -EMSGSIZE;
1547
1548 return 0;
1549}
1550
1551/**
1552 * batadv_mcast_flags_dump_entry() - dump one entry of the multicast flags table
1553 * to a netlink socket
1554 * @msg: buffer for the message
1555 * @portid: netlink port
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001556 * @cb: Control block containing additional options
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001557 * @orig_node: originator to dump the multicast flags of
1558 *
1559 * Return: 0 or error code.
1560 */
1561static int
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001562batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid,
1563 struct netlink_callback *cb,
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001564 struct batadv_orig_node *orig_node)
1565{
1566 void *hdr;
1567
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001568 hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
1569 &batadv_netlink_family, NLM_F_MULTI,
1570 BATADV_CMD_GET_MCAST_FLAGS);
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001571 if (!hdr)
1572 return -ENOBUFS;
1573
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001574 genl_dump_check_consistent(cb, hdr);
1575
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001576 if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
1577 orig_node->orig)) {
1578 genlmsg_cancel(msg, hdr);
1579 return -EMSGSIZE;
1580 }
1581
1582 if (test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1583 &orig_node->capabilities)) {
1584 if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS,
1585 orig_node->mcast_flags)) {
1586 genlmsg_cancel(msg, hdr);
1587 return -EMSGSIZE;
1588 }
1589 }
1590
1591 genlmsg_end(msg, hdr);
1592 return 0;
1593}
1594
1595/**
1596 * batadv_mcast_flags_dump_bucket() - dump one bucket of the multicast flags
1597 * table to a netlink socket
1598 * @msg: buffer for the message
1599 * @portid: netlink port
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001600 * @cb: Control block containing additional options
1601 * @hash: hash to dump
1602 * @bucket: bucket index to dump
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001603 * @idx_skip: How many entries to skip
1604 *
1605 * Return: 0 or error code.
1606 */
1607static int
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001608batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid,
1609 struct netlink_callback *cb,
1610 struct batadv_hashtable *hash,
1611 unsigned int bucket, long *idx_skip)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001612{
1613 struct batadv_orig_node *orig_node;
1614 long idx = 0;
1615
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001616 spin_lock_bh(&hash->list_locks[bucket]);
1617 cb->seq = atomic_read(&hash->generation) << 1 | 1;
1618
1619 hlist_for_each_entry(orig_node, &hash->table[bucket], hash_entry) {
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001620 if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1621 &orig_node->capa_initialized))
1622 continue;
1623
1624 if (idx < *idx_skip)
1625 goto skip;
1626
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001627 if (batadv_mcast_flags_dump_entry(msg, portid, cb, orig_node)) {
1628 spin_unlock_bh(&hash->list_locks[bucket]);
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001629 *idx_skip = idx;
1630
1631 return -EMSGSIZE;
1632 }
1633
1634skip:
1635 idx++;
1636 }
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001637 spin_unlock_bh(&hash->list_locks[bucket]);
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001638
1639 return 0;
1640}
1641
1642/**
1643 * __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
1644 * @msg: buffer for the message
1645 * @portid: netlink port
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001646 * @cb: Control block containing additional options
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001647 * @bat_priv: the bat priv with all the soft interface information
1648 * @bucket: current bucket to dump
1649 * @idx: index in current bucket to the next entry to dump
1650 *
1651 * Return: 0 or error code.
1652 */
1653static int
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001654__batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
1655 struct netlink_callback *cb,
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001656 struct batadv_priv *bat_priv, long *bucket, long *idx)
1657{
1658 struct batadv_hashtable *hash = bat_priv->orig_hash;
1659 long bucket_tmp = *bucket;
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001660 long idx_tmp = *idx;
1661
1662 while (bucket_tmp < hash->size) {
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001663 if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
1664 *bucket, &idx_tmp))
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001665 break;
1666
1667 bucket_tmp++;
1668 idx_tmp = 0;
1669 }
1670
1671 *bucket = bucket_tmp;
1672 *idx = idx_tmp;
1673
1674 return msg->len;
1675}
1676
1677/**
1678 * batadv_mcast_netlink_get_primary() - get primary interface from netlink
1679 * callback
1680 * @cb: netlink callback structure
1681 * @primary_if: the primary interface pointer to return the result in
1682 *
1683 * Return: 0 or error code.
1684 */
1685static int
1686batadv_mcast_netlink_get_primary(struct netlink_callback *cb,
1687 struct batadv_hard_iface **primary_if)
1688{
1689 struct batadv_hard_iface *hard_iface = NULL;
1690 struct net *net = sock_net(cb->skb->sk);
1691 struct net_device *soft_iface;
1692 struct batadv_priv *bat_priv;
1693 int ifindex;
1694 int ret = 0;
1695
1696 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1697 if (!ifindex)
1698 return -EINVAL;
1699
1700 soft_iface = dev_get_by_index(net, ifindex);
1701 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1702 ret = -ENODEV;
1703 goto out;
1704 }
1705
1706 bat_priv = netdev_priv(soft_iface);
1707
1708 hard_iface = batadv_primary_if_get_selected(bat_priv);
1709 if (!hard_iface || hard_iface->if_status != BATADV_IF_ACTIVE) {
1710 ret = -ENOENT;
1711 goto out;
1712 }
1713
1714out:
1715 if (soft_iface)
1716 dev_put(soft_iface);
1717
1718 if (!ret && primary_if)
1719 *primary_if = hard_iface;
Colin Ian King65cc02a2018-03-23 22:53:50 +00001720 else if (hard_iface)
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001721 batadv_hardif_put(hard_iface);
1722
1723 return ret;
1724}
1725
1726/**
1727 * batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
1728 * @msg: buffer for the message
1729 * @cb: callback structure containing arguments
1730 *
1731 * Return: message length.
1732 */
1733int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb)
1734{
1735 struct batadv_hard_iface *primary_if = NULL;
1736 int portid = NETLINK_CB(cb->skb).portid;
1737 struct batadv_priv *bat_priv;
1738 long *bucket = &cb->args[0];
1739 long *idx = &cb->args[1];
1740 int ret;
1741
1742 ret = batadv_mcast_netlink_get_primary(cb, &primary_if);
1743 if (ret)
1744 return ret;
1745
1746 bat_priv = netdev_priv(primary_if->soft_iface);
Sven Eckelmannd2d489b2018-10-30 22:01:30 +01001747 ret = __batadv_mcast_flags_dump(msg, portid, cb, bat_priv, bucket, idx);
Linus Lüssing53dd9a62018-03-13 11:41:13 +01001748
1749 batadv_hardif_put(primary_if);
1750 return ret;
1751}
1752
1753/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001754 * batadv_mcast_free() - free the multicast optimizations structures
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01001755 * @bat_priv: the bat priv with all the soft interface information
1756 */
1757void batadv_mcast_free(struct batadv_priv *bat_priv)
1758{
Linus Lüssingcbebd362016-08-06 22:23:16 +02001759 cancel_delayed_work_sync(&bat_priv->mcast.work);
1760
Linus Lüssingbd2a9792016-05-10 18:41:24 +02001761 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
1762 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
Linus Lüssing60432d72014-02-15 17:47:51 +01001763
Linus Lüssingcbebd362016-08-06 22:23:16 +02001764 /* safely calling outside of worker, as worker was canceled above */
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01001765 batadv_mcast_mla_tt_retract(bat_priv, NULL);
1766}
Linus Lüssing60432d72014-02-15 17:47:51 +01001767
1768/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001769 * batadv_mcast_purge_orig() - reset originator global mcast state modifications
Linus Lüssing60432d72014-02-15 17:47:51 +01001770 * @orig: the originator which is going to get purged
1771 */
1772void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
1773{
1774 struct batadv_priv *bat_priv = orig->bat_priv;
1775
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001776 spin_lock_bh(&orig->mcast_handler_lock);
1777
Linus Lüssingab498862014-02-15 17:47:53 +01001778 batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
Linus Lüssing4c8755d2014-02-15 17:47:54 +01001779 batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
1780 batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
Linus Lüssing8a4023c2015-06-16 17:10:26 +02001781
1782 spin_unlock_bh(&orig->mcast_handler_lock);
Linus Lüssing60432d72014-02-15 17:47:51 +01001783}