diff options
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 2 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 3 | ||||
-rw-r--r-- | net/batman-adv/fragmentation.c | 11 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 11 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 2 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 62 |
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); |
1547 | out: | 1547 | out: |
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 | |||
487 | out_err: | 489 | out_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 | ||
43 | static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) | 43 | static 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 | ||
49 | static struct batadv_gw_node * | 51 | static 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, | |||
501 | static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) | 501 | static 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 | */ | ||
714 | static void | ||
715 | batadv_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 | ||
1030 | out: | 1081 | out: |
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 | ||