aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/bat_iv_ogm.c2
-rw-r--r--net/batman-adv/distributed-arp-table.c3
-rw-r--r--net/batman-adv/fragmentation.c11
-rw-r--r--net/batman-adv/gateway_client.c11
-rw-r--r--net/batman-adv/hard-interface.c2
-rw-r--r--net/batman-adv/originator.c62
6 files changed, 78 insertions, 13 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index b3bd4ec3fd94..f04224c32005 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1545,6 +1545,8 @@ out_neigh:
1545 if ((orig_neigh_node) && (!is_single_hop_neigh)) 1545 if ((orig_neigh_node) && (!is_single_hop_neigh))
1546 batadv_orig_node_free_ref(orig_neigh_node); 1546 batadv_orig_node_free_ref(orig_neigh_node);
1547out: 1547out:
1548 if (router_ifinfo)
1549 batadv_neigh_ifinfo_free_ref(router_ifinfo);
1548 if (router) 1550 if (router)
1549 batadv_neigh_node_free_ref(router); 1551 batadv_neigh_node_free_ref(router);
1550 if (router_router) 1552 if (router_router)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index b25fd64d727b..aa5d4946d0d7 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -940,8 +940,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
940 * additional DAT answer may trigger kernel warnings about 940 * additional DAT answer may trigger kernel warnings about
941 * a packet coming from the wrong port. 941 * a packet coming from the wrong port.
942 */ 942 */
943 if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, 943 if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, vid)) {
944 BATADV_NO_FLAGS)) {
945 ret = true; 944 ret = true;
946 goto out; 945 goto out;
947 } 946 }
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index bcc4bea632fa..f14e54a05691 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -418,12 +418,13 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
418 struct batadv_neigh_node *neigh_node) 418 struct batadv_neigh_node *neigh_node)
419{ 419{
420 struct batadv_priv *bat_priv; 420 struct batadv_priv *bat_priv;
421 struct batadv_hard_iface *primary_if; 421 struct batadv_hard_iface *primary_if = NULL;
422 struct batadv_frag_packet frag_header; 422 struct batadv_frag_packet frag_header;
423 struct sk_buff *skb_fragment; 423 struct sk_buff *skb_fragment;
424 unsigned mtu = neigh_node->if_incoming->net_dev->mtu; 424 unsigned mtu = neigh_node->if_incoming->net_dev->mtu;
425 unsigned header_size = sizeof(frag_header); 425 unsigned header_size = sizeof(frag_header);
426 unsigned max_fragment_size, max_packet_size; 426 unsigned max_fragment_size, max_packet_size;
427 bool ret = false;
427 428
428 /* To avoid merge and refragmentation at next-hops we never send 429 /* To avoid merge and refragmentation at next-hops we never send
429 * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE 430 * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -483,7 +484,11 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
483 skb->len + ETH_HLEN); 484 skb->len + ETH_HLEN);
484 batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 485 batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
485 486
486 return true; 487 ret = true;
488
487out_err: 489out_err:
488 return false; 490 if (primary_if)
491 batadv_hardif_free_ref(primary_if);
492
493 return ret;
489} 494}
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index c835e137423b..90cff585b37d 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -42,8 +42,10 @@
42 42
43static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) 43static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
44{ 44{
45 if (atomic_dec_and_test(&gw_node->refcount)) 45 if (atomic_dec_and_test(&gw_node->refcount)) {
46 batadv_orig_node_free_ref(gw_node->orig_node);
46 kfree_rcu(gw_node, rcu); 47 kfree_rcu(gw_node, rcu);
48 }
47} 49}
48 50
49static struct batadv_gw_node * 51static struct batadv_gw_node *
@@ -406,9 +408,14 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
406 if (gateway->bandwidth_down == 0) 408 if (gateway->bandwidth_down == 0)
407 return; 409 return;
408 410
411 if (!atomic_inc_not_zero(&orig_node->refcount))
412 return;
413
409 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); 414 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
410 if (!gw_node) 415 if (!gw_node) {
416 batadv_orig_node_free_ref(orig_node);
411 return; 417 return;
418 }
412 419
413 INIT_HLIST_NODE(&gw_node->list); 420 INIT_HLIST_NODE(&gw_node->list);
414 gw_node->orig_node = orig_node; 421 gw_node->orig_node = orig_node;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index b851cc580853..fbda6b54baff 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
83 return true; 83 return true;
84 84
85 /* no more parents..stop recursion */ 85 /* no more parents..stop recursion */
86 if (net_dev->iflink == net_dev->ifindex) 86 if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex)
87 return false; 87 return false;
88 88
89 /* recurse over the parent device */ 89 /* recurse over the parent device */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ffd9dfbd9b0e..6a484514cd3e 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -501,12 +501,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
501static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) 501static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
502{ 502{
503 struct batadv_orig_ifinfo *orig_ifinfo; 503 struct batadv_orig_ifinfo *orig_ifinfo;
504 struct batadv_neigh_node *router;
504 505
505 orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); 506 orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
506 507
507 if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) 508 if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
508 batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); 509 batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
509 510
511 /* this is the last reference to this object */
512 router = rcu_dereference_protected(orig_ifinfo->router, true);
513 if (router)
514 batadv_neigh_node_free_ref_now(router);
510 kfree(orig_ifinfo); 515 kfree(orig_ifinfo);
511} 516}
512 517
@@ -702,6 +707,47 @@ free_orig_node:
702} 707}
703 708
704/** 709/**
710 * batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor
711 * @bat_priv: the bat priv with all the soft interface information
712 * @neigh: orig node which is to be checked
713 */
714static void
715batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
716 struct batadv_neigh_node *neigh)
717{
718 struct batadv_neigh_ifinfo *neigh_ifinfo;
719 struct batadv_hard_iface *if_outgoing;
720 struct hlist_node *node_tmp;
721
722 spin_lock_bh(&neigh->ifinfo_lock);
723
724 /* for all ifinfo objects for this neighinator */
725 hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
726 &neigh->ifinfo_list, list) {
727 if_outgoing = neigh_ifinfo->if_outgoing;
728
729 /* always keep the default interface */
730 if (if_outgoing == BATADV_IF_DEFAULT)
731 continue;
732
733 /* don't purge if the interface is not (going) down */
734 if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
735 (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
736 (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
737 continue;
738
739 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
740 "neighbor/ifinfo purge: neighbor %pM, iface: %s\n",
741 neigh->addr, if_outgoing->net_dev->name);
742
743 hlist_del_rcu(&neigh_ifinfo->list);
744 batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
745 }
746
747 spin_unlock_bh(&neigh->ifinfo_lock);
748}
749
750/**
705 * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator 751 * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator
706 * @bat_priv: the bat priv with all the soft interface information 752 * @bat_priv: the bat priv with all the soft interface information
707 * @orig_node: orig node which is to be checked 753 * @orig_node: orig node which is to be checked
@@ -800,6 +846,11 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
800 846
801 hlist_del_rcu(&neigh_node->list); 847 hlist_del_rcu(&neigh_node->list);
802 batadv_neigh_node_free_ref(neigh_node); 848 batadv_neigh_node_free_ref(neigh_node);
849 } else {
850 /* only necessary if not the whole neighbor is to be
851 * deleted, but some interface has been removed.
852 */
853 batadv_purge_neigh_ifinfo(bat_priv, neigh_node);
803 } 854 }
804 } 855 }
805 856
@@ -857,7 +908,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
857{ 908{
858 struct batadv_neigh_node *best_neigh_node; 909 struct batadv_neigh_node *best_neigh_node;
859 struct batadv_hard_iface *hard_iface; 910 struct batadv_hard_iface *hard_iface;
860 bool changed; 911 bool changed_ifinfo, changed_neigh;
861 912
862 if (batadv_has_timed_out(orig_node->last_seen, 913 if (batadv_has_timed_out(orig_node->last_seen,
863 2 * BATADV_PURGE_TIMEOUT)) { 914 2 * BATADV_PURGE_TIMEOUT)) {
@@ -867,10 +918,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
867 jiffies_to_msecs(orig_node->last_seen)); 918 jiffies_to_msecs(orig_node->last_seen));
868 return true; 919 return true;
869 } 920 }
870 changed = batadv_purge_orig_ifinfo(bat_priv, orig_node); 921 changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node);
871 changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node); 922 changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node);
872 923
873 if (!changed) 924 if (!changed_ifinfo && !changed_neigh)
874 return false; 925 return false;
875 926
876 /* first for NULL ... */ 927 /* first for NULL ... */
@@ -1028,7 +1079,8 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset)
1028 bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); 1079 bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface);
1029 1080
1030out: 1081out:
1031 batadv_hardif_free_ref(hard_iface); 1082 if (hard_iface)
1083 batadv_hardif_free_ref(hard_iface);
1032 return 0; 1084 return 0;
1033} 1085}
1034 1086