linux/net/batman-adv/bridge_loop_avoidance.c
<<
>>
Prefs
   1/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
   2 *
   3 * Simon Wunderlich
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of version 2 of the GNU General Public
   7 * License as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but
  10 * WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 * General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17 * 02110-1301, USA
  18 */
  19
  20#include "main.h"
  21#include "hash.h"
  22#include "hard-interface.h"
  23#include "originator.h"
  24#include "bridge_loop_avoidance.h"
  25#include "translation-table.h"
  26#include "send.h"
  27
  28#include <linux/etherdevice.h>
  29#include <linux/crc16.h>
  30#include <linux/if_arp.h>
  31#include <net/arp.h>
  32#include <linux/if_vlan.h>
  33
  34static const uint8_t batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
  35
  36static void batadv_bla_periodic_work(struct work_struct *work);
  37static void
  38batadv_bla_send_announce(struct batadv_priv *bat_priv,
  39                         struct batadv_bla_backbone_gw *backbone_gw);
  40
  41/* return the index of the claim */
  42static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
  43{
  44        struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data;
  45        uint32_t hash = 0;
  46
  47        hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
  48        hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
  49
  50        hash += (hash << 3);
  51        hash ^= (hash >> 11);
  52        hash += (hash << 15);
  53
  54        return hash % size;
  55}
  56
  57/* return the index of the backbone gateway */
  58static inline uint32_t batadv_choose_backbone_gw(const void *data,
  59                                                 uint32_t size)
  60{
  61        const struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data;
  62        uint32_t hash = 0;
  63
  64        hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
  65        hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
  66
  67        hash += (hash << 3);
  68        hash ^= (hash >> 11);
  69        hash += (hash << 15);
  70
  71        return hash % size;
  72}
  73
  74
  75/* compares address and vid of two backbone gws */
  76static int batadv_compare_backbone_gw(const struct hlist_node *node,
  77                                      const void *data2)
  78{
  79        const void *data1 = container_of(node, struct batadv_bla_backbone_gw,
  80                                         hash_entry);
  81        const struct batadv_bla_backbone_gw *gw1 = data1, *gw2 = data2;
  82
  83        if (!batadv_compare_eth(gw1->orig, gw2->orig))
  84                return 0;
  85
  86        if (gw1->vid != gw2->vid)
  87                return 0;
  88
  89        return 1;
  90}
  91
  92/* compares address and vid of two claims */
  93static int batadv_compare_claim(const struct hlist_node *node,
  94                                const void *data2)
  95{
  96        const void *data1 = container_of(node, struct batadv_bla_claim,
  97                                         hash_entry);
  98        const struct batadv_bla_claim *cl1 = data1, *cl2 = data2;
  99
 100        if (!batadv_compare_eth(cl1->addr, cl2->addr))
 101                return 0;
 102
 103        if (cl1->vid != cl2->vid)
 104                return 0;
 105
 106        return 1;
 107}
 108
 109/* free a backbone gw */
 110static void
 111batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw)
 112{
 113        if (atomic_dec_and_test(&backbone_gw->refcount))
 114                kfree_rcu(backbone_gw, rcu);
 115}
 116
 117/* finally deinitialize the claim */
 118static void batadv_claim_free_rcu(struct rcu_head *rcu)
 119{
 120        struct batadv_bla_claim *claim;
 121
 122        claim = container_of(rcu, struct batadv_bla_claim, rcu);
 123
 124        batadv_backbone_gw_free_ref(claim->backbone_gw);
 125        kfree(claim);
 126}
 127
 128/* free a claim, call claim_free_rcu if its the last reference */
 129static void batadv_claim_free_ref(struct batadv_bla_claim *claim)
 130{
 131        if (atomic_dec_and_test(&claim->refcount))
 132                call_rcu(&claim->rcu, batadv_claim_free_rcu);
 133}
 134
 135/* @bat_priv: the bat priv with all the soft interface information
 136 * @data: search data (may be local/static data)
 137 *
 138 * looks for a claim in the hash, and returns it if found
 139 * or NULL otherwise.
 140 */
 141static struct batadv_bla_claim
 142*batadv_claim_hash_find(struct batadv_priv *bat_priv,
 143                        struct batadv_bla_claim *data)
 144{
 145        struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
 146        struct hlist_head *head;
 147        struct batadv_bla_claim *claim;
 148        struct batadv_bla_claim *claim_tmp = NULL;
 149        int index;
 150
 151        if (!hash)
 152                return NULL;
 153
 154        index = batadv_choose_claim(data, hash->size);
 155        head = &hash->table[index];
 156
 157        rcu_read_lock();
 158        hlist_for_each_entry_rcu(claim, head, hash_entry) {
 159                if (!batadv_compare_claim(&claim->hash_entry, data))
 160                        continue;
 161
 162                if (!atomic_inc_not_zero(&claim->refcount))
 163                        continue;
 164
 165                claim_tmp = claim;
 166                break;
 167        }
 168        rcu_read_unlock();
 169
 170        return claim_tmp;
 171}
 172
 173/**
 174 * batadv_backbone_hash_find - looks for a claim in the hash
 175 * @bat_priv: the bat priv with all the soft interface information
 176 * @addr: the address of the originator
 177 * @vid: the VLAN ID
 178 *
 179 * Returns claim if found or NULL otherwise.
 180 */
 181static struct batadv_bla_backbone_gw *
 182batadv_backbone_hash_find(struct batadv_priv *bat_priv,
 183                          uint8_t *addr, unsigned short vid)
 184{
 185        struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 186        struct hlist_head *head;
 187        struct batadv_bla_backbone_gw search_entry, *backbone_gw;
 188        struct batadv_bla_backbone_gw *backbone_gw_tmp = NULL;
 189        int index;
 190
 191        if (!hash)
 192                return NULL;
 193
 194        memcpy(search_entry.orig, addr, ETH_ALEN);
 195        search_entry.vid = vid;
 196
 197        index = batadv_choose_backbone_gw(&search_entry, hash->size);
 198        head = &hash->table[index];
 199
 200        rcu_read_lock();
 201        hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
 202                if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
 203                                                &search_entry))
 204                        continue;
 205
 206                if (!atomic_inc_not_zero(&backbone_gw->refcount))
 207                        continue;
 208
 209                backbone_gw_tmp = backbone_gw;
 210                break;
 211        }
 212        rcu_read_unlock();
 213
 214        return backbone_gw_tmp;
 215}
 216
 217/* delete all claims for a backbone */
 218static void
 219batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
 220{
 221        struct batadv_hashtable *hash;
 222        struct hlist_node *node_tmp;
 223        struct hlist_head *head;
 224        struct batadv_bla_claim *claim;
 225        int i;
 226        spinlock_t *list_lock;  /* protects write access to the hash lists */
 227
 228        hash = backbone_gw->bat_priv->bla.claim_hash;
 229        if (!hash)
 230                return;
 231
 232        for (i = 0; i < hash->size; i++) {
 233                head = &hash->table[i];
 234                list_lock = &hash->list_locks[i];
 235
 236                spin_lock_bh(list_lock);
 237                hlist_for_each_entry_safe(claim, node_tmp,
 238                                          head, hash_entry) {
 239                        if (claim->backbone_gw != backbone_gw)
 240                                continue;
 241
 242                        batadv_claim_free_ref(claim);
 243                        hlist_del_rcu(&claim->hash_entry);
 244                }
 245                spin_unlock_bh(list_lock);
 246        }
 247
 248        /* all claims gone, intialize CRC */
 249        backbone_gw->crc = BATADV_BLA_CRC_INIT;
 250}
 251
 252/**
 253 * batadv_bla_send_claim - sends a claim frame according to the provided info
 254 * @bat_priv: the bat priv with all the soft interface information
 255 * @orig: the mac address to be announced within the claim
 256 * @vid: the VLAN ID
 257 * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
 258 */
 259static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 260                                  unsigned short vid, int claimtype)
 261{
 262        struct sk_buff *skb;
 263        struct ethhdr *ethhdr;
 264        struct batadv_hard_iface *primary_if;
 265        struct net_device *soft_iface;
 266        uint8_t *hw_src;
 267        struct batadv_bla_claim_dst local_claim_dest;
 268        __be32 zeroip = 0;
 269
 270        primary_if = batadv_primary_if_get_selected(bat_priv);
 271        if (!primary_if)
 272                return;
 273
 274        memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
 275               sizeof(local_claim_dest));
 276        local_claim_dest.type = claimtype;
 277
 278        soft_iface = primary_if->soft_iface;
 279
 280        skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
 281                         /* IP DST: 0.0.0.0 */
 282                         zeroip,
 283                         primary_if->soft_iface,
 284                         /* IP SRC: 0.0.0.0 */
 285                         zeroip,
 286                         /* Ethernet DST: Broadcast */
 287                         NULL,
 288                         /* Ethernet SRC/HW SRC:  originator mac */
 289                         primary_if->net_dev->dev_addr,
 290                         /* HW DST: FF:43:05:XX:YY:YY
 291                          * with XX   = claim type
 292                          * and YY:YY = group id
 293                          */
 294                         (uint8_t *)&local_claim_dest);
 295
 296        if (!skb)
 297                goto out;
 298
 299        ethhdr = (struct ethhdr *)skb->data;
 300        hw_src = (uint8_t *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
 301
 302        /* now we pretend that the client would have sent this ... */
 303        switch (claimtype) {
 304        case BATADV_CLAIM_TYPE_CLAIM:
 305                /* normal claim frame
 306                 * set Ethernet SRC to the clients mac
 307                 */
 308                memcpy(ethhdr->h_source, mac, ETH_ALEN);
 309                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 310                           "bla_send_claim(): CLAIM %pM on vid %d\n", mac,
 311                           BATADV_PRINT_VID(vid));
 312                break;
 313        case BATADV_CLAIM_TYPE_UNCLAIM:
 314                /* unclaim frame
 315                 * set HW SRC to the clients mac
 316                 */
 317                memcpy(hw_src, mac, ETH_ALEN);
 318                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 319                           "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
 320                           BATADV_PRINT_VID(vid));
 321                break;
 322        case BATADV_CLAIM_TYPE_ANNOUNCE:
 323                /* announcement frame
 324                 * set HW SRC to the special mac containg the crc
 325                 */
 326                memcpy(hw_src, mac, ETH_ALEN);
 327                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 328                           "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
 329                           ethhdr->h_source, BATADV_PRINT_VID(vid));
 330                break;
 331        case BATADV_CLAIM_TYPE_REQUEST:
 332                /* request frame
 333                 * set HW SRC and header destination to the receiving backbone
 334                 * gws mac
 335                 */
 336                memcpy(hw_src, mac, ETH_ALEN);
 337                memcpy(ethhdr->h_dest, mac, ETH_ALEN);
 338                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 339                           "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n",
 340                           ethhdr->h_source, ethhdr->h_dest,
 341                           BATADV_PRINT_VID(vid));
 342                break;
 343        }
 344
 345        if (vid & BATADV_VLAN_HAS_TAG)
 346                skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
 347                                      vid & VLAN_VID_MASK);
 348
 349        skb_reset_mac_header(skb);
 350        skb->protocol = eth_type_trans(skb, soft_iface);
 351        batadv_inc_counter(bat_priv, BATADV_CNT_RX);
 352        batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
 353                           skb->len + ETH_HLEN);
 354        soft_iface->last_rx = jiffies;
 355
 356        netif_rx(skb);
 357out:
 358        if (primary_if)
 359                batadv_hardif_free_ref(primary_if);
 360}
 361
 362/**
 363 * batadv_bla_get_backbone_gw
 364 * @bat_priv: the bat priv with all the soft interface information
 365 * @orig: the mac address of the originator
 366 * @vid: the VLAN ID
 367 *
 368 * searches for the backbone gw or creates a new one if it could not
 369 * be found.
 370 */
 371static struct batadv_bla_backbone_gw *
 372batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 373                           unsigned short vid, bool own_backbone)
 374{
 375        struct batadv_bla_backbone_gw *entry;
 376        struct batadv_orig_node *orig_node;
 377        int hash_added;
 378
 379        entry = batadv_backbone_hash_find(bat_priv, orig, vid);
 380
 381        if (entry)
 382                return entry;
 383
 384        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 385                   "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
 386                   orig, BATADV_PRINT_VID(vid));
 387
 388        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 389        if (!entry)
 390                return NULL;
 391
 392        entry->vid = vid;
 393        entry->lasttime = jiffies;
 394        entry->crc = BATADV_BLA_CRC_INIT;
 395        entry->bat_priv = bat_priv;
 396        atomic_set(&entry->request_sent, 0);
 397        atomic_set(&entry->wait_periods, 0);
 398        memcpy(entry->orig, orig, ETH_ALEN);
 399
 400        /* one for the hash, one for returning */
 401        atomic_set(&entry->refcount, 2);
 402
 403        hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
 404                                     batadv_compare_backbone_gw,
 405                                     batadv_choose_backbone_gw, entry,
 406                                     &entry->hash_entry);
 407
 408        if (unlikely(hash_added != 0)) {
 409                /* hash failed, free the structure */
 410                kfree(entry);
 411                return NULL;
 412        }
 413
 414        /* this is a gateway now, remove any tt entries */
 415        orig_node = batadv_orig_hash_find(bat_priv, orig);
 416        if (orig_node) {
 417                batadv_tt_global_del_orig(bat_priv, orig_node,
 418                                          "became a backbone gateway");
 419                batadv_orig_node_free_ref(orig_node);
 420        }
 421
 422        if (own_backbone) {
 423                batadv_bla_send_announce(bat_priv, entry);
 424
 425                /* this will be decreased in the worker thread */
 426                atomic_inc(&entry->request_sent);
 427                atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
 428                atomic_inc(&bat_priv->bla.num_requests);
 429        }
 430
 431        return entry;
 432}
 433
 434/* update or add the own backbone gw to make sure we announce
 435 * where we receive other backbone gws
 436 */
 437static void
 438batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
 439                                  struct batadv_hard_iface *primary_if,
 440                                  unsigned short vid)
 441{
 442        struct batadv_bla_backbone_gw *backbone_gw;
 443
 444        backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
 445                                                 primary_if->net_dev->dev_addr,
 446                                                 vid, true);
 447        if (unlikely(!backbone_gw))
 448                return;
 449
 450        backbone_gw->lasttime = jiffies;
 451        batadv_backbone_gw_free_ref(backbone_gw);
 452}
 453
 454/* @bat_priv: the bat priv with all the soft interface information
 455 * @vid: the vid where the request came on
 456 *
 457 * Repeat all of our own claims, and finally send an ANNOUNCE frame
 458 * to allow the requester another check if the CRC is correct now.
 459 */
 460static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
 461                                      struct batadv_hard_iface *primary_if,
 462                                      unsigned short vid)
 463{
 464        struct hlist_head *head;
 465        struct batadv_hashtable *hash;
 466        struct batadv_bla_claim *claim;
 467        struct batadv_bla_backbone_gw *backbone_gw;
 468        int i;
 469
 470        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 471                   "bla_answer_request(): received a claim request, send all of our own claims again\n");
 472
 473        backbone_gw = batadv_backbone_hash_find(bat_priv,
 474                                                primary_if->net_dev->dev_addr,
 475                                                vid);
 476        if (!backbone_gw)
 477                return;
 478
 479        hash = bat_priv->bla.claim_hash;
 480        for (i = 0; i < hash->size; i++) {
 481                head = &hash->table[i];
 482
 483                rcu_read_lock();
 484                hlist_for_each_entry_rcu(claim, head, hash_entry) {
 485                        /* only own claims are interesting */
 486                        if (claim->backbone_gw != backbone_gw)
 487                                continue;
 488
 489                        batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
 490                                              BATADV_CLAIM_TYPE_CLAIM);
 491                }
 492                rcu_read_unlock();
 493        }
 494
 495        /* finally, send an announcement frame */
 496        batadv_bla_send_announce(bat_priv, backbone_gw);
 497        batadv_backbone_gw_free_ref(backbone_gw);
 498}
 499
 500/* @backbone_gw: the backbone gateway from whom we are out of sync
 501 *
 502 * When the crc is wrong, ask the backbone gateway for a full table update.
 503 * After the request, it will repeat all of his own claims and finally
 504 * send an announcement claim with which we can check again.
 505 */
 506static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw)
 507{
 508        /* first, remove all old entries */
 509        batadv_bla_del_backbone_claims(backbone_gw);
 510
 511        batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
 512                   "Sending REQUEST to %pM\n", backbone_gw->orig);
 513
 514        /* send request */
 515        batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
 516                              backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
 517
 518        /* no local broadcasts should be sent or received, for now. */
 519        if (!atomic_read(&backbone_gw->request_sent)) {
 520                atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
 521                atomic_set(&backbone_gw->request_sent, 1);
 522        }
 523}
 524
 525/* @bat_priv: the bat priv with all the soft interface information
 526 * @backbone_gw: our backbone gateway which should be announced
 527 *
 528 * This function sends an announcement. It is called from multiple
 529 * places.
 530 */
 531static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
 532                                     struct batadv_bla_backbone_gw *backbone_gw)
 533{
 534        uint8_t mac[ETH_ALEN];
 535        __be16 crc;
 536
 537        memcpy(mac, batadv_announce_mac, 4);
 538        crc = htons(backbone_gw->crc);
 539        memcpy(&mac[4], &crc, 2);
 540
 541        batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
 542                              BATADV_CLAIM_TYPE_ANNOUNCE);
 543}
 544
 545/**
 546 * batadv_bla_add_claim - Adds a claim in the claim hash
 547 * @bat_priv: the bat priv with all the soft interface information
 548 * @mac: the mac address of the claim
 549 * @vid: the VLAN ID of the frame
 550 * @backbone_gw: the backbone gateway which claims it
 551 */
 552static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
 553                                 const uint8_t *mac, const unsigned short vid,
 554                                 struct batadv_bla_backbone_gw *backbone_gw)
 555{
 556        struct batadv_bla_claim *claim;
 557        struct batadv_bla_claim search_claim;
 558        int hash_added;
 559
 560        memcpy(search_claim.addr, mac, ETH_ALEN);
 561        search_claim.vid = vid;
 562        claim = batadv_claim_hash_find(bat_priv, &search_claim);
 563
 564        /* create a new claim entry if it does not exist yet. */
 565        if (!claim) {
 566                claim = kzalloc(sizeof(*claim), GFP_ATOMIC);
 567                if (!claim)
 568                        return;
 569
 570                memcpy(claim->addr, mac, ETH_ALEN);
 571                claim->vid = vid;
 572                claim->lasttime = jiffies;
 573                claim->backbone_gw = backbone_gw;
 574
 575                atomic_set(&claim->refcount, 2);
 576                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 577                           "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
 578                           mac, BATADV_PRINT_VID(vid));
 579                hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
 580                                             batadv_compare_claim,
 581                                             batadv_choose_claim, claim,
 582                                             &claim->hash_entry);
 583
 584                if (unlikely(hash_added != 0)) {
 585                        /* only local changes happened. */
 586                        kfree(claim);
 587                        return;
 588                }
 589        } else {
 590                claim->lasttime = jiffies;
 591                if (claim->backbone_gw == backbone_gw)
 592                        /* no need to register a new backbone */
 593                        goto claim_free_ref;
 594
 595                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 596                           "bla_add_claim(): changing ownership for %pM, vid %d\n",
 597                           mac, BATADV_PRINT_VID(vid));
 598
 599                claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
 600                batadv_backbone_gw_free_ref(claim->backbone_gw);
 601        }
 602        /* set (new) backbone gw */
 603        atomic_inc(&backbone_gw->refcount);
 604        claim->backbone_gw = backbone_gw;
 605
 606        backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
 607        backbone_gw->lasttime = jiffies;
 608
 609claim_free_ref:
 610        batadv_claim_free_ref(claim);
 611}
 612
 613/* Delete a claim from the claim hash which has the
 614 * given mac address and vid.
 615 */
 616static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
 617                                 const uint8_t *mac, const unsigned short vid)
 618{
 619        struct batadv_bla_claim search_claim, *claim;
 620
 621        memcpy(search_claim.addr, mac, ETH_ALEN);
 622        search_claim.vid = vid;
 623        claim = batadv_claim_hash_find(bat_priv, &search_claim);
 624        if (!claim)
 625                return;
 626
 627        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
 628                   mac, BATADV_PRINT_VID(vid));
 629
 630        batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
 631                           batadv_choose_claim, claim);
 632        batadv_claim_free_ref(claim); /* reference from the hash is gone */
 633
 634        claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
 635
 636        /* don't need the reference from hash_find() anymore */
 637        batadv_claim_free_ref(claim);
 638}
 639
 640/* check for ANNOUNCE frame, return 1 if handled */
 641static int batadv_handle_announce(struct batadv_priv *bat_priv,
 642                                  uint8_t *an_addr, uint8_t *backbone_addr,
 643                                  unsigned short vid)
 644{
 645        struct batadv_bla_backbone_gw *backbone_gw;
 646        uint16_t crc;
 647
 648        if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
 649                return 0;
 650
 651        backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
 652                                                 false);
 653
 654        if (unlikely(!backbone_gw))
 655                return 1;
 656
 657
 658        /* handle as ANNOUNCE frame */
 659        backbone_gw->lasttime = jiffies;
 660        crc = ntohs(*((__be16 *)(&an_addr[4])));
 661
 662        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 663                   "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
 664                   BATADV_PRINT_VID(vid), backbone_gw->orig, crc);
 665
 666        if (backbone_gw->crc != crc) {
 667                batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
 668                           "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
 669                           backbone_gw->orig,
 670                           BATADV_PRINT_VID(backbone_gw->vid),
 671                           backbone_gw->crc, crc);
 672
 673                batadv_bla_send_request(backbone_gw);
 674        } else {
 675                /* if we have sent a request and the crc was OK,
 676                 * we can allow traffic again.
 677                 */
 678                if (atomic_read(&backbone_gw->request_sent)) {
 679                        atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
 680                        atomic_set(&backbone_gw->request_sent, 0);
 681                }
 682        }
 683
 684        batadv_backbone_gw_free_ref(backbone_gw);
 685        return 1;
 686}
 687
 688/* check for REQUEST frame, return 1 if handled */
 689static int batadv_handle_request(struct batadv_priv *bat_priv,
 690                                 struct batadv_hard_iface *primary_if,
 691                                 uint8_t *backbone_addr,
 692                                 struct ethhdr *ethhdr, unsigned short vid)
 693{
 694        /* check for REQUEST frame */
 695        if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
 696                return 0;
 697
 698        /* sanity check, this should not happen on a normal switch,
 699         * we ignore it in this case.
 700         */
 701        if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
 702                return 1;
 703
 704        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 705                   "handle_request(): REQUEST vid %d (sent by %pM)...\n",
 706                   BATADV_PRINT_VID(vid), ethhdr->h_source);
 707
 708        batadv_bla_answer_request(bat_priv, primary_if, vid);
 709        return 1;
 710}
 711
 712/* check for UNCLAIM frame, return 1 if handled */
 713static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
 714                                 struct batadv_hard_iface *primary_if,
 715                                 uint8_t *backbone_addr,
 716                                 uint8_t *claim_addr, unsigned short vid)
 717{
 718        struct batadv_bla_backbone_gw *backbone_gw;
 719
 720        /* unclaim in any case if it is our own */
 721        if (primary_if && batadv_compare_eth(backbone_addr,
 722                                             primary_if->net_dev->dev_addr))
 723                batadv_bla_send_claim(bat_priv, claim_addr, vid,
 724                                      BATADV_CLAIM_TYPE_UNCLAIM);
 725
 726        backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
 727
 728        if (!backbone_gw)
 729                return 1;
 730
 731        /* this must be an UNCLAIM frame */
 732        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 733                   "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
 734                   claim_addr, BATADV_PRINT_VID(vid), backbone_gw->orig);
 735
 736        batadv_bla_del_claim(bat_priv, claim_addr, vid);
 737        batadv_backbone_gw_free_ref(backbone_gw);
 738        return 1;
 739}
 740
 741/* check for CLAIM frame, return 1 if handled */
 742static int batadv_handle_claim(struct batadv_priv *bat_priv,
 743                               struct batadv_hard_iface *primary_if,
 744                               uint8_t *backbone_addr, uint8_t *claim_addr,
 745                               unsigned short vid)
 746{
 747        struct batadv_bla_backbone_gw *backbone_gw;
 748
 749        /* register the gateway if not yet available, and add the claim. */
 750
 751        backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
 752                                                 false);
 753
 754        if (unlikely(!backbone_gw))
 755                return 1;
 756
 757        /* this must be a CLAIM frame */
 758        batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
 759        if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
 760                batadv_bla_send_claim(bat_priv, claim_addr, vid,
 761                                      BATADV_CLAIM_TYPE_CLAIM);
 762
 763        /* TODO: we could call something like tt_local_del() here. */
 764
 765        batadv_backbone_gw_free_ref(backbone_gw);
 766        return 1;
 767}
 768
 769/**
 770 * batadv_check_claim_group
 771 * @bat_priv: the bat priv with all the soft interface information
 772 * @hw_src: the Hardware source in the ARP Header
 773 * @hw_dst: the Hardware destination in the ARP Header
 774 * @ethhdr: pointer to the Ethernet header of the claim frame
 775 *
 776 * checks if it is a claim packet and if its on the same group.
 777 * This function also applies the group ID of the sender
 778 * if it is in the same mesh.
 779 *
 780 * returns:
 781 *      2  - if it is a claim packet and on the same group
 782 *      1  - if is a claim packet from another group
 783 *      0  - if it is not a claim packet
 784 */
 785static int batadv_check_claim_group(struct batadv_priv *bat_priv,
 786                                    struct batadv_hard_iface *primary_if,
 787                                    uint8_t *hw_src, uint8_t *hw_dst,
 788                                    struct ethhdr *ethhdr)
 789{
 790        uint8_t *backbone_addr;
 791        struct batadv_orig_node *orig_node;
 792        struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
 793
 794        bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
 795        bla_dst_own = &bat_priv->bla.claim_dest;
 796
 797        /* check if it is a claim packet in general */
 798        if (memcmp(bla_dst->magic, bla_dst_own->magic,
 799                   sizeof(bla_dst->magic)) != 0)
 800                return 0;
 801
 802        /* if announcement packet, use the source,
 803         * otherwise assume it is in the hw_src
 804         */
 805        switch (bla_dst->type) {
 806        case BATADV_CLAIM_TYPE_CLAIM:
 807                backbone_addr = hw_src;
 808                break;
 809        case BATADV_CLAIM_TYPE_REQUEST:
 810        case BATADV_CLAIM_TYPE_ANNOUNCE:
 811        case BATADV_CLAIM_TYPE_UNCLAIM:
 812                backbone_addr = ethhdr->h_source;
 813                break;
 814        default:
 815                return 0;
 816        }
 817
 818        /* don't accept claim frames from ourselves */
 819        if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
 820                return 0;
 821
 822        /* if its already the same group, it is fine. */
 823        if (bla_dst->group == bla_dst_own->group)
 824                return 2;
 825
 826        /* lets see if this originator is in our mesh */
 827        orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
 828
 829        /* dont accept claims from gateways which are not in
 830         * the same mesh or group.
 831         */
 832        if (!orig_node)
 833                return 1;
 834
 835        /* if our mesh friends mac is bigger, use it for ourselves. */
 836        if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) {
 837                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 838                           "taking other backbones claim group: %#.4x\n",
 839                           ntohs(bla_dst->group));
 840                bla_dst_own->group = bla_dst->group;
 841        }
 842
 843        batadv_orig_node_free_ref(orig_node);
 844
 845        return 2;
 846}
 847
 848
 849/* @bat_priv: the bat priv with all the soft interface information
 850 * @skb: the frame to be checked
 851 *
 852 * Check if this is a claim frame, and process it accordingly.
 853 *
 854 * returns 1 if it was a claim frame, otherwise return 0 to
 855 * tell the callee that it can use the frame on its own.
 856 */
 857static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
 858                                    struct batadv_hard_iface *primary_if,
 859                                    struct sk_buff *skb)
 860{
 861        struct ethhdr *ethhdr;
 862        struct vlan_ethhdr *vhdr;
 863        struct arphdr *arphdr;
 864        uint8_t *hw_src, *hw_dst;
 865        struct batadv_bla_claim_dst *bla_dst;
 866        uint16_t proto;
 867        int headlen;
 868        unsigned short vid = BATADV_NO_FLAGS;
 869        int ret;
 870
 871        ethhdr = eth_hdr(skb);
 872
 873        if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
 874                vhdr = (struct vlan_ethhdr *)ethhdr;
 875                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
 876                vid |= BATADV_VLAN_HAS_TAG;
 877                proto = ntohs(vhdr->h_vlan_encapsulated_proto);
 878                headlen = sizeof(*vhdr);
 879        } else {
 880                proto = ntohs(ethhdr->h_proto);
 881                headlen = ETH_HLEN;
 882        }
 883
 884        if (proto != ETH_P_ARP)
 885                return 0; /* not a claim frame */
 886
 887        /* this must be a ARP frame. check if it is a claim. */
 888
 889        if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
 890                return 0;
 891
 892        /* pskb_may_pull() may have modified the pointers, get ethhdr again */
 893        ethhdr = eth_hdr(skb);
 894        arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen);
 895
 896        /* Check whether the ARP frame carries a valid
 897         * IP information
 898         */
 899        if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
 900                return 0;
 901        if (arphdr->ar_pro != htons(ETH_P_IP))
 902                return 0;
 903        if (arphdr->ar_hln != ETH_ALEN)
 904                return 0;
 905        if (arphdr->ar_pln != 4)
 906                return 0;
 907
 908        hw_src = (uint8_t *)arphdr + sizeof(struct arphdr);
 909        hw_dst = hw_src + ETH_ALEN + 4;
 910        bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
 911
 912        /* check if it is a claim frame. */
 913        ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
 914                                       ethhdr);
 915        if (ret == 1)
 916                batadv_dbg(BATADV_DBG_BLA, bat_priv,
 917                           "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
 918                           ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src,
 919                           hw_dst);
 920
 921        if (ret < 2)
 922                return ret;
 923
 924        /* become a backbone gw ourselves on this vlan if not happened yet */
 925        batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
 926
 927        /* check for the different types of claim frames ... */
 928        switch (bla_dst->type) {
 929        case BATADV_CLAIM_TYPE_CLAIM:
 930                if (batadv_handle_claim(bat_priv, primary_if, hw_src,
 931                                        ethhdr->h_source, vid))
 932                        return 1;
 933                break;
 934        case BATADV_CLAIM_TYPE_UNCLAIM:
 935                if (batadv_handle_unclaim(bat_priv, primary_if,
 936                                          ethhdr->h_source, hw_src, vid))
 937                        return 1;
 938                break;
 939
 940        case BATADV_CLAIM_TYPE_ANNOUNCE:
 941                if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
 942                                           vid))
 943                        return 1;
 944                break;
 945        case BATADV_CLAIM_TYPE_REQUEST:
 946                if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
 947                                          vid))
 948                        return 1;
 949                break;
 950        }
 951
 952        batadv_dbg(BATADV_DBG_BLA, bat_priv,
 953                   "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
 954                   ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src, hw_dst);
 955        return 1;
 956}
 957
 958/* Check when we last heard from other nodes, and remove them in case of
 959 * a time out, or clean all backbone gws if now is set.
 960 */
 961static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 962{
 963        struct batadv_bla_backbone_gw *backbone_gw;
 964        struct hlist_node *node_tmp;
 965        struct hlist_head *head;
 966        struct batadv_hashtable *hash;
 967        spinlock_t *list_lock;  /* protects write access to the hash lists */
 968        int i;
 969
 970        hash = bat_priv->bla.backbone_hash;
 971        if (!hash)
 972                return;
 973
 974        for (i = 0; i < hash->size; i++) {
 975                head = &hash->table[i];
 976                list_lock = &hash->list_locks[i];
 977
 978                spin_lock_bh(list_lock);
 979                hlist_for_each_entry_safe(backbone_gw, node_tmp,
 980                                          head, hash_entry) {
 981                        if (now)
 982                                goto purge_now;
 983                        if (!batadv_has_timed_out(backbone_gw->lasttime,
 984                                                  BATADV_BLA_BACKBONE_TIMEOUT))
 985                                continue;
 986
 987                        batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
 988                                   "bla_purge_backbone_gw(): backbone gw %pM timed out\n",
 989                                   backbone_gw->orig);
 990
 991purge_now:
 992                        /* don't wait for the pending request anymore */
 993                        if (atomic_read(&backbone_gw->request_sent))
 994                                atomic_dec(&bat_priv->bla.num_requests);
 995
 996                        batadv_bla_del_backbone_claims(backbone_gw);
 997
 998                        hlist_del_rcu(&backbone_gw->hash_entry);
 999                        batadv_backbone_gw_free_ref(backbone_gw);
1000                }
1001                spin_unlock_bh(list_lock);
1002        }
1003}
1004
1005/**
1006 * batadv_bla_purge_claims
1007 * @bat_priv: the bat priv with all the soft interface information
1008 * @primary_if: the selected primary interface, may be NULL if now is set
1009 * @now: whether the whole hash shall be wiped now
1010 *
1011 * Check when we heard last time from our own claims, and remove them in case of
1012 * a time out, or clean all claims if now is set
1013 */
1014static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
1015                                    struct batadv_hard_iface *primary_if,
1016                                    int now)
1017{
1018        struct batadv_bla_claim *claim;
1019        struct hlist_head *head;
1020        struct batadv_hashtable *hash;
1021        int i;
1022
1023        hash = bat_priv->bla.claim_hash;
1024        if (!hash)
1025                return;
1026
1027        for (i = 0; i < hash->size; i++) {
1028                head = &hash->table[i];
1029
1030                rcu_read_lock();
1031                hlist_for_each_entry_rcu(claim, head, hash_entry) {
1032                        if (now)
1033                                goto purge_now;
1034                        if (!batadv_compare_eth(claim->backbone_gw->orig,
1035                                                primary_if->net_dev->dev_addr))
1036                                continue;
1037                        if (!batadv_has_timed_out(claim->lasttime,
1038                                                  BATADV_BLA_CLAIM_TIMEOUT))
1039                                continue;
1040
1041                        batadv_dbg(BATADV_DBG_BLA, bat_priv,
1042                                   "bla_purge_claims(): %pM, vid %d, time out\n",
1043                                   claim->addr, claim->vid);
1044
1045purge_now:
1046                        batadv_handle_unclaim(bat_priv, primary_if,
1047                                              claim->backbone_gw->orig,
1048                                              claim->addr, claim->vid);
1049                }
1050                rcu_read_unlock();
1051        }
1052}
1053
1054/**
1055 * batadv_bla_update_orig_address
1056 * @bat_priv: the bat priv with all the soft interface information
1057 * @primary_if: the new selected primary_if
1058 * @oldif: the old primary interface, may be NULL
1059 *
1060 * Update the backbone gateways when the own orig address changes.
1061 */
1062void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1063                                    struct batadv_hard_iface *primary_if,
1064                                    struct batadv_hard_iface *oldif)
1065{
1066        struct batadv_bla_backbone_gw *backbone_gw;
1067        struct hlist_head *head;
1068        struct batadv_hashtable *hash;
1069        __be16 group;
1070        int i;
1071
1072        /* reset bridge loop avoidance group id */
1073        group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
1074        bat_priv->bla.claim_dest.group = group;
1075
1076        /* purge everything when bridge loop avoidance is turned off */
1077        if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1078                oldif = NULL;
1079
1080        if (!oldif) {
1081                batadv_bla_purge_claims(bat_priv, NULL, 1);
1082                batadv_bla_purge_backbone_gw(bat_priv, 1);
1083                return;
1084        }
1085
1086        hash = bat_priv->bla.backbone_hash;
1087        if (!hash)
1088                return;
1089
1090        for (i = 0; i < hash->size; i++) {
1091                head = &hash->table[i];
1092
1093                rcu_read_lock();
1094                hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1095                        /* own orig still holds the old value. */
1096                        if (!batadv_compare_eth(backbone_gw->orig,
1097                                                oldif->net_dev->dev_addr))
1098                                continue;
1099
1100                        memcpy(backbone_gw->orig,
1101                               primary_if->net_dev->dev_addr, ETH_ALEN);
1102                        /* send an announce frame so others will ask for our
1103                         * claims and update their tables.
1104                         */
1105                        batadv_bla_send_announce(bat_priv, backbone_gw);
1106                }
1107                rcu_read_unlock();
1108        }
1109}
1110
1111/* periodic work to do:
1112 *  * purge structures when they are too old
1113 *  * send announcements
1114 */
1115static void batadv_bla_periodic_work(struct work_struct *work)
1116{
1117        struct delayed_work *delayed_work;
1118        struct batadv_priv *bat_priv;
1119        struct batadv_priv_bla *priv_bla;
1120        struct hlist_head *head;
1121        struct batadv_bla_backbone_gw *backbone_gw;
1122        struct batadv_hashtable *hash;
1123        struct batadv_hard_iface *primary_if;
1124        int i;
1125
1126        delayed_work = container_of(work, struct delayed_work, work);
1127        priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
1128        bat_priv = container_of(priv_bla, struct batadv_priv, bla);
1129        primary_if = batadv_primary_if_get_selected(bat_priv);
1130        if (!primary_if)
1131                goto out;
1132
1133        batadv_bla_purge_claims(bat_priv, primary_if, 0);
1134        batadv_bla_purge_backbone_gw(bat_priv, 0);
1135
1136        if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1137                goto out;
1138
1139        hash = bat_priv->bla.backbone_hash;
1140        if (!hash)
1141                goto out;
1142
1143        for (i = 0; i < hash->size; i++) {
1144                head = &hash->table[i];
1145
1146                rcu_read_lock();
1147                hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1148                        if (!batadv_compare_eth(backbone_gw->orig,
1149                                                primary_if->net_dev->dev_addr))
1150                                continue;
1151
1152                        backbone_gw->lasttime = jiffies;
1153
1154                        batadv_bla_send_announce(bat_priv, backbone_gw);
1155
1156                        /* request_sent is only set after creation to avoid
1157                         * problems when we are not yet known as backbone gw
1158                         * in the backbone.
1159                         *
1160                         * We can reset this now after we waited some periods
1161                         * to give bridge forward delays and bla group forming
1162                         * some grace time.
1163                         */
1164
1165                        if (atomic_read(&backbone_gw->request_sent) == 0)
1166                                continue;
1167
1168                        if (!atomic_dec_and_test(&backbone_gw->wait_periods))
1169                                continue;
1170
1171                        atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
1172                        atomic_set(&backbone_gw->request_sent, 0);
1173                }
1174                rcu_read_unlock();
1175        }
1176out:
1177        if (primary_if)
1178                batadv_hardif_free_ref(primary_if);
1179
1180        queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1181                           msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
1182}
1183
1184/* The hash for claim and backbone hash receive the same key because they
1185 * are getting initialized by hash_new with the same key. Reinitializing
1186 * them with to different keys to allow nested locking without generating
1187 * lockdep warnings
1188 */
1189static struct lock_class_key batadv_claim_hash_lock_class_key;
1190static struct lock_class_key batadv_backbone_hash_lock_class_key;
1191
1192/* initialize all bla structures */
1193int batadv_bla_init(struct batadv_priv *bat_priv)
1194{
1195        int i;
1196        uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
1197        struct batadv_hard_iface *primary_if;
1198        uint16_t crc;
1199        unsigned long entrytime;
1200
1201        spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
1202
1203        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
1204
1205        /* setting claim destination address */
1206        memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
1207        bat_priv->bla.claim_dest.type = 0;
1208        primary_if = batadv_primary_if_get_selected(bat_priv);
1209        if (primary_if) {
1210                crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
1211                bat_priv->bla.claim_dest.group = htons(crc);
1212                batadv_hardif_free_ref(primary_if);
1213        } else {
1214                bat_priv->bla.claim_dest.group = 0; /* will be set later */
1215        }
1216
1217        /* initialize the duplicate list */
1218        entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
1219        for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
1220                bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
1221        bat_priv->bla.bcast_duplist_curr = 0;
1222
1223        if (bat_priv->bla.claim_hash)
1224                return 0;
1225
1226        bat_priv->bla.claim_hash = batadv_hash_new(128);
1227        bat_priv->bla.backbone_hash = batadv_hash_new(32);
1228
1229        if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash)
1230                return -ENOMEM;
1231
1232        batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
1233                                   &batadv_claim_hash_lock_class_key);
1234        batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
1235                                   &batadv_backbone_hash_lock_class_key);
1236
1237        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
1238
1239        INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
1240
1241        queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1242                           msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
1243        return 0;
1244}
1245
1246/**
1247 * batadv_bla_check_bcast_duplist
1248 * @bat_priv: the bat priv with all the soft interface information
1249 * @skb: contains the bcast_packet to be checked
1250 *
1251 * check if it is on our broadcast list. Another gateway might
1252 * have sent the same packet because it is connected to the same backbone,
1253 * so we have to remove this duplicate.
1254 *
1255 * This is performed by checking the CRC, which will tell us
1256 * with a good chance that it is the same packet. If it is furthermore
1257 * sent by another host, drop it. We allow equal packets from
1258 * the same host however as this might be intended.
1259 */
1260int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
1261                                   struct sk_buff *skb)
1262{
1263        int i, curr, ret = 0;
1264        __be32 crc;
1265        struct batadv_bcast_packet *bcast_packet;
1266        struct batadv_bcast_duplist_entry *entry;
1267
1268        bcast_packet = (struct batadv_bcast_packet *)skb->data;
1269
1270        /* calculate the crc ... */
1271        crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
1272
1273        spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
1274
1275        for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
1276                curr = (bat_priv->bla.bcast_duplist_curr + i);
1277                curr %= BATADV_DUPLIST_SIZE;
1278                entry = &bat_priv->bla.bcast_duplist[curr];
1279
1280                /* we can stop searching if the entry is too old ;
1281                 * later entries will be even older
1282                 */
1283                if (batadv_has_timed_out(entry->entrytime,
1284                                         BATADV_DUPLIST_TIMEOUT))
1285                        break;
1286
1287                if (entry->crc != crc)
1288                        continue;
1289
1290                if (batadv_compare_eth(entry->orig, bcast_packet->orig))
1291                        continue;
1292
1293                /* this entry seems to match: same crc, not too old,
1294                 * and from another gw. therefore return 1 to forbid it.
1295                 */
1296                ret = 1;
1297                goto out;
1298        }
1299        /* not found, add a new entry (overwrite the oldest entry)
1300         * and allow it, its the first occurence.
1301         */
1302        curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
1303        curr %= BATADV_DUPLIST_SIZE;
1304        entry = &bat_priv->bla.bcast_duplist[curr];
1305        entry->crc = crc;
1306        entry->entrytime = jiffies;
1307        memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
1308        bat_priv->bla.bcast_duplist_curr = curr;
1309
1310out:
1311        spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
1312
1313        return ret;
1314}
1315
1316
1317
1318/* @bat_priv: the bat priv with all the soft interface information
1319 * @orig: originator mac address
1320 *
1321 * check if the originator is a gateway for any VLAN ID.
1322 *
1323 * returns 1 if it is found, 0 otherwise
1324 */
1325int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
1326{
1327        struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
1328        struct hlist_head *head;
1329        struct batadv_bla_backbone_gw *backbone_gw;
1330        int i;
1331
1332        if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1333                return 0;
1334
1335        if (!hash)
1336                return 0;
1337
1338        for (i = 0; i < hash->size; i++) {
1339                head = &hash->table[i];
1340
1341                rcu_read_lock();
1342                hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1343                        if (batadv_compare_eth(backbone_gw->orig, orig)) {
1344                                rcu_read_unlock();
1345                                return 1;
1346                        }
1347                }
1348                rcu_read_unlock();
1349        }
1350
1351        return 0;
1352}
1353
1354
1355/**
1356 * batadv_bla_is_backbone_gw
1357 * @skb: the frame to be checked
1358 * @orig_node: the orig_node of the frame
1359 * @hdr_size: maximum length of the frame
1360 *
1361 * bla_is_backbone_gw inspects the skb for the VLAN ID and returns 1
1362 * if the orig_node is also a gateway on the soft interface, otherwise it
1363 * returns 0.
1364 */
1365int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1366                              struct batadv_orig_node *orig_node, int hdr_size)
1367{
1368        struct ethhdr *ethhdr;
1369        struct vlan_ethhdr *vhdr;
1370        struct batadv_bla_backbone_gw *backbone_gw;
1371        unsigned short vid = BATADV_NO_FLAGS;
1372
1373        if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
1374                return 0;
1375
1376        /* first, find out the vid. */
1377        if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1378                return 0;
1379
1380        ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);
1381
1382        if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
1383                if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
1384                        return 0;
1385
1386                vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
1387                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
1388                vid |= BATADV_VLAN_HAS_TAG;
1389        }
1390
1391        /* see if this originator is a backbone gw for this VLAN */
1392        backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
1393                                                orig_node->orig, vid);
1394        if (!backbone_gw)
1395                return 0;
1396
1397        batadv_backbone_gw_free_ref(backbone_gw);
1398        return 1;
1399}
1400
1401/* free all bla structures (for softinterface free or module unload) */
1402void batadv_bla_free(struct batadv_priv *bat_priv)
1403{
1404        struct batadv_hard_iface *primary_if;
1405
1406        cancel_delayed_work_sync(&bat_priv->bla.work);
1407        primary_if = batadv_primary_if_get_selected(bat_priv);
1408
1409        if (bat_priv->bla.claim_hash) {
1410                batadv_bla_purge_claims(bat_priv, primary_if, 1);
1411                batadv_hash_destroy(bat_priv->bla.claim_hash);
1412                bat_priv->bla.claim_hash = NULL;
1413        }
1414        if (bat_priv->bla.backbone_hash) {
1415                batadv_bla_purge_backbone_gw(bat_priv, 1);
1416                batadv_hash_destroy(bat_priv->bla.backbone_hash);
1417                bat_priv->bla.backbone_hash = NULL;
1418        }
1419        if (primary_if)
1420                batadv_hardif_free_ref(primary_if);
1421}
1422
1423/**
1424 * batadv_bla_rx
1425 * @bat_priv: the bat priv with all the soft interface information
1426 * @skb: the frame to be checked
1427 * @vid: the VLAN ID of the frame
1428 * @is_bcast: the packet came in a broadcast packet type.
1429 *
1430 * bla_rx avoidance checks if:
1431 *  * we have to race for a claim
1432 *  * if the frame is allowed on the LAN
1433 *
1434 * in these cases, the skb is further handled by this function and
1435 * returns 1, otherwise it returns 0 and the caller shall further
1436 * process the skb.
1437 */
1438int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
1439                  unsigned short vid, bool is_bcast)
1440{
1441        struct ethhdr *ethhdr;
1442        struct batadv_bla_claim search_claim, *claim = NULL;
1443        struct batadv_hard_iface *primary_if;
1444        int ret;
1445
1446        ethhdr = eth_hdr(skb);
1447
1448        primary_if = batadv_primary_if_get_selected(bat_priv);
1449        if (!primary_if)
1450                goto handled;
1451
1452        if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1453                goto allow;
1454
1455
1456        if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1457                /* don't allow broadcasts while requests are in flight */
1458                if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
1459                        goto handled;
1460
1461        memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
1462        search_claim.vid = vid;
1463        claim = batadv_claim_hash_find(bat_priv, &search_claim);
1464
1465        if (!claim) {
1466                /* possible optimization: race for a claim */
1467                /* No claim exists yet, claim it for us!
1468                 */
1469                batadv_handle_claim(bat_priv, primary_if,
1470                                    primary_if->net_dev->dev_addr,
1471                                    ethhdr->h_source, vid);
1472                goto allow;
1473        }
1474
1475        /* if it is our own claim ... */
1476        if (batadv_compare_eth(claim->backbone_gw->orig,
1477                               primary_if->net_dev->dev_addr)) {
1478                /* ... allow it in any case */
1479                claim->lasttime = jiffies;
1480                goto allow;
1481        }
1482
1483        /* if it is a broadcast ... */
1484        if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
1485                /* ... drop it. the responsible gateway is in charge.
1486                 *
1487                 * We need to check is_bcast because with the gateway
1488                 * feature, broadcasts (like DHCP requests) may be sent
1489                 * using a unicast packet type.
1490                 */
1491                goto handled;
1492        } else {
1493                /* seems the client considers us as its best gateway.
1494                 * send a claim and update the claim table
1495                 * immediately.
1496                 */
1497                batadv_handle_claim(bat_priv, primary_if,
1498                                    primary_if->net_dev->dev_addr,
1499                                    ethhdr->h_source, vid);
1500                goto allow;
1501        }
1502allow:
1503        batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1504        ret = 0;
1505        goto out;
1506
1507handled:
1508        kfree_skb(skb);
1509        ret = 1;
1510
1511out:
1512        if (primary_if)
1513                batadv_hardif_free_ref(primary_if);
1514        if (claim)
1515                batadv_claim_free_ref(claim);
1516        return ret;
1517}
1518
1519/**
1520 * batadv_bla_tx
1521 * @bat_priv: the bat priv with all the soft interface information
1522 * @skb: the frame to be checked
1523 * @vid: the VLAN ID of the frame
1524 *
1525 * bla_tx checks if:
1526 *  * a claim was received which has to be processed
1527 *  * the frame is allowed on the mesh
1528 *
1529 * in these cases, the skb is further handled by this function and
1530 * returns 1, otherwise it returns 0 and the caller shall further
1531 * process the skb.
1532 *
1533 * This call might reallocate skb data.
1534 */
1535int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
1536                  unsigned short vid)
1537{
1538        struct ethhdr *ethhdr;
1539        struct batadv_bla_claim search_claim, *claim = NULL;
1540        struct batadv_hard_iface *primary_if;
1541        int ret = 0;
1542
1543        primary_if = batadv_primary_if_get_selected(bat_priv);
1544        if (!primary_if)
1545                goto out;
1546
1547        if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1548                goto allow;
1549
1550        /* in VLAN case, the mac header might not be set. */
1551        skb_reset_mac_header(skb);
1552
1553        if (batadv_bla_process_claim(bat_priv, primary_if, skb))
1554                goto handled;
1555
1556        ethhdr = eth_hdr(skb);
1557
1558        if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1559                /* don't allow broadcasts while requests are in flight */
1560                if (is_multicast_ether_addr(ethhdr->h_dest))
1561                        goto handled;
1562
1563        memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
1564        search_claim.vid = vid;
1565
1566        claim = batadv_claim_hash_find(bat_priv, &search_claim);
1567
1568        /* if no claim exists, allow it. */
1569        if (!claim)
1570                goto allow;
1571
1572        /* check if we are responsible. */
1573        if (batadv_compare_eth(claim->backbone_gw->orig,
1574                               primary_if->net_dev->dev_addr)) {
1575                /* if yes, the client has roamed and we have
1576                 * to unclaim it.
1577                 */
1578                batadv_handle_unclaim(bat_priv, primary_if,
1579                                      primary_if->net_dev->dev_addr,
1580                                      ethhdr->h_source, vid);
1581                goto allow;
1582        }
1583
1584        /* check if it is a multicast/broadcast frame */
1585        if (is_multicast_ether_addr(ethhdr->h_dest)) {
1586                /* drop it. the responsible gateway has forwarded it into
1587                 * the backbone network.
1588                 */
1589                goto handled;
1590        } else {
1591                /* we must allow it. at least if we are
1592                 * responsible for the DESTINATION.
1593                 */
1594                goto allow;
1595        }
1596allow:
1597        batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1598        ret = 0;
1599        goto out;
1600handled:
1601        ret = 1;
1602out:
1603        if (primary_if)
1604                batadv_hardif_free_ref(primary_if);
1605        if (claim)
1606                batadv_claim_free_ref(claim);
1607        return ret;
1608}
1609
1610int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
1611{
1612        struct net_device *net_dev = (struct net_device *)seq->private;
1613        struct batadv_priv *bat_priv = netdev_priv(net_dev);
1614        struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
1615        struct batadv_bla_claim *claim;
1616        struct batadv_hard_iface *primary_if;
1617        struct hlist_head *head;
1618        uint32_t i;
1619        bool is_own;
1620        uint8_t *primary_addr;
1621
1622        primary_if = batadv_seq_print_text_primary_if_get(seq);
1623        if (!primary_if)
1624                goto out;
1625
1626        primary_addr = primary_if->net_dev->dev_addr;
1627        seq_printf(seq,
1628                   "Claims announced for the mesh %s (orig %pM, group id %#.4x)\n",
1629                   net_dev->name, primary_addr,
1630                   ntohs(bat_priv->bla.claim_dest.group));
1631        seq_printf(seq, "   %-17s    %-5s    %-17s [o] (%-6s)\n",
1632                   "Client", "VID", "Originator", "CRC");
1633        for (i = 0; i < hash->size; i++) {
1634                head = &hash->table[i];
1635
1636                rcu_read_lock();
1637                hlist_for_each_entry_rcu(claim, head, hash_entry) {
1638                        is_own = batadv_compare_eth(claim->backbone_gw->orig,
1639                                                    primary_addr);
1640                        seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n",
1641                                   claim->addr, BATADV_PRINT_VID(claim->vid),
1642                                   claim->backbone_gw->orig,
1643                                   (is_own ? 'x' : ' '),
1644                                   claim->backbone_gw->crc);
1645                }
1646                rcu_read_unlock();
1647        }
1648out:
1649        if (primary_if)
1650                batadv_hardif_free_ref(primary_if);
1651        return 0;
1652}
1653
1654int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
1655{
1656        struct net_device *net_dev = (struct net_device *)seq->private;
1657        struct batadv_priv *bat_priv = netdev_priv(net_dev);
1658        struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
1659        struct batadv_bla_backbone_gw *backbone_gw;
1660        struct batadv_hard_iface *primary_if;
1661        struct hlist_head *head;
1662        int secs, msecs;
1663        uint32_t i;
1664        bool is_own;
1665        uint8_t *primary_addr;
1666
1667        primary_if = batadv_seq_print_text_primary_if_get(seq);
1668        if (!primary_if)
1669                goto out;
1670
1671        primary_addr = primary_if->net_dev->dev_addr;
1672        seq_printf(seq,
1673                   "Backbones announced for the mesh %s (orig %pM, group id %#.4x)\n",
1674                   net_dev->name, primary_addr,
1675                   ntohs(bat_priv->bla.claim_dest.group));
1676        seq_printf(seq, "   %-17s    %-5s %-9s (%-6s)\n",
1677                   "Originator", "VID", "last seen", "CRC");
1678        for (i = 0; i < hash->size; i++) {
1679                head = &hash->table[i];
1680
1681                rcu_read_lock();
1682                hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1683                        msecs = jiffies_to_msecs(jiffies -
1684                                                 backbone_gw->lasttime);
1685                        secs = msecs / 1000;
1686                        msecs = msecs % 1000;
1687
1688                        is_own = batadv_compare_eth(backbone_gw->orig,
1689                                                    primary_addr);
1690                        if (is_own)
1691                                continue;
1692
1693                        seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n",
1694                                   backbone_gw->orig,
1695                                   BATADV_PRINT_VID(backbone_gw->vid), secs,
1696                                   msecs, backbone_gw->crc);
1697                }
1698                rcu_read_unlock();
1699        }
1700out:
1701        if (primary_if)
1702                batadv_hardif_free_ref(primary_if);
1703        return 0;
1704}
1705