bridge_loop_avoidance.c 45.3 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->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->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 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
	int i;
	spinlock_t *list_lock;	/* protects write access to the hash lists */

	hash = backbone_gw->bat_priv->claim_hash;
	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 269
	memcpy(&local_claim_dest, &bat_priv->claim_dest,
	       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_ADD:
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_DEL:
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 343
		break;

	}

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

	skb_reset_mac_header(skb);
	skb->protocol = eth_type_trans(skb, soft_iface);
	bat_priv->stats.rx_packets++;
344
	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
345 346 347 348 349
	soft_iface->last_rx = jiffies;

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

353 354 355
/**
 * batadv_bla_get_backbone_gw
 * @bat_priv: the bat priv with all the soft interface information
356 357 358 359 360 361
 * @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.
 */
362 363 364
static struct batadv_backbone_gw *
batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
			   short vid)
365
{
366 367
	struct batadv_backbone_gw *entry;
	struct batadv_orig_node *orig_node;
368 369
	int hash_added;

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

	if (entry)
		return entry;

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

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

	entry->vid = vid;
	entry->lasttime = jiffies;
385
	entry->crc = BATADV_BLA_CRC_INIT;
386 387 388 389 390 391 392
	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);

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

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

404
	/* this is a gateway now, remove any tt entries */
405
	orig_node = batadv_orig_hash_find(bat_priv, orig);
406
	if (orig_node) {
407 408
		batadv_tt_global_del_orig(bat_priv, orig_node,
					  "became a backbone gateway");
409
		batadv_orig_node_free_ref(orig_node);
410
	}
411 412 413 414 415 416
	return entry;
}

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

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

	backbone_gw->lasttime = jiffies;
431
	batadv_backbone_gw_free_ref(backbone_gw);
432 433
}

434
/* @bat_priv: the bat priv with all the soft interface information
435 436 437 438 439
 * @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.
 */
440 441 442
static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
				      struct batadv_hard_iface *primary_if,
				      short vid)
443 444 445
{
	struct hlist_node *node;
	struct hlist_head *head;
446
	struct batadv_hashtable *hash;
447 448
	struct batadv_claim *claim;
	struct batadv_backbone_gw *backbone_gw;
449 450
	int i;

451
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
452
		   "bla_answer_request(): received a claim request, send all of our own claims again\n");
453

454 455 456
	backbone_gw = batadv_backbone_hash_find(bat_priv,
						primary_if->net_dev->dev_addr,
						vid);
457 458 459 460 461 462 463 464 465 466 467 468 469
	if (!backbone_gw)
		return;

	hash = bat_priv->claim_hash;
	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;

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

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

481
/* @backbone_gw: the backbone gateway from whom we are out of sync
482 483 484 485 486
 *
 * 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.
 */
487
static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw)
488 489
{
	/* first, remove all old entries */
490
	batadv_bla_del_backbone_claims(backbone_gw);
491

492 493
	batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
		   "Sending REQUEST to %pM\n", backbone_gw->orig);
494 495

	/* send request */
496
	batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
497
			      backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
498 499 500 501 502 503 504 505

	/* no local broadcasts should be sent or received, for now. */
	if (!atomic_read(&backbone_gw->request_sent)) {
		atomic_inc(&backbone_gw->bat_priv->bla_num_requests);
		atomic_set(&backbone_gw->request_sent, 1);
	}
}

506
/* @bat_priv: the bat priv with all the soft interface information
507 508 509 510 511
 * @backbone_gw: our backbone gateway which should be announced
 *
 * This function sends an announcement. It is called from multiple
 * places.
 */
512 513
static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
				     struct batadv_backbone_gw *backbone_gw)
514 515
{
	uint8_t mac[ETH_ALEN];
516
	__be16 crc;
517

518
	memcpy(mac, batadv_announce_mac, 4);
519
	crc = htons(backbone_gw->crc);
520
	memcpy(&mac[4], &crc, 2);
521

522
	batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
523
			      BATADV_CLAIM_TYPE_ANNOUNCE);
524 525 526

}

527 528 529
/**
 * batadv_bla_add_claim - Adds a claim in the claim hash
 * @bat_priv: the bat priv with all the soft interface information
530 531 532 533
 * @mac: the mac address of the claim
 * @vid: the VLAN ID of the frame
 * @backbone_gw: the backbone gateway which claims it
 */
534 535 536
static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
				 const uint8_t *mac, const short vid,
				 struct batadv_backbone_gw *backbone_gw)
537
{
538 539
	struct batadv_claim *claim;
	struct batadv_claim search_claim;
540 541 542 543
	int hash_added;

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

	/* 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);
558
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
559 560
			   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
			   mac, vid);
561
		hash_added = batadv_hash_add(bat_priv->claim_hash,
562 563 564
					     batadv_compare_claim,
					     batadv_choose_claim, claim,
					     &claim->hash_entry);
565 566 567 568 569 570 571 572 573 574 575 576

		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;

577
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
578 579
			   "bla_add_claim(): changing ownership for %pM, vid %d\n",
			   mac, vid);
580 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 615 616
	batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim,
			   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 661 662 663 664 665
	} else {
		/* if we have sent a request and the crc was OK,
		 * we can allow traffic again.
		 */
		if (atomic_read(&backbone_gw->request_sent)) {
			atomic_dec(&backbone_gw->bat_priv->bla_num_requests);
			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_DEL);
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_ADD);
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 777 778 779 780 781 782 783 784 785 786
	bla_dst_own = &bat_priv->claim_dest;

	/* 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_ADD:
788 789
		backbone_addr = hw_src;
		break;
790 791 792
	case BATADV_CLAIM_TYPE_REQUEST:
	case BATADV_CLAIM_TYPE_ANNOUNCE:
	case BATADV_CLAIM_TYPE_DEL:
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_ADD:
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_DEL:
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 949 950 951 952 953 954 955 956 957 958 959 960 961
	spinlock_t *list_lock;	/* protects write access to the hash lists */
	int i;

	hash = bat_priv->backbone_hash;
	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 973 974

purge_now:
			/* don't wait for the pending request anymore */
			if (atomic_read(&backbone_gw->request_sent))
				atomic_dec(&bat_priv->bla_num_requests);

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 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
	int i;

	hash = bat_priv->claim_hash;
	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 1051
	int i;

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

1056
	if (!oldif) {
1057 1058
		batadv_bla_purge_claims(bat_priv, NULL, 1);
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
		return;
	}

	hash = bat_priv->backbone_hash;
	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. */
1072 1073
			if (!batadv_compare_eth(backbone_gw->orig,
						oldif->net_dev->dev_addr))
1074 1075 1076 1077 1078 1079 1080
				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.
			 */
1081
			batadv_bla_send_announce(bat_priv, backbone_gw);
1082 1083 1084 1085 1086 1087 1088 1089
		}
		rcu_read_unlock();
	}
}



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

/* periodic work to do:
 *  * purge structures when they are too old
 *  * send announcements
 */
1101
static void batadv_bla_periodic_work(struct work_struct *work)
1102 1103 1104
{
	struct delayed_work *delayed_work =
		container_of(work, struct delayed_work, work);
1105
	struct batadv_priv *bat_priv;
1106 1107
	struct hlist_node *node;
	struct hlist_head *head;
1108
	struct batadv_backbone_gw *backbone_gw;
1109
	struct batadv_hashtable *hash;
1110
	struct batadv_hard_iface *primary_if;
1111 1112
	int i;

1113
	bat_priv = container_of(delayed_work, struct batadv_priv, bla_work);
1114
	primary_if = batadv_primary_if_get_selected(bat_priv);
1115 1116 1117
	if (!primary_if)
		goto out;

1118 1119
	batadv_bla_purge_claims(bat_priv, primary_if, 0);
	batadv_bla_purge_backbone_gw(bat_priv, 0);
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132

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

	hash = bat_priv->backbone_hash;
	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) {
1133 1134
			if (!batadv_compare_eth(backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1135 1136 1137 1138
				continue;

			backbone_gw->lasttime = jiffies;

1139
			batadv_bla_send_announce(bat_priv, backbone_gw);
1140 1141 1142 1143 1144
		}
		rcu_read_unlock();
	}
out:
	if (primary_if)
1145
		batadv_hardif_free_ref(primary_if);
1146

1147
	batadv_bla_start_timer(bat_priv);
1148 1149
}

1150 1151 1152 1153 1154
/* 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
 */
1155 1156
static struct lock_class_key batadv_claim_hash_lock_class_key;
static struct lock_class_key batadv_backbone_hash_lock_class_key;
1157

1158
/* initialize all bla structures */
1159
int batadv_bla_init(struct batadv_priv *bat_priv)
1160
{
1161
	int i;
1162
	uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
1163
	struct batadv_hard_iface *primary_if;
1164

1165
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
1166

1167 1168 1169
	/* setting claim destination address */
	memcpy(&bat_priv->claim_dest.magic, claim_dest, 3);
	bat_priv->claim_dest.type = 0;
1170
	primary_if = batadv_primary_if_get_selected(bat_priv);
1171 1172 1173 1174
	if (primary_if) {
		bat_priv->claim_dest.group =
			htons(crc16(0, primary_if->net_dev->dev_addr,
				    ETH_ALEN));
1175
		batadv_hardif_free_ref(primary_if);
1176 1177 1178 1179
	} else {
		bat_priv->claim_dest.group = 0; /* will be set later */
	}

1180
	/* initialize the duplicate list */
1181
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
1182
		bat_priv->bcast_duplist[i].entrytime =
1183
			jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
1184 1185
	bat_priv->bcast_duplist_curr = 0;

1186
	if (bat_priv->claim_hash)
1187
		return 0;
1188

1189 1190
	bat_priv->claim_hash = batadv_hash_new(128);
	bat_priv->backbone_hash = batadv_hash_new(32);
1191 1192

	if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
1193
		return -ENOMEM;
1194

1195
	batadv_hash_set_lock_class(bat_priv->claim_hash,
1196
				   &batadv_claim_hash_lock_class_key);
1197
	batadv_hash_set_lock_class(bat_priv->backbone_hash,
1198
				   &batadv_backbone_hash_lock_class_key);
1199

1200
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
1201

1202
	batadv_bla_start_timer(bat_priv);
1203
	return 0;
1204 1205
}

1206 1207 1208
/**
 * batadv_bla_check_bcast_duplist
 * @bat_priv: the bat priv with all the soft interface information
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
 * @bcast_packet: originator mac address
 * @hdr_size: maximum length of the frame
 *
 * 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.
1220
 */
1221
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
1222
				   struct batadv_bcast_packet *bcast_packet,
1223
				   int hdr_size)
1224 1225 1226 1227
{
	int i, length, curr;
	uint8_t *content;
	uint16_t crc;
1228
	struct batadv_bcast_duplist_entry *entry;
1229 1230 1231 1232 1233 1234 1235 1236

	length = hdr_size - sizeof(*bcast_packet);
	content = (uint8_t *)bcast_packet;
	content += sizeof(*bcast_packet);

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

1237 1238
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
		curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE;
1239 1240 1241 1242 1243
		entry = &bat_priv->bcast_duplist[curr];

		/* we can stop searching if the entry is too old ;
		 * later entries will be even older
		 */
1244 1245
		if (batadv_has_timed_out(entry->entrytime,
					 BATADV_DUPLIST_TIMEOUT))
1246 1247 1248 1249 1250
			break;

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

1251
		if (batadv_compare_eth(entry->orig, bcast_packet->orig))
1252 1253 1254 1255 1256 1257 1258 1259
			continue;

		/* this entry seems to match: same crc, not too old,
		 * and from another gw. therefore return 1 to forbid it.
		 */
		return 1;
	}
	/* not found, add a new entry (overwrite the oldest entry) */
1260 1261
	curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
	curr %= BATADV_DUPLIST_SIZE;
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
	entry = &bat_priv->bcast_duplist[curr];
	entry->crc = crc;
	entry->entrytime = jiffies;
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
	bat_priv->bcast_duplist_curr = curr;

	/* allow it, its the first occurence. */
	return 0;
}



1274
/* @bat_priv: the bat priv with all the soft interface information
1275 1276 1277 1278 1279 1280
 * @orig: originator mac address
 *
 * check if the originator is a gateway for any VLAN ID.
 *
 * returns 1 if it is found, 0 otherwise
 */
1281
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
1282
{
1283
	struct batadv_hashtable *hash = bat_priv->backbone_hash;
1284 1285
	struct hlist_head *head;
	struct hlist_node *node;
1286
	struct batadv_backbone_gw *backbone_gw;
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
	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) {
1300
			if (batadv_compare_eth(backbone_gw->orig, orig)) {
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
				rcu_read_unlock();
				return 1;
			}
		}
		rcu_read_unlock();
	}

	return 0;
}


1312 1313 1314
/**
 * batadv_bla_is_backbone_gw
 * @skb: the frame to be checked
1315 1316 1317 1318 1319 1320 1321
 * @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.
 */
1322
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1323
			      struct batadv_orig_node *orig_node, int hdr_size)
1324 1325 1326
{
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
1327
	struct batadv_backbone_gw *backbone_gw;
1328 1329 1330 1331 1332 1333
	short vid = -1;

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

	/* first, find out the vid. */
1334
	if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
		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;

		vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) +
					      hdr_size);
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
	}

	/* see if this originator is a backbone gw for this VLAN */
1349 1350
	backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
						orig_node->orig, vid);
1351 1352 1353
	if (!backbone_gw)
		return 0;

1354
	batadv_backbone_gw_free_ref(backbone_gw);
1355 1356 1357 1358
	return 1;
}

/* free all bla structures (for softinterface free or module unload) */
1359
void batadv_bla_free(struct batadv_priv *bat_priv)
1360
{
1361
	struct batadv_hard_iface *primary_if;
1362 1363

	cancel_delayed_work_sync(&bat_priv->bla_work);
1364
	primary_if = batadv_primary_if_get_selected(bat_priv);
1365 1366

	if (bat_priv->claim_hash) {
1367
		batadv_bla_purge_claims(bat_priv, primary_if, 1);
1368
		batadv_hash_destroy(bat_priv->claim_hash);
1369 1370 1371
		bat_priv->claim_hash = NULL;
	}
	if (bat_priv->backbone_hash) {
1372
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1373
		batadv_hash_destroy(bat_priv->backbone_hash);
1374 1375 1376
		bat_priv->backbone_hash = NULL;
	}
	if (primary_if)
1377
		batadv_hardif_free_ref(primary_if);
1378 1379
}

1380 1381 1382
/**
 * batadv_bla_rx
 * @bat_priv: the bat priv with all the soft interface information
1383 1384
 * @skb: the frame to be checked
 * @vid: the VLAN ID of the frame
1385
 * @is_bcast: the packet came in a broadcast packet type.
1386 1387 1388 1389 1390 1391 1392 1393 1394
 *
 * 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.
 */
1395 1396
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
		  bool is_bcast)
1397 1398
{
	struct ethhdr *ethhdr;
1399 1400
	struct batadv_claim search_claim, *claim = NULL;
	struct batadv_hard_iface *primary_if;
1401 1402 1403 1404
	int ret;

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

1405
	primary_if = batadv_primary_if_get_selected(bat_priv);
1406 1407 1408 1409 1410 1411 1412 1413 1414
	if (!primary_if)
		goto handled;

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


	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
		/* don't allow broadcasts while requests are in flight */
1415
		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
1416 1417 1418 1419
			goto handled;

	memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
	search_claim.vid = vid;
1420
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1421 1422 1423 1424 1425

	if (!claim) {
		/* possible optimization: race for a claim */
		/* No claim exists yet, claim it for us!
		 */
1426 1427 1428
		batadv_handle_claim(bat_priv, primary_if,
				    primary_if->net_dev->dev_addr,
				    ethhdr->h_source, vid);
1429 1430 1431 1432
		goto allow;
	}

	/* if it is our own claim ... */
1433 1434
	if (batadv_compare_eth(claim->backbone_gw->orig,
			       primary_if->net_dev->dev_addr)) {
1435 1436 1437 1438 1439 1440
		/* ... allow it in any case */
		claim->lasttime = jiffies;
		goto allow;
	}

	/* if it is a broadcast ... */
1441 1442 1443 1444 1445 1446 1447
	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.
		 */
1448 1449 1450 1451 1452 1453
		goto handled;
	} else {
		/* seems the client considers us as its best gateway.
		 * send a claim and update the claim table
		 * immediately.
		 */
1454 1455 1456
		batadv_handle_claim(bat_priv, primary_if,
				    primary_if->net_dev->dev_addr,
				    ethhdr->h_source, vid);
1457 1458 1459
		goto allow;
	}
allow:
1460
	batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1461 1462 1463 1464 1465 1466 1467 1468 1469
	ret = 0;
	goto out;

handled:
	kfree_skb(skb);
	ret = 1;

out:
	if (primary_if)
1470
		batadv_hardif_free_ref(primary_if);
1471
	if (claim)
1472
		batadv_claim_free_ref(claim);
1473 1474 1475
	return ret;
}

1476 1477 1478
/**
 * batadv_bla_tx
 * @bat_priv: the bat priv with all the soft interface information
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489
 * @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.
 */
1490
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
1491 1492
{
	struct ethhdr *ethhdr;
1493 1494
	struct batadv_claim search_claim, *claim = NULL;
	struct batadv_hard_iface *primary_if;
1495 1496
	int ret = 0;

1497
	primary_if = batadv_primary_if_get_selected(bat_priv);
1498 1499 1500 1501 1502 1503 1504 1505 1506
	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);

1507
	if (batadv_bla_process_claim(bat_priv, primary_if, skb))
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
		goto handled;

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

	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
		/* 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;

1520
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1521 1522 1523 1524 1525 1526

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

	/* check if we are responsible. */
1527 1528
	if (batadv_compare_eth(claim->backbone_gw->orig,
			       primary_if->net_dev->dev_addr)) {
1529 1530 1531
		/* if yes, the client has roamed and we have
		 * to unclaim it.
		 */
1532 1533 1534
		batadv_handle_unclaim(bat_priv, primary_if,
				      primary_if->net_dev->dev_addr,
				      ethhdr->h_source, vid);
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
		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:
1551
	batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
1552 1553 1554 1555 1556 1557
	ret = 0;
	goto out;
handled:
	ret = 1;
out:
	if (primary_if)
1558
		batadv_hardif_free_ref(primary_if);
1559
	if (claim)
1560
		batadv_claim_free_ref(claim);
1561 1562
	return ret;
}
1563

1564
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
1565 1566
{
	struct net_device *net_dev = (struct net_device *)seq->private;
1567
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
1568
	struct batadv_hashtable *hash = bat_priv->claim_hash;
1569 1570
	struct batadv_claim *claim;
	struct batadv_hard_iface *primary_if;
1571 1572 1573 1574 1575
	struct hlist_node *node;
	struct hlist_head *head;
	uint32_t i;
	bool is_own;
	int ret = 0;
1576
	uint8_t *primary_addr;
1577

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

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

1593
	primary_addr = primary_if->net_dev->dev_addr;
1594 1595
	seq_printf(seq,
		   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
1596
		   net_dev->name, primary_addr,
1597
		   ntohs(bat_priv->claim_dest.group));
1598 1599 1600 1601 1602 1603 1604
	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) {
1605 1606
			is_own = batadv_compare_eth(claim->backbone_gw->orig,
						    primary_addr);
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616
			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)
1617
		batadv_hardif_free_ref(primary_if);
1618 1619
	return ret;
}
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 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 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684

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);
	struct batadv_hashtable *hash = bat_priv->backbone_hash;
	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,
		   ntohs(bat_priv->claim_dest.group));
	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;
}