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