bridge_loop_avoidance.c 45.7 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 583

		claim->backbone_gw->crc ^=
			crc16(0, claim->addr, ETH_ALEN);
584
		batadv_backbone_gw_free_ref(claim->backbone_gw);
585 586 587 588 589 590 591 592 593 594

	}
	/* 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:
595
	batadv_claim_free_ref(claim);
596 597 598 599 600
}

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

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

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

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

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

	/* don't need the reference from hash_find() anymore */
622
	batadv_claim_free_ref(claim);
623 624 625
}

/* check for ANNOUNCE frame, return 1 if handled */
626
static int batadv_handle_announce(struct batadv_priv *bat_priv,
627 628
				  uint8_t *an_addr, uint8_t *backbone_addr,
				  short vid)
629
{
630
	struct batadv_backbone_gw *backbone_gw;
631 632
	uint16_t crc;

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

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

	if (unlikely(!backbone_gw))
		return 1;


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

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

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

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

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

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

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

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

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

/* check for UNCLAIM frame, return 1 if handled */
696 697
static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
				 struct batadv_hard_iface *primary_if,
698 699
				 uint8_t *backbone_addr,
				 uint8_t *claim_addr, short vid)
700
{
701
	struct batadv_backbone_gw *backbone_gw;
702 703

	/* unclaim in any case if it is our own */
704 705
	if (primary_if && batadv_compare_eth(backbone_addr,
					     primary_if->net_dev->dev_addr))
706
		batadv_bla_send_claim(bat_priv, claim_addr, vid,
707
				      BATADV_CLAIM_TYPE_UNCLAIM);
708

709
	backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
710 711 712 713 714

	if (!backbone_gw)
		return 1;

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

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

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

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

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

	if (unlikely(!backbone_gw))
		return 1;

	/* this must be a CLAIM frame */
740
	batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
741
	if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
742
		batadv_bla_send_claim(bat_priv, claim_addr, vid,
743
				      BATADV_CLAIM_TYPE_CLAIM);
744 745 746

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

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

751 752 753
/**
 * batadv_check_claim_group
 * @bat_priv: the bat priv with all the soft interface information
754 755 756 757 758 759 760 761 762 763 764 765 766
 * @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
 */
767 768
static int batadv_check_claim_group(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
769 770
				    uint8_t *hw_src, uint8_t *hw_dst,
				    struct ethhdr *ethhdr)
771 772
{
	uint8_t *backbone_addr;
773
	struct batadv_orig_node *orig_node;
774
	struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
775

776
	bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
777
	bla_dst_own = &bat_priv->bla.claim_dest;
778 779 780 781 782 783 784 785 786 787

	/* 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) {
788
	case BATADV_CLAIM_TYPE_CLAIM:
789 790
		backbone_addr = hw_src;
		break;
791 792
	case BATADV_CLAIM_TYPE_REQUEST:
	case BATADV_CLAIM_TYPE_ANNOUNCE:
793
	case BATADV_CLAIM_TYPE_UNCLAIM:
794 795 796 797 798 799 800
		backbone_addr = ethhdr->h_source;
		break;
	default:
		return 0;
	}

	/* don't accept claim frames from ourselves */
801
	if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
802 803 804 805 806 807 808
		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 */
809
	orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
810 811 812 813 814 815 816 817 818

	/* 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)) {
819
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
820 821
			   "taking other backbones claim group: %04x\n",
			   ntohs(bla_dst->group));
822 823 824
		bla_dst_own->group = bla_dst->group;
	}

825
	batadv_orig_node_free_ref(orig_node);
826 827 828 829 830

	return 2;
}


831
/* @bat_priv: the bat priv with all the soft interface information
832 833 834 835 836 837 838
 * @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.
 */
839 840
static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
841
				    struct sk_buff *skb)
842 843 844 845 846
{
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
	struct arphdr *arphdr;
	uint8_t *hw_src, *hw_dst;
847
	struct batadv_bla_claim_dst *bla_dst;
848 849 850
	uint16_t proto;
	int headlen;
	short vid = -1;
851
	int ret;
852 853 854 855 856 857 858 859 860 861

	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);
862
		headlen = ETH_HLEN;
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 890
	}

	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;
891
	bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
892 893

	/* check if it is a claim frame. */
894 895
	ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
				       ethhdr);
896
	if (ret == 1)
897
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
898 899
			   "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);
900 901 902

	if (ret < 2)
		return ret;
903 904

	/* become a backbone gw ourselves on this vlan if not happened yet */
905
	batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
906 907 908

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

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

932
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
933 934
		   "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);
935 936 937 938 939 940
	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.
 */
941
static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
942
{
943
	struct batadv_backbone_gw *backbone_gw;
944 945
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
946
	struct batadv_hashtable *hash;
947 948 949
	spinlock_t *list_lock;	/* protects write access to the hash lists */
	int i;

950
	hash = bat_priv->bla.backbone_hash;
951 952 953 954 955 956 957 958 959 960 961 962
	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;
963
			if (!batadv_has_timed_out(backbone_gw->lasttime,
964
						  BATADV_BLA_BACKBONE_TIMEOUT))
965 966
				continue;

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

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

976
			batadv_bla_del_backbone_claims(backbone_gw);
977 978

			hlist_del_rcu(node);
979
			batadv_backbone_gw_free_ref(backbone_gw);
980 981 982 983 984
		}
		spin_unlock_bh(list_lock);
	}
}

985 986 987
/**
 * batadv_bla_purge_claims
 * @bat_priv: the bat priv with all the soft interface information
988 989 990 991 992 993
 * @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
 */
994 995 996
static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
				    int now)
997
{
998
	struct batadv_claim *claim;
999 1000
	struct hlist_node *node;
	struct hlist_head *head;
1001
	struct batadv_hashtable *hash;
1002 1003
	int i;

1004
	hash = bat_priv->bla.claim_hash;
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
	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;
1015 1016
			if (!batadv_compare_eth(claim->backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1017
				continue;
1018
			if (!batadv_has_timed_out(claim->lasttime,
1019
						  BATADV_BLA_CLAIM_TIMEOUT))
1020 1021
				continue;

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

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

1035 1036 1037
/**
 * batadv_bla_update_orig_address
 * @bat_priv: the bat priv with all the soft interface information
1038 1039 1040 1041 1042
 * @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.
 */
1043 1044 1045
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
				    struct batadv_hard_iface *oldif)
1046
{
1047
	struct batadv_backbone_gw *backbone_gw;
1048 1049
	struct hlist_node *node;
	struct hlist_head *head;
1050
	struct batadv_hashtable *hash;
1051
	__be16 group;
1052 1053
	int i;

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

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

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



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

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

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

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

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

1128
	hash = bat_priv->bla.backbone_hash;
1129 1130 1131 1132 1133 1134 1135 1136
	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) {
1137 1138
			if (!batadv_compare_eth(backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1139 1140 1141 1142
				continue;

			backbone_gw->lasttime = jiffies;

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

1151
	batadv_bla_start_timer(bat_priv);
1152 1153
}

1154 1155 1156 1157 1158
/* 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
 */
1159 1160
static struct lock_class_key batadv_claim_hash_lock_class_key;
static struct lock_class_key batadv_backbone_hash_lock_class_key;
1161

1162
/* initialize all bla structures */
1163
int batadv_bla_init(struct batadv_priv *bat_priv)
1164
{
1165
	int i;
1166
	uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
1167
	struct batadv_hard_iface *primary_if;
1168 1169
	uint16_t crc;
	unsigned long entrytime;
1170

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

1173
	/* setting claim destination address */
1174 1175
	memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
	bat_priv->bla.claim_dest.type = 0;
1176
	primary_if = batadv_primary_if_get_selected(bat_priv);
1177
	if (primary_if) {
1178 1179
		crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
		bat_priv->bla.claim_dest.group = htons(crc);
1180
		batadv_hardif_free_ref(primary_if);
1181
	} else {
1182
		bat_priv->bla.claim_dest.group = 0; /* will be set later */
1183 1184
	}

1185
	/* initialize the duplicate list */
1186
	entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
1187
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
1188 1189
		bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
	bat_priv->bla.bcast_duplist_curr = 0;
1190

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

1194 1195
	bat_priv->bla.claim_hash = batadv_hash_new(128);
	bat_priv->bla.backbone_hash = batadv_hash_new(32);
1196

1197
	if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash)
1198
		return -ENOMEM;
1199

1200
	batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
1201
				   &batadv_claim_hash_lock_class_key);
1202
	batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
1203
				   &batadv_backbone_hash_lock_class_key);
1204

1205
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
1206

1207
	batadv_bla_start_timer(bat_priv);
1208
	return 0;
1209 1210
}

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

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

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

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

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

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

1257
		if (batadv_compare_eth(entry->orig, bcast_packet->orig))
1258 1259 1260 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.
		 */
		return 1;
	}
	/* not found, add a new entry (overwrite the oldest entry) */
1266
	curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
1267
	curr %= BATADV_DUPLIST_SIZE;
1268
	entry = &bat_priv->bla.bcast_duplist[curr];
1269 1270 1271
	entry->crc = crc;
	entry->entrytime = jiffies;
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
1272
	bat_priv->bla.bcast_duplist_curr = curr;
1273 1274 1275 1276 1277 1278 1279

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



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

	return 0;
}


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

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

	/* first, find out the vid. */
1340
	if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
		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 */
1355 1356
	backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
						orig_node->orig, vid);
1357 1358 1359
	if (!backbone_gw)
		return 0;

1360
	batadv_backbone_gw_free_ref(backbone_gw);
1361 1362 1363 1364
	return 1;
}

/* free all bla structures (for softinterface free or module unload) */
1365
void batadv_bla_free(struct batadv_priv *bat_priv)
1366
{
1367
	struct batadv_hard_iface *primary_if;
1368

1369
	cancel_delayed_work_sync(&bat_priv->bla.work);
1370
	primary_if = batadv_primary_if_get_selected(bat_priv);
1371

1372
	if (bat_priv->bla.claim_hash) {
1373
		batadv_bla_purge_claims(bat_priv, primary_if, 1);
1374 1375
		batadv_hash_destroy(bat_priv->bla.claim_hash);
		bat_priv->bla.claim_hash = NULL;
1376
	}
1377
	if (bat_priv->bla.backbone_hash) {
1378
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1379 1380
		batadv_hash_destroy(bat_priv->bla.backbone_hash);
		bat_priv->bla.backbone_hash = NULL;
1381 1382
	}
	if (primary_if)
1383
		batadv_hardif_free_ref(primary_if);
1384 1385
}

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

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

1411
	primary_if = batadv_primary_if_get_selected(bat_priv);
1412 1413 1414 1415 1416 1417 1418
	if (!primary_if)
		goto handled;

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


1419
	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1420
		/* don't allow broadcasts while requests are in flight */
1421
		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
1422 1423 1424 1425
			goto handled;

	memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
	search_claim.vid = vid;
1426
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1427 1428 1429 1430 1431

	if (!claim) {
		/* possible optimization: race for a claim */
		/* No claim exists yet, claim it for us!
		 */
1432 1433 1434
		batadv_handle_claim(bat_priv, primary_if,
				    primary_if->net_dev->dev_addr,
				    ethhdr->h_source, vid);
1435 1436 1437 1438
		goto allow;
	}

	/* if it is our own claim ... */
1439 1440
	if (batadv_compare_eth(claim->backbone_gw->orig,
			       primary_if->net_dev->dev_addr)) {
1441 1442 1443 1444 1445 1446
		/* ... allow it in any case */
		claim->lasttime = jiffies;
		goto allow;
	}

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

handled:
	kfree_skb(skb);
	ret = 1;

out:
	if (primary_if)
1476
		batadv_hardif_free_ref(primary_if);
1477
	if (claim)
1478
		batadv_claim_free_ref(claim);
1479 1480 1481
	return ret;
}

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

1503
	primary_if = batadv_primary_if_get_selected(bat_priv);
1504 1505 1506 1507 1508 1509 1510 1511 1512
	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);

1513
	if (batadv_bla_process_claim(bat_priv, primary_if, skb))
1514 1515 1516 1517
		goto handled;

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

1518
	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
1519 1520 1521 1522 1523 1524 1525
		/* 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;

1526
	claim = batadv_claim_hash_find(bat_priv, &search_claim);
1527 1528 1529 1530 1531 1532

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

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

1570
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
1571 1572
{
	struct net_device *net_dev = (struct net_device *)seq->private;
1573
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
1574
	struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
1575 1576
	struct batadv_claim *claim;
	struct batadv_hard_iface *primary_if;
1577 1578 1579 1580 1581
	struct hlist_node *node;
	struct hlist_head *head;
	uint32_t i;
	bool is_own;
	int ret = 0;
1582
	uint8_t *primary_addr;
1583

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

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

1599
	primary_addr = primary_if->net_dev->dev_addr;
1600 1601
	seq_printf(seq,
		   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
1602
		   net_dev->name, primary_addr,
1603
		   ntohs(bat_priv->bla.claim_dest.group));
1604 1605 1606 1607 1608 1609 1610
	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) {
1611 1612
			is_own = batadv_compare_eth(claim->backbone_gw->orig,
						    primary_addr);
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
			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)
1623
		batadv_hardif_free_ref(primary_if);
1624 1625
	return ret;
}
1626 1627 1628 1629 1630

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);
1631
	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
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
	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,
1661
		   ntohs(bat_priv->bla.claim_dest.group));
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690
	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;
}