aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/originator.c1
-rw-r--r--net/batman-adv/routing.c56
-rw-r--r--net/batman-adv/types.h2
3 files changed, 37 insertions, 22 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 61299da82c6b..d9a8e316c249 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -215,6 +215,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
215 INIT_HLIST_HEAD(&orig_node->neigh_list); 215 INIT_HLIST_HEAD(&orig_node->neigh_list);
216 INIT_LIST_HEAD(&orig_node->bond_list); 216 INIT_LIST_HEAD(&orig_node->bond_list);
217 spin_lock_init(&orig_node->ogm_cnt_lock); 217 spin_lock_init(&orig_node->ogm_cnt_lock);
218 spin_lock_init(&orig_node->bcast_seqno_lock);
218 spin_lock_init(&orig_node->neigh_list_lock); 219 spin_lock_init(&orig_node->neigh_list_lock);
219 kref_init(&orig_node->refcount); 220 kref_init(&orig_node->refcount);
220 221
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 29a689ac5693..ce68815f3eb3 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -1473,81 +1473,93 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
1473int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if) 1473int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1474{ 1474{
1475 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1475 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1476 struct orig_node *orig_node; 1476 struct orig_node *orig_node = NULL;
1477 struct bcast_packet *bcast_packet; 1477 struct bcast_packet *bcast_packet;
1478 struct ethhdr *ethhdr; 1478 struct ethhdr *ethhdr;
1479 int hdr_size = sizeof(struct bcast_packet); 1479 int hdr_size = sizeof(struct bcast_packet);
1480 int ret = NET_RX_DROP;
1480 int32_t seq_diff; 1481 int32_t seq_diff;
1481 1482
1482 /* drop packet if it has not necessary minimum size */ 1483 /* drop packet if it has not necessary minimum size */
1483 if (unlikely(!pskb_may_pull(skb, hdr_size))) 1484 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1484 return NET_RX_DROP; 1485 goto out;
1485 1486
1486 ethhdr = (struct ethhdr *)skb_mac_header(skb); 1487 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1487 1488
1488 /* packet with broadcast indication but unicast recipient */ 1489 /* packet with broadcast indication but unicast recipient */
1489 if (!is_broadcast_ether_addr(ethhdr->h_dest)) 1490 if (!is_broadcast_ether_addr(ethhdr->h_dest))
1490 return NET_RX_DROP; 1491 goto out;
1491 1492
1492 /* packet with broadcast sender address */ 1493 /* packet with broadcast sender address */
1493 if (is_broadcast_ether_addr(ethhdr->h_source)) 1494 if (is_broadcast_ether_addr(ethhdr->h_source))
1494 return NET_RX_DROP; 1495 goto out;
1495 1496
1496 /* ignore broadcasts sent by myself */ 1497 /* ignore broadcasts sent by myself */
1497 if (is_my_mac(ethhdr->h_source)) 1498 if (is_my_mac(ethhdr->h_source))
1498 return NET_RX_DROP; 1499 goto out;
1499 1500
1500 bcast_packet = (struct bcast_packet *)skb->data; 1501 bcast_packet = (struct bcast_packet *)skb->data;
1501 1502
1502 /* ignore broadcasts originated by myself */ 1503 /* ignore broadcasts originated by myself */
1503 if (is_my_mac(bcast_packet->orig)) 1504 if (is_my_mac(bcast_packet->orig))
1504 return NET_RX_DROP; 1505 goto out;
1505 1506
1506 if (bcast_packet->ttl < 2) 1507 if (bcast_packet->ttl < 2)
1507 return NET_RX_DROP; 1508 goto out;
1508 1509
1509 spin_lock_bh(&bat_priv->orig_hash_lock); 1510 spin_lock_bh(&bat_priv->orig_hash_lock);
1510 rcu_read_lock(); 1511 rcu_read_lock();
1511 orig_node = ((struct orig_node *) 1512 orig_node = ((struct orig_node *)
1512 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 1513 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1513 bcast_packet->orig)); 1514 bcast_packet->orig));
1515
1516 if (!orig_node)
1517 goto rcu_unlock;
1518
1519 kref_get(&orig_node->refcount);
1514 rcu_read_unlock(); 1520 rcu_read_unlock();
1515 1521
1516 if (!orig_node) { 1522 spin_lock_bh(&orig_node->bcast_seqno_lock);
1517 spin_unlock_bh(&bat_priv->orig_hash_lock);
1518 return NET_RX_DROP;
1519 }
1520 1523
1521 /* check whether the packet is a duplicate */ 1524 /* check whether the packet is a duplicate */
1522 if (get_bit_status(orig_node->bcast_bits, 1525 if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno,
1523 orig_node->last_bcast_seqno, 1526 ntohl(bcast_packet->seqno)))
1524 ntohl(bcast_packet->seqno))) { 1527 goto spin_unlock;
1525 spin_unlock_bh(&bat_priv->orig_hash_lock);
1526 return NET_RX_DROP;
1527 }
1528 1528
1529 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; 1529 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
1530 1530
1531 /* check whether the packet is old and the host just restarted. */ 1531 /* check whether the packet is old and the host just restarted. */
1532 if (window_protected(bat_priv, seq_diff, 1532 if (window_protected(bat_priv, seq_diff,
1533 &orig_node->bcast_seqno_reset)) { 1533 &orig_node->bcast_seqno_reset))
1534 spin_unlock_bh(&bat_priv->orig_hash_lock); 1534 goto spin_unlock;
1535 return NET_RX_DROP;
1536 }
1537 1535
1538 /* mark broadcast in flood history, update window position 1536 /* mark broadcast in flood history, update window position
1539 * if required. */ 1537 * if required. */
1540 if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) 1538 if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
1541 orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno); 1539 orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
1542 1540
1541 spin_unlock_bh(&orig_node->bcast_seqno_lock);
1543 spin_unlock_bh(&bat_priv->orig_hash_lock); 1542 spin_unlock_bh(&bat_priv->orig_hash_lock);
1543
1544 /* rebroadcast packet */ 1544 /* rebroadcast packet */
1545 add_bcast_packet_to_list(bat_priv, skb); 1545 add_bcast_packet_to_list(bat_priv, skb);
1546 1546
1547 /* broadcast for me */ 1547 /* broadcast for me */
1548 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); 1548 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
1549 ret = NET_RX_SUCCESS;
1550 goto out;
1549 1551
1550 return NET_RX_SUCCESS; 1552rcu_unlock:
1553 rcu_read_unlock();
1554 spin_unlock_bh(&bat_priv->orig_hash_lock);
1555 goto out;
1556spin_unlock:
1557 spin_unlock_bh(&orig_node->bcast_seqno_lock);
1558 spin_unlock_bh(&bat_priv->orig_hash_lock);
1559out:
1560 if (orig_node)
1561 kref_put(&orig_node->refcount, orig_node_free_ref);
1562 return ret;
1551} 1563}
1552 1564
1553int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if) 1565int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if)
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 9a142760bd9c..e1f3e5e71555 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -90,6 +90,8 @@ struct orig_node {
90 spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, 90 spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum,
91 * neigh_node->real_bits, 91 * neigh_node->real_bits,
92 * neigh_node->real_packet_count */ 92 * neigh_node->real_packet_count */
93 spinlock_t bcast_seqno_lock; /* protects bcast_bits,
94 * last_bcast_seqno */
93 atomic_t bond_candidates; 95 atomic_t bond_candidates;
94 struct list_head bond_list; 96 struct list_head bond_list;
95}; 97};