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

TOMOYO Linux Cross Reference
Linux/net/batman-adv/bridge_loop_avoidance.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  * Simon Wunderlich
  5  */
  6 
  7 #include "bridge_loop_avoidance.h"
  8 #include "main.h"
  9 
 10 #include <linux/atomic.h>
 11 #include <linux/byteorder/generic.h>
 12 #include <linux/compiler.h>
 13 #include <linux/container_of.h>
 14 #include <linux/crc16.h>
 15 #include <linux/errno.h>
 16 #include <linux/etherdevice.h>
 17 #include <linux/gfp.h>
 18 #include <linux/if_arp.h>
 19 #include <linux/if_ether.h>
 20 #include <linux/if_vlan.h>
 21 #include <linux/jhash.h>
 22 #include <linux/jiffies.h>
 23 #include <linux/kref.h>
 24 #include <linux/list.h>
 25 #include <linux/lockdep.h>
 26 #include <linux/netdevice.h>
 27 #include <linux/netlink.h>
 28 #include <linux/rculist.h>
 29 #include <linux/rcupdate.h>
 30 #include <linux/skbuff.h>
 31 #include <linux/slab.h>
 32 #include <linux/spinlock.h>
 33 #include <linux/sprintf.h>
 34 #include <linux/stddef.h>
 35 #include <linux/string.h>
 36 #include <linux/workqueue.h>
 37 #include <net/arp.h>
 38 #include <net/genetlink.h>
 39 #include <net/netlink.h>
 40 #include <net/sock.h>
 41 #include <uapi/linux/batadv_packet.h>
 42 #include <uapi/linux/batman_adv.h>
 43 
 44 #include "hard-interface.h"
 45 #include "hash.h"
 46 #include "log.h"
 47 #include "netlink.h"
 48 #include "originator.h"
 49 #include "soft-interface.h"
 50 #include "translation-table.h"
 51 
 52 static const u8 batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
 53 
 54 static void batadv_bla_periodic_work(struct work_struct *work);
 55 static void
 56 batadv_bla_send_announce(struct batadv_priv *bat_priv,
 57                          struct batadv_bla_backbone_gw *backbone_gw);
 58 
 59 /**
 60  * batadv_choose_claim() - choose the right bucket for a claim.
 61  * @data: data to hash
 62  * @size: size of the hash table
 63  *
 64  * Return: the hash index of the claim
 65  */
 66 static inline u32 batadv_choose_claim(const void *data, u32 size)
 67 {
 68         const struct batadv_bla_claim *claim = data;
 69         u32 hash = 0;
 70 
 71         hash = jhash(&claim->addr, sizeof(claim->addr), hash);
 72         hash = jhash(&claim->vid, sizeof(claim->vid), hash);
 73 
 74         return hash % size;
 75 }
 76 
 77 /**
 78  * batadv_choose_backbone_gw() - choose the right bucket for a backbone gateway.
 79  * @data: data to hash
 80  * @size: size of the hash table
 81  *
 82  * Return: the hash index of the backbone gateway
 83  */
 84 static inline u32 batadv_choose_backbone_gw(const void *data, u32 size)
 85 {
 86         const struct batadv_bla_backbone_gw *gw;
 87         u32 hash = 0;
 88 
 89         gw = data;
 90         hash = jhash(&gw->orig, sizeof(gw->orig), hash);
 91         hash = jhash(&gw->vid, sizeof(gw->vid), hash);
 92 
 93         return hash % size;
 94 }
 95 
 96 /**
 97  * batadv_compare_backbone_gw() - compare address and vid of two backbone gws
 98  * @node: list node of the first entry to compare
 99  * @data2: pointer to the second backbone gateway
100  *
101  * Return: true if the backbones have the same data, false otherwise
102  */
103 static bool batadv_compare_backbone_gw(const struct hlist_node *node,
104                                        const void *data2)
105 {
106         const void *data1 = container_of(node, struct batadv_bla_backbone_gw,
107                                          hash_entry);
108         const struct batadv_bla_backbone_gw *gw1 = data1;
109         const struct batadv_bla_backbone_gw *gw2 = data2;
110 
111         if (!batadv_compare_eth(gw1->orig, gw2->orig))
112                 return false;
113 
114         if (gw1->vid != gw2->vid)
115                 return false;
116 
117         return true;
118 }
119 
120 /**
121  * batadv_compare_claim() - compare address and vid of two claims
122  * @node: list node of the first entry to compare
123  * @data2: pointer to the second claims
124  *
125  * Return: true if the claim have the same data, 0 otherwise
126  */
127 static bool batadv_compare_claim(const struct hlist_node *node,
128                                  const void *data2)
129 {
130         const void *data1 = container_of(node, struct batadv_bla_claim,
131                                          hash_entry);
132         const struct batadv_bla_claim *cl1 = data1;
133         const struct batadv_bla_claim *cl2 = data2;
134 
135         if (!batadv_compare_eth(cl1->addr, cl2->addr))
136                 return false;
137 
138         if (cl1->vid != cl2->vid)
139                 return false;
140 
141         return true;
142 }
143 
144 /**
145  * batadv_backbone_gw_release() - release backbone gw from lists and queue for
146  *  free after rcu grace period
147  * @ref: kref pointer of the backbone gw
148  */
149 static void batadv_backbone_gw_release(struct kref *ref)
150 {
151         struct batadv_bla_backbone_gw *backbone_gw;
152 
153         backbone_gw = container_of(ref, struct batadv_bla_backbone_gw,
154                                    refcount);
155 
156         kfree_rcu(backbone_gw, rcu);
157 }
158 
159 /**
160  * batadv_backbone_gw_put() - decrement the backbone gw refcounter and possibly
161  *  release it
162  * @backbone_gw: backbone gateway to be free'd
163  */
164 static void batadv_backbone_gw_put(struct batadv_bla_backbone_gw *backbone_gw)
165 {
166         if (!backbone_gw)
167                 return;
168 
169         kref_put(&backbone_gw->refcount, batadv_backbone_gw_release);
170 }
171 
172 /**
173  * batadv_claim_release() - release claim from lists and queue for free after
174  *  rcu grace period
175  * @ref: kref pointer of the claim
176  */
177 static void batadv_claim_release(struct kref *ref)
178 {
179         struct batadv_bla_claim *claim;
180         struct batadv_bla_backbone_gw *old_backbone_gw;
181 
182         claim = container_of(ref, struct batadv_bla_claim, refcount);
183 
184         spin_lock_bh(&claim->backbone_lock);
185         old_backbone_gw = claim->backbone_gw;
186         claim->backbone_gw = NULL;
187         spin_unlock_bh(&claim->backbone_lock);
188 
189         spin_lock_bh(&old_backbone_gw->crc_lock);
190         old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
191         spin_unlock_bh(&old_backbone_gw->crc_lock);
192 
193         batadv_backbone_gw_put(old_backbone_gw);
194 
195         kfree_rcu(claim, rcu);
196 }
197 
198 /**
199  * batadv_claim_put() - decrement the claim refcounter and possibly release it
200  * @claim: claim to be free'd
201  */
202 static void batadv_claim_put(struct batadv_bla_claim *claim)
203 {
204         if (!claim)
205                 return;
206 
207         kref_put(&claim->refcount, batadv_claim_release);
208 }
209 
210 /**
211  * batadv_claim_hash_find() - looks for a claim in the claim hash
212  * @bat_priv: the bat priv with all the soft interface information
213  * @data: search data (may be local/static data)
214  *
215  * Return: claim if found or NULL otherwise.
216  */
217 static struct batadv_bla_claim *
218 batadv_claim_hash_find(struct batadv_priv *bat_priv,
219                        struct batadv_bla_claim *data)
220 {
221         struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
222         struct hlist_head *head;
223         struct batadv_bla_claim *claim;
224         struct batadv_bla_claim *claim_tmp = NULL;
225         int index;
226 
227         if (!hash)
228                 return NULL;
229 
230         index = batadv_choose_claim(data, hash->size);
231         head = &hash->table[index];
232 
233         rcu_read_lock();
234         hlist_for_each_entry_rcu(claim, head, hash_entry) {
235                 if (!batadv_compare_claim(&claim->hash_entry, data))
236                         continue;
237 
238                 if (!kref_get_unless_zero(&claim->refcount))
239                         continue;
240 
241                 claim_tmp = claim;
242                 break;
243         }
244         rcu_read_unlock();
245 
246         return claim_tmp;
247 }
248 
249 /**
250  * batadv_backbone_hash_find() - looks for a backbone gateway in the hash
251  * @bat_priv: the bat priv with all the soft interface information
252  * @addr: the address of the originator
253  * @vid: the VLAN ID
254  *
255  * Return: backbone gateway if found or NULL otherwise
256  */
257 static struct batadv_bla_backbone_gw *
258 batadv_backbone_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
259                           unsigned short vid)
260 {
261         struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
262         struct hlist_head *head;
263         struct batadv_bla_backbone_gw search_entry, *backbone_gw;
264         struct batadv_bla_backbone_gw *backbone_gw_tmp = NULL;
265         int index;
266 
267         if (!hash)
268                 return NULL;
269 
270         ether_addr_copy(search_entry.orig, addr);
271         search_entry.vid = vid;
272 
273         index = batadv_choose_backbone_gw(&search_entry, hash->size);
274         head = &hash->table[index];
275 
276         rcu_read_lock();
277         hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
278                 if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
279                                                 &search_entry))
280                         continue;
281 
282                 if (!kref_get_unless_zero(&backbone_gw->refcount))
283                         continue;
284 
285                 backbone_gw_tmp = backbone_gw;
286                 break;
287         }
288         rcu_read_unlock();
289 
290         return backbone_gw_tmp;
291 }
292 
293 /**
294  * batadv_bla_del_backbone_claims() - delete all claims for a backbone
295  * @backbone_gw: backbone gateway where the claims should be removed
296  */
297 static void
298 batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
299 {
300         struct batadv_hashtable *hash;
301         struct hlist_node *node_tmp;
302         struct hlist_head *head;
303         struct batadv_bla_claim *claim;
304         int i;
305         spinlock_t *list_lock;  /* protects write access to the hash lists */
306 
307         hash = backbone_gw->bat_priv->bla.claim_hash;
308         if (!hash)
309                 return;
310 
311         for (i = 0; i < hash->size; i++) {
312                 head = &hash->table[i];
313                 list_lock = &hash->list_locks[i];
314 
315                 spin_lock_bh(list_lock);
316                 hlist_for_each_entry_safe(claim, node_tmp,
317                                           head, hash_entry) {
318                         if (claim->backbone_gw != backbone_gw)
319                                 continue;
320 
321                         batadv_claim_put(claim);
322                         hlist_del_rcu(&claim->hash_entry);
323                 }
324                 spin_unlock_bh(list_lock);
325         }
326 
327         /* all claims gone, initialize CRC */
328         spin_lock_bh(&backbone_gw->crc_lock);
329         backbone_gw->crc = BATADV_BLA_CRC_INIT;
330         spin_unlock_bh(&backbone_gw->crc_lock);
331 }
332 
333 /**
334  * batadv_bla_send_claim() - sends a claim frame according to the provided info
335  * @bat_priv: the bat priv with all the soft interface information
336  * @mac: the mac address to be announced within the claim
337  * @vid: the VLAN ID
338  * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
339  */
340 static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const u8 *mac,
341                                   unsigned short vid, int claimtype)
342 {
343         struct sk_buff *skb;
344         struct ethhdr *ethhdr;
345         struct batadv_hard_iface *primary_if;
346         struct net_device *soft_iface;
347         u8 *hw_src;
348         struct batadv_bla_claim_dst local_claim_dest;
349         __be32 zeroip = 0;
350 
351         primary_if = batadv_primary_if_get_selected(bat_priv);
352         if (!primary_if)
353                 return;
354 
355         memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
356                sizeof(local_claim_dest));
357         local_claim_dest.type = claimtype;
358 
359         soft_iface = primary_if->soft_iface;
360 
361         skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
362                          /* IP DST: 0.0.0.0 */
363                          zeroip,
364                          primary_if->soft_iface,
365                          /* IP SRC: 0.0.0.0 */
366                          zeroip,
367                          /* Ethernet DST: Broadcast */
368                          NULL,
369                          /* Ethernet SRC/HW SRC:  originator mac */
370                          primary_if->net_dev->dev_addr,
371                          /* HW DST: FF:43:05:XX:YY:YY
372                           * with XX   = claim type
373                           * and YY:YY = group id
374                           */
375                          (u8 *)&local_claim_dest);
376 
377         if (!skb)
378                 goto out;
379 
380         ethhdr = (struct ethhdr *)skb->data;
381         hw_src = (u8 *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
382 
383         /* now we pretend that the client would have sent this ... */
384         switch (claimtype) {
385         case BATADV_CLAIM_TYPE_CLAIM:
386                 /* normal claim frame
387                  * set Ethernet SRC to the clients mac
388                  */
389                 ether_addr_copy(ethhdr->h_source, mac);
390                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
391                            "%s(): CLAIM %pM on vid %d\n", __func__, mac,
392                            batadv_print_vid(vid));
393                 break;
394         case BATADV_CLAIM_TYPE_UNCLAIM:
395                 /* unclaim frame
396                  * set HW SRC to the clients mac
397                  */
398                 ether_addr_copy(hw_src, mac);
399                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
400                            "%s(): UNCLAIM %pM on vid %d\n", __func__, mac,
401                            batadv_print_vid(vid));
402                 break;
403         case BATADV_CLAIM_TYPE_ANNOUNCE:
404                 /* announcement frame
405                  * set HW SRC to the special mac containing the crc
406                  */
407                 ether_addr_copy(hw_src, mac);
408                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
409                            "%s(): ANNOUNCE of %pM on vid %d\n", __func__,
410                            ethhdr->h_source, batadv_print_vid(vid));
411                 break;
412         case BATADV_CLAIM_TYPE_REQUEST:
413                 /* request frame
414                  * set HW SRC and header destination to the receiving backbone
415                  * gws mac
416                  */
417                 ether_addr_copy(hw_src, mac);
418                 ether_addr_copy(ethhdr->h_dest, mac);
419                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
420                            "%s(): REQUEST of %pM to %pM on vid %d\n", __func__,
421                            ethhdr->h_source, ethhdr->h_dest,
422                            batadv_print_vid(vid));
423                 break;
424         case BATADV_CLAIM_TYPE_LOOPDETECT:
425                 ether_addr_copy(ethhdr->h_source, mac);
426                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
427                            "%s(): LOOPDETECT of %pM to %pM on vid %d\n",
428                            __func__, ethhdr->h_source, ethhdr->h_dest,
429                            batadv_print_vid(vid));
430 
431                 break;
432         }
433 
434         if (vid & BATADV_VLAN_HAS_TAG) {
435                 skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
436                                       vid & VLAN_VID_MASK);
437                 if (!skb)
438                         goto out;
439         }
440 
441         skb_reset_mac_header(skb);
442         skb->protocol = eth_type_trans(skb, soft_iface);
443         batadv_inc_counter(bat_priv, BATADV_CNT_RX);
444         batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
445                            skb->len + ETH_HLEN);
446 
447         netif_rx(skb);
448 out:
449         batadv_hardif_put(primary_if);
450 }
451 
452 /**
453  * batadv_bla_loopdetect_report() - worker for reporting the loop
454  * @work: work queue item
455  *
456  * Throws an uevent, as the loopdetect check function can't do that itself
457  * since the kernel may sleep while throwing uevents.
458  */
459 static void batadv_bla_loopdetect_report(struct work_struct *work)
460 {
461         struct batadv_bla_backbone_gw *backbone_gw;
462         struct batadv_priv *bat_priv;
463         char vid_str[6] = { '\0' };
464 
465         backbone_gw = container_of(work, struct batadv_bla_backbone_gw,
466                                    report_work);
467         bat_priv = backbone_gw->bat_priv;
468 
469         batadv_info(bat_priv->soft_iface,
470                     "Possible loop on VLAN %d detected which can't be handled by BLA - please check your network setup!\n",
471                     batadv_print_vid(backbone_gw->vid));
472         snprintf(vid_str, sizeof(vid_str), "%d",
473                  batadv_print_vid(backbone_gw->vid));
474         vid_str[sizeof(vid_str) - 1] = 0;
475 
476         batadv_throw_uevent(bat_priv, BATADV_UEV_BLA, BATADV_UEV_LOOPDETECT,
477                             vid_str);
478 
479         batadv_backbone_gw_put(backbone_gw);
480 }
481 
482 /**
483  * batadv_bla_get_backbone_gw() - finds or creates a backbone gateway
484  * @bat_priv: the bat priv with all the soft interface information
485  * @orig: the mac address of the originator
486  * @vid: the VLAN ID
487  * @own_backbone: set if the requested backbone is local
488  *
489  * Return: the (possibly created) backbone gateway or NULL on error
490  */
491 static struct batadv_bla_backbone_gw *
492 batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
493                            unsigned short vid, bool own_backbone)
494 {
495         struct batadv_bla_backbone_gw *entry;
496         struct batadv_orig_node *orig_node;
497         int hash_added;
498 
499         entry = batadv_backbone_hash_find(bat_priv, orig, vid);
500 
501         if (entry)
502                 return entry;
503 
504         batadv_dbg(BATADV_DBG_BLA, bat_priv,
505                    "%s(): not found (%pM, %d), creating new entry\n", __func__,
506                    orig, batadv_print_vid(vid));
507 
508         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
509         if (!entry)
510                 return NULL;
511 
512         entry->vid = vid;
513         entry->lasttime = jiffies;
514         entry->crc = BATADV_BLA_CRC_INIT;
515         entry->bat_priv = bat_priv;
516         spin_lock_init(&entry->crc_lock);
517         atomic_set(&entry->request_sent, 0);
518         atomic_set(&entry->wait_periods, 0);
519         ether_addr_copy(entry->orig, orig);
520         INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
521         kref_init(&entry->refcount);
522 
523         kref_get(&entry->refcount);
524         hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
525                                      batadv_compare_backbone_gw,
526                                      batadv_choose_backbone_gw, entry,
527                                      &entry->hash_entry);
528 
529         if (unlikely(hash_added != 0)) {
530                 /* hash failed, free the structure */
531                 kfree(entry);
532                 return NULL;
533         }
534 
535         /* this is a gateway now, remove any TT entry on this VLAN */
536         orig_node = batadv_orig_hash_find(bat_priv, orig);
537         if (orig_node) {
538                 batadv_tt_global_del_orig(bat_priv, orig_node, vid,
539                                           "became a backbone gateway");
540                 batadv_orig_node_put(orig_node);
541         }
542 
543         if (own_backbone) {
544                 batadv_bla_send_announce(bat_priv, entry);
545 
546                 /* this will be decreased in the worker thread */
547                 atomic_inc(&entry->request_sent);
548                 atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
549                 atomic_inc(&bat_priv->bla.num_requests);
550         }
551 
552         return entry;
553 }
554 
555 /**
556  * batadv_bla_update_own_backbone_gw() - updates the own backbone gw for a VLAN
557  * @bat_priv: the bat priv with all the soft interface information
558  * @primary_if: the selected primary interface
559  * @vid: VLAN identifier
560  *
561  * update or add the own backbone gw to make sure we announce
562  * where we receive other backbone gws
563  */
564 static void
565 batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
566                                   struct batadv_hard_iface *primary_if,
567                                   unsigned short vid)
568 {
569         struct batadv_bla_backbone_gw *backbone_gw;
570 
571         backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
572                                                  primary_if->net_dev->dev_addr,
573                                                  vid, true);
574         if (unlikely(!backbone_gw))
575                 return;
576 
577         backbone_gw->lasttime = jiffies;
578         batadv_backbone_gw_put(backbone_gw);
579 }
580 
581 /**
582  * batadv_bla_answer_request() - answer a bla request by sending own claims
583  * @bat_priv: the bat priv with all the soft interface information
584  * @primary_if: interface where the request came on
585  * @vid: the vid where the request came on
586  *
587  * Repeat all of our own claims, and finally send an ANNOUNCE frame
588  * to allow the requester another check if the CRC is correct now.
589  */
590 static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
591                                       struct batadv_hard_iface *primary_if,
592                                       unsigned short vid)
593 {
594         struct hlist_head *head;
595         struct batadv_hashtable *hash;
596         struct batadv_bla_claim *claim;
597         struct batadv_bla_backbone_gw *backbone_gw;
598         int i;
599 
600         batadv_dbg(BATADV_DBG_BLA, bat_priv,
601                    "%s(): received a claim request, send all of our own claims again\n",
602                    __func__);
603 
604         backbone_gw = batadv_backbone_hash_find(bat_priv,
605                                                 primary_if->net_dev->dev_addr,
606                                                 vid);
607         if (!backbone_gw)
608                 return;
609 
610         hash = bat_priv->bla.claim_hash;
611         for (i = 0; i < hash->size; i++) {
612                 head = &hash->table[i];
613 
614                 rcu_read_lock();
615                 hlist_for_each_entry_rcu(claim, head, hash_entry) {
616                         /* only own claims are interesting */
617                         if (claim->backbone_gw != backbone_gw)
618                                 continue;
619 
620                         batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
621                                               BATADV_CLAIM_TYPE_CLAIM);
622                 }
623                 rcu_read_unlock();
624         }
625 
626         /* finally, send an announcement frame */
627         batadv_bla_send_announce(bat_priv, backbone_gw);
628         batadv_backbone_gw_put(backbone_gw);
629 }
630 
631 /**
632  * batadv_bla_send_request() - send a request to repeat claims
633  * @backbone_gw: the backbone gateway from whom we are out of sync
634  *
635  * When the crc is wrong, ask the backbone gateway for a full table update.
636  * After the request, it will repeat all of his own claims and finally
637  * send an announcement claim with which we can check again.
638  */
639 static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw)
640 {
641         /* first, remove all old entries */
642         batadv_bla_del_backbone_claims(backbone_gw);
643 
644         batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
645                    "Sending REQUEST to %pM\n", backbone_gw->orig);
646 
647         /* send request */
648         batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
649                               backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
650 
651         /* no local broadcasts should be sent or received, for now. */
652         if (!atomic_read(&backbone_gw->request_sent)) {
653                 atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
654                 atomic_set(&backbone_gw->request_sent, 1);
655         }
656 }
657 
658 /**
659  * batadv_bla_send_announce() - Send an announcement frame
660  * @bat_priv: the bat priv with all the soft interface information
661  * @backbone_gw: our backbone gateway which should be announced
662  */
663 static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
664                                      struct batadv_bla_backbone_gw *backbone_gw)
665 {
666         u8 mac[ETH_ALEN];
667         __be16 crc;
668 
669         memcpy(mac, batadv_announce_mac, 4);
670         spin_lock_bh(&backbone_gw->crc_lock);
671         crc = htons(backbone_gw->crc);
672         spin_unlock_bh(&backbone_gw->crc_lock);
673         memcpy(&mac[4], &crc, 2);
674 
675         batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
676                               BATADV_CLAIM_TYPE_ANNOUNCE);
677 }
678 
679 /**
680  * batadv_bla_add_claim() - Adds a claim in the claim hash
681  * @bat_priv: the bat priv with all the soft interface information
682  * @mac: the mac address of the claim
683  * @vid: the VLAN ID of the frame
684  * @backbone_gw: the backbone gateway which claims it
685  */
686 static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
687                                  const u8 *mac, const unsigned short vid,
688                                  struct batadv_bla_backbone_gw *backbone_gw)
689 {
690         struct batadv_bla_backbone_gw *old_backbone_gw;
691         struct batadv_bla_claim *claim;
692         struct batadv_bla_claim search_claim;
693         bool remove_crc = false;
694         int hash_added;
695 
696         ether_addr_copy(search_claim.addr, mac);
697         search_claim.vid = vid;
698         claim = batadv_claim_hash_find(bat_priv, &search_claim);
699 
700         /* create a new claim entry if it does not exist yet. */
701         if (!claim) {
702                 claim = kzalloc(sizeof(*claim), GFP_ATOMIC);
703                 if (!claim)
704                         return;
705 
706                 ether_addr_copy(claim->addr, mac);
707                 spin_lock_init(&claim->backbone_lock);
708                 claim->vid = vid;
709                 claim->lasttime = jiffies;
710                 kref_get(&backbone_gw->refcount);
711                 claim->backbone_gw = backbone_gw;
712                 kref_init(&claim->refcount);
713 
714                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
715                            "%s(): adding new entry %pM, vid %d to hash ...\n",
716                            __func__, mac, batadv_print_vid(vid));
717 
718                 kref_get(&claim->refcount);
719                 hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
720                                              batadv_compare_claim,
721                                              batadv_choose_claim, claim,
722                                              &claim->hash_entry);
723 
724                 if (unlikely(hash_added != 0)) {
725                         /* only local changes happened. */
726                         kfree(claim);
727                         return;
728                 }
729         } else {
730                 claim->lasttime = jiffies;
731                 if (claim->backbone_gw == backbone_gw)
732                         /* no need to register a new backbone */
733                         goto claim_free_ref;
734 
735                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
736                            "%s(): changing ownership for %pM, vid %d to gw %pM\n",
737                            __func__, mac, batadv_print_vid(vid),
738                            backbone_gw->orig);
739 
740                 remove_crc = true;
741         }
742 
743         /* replace backbone_gw atomically and adjust reference counters */
744         spin_lock_bh(&claim->backbone_lock);
745         old_backbone_gw = claim->backbone_gw;
746         kref_get(&backbone_gw->refcount);
747         claim->backbone_gw = backbone_gw;
748         spin_unlock_bh(&claim->backbone_lock);
749 
750         if (remove_crc) {
751                 /* remove claim address from old backbone_gw */
752                 spin_lock_bh(&old_backbone_gw->crc_lock);
753                 old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
754                 spin_unlock_bh(&old_backbone_gw->crc_lock);
755         }
756 
757         batadv_backbone_gw_put(old_backbone_gw);
758 
759         /* add claim address to new backbone_gw */
760         spin_lock_bh(&backbone_gw->crc_lock);
761         backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
762         spin_unlock_bh(&backbone_gw->crc_lock);
763         backbone_gw->lasttime = jiffies;
764 
765 claim_free_ref:
766         batadv_claim_put(claim);
767 }
768 
769 /**
770  * batadv_bla_claim_get_backbone_gw() - Get valid reference for backbone_gw of
771  *  claim
772  * @claim: claim whose backbone_gw should be returned
773  *
774  * Return: valid reference to claim::backbone_gw
775  */
776 static struct batadv_bla_backbone_gw *
777 batadv_bla_claim_get_backbone_gw(struct batadv_bla_claim *claim)
778 {
779         struct batadv_bla_backbone_gw *backbone_gw;
780 
781         spin_lock_bh(&claim->backbone_lock);
782         backbone_gw = claim->backbone_gw;
783         kref_get(&backbone_gw->refcount);
784         spin_unlock_bh(&claim->backbone_lock);
785 
786         return backbone_gw;
787 }
788 
789 /**
790  * batadv_bla_del_claim() - delete a claim from the claim hash
791  * @bat_priv: the bat priv with all the soft interface information
792  * @mac: mac address of the claim to be removed
793  * @vid: VLAN id for the claim to be removed
794  */
795 static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
796                                  const u8 *mac, const unsigned short vid)
797 {
798         struct batadv_bla_claim search_claim, *claim;
799         struct batadv_bla_claim *claim_removed_entry;
800         struct hlist_node *claim_removed_node;
801 
802         ether_addr_copy(search_claim.addr, mac);
803         search_claim.vid = vid;
804         claim = batadv_claim_hash_find(bat_priv, &search_claim);
805         if (!claim)
806                 return;
807 
808         batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): %pM, vid %d\n", __func__,
809                    mac, batadv_print_vid(vid));
810 
811         claim_removed_node = batadv_hash_remove(bat_priv->bla.claim_hash,
812                                                 batadv_compare_claim,
813                                                 batadv_choose_claim, claim);
814         if (!claim_removed_node)
815                 goto free_claim;
816 
817         /* reference from the hash is gone */
818         claim_removed_entry = hlist_entry(claim_removed_node,
819                                           struct batadv_bla_claim, hash_entry);
820         batadv_claim_put(claim_removed_entry);
821 
822 free_claim:
823         /* don't need the reference from hash_find() anymore */
824         batadv_claim_put(claim);
825 }
826 
827 /**
828  * batadv_handle_announce() - check for ANNOUNCE frame
829  * @bat_priv: the bat priv with all the soft interface information
830  * @an_addr: announcement mac address (ARP Sender HW address)
831  * @backbone_addr: originator address of the sender (Ethernet source MAC)
832  * @vid: the VLAN ID of the frame
833  *
834  * Return: true if handled
835  */
836 static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
837                                    u8 *backbone_addr, unsigned short vid)
838 {
839         struct batadv_bla_backbone_gw *backbone_gw;
840         u16 backbone_crc, crc;
841 
842         if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
843                 return false;
844 
845         backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
846                                                  false);
847 
848         if (unlikely(!backbone_gw))
849                 return true;
850 
851         /* handle as ANNOUNCE frame */
852         backbone_gw->lasttime = jiffies;
853         crc = ntohs(*((__force __be16 *)(&an_addr[4])));
854 
855         batadv_dbg(BATADV_DBG_BLA, bat_priv,
856                    "%s(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
857                    __func__, batadv_print_vid(vid), backbone_gw->orig, crc);
858 
859         spin_lock_bh(&backbone_gw->crc_lock);
860         backbone_crc = backbone_gw->crc;
861         spin_unlock_bh(&backbone_gw->crc_lock);
862 
863         if (backbone_crc != crc) {
864                 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
865                            "%s(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
866                            __func__, backbone_gw->orig,
867                            batadv_print_vid(backbone_gw->vid),
868                            backbone_crc, crc);
869 
870                 batadv_bla_send_request(backbone_gw);
871         } else {
872                 /* if we have sent a request and the crc was OK,
873                  * we can allow traffic again.
874                  */
875                 if (atomic_read(&backbone_gw->request_sent)) {
876                         atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
877                         atomic_set(&backbone_gw->request_sent, 0);
878                 }
879         }
880 
881         batadv_backbone_gw_put(backbone_gw);
882         return true;
883 }
884 
885 /**
886  * batadv_handle_request() - check for REQUEST frame
887  * @bat_priv: the bat priv with all the soft interface information
888  * @primary_if: the primary hard interface of this batman soft interface
889  * @backbone_addr: backbone address to be requested (ARP sender HW MAC)
890  * @ethhdr: ethernet header of a packet
891  * @vid: the VLAN ID of the frame
892  *
893  * Return: true if handled
894  */
895 static bool batadv_handle_request(struct batadv_priv *bat_priv,
896                                   struct batadv_hard_iface *primary_if,
897                                   u8 *backbone_addr, struct ethhdr *ethhdr,
898                                   unsigned short vid)
899 {
900         /* check for REQUEST frame */
901         if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
902                 return false;
903 
904         /* sanity check, this should not happen on a normal switch,
905          * we ignore it in this case.
906          */
907         if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
908                 return true;
909 
910         batadv_dbg(BATADV_DBG_BLA, bat_priv,
911                    "%s(): REQUEST vid %d (sent by %pM)...\n",
912                    __func__, batadv_print_vid(vid), ethhdr->h_source);
913 
914         batadv_bla_answer_request(bat_priv, primary_if, vid);
915         return true;
916 }
917 
918 /**
919  * batadv_handle_unclaim() - check for UNCLAIM frame
920  * @bat_priv: the bat priv with all the soft interface information
921  * @primary_if: the primary hard interface of this batman soft interface
922  * @backbone_addr: originator address of the backbone (Ethernet source)
923  * @claim_addr: Client to be unclaimed (ARP sender HW MAC)
924  * @vid: the VLAN ID of the frame
925  *
926  * Return: true if handled
927  */
928 static bool batadv_handle_unclaim(struct batadv_priv *bat_priv,
929                                   struct batadv_hard_iface *primary_if,
930                                   const u8 *backbone_addr, const u8 *claim_addr,
931                                   unsigned short vid)
932 {
933         struct batadv_bla_backbone_gw *backbone_gw;
934 
935         /* unclaim in any case if it is our own */
936         if (primary_if && batadv_compare_eth(backbone_addr,
937                                              primary_if->net_dev->dev_addr))
938                 batadv_bla_send_claim(bat_priv, claim_addr, vid,
939                                       BATADV_CLAIM_TYPE_UNCLAIM);
940 
941         backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
942 
943         if (!backbone_gw)
944                 return true;
945 
946         /* this must be an UNCLAIM frame */
947         batadv_dbg(BATADV_DBG_BLA, bat_priv,
948                    "%s(): UNCLAIM %pM on vid %d (sent by %pM)...\n", __func__,
949                    claim_addr, batadv_print_vid(vid), backbone_gw->orig);
950 
951         batadv_bla_del_claim(bat_priv, claim_addr, vid);
952         batadv_backbone_gw_put(backbone_gw);
953         return true;
954 }
955 
956 /**
957  * batadv_handle_claim() - check for CLAIM frame
958  * @bat_priv: the bat priv with all the soft interface information
959  * @primary_if: the primary hard interface of this batman soft interface
960  * @backbone_addr: originator address of the backbone (Ethernet Source)
961  * @claim_addr: client mac address to be claimed (ARP sender HW MAC)
962  * @vid: the VLAN ID of the frame
963  *
964  * Return: true if handled
965  */
966 static bool batadv_handle_claim(struct batadv_priv *bat_priv,
967                                 struct batadv_hard_iface *primary_if,
968                                 const u8 *backbone_addr, const u8 *claim_addr,
969                                 unsigned short vid)
970 {
971         struct batadv_bla_backbone_gw *backbone_gw;
972 
973         /* register the gateway if not yet available, and add the claim. */
974 
975         backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
976                                                  false);
977 
978         if (unlikely(!backbone_gw))
979                 return true;
980 
981         /* this must be a CLAIM frame */
982         batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
983         if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
984                 batadv_bla_send_claim(bat_priv, claim_addr, vid,
985                                       BATADV_CLAIM_TYPE_CLAIM);
986 
987         /* TODO: we could call something like tt_local_del() here. */
988 
989         batadv_backbone_gw_put(backbone_gw);
990         return true;
991 }
992 
993 /**
994  * batadv_check_claim_group() - check for claim group membership
995  * @bat_priv: the bat priv with all the soft interface information
996  * @primary_if: the primary interface of this batman interface
997  * @hw_src: the Hardware source in the ARP Header
998  * @hw_dst: the Hardware destination in the ARP Header
999  * @ethhdr: pointer to the Ethernet header of the claim frame
1000  *
1001  * checks if it is a claim packet and if it's on the same group.
1002  * This function also applies the group ID of the sender
1003  * if it is in the same mesh.
1004  *
1005  * Return:
1006  *      2  - if it is a claim packet and on the same group
1007  *      1  - if is a claim packet from another group
1008  *      0  - if it is not a claim packet
1009  */
1010 static int batadv_check_claim_group(struct batadv_priv *bat_priv,
1011                                     struct batadv_hard_iface *primary_if,
1012                                     u8 *hw_src, u8 *hw_dst,
1013                                     struct ethhdr *ethhdr)
1014 {
1015         u8 *backbone_addr;
1016         struct batadv_orig_node *orig_node;
1017         struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
1018 
1019         bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
1020         bla_dst_own = &bat_priv->bla.claim_dest;
1021 
1022         /* if announcement packet, use the source,
1023          * otherwise assume it is in the hw_src
1024          */
1025         switch (bla_dst->type) {
1026         case BATADV_CLAIM_TYPE_CLAIM:
1027                 backbone_addr = hw_src;
1028                 break;
1029         case BATADV_CLAIM_TYPE_REQUEST:
1030         case BATADV_CLAIM_TYPE_ANNOUNCE:
1031         case BATADV_CLAIM_TYPE_UNCLAIM:
1032                 backbone_addr = ethhdr->h_source;
1033                 break;
1034         default:
1035                 return 0;
1036         }
1037 
1038         /* don't accept claim frames from ourselves */
1039         if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
1040                 return 0;
1041 
1042         /* if its already the same group, it is fine. */
1043         if (bla_dst->group == bla_dst_own->group)
1044                 return 2;
1045 
1046         /* lets see if this originator is in our mesh */
1047         orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
1048 
1049         /* don't accept claims from gateways which are not in
1050          * the same mesh or group.
1051          */
1052         if (!orig_node)
1053                 return 1;
1054 
1055         /* if our mesh friends mac is bigger, use it for ourselves. */
1056         if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) {
1057                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1058                            "taking other backbones claim group: %#.4x\n",
1059                            ntohs(bla_dst->group));
1060                 bla_dst_own->group = bla_dst->group;
1061         }
1062 
1063         batadv_orig_node_put(orig_node);
1064 
1065         return 2;
1066 }
1067 
1068 /**
1069  * batadv_bla_process_claim() - Check if this is a claim frame, and process it
1070  * @bat_priv: the bat priv with all the soft interface information
1071  * @primary_if: the primary hard interface of this batman soft interface
1072  * @skb: the frame to be checked
1073  *
1074  * Return: true if it was a claim frame, otherwise return false to
1075  * tell the callee that it can use the frame on its own.
1076  */
1077 static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
1078                                      struct batadv_hard_iface *primary_if,
1079                                      struct sk_buff *skb)
1080 {
1081         struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
1082         u8 *hw_src, *hw_dst;
1083         struct vlan_hdr *vhdr, vhdr_buf;
1084         struct ethhdr *ethhdr;
1085         struct arphdr *arphdr;
1086         unsigned short vid;
1087         int vlan_depth = 0;
1088         __be16 proto;
1089         int headlen;
1090         int ret;
1091 
1092         vid = batadv_get_vid(skb, 0);
1093         ethhdr = eth_hdr(skb);
1094 
1095         proto = ethhdr->h_proto;
1096         headlen = ETH_HLEN;
1097         if (vid & BATADV_VLAN_HAS_TAG) {
1098                 /* Traverse the VLAN/Ethertypes.
1099                  *
1100                  * At this point it is known that the first protocol is a VLAN
1101                  * header, so start checking at the encapsulated protocol.
1102                  *
1103                  * The depth of the VLAN headers is recorded to drop BLA claim
1104                  * frames encapsulated into multiple VLAN headers (QinQ).
1105                  */
1106                 do {
1107                         vhdr = skb_header_pointer(skb, headlen, VLAN_HLEN,
1108                                                   &vhdr_buf);
1109                         if (!vhdr)
1110                                 return false;
1111 
1112                         proto = vhdr->h_vlan_encapsulated_proto;
1113                         headlen += VLAN_HLEN;
1114                         vlan_depth++;
1115                 } while (proto == htons(ETH_P_8021Q));
1116         }
1117 
1118         if (proto != htons(ETH_P_ARP))
1119                 return false; /* not a claim frame */
1120 
1121         /* this must be a ARP frame. check if it is a claim. */
1122 
1123         if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
1124                 return false;
1125 
1126         /* pskb_may_pull() may have modified the pointers, get ethhdr again */
1127         ethhdr = eth_hdr(skb);
1128         arphdr = (struct arphdr *)((u8 *)ethhdr + headlen);
1129 
1130         /* Check whether the ARP frame carries a valid
1131          * IP information
1132          */
1133         if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
1134                 return false;
1135         if (arphdr->ar_pro != htons(ETH_P_IP))
1136                 return false;
1137         if (arphdr->ar_hln != ETH_ALEN)
1138                 return false;
1139         if (arphdr->ar_pln != 4)
1140                 return false;
1141 
1142         hw_src = (u8 *)arphdr + sizeof(struct arphdr);
1143         hw_dst = hw_src + ETH_ALEN + 4;
1144         bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
1145         bla_dst_own = &bat_priv->bla.claim_dest;
1146 
1147         /* check if it is a claim frame in general */
1148         if (memcmp(bla_dst->magic, bla_dst_own->magic,
1149                    sizeof(bla_dst->magic)) != 0)
1150                 return false;
1151 
1152         /* check if there is a claim frame encapsulated deeper in (QinQ) and
1153          * drop that, as this is not supported by BLA but should also not be
1154          * sent via the mesh.
1155          */
1156         if (vlan_depth > 1)
1157                 return true;
1158 
1159         /* Let the loopdetect frames on the mesh in any case. */
1160         if (bla_dst->type == BATADV_CLAIM_TYPE_LOOPDETECT)
1161                 return false;
1162 
1163         /* check if it is a claim frame. */
1164         ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
1165                                        ethhdr);
1166         if (ret == 1)
1167                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1168                            "%s(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
1169                            __func__, ethhdr->h_source, batadv_print_vid(vid),
1170                            hw_src, hw_dst);
1171 
1172         if (ret < 2)
1173                 return !!ret;
1174 
1175         /* become a backbone gw ourselves on this vlan if not happened yet */
1176         batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1177 
1178         /* check for the different types of claim frames ... */
1179         switch (bla_dst->type) {
1180         case BATADV_CLAIM_TYPE_CLAIM:
1181                 if (batadv_handle_claim(bat_priv, primary_if, hw_src,
1182                                         ethhdr->h_source, vid))
1183                         return true;
1184                 break;
1185         case BATADV_CLAIM_TYPE_UNCLAIM:
1186                 if (batadv_handle_unclaim(bat_priv, primary_if,
1187                                           ethhdr->h_source, hw_src, vid))
1188                         return true;
1189                 break;
1190 
1191         case BATADV_CLAIM_TYPE_ANNOUNCE:
1192                 if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
1193                                            vid))
1194                         return true;
1195                 break;
1196         case BATADV_CLAIM_TYPE_REQUEST:
1197                 if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
1198                                           vid))
1199                         return true;
1200                 break;
1201         }
1202 
1203         batadv_dbg(BATADV_DBG_BLA, bat_priv,
1204                    "%s(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
1205                    __func__, ethhdr->h_source, batadv_print_vid(vid), hw_src,
1206                    hw_dst);
1207         return true;
1208 }
1209 
1210 /**
1211  * batadv_bla_purge_backbone_gw() - Remove backbone gateways after a timeout or
1212  *  immediately
1213  * @bat_priv: the bat priv with all the soft interface information
1214  * @now: whether the whole hash shall be wiped now
1215  *
1216  * Check when we last heard from other nodes, and remove them in case of
1217  * a time out, or clean all backbone gws if now is set.
1218  */
1219 static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
1220 {
1221         struct batadv_bla_backbone_gw *backbone_gw;
1222         struct hlist_node *node_tmp;
1223         struct hlist_head *head;
1224         struct batadv_hashtable *hash;
1225         spinlock_t *list_lock;  /* protects write access to the hash lists */
1226         int i;
1227 
1228         hash = bat_priv->bla.backbone_hash;
1229         if (!hash)
1230                 return;
1231 
1232         for (i = 0; i < hash->size; i++) {
1233                 head = &hash->table[i];
1234                 list_lock = &hash->list_locks[i];
1235 
1236                 spin_lock_bh(list_lock);
1237                 hlist_for_each_entry_safe(backbone_gw, node_tmp,
1238                                           head, hash_entry) {
1239                         if (now)
1240                                 goto purge_now;
1241                         if (!batadv_has_timed_out(backbone_gw->lasttime,
1242                                                   BATADV_BLA_BACKBONE_TIMEOUT))
1243                                 continue;
1244 
1245                         batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
1246                                    "%s(): backbone gw %pM timed out\n",
1247                                    __func__, backbone_gw->orig);
1248 
1249 purge_now:
1250                         /* don't wait for the pending request anymore */
1251                         if (atomic_read(&backbone_gw->request_sent))
1252                                 atomic_dec(&bat_priv->bla.num_requests);
1253 
1254                         batadv_bla_del_backbone_claims(backbone_gw);
1255 
1256                         hlist_del_rcu(&backbone_gw->hash_entry);
1257                         batadv_backbone_gw_put(backbone_gw);
1258                 }
1259                 spin_unlock_bh(list_lock);
1260         }
1261 }
1262 
1263 /**
1264  * batadv_bla_purge_claims() - Remove claims after a timeout or immediately
1265  * @bat_priv: the bat priv with all the soft interface information
1266  * @primary_if: the selected primary interface, may be NULL if now is set
1267  * @now: whether the whole hash shall be wiped now
1268  *
1269  * Check when we heard last time from our own claims, and remove them in case of
1270  * a time out, or clean all claims if now is set
1271  */
1272 static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
1273                                     struct batadv_hard_iface *primary_if,
1274                                     int now)
1275 {
1276         struct batadv_bla_backbone_gw *backbone_gw;
1277         struct batadv_bla_claim *claim;
1278         struct hlist_head *head;
1279         struct batadv_hashtable *hash;
1280         int i;
1281 
1282         hash = bat_priv->bla.claim_hash;
1283         if (!hash)
1284                 return;
1285 
1286         for (i = 0; i < hash->size; i++) {
1287                 head = &hash->table[i];
1288 
1289                 rcu_read_lock();
1290                 hlist_for_each_entry_rcu(claim, head, hash_entry) {
1291                         backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
1292                         if (now)
1293                                 goto purge_now;
1294 
1295                         if (!batadv_compare_eth(backbone_gw->orig,
1296                                                 primary_if->net_dev->dev_addr))
1297                                 goto skip;
1298 
1299                         if (!batadv_has_timed_out(claim->lasttime,
1300                                                   BATADV_BLA_CLAIM_TIMEOUT))
1301                                 goto skip;
1302 
1303                         batadv_dbg(BATADV_DBG_BLA, bat_priv,
1304                                    "%s(): timed out.\n", __func__);
1305 
1306 purge_now:
1307                         batadv_dbg(BATADV_DBG_BLA, bat_priv,
1308                                    "%s(): %pM, vid %d\n", __func__,
1309                                    claim->addr, claim->vid);
1310 
1311                         batadv_handle_unclaim(bat_priv, primary_if,
1312                                               backbone_gw->orig,
1313                                               claim->addr, claim->vid);
1314 skip:
1315                         batadv_backbone_gw_put(backbone_gw);
1316                 }
1317                 rcu_read_unlock();
1318         }
1319 }
1320 
1321 /**
1322  * batadv_bla_update_orig_address() - Update the backbone gateways when the own
1323  *  originator address changes
1324  * @bat_priv: the bat priv with all the soft interface information
1325  * @primary_if: the new selected primary_if
1326  * @oldif: the old primary interface, may be NULL
1327  */
1328 void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1329                                     struct batadv_hard_iface *primary_if,
1330                                     struct batadv_hard_iface *oldif)
1331 {
1332         struct batadv_bla_backbone_gw *backbone_gw;
1333         struct hlist_head *head;
1334         struct batadv_hashtable *hash;
1335         __be16 group;
1336         int i;
1337 
1338         /* reset bridge loop avoidance group id */
1339         group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
1340         bat_priv->bla.claim_dest.group = group;
1341 
1342         /* purge everything when bridge loop avoidance is turned off */
1343         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1344                 oldif = NULL;
1345 
1346         if (!oldif) {
1347                 batadv_bla_purge_claims(bat_priv, NULL, 1);
1348                 batadv_bla_purge_backbone_gw(bat_priv, 1);
1349                 return;
1350         }
1351 
1352         hash = bat_priv->bla.backbone_hash;
1353         if (!hash)
1354                 return;
1355 
1356         for (i = 0; i < hash->size; i++) {
1357                 head = &hash->table[i];
1358 
1359                 rcu_read_lock();
1360                 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1361                         /* own orig still holds the old value. */
1362                         if (!batadv_compare_eth(backbone_gw->orig,
1363                                                 oldif->net_dev->dev_addr))
1364                                 continue;
1365 
1366                         ether_addr_copy(backbone_gw->orig,
1367                                         primary_if->net_dev->dev_addr);
1368                         /* send an announce frame so others will ask for our
1369                          * claims and update their tables.
1370                          */
1371                         batadv_bla_send_announce(bat_priv, backbone_gw);
1372                 }
1373                 rcu_read_unlock();
1374         }
1375 }
1376 
1377 /**
1378  * batadv_bla_send_loopdetect() - send a loopdetect frame
1379  * @bat_priv: the bat priv with all the soft interface information
1380  * @backbone_gw: the backbone gateway for which a loop should be detected
1381  *
1382  * To detect loops that the bridge loop avoidance can't handle, send a loop
1383  * detection packet on the backbone. Unlike other BLA frames, this frame will
1384  * be allowed on the mesh by other nodes. If it is received on the mesh, this
1385  * indicates that there is a loop.
1386  */
1387 static void
1388 batadv_bla_send_loopdetect(struct batadv_priv *bat_priv,
1389                            struct batadv_bla_backbone_gw *backbone_gw)
1390 {
1391         batadv_dbg(BATADV_DBG_BLA, bat_priv, "Send loopdetect frame for vid %d\n",
1392                    backbone_gw->vid);
1393         batadv_bla_send_claim(bat_priv, bat_priv->bla.loopdetect_addr,
1394                               backbone_gw->vid, BATADV_CLAIM_TYPE_LOOPDETECT);
1395 }
1396 
1397 /**
1398  * batadv_bla_status_update() - purge bla interfaces if necessary
1399  * @net_dev: the soft interface net device
1400  */
1401 void batadv_bla_status_update(struct net_device *net_dev)
1402 {
1403         struct batadv_priv *bat_priv = netdev_priv(net_dev);
1404         struct batadv_hard_iface *primary_if;
1405 
1406         primary_if = batadv_primary_if_get_selected(bat_priv);
1407         if (!primary_if)
1408                 return;
1409 
1410         /* this function already purges everything when bla is disabled,
1411          * so just call that one.
1412          */
1413         batadv_bla_update_orig_address(bat_priv, primary_if, primary_if);
1414         batadv_hardif_put(primary_if);
1415 }
1416 
1417 /**
1418  * batadv_bla_periodic_work() - performs periodic bla work
1419  * @work: kernel work struct
1420  *
1421  * periodic work to do:
1422  *  * purge structures when they are too old
1423  *  * send announcements
1424  */
1425 static void batadv_bla_periodic_work(struct work_struct *work)
1426 {
1427         struct delayed_work *delayed_work;
1428         struct batadv_priv *bat_priv;
1429         struct batadv_priv_bla *priv_bla;
1430         struct hlist_head *head;
1431         struct batadv_bla_backbone_gw *backbone_gw;
1432         struct batadv_hashtable *hash;
1433         struct batadv_hard_iface *primary_if;
1434         bool send_loopdetect = false;
1435         int i;
1436 
1437         delayed_work = to_delayed_work(work);
1438         priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
1439         bat_priv = container_of(priv_bla, struct batadv_priv, bla);
1440         primary_if = batadv_primary_if_get_selected(bat_priv);
1441         if (!primary_if)
1442                 goto out;
1443 
1444         batadv_bla_purge_claims(bat_priv, primary_if, 0);
1445         batadv_bla_purge_backbone_gw(bat_priv, 0);
1446 
1447         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1448                 goto out;
1449 
1450         if (atomic_dec_and_test(&bat_priv->bla.loopdetect_next)) {
1451                 /* set a new random mac address for the next bridge loop
1452                  * detection frames. Set the locally administered bit to avoid
1453                  * collisions with users mac addresses.
1454                  */
1455                 eth_random_addr(bat_priv->bla.loopdetect_addr);
1456                 bat_priv->bla.loopdetect_addr[0] = 0xba;
1457                 bat_priv->bla.loopdetect_addr[1] = 0xbe;
1458                 bat_priv->bla.loopdetect_lasttime = jiffies;
1459                 atomic_set(&bat_priv->bla.loopdetect_next,
1460                            BATADV_BLA_LOOPDETECT_PERIODS);
1461 
1462                 /* mark for sending loop detect on all VLANs */
1463                 send_loopdetect = true;
1464         }
1465 
1466         hash = bat_priv->bla.backbone_hash;
1467         if (!hash)
1468                 goto out;
1469 
1470         for (i = 0; i < hash->size; i++) {
1471                 head = &hash->table[i];
1472 
1473                 rcu_read_lock();
1474                 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1475                         if (!batadv_compare_eth(backbone_gw->orig,
1476                                                 primary_if->net_dev->dev_addr))
1477                                 continue;
1478 
1479                         backbone_gw->lasttime = jiffies;
1480 
1481                         batadv_bla_send_announce(bat_priv, backbone_gw);
1482                         if (send_loopdetect)
1483                                 batadv_bla_send_loopdetect(bat_priv,
1484                                                            backbone_gw);
1485 
1486                         /* request_sent is only set after creation to avoid
1487                          * problems when we are not yet known as backbone gw
1488                          * in the backbone.
1489                          *
1490                          * We can reset this now after we waited some periods
1491                          * to give bridge forward delays and bla group forming
1492                          * some grace time.
1493                          */
1494 
1495                         if (atomic_read(&backbone_gw->request_sent) == 0)
1496                                 continue;
1497 
1498                         if (!atomic_dec_and_test(&backbone_gw->wait_periods))
1499                                 continue;
1500 
1501                         atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
1502                         atomic_set(&backbone_gw->request_sent, 0);
1503                 }
1504                 rcu_read_unlock();
1505         }
1506 out:
1507         batadv_hardif_put(primary_if);
1508 
1509         queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1510                            msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
1511 }
1512 
1513 /* The hash for claim and backbone hash receive the same key because they
1514  * are getting initialized by hash_new with the same key. Reinitializing
1515  * them with to different keys to allow nested locking without generating
1516  * lockdep warnings
1517  */
1518 static struct lock_class_key batadv_claim_hash_lock_class_key;
1519 static struct lock_class_key batadv_backbone_hash_lock_class_key;
1520 
1521 /**
1522  * batadv_bla_init() - initialize all bla structures
1523  * @bat_priv: the bat priv with all the soft interface information
1524  *
1525  * Return: 0 on success, < 0 on error.
1526  */
1527 int batadv_bla_init(struct batadv_priv *bat_priv)
1528 {
1529         int i;
1530         u8 claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
1531         struct batadv_hard_iface *primary_if;
1532         u16 crc;
1533         unsigned long entrytime;
1534 
1535         spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
1536 
1537         batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
1538 
1539         /* setting claim destination address */
1540         memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
1541         bat_priv->bla.claim_dest.type = 0;
1542         primary_if = batadv_primary_if_get_selected(bat_priv);
1543         if (primary_if) {
1544                 crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
1545                 bat_priv->bla.claim_dest.group = htons(crc);
1546                 batadv_hardif_put(primary_if);
1547         } else {
1548                 bat_priv->bla.claim_dest.group = 0; /* will be set later */
1549         }
1550 
1551         /* initialize the duplicate list */
1552         entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
1553         for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
1554                 bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
1555         bat_priv->bla.bcast_duplist_curr = 0;
1556 
1557         atomic_set(&bat_priv->bla.loopdetect_next,
1558                    BATADV_BLA_LOOPDETECT_PERIODS);
1559 
1560         if (bat_priv->bla.claim_hash)
1561                 return 0;
1562 
1563         bat_priv->bla.claim_hash = batadv_hash_new(128);
1564         if (!bat_priv->bla.claim_hash)
1565                 return -ENOMEM;
1566 
1567         bat_priv->bla.backbone_hash = batadv_hash_new(32);
1568         if (!bat_priv->bla.backbone_hash) {
1569                 batadv_hash_destroy(bat_priv->bla.claim_hash);
1570                 return -ENOMEM;
1571         }
1572 
1573         batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
1574                                    &batadv_claim_hash_lock_class_key);
1575         batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
1576                                    &batadv_backbone_hash_lock_class_key);
1577 
1578         batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
1579 
1580         INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
1581 
1582         queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1583                            msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
1584         return 0;
1585 }
1586 
1587 /**
1588  * batadv_bla_check_duplist() - Check if a frame is in the broadcast dup.
1589  * @bat_priv: the bat priv with all the soft interface information
1590  * @skb: contains the multicast packet to be checked
1591  * @payload_ptr: pointer to position inside the head buffer of the skb
1592  *  marking the start of the data to be CRC'ed
1593  * @orig: originator mac address, NULL if unknown
1594  *
1595  * Check if it is on our broadcast list. Another gateway might have sent the
1596  * same packet because it is connected to the same backbone, so we have to
1597  * remove this duplicate.
1598  *
1599  * This is performed by checking the CRC, which will tell us
1600  * with a good chance that it is the same packet. If it is furthermore
1601  * sent by another host, drop it. We allow equal packets from
1602  * the same host however as this might be intended.
1603  *
1604  * Return: true if a packet is in the duplicate list, false otherwise.
1605  */
1606 static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
1607                                      struct sk_buff *skb, u8 *payload_ptr,
1608                                      const u8 *orig)
1609 {
1610         struct batadv_bcast_duplist_entry *entry;
1611         bool ret = false;
1612         int i, curr;
1613         __be32 crc;
1614 
1615         /* calculate the crc ... */
1616         crc = batadv_skb_crc32(skb, payload_ptr);
1617 
1618         spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
1619 
1620         for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
1621                 curr = (bat_priv->bla.bcast_duplist_curr + i);
1622                 curr %= BATADV_DUPLIST_SIZE;
1623                 entry = &bat_priv->bla.bcast_duplist[curr];
1624 
1625                 /* we can stop searching if the entry is too old ;
1626                  * later entries will be even older
1627                  */
1628                 if (batadv_has_timed_out(entry->entrytime,
1629                                          BATADV_DUPLIST_TIMEOUT))
1630                         break;
1631 
1632                 if (entry->crc != crc)
1633                         continue;
1634 
1635                 /* are the originators both known and not anonymous? */
1636                 if (orig && !is_zero_ether_addr(orig) &&
1637                     !is_zero_ether_addr(entry->orig)) {
1638                         /* If known, check if the new frame came from
1639                          * the same originator:
1640                          * We are safe to take identical frames from the
1641                          * same orig, if known, as multiplications in
1642                          * the mesh are detected via the (orig, seqno) pair.
1643                          * So we can be a bit more liberal here and allow
1644                          * identical frames from the same orig which the source
1645                          * host might have sent multiple times on purpose.
1646                          */
1647                         if (batadv_compare_eth(entry->orig, orig))
1648                                 continue;
1649                 }
1650 
1651                 /* this entry seems to match: same crc, not too old,
1652                  * and from another gw. therefore return true to forbid it.
1653                  */
1654                 ret = true;
1655                 goto out;
1656         }
1657         /* not found, add a new entry (overwrite the oldest entry)
1658          * and allow it, its the first occurrence.
1659          */
1660         curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
1661         curr %= BATADV_DUPLIST_SIZE;
1662         entry = &bat_priv->bla.bcast_duplist[curr];
1663         entry->crc = crc;
1664         entry->entrytime = jiffies;
1665 
1666         /* known originator */
1667         if (orig)
1668                 ether_addr_copy(entry->orig, orig);
1669         /* anonymous originator */
1670         else
1671                 eth_zero_addr(entry->orig);
1672 
1673         bat_priv->bla.bcast_duplist_curr = curr;
1674 
1675 out:
1676         spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
1677 
1678         return ret;
1679 }
1680 
1681 /**
1682  * batadv_bla_check_ucast_duplist() - Check if a frame is in the broadcast dup.
1683  * @bat_priv: the bat priv with all the soft interface information
1684  * @skb: contains the multicast packet to be checked, decapsulated from a
1685  *  unicast_packet
1686  *
1687  * Check if it is on our broadcast list. Another gateway might have sent the
1688  * same packet because it is connected to the same backbone, so we have to
1689  * remove this duplicate.
1690  *
1691  * Return: true if a packet is in the duplicate list, false otherwise.
1692  */
1693 static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv,
1694                                            struct sk_buff *skb)
1695 {
1696         return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL);
1697 }
1698 
1699 /**
1700  * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
1701  * @bat_priv: the bat priv with all the soft interface information
1702  * @skb: contains the bcast_packet to be checked
1703  *
1704  * Check if it is on our broadcast list. Another gateway might have sent the
1705  * same packet because it is connected to the same backbone, so we have to
1706  * remove this duplicate.
1707  *
1708  * Return: true if a packet is in the duplicate list, false otherwise.
1709  */
1710 bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
1711                                     struct sk_buff *skb)
1712 {
1713         struct batadv_bcast_packet *bcast_packet;
1714         u8 *payload_ptr;
1715 
1716         bcast_packet = (struct batadv_bcast_packet *)skb->data;
1717         payload_ptr = (u8 *)(bcast_packet + 1);
1718 
1719         return batadv_bla_check_duplist(bat_priv, skb, payload_ptr,
1720                                         bcast_packet->orig);
1721 }
1722 
1723 /**
1724  * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
1725  *  the VLAN identified by vid.
1726  * @bat_priv: the bat priv with all the soft interface information
1727  * @orig: originator mac address
1728  * @vid: VLAN identifier
1729  *
1730  * Return: true if orig is a backbone for this vid, false otherwise.
1731  */
1732 bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
1733                                     unsigned short vid)
1734 {
1735         struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
1736         struct hlist_head *head;
1737         struct batadv_bla_backbone_gw *backbone_gw;
1738         int i;
1739 
1740         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1741                 return false;
1742 
1743         if (!hash)
1744                 return false;
1745 
1746         for (i = 0; i < hash->size; i++) {
1747                 head = &hash->table[i];
1748 
1749                 rcu_read_lock();
1750                 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1751                         if (batadv_compare_eth(backbone_gw->orig, orig) &&
1752                             backbone_gw->vid == vid) {
1753                                 rcu_read_unlock();
1754                                 return true;
1755                         }
1756                 }
1757                 rcu_read_unlock();
1758         }
1759 
1760         return false;
1761 }
1762 
1763 /**
1764  * batadv_bla_is_backbone_gw() - check if originator is a backbone gw for a VLAN
1765  * @skb: the frame to be checked
1766  * @orig_node: the orig_node of the frame
1767  * @hdr_size: maximum length of the frame
1768  *
1769  * Return: true if the orig_node is also a gateway on the soft interface,
1770  * otherwise it returns false.
1771  */
1772 bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
1773                                struct batadv_orig_node *orig_node, int hdr_size)
1774 {
1775         struct batadv_bla_backbone_gw *backbone_gw;
1776         unsigned short vid;
1777 
1778         if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
1779                 return false;
1780 
1781         /* first, find out the vid. */
1782         if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1783                 return false;
1784 
1785         vid = batadv_get_vid(skb, hdr_size);
1786 
1787         /* see if this originator is a backbone gw for this VLAN */
1788         backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
1789                                                 orig_node->orig, vid);
1790         if (!backbone_gw)
1791                 return false;
1792 
1793         batadv_backbone_gw_put(backbone_gw);
1794         return true;
1795 }
1796 
1797 /**
1798  * batadv_bla_free() - free all bla structures
1799  * @bat_priv: the bat priv with all the soft interface information
1800  *
1801  * for softinterface free or module unload
1802  */
1803 void batadv_bla_free(struct batadv_priv *bat_priv)
1804 {
1805         struct batadv_hard_iface *primary_if;
1806 
1807         cancel_delayed_work_sync(&bat_priv->bla.work);
1808         primary_if = batadv_primary_if_get_selected(bat_priv);
1809 
1810         if (bat_priv->bla.claim_hash) {
1811                 batadv_bla_purge_claims(bat_priv, primary_if, 1);
1812                 batadv_hash_destroy(bat_priv->bla.claim_hash);
1813                 bat_priv->bla.claim_hash = NULL;
1814         }
1815         if (bat_priv->bla.backbone_hash) {
1816                 batadv_bla_purge_backbone_gw(bat_priv, 1);
1817                 batadv_hash_destroy(bat_priv->bla.backbone_hash);
1818                 bat_priv->bla.backbone_hash = NULL;
1819         }
1820         batadv_hardif_put(primary_if);
1821 }
1822 
1823 /**
1824  * batadv_bla_loopdetect_check() - check and handle a detected loop
1825  * @bat_priv: the bat priv with all the soft interface information
1826  * @skb: the packet to check
1827  * @primary_if: interface where the request came on
1828  * @vid: the VLAN ID of the frame
1829  *
1830  * Checks if this packet is a loop detect frame which has been sent by us,
1831  * throws an uevent and logs the event if that is the case.
1832  *
1833  * Return: true if it is a loop detect frame which is to be dropped, false
1834  * otherwise.
1835  */
1836 static bool
1837 batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
1838                             struct batadv_hard_iface *primary_if,
1839                             unsigned short vid)
1840 {
1841         struct batadv_bla_backbone_gw *backbone_gw;
1842         struct ethhdr *ethhdr;
1843         bool ret;
1844 
1845         ethhdr = eth_hdr(skb);
1846 
1847         /* Only check for the MAC address and skip more checks here for
1848          * performance reasons - this function is on the hotpath, after all.
1849          */
1850         if (!batadv_compare_eth(ethhdr->h_source,
1851                                 bat_priv->bla.loopdetect_addr))
1852                 return false;
1853 
1854         /* If the packet came too late, don't forward it on the mesh
1855          * but don't consider that as loop. It might be a coincidence.
1856          */
1857         if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
1858                                  BATADV_BLA_LOOPDETECT_TIMEOUT))
1859                 return true;
1860 
1861         backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
1862                                                  primary_if->net_dev->dev_addr,
1863                                                  vid, true);
1864         if (unlikely(!backbone_gw))
1865                 return true;
1866 
1867         ret = queue_work(batadv_event_workqueue, &backbone_gw->report_work);
1868 
1869         /* backbone_gw is unreferenced in the report work function
1870          * if queue_work() call was successful
1871          */
1872         if (!ret)
1873                 batadv_backbone_gw_put(backbone_gw);
1874 
1875         return true;
1876 }
1877 
1878 /**
1879  * batadv_bla_rx() - check packets coming from the mesh.
1880  * @bat_priv: the bat priv with all the soft interface information
1881  * @skb: the frame to be checked
1882  * @vid: the VLAN ID of the frame
1883  * @packet_type: the batman packet type this frame came in
1884  *
1885  * batadv_bla_rx avoidance checks if:
1886  *  * we have to race for a claim
1887  *  * if the frame is allowed on the LAN
1888  *
1889  * In these cases, the skb is further handled by this function
1890  *
1891  * Return: true if handled, otherwise it returns false and the caller shall
1892  * further process the skb.
1893  */
1894 bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
1895                    unsigned short vid, int packet_type)
1896 {
1897         struct batadv_bla_backbone_gw *backbone_gw;
1898         struct ethhdr *ethhdr;
1899         struct batadv_bla_claim search_claim, *claim = NULL;
1900         struct batadv_hard_iface *primary_if;
1901         bool own_claim;
1902         bool ret;
1903 
1904         ethhdr = eth_hdr(skb);
1905 
1906         primary_if = batadv_primary_if_get_selected(bat_priv);
1907         if (!primary_if)
1908                 goto handled;
1909 
1910         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1911                 goto allow;
1912 
1913         if (batadv_bla_loopdetect_check(bat_priv, skb, primary_if, vid))
1914                 goto handled;
1915 
1916         if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1917                 /* don't allow multicast packets while requests are in flight */
1918                 if (is_multicast_ether_addr(ethhdr->h_dest))
1919                         /* Both broadcast flooding or multicast-via-unicasts
1920                          * delivery might send to multiple backbone gateways
1921                          * sharing the same LAN and therefore need to coordinate
1922                          * which backbone gateway forwards into the LAN,
1923                          * by claiming the payload source address.
1924                          *
1925                          * Broadcast flooding and multicast-via-unicasts
1926                          * delivery use the following two batman packet types.
1927                          * Note: explicitly exclude BATADV_UNICAST_4ADDR,
1928                          * as the DHCP gateway feature will send explicitly
1929                          * to only one BLA gateway, so the claiming process
1930                          * should be avoided there.
1931                          */
1932                         if (packet_type == BATADV_BCAST ||
1933                             packet_type == BATADV_UNICAST)
1934                                 goto handled;
1935 
1936         /* potential duplicates from foreign BLA backbone gateways via
1937          * multicast-in-unicast packets
1938          */
1939         if (is_multicast_ether_addr(ethhdr->h_dest) &&
1940             packet_type == BATADV_UNICAST &&
1941             batadv_bla_check_ucast_duplist(bat_priv, skb))
1942                 goto handled;
1943 
1944         ether_addr_copy(search_claim.addr, ethhdr->h_source);
1945         search_claim.vid = vid;
1946         claim = batadv_claim_hash_find(bat_priv, &search_claim);
1947 
1948         if (!claim) {
1949                 /* possible optimization: race for a claim */
1950                 /* No claim exists yet, claim it for us!
1951                  */
1952 
1953                 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1954                            "%s(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
1955                            __func__, ethhdr->h_source,
1956                            batadv_is_my_client(bat_priv,
1957                                                ethhdr->h_source, vid) ?
1958                            "yes" : "no");
1959                 batadv_handle_claim(bat_priv, primary_if,
1960                                     primary_if->net_dev->dev_addr,
1961                                     ethhdr->h_source, vid);
1962                 goto allow;
1963         }
1964 
1965         /* if it is our own claim ... */
1966         backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
1967         own_claim = batadv_compare_eth(backbone_gw->orig,
1968                                        primary_if->net_dev->dev_addr);
1969         batadv_backbone_gw_put(backbone_gw);
1970 
1971         if (own_claim) {
1972                 /* ... allow it in any case */
1973                 claim->lasttime = jiffies;
1974                 goto allow;
1975         }
1976 
1977         /* if it is a multicast ... */
1978         if (is_multicast_ether_addr(ethhdr->h_dest) &&
1979             (packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) {
1980                 /* ... drop it. the responsible gateway is in charge.
1981                  *
1982                  * We need to check packet type because with the gateway
1983                  * feature, broadcasts (like DHCP requests) may be sent
1984                  * using a unicast 4 address packet type. See comment above.
1985                  */
1986                 goto handled;
1987         } else {
1988                 /* seems the client considers us as its best gateway.
1989                  * send a claim and update the claim table
1990                  * immediately.
1991                  */
1992                 batadv_handle_claim(bat_priv, primary_if,
1993                                     primary_if->net_dev->dev_addr,
1994                                     ethhdr->h_source, vid);
1995                 goto allow;
1996         }
1997 allow:
1998         batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1999         ret = false;
2000         goto out;
2001 
2002 handled:
2003         kfree_skb(skb);
2004         ret = true;
2005 
2006 out:
2007         batadv_hardif_put(primary_if);
2008         batadv_claim_put(claim);
2009         return ret;
2010 }
2011 
2012 /**
2013  * batadv_bla_tx() - check packets going into the mesh
2014  * @bat_priv: the bat priv with all the soft interface information
2015  * @skb: the frame to be checked
2016  * @vid: the VLAN ID of the frame
2017  *
2018  * batadv_bla_tx checks if:
2019  *  * a claim was received which has to be processed
2020  *  * the frame is allowed on the mesh
2021  *
2022  * in these cases, the skb is further handled by this function.
2023  *
2024  * This call might reallocate skb data.
2025  *
2026  * Return: true if handled, otherwise it returns false and the caller shall
2027  * further process the skb.
2028  */
2029 bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
2030                    unsigned short vid)
2031 {
2032         struct ethhdr *ethhdr;
2033         struct batadv_bla_claim search_claim, *claim = NULL;
2034         struct batadv_bla_backbone_gw *backbone_gw;
2035         struct batadv_hard_iface *primary_if;
2036         bool client_roamed;
2037         bool ret = false;
2038 
2039         primary_if = batadv_primary_if_get_selected(bat_priv);
2040         if (!primary_if)
2041                 goto out;
2042 
2043         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
2044                 goto allow;
2045 
2046         if (batadv_bla_process_claim(bat_priv, primary_if, skb))
2047                 goto handled;
2048 
2049         ethhdr = eth_hdr(skb);
2050 
2051         if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
2052                 /* don't allow broadcasts while requests are in flight */
2053                 if (is_multicast_ether_addr(ethhdr->h_dest))
2054                         goto handled;
2055 
2056         ether_addr_copy(search_claim.addr, ethhdr->h_source);
2057         search_claim.vid = vid;
2058 
2059         claim = batadv_claim_hash_find(bat_priv, &search_claim);
2060 
2061         /* if no claim exists, allow it. */
2062         if (!claim)
2063                 goto allow;
2064 
2065         /* check if we are responsible. */
2066         backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
2067         client_roamed = batadv_compare_eth(backbone_gw->orig,
2068                                            primary_if->net_dev->dev_addr);
2069         batadv_backbone_gw_put(backbone_gw);
2070 
2071         if (client_roamed) {
2072                 /* if yes, the client has roamed and we have
2073                  * to unclaim it.
2074                  */
2075                 if (batadv_has_timed_out(claim->lasttime, 100)) {
2076                         /* only unclaim if the last claim entry is
2077                          * older than 100 ms to make sure we really
2078                          * have a roaming client here.
2079                          */
2080                         batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Roaming client %pM detected. Unclaim it.\n",
2081                                    __func__, ethhdr->h_source);
2082                         batadv_handle_unclaim(bat_priv, primary_if,
2083                                               primary_if->net_dev->dev_addr,
2084                                               ethhdr->h_source, vid);
2085                         goto allow;
2086                 } else {
2087                         batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Race for claim %pM detected. Drop packet.\n",
2088                                    __func__, ethhdr->h_source);
2089                         goto handled;
2090                 }
2091         }
2092 
2093         /* check if it is a multicast/broadcast frame */
2094         if (is_multicast_ether_addr(ethhdr->h_dest)) {
2095                 /* drop it. the responsible gateway has forwarded it into
2096                  * the backbone network.
2097                  */
2098                 goto handled;
2099         } else {
2100                 /* we must allow it. at least if we are
2101                  * responsible for the DESTINATION.
2102                  */
2103                 goto allow;
2104         }
2105 allow:
2106         batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
2107         ret = false;
2108         goto out;
2109 handled:
2110         ret = true;
2111 out:
2112         batadv_hardif_put(primary_if);
2113         batadv_claim_put(claim);
2114         return ret;
2115 }
2116 
2117 /**
2118  * batadv_bla_claim_dump_entry() - dump one entry of the claim table
2119  * to a netlink socket
2120  * @msg: buffer for the message
2121  * @portid: netlink port
2122  * @cb: Control block containing additional options
2123  * @primary_if: primary interface
2124  * @claim: entry to dump
2125  *
2126  * Return: 0 or error code.
2127  */
2128 static int
2129 batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
2130                             struct netlink_callback *cb,
2131                             struct batadv_hard_iface *primary_if,
2132                             struct batadv_bla_claim *claim)
2133 {
2134         const u8 *primary_addr = primary_if->net_dev->dev_addr;
2135         u16 backbone_crc;
2136         bool is_own;
2137         void *hdr;
2138         int ret = -EINVAL;
2139 
2140         hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2141                           &batadv_netlink_family, NLM_F_MULTI,
2142                           BATADV_CMD_GET_BLA_CLAIM);
2143         if (!hdr) {
2144                 ret = -ENOBUFS;
2145                 goto out;
2146         }
2147 
2148         genl_dump_check_consistent(cb, hdr);
2149 
2150         is_own = batadv_compare_eth(claim->backbone_gw->orig,
2151                                     primary_addr);
2152 
2153         spin_lock_bh(&claim->backbone_gw->crc_lock);
2154         backbone_crc = claim->backbone_gw->crc;
2155         spin_unlock_bh(&claim->backbone_gw->crc_lock);
2156 
2157         if (is_own)
2158                 if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
2159                         genlmsg_cancel(msg, hdr);
2160                         goto out;
2161                 }
2162 
2163         if (nla_put(msg, BATADV_ATTR_BLA_ADDRESS, ETH_ALEN, claim->addr) ||
2164             nla_put_u16(msg, BATADV_ATTR_BLA_VID, claim->vid) ||
2165             nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
2166                     claim->backbone_gw->orig) ||
2167             nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2168                         backbone_crc)) {
2169                 genlmsg_cancel(msg, hdr);
2170                 goto out;
2171         }
2172 
2173         genlmsg_end(msg, hdr);
2174         ret = 0;
2175 
2176 out:
2177         return ret;
2178 }
2179 
2180 /**
2181  * batadv_bla_claim_dump_bucket() - dump one bucket of the claim table
2182  * to a netlink socket
2183  * @msg: buffer for the message
2184  * @portid: netlink port
2185  * @cb: Control block containing additional options
2186  * @primary_if: primary interface
2187  * @hash: hash to dump
2188  * @bucket: bucket index to dump
2189  * @idx_skip: How many entries to skip
2190  *
2191  * Return: always 0.
2192  */
2193 static int
2194 batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid,
2195                              struct netlink_callback *cb,
2196                              struct batadv_hard_iface *primary_if,
2197                              struct batadv_hashtable *hash, unsigned int bucket,
2198                              int *idx_skip)
2199 {
2200         struct batadv_bla_claim *claim;
2201         int idx = 0;
2202         int ret = 0;
2203 
2204         spin_lock_bh(&hash->list_locks[bucket]);
2205         cb->seq = atomic_read(&hash->generation) << 1 | 1;
2206 
2207         hlist_for_each_entry(claim, &hash->table[bucket], hash_entry) {
2208                 if (idx++ < *idx_skip)
2209                         continue;
2210 
2211                 ret = batadv_bla_claim_dump_entry(msg, portid, cb,
2212                                                   primary_if, claim);
2213                 if (ret) {
2214                         *idx_skip = idx - 1;
2215                         goto unlock;
2216                 }
2217         }
2218 
2219         *idx_skip = 0;
2220 unlock:
2221         spin_unlock_bh(&hash->list_locks[bucket]);
2222         return ret;
2223 }
2224 
2225 /**
2226  * batadv_bla_claim_dump() - dump claim table to a netlink socket
2227  * @msg: buffer for the message
2228  * @cb: callback structure containing arguments
2229  *
2230  * Return: message length.
2231  */
2232 int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
2233 {
2234         struct batadv_hard_iface *primary_if = NULL;
2235         int portid = NETLINK_CB(cb->skb).portid;
2236         struct net *net = sock_net(cb->skb->sk);
2237         struct net_device *soft_iface;
2238         struct batadv_hashtable *hash;
2239         struct batadv_priv *bat_priv;
2240         int bucket = cb->args[0];
2241         int idx = cb->args[1];
2242         int ifindex;
2243         int ret = 0;
2244 
2245         ifindex = batadv_netlink_get_ifindex(cb->nlh,
2246                                              BATADV_ATTR_MESH_IFINDEX);
2247         if (!ifindex)
2248                 return -EINVAL;
2249 
2250         soft_iface = dev_get_by_index(net, ifindex);
2251         if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2252                 ret = -ENODEV;
2253                 goto out;
2254         }
2255 
2256         bat_priv = netdev_priv(soft_iface);
2257         hash = bat_priv->bla.claim_hash;
2258 
2259         primary_if = batadv_primary_if_get_selected(bat_priv);
2260         if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2261                 ret = -ENOENT;
2262                 goto out;
2263         }
2264 
2265         while (bucket < hash->size) {
2266                 if (batadv_bla_claim_dump_bucket(msg, portid, cb, primary_if,
2267                                                  hash, bucket, &idx))
2268                         break;
2269                 bucket++;
2270         }
2271 
2272         cb->args[0] = bucket;
2273         cb->args[1] = idx;
2274 
2275         ret = msg->len;
2276 
2277 out:
2278         batadv_hardif_put(primary_if);
2279 
2280         dev_put(soft_iface);
2281 
2282         return ret;
2283 }
2284 
2285 /**
2286  * batadv_bla_backbone_dump_entry() - dump one entry of the backbone table to a
2287  *  netlink socket
2288  * @msg: buffer for the message
2289  * @portid: netlink port
2290  * @cb: Control block containing additional options
2291  * @primary_if: primary interface
2292  * @backbone_gw: entry to dump
2293  *
2294  * Return: 0 or error code.
2295  */
2296 static int
2297 batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid,
2298                                struct netlink_callback *cb,
2299                                struct batadv_hard_iface *primary_if,
2300                                struct batadv_bla_backbone_gw *backbone_gw)
2301 {
2302         const u8 *primary_addr = primary_if->net_dev->dev_addr;
2303         u16 backbone_crc;
2304         bool is_own;
2305         int msecs;
2306         void *hdr;
2307         int ret = -EINVAL;
2308 
2309         hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2310                           &batadv_netlink_family, NLM_F_MULTI,
2311                           BATADV_CMD_GET_BLA_BACKBONE);
2312         if (!hdr) {
2313                 ret = -ENOBUFS;
2314                 goto out;
2315         }
2316 
2317         genl_dump_check_consistent(cb, hdr);
2318 
2319         is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
2320 
2321         spin_lock_bh(&backbone_gw->crc_lock);
2322         backbone_crc = backbone_gw->crc;
2323         spin_unlock_bh(&backbone_gw->crc_lock);
2324 
2325         msecs = jiffies_to_msecs(jiffies - backbone_gw->lasttime);
2326 
2327         if (is_own)
2328                 if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
2329                         genlmsg_cancel(msg, hdr);
2330                         goto out;
2331                 }
2332 
2333         if (nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
2334                     backbone_gw->orig) ||
2335             nla_put_u16(msg, BATADV_ATTR_BLA_VID, backbone_gw->vid) ||
2336             nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2337                         backbone_crc) ||
2338             nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, msecs)) {
2339                 genlmsg_cancel(msg, hdr);
2340                 goto out;
2341         }
2342 
2343         genlmsg_end(msg, hdr);
2344         ret = 0;
2345 
2346 out:
2347         return ret;
2348 }
2349 
2350 /**
2351  * batadv_bla_backbone_dump_bucket() - dump one bucket of the backbone table to
2352  *  a netlink socket
2353  * @msg: buffer for the message
2354  * @portid: netlink port
2355  * @cb: Control block containing additional options
2356  * @primary_if: primary interface
2357  * @hash: hash to dump
2358  * @bucket: bucket index to dump
2359  * @idx_skip: How many entries to skip
2360  *
2361  * Return: always 0.
2362  */
2363 static int
2364 batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid,
2365                                 struct netlink_callback *cb,
2366                                 struct batadv_hard_iface *primary_if,
2367                                 struct batadv_hashtable *hash,
2368                                 unsigned int bucket, int *idx_skip)
2369 {
2370         struct batadv_bla_backbone_gw *backbone_gw;
2371         int idx = 0;
2372         int ret = 0;
2373 
2374         spin_lock_bh(&hash->list_locks[bucket]);
2375         cb->seq = atomic_read(&hash->generation) << 1 | 1;
2376 
2377         hlist_for_each_entry(backbone_gw, &hash->table[bucket], hash_entry) {
2378                 if (idx++ < *idx_skip)
2379                         continue;
2380 
2381                 ret = batadv_bla_backbone_dump_entry(msg, portid, cb,
2382                                                      primary_if, backbone_gw);
2383                 if (ret) {
2384                         *idx_skip = idx - 1;
2385                         goto unlock;
2386                 }
2387         }
2388 
2389         *idx_skip = 0;
2390 unlock:
2391         spin_unlock_bh(&hash->list_locks[bucket]);
2392         return ret;
2393 }
2394 
2395 /**
2396  * batadv_bla_backbone_dump() - dump backbone table to a netlink socket
2397  * @msg: buffer for the message
2398  * @cb: callback structure containing arguments
2399  *
2400  * Return: message length.
2401  */
2402 int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
2403 {
2404         struct batadv_hard_iface *primary_if = NULL;
2405         int portid = NETLINK_CB(cb->skb).portid;
2406         struct net *net = sock_net(cb->skb->sk);
2407         struct net_device *soft_iface;
2408         struct batadv_hashtable *hash;
2409         struct batadv_priv *bat_priv;
2410         int bucket = cb->args[0];
2411         int idx = cb->args[1];
2412         int ifindex;
2413         int ret = 0;
2414 
2415         ifindex = batadv_netlink_get_ifindex(cb->nlh,
2416                                              BATADV_ATTR_MESH_IFINDEX);
2417         if (!ifindex)
2418                 return -EINVAL;
2419 
2420         soft_iface = dev_get_by_index(net, ifindex);
2421         if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2422                 ret = -ENODEV;
2423                 goto out;
2424         }
2425 
2426         bat_priv = netdev_priv(soft_iface);
2427         hash = bat_priv->bla.backbone_hash;
2428 
2429         primary_if = batadv_primary_if_get_selected(bat_priv);
2430         if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2431                 ret = -ENOENT;
2432                 goto out;
2433         }
2434 
2435         while (bucket < hash->size) {
2436                 if (batadv_bla_backbone_dump_bucket(msg, portid, cb, primary_if,
2437                                                     hash, bucket, &idx))
2438                         break;
2439                 bucket++;
2440         }
2441 
2442         cb->args[0] = bucket;
2443         cb->args[1] = idx;
2444 
2445         ret = msg->len;
2446 
2447 out:
2448         batadv_hardif_put(primary_if);
2449 
2450         dev_put(soft_iface);
2451 
2452         return ret;
2453 }
2454 
2455 #ifdef CONFIG_BATMAN_ADV_DAT
2456 /**
2457  * batadv_bla_check_claim() - check if address is claimed
2458  *
2459  * @bat_priv: the bat priv with all the soft interface information
2460  * @addr: mac address of which the claim status is checked
2461  * @vid: the VLAN ID
2462  *
2463  * addr is checked if this address is claimed by the local device itself.
2464  *
2465  * Return: true if bla is disabled or the mac is claimed by the device,
2466  * false if the device addr is already claimed by another gateway
2467  */
2468 bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
2469                             u8 *addr, unsigned short vid)
2470 {
2471         struct batadv_bla_claim search_claim;
2472         struct batadv_bla_claim *claim = NULL;
2473         struct batadv_hard_iface *primary_if = NULL;
2474         bool ret = true;
2475 
2476         if (!atomic_read(&bat_priv->bridge_loop_avoidance))
2477                 return ret;
2478 
2479         primary_if = batadv_primary_if_get_selected(bat_priv);
2480         if (!primary_if)
2481                 return ret;
2482 
2483         /* First look if the mac address is claimed */
2484         ether_addr_copy(search_claim.addr, addr);
2485         search_claim.vid = vid;
2486 
2487         claim = batadv_claim_hash_find(bat_priv, &search_claim);
2488 
2489         /* If there is a claim and we are not owner of the claim,
2490          * return false.
2491          */
2492         if (claim) {
2493                 if (!batadv_compare_eth(claim->backbone_gw->orig,
2494                                         primary_if->net_dev->dev_addr))
2495                         ret = false;
2496                 batadv_claim_put(claim);
2497         }
2498 
2499         batadv_hardif_put(primary_if);
2500         return ret;
2501 }
2502 #endif
2503 

~ [ 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