bridge_loop_avoidance.c 46.0 KB
Newer Older
1
/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * Simon Wunderlich
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "main.h"
#include "hash.h"
#include "hard-interface.h"
#include "originator.h"
#include "bridge_loop_avoidance.h"
25
#include "translation-table.h"
26 27 28 29 30 31 32 33
#include "send.h"

#include <linux/etherdevice.h>
#include <linux/crc16.h>
#include <linux/if_arp.h>
#include <net/arp.h>
#include <linux/if_vlan.h>

34
static const uint8_t batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
35

36
static void batadv_bla_periodic_work(struct work_struct *work);
37 38
static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
				     struct batadv_backbone_gw *backbone_gw);
39 40

/* return the index of the claim */
41
static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
{
	const unsigned char *key = data;
	uint32_t hash = 0;
	size_t i;

	for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
		hash += key[i];
		hash += (hash << 10);
		hash ^= (hash >> 6);
	}

	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);

	return hash % size;
}

/* return the index of the backbone gateway */
61 62
static inline uint32_t batadv_choose_backbone_gw(const void *data,
						 uint32_t size)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
{
	const unsigned char *key = data;
	uint32_t hash = 0;
	size_t i;

	for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
		hash += key[i];
		hash += (hash << 10);
		hash ^= (hash >> 6);
	}

	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);

	return hash % size;
}


/* compares address and vid of two backbone gws */
83 84
static int batadv_compare_backbone_gw(const struct hlist_node *node,
				      const void *data2)
85
{
86
	const void *data1 = container_of(node, struct batadv_backbone_gw,
87 88 89 90 91 92
					 hash_entry);

	return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
}

/* compares address and vid of two claims */
93 94
static int batadv_compare_claim(const struct hlist_node *node,
				const void *data2)
95
{
96
	const void *data1 = container_of(node, struct batadv_claim,
97 98 99 100 101 102
					 hash_entry);

	return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
}

/* free a backbone gw */
103
static void batadv_backbone_gw_free_ref(struct batadv_backbone_gw *backbone_gw)
104 105 106 107 108 109
{
	if (atomic_dec_and_test(&backbone_gw->refcount))
		kfree_rcu(backbone_gw, rcu);
}

/* finally deinitialize the claim */
110
static 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 118 119 120
	kfree(claim);
}

/* free a claim, call claim_free_rcu if its the last reference */
121
static 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 129 130 131 132
 * @data: search data (may be local/static data)
 *
 * looks for a claim in the hash, and returns it if found
 * or NULL otherwise.
 */
133 134
static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
						   struct batadv_claim *data)
135
{
136
	struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
137 138
	struct hlist_head *head;
	struct hlist_node *node;
139 140
	struct batadv_claim *claim;
	struct batadv_claim *claim_tmp = NULL;
141 142 143 144 145
	int index;

	if (!hash)
		return NULL;

146
	index = batadv_choose_claim(data, hash->size);
147 148 149 150
	head = &hash->table[index];

	rcu_read_lock();
	hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
151
		if (!batadv_compare_claim(&claim->hash_entry, data))
152 153 154 155 156 157 158 159 160 161 162 163 164
			continue;

		if (!atomic_inc_not_zero(&claim->refcount))
			continue;

		claim_tmp = claim;
		break;
	}
	rcu_read_unlock();

	return claim_tmp;
}

165 166 167
/**
 * batadv_backbone_hash_find - looks for a claim in the hash
 * @bat_priv: the bat priv with all the soft interface information
168 169 170
 * @addr: the address of the originator
 * @vid: the VLAN ID
 *
171
 * Returns claim if found or NULL otherwise.
172
 */
173 174 175
static struct batadv_backbone_gw *
batadv_backbone_hash_find(struct batadv_priv *bat_priv,
			  uint8_t *addr, short vid)
176
{
177
	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
178 179
	struct hlist_head *head;
	struct hlist_node *node;
180 181
	struct batadv_backbone_gw search_entry, *backbone_gw;
	struct batadv_backbone_gw *backbone_gw_tmp = NULL;
182 183 184 185 186 187 188 189
	int index;

	if (!hash)
		return NULL;

	memcpy(search_entry.orig, addr, ETH_ALEN);
	search_entry.vid = vid;

190
	index = batadv_choose_backbone_gw(&search_entry, hash->size);
191 192 193 194
	head = &hash->table[index];

	rcu_read_lock();
	hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
195 196
		if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
						&search_entry))
197 198 199 200 201 202 203 204 205 206 207 208 209 210
			continue;

		if (!atomic_inc_not_zero(&backbone_gw->refcount))
			continue;

		backbone_gw_tmp = backbone_gw;
		break;
	}
	rcu_read_unlock();

	return backbone_gw_tmp;
}

/* delete all claims for a backbone */
211 212
static void
batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw)
213
{
214
	struct batadv_hashtable *hash;
215 216
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
217
	struct batadv_claim *claim;
218 219 220
	int i;
	spinlock_t *list_lock;	/* protects write access to the hash lists */

221
	hash = backbone_gw->bat_priv->bla.claim_hash;
222 223 224 225 226 227 228 229 230 231 232 233 234 235
	if (!hash)
		return;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
		list_lock = &hash->list_locks[i];

		spin_lock_bh(list_lock);
		hlist_for_each_entry_safe(claim, node, node_tmp,
					  head, hash_entry) {

			if (claim->backbone_gw != backbone_gw)
				continue;

236
			batadv_claim_free_ref(claim);
237 238 239 240 241 242
			hlist_del_rcu(node);
		}
		spin_unlock_bh(list_lock);
	}

	/* all claims gone, intialize CRC */
243
	backbone_gw->crc = BATADV_BLA_CRC_INIT;
244 245
}

246 247 248
/**
 * batadv_bla_send_claim - sends a claim frame according to the provided info
 * @bat_priv: the bat priv with all the soft interface information
249 250 251 252
 * @orig: the mac address to be announced within the claim
 * @vid: the VLAN ID
 * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
 */
253
static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
254
				  short vid, int claimtype)
255 256 257
{
	struct sk_buff *skb;
	struct ethhdr *ethhdr;
258
	struct batadv_hard_iface *primary_if;
259 260
	struct net_device *soft_iface;
	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 266 267
	if (!primary_if)
		return;

268
	memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
269
	       sizeof(local_claim_dest));
270 271 272 273 274 275 276 277 278 279 280 281 282 283
	local_claim_dest.type = claimtype;

	soft_iface = primary_if->soft_iface;

	skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
			 /* IP DST: 0.0.0.0 */
			 zeroip,
			 primary_if->soft_iface,
			 /* IP SRC: 0.0.0.0 */
			 zeroip,
			 /* Ethernet DST: Broadcast */
			 NULL,
			 /* Ethernet SRC/HW SRC:  originator mac */
			 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 289 290 291 292 293
			  */
			 (uint8_t *)&local_claim_dest);

	if (!skb)
		goto out;

	ethhdr = (struct ethhdr *)skb->data;
294
	hw_src = (uint8_t *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
295 296 297

	/* now we pretend that the client would have sent this ... */
	switch (claimtype) {
298
	case BATADV_CLAIM_TYPE_CLAIM:
299 300 301 302
		/* normal claim frame
		 * set Ethernet SRC to the clients mac
		 */
		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 308 309 310
		/* unclaim frame
		 * set HW SRC to the clients mac
		 */
		memcpy(hw_src, mac, ETH_ALEN);
311
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
312 313
			   "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
			   vid);
314
		break;
315
	case BATADV_CLAIM_TYPE_ANNOUNCE:
316 317 318 319
		/* announcement frame
		 * set HW SRC to the special mac containg the crc
		 */
		memcpy(hw_src, mac, ETH_ALEN);
320
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
321 322
			   "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
			   ethhdr->h_source, vid);
323
		break;
324
	case BATADV_CLAIM_TYPE_REQUEST:
325
		/* request frame
326 327
		 * set HW SRC and header destination to the receiving backbone
		 * gws mac
328 329 330
		 */
		memcpy(hw_src, mac, ETH_ALEN);
		memcpy(ethhdr->h_dest, mac, ETH_ALEN);
331
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
332 333
			   "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n",
			   ethhdr->h_source, ethhdr->h_dest, vid);
334 335 336 337 338 339 340 341 342
		break;

	}

	if (vid != -1)
		skb = vlan_insert_tag(skb, vid);

	skb_reset_mac_header(skb);
	skb->protocol = eth_type_trans(skb, soft_iface);
343 344 345
	batadv_inc_counter(bat_priv, BATADV_CNT_RX);
	batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
			   skb->len + ETH_HLEN);
346 347 348 349 350
	soft_iface->last_rx = jiffies;

	netif_rx(skb);
out:
	if (primary_if)
351
		batadv_hardif_free_ref(primary_if);
352 353
}

354 355 356
/**
 * batadv_bla_get_backbone_gw
 * @bat_priv: the bat priv with all the soft interface information
357 358 359 360 361 362
 * @orig: the mac address of the originator
 * @vid: the VLAN ID
 *
 * searches for the backbone gw or creates a new one if it could not
 * be found.
 */
363 364 365
static struct batadv_backbone_gw *
batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
			   short vid)
366
{
367 368
	struct batadv_backbone_gw *entry;
	struct batadv_orig_node *orig_node;
369 370
	int hash_added;

371
	entry = batadv_backbone_hash_find(bat_priv, orig, vid);
372 373 374 375

	if (entry)
		return entry;

376
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
377 378
		   "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
		   orig, vid);
379 380 381 382 383 384 385

	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
	if (!entry)
		return NULL;

	entry->vid = vid;
	entry->lasttime = jiffies;
386
	entry->crc = BATADV_BLA_CRC_INIT;
387 388 389 390 391 392 393
	entry->bat_priv = bat_priv;
	atomic_set(&entry->request_sent, 0);
	memcpy(entry->orig, orig, ETH_ALEN);

	/* one for the hash, one for returning */
	atomic_set(&entry->refcount, 2);

394
	hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
395 396 397
				     batadv_compare_backbone_gw,
				     batadv_choose_backbone_gw, entry,
				     &entry->hash_entry);
398 399 400 401 402 403 404

	if (unlikely(hash_added != 0)) {
		/* hash failed, free the structure */
		kfree(entry);
		return NULL;
	}

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 409
		batadv_tt_global_del_orig(bat_priv, orig_node,
					  "became a backbone gateway");
410
		batadv_orig_node_free_ref(orig_node);
411
	}
412 413 414 415 416 417
	return entry;
}

/* update or add the own backbone gw to make sure we announce
 * where we receive other backbone gws
 */
418 419 420 421
static void
batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
				  struct batadv_hard_iface *primary_if,
				  short vid)
422
{
423
	struct batadv_backbone_gw *backbone_gw;
424

425 426 427
	backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
						 primary_if->net_dev->dev_addr,
						 vid);
428 429 430 431
	if (unlikely(!backbone_gw))
		return;

	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 437 438 439 440
 * @vid: the vid where the request came on
 *
 * Repeat all of our own claims, and finally send an ANNOUNCE frame
 * to allow the requester another check if the CRC is correct now.
 */
441 442 443
static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
				      struct batadv_hard_iface *primary_if,
				      short vid)
444 445 446
{
	struct hlist_node *node;
	struct hlist_head *head;
447
	struct batadv_hashtable *hash;
448 449
	struct batadv_claim *claim;
	struct batadv_backbone_gw *backbone_gw;
450 451
	int i;

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 456 457
	backbone_gw = batadv_backbone_hash_find(bat_priv,
						primary_if->net_dev->dev_addr,
						vid);
458 459 460
	if (!backbone_gw)
		return;

461
	hash = bat_priv->bla.claim_hash;
462 463 464 465 466 467 468 469 470
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
			/* only own claims are interesting */
			if (claim->backbone_gw != backbone_gw)
				continue;

471
			batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
472
					      BATADV_CLAIM_TYPE_CLAIM);
473 474 475 476 477
		}
		rcu_read_unlock();
	}

	/* finally, send an announcement frame */
478 479
	batadv_bla_send_announce(bat_priv, backbone_gw);
	batadv_backbone_gw_free_ref(backbone_gw);
480 481
}

482
/* @backbone_gw: the backbone gateway from whom we are out of sync
483 484 485 486 487
 *
 * When the crc is wrong, ask the backbone gateway for a full table update.
 * After the request, it will repeat all of his own claims and finally
 * send an announcement claim with which we can check again.
 */
488
static 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 494
	batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
		   "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 501

	/* no local broadcasts should be sent or received, for now. */
	if (!atomic_read(&backbone_gw->request_sent)) {
502
		atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
503 504 505 506
		atomic_set(&backbone_gw->request_sent, 1);
	}
}

507
/* @bat_priv: the bat priv with all the soft interface information
508 509 510 511 512
 * @backbone_gw: our backbone gateway which should be announced
 *
 * This function sends an announcement. It is called from multiple
 * places.
 */
513 514
static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
				     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 530
/**
 * batadv_bla_add_claim - Adds a claim in the claim hash
 * @bat_priv: the bat priv with all the soft interface information
531 532 533 534
 * @mac: the mac address of the claim
 * @vid: the VLAN ID of the frame
 * @backbone_gw: the backbone gateway which claims it
 */
535 536 537
static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
				 const uint8_t *mac, const short vid,
				 struct batadv_backbone_gw *backbone_gw)
538
{
539 540
	struct batadv_claim *claim;
	struct batadv_claim search_claim;
541 542 543 544
	int hash_added;

	memcpy(search_claim.addr, mac, ETH_ALEN);
	search_claim.vid = vid;
545
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
546 547 548 549 550 551 552 553 554 555 556 557 558

	/* create a new claim entry if it does not exist yet. */
	if (!claim) {
		claim = kzalloc(sizeof(*claim), GFP_ATOMIC);
		if (!claim)
			return;

		memcpy(claim->addr, mac, ETH_ALEN);
		claim->vid = vid;
		claim->lasttime = jiffies;
		claim->backbone_gw = backbone_gw;

		atomic_set(&claim->refcount, 2);
559
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
560 561
			   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
			   mac, vid);
562
		hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
563 564 565
					     batadv_compare_claim,
					     batadv_choose_claim, claim,
					     &claim->hash_entry);
566 567 568 569 570 571 572 573 574 575 576 577

		if (unlikely(hash_added != 0)) {
			/* only local changes happened. */
			kfree(claim);
			return;
		}
	} else {
		claim->lasttime = jiffies;
		if (claim->backbone_gw == backbone_gw)
			/* no need to register a new backbone */
			goto claim_free_ref;

578
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
579 580
			   "bla_add_claim(): changing ownership for %pM, vid %d\n",
			   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 587 588 589 590 591 592 593

	}
	/* set (new) backbone gw */
	atomic_inc(&backbone_gw->refcount);
	claim->backbone_gw = backbone_gw;

	backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
	backbone_gw->lasttime = jiffies;

claim_free_ref:
594
	batadv_claim_free_ref(claim);
595 596 597 598 599
}

/* Delete a claim from the claim hash which has the
 * given mac address and vid.
 */
600 601
static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
				 const uint8_t *mac, const short vid)
602
{
603
	struct batadv_claim search_claim, *claim;
604 605 606

	memcpy(search_claim.addr, mac, ETH_ALEN);
	search_claim.vid = vid;
607
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
608 609 610
	if (!claim)
		return;

611 612
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
		   mac, vid);
613

614
	batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
615 616
			   batadv_choose_claim, claim);
	batadv_claim_free_ref(claim); /* reference from the hash is gone */
617 618 619 620

	claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);

	/* 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 */
625
static int batadv_handle_announce(struct batadv_priv *bat_priv,
626 627
				  uint8_t *an_addr, uint8_t *backbone_addr,
				  short vid)
628
{
629
	struct batadv_backbone_gw *backbone_gw;
630 631
	uint16_t crc;

632
	if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
633 634
		return 0;

635
	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
636 637 638 639 640 641 642

	if (unlikely(!backbone_gw))
		return 1;


	/* handle as ANNOUNCE frame */
	backbone_gw->lasttime = jiffies;
643
	crc = ntohs(*((__be16 *)(&an_addr[4])));
644

645
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
646 647
		   "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %04x\n",
		   vid, backbone_gw->orig, crc);
648 649

	if (backbone_gw->crc != crc) {
650
		batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
651 652 653
			   "handle_announce(): CRC FAILED for %pM/%d (my = %04x, sent = %04x)\n",
			   backbone_gw->orig, backbone_gw->vid,
			   backbone_gw->crc, crc);
654

655
		batadv_bla_send_request(backbone_gw);
656 657 658 659 660
	} else {
		/* if we have sent a request and the crc was OK,
		 * we can allow traffic again.
		 */
		if (atomic_read(&backbone_gw->request_sent)) {
661
			atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
662 663 664 665
			atomic_set(&backbone_gw->request_sent, 0);
		}
	}

666
	batadv_backbone_gw_free_ref(backbone_gw);
667 668 669 670
	return 1;
}

/* check for REQUEST frame, return 1 if handled */
671 672
static int batadv_handle_request(struct batadv_priv *bat_priv,
				 struct batadv_hard_iface *primary_if,
673 674
				 uint8_t *backbone_addr,
				 struct ethhdr *ethhdr, short vid)
675 676
{
	/* check for REQUEST frame */
677
	if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
678 679 680 681 682
		return 0;

	/* sanity check, this should not happen on a normal switch,
	 * we ignore it in this case.
	 */
683
	if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
684 685
		return 1;

686
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
687 688
		   "handle_request(): REQUEST vid %d (sent by %pM)...\n",
		   vid, ethhdr->h_source);
689

690
	batadv_bla_answer_request(bat_priv, primary_if, vid);
691 692 693 694
	return 1;
}

/* check for UNCLAIM frame, return 1 if handled */
695 696
static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
				 struct batadv_hard_iface *primary_if,
697 698
				 uint8_t *backbone_addr,
				 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 704
	if (primary_if && batadv_compare_eth(backbone_addr,
					     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 711 712 713

	if (!backbone_gw)
		return 1;

	/* this must be an UNCLAIM frame */
714
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
715 716
		   "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
		   claim_addr, vid, backbone_gw->orig);
717

718 719
	batadv_bla_del_claim(bat_priv, claim_addr, vid);
	batadv_backbone_gw_free_ref(backbone_gw);
720 721 722 723
	return 1;
}

/* check for CLAIM frame, return 1 if handled */
724 725
static int batadv_handle_claim(struct batadv_priv *bat_priv,
			       struct batadv_hard_iface *primary_if,
726 727
			       uint8_t *backbone_addr, uint8_t *claim_addr,
			       short vid)
728
{
729
	struct batadv_backbone_gw *backbone_gw;
730 731 732

	/* register the gateway if not yet available, and add the claim. */

733
	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
734 735 736 737 738

	if (unlikely(!backbone_gw))
		return 1;

	/* 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 745

	/* TODO: we could call something like tt_local_del() here. */

746
	batadv_backbone_gw_free_ref(backbone_gw);
747 748 749
	return 1;
}

750 751 752
/**
 * batadv_check_claim_group
 * @bat_priv: the bat priv with all the soft interface information
753 754 755 756 757 758 759 760 761 762 763 764 765
 * @hw_src: the Hardware source in the ARP Header
 * @hw_dst: the Hardware destination in the ARP Header
 * @ethhdr: pointer to the Ethernet header of the claim frame
 *
 * checks if it is a claim packet and if its on the same group.
 * This function also applies the group ID of the sender
 * if it is in the same mesh.
 *
 * returns:
 *	2  - if it is a claim packet and on the same group
 *	1  - if is a claim packet from another group
 *	0  - if it is not a claim packet
 */
766 767
static int batadv_check_claim_group(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
768 769
				    uint8_t *hw_src, uint8_t *hw_dst,
				    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 779 780 781 782 783 784 785 786

	/* check if it is a claim packet in general */
	if (memcmp(bla_dst->magic, bla_dst_own->magic,
		   sizeof(bla_dst->magic)) != 0)
		return 0;

	/* if announcement packet, use the source,
	 * otherwise assume it is in the hw_src
	 */
	switch (bla_dst->type) {
787
	case BATADV_CLAIM_TYPE_CLAIM:
788 789
		backbone_addr = hw_src;
		break;
790 791
	case BATADV_CLAIM_TYPE_REQUEST:
	case BATADV_CLAIM_TYPE_ANNOUNCE:
792
	case BATADV_CLAIM_TYPE_UNCLAIM:
793 794 795 796 797 798 799
		backbone_addr = ethhdr->h_source;
		break;
	default:
		return 0;
	}

	/* don't accept claim frames from ourselves */
800
	if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
801 802 803 804 805 806 807
		return 0;

	/* if its already the same group, it is fine. */
	if (bla_dst->group == bla_dst_own->group)
		return 2;

	/* lets see if this originator is in our mesh */
808
	orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
809 810 811 812 813 814 815 816 817

	/* dont accept claims from gateways which are not in
	 * the same mesh or group.
	 */
	if (!orig_node)
		return 1;

	/* if our mesh friends mac is bigger, use it for ourselves. */
	if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) {
818
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
819 820
			   "taking other backbones claim group: %04x\n",
			   ntohs(bla_dst->group));
821 822 823
		bla_dst_own->group = bla_dst->group;
	}

824
	batadv_orig_node_free_ref(orig_node);
825 826 827 828 829

	return 2;
}


830
/* @bat_priv: the bat priv with all the soft interface information
831 832 833 834 835 836 837
 * @skb: the frame to be checked
 *
 * Check if this is a claim frame, and process it accordingly.
 *
 * returns 1 if it was a claim frame, otherwise return 0 to
 * tell the callee that it can use the frame on its own.
 */
838 839
static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
840
				    struct sk_buff *skb)
841 842 843 844 845
{
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
	struct arphdr *arphdr;
	uint8_t *hw_src, *hw_dst;
846
	struct batadv_bla_claim_dst *bla_dst;
847 848 849
	uint16_t proto;
	int headlen;
	short vid = -1;
850
	int ret;
851 852 853 854 855 856 857 858 859 860

	ethhdr = (struct ethhdr *)skb_mac_header(skb);

	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
		vhdr = (struct vlan_ethhdr *)ethhdr;
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
		proto = ntohs(vhdr->h_vlan_encapsulated_proto);
		headlen = sizeof(*vhdr);
	} else {
		proto = ntohs(ethhdr->h_proto);
861
		headlen = ETH_HLEN;
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
	}

	if (proto != ETH_P_ARP)
		return 0; /* not a claim frame */

	/* this must be a ARP frame. check if it is a claim. */

	if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
		return 0;

	/* pskb_may_pull() may have modified the pointers, get ethhdr again */
	ethhdr = (struct ethhdr *)skb_mac_header(skb);
	arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen);

	/* Check whether the ARP frame carries a valid
	 * IP information
	 */
	if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
		return 0;
	if (arphdr->ar_pro != htons(ETH_P_IP))
		return 0;
	if (arphdr->ar_hln != ETH_ALEN)
		return 0;
	if (arphdr->ar_pln != 4)
		return 0;

	hw_src = (uint8_t *)arphdr + sizeof(struct arphdr);
	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 894
	ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
				       ethhdr);
895
	if (ret == 1)
896
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
897 898
			   "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
			   ethhdr->h_source, vid, hw_src, hw_dst);
899 900 901

	if (ret < 2)
		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 907

	/* check for the different types of claim frames ... */
	switch (bla_dst->type) {
908
	case BATADV_CLAIM_TYPE_CLAIM:
909 910
		if (batadv_handle_claim(bat_priv, primary_if, hw_src,
					ethhdr->h_source, vid))
911 912
			return 1;
		break;
913
	case BATADV_CLAIM_TYPE_UNCLAIM:
914 915
		if (batadv_handle_unclaim(bat_priv, primary_if,
					  ethhdr->h_source, hw_src, vid))
916 917 918
			return 1;
		break;

919
	case BATADV_CLAIM_TYPE_ANNOUNCE:
920 921
		if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
					   vid))
922 923
			return 1;
		break;
924
	case BATADV_CLAIM_TYPE_REQUEST:
925 926
		if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
					  vid))
927 928 929 930
			return 1;
		break;
	}

931
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
932 933
		   "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",
		   ethhdr->h_source, vid, hw_src, hw_dst);
934 935 936 937 938 939
	return 1;
}

/* Check when we last heard from other nodes, and remove them in case of
 * a time out, or clean all backbone gws if now is set.
 */
940
static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
941
{
942
	struct batadv_backbone_gw *backbone_gw;
943 944
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
945
	struct batadv_hashtable *hash;
946 947 948
	spinlock_t *list_lock;	/* protects write access to the hash lists */
	int i;

949
	hash = bat_priv->bla.backbone_hash;
950 951 952 953 954 955 956 957 958 959 960 961
	if (!hash)
		return;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
		list_lock = &hash->list_locks[i];

		spin_lock_bh(list_lock);
		hlist_for_each_entry_safe(backbone_gw, node, node_tmp,
					  head, hash_entry) {
			if (now)
				goto purge_now;
962
			if (!batadv_has_timed_out(backbone_gw->lasttime,
963
						  BATADV_BLA_BACKBONE_TIMEOUT))
964 965
				continue;

966
			batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
967 968
				   "bla_purge_backbone_gw(): backbone gw %pM timed out\n",
				   backbone_gw->orig);
969 970 971 972

purge_now:
			/* don't wait for the pending request anymore */
			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 981 982 983
		}
		spin_unlock_bh(list_lock);
	}
}

984 985 986
/**
 * batadv_bla_purge_claims
 * @bat_priv: the bat priv with all the soft interface information
987 988 989 990 991 992
 * @primary_if: the selected primary interface, may be NULL if now is set
 * @now: whether the whole hash shall be wiped now
 *
 * Check when we heard last time from our own claims, and remove them in case of
 * a time out, or clean all claims if now is set
 */
993 994 995
static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
				    int now)
996
{
997
	struct batadv_claim *claim;
998 999
	struct hlist_node *node;
	struct hlist_head *head;
1000
	struct batadv_hashtable *hash;
1001 1002
	int i;

1003
	hash = bat_priv->bla.claim_hash;
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
	if (!hash)
		return;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
			if (now)
				goto purge_now;
1014 1015
			if (!batadv_compare_eth(claim->backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1016
				continue;
1017
			if (!batadv_has_timed_out(claim->lasttime,
1018
						  BATADV_BLA_CLAIM_TIMEOUT))
1019 1020
				continue;

1021
			batadv_dbg(BATADV_DBG_BLA, bat_priv,
1022 1023
				   "bla_purge_claims(): %pM, vid %d, time out\n",
				   claim->addr, claim->vid);
1024 1025

purge_now:
1026 1027 1028
			batadv_handle_unclaim(bat_priv, primary_if,
					      claim->backbone_gw->orig,
					      claim->addr, claim->vid);
1029 1030 1031 1032 1033
		}
		rcu_read_unlock();
	}
}

1034 1035 1036
/**
 * batadv_bla_update_orig_address
 * @bat_priv: the bat priv with all the soft interface information
1037 1038 1039 1040 1041
 * @primary_if: the new selected primary_if
 * @oldif: the old primary interface, may be NULL
 *
 * Update the backbone gateways when the own orig address changes.
 */
1042 1043 1044
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
				    struct batadv_hard_iface *oldif)
1045
{
1046
	struct batadv_backbone_gw *backbone_gw;
1047 1048
	struct hlist_node *node;
	struct hlist_head *head;
1049
	struct batadv_hashtable *hash;
1050
	__be16 group;
1051 1052
	int i;

1053
	/* reset bridge loop avoidance group id */
1054 1055
	group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
	bat_priv->bla.claim_dest.group = group;
1056

1057
	if (!oldif) {
1058 1059
		batadv_bla_purge_claims(bat_priv, NULL, 1);
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1060 1061 1062
		return;
	}

1063
	hash = bat_priv->bla.backbone_hash;
1064 1065 1066 1067 1068 1069 1070 1071 1072
	if (!hash)
		return;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
			/* own orig still holds the old value. */
1073 1074
			if (!batadv_compare_eth(backbone_gw->orig,
						oldif->net_dev->dev_addr))
1075 1076 1077 1078 1079 1080 1081
				continue;

			memcpy(backbone_gw->orig,
			       primary_if->net_dev->dev_addr, ETH_ALEN);
			/* send an announce frame so others will ask for our
			 * claims and update their tables.
			 */
1082
			batadv_bla_send_announce(bat_priv, backbone_gw);
1083 1084 1085 1086 1087 1088 1089 1090
		}
		rcu_read_unlock();
	}
}



/* (re)start the timer */
1091
static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
1092
{
1093 1094
	INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
	queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1095
			   msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
1096 1097 1098 1099 1100 1101
}

/* periodic work to do:
 *  * purge structures when they are too old
 *  * send announcements
 */
1102
static 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 1108
	struct hlist_node *node;
	struct hlist_head *head;
1109
	struct batadv_backbone_gw *backbone_gw;
1110
	struct batadv_hashtable *hash;
1111
	struct batadv_hard_iface *primary_if;
1112 1113
	int i;

1114
	delayed_work = container_of(work, struct delayed_work, work);
1115 1116
	priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
	bat_priv = container_of(priv_bla, struct batadv_priv, bla);
1117
	primary_if = batadv_primary_if_get_selected(bat_priv);
1118 1119 1120
	if (!primary_if)
		goto out;

1121 1122
	batadv_bla_purge_claims(bat_priv, primary_if, 0);
	batadv_bla_purge_backbone_gw(bat_priv, 0);
1123 1124 1125 1126

	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
		goto out;

1127
	hash = bat_priv->bla.backbone_hash;
1128 1129 1130 1131 1132 1133 1134 1135
	if (!hash)
		goto out;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1136 1137
			if (!batadv_compare_eth(backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1138 1139 1140 1141
				continue;

			backbone_gw->lasttime = jiffies;

1142
			batadv_bla_send_announce(bat_priv, backbone_gw);
1143 1144 1145 1146 1147
		}
		rcu_read_unlock();
	}
out:
	if (primary_if)
1148
		batadv_hardif_free_ref(primary_if);
1149

1150
	batadv_bla_start_timer(bat_priv);
1151 1152
}

1153 1154 1155 1156 1157
/* The hash for claim and backbone hash receive the same key because they
 * are getting initialized by hash_new with the same key. Reinitializing
 * them with to different keys to allow nested locking without generating
 * lockdep warnings
 */
1158 1159
static struct lock_class_key batadv_claim_hash_lock_class_key;
static struct lock_class_key batadv_backbone_hash_lock_class_key;
1160

1161
/* initialize all bla structures */
1162
int 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 1168
	uint16_t crc;
	unsigned long entrytime;
1169

1170 1171
	spin_lock_init(&bat_priv->bla.bcast_duplist_lock);

1172
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
1173

1174
	/* setting claim destination address */
1175 1176
	memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
	bat_priv->bla.claim_dest.type = 0;
1177
	primary_if = batadv_primary_if_get_selected(bat_priv);
1178
	if (primary_if) {
1179 1180
		crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
		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 1190
		bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
	bat_priv->bla.bcast_duplist_curr = 0;
1191

1192
	if (bat_priv->bla.claim_hash)
1193
		return 0;
1194

1195 1196
	bat_priv->bla.claim_hash = batadv_hash_new(128);
	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 1214
/**
 * batadv_bla_check_bcast_duplist
 * @bat_priv: the bat priv with all the soft interface information
1215 1216
 * @bcast_packet: encapsulated broadcast frame plus batman header
 * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
1217 1218 1219 1220 1221 1222 1223 1224 1225
 *
 * check if it is on our broadcast list. Another gateway might
 * have sent the same packet because it is connected to the same backbone,
 * so we have to remove this duplicate.
 *
 * This is performed by checking the CRC, which will tell us
 * with a good chance that it is the same packet. If it is furthermore
 * sent by another host, drop it. We allow equal packets from
 * the same host however as this might be intended.
1226
 */
1227
int 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 1233
	uint8_t *content;
	uint16_t crc;
1234
	struct batadv_bcast_duplist_entry *entry;
1235

1236
	length = bcast_packet_len - sizeof(*bcast_packet);
1237 1238 1239 1240 1241 1242
	content = (uint8_t *)bcast_packet;
	content += sizeof(*bcast_packet);

	/* calculate the crc ... */
	crc = crc16(0, content, length);

1243 1244
	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);

1245
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
1246 1247 1248
		curr = (bat_priv->bla.bcast_duplist_curr + i);
		curr %= BATADV_DUPLIST_SIZE;
		entry = &bat_priv->bla.bcast_duplist[curr];
1249 1250 1251 1252

		/* we can stop searching if the entry is too old ;
		 * later entries will be even older
		 */
1253 1254
		if (batadv_has_timed_out(entry->entrytime,
					 BATADV_DUPLIST_TIMEOUT))
1255 1256 1257 1258 1259
			break;

		if (entry->crc != crc)
			continue;

1260
		if (batadv_compare_eth(entry->orig, bcast_packet->orig))
1261 1262 1263 1264 1265
			continue;

		/* this entry seems to match: same crc, not too old,
		 * and from another gw. therefore return 1 to forbid it.
		 */
1266 1267
		ret = 1;
		goto out;
1268
	}
1269 1270 1271
	/* not found, add a new entry (overwrite the oldest entry)
	 * and allow it, its the first occurence.
	 */
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 1276 1277
	entry->crc = crc;
	entry->entrytime = jiffies;
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
1278
	bat_priv->bla.bcast_duplist_curr = curr;
1279

1280 1281 1282 1283
out:
	spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);

	return ret;
1284 1285 1286 1287
}



1288
/* @bat_priv: the bat priv with all the soft interface information
1289 1290 1291 1292 1293 1294
 * @orig: originator mac address
 *
 * check if the originator is a gateway for any VLAN ID.
 *
 * returns 1 if it is found, 0 otherwise
 */
1295
int 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 1299
	struct hlist_head *head;
	struct hlist_node *node;
1300
	struct batadv_backbone_gw *backbone_gw;
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
	int i;

	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
		return 0;

	if (!hash)
		return 0;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1314
			if (batadv_compare_eth(backbone_gw->orig, orig)) {
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
				rcu_read_unlock();
				return 1;
			}
		}
		rcu_read_unlock();
	}

	return 0;
}


1326 1327 1328
/**
 * batadv_bla_is_backbone_gw
 * @skb: the frame to be checked
1329 1330 1331 1332 1333 1334 1335
 * @orig_node: the orig_node of the frame
 * @hdr_size: maximum length of the frame
 *
 * bla_is_backbone_gw inspects the skb for the VLAN ID and returns 1
 * if the orig_node is also a gateway on the soft interface, otherwise it
 * returns 0.
 */
1336
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1337
			      struct batadv_orig_node *orig_node, int hdr_size)
1338 1339 1340
{
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
1341
	struct batadv_backbone_gw *backbone_gw;
1342 1343 1344 1345 1346 1347
	short vid = -1;

	if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
		return 0;

	/* first, find out the vid. */
1348
	if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1349 1350 1351 1352 1353 1354 1355 1356
		return 0;

	ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);

	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
		if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
			return 0;

1357
		vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
1358 1359 1360 1361
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
	}

	/* see if this originator is a backbone gw for this VLAN */
1362 1363
	backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
						orig_node->orig, vid);
1364 1365 1366
	if (!backbone_gw)
		return 0;

1367
	batadv_backbone_gw_free_ref(backbone_gw);
1368 1369 1370 1371
	return 1;
}

/* free all bla structures (for softinterface free or module unload) */
1372
void 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 1382
		batadv_hash_destroy(bat_priv->bla.claim_hash);
		bat_priv->bla.claim_hash = NULL;
1383
	}
1384
	if (bat_priv->bla.backbone_hash) {
1385
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1386 1387
		batadv_hash_destroy(bat_priv->bla.backbone_hash);
		bat_priv->bla.backbone_hash = NULL;
1388 1389
	}
	if (primary_if)
1390
		batadv_hardif_free_ref(primary_if);
1391 1392
}

1393 1394 1395
/**
 * batadv_bla_rx
 * @bat_priv: the bat priv with all the soft interface information
1396 1397
 * @skb: the frame to be checked
 * @vid: the VLAN ID of the frame
1398
 * @is_bcast: the packet came in a broadcast packet type.
1399 1400 1401 1402 1403 1404 1405 1406 1407
 *
 * bla_rx avoidance checks if:
 *  * we have to race for a claim
 *  * if the frame is allowed on the LAN
 *
 * in these cases, the skb is further handled by this function and
 * returns 1, otherwise it returns 0 and the caller shall further
 * process the skb.
 */
1408 1409
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
		  bool is_bcast)
1410 1411
{
	struct ethhdr *ethhdr;
1412 1413
	struct batadv_claim search_claim, *claim = NULL;
	struct batadv_hard_iface *primary_if;
1414 1415 1416 1417
	int ret;

	ethhdr = (struct ethhdr *)skb_mac_header(skb);

1418
	primary_if = batadv_primary_if_get_selected(bat_priv);
1419 1420 1421 1422 1423 1424 1425
	if (!primary_if)
		goto handled;

	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
		goto allow;


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 1430 1431 1432
			goto handled;

	memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
	search_claim.vid = vid;
1433
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1434 1435 1436 1437 1438

	if (!claim) {
		/* possible optimization: race for a claim */
		/* No claim exists yet, claim it for us!
		 */
1439 1440 1441
		batadv_handle_claim(bat_priv, primary_if,
				    primary_if->net_dev->dev_addr,
				    ethhdr->h_source, vid);
1442 1443 1444 1445
		goto allow;
	}

	/* if it is our own claim ... */
1446 1447
	if (batadv_compare_eth(claim->backbone_gw->orig,
			       primary_if->net_dev->dev_addr)) {
1448 1449 1450 1451 1452 1453
		/* ... allow it in any case */
		claim->lasttime = jiffies;
		goto allow;
	}

	/* if it is a broadcast ... */
1454 1455 1456 1457 1458 1459 1460
	if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
		/* ... drop it. the responsible gateway is in charge.
		 *
		 * We need to check is_bcast because with the gateway
		 * feature, broadcasts (like DHCP requests) may be sent
		 * using a unicast packet type.
		 */
1461 1462 1463 1464 1465 1466
		goto handled;
	} else {
		/* seems the client considers us as its best gateway.
		 * send a claim and update the claim table
		 * immediately.
		 */
1467 1468 1469
		batadv_handle_claim(bat_priv, primary_if,
				    primary_if->net_dev->dev_addr,
				    ethhdr->h_source, vid);
1470 1471 1472
		goto allow;
	}
allow:
1473
	batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1474 1475 1476 1477 1478 1479 1480 1481 1482
	ret = 0;
	goto out;

handled:
	kfree_skb(skb);
	ret = 1;

out:
	if (primary_if)
1483
		batadv_hardif_free_ref(primary_if);
1484
	if (claim)
1485
		batadv_claim_free_ref(claim);
1486 1487 1488
	return ret;
}

1489 1490 1491
/**
 * batadv_bla_tx
 * @bat_priv: the bat priv with all the soft interface information
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
 * @skb: the frame to be checked
 * @vid: the VLAN ID of the frame
 *
 * bla_tx checks if:
 *  * a claim was received which has to be processed
 *  * the frame is allowed on the mesh
 *
 * in these cases, the skb is further handled by this function and
 * returns 1, otherwise it returns 0 and the caller shall further
 * process the skb.
 */
1503
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
1504 1505
{
	struct ethhdr *ethhdr;
1506 1507
	struct batadv_claim search_claim, *claim = NULL;
	struct batadv_hard_iface *primary_if;
1508 1509
	int ret = 0;

1510
	primary_if = batadv_primary_if_get_selected(bat_priv);
1511 1512 1513 1514 1515 1516 1517 1518 1519
	if (!primary_if)
		goto out;

	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
		goto allow;

	/* in VLAN case, the mac header might not be set. */
	skb_reset_mac_header(skb);

1520
	if (batadv_bla_process_claim(bat_priv, primary_if, skb))
1521 1522 1523 1524
		goto handled;

	ethhdr = (struct ethhdr *)skb_mac_header(skb);

1525
	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1526 1527 1528 1529 1530 1531 1532
		/* don't allow broadcasts while requests are in flight */
		if (is_multicast_ether_addr(ethhdr->h_dest))
			goto handled;

	memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
	search_claim.vid = vid;

1533
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1534 1535 1536 1537 1538 1539

	/* if no claim exists, allow it. */
	if (!claim)
		goto allow;

	/* check if we are responsible. */
1540 1541
	if (batadv_compare_eth(claim->backbone_gw->orig,
			       primary_if->net_dev->dev_addr)) {
1542 1543 1544
		/* if yes, the client has roamed and we have
		 * to unclaim it.
		 */
1545 1546 1547
		batadv_handle_unclaim(bat_priv, primary_if,
				      primary_if->net_dev->dev_addr,
				      ethhdr->h_source, vid);
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
		goto allow;
	}

	/* check if it is a multicast/broadcast frame */
	if (is_multicast_ether_addr(ethhdr->h_dest)) {
		/* drop it. the responsible gateway has forwarded it into
		 * the backbone network.
		 */
		goto handled;
	} else {
		/* we must allow it. at least if we are
		 * responsible for the DESTINATION.
		 */
		goto allow;
	}
allow:
1564
	batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1565 1566 1567 1568 1569 1570
	ret = 0;
	goto out;
handled:
	ret = 1;
out:
	if (primary_if)
1571
		batadv_hardif_free_ref(primary_if);
1572
	if (claim)
1573
		batadv_claim_free_ref(claim);
1574 1575
	return ret;
}
1576

1577
int 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 1583
	struct batadv_claim *claim;
	struct batadv_hard_iface *primary_if;
1584 1585 1586 1587 1588
	struct hlist_node *node;
	struct hlist_head *head;
	uint32_t i;
	bool is_own;
	int ret = 0;
1589
	uint8_t *primary_addr;
1590

1591
	primary_if = batadv_primary_if_get_selected(bat_priv);
1592 1593 1594 1595 1596 1597 1598
	if (!primary_if) {
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
				 net_dev->name);
		goto out;
	}

1599
	if (primary_if->if_status != BATADV_IF_ACTIVE) {
1600 1601 1602 1603 1604 1605
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - primary interface not active\n",
				 net_dev->name);
		goto out;
	}

1606
	primary_addr = primary_if->net_dev->dev_addr;
1607 1608
	seq_printf(seq,
		   "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 1612 1613 1614 1615 1616 1617
	seq_printf(seq, "   %-17s    %-5s    %-17s [o] (%-4s)\n",
		   "Client", "VID", "Originator", "CRC");
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
1618 1619
			is_own = batadv_compare_eth(claim->backbone_gw->orig,
						    primary_addr);
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
			seq_printf(seq,	" * %pM on % 5d by %pM [%c] (%04x)\n",
				   claim->addr, claim->vid,
				   claim->backbone_gw->orig,
				   (is_own ? 'x' : ' '),
				   claim->backbone_gw->crc);
		}
		rcu_read_unlock();
	}
out:
	if (primary_if)
1630
		batadv_hardif_free_ref(primary_if);
1631 1632
	return ret;
}
1633 1634 1635 1636 1637

int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
{
	struct net_device *net_dev = (struct net_device *)seq->private;
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
1638
	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667
	struct batadv_backbone_gw *backbone_gw;
	struct batadv_hard_iface *primary_if;
	struct hlist_node *node;
	struct hlist_head *head;
	int secs, msecs;
	uint32_t i;
	bool is_own;
	int ret = 0;
	uint8_t *primary_addr;

	primary_if = batadv_primary_if_get_selected(bat_priv);
	if (!primary_if) {
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
				 net_dev->name);
		goto out;
	}

	if (primary_if->if_status != BATADV_IF_ACTIVE) {
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - primary interface not active\n",
				 net_dev->name);
		goto out;
	}

	primary_addr = primary_if->net_dev->dev_addr;
	seq_printf(seq,
		   "Backbones announced for the mesh %s (orig %pM, group id %04x)\n",
		   net_dev->name, primary_addr,
1668
		   ntohs(bat_priv->bla.claim_dest.group));
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
	seq_printf(seq, "   %-17s    %-5s %-9s (%-4s)\n",
		   "Originator", "VID", "last seen", "CRC");
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
		hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
			msecs = jiffies_to_msecs(jiffies -
						 backbone_gw->lasttime);
			secs = msecs / 1000;
			msecs = msecs % 1000;

			is_own = batadv_compare_eth(backbone_gw->orig,
						    primary_addr);
			if (is_own)
				continue;

			seq_printf(seq,
				   " * %pM on % 5d % 4i.%03is (%04x)\n",
				   backbone_gw->orig, backbone_gw->vid,
				   secs, msecs, backbone_gw->crc);
		}
		rcu_read_unlock();
	}
out:
	if (primary_if)
		batadv_hardif_free_ref(primary_if);
	return ret;
}