~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/batman-adv/multicast_forw.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright (C) B.A.T.M.A.N. contributors:
  3  *
  4  * Linus Lüssing
  5  */
  6 
  7 #include "multicast.h"
  8 #include "main.h"
  9 
 10 #include <linux/bug.h>
 11 #include <linux/build_bug.h>
 12 #include <linux/byteorder/generic.h>
 13 #include <linux/compiler.h>
 14 #include <linux/errno.h>
 15 #include <linux/etherdevice.h>
 16 #include <linux/gfp.h>
 17 #include <linux/if_ether.h>
 18 #include <linux/if_vlan.h>
 19 #include <linux/ipv6.h>
 20 #include <linux/limits.h>
 21 #include <linux/netdevice.h>
 22 #include <linux/rculist.h>
 23 #include <linux/rcupdate.h>
 24 #include <linux/skbuff.h>
 25 #include <linux/stddef.h>
 26 #include <linux/string.h>
 27 #include <linux/types.h>
 28 #include <uapi/linux/batadv_packet.h>
 29 
 30 #include "bridge_loop_avoidance.h"
 31 #include "originator.h"
 32 #include "send.h"
 33 #include "translation-table.h"
 34 
 35 #define batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) \
 36         for (; num_dests; num_dests--, (dest) += ETH_ALEN)
 37 
 38 #define batadv_mcast_forw_tracker_for_each_dest2(dest1, dest2, num_dests) \
 39         for (; num_dests; num_dests--, (dest1) += ETH_ALEN, (dest2) += ETH_ALEN)
 40 
 41 /**
 42  * batadv_mcast_forw_skb_push() - skb_push and memorize amount of pushed bytes
 43  * @skb: the skb to push onto
 44  * @size: the amount of bytes to push
 45  * @len: stores the total amount of bytes pushed
 46  *
 47  * Performs an skb_push() onto the given skb and adds the amount of pushed bytes
 48  * to the given len pointer.
 49  *
 50  * Return: the return value of the skb_push() call.
 51  */
 52 static void *batadv_mcast_forw_skb_push(struct sk_buff *skb, size_t size,
 53                                         unsigned short *len)
 54 {
 55         *len += size;
 56         return skb_push(skb, size);
 57 }
 58 
 59 /**
 60  * batadv_mcast_forw_push_padding() - push 2 padding bytes to skb's front
 61  * @skb: the skb to push onto
 62  * @tvlv_len: stores the amount of currently pushed TVLV bytes
 63  *
 64  * Pushes two padding bytes to the front of the given skb.
 65  *
 66  * Return: On success a pointer to the first byte of the two pushed padding
 67  * bytes within the skb. NULL otherwise.
 68  */
 69 static char *
 70 batadv_mcast_forw_push_padding(struct sk_buff *skb, unsigned short *tvlv_len)
 71 {
 72         const int pad_len = 2;
 73         char *padding;
 74 
 75         if (skb_headroom(skb) < pad_len)
 76                 return NULL;
 77 
 78         padding = batadv_mcast_forw_skb_push(skb, pad_len, tvlv_len);
 79         memset(padding, 0, pad_len);
 80 
 81         return padding;
 82 }
 83 
 84 /**
 85  * batadv_mcast_forw_push_est_padding() - push padding bytes if necessary
 86  * @skb: the skb to potentially push the padding onto
 87  * @count: the (estimated) number of originators the multicast packet needs to
 88  *  be sent to
 89  * @tvlv_len: stores the amount of currently pushed TVLV bytes
 90  *
 91  * If the number of destination entries is even then this adds two
 92  * padding bytes to the end of the tracker TVLV.
 93  *
 94  * Return: true on success or if no padding is needed, false otherwise.
 95  */
 96 static bool
 97 batadv_mcast_forw_push_est_padding(struct sk_buff *skb, int count,
 98                                    unsigned short *tvlv_len)
 99 {
100         if (!(count % 2) && !batadv_mcast_forw_push_padding(skb, tvlv_len))
101                 return false;
102 
103         return true;
104 }
105 
106 /**
107  * batadv_mcast_forw_orig_entry() - get orig_node from an hlist node
108  * @node: the hlist node to get the orig_node from
109  * @entry_offset: the offset of the hlist node within the orig_node struct
110  *
111  * Return: The orig_node containing the hlist node on success, NULL on error.
112  */
113 static struct batadv_orig_node *
114 batadv_mcast_forw_orig_entry(struct hlist_node *node,
115                              size_t entry_offset)
116 {
117         /* sanity check */
118         switch (entry_offset) {
119         case offsetof(struct batadv_orig_node, mcast_want_all_ipv4_node):
120         case offsetof(struct batadv_orig_node, mcast_want_all_ipv6_node):
121         case offsetof(struct batadv_orig_node, mcast_want_all_rtr4_node):
122         case offsetof(struct batadv_orig_node, mcast_want_all_rtr6_node):
123                 break;
124         default:
125                 WARN_ON(1);
126                 return NULL;
127         }
128 
129         return (struct batadv_orig_node *)((void *)node - entry_offset);
130 }
131 
132 /**
133  * batadv_mcast_forw_push_dest() - push an originator MAC address onto an skb
134  * @bat_priv: the bat priv with all the soft interface information
135  * @skb: the skb to push the destination address onto
136  * @vid: the vlan identifier
137  * @orig_node: the originator node to get the MAC address from
138  * @num_dests: a pointer to store the number of pushed addresses in
139  * @tvlv_len: stores the amount of currently pushed TVLV bytes
140  *
141  * If the orig_node is a BLA backbone gateway, if there is not enough skb
142  * headroom available or if num_dests is already at its maximum (65535) then
143  * neither the skb nor num_dests is changed. Otherwise the originator's MAC
144  * address is pushed onto the given skb and num_dests incremented by one.
145  *
146  * Return: true if the orig_node is a backbone gateway or if an orig address
147  *  was pushed successfully, false otherwise.
148  */
149 static bool batadv_mcast_forw_push_dest(struct batadv_priv *bat_priv,
150                                         struct sk_buff *skb, unsigned short vid,
151                                         struct batadv_orig_node *orig_node,
152                                         unsigned short *num_dests,
153                                         unsigned short *tvlv_len)
154 {
155         BUILD_BUG_ON(sizeof_field(struct batadv_tvlv_mcast_tracker, num_dests)
156                      != sizeof(__be16));
157 
158         /* Avoid sending to other BLA gateways - they already got the frame from
159          * the LAN side we share with them.
160          * TODO: Refactor to take BLA into account earlier in mode check.
161          */
162         if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
163                 return true;
164 
165         if (skb_headroom(skb) < ETH_ALEN || *num_dests == U16_MAX)
166                 return false;
167 
168         batadv_mcast_forw_skb_push(skb, ETH_ALEN, tvlv_len);
169         ether_addr_copy(skb->data, orig_node->orig);
170         (*num_dests)++;
171 
172         return true;
173 }
174 
175 /**
176  * batadv_mcast_forw_push_dests_list() - push originators from list onto an skb
177  * @bat_priv: the bat priv with all the soft interface information
178  * @skb: the skb to push the destination addresses onto
179  * @vid: the vlan identifier
180  * @head: the list to gather originators from
181  * @entry_offset: offset of an hlist node in an orig_node structure
182  * @num_dests: a pointer to store the number of pushed addresses in
183  * @tvlv_len: stores the amount of currently pushed TVLV bytes
184  *
185  * Push the MAC addresses of all originators in the given list onto the given
186  * skb.
187  *
188  * Return: true on success, false otherwise.
189  */
190 static int batadv_mcast_forw_push_dests_list(struct batadv_priv *bat_priv,
191                                              struct sk_buff *skb,
192                                              unsigned short vid,
193                                              struct hlist_head *head,
194                                              size_t entry_offset,
195                                              unsigned short *num_dests,
196                                              unsigned short *tvlv_len)
197 {
198         struct hlist_node *node;
199         struct batadv_orig_node *orig_node;
200 
201         rcu_read_lock();
202         __hlist_for_each_rcu(node, head) {
203                 orig_node = batadv_mcast_forw_orig_entry(node, entry_offset);
204                 if (!orig_node ||
205                     !batadv_mcast_forw_push_dest(bat_priv, skb, vid, orig_node,
206                                                  num_dests, tvlv_len)) {
207                         rcu_read_unlock();
208                         return false;
209                 }
210         }
211         rcu_read_unlock();
212 
213         return true;
214 }
215 
216 /**
217  * batadv_mcast_forw_push_tt() - push originators with interest through TT
218  * @bat_priv: the bat priv with all the soft interface information
219  * @skb: the skb to push the destination addresses onto
220  * @vid: the vlan identifier
221  * @num_dests: a pointer to store the number of pushed addresses in
222  * @tvlv_len: stores the amount of currently pushed TVLV bytes
223  *
224  * Push the MAC addresses of all originators which have indicated interest in
225  * this multicast packet through the translation table onto the given skb.
226  *
227  * Return: true on success, false otherwise.
228  */
229 static bool
230 batadv_mcast_forw_push_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
231                           unsigned short vid, unsigned short *num_dests,
232                           unsigned short *tvlv_len)
233 {
234         struct batadv_tt_orig_list_entry *orig_entry;
235 
236         struct batadv_tt_global_entry *tt_global;
237         const u8 *addr = eth_hdr(skb)->h_dest;
238 
239         /* ok */
240         int ret = true;
241 
242         tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
243         if (!tt_global)
244                 goto out;
245 
246         rcu_read_lock();
247         hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) {
248                 if (!batadv_mcast_forw_push_dest(bat_priv, skb, vid,
249                                                  orig_entry->orig_node,
250                                                  num_dests, tvlv_len)) {
251                         ret = false;
252                         break;
253                 }
254         }
255         rcu_read_unlock();
256 
257         batadv_tt_global_entry_put(tt_global);
258 
259 out:
260         return ret;
261 }
262 
263 /**
264  * batadv_mcast_forw_push_want_all() - push originators with want-all flag
265  * @bat_priv: the bat priv with all the soft interface information
266  * @skb: the skb to push the destination addresses onto
267  * @vid: the vlan identifier
268  * @num_dests: a pointer to store the number of pushed addresses in
269  * @tvlv_len: stores the amount of currently pushed TVLV bytes
270  *
271  * Push the MAC addresses of all originators which have indicated interest in
272  * this multicast packet through the want-all flag onto the given skb.
273  *
274  * Return: true on success, false otherwise.
275  */
276 static bool batadv_mcast_forw_push_want_all(struct batadv_priv *bat_priv,
277                                             struct sk_buff *skb,
278                                             unsigned short vid,
279                                             unsigned short *num_dests,
280                                             unsigned short *tvlv_len)
281 {
282         struct hlist_head *head = NULL;
283         size_t offset;
284         int ret;
285 
286         switch (eth_hdr(skb)->h_proto) {
287         case htons(ETH_P_IP):
288                 head = &bat_priv->mcast.want_all_ipv4_list;
289                 offset = offsetof(struct batadv_orig_node,
290                                   mcast_want_all_ipv4_node);
291                 break;
292         case htons(ETH_P_IPV6):
293                 head = &bat_priv->mcast.want_all_ipv6_list;
294                 offset = offsetof(struct batadv_orig_node,
295                                   mcast_want_all_ipv6_node);
296                 break;
297         default:
298                 return false;
299         }
300 
301         ret = batadv_mcast_forw_push_dests_list(bat_priv, skb, vid, head,
302                                                 offset, num_dests, tvlv_len);
303         if (!ret)
304                 return false;
305 
306         return true;
307 }
308 
309 /**
310  * batadv_mcast_forw_push_want_rtr() - push originators with want-router flag
311  * @bat_priv: the bat priv with all the soft interface information
312  * @skb: the skb to push the destination addresses onto
313  * @vid: the vlan identifier
314  * @num_dests: a pointer to store the number of pushed addresses in
315  * @tvlv_len: stores the amount of currently pushed TVLV bytes
316  *
317  * Push the MAC addresses of all originators which have indicated interest in
318  * this multicast packet through the want-all-rtr flag onto the given skb.
319  *
320  * Return: true on success, false otherwise.
321  */
322 static bool batadv_mcast_forw_push_want_rtr(struct batadv_priv *bat_priv,
323                                             struct sk_buff *skb,
324                                             unsigned short vid,
325                                             unsigned short *num_dests,
326                                             unsigned short *tvlv_len)
327 {
328         struct hlist_head *head = NULL;
329         size_t offset;
330         int ret;
331 
332         switch (eth_hdr(skb)->h_proto) {
333         case htons(ETH_P_IP):
334                 head = &bat_priv->mcast.want_all_rtr4_list;
335                 offset = offsetof(struct batadv_orig_node,
336                                   mcast_want_all_rtr4_node);
337                 break;
338         case htons(ETH_P_IPV6):
339                 head = &bat_priv->mcast.want_all_rtr6_list;
340                 offset = offsetof(struct batadv_orig_node,
341                                   mcast_want_all_rtr6_node);
342                 break;
343         default:
344                 return false;
345         }
346 
347         ret = batadv_mcast_forw_push_dests_list(bat_priv, skb, vid, head,
348                                                 offset, num_dests, tvlv_len);
349         if (!ret)
350                 return false;
351 
352         return true;
353 }
354 
355 /**
356  * batadv_mcast_forw_scrape() - remove bytes within skb data
357  * @skb: the skb to remove bytes from
358  * @offset: the offset from the skb data from which to scrape
359  * @len: the amount of bytes to scrape starting from the offset
360  *
361  * Scrapes/removes len bytes from the given skb at the given offset from the
362  * skb data.
363  *
364  * Caller needs to ensure that the region from the skb data's start up
365  * to/including the to be removed bytes are linearized.
366  */
367 static void batadv_mcast_forw_scrape(struct sk_buff *skb,
368                                      unsigned short offset,
369                                      unsigned short len)
370 {
371         char *to, *from;
372 
373         SKB_LINEAR_ASSERT(skb);
374 
375         to = skb_pull(skb, len);
376         from = to - len;
377 
378         memmove(to, from, offset);
379 }
380 
381 /**
382  * batadv_mcast_forw_push_scrape_padding() - remove TVLV padding
383  * @skb: the skb to potentially adjust the TVLV's padding on
384  * @tvlv_len: stores the amount of currently pushed TVLV bytes
385  *
386  * Remove two padding bytes from the end of the multicast tracker TVLV,
387  * from before the payload data.
388  *
389  * Caller needs to ensure that the TVLV bytes are linearized.
390  */
391 static void batadv_mcast_forw_push_scrape_padding(struct sk_buff *skb,
392                                                   unsigned short *tvlv_len)
393 {
394         const int pad_len = 2;
395 
396         batadv_mcast_forw_scrape(skb, *tvlv_len - pad_len, pad_len);
397         *tvlv_len -= pad_len;
398 }
399 
400 /**
401  * batadv_mcast_forw_push_insert_padding() - insert TVLV padding
402  * @skb: the skb to potentially adjust the TVLV's padding on
403  * @tvlv_len: stores the amount of currently pushed TVLV bytes
404  *
405  * Inserts two padding bytes at the end of the multicast tracker TVLV,
406  * before the payload data in the given skb.
407  *
408  * Return: true on success, false otherwise.
409  */
410 static bool batadv_mcast_forw_push_insert_padding(struct sk_buff *skb,
411                                                   unsigned short *tvlv_len)
412 {
413         unsigned short offset = *tvlv_len;
414         char *to, *from = skb->data;
415 
416         to = batadv_mcast_forw_push_padding(skb, tvlv_len);
417         if (!to)
418                 return false;
419 
420         memmove(to, from, offset);
421         memset(to + offset, 0, *tvlv_len - offset);
422         return true;
423 }
424 
425 /**
426  * batadv_mcast_forw_push_adjust_padding() - adjust padding if necessary
427  * @skb: the skb to potentially adjust the TVLV's padding on
428  * @count: the estimated number of originators the multicast packet needs to
429  *  be sent to
430  * @num_dests_pushed: the number of originators that were actually added to the
431  *  multicast packet's tracker TVLV
432  * @tvlv_len: stores the amount of currently pushed TVLV bytes
433  *
434  * Adjusts the padding in the multicast packet's tracker TVLV depending on the
435  * initially estimated amount of destinations versus the amount of destinations
436  * that were actually added to the tracker TVLV.
437  *
438  * If the initial estimate was correct or at least the oddness was the same then
439  * no padding adjustment is performed.
440  * If the initially estimated number was even, so padding was initially added,
441  * but it turned out to be odd then padding is removed.
442  * If the initially estimated number was odd, so no padding was initially added,
443  * but it turned out to be even then padding is added.
444  *
445  * Return: true if no padding adjustment is needed or the adjustment was
446  * successful, false otherwise.
447  */
448 static bool
449 batadv_mcast_forw_push_adjust_padding(struct sk_buff *skb, int *count,
450                                       unsigned short num_dests_pushed,
451                                       unsigned short *tvlv_len)
452 {
453         int ret = true;
454 
455         if (likely((num_dests_pushed % 2) == (*count % 2)))
456                 goto out;
457 
458         /**
459          * estimated even number of destinations, but turned out to be odd
460          * -> remove padding
461          */
462         if (!(*count % 2) && (num_dests_pushed % 2))
463                 batadv_mcast_forw_push_scrape_padding(skb, tvlv_len);
464         /**
465          * estimated odd number of destinations, but turned out to be even
466          * -> add padding
467          */
468         else if ((*count % 2) && (!(num_dests_pushed % 2)))
469                 ret = batadv_mcast_forw_push_insert_padding(skb, tvlv_len);
470 
471 out:
472         *count = num_dests_pushed;
473         return ret;
474 }
475 
476 /**
477  * batadv_mcast_forw_push_dests() - push originator addresses onto an skb
478  * @bat_priv: the bat priv with all the soft interface information
479  * @skb: the skb to push the destination addresses onto
480  * @vid: the vlan identifier
481  * @is_routable: indicates whether the destination is routable
482  * @count: the number of originators the multicast packet needs to be sent to
483  * @tvlv_len: stores the amount of currently pushed TVLV bytes
484  *
485  * Push the MAC addresses of all originators which have indicated interest in
486  * this multicast packet onto the given skb.
487  *
488  * Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on
489  * success 0.
490  */
491 static int
492 batadv_mcast_forw_push_dests(struct batadv_priv *bat_priv, struct sk_buff *skb,
493                              unsigned short vid, int is_routable, int *count,
494                              unsigned short *tvlv_len)
495 {
496         unsigned short num_dests = 0;
497 
498         if (!batadv_mcast_forw_push_est_padding(skb, *count, tvlv_len))
499                 goto err;
500 
501         if (!batadv_mcast_forw_push_tt(bat_priv, skb, vid, &num_dests,
502                                        tvlv_len))
503                 goto err;
504 
505         if (!batadv_mcast_forw_push_want_all(bat_priv, skb, vid, &num_dests,
506                                              tvlv_len))
507                 goto err;
508 
509         if (is_routable &&
510             !batadv_mcast_forw_push_want_rtr(bat_priv, skb, vid, &num_dests,
511                                              tvlv_len))
512                 goto err;
513 
514         if (!batadv_mcast_forw_push_adjust_padding(skb, count, num_dests,
515                                                    tvlv_len))
516                 goto err;
517 
518         return 0;
519 err:
520         return -ENOMEM;
521 }
522 
523 /**
524  * batadv_mcast_forw_push_tracker() - push a multicast tracker TVLV header
525  * @skb: the skb to push the tracker TVLV onto
526  * @num_dests: the number of destination addresses to set in the header
527  * @tvlv_len: stores the amount of currently pushed TVLV bytes
528  *
529  * Pushes a multicast tracker TVLV header onto the given skb, including the
530  * generic TVLV header but excluding the destination MAC addresses.
531  *
532  * The provided num_dests value is taken into consideration to set the
533  * num_dests field in the tracker header and to set the appropriate TVLV length
534  * value fields.
535  *
536  * Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on
537  * success 0.
538  */
539 static int batadv_mcast_forw_push_tracker(struct sk_buff *skb, int num_dests,
540                                           unsigned short *tvlv_len)
541 {
542         struct batadv_tvlv_mcast_tracker *mcast_tracker;
543         struct batadv_tvlv_hdr *tvlv_hdr;
544         unsigned int tvlv_value_len;
545 
546         if (skb_headroom(skb) < sizeof(*mcast_tracker) + sizeof(*tvlv_hdr))
547                 return -ENOMEM;
548 
549         tvlv_value_len = sizeof(*mcast_tracker) + *tvlv_len;
550         if (tvlv_value_len + sizeof(*tvlv_hdr) > U16_MAX)
551                 return -ENOMEM;
552 
553         batadv_mcast_forw_skb_push(skb, sizeof(*mcast_tracker), tvlv_len);
554         mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb->data;
555         mcast_tracker->num_dests = htons(num_dests);
556 
557         skb_reset_network_header(skb);
558 
559         batadv_mcast_forw_skb_push(skb, sizeof(*tvlv_hdr), tvlv_len);
560         tvlv_hdr = (struct batadv_tvlv_hdr *)skb->data;
561         tvlv_hdr->type = BATADV_TVLV_MCAST_TRACKER;
562         tvlv_hdr->version = 1;
563         tvlv_hdr->len = htons(tvlv_value_len);
564 
565         return 0;
566 }
567 
568 /**
569  * batadv_mcast_forw_push_tvlvs() - push a multicast tracker TVLV onto an skb
570  * @bat_priv: the bat priv with all the soft interface information
571  * @skb: the skb to push the tracker TVLV onto
572  * @vid: the vlan identifier
573  * @is_routable: indicates whether the destination is routable
574  * @count: the number of originators the multicast packet needs to be sent to
575  * @tvlv_len: stores the amount of currently pushed TVLV bytes
576  *
577  * Pushes a multicast tracker TVLV onto the given skb, including the collected
578  * destination MAC addresses and the generic TVLV header.
579  *
580  * Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on
581  * success 0.
582  */
583 static int
584 batadv_mcast_forw_push_tvlvs(struct batadv_priv *bat_priv, struct sk_buff *skb,
585                              unsigned short vid, int is_routable, int count,
586                              unsigned short *tvlv_len)
587 {
588         int ret;
589 
590         ret = batadv_mcast_forw_push_dests(bat_priv, skb, vid, is_routable,
591                                            &count, tvlv_len);
592         if (ret < 0)
593                 return ret;
594 
595         ret = batadv_mcast_forw_push_tracker(skb, count, tvlv_len);
596         if (ret < 0)
597                 return ret;
598 
599         return 0;
600 }
601 
602 /**
603  * batadv_mcast_forw_push_hdr() - push a multicast packet header onto an skb
604  * @skb: the skb to push the header onto
605  * @tvlv_len: the total TVLV length value to set in the header
606  *
607  * Pushes a batman-adv multicast packet header onto the given skb and sets
608  * the provided total TVLV length value in it.
609  *
610  * Caller needs to ensure enough skb headroom is available.
611  *
612  * Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on
613  * success 0.
614  */
615 static int
616 batadv_mcast_forw_push_hdr(struct sk_buff *skb, unsigned short tvlv_len)
617 {
618         struct batadv_mcast_packet *mcast_packet;
619 
620         if (skb_headroom(skb) < sizeof(*mcast_packet))
621                 return -ENOMEM;
622 
623         skb_push(skb, sizeof(*mcast_packet));
624 
625         mcast_packet = (struct batadv_mcast_packet *)skb->data;
626         mcast_packet->version = BATADV_COMPAT_VERSION;
627         mcast_packet->ttl = BATADV_TTL;
628         mcast_packet->packet_type = BATADV_MCAST;
629         mcast_packet->reserved = 0;
630         mcast_packet->tvlv_len = htons(tvlv_len);
631 
632         return 0;
633 }
634 
635 /**
636  * batadv_mcast_forw_scrub_dests() - scrub destinations in a tracker TVLV
637  * @bat_priv: the bat priv with all the soft interface information
638  * @comp_neigh: next hop neighbor to scrub+collect destinations for
639  * @dest: start MAC entry in original skb's tracker TVLV
640  * @next_dest: start MAC entry in to be sent skb's tracker TVLV
641  * @num_dests: number of remaining destination MAC entries to iterate over
642  *
643  * This sorts destination entries into either the original batman-adv
644  * multicast packet or the skb (copy) that is going to be sent to comp_neigh
645  * next.
646  *
647  * In preparation for the next, to be (unicast) transmitted batman-adv multicast
648  * packet skb to be sent to the given neighbor node, tries to collect all
649  * originator MAC addresses that have the given neighbor node as their next hop
650  * in the to be transmitted skb (copy), which next_dest points into. That is we
651  * zero all destination entries in next_dest which do not have comp_neigh as
652  * their next hop. And zero all destination entries in the original skb that
653  * would have comp_neigh as their next hop (to avoid redundant transmissions and
654  * duplicated payload later).
655  */
656 static void
657 batadv_mcast_forw_scrub_dests(struct batadv_priv *bat_priv,
658                               struct batadv_neigh_node *comp_neigh, u8 *dest,
659                               u8 *next_dest, u16 num_dests)
660 {
661         struct batadv_neigh_node *next_neigh;
662 
663         /* skip first entry, this is what we are comparing with */
664         eth_zero_addr(dest);
665         dest += ETH_ALEN;
666         next_dest += ETH_ALEN;
667         num_dests--;
668 
669         batadv_mcast_forw_tracker_for_each_dest2(dest, next_dest, num_dests) {
670                 if (is_zero_ether_addr(next_dest))
671                         continue;
672 
673                 /* sanity check, we expect unicast destinations */
674                 if (is_multicast_ether_addr(next_dest)) {
675                         eth_zero_addr(dest);
676                         eth_zero_addr(next_dest);
677                         continue;
678                 }
679 
680                 next_neigh = batadv_orig_to_router(bat_priv, next_dest, NULL);
681                 if (!next_neigh) {
682                         eth_zero_addr(next_dest);
683                         continue;
684                 }
685 
686                 if (!batadv_compare_eth(next_neigh->addr, comp_neigh->addr)) {
687                         eth_zero_addr(next_dest);
688                         batadv_neigh_node_put(next_neigh);
689                         continue;
690                 }
691 
692                 /* found an entry for our next packet to transmit, so remove it
693                  * from the original packet
694                  */
695                 eth_zero_addr(dest);
696                 batadv_neigh_node_put(next_neigh);
697         }
698 }
699 
700 /**
701  * batadv_mcast_forw_shrink_fill() - swap slot with next non-zero destination
702  * @slot: the to be filled zero-MAC destination entry in a tracker TVLV
703  * @num_dests_slot: remaining entries in tracker TVLV from/including slot
704  *
705  * Searches for the next non-zero-MAC destination entry in a tracker TVLV after
706  * the given slot pointer. And if found, swaps it with the zero-MAC destination
707  * entry which the slot points to.
708  *
709  * Return: true if slot was swapped/filled successfully, false otherwise.
710  */
711 static bool batadv_mcast_forw_shrink_fill(u8 *slot, u16 num_dests_slot)
712 {
713         u16 num_dests_filler;
714         u8 *filler;
715 
716         /* sanity check, should not happen */
717         if (!num_dests_slot)
718                 return false;
719 
720         num_dests_filler = num_dests_slot - 1;
721         filler = slot + ETH_ALEN;
722 
723         /* find a candidate to fill the empty slot */
724         batadv_mcast_forw_tracker_for_each_dest(filler, num_dests_filler) {
725                 if (is_zero_ether_addr(filler))
726                         continue;
727 
728                 ether_addr_copy(slot, filler);
729                 eth_zero_addr(filler);
730                 return true;
731         }
732 
733         return false;
734 }
735 
736 /**
737  * batadv_mcast_forw_shrink_pack_dests() - pack destinations of a tracker TVLV
738  * @skb: the batman-adv multicast packet to compact destinations in
739  *
740  * Compacts the originator destination MAC addresses in the multicast tracker
741  * TVLV of the given multicast packet. This is done by moving all non-zero
742  * MAC addresses in direction of the skb head and all zero MAC addresses in skb
743  * tail direction, within the multicast tracker TVLV.
744  *
745  * Return: The number of consecutive zero MAC address destinations which are
746  * now at the end of the multicast tracker TVLV.
747  */
748 static int batadv_mcast_forw_shrink_pack_dests(struct sk_buff *skb)
749 {
750         struct batadv_tvlv_mcast_tracker *mcast_tracker;
751         unsigned char *skb_net_hdr;
752         u16 num_dests_slot;
753         u8 *slot;
754 
755         skb_net_hdr = skb_network_header(skb);
756         mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;
757         num_dests_slot = ntohs(mcast_tracker->num_dests);
758 
759         slot = (u8 *)mcast_tracker + sizeof(*mcast_tracker);
760 
761         batadv_mcast_forw_tracker_for_each_dest(slot, num_dests_slot) {
762                 /* find an empty slot */
763                 if (!is_zero_ether_addr(slot))
764                         continue;
765 
766                 if (!batadv_mcast_forw_shrink_fill(slot, num_dests_slot))
767                         /* could not find a filler, so we successfully packed
768                          * and can stop - and must not reduce num_dests_slot!
769                          */
770                         break;
771         }
772 
773         /* num_dests_slot is now the amount of reduced, zeroed
774          * destinations at the end of the tracker TVLV
775          */
776         return num_dests_slot;
777 }
778 
779 /**
780  * batadv_mcast_forw_shrink_align_offset() - get new alignment offset
781  * @num_dests_old: the old, to be updated amount of destination nodes
782  * @num_dests_reduce: the number of destinations that were removed
783  *
784  * Calculates the amount of potential extra alignment offset that is needed to
785  * adjust the TVLV padding after the change in destination nodes.
786  *
787  * Return:
788  *      0: If no change to padding is needed.
789  *      2: If padding needs to be removed.
790  *      -2: If padding needs to be added.
791  */
792 static short
793 batadv_mcast_forw_shrink_align_offset(unsigned int num_dests_old,
794                                       unsigned int num_dests_reduce)
795 {
796         /* even amount of removed destinations -> no alignment change */
797         if (!(num_dests_reduce % 2))
798                 return 0;
799 
800         /* even to odd amount of destinations -> remove padding */
801         if (!(num_dests_old % 2))
802                 return 2;
803 
804         /* odd to even amount of destinations -> add padding */
805         return -2;
806 }
807 
808 /**
809  * batadv_mcast_forw_shrink_update_headers() - update shrunk mc packet headers
810  * @skb: the batman-adv multicast packet to update headers of
811  * @num_dests_reduce: the number of destinations that were removed
812  *
813  * This updates any fields of a batman-adv multicast packet that are affected
814  * by the reduced number of destinations in the multicast tracket TVLV. In
815  * particular this updates:
816  *
817  * The num_dest field of the multicast tracker TVLV.
818  * The TVLV length field of the according generic TVLV header.
819  * The batman-adv multicast packet's total TVLV length field.
820  *
821  * Return: The offset in skb's tail direction at which the new batman-adv
822  * multicast packet header needs to start.
823  */
824 static unsigned int
825 batadv_mcast_forw_shrink_update_headers(struct sk_buff *skb,
826                                         unsigned int num_dests_reduce)
827 {
828         struct batadv_tvlv_mcast_tracker *mcast_tracker;
829         struct batadv_mcast_packet *mcast_packet;
830         struct batadv_tvlv_hdr *tvlv_hdr;
831         unsigned char *skb_net_hdr;
832         unsigned int offset;
833         short align_offset;
834         u16 num_dests;
835 
836         skb_net_hdr = skb_network_header(skb);
837         mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;
838         num_dests = ntohs(mcast_tracker->num_dests);
839 
840         align_offset = batadv_mcast_forw_shrink_align_offset(num_dests,
841                                                              num_dests_reduce);
842         offset = ETH_ALEN * num_dests_reduce + align_offset;
843         num_dests -= num_dests_reduce;
844 
845         /* update tracker header */
846         mcast_tracker->num_dests = htons(num_dests);
847 
848         /* update tracker's tvlv header's length field */
849         tvlv_hdr = (struct batadv_tvlv_hdr *)(skb_network_header(skb) -
850                                               sizeof(*tvlv_hdr));
851         tvlv_hdr->len = htons(ntohs(tvlv_hdr->len) - offset);
852 
853         /* update multicast packet header's tvlv length field */
854         mcast_packet = (struct batadv_mcast_packet *)skb->data;
855         mcast_packet->tvlv_len = htons(ntohs(mcast_packet->tvlv_len) - offset);
856 
857         return offset;
858 }
859 
860 /**
861  * batadv_mcast_forw_shrink_move_headers() - move multicast headers by offset
862  * @skb: the batman-adv multicast packet to move headers for
863  * @offset: a non-negative offset to move headers by, towards the skb tail
864  *
865  * Moves the batman-adv multicast packet header, its multicast tracker TVLV and
866  * any TVLVs in between by the given offset in direction towards the tail.
867  */
868 static void
869 batadv_mcast_forw_shrink_move_headers(struct sk_buff *skb, unsigned int offset)
870 {
871         struct batadv_tvlv_mcast_tracker *mcast_tracker;
872         unsigned char *skb_net_hdr;
873         unsigned int len;
874         u16 num_dests;
875 
876         skb_net_hdr = skb_network_header(skb);
877         mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;
878         num_dests = ntohs(mcast_tracker->num_dests);
879         len = skb_network_offset(skb) + sizeof(*mcast_tracker);
880         len += num_dests * ETH_ALEN;
881 
882         batadv_mcast_forw_scrape(skb, len, offset);
883 }
884 
885 /**
886  * batadv_mcast_forw_shrink_tracker() - remove zero addresses in a tracker tvlv
887  * @skb: the batman-adv multicast packet to (potentially) shrink
888  *
889  * Removes all destinations with a zero MAC addresses (00:00:00:00:00:00) from
890  * the given batman-adv multicast packet's tracker TVLV and updates headers
891  * accordingly to maintain a valid batman-adv multicast packet.
892  */
893 static void batadv_mcast_forw_shrink_tracker(struct sk_buff *skb)
894 {
895         unsigned int offset;
896         u16 dests_reduced;
897 
898         dests_reduced = batadv_mcast_forw_shrink_pack_dests(skb);
899         if (!dests_reduced)
900                 return;
901 
902         offset = batadv_mcast_forw_shrink_update_headers(skb, dests_reduced);
903         batadv_mcast_forw_shrink_move_headers(skb, offset);
904 }
905 
906 /**
907  * batadv_mcast_forw_packet() - forward a batman-adv multicast packet
908  * @bat_priv: the bat priv with all the soft interface information
909  * @skb: the received or locally generated batman-adv multicast packet
910  * @local_xmit: indicates that the packet was locally generated and not received
911  *
912  * Parses the tracker TVLV of a batman-adv multicast packet and forwards the
913  * packet as indicated in this TVLV.
914  *
915  * Caller needs to set the skb network header to the start of the multicast
916  * tracker TVLV (excluding the generic TVLV header) and the skb transport header
917  * to the next byte after this multicast tracker TVLV.
918  *
919  * Caller needs to free the skb.
920  *
921  * Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error
922  * code on failure. NET_RX_SUCCESS if the received packet is supposed to be
923  * decapsulated and forwarded to the own soft interface, NET_RX_DROP otherwise.
924  */
925 static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,
926                                     struct sk_buff *skb, bool local_xmit)
927 {
928         struct batadv_tvlv_mcast_tracker *mcast_tracker;
929         struct batadv_neigh_node *neigh_node;
930         unsigned long offset, num_dests_off;
931         struct sk_buff *nexthop_skb;
932         unsigned char *skb_net_hdr;
933         bool local_recv = false;
934         unsigned int tvlv_len;
935         bool xmitted = false;
936         u8 *dest, *next_dest;
937         u16 num_dests;
938         int ret;
939 
940         /* (at least) TVLV part needs to be linearized */
941         SKB_LINEAR_ASSERT(skb);
942 
943         /* check if num_dests is within skb length */
944         num_dests_off = offsetof(struct batadv_tvlv_mcast_tracker, num_dests);
945         if (num_dests_off > skb_network_header_len(skb))
946                 return -EINVAL;
947 
948         skb_net_hdr = skb_network_header(skb);
949         mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;
950         num_dests = ntohs(mcast_tracker->num_dests);
951 
952         dest = (u8 *)mcast_tracker + sizeof(*mcast_tracker);
953 
954         /* check if full tracker tvlv is within skb length */
955         tvlv_len = sizeof(*mcast_tracker) + ETH_ALEN * num_dests;
956         if (tvlv_len > skb_network_header_len(skb))
957                 return -EINVAL;
958 
959         /* invalidate checksum: */
960         skb->ip_summed = CHECKSUM_NONE;
961 
962         batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) {
963                 if (is_zero_ether_addr(dest))
964                         continue;
965 
966                 /* only unicast originator addresses supported */
967                 if (is_multicast_ether_addr(dest)) {
968                         eth_zero_addr(dest);
969                         continue;
970                 }
971 
972                 if (batadv_is_my_mac(bat_priv, dest)) {
973                         eth_zero_addr(dest);
974                         local_recv = true;
975                         continue;
976                 }
977 
978                 neigh_node = batadv_orig_to_router(bat_priv, dest, NULL);
979                 if (!neigh_node) {
980                         eth_zero_addr(dest);
981                         continue;
982                 }
983 
984                 nexthop_skb = skb_copy(skb, GFP_ATOMIC);
985                 if (!nexthop_skb) {
986                         batadv_neigh_node_put(neigh_node);
987                         return -ENOMEM;
988                 }
989 
990                 offset = dest - skb->data;
991                 next_dest = nexthop_skb->data + offset;
992 
993                 batadv_mcast_forw_scrub_dests(bat_priv, neigh_node, dest,
994                                               next_dest, num_dests);
995                 batadv_mcast_forw_shrink_tracker(nexthop_skb);
996 
997                 batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX);
998                 batadv_add_counter(bat_priv, BATADV_CNT_MCAST_TX_BYTES,
999                                    nexthop_skb->len + ETH_HLEN);
1000                 xmitted = true;
1001                 ret = batadv_send_unicast_skb(nexthop_skb, neigh_node);
1002 
1003                 batadv_neigh_node_put(neigh_node);
1004 
1005                 if (ret < 0)
1006                         return ret;
1007         }
1008 
1009         if (xmitted) {
1010                 if (local_xmit) {
1011                         batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX_LOCAL);
1012                         batadv_add_counter(bat_priv,
1013                                            BATADV_CNT_MCAST_TX_LOCAL_BYTES,
1014                                            skb->len -
1015                                            skb_transport_offset(skb));
1016                 } else {
1017                         batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_FWD);
1018                         batadv_add_counter(bat_priv, BATADV_CNT_MCAST_FWD_BYTES,
1019                                            skb->len + ETH_HLEN);
1020                 }
1021         }
1022 
1023         if (local_recv)
1024                 return NET_RX_SUCCESS;
1025         else
1026                 return NET_RX_DROP;
1027 }
1028 
1029 /**
1030  * batadv_mcast_forw_tracker_tvlv_handler() - handle an mcast tracker tvlv
1031  * @bat_priv: the bat priv with all the soft interface information
1032  * @skb: the received batman-adv multicast packet
1033  *
1034  * Parses the tracker TVLV of an incoming batman-adv multicast packet and
1035  * forwards the packet as indicated in this TVLV.
1036  *
1037  * Caller needs to set the skb network header to the start of the multicast
1038  * tracker TVLV (excluding the generic TVLV header) and the skb transport header
1039  * to the next byte after this multicast tracker TVLV.
1040  *
1041  * Caller needs to free the skb.
1042  *
1043  * Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error
1044  * code on failure. NET_RX_SUCCESS if the received packet is supposed to be
1045  * decapsulated and forwarded to the own soft interface, NET_RX_DROP otherwise.
1046  */
1047 int batadv_mcast_forw_tracker_tvlv_handler(struct batadv_priv *bat_priv,
1048                                            struct sk_buff *skb)
1049 {
1050         return batadv_mcast_forw_packet(bat_priv, skb, false);
1051 }
1052 
1053 /**
1054  * batadv_mcast_forw_packet_hdrlen() - multicast packet header length
1055  * @num_dests: number of destination nodes
1056  *
1057  * Calculates the total batman-adv multicast packet header length for a given
1058  * number of destination nodes (excluding the outer ethernet frame).
1059  *
1060  * Return: The calculated total batman-adv multicast packet header length.
1061  */
1062 unsigned int batadv_mcast_forw_packet_hdrlen(unsigned int num_dests)
1063 {
1064         /**
1065          * If the number of destination entries is even then we need to add
1066          * two byte padding to the tracker TVLV.
1067          */
1068         int padding = (!(num_dests % 2)) ? 2 : 0;
1069 
1070         return padding + num_dests * ETH_ALEN +
1071                sizeof(struct batadv_tvlv_mcast_tracker) +
1072                sizeof(struct batadv_tvlv_hdr) +
1073                sizeof(struct batadv_mcast_packet);
1074 }
1075 
1076 /**
1077  * batadv_mcast_forw_expand_head() - expand headroom for an mcast packet
1078  * @bat_priv: the bat priv with all the soft interface information
1079  * @skb: the multicast packet to send
1080  *
1081  * Tries to expand an skb's headroom so that its head to tail is 1298
1082  * bytes (minimum IPv6 MTU + vlan ethernet header size) large.
1083  *
1084  * Return: -EINVAL if the given skb's length is too large or -ENOMEM on memory
1085  * allocation failure. Otherwise, on success, zero is returned.
1086  */
1087 static int batadv_mcast_forw_expand_head(struct batadv_priv *bat_priv,
1088                                          struct sk_buff *skb)
1089 {
1090         int hdr_size = VLAN_ETH_HLEN + IPV6_MIN_MTU - skb->len;
1091 
1092          /* TODO: Could be tightened to actual number of destination nodes?
1093           * But it's tricky, number of destinations might have increased since
1094           * we last checked.
1095           */
1096         if (hdr_size < 0) {
1097                 /* batadv_mcast_forw_mode_check_count() should ensure we do not
1098                  * end up here
1099                  */
1100                 WARN_ON(1);
1101                 return -EINVAL;
1102         }
1103 
1104         if (skb_headroom(skb) < hdr_size &&
1105             pskb_expand_head(skb, hdr_size, 0, GFP_ATOMIC) < 0)
1106                 return -ENOMEM;
1107 
1108         return 0;
1109 }
1110 
1111 /**
1112  * batadv_mcast_forw_push() - encapsulate skb in a batman-adv multicast packet
1113  * @bat_priv: the bat priv with all the soft interface information
1114  * @skb: the multicast packet to encapsulate and send
1115  * @vid: the vlan identifier
1116  * @is_routable: indicates whether the destination is routable
1117  * @count: the number of originators the multicast packet needs to be sent to
1118  *
1119  * Encapsulates the given multicast packet in a batman-adv multicast packet.
1120  * A multicast tracker TVLV with destination originator addresses for any node
1121  * that signaled interest in it, that is either via the translation table or the
1122  * according want-all flags, is attached accordingly.
1123  *
1124  * Return: true on success, false otherwise.
1125  */
1126 bool batadv_mcast_forw_push(struct batadv_priv *bat_priv, struct sk_buff *skb,
1127                             unsigned short vid, int is_routable, int count)
1128 {
1129         unsigned short tvlv_len = 0;
1130         int ret;
1131 
1132         if (batadv_mcast_forw_expand_head(bat_priv, skb) < 0)
1133                 goto err;
1134 
1135         skb_reset_transport_header(skb);
1136 
1137         ret = batadv_mcast_forw_push_tvlvs(bat_priv, skb, vid, is_routable,
1138                                            count, &tvlv_len);
1139         if (ret < 0)
1140                 goto err;
1141 
1142         ret = batadv_mcast_forw_push_hdr(skb, tvlv_len);
1143         if (ret < 0)
1144                 goto err;
1145 
1146         return true;
1147 
1148 err:
1149         if (tvlv_len)
1150                 skb_pull(skb, tvlv_len);
1151 
1152         return false;
1153 }
1154 
1155 /**
1156  * batadv_mcast_forw_mcsend() - send a self prepared batman-adv multicast packet
1157  * @bat_priv: the bat priv with all the soft interface information
1158  * @skb: the multicast packet to encapsulate and send
1159  *
1160  * Transmits a batman-adv multicast packet that was locally prepared and
1161  * consumes/frees it.
1162  *
1163  * Return: NET_XMIT_DROP on memory allocation failure. NET_XMIT_SUCCESS
1164  * otherwise.
1165  */
1166 int batadv_mcast_forw_mcsend(struct batadv_priv *bat_priv,
1167                              struct sk_buff *skb)
1168 {
1169         int ret = batadv_mcast_forw_packet(bat_priv, skb, true);
1170 
1171         if (ret < 0) {
1172                 kfree_skb(skb);
1173                 return NET_XMIT_DROP;
1174         }
1175 
1176         consume_skb(skb);
1177         return NET_XMIT_SUCCESS;
1178 }
1179 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php