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