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 284 285
	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,
			 /* HW DST: FF:43:05:XX:00:00
			  * 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 326 327 328 329
		/* request frame
		 * set HW SRC to the special mac containg the crc
		 */
		memcpy(hw_src, mac, ETH_ALEN);
		memcpy(ethhdr->h_dest, mac, ETH_ALEN);
330
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
331 332
			   "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n",
			   ethhdr->h_source, ethhdr->h_dest, vid);
333 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);
	bat_priv->stats.rx_packets++;
343
	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
344 345 346 347 348
	soft_iface->last_rx = jiffies;

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

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

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

	if (entry)
		return entry;

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

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

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

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

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

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

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

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

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

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

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

453 454 455
	backbone_gw = batadv_backbone_hash_find(bat_priv,
						primary_if->net_dev->dev_addr,
						vid);
456 457 458 459 460 461 462 463 464 465 466 467 468
	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;

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

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

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

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

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

	/* 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);
	}
}

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

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

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

}

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

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

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

		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;

576
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
577 578
			   "bla_add_claim(): changing ownership for %pM, vid %d\n",
			   mac, vid);
579 580 581

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

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

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

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

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

613 614 615
	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 */
616 617 618 619

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

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

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

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

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

	if (unlikely(!backbone_gw))
		return 1;


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

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

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

654
		batadv_bla_send_request(backbone_gw);
655 656 657 658 659 660 661 662 663 664
	} 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);
		}
	}

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

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

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

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

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

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

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

707
	backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
708 709 710 711 712

	if (!backbone_gw)
		return 1;

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

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

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

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

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

	if (unlikely(!backbone_gw))
		return 1;

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

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

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

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

774
	bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
775 776 777 778 779 780 781 782 783 784 785
	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) {
786
	case BATADV_CLAIM_TYPE_ADD:
787 788
		backbone_addr = hw_src;
		break;
789 790 791
	case BATADV_CLAIM_TYPE_REQUEST:
	case BATADV_CLAIM_TYPE_ANNOUNCE:
	case BATADV_CLAIM_TYPE_DEL:
792 793 794 795 796 797 798
		backbone_addr = ethhdr->h_source;
		break;
	default:
		return 0;
	}

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

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

823
	batadv_orig_node_free_ref(orig_node);
824 825 826 827 828

	return 2;
}


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

	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);
860
		headlen = ETH_HLEN;
861 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
	}

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

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

	if (ret < 2)
		return ret;
901 902

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

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

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

930
	batadv_dbg(BATADV_DBG_BLA, bat_priv,
931 932
		   "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
		   ethhdr->h_source, vid, hw_src, hw_dst);
933 934 935 936 937 938
	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.
 */
939
static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
940
{
941
	struct batadv_backbone_gw *backbone_gw;
942 943
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
944
	struct batadv_hashtable *hash;
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
	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;
961
			if (!batadv_has_timed_out(backbone_gw->lasttime,
962
						  BATADV_BLA_BACKBONE_TIMEOUT))
963 964
				continue;

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

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

974
			batadv_bla_del_backbone_claims(backbone_gw);
975 976

			hlist_del_rcu(node);
977
			batadv_backbone_gw_free_ref(backbone_gw);
978 979 980 981 982
		}
		spin_unlock_bh(list_lock);
	}
}

983 984 985
/**
 * batadv_bla_purge_claims
 * @bat_priv: the bat priv with all the soft interface information
986 987 988 989 990 991
 * @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
 */
992 993 994
static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
				    struct batadv_hard_iface *primary_if,
				    int now)
995
{
996
	struct batadv_claim *claim;
997 998
	struct hlist_node *node;
	struct hlist_head *head;
999
	struct batadv_hashtable *hash;
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
	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;
1013 1014
			if (!batadv_compare_eth(claim->backbone_gw->orig,
						primary_if->net_dev->dev_addr))
1015
				continue;
1016
			if (!batadv_has_timed_out(claim->lasttime,
1017
						  BATADV_BLA_CLAIM_TIMEOUT))
1018 1019
				continue;

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

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

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

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

1055
	if (!oldif) {
1056 1057
		batadv_bla_purge_claims(bat_priv, NULL, 1);
		batadv_bla_purge_backbone_gw(bat_priv, 1);
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
		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. */
1071 1072
			if (!batadv_compare_eth(backbone_gw->orig,
						oldif->net_dev->dev_addr))
1073 1074 1075 1076 1077 1078 1079
				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.
			 */
1080
			batadv_bla_send_announce(bat_priv, backbone_gw);
1081 1082 1083 1084 1085 1086 1087 1088
		}
		rcu_read_unlock();
	}
}



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

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

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

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

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

			backbone_gw->lasttime = jiffies;

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

1146
	batadv_bla_start_timer(bat_priv);
1147 1148
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1250
		if (batadv_compare_eth(entry->orig, bcast_packet->orig))
1251 1252 1253 1254 1255 1256 1257 1258
			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) */
1259 1260
	curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
	curr %= BATADV_DUPLIST_SIZE;
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
	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;
}



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

	return 0;
}


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

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

	/* first, find out the vid. */
1333
	if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
		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 */
1348 1349
	backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
						orig_node->orig, vid);
1350 1351 1352
	if (!backbone_gw)
		return 0;

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

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

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

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

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

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

1404
	primary_if = batadv_primary_if_get_selected(bat_priv);
1405 1406 1407 1408 1409 1410 1411 1412 1413
	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 */
1414
		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
1415 1416 1417 1418
			goto handled;

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

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

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

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

handled:
	kfree_skb(skb);
	ret = 1;

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

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

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

1506
	if (batadv_bla_process_claim(bat_priv, primary_if, skb))
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518
		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;

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

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

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

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

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

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

1592
	primary_addr = primary_if->net_dev->dev_addr;
1593 1594
	seq_printf(seq,
		   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
1595
		   net_dev->name, primary_addr,
1596
		   ntohs(bat_priv->claim_dest.group));
1597 1598 1599 1600 1601 1602 1603
	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) {
1604 1605
			is_own = batadv_compare_eth(claim->backbone_gw->orig,
						    primary_addr);
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
			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)
1616
		batadv_hardif_free_ref(primary_if);
1617 1618
	return ret;
}
1619 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

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;
}