aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/icmp_socket.c27
-rw-r--r--net/batman-adv/originator.c26
-rw-r--r--net/batman-adv/originator.h3
-rw-r--r--net/batman-adv/routing.c338
-rw-r--r--net/batman-adv/types.h3
-rw-r--r--net/batman-adv/unicast.c57
-rw-r--r--net/batman-adv/vis.c33
7 files changed, 313 insertions, 174 deletions
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 8e0cd8a1bc02..7fa5bb8a9409 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -156,7 +156,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
156 struct sk_buff *skb; 156 struct sk_buff *skb;
157 struct icmp_packet_rr *icmp_packet; 157 struct icmp_packet_rr *icmp_packet;
158 158
159 struct orig_node *orig_node; 159 struct orig_node *orig_node = NULL;
160 struct neigh_node *neigh_node = NULL;
160 struct batman_if *batman_if; 161 struct batman_if *batman_if;
161 size_t packet_len = sizeof(struct icmp_packet); 162 size_t packet_len = sizeof(struct icmp_packet);
162 uint8_t dstaddr[ETH_ALEN]; 163 uint8_t dstaddr[ETH_ALEN];
@@ -224,17 +225,25 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
224 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 225 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
225 compare_orig, choose_orig, 226 compare_orig, choose_orig,
226 icmp_packet->dst)); 227 icmp_packet->dst));
227 rcu_read_unlock();
228 228
229 if (!orig_node) 229 if (!orig_node)
230 goto unlock; 230 goto unlock;
231 231
232 if (!orig_node->router) 232 kref_get(&orig_node->refcount);
233 neigh_node = orig_node->router;
234
235 if (!neigh_node)
236 goto unlock;
237
238 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
239 neigh_node = NULL;
233 goto unlock; 240 goto unlock;
241 }
242
243 rcu_read_unlock();
234 244
235 batman_if = orig_node->router->if_incoming; 245 batman_if = orig_node->router->if_incoming;
236 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 246 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
237
238 spin_unlock_bh(&bat_priv->orig_hash_lock); 247 spin_unlock_bh(&bat_priv->orig_hash_lock);
239 248
240 if (!batman_if) 249 if (!batman_if)
@@ -247,14 +256,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
247 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 256 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
248 257
249 if (packet_len == sizeof(struct icmp_packet_rr)) 258 if (packet_len == sizeof(struct icmp_packet_rr))
250 memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN); 259 memcpy(icmp_packet->rr,
251 260 batman_if->net_dev->dev_addr, ETH_ALEN);
252 261
253 send_skb_packet(skb, batman_if, dstaddr); 262 send_skb_packet(skb, batman_if, dstaddr);
254
255 goto out; 263 goto out;
256 264
257unlock: 265unlock:
266 rcu_read_unlock();
258 spin_unlock_bh(&bat_priv->orig_hash_lock); 267 spin_unlock_bh(&bat_priv->orig_hash_lock);
259dst_unreach: 268dst_unreach:
260 icmp_packet->msg_type = DESTINATION_UNREACHABLE; 269 icmp_packet->msg_type = DESTINATION_UNREACHABLE;
@@ -262,6 +271,10 @@ dst_unreach:
262free_skb: 271free_skb:
263 kfree_skb(skb); 272 kfree_skb(skb);
264out: 273out:
274 if (neigh_node)
275 neigh_node_free_ref(neigh_node);
276 if (orig_node)
277 kref_put(&orig_node->refcount, orig_node_free_ref);
265 return len; 278 return len;
266} 279}
267 280
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index a85eadca6b2d..61299da82c6b 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -59,28 +59,18 @@ err:
59 return 0; 59 return 0;
60} 60}
61 61
62void neigh_node_free_ref(struct kref *refcount)
63{
64 struct neigh_node *neigh_node;
65
66 neigh_node = container_of(refcount, struct neigh_node, refcount);
67 kfree(neigh_node);
68}
69
70static void neigh_node_free_rcu(struct rcu_head *rcu) 62static void neigh_node_free_rcu(struct rcu_head *rcu)
71{ 63{
72 struct neigh_node *neigh_node; 64 struct neigh_node *neigh_node;
73 65
74 neigh_node = container_of(rcu, struct neigh_node, rcu); 66 neigh_node = container_of(rcu, struct neigh_node, rcu);
75 kref_put(&neigh_node->refcount, neigh_node_free_ref); 67 kfree(neigh_node);
76} 68}
77 69
78void neigh_node_free_rcu_bond(struct rcu_head *rcu) 70void neigh_node_free_ref(struct neigh_node *neigh_node)
79{ 71{
80 struct neigh_node *neigh_node; 72 if (atomic_dec_and_test(&neigh_node->refcount))
81 73 call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
82 neigh_node = container_of(rcu, struct neigh_node, rcu_bond);
83 kref_put(&neigh_node->refcount, neigh_node_free_ref);
84} 74}
85 75
86struct neigh_node *create_neighbor(struct orig_node *orig_node, 76struct neigh_node *create_neighbor(struct orig_node *orig_node,
@@ -104,7 +94,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
104 memcpy(neigh_node->addr, neigh, ETH_ALEN); 94 memcpy(neigh_node->addr, neigh, ETH_ALEN);
105 neigh_node->orig_node = orig_neigh_node; 95 neigh_node->orig_node = orig_neigh_node;
106 neigh_node->if_incoming = if_incoming; 96 neigh_node->if_incoming = if_incoming;
107 kref_init(&neigh_node->refcount); 97 atomic_set(&neigh_node->refcount, 1);
108 98
109 spin_lock_bh(&orig_node->neigh_list_lock); 99 spin_lock_bh(&orig_node->neigh_list_lock);
110 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); 100 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
@@ -126,14 +116,14 @@ void orig_node_free_ref(struct kref *refcount)
126 list_for_each_entry_safe(neigh_node, tmp_neigh_node, 116 list_for_each_entry_safe(neigh_node, tmp_neigh_node,
127 &orig_node->bond_list, bonding_list) { 117 &orig_node->bond_list, bonding_list) {
128 list_del_rcu(&neigh_node->bonding_list); 118 list_del_rcu(&neigh_node->bonding_list);
129 call_rcu(&neigh_node->rcu_bond, neigh_node_free_rcu_bond); 119 neigh_node_free_ref(neigh_node);
130 } 120 }
131 121
132 /* for all neighbors towards this originator ... */ 122 /* for all neighbors towards this originator ... */
133 hlist_for_each_entry_safe(neigh_node, node, node_tmp, 123 hlist_for_each_entry_safe(neigh_node, node, node_tmp,
134 &orig_node->neigh_list, list) { 124 &orig_node->neigh_list, list) {
135 hlist_del_rcu(&neigh_node->list); 125 hlist_del_rcu(&neigh_node->list);
136 call_rcu(&neigh_node->rcu, neigh_node_free_rcu); 126 neigh_node_free_ref(neigh_node);
137 } 127 }
138 128
139 spin_unlock_bh(&orig_node->neigh_list_lock); 129 spin_unlock_bh(&orig_node->neigh_list_lock);
@@ -315,7 +305,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
315 305
316 hlist_del_rcu(&neigh_node->list); 306 hlist_del_rcu(&neigh_node->list);
317 bonding_candidate_del(orig_node, neigh_node); 307 bonding_candidate_del(orig_node, neigh_node);
318 call_rcu(&neigh_node->rcu, neigh_node_free_rcu); 308 neigh_node_free_ref(neigh_node);
319 } else { 309 } else {
320 if ((!*best_neigh_node) || 310 if ((!*best_neigh_node) ||
321 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg)) 311 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 360dfd19a32f..84d96e2eea47 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -26,13 +26,12 @@ int originator_init(struct bat_priv *bat_priv);
26void originator_free(struct bat_priv *bat_priv); 26void originator_free(struct bat_priv *bat_priv);
27void purge_orig_ref(struct bat_priv *bat_priv); 27void purge_orig_ref(struct bat_priv *bat_priv);
28void orig_node_free_ref(struct kref *refcount); 28void orig_node_free_ref(struct kref *refcount);
29void neigh_node_free_rcu_bond(struct rcu_head *rcu);
30struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); 29struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
31struct neigh_node *create_neighbor(struct orig_node *orig_node, 30struct neigh_node *create_neighbor(struct orig_node *orig_node,
32 struct orig_node *orig_neigh_node, 31 struct orig_node *orig_neigh_node,
33 uint8_t *neigh, 32 uint8_t *neigh,
34 struct batman_if *if_incoming); 33 struct batman_if *if_incoming);
35void neigh_node_free_ref(struct kref *refcount); 34void neigh_node_free_ref(struct neigh_node *neigh_node);
36int orig_seq_print_text(struct seq_file *seq, void *offset); 35int orig_seq_print_text(struct seq_file *seq, void *offset);
37int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); 36int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
38int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); 37int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 1ad14da20839..9185666ab3e0 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -121,12 +121,12 @@ static void update_route(struct bat_priv *bat_priv,
121 orig_node->router->addr); 121 orig_node->router->addr);
122 } 122 }
123 123
124 if (neigh_node) 124 if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
125 kref_get(&neigh_node->refcount); 125 neigh_node = NULL;
126 neigh_node_tmp = orig_node->router; 126 neigh_node_tmp = orig_node->router;
127 orig_node->router = neigh_node; 127 orig_node->router = neigh_node;
128 if (neigh_node_tmp) 128 if (neigh_node_tmp)
129 kref_put(&neigh_node_tmp->refcount, neigh_node_free_ref); 129 neigh_node_free_ref(neigh_node_tmp);
130} 130}
131 131
132 132
@@ -177,7 +177,11 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
177 if (!neigh_node) 177 if (!neigh_node)
178 goto unlock; 178 goto unlock;
179 179
180 kref_get(&neigh_node->refcount); 180 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
181 neigh_node = NULL;
182 goto unlock;
183 }
184
181 rcu_read_unlock(); 185 rcu_read_unlock();
182 186
183 neigh_node->last_valid = jiffies; 187 neigh_node->last_valid = jiffies;
@@ -202,7 +206,11 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
202 if (!neigh_node) 206 if (!neigh_node)
203 goto unlock; 207 goto unlock;
204 208
205 kref_get(&neigh_node->refcount); 209 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
210 neigh_node = NULL;
211 goto unlock;
212 }
213
206 rcu_read_unlock(); 214 rcu_read_unlock();
207 } 215 }
208 216
@@ -267,7 +275,7 @@ unlock:
267 rcu_read_unlock(); 275 rcu_read_unlock();
268out: 276out:
269 if (neigh_node) 277 if (neigh_node)
270 kref_put(&neigh_node->refcount, neigh_node_free_ref); 278 neigh_node_free_ref(neigh_node);
271 return ret; 279 return ret;
272} 280}
273 281
@@ -280,8 +288,8 @@ void bonding_candidate_del(struct orig_node *orig_node,
280 goto out; 288 goto out;
281 289
282 list_del_rcu(&neigh_node->bonding_list); 290 list_del_rcu(&neigh_node->bonding_list);
283 call_rcu(&neigh_node->rcu_bond, neigh_node_free_rcu_bond);
284 INIT_LIST_HEAD(&neigh_node->bonding_list); 291 INIT_LIST_HEAD(&neigh_node->bonding_list);
292 neigh_node_free_ref(neigh_node);
285 atomic_dec(&orig_node->bond_candidates); 293 atomic_dec(&orig_node->bond_candidates);
286 294
287out: 295out:
@@ -342,8 +350,10 @@ static void bonding_candidate_add(struct orig_node *orig_node,
342 if (!list_empty(&neigh_node->bonding_list)) 350 if (!list_empty(&neigh_node->bonding_list))
343 goto out; 351 goto out;
344 352
353 if (!atomic_inc_not_zero(&neigh_node->refcount))
354 goto out;
355
345 list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list); 356 list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
346 kref_get(&neigh_node->refcount);
347 atomic_inc(&orig_node->bond_candidates); 357 atomic_inc(&orig_node->bond_candidates);
348 goto out; 358 goto out;
349 359
@@ -387,7 +397,10 @@ static void update_orig(struct bat_priv *bat_priv,
387 hlist_for_each_entry_rcu(tmp_neigh_node, node, 397 hlist_for_each_entry_rcu(tmp_neigh_node, node,
388 &orig_node->neigh_list, list) { 398 &orig_node->neigh_list, list) {
389 if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && 399 if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
390 (tmp_neigh_node->if_incoming == if_incoming)) { 400 (tmp_neigh_node->if_incoming == if_incoming) &&
401 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
402 if (neigh_node)
403 neigh_node_free_ref(neigh_node);
391 neigh_node = tmp_neigh_node; 404 neigh_node = tmp_neigh_node;
392 continue; 405 continue;
393 } 406 }
@@ -414,11 +427,15 @@ static void update_orig(struct bat_priv *bat_priv,
414 kref_put(&orig_tmp->refcount, orig_node_free_ref); 427 kref_put(&orig_tmp->refcount, orig_node_free_ref);
415 if (!neigh_node) 428 if (!neigh_node)
416 goto unlock; 429 goto unlock;
430
431 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
432 neigh_node = NULL;
433 goto unlock;
434 }
417 } else 435 } else
418 bat_dbg(DBG_BATMAN, bat_priv, 436 bat_dbg(DBG_BATMAN, bat_priv,
419 "Updating existing last-hop neighbor of originator\n"); 437 "Updating existing last-hop neighbor of originator\n");
420 438
421 kref_get(&neigh_node->refcount);
422 rcu_read_unlock(); 439 rcu_read_unlock();
423 440
424 orig_node->flags = batman_packet->flags; 441 orig_node->flags = batman_packet->flags;
@@ -495,7 +512,7 @@ unlock:
495 rcu_read_unlock(); 512 rcu_read_unlock();
496out: 513out:
497 if (neigh_node) 514 if (neigh_node)
498 kref_put(&neigh_node->refcount, neigh_node_free_ref); 515 neigh_node_free_ref(neigh_node);
499} 516}
500 517
501/* checks whether the host restarted and is in the protection time. 518/* checks whether the host restarted and is in the protection time.
@@ -870,22 +887,23 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
870static int recv_my_icmp_packet(struct bat_priv *bat_priv, 887static int recv_my_icmp_packet(struct bat_priv *bat_priv,
871 struct sk_buff *skb, size_t icmp_len) 888 struct sk_buff *skb, size_t icmp_len)
872{ 889{
873 struct orig_node *orig_node; 890 struct orig_node *orig_node = NULL;
891 struct neigh_node *neigh_node = NULL;
874 struct icmp_packet_rr *icmp_packet; 892 struct icmp_packet_rr *icmp_packet;
875 struct batman_if *batman_if; 893 struct batman_if *batman_if;
876 int ret;
877 uint8_t dstaddr[ETH_ALEN]; 894 uint8_t dstaddr[ETH_ALEN];
895 int ret = NET_RX_DROP;
878 896
879 icmp_packet = (struct icmp_packet_rr *)skb->data; 897 icmp_packet = (struct icmp_packet_rr *)skb->data;
880 898
881 /* add data to device queue */ 899 /* add data to device queue */
882 if (icmp_packet->msg_type != ECHO_REQUEST) { 900 if (icmp_packet->msg_type != ECHO_REQUEST) {
883 bat_socket_receive_packet(icmp_packet, icmp_len); 901 bat_socket_receive_packet(icmp_packet, icmp_len);
884 return NET_RX_DROP; 902 goto out;
885 } 903 }
886 904
887 if (!bat_priv->primary_if) 905 if (!bat_priv->primary_if)
888 return NET_RX_DROP; 906 goto out;
889 907
890 /* answer echo request (ping) */ 908 /* answer echo request (ping) */
891 /* get routing information */ 909 /* get routing information */
@@ -894,46 +912,65 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
894 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 912 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
895 compare_orig, choose_orig, 913 compare_orig, choose_orig,
896 icmp_packet->orig)); 914 icmp_packet->orig));
897 rcu_read_unlock();
898 ret = NET_RX_DROP;
899 915
900 if ((orig_node) && (orig_node->router)) { 916 if (!orig_node)
917 goto unlock;
901 918
902 /* don't lock while sending the packets ... we therefore 919 kref_get(&orig_node->refcount);
903 * copy the required data before sending */ 920 neigh_node = orig_node->router;
904 batman_if = orig_node->router->if_incoming;
905 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
906 spin_unlock_bh(&bat_priv->orig_hash_lock);
907 921
908 /* create a copy of the skb, if needed, to modify it. */ 922 if (!neigh_node)
909 if (skb_cow(skb, sizeof(struct ethhdr)) < 0) 923 goto unlock;
910 return NET_RX_DROP;
911 924
912 icmp_packet = (struct icmp_packet_rr *)skb->data; 925 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
926 neigh_node = NULL;
927 goto unlock;
928 }
913 929
914 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 930 rcu_read_unlock();
915 memcpy(icmp_packet->orig,
916 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
917 icmp_packet->msg_type = ECHO_REPLY;
918 icmp_packet->ttl = TTL;
919 931
920 send_skb_packet(skb, batman_if, dstaddr); 932 /* don't lock while sending the packets ... we therefore
921 ret = NET_RX_SUCCESS; 933 * copy the required data before sending */
934 batman_if = orig_node->router->if_incoming;
935 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
936 spin_unlock_bh(&bat_priv->orig_hash_lock);
922 937
923 } else 938 /* create a copy of the skb, if needed, to modify it. */
924 spin_unlock_bh(&bat_priv->orig_hash_lock); 939 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
940 goto out;
925 941
942 icmp_packet = (struct icmp_packet_rr *)skb->data;
943
944 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
945 memcpy(icmp_packet->orig,
946 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
947 icmp_packet->msg_type = ECHO_REPLY;
948 icmp_packet->ttl = TTL;
949
950 send_skb_packet(skb, batman_if, dstaddr);
951 ret = NET_RX_SUCCESS;
952 goto out;
953
954unlock:
955 rcu_read_unlock();
956 spin_unlock_bh(&bat_priv->orig_hash_lock);
957out:
958 if (neigh_node)
959 neigh_node_free_ref(neigh_node);
960 if (orig_node)
961 kref_put(&orig_node->refcount, orig_node_free_ref);
926 return ret; 962 return ret;
927} 963}
928 964
929static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, 965static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
930 struct sk_buff *skb) 966 struct sk_buff *skb)
931{ 967{
932 struct orig_node *orig_node; 968 struct orig_node *orig_node = NULL;
969 struct neigh_node *neigh_node = NULL;
933 struct icmp_packet *icmp_packet; 970 struct icmp_packet *icmp_packet;
934 struct batman_if *batman_if; 971 struct batman_if *batman_if;
935 int ret;
936 uint8_t dstaddr[ETH_ALEN]; 972 uint8_t dstaddr[ETH_ALEN];
973 int ret = NET_RX_DROP;
937 974
938 icmp_packet = (struct icmp_packet *)skb->data; 975 icmp_packet = (struct icmp_packet *)skb->data;
939 976
@@ -942,11 +979,11 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
942 pr_debug("Warning - can't forward icmp packet from %pM to " 979 pr_debug("Warning - can't forward icmp packet from %pM to "
943 "%pM: ttl exceeded\n", icmp_packet->orig, 980 "%pM: ttl exceeded\n", icmp_packet->orig,
944 icmp_packet->dst); 981 icmp_packet->dst);
945 return NET_RX_DROP; 982 goto out;
946 } 983 }
947 984
948 if (!bat_priv->primary_if) 985 if (!bat_priv->primary_if)
949 return NET_RX_DROP; 986 goto out;
950 987
951 /* get routing information */ 988 /* get routing information */
952 spin_lock_bh(&bat_priv->orig_hash_lock); 989 spin_lock_bh(&bat_priv->orig_hash_lock);
@@ -954,35 +991,53 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
954 orig_node = ((struct orig_node *) 991 orig_node = ((struct orig_node *)
955 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 992 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
956 icmp_packet->orig)); 993 icmp_packet->orig));
957 rcu_read_unlock();
958 ret = NET_RX_DROP;
959 994
960 if ((orig_node) && (orig_node->router)) { 995 if (!orig_node)
996 goto unlock;
961 997
962 /* don't lock while sending the packets ... we therefore 998 kref_get(&orig_node->refcount);
963 * copy the required data before sending */ 999 neigh_node = orig_node->router;
964 batman_if = orig_node->router->if_incoming;
965 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
966 spin_unlock_bh(&bat_priv->orig_hash_lock);
967 1000
968 /* create a copy of the skb, if needed, to modify it. */ 1001 if (!neigh_node)
969 if (skb_cow(skb, sizeof(struct ethhdr)) < 0) 1002 goto unlock;
970 return NET_RX_DROP; 1003
1004 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
1005 neigh_node = NULL;
1006 goto unlock;
1007 }
971 1008
972 icmp_packet = (struct icmp_packet *) skb->data; 1009 rcu_read_unlock();
973 1010
974 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 1011 /* don't lock while sending the packets ... we therefore
975 memcpy(icmp_packet->orig, 1012 * copy the required data before sending */
976 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 1013 batman_if = orig_node->router->if_incoming;
977 icmp_packet->msg_type = TTL_EXCEEDED; 1014 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
978 icmp_packet->ttl = TTL; 1015 spin_unlock_bh(&bat_priv->orig_hash_lock);
979 1016
980 send_skb_packet(skb, batman_if, dstaddr); 1017 /* create a copy of the skb, if needed, to modify it. */
981 ret = NET_RX_SUCCESS; 1018 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1019 goto out;
982 1020
983 } else 1021 icmp_packet = (struct icmp_packet *)skb->data;
984 spin_unlock_bh(&bat_priv->orig_hash_lock); 1022
1023 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
1024 memcpy(icmp_packet->orig,
1025 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
1026 icmp_packet->msg_type = TTL_EXCEEDED;
1027 icmp_packet->ttl = TTL;
1028
1029 send_skb_packet(skb, batman_if, dstaddr);
1030 ret = NET_RX_SUCCESS;
1031 goto out;
985 1032
1033unlock:
1034 rcu_read_unlock();
1035 spin_unlock_bh(&bat_priv->orig_hash_lock);
1036out:
1037 if (neigh_node)
1038 neigh_node_free_ref(neigh_node);
1039 if (orig_node)
1040 kref_put(&orig_node->refcount, orig_node_free_ref);
986 return ret; 1041 return ret;
987} 1042}
988 1043
@@ -992,11 +1047,12 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
992 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1047 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
993 struct icmp_packet_rr *icmp_packet; 1048 struct icmp_packet_rr *icmp_packet;
994 struct ethhdr *ethhdr; 1049 struct ethhdr *ethhdr;
995 struct orig_node *orig_node; 1050 struct orig_node *orig_node = NULL;
1051 struct neigh_node *neigh_node = NULL;
996 struct batman_if *batman_if; 1052 struct batman_if *batman_if;
997 int hdr_size = sizeof(struct icmp_packet); 1053 int hdr_size = sizeof(struct icmp_packet);
998 int ret;
999 uint8_t dstaddr[ETH_ALEN]; 1054 uint8_t dstaddr[ETH_ALEN];
1055 int ret = NET_RX_DROP;
1000 1056
1001 /** 1057 /**
1002 * we truncate all incoming icmp packets if they don't match our size 1058 * we truncate all incoming icmp packets if they don't match our size
@@ -1006,21 +1062,21 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
1006 1062
1007 /* drop packet if it has not necessary minimum size */ 1063 /* drop packet if it has not necessary minimum size */
1008 if (unlikely(!pskb_may_pull(skb, hdr_size))) 1064 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1009 return NET_RX_DROP; 1065 goto out;
1010 1066
1011 ethhdr = (struct ethhdr *)skb_mac_header(skb); 1067 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1012 1068
1013 /* packet with unicast indication but broadcast recipient */ 1069 /* packet with unicast indication but broadcast recipient */
1014 if (is_broadcast_ether_addr(ethhdr->h_dest)) 1070 if (is_broadcast_ether_addr(ethhdr->h_dest))
1015 return NET_RX_DROP; 1071 goto out;
1016 1072
1017 /* packet with broadcast sender address */ 1073 /* packet with broadcast sender address */
1018 if (is_broadcast_ether_addr(ethhdr->h_source)) 1074 if (is_broadcast_ether_addr(ethhdr->h_source))
1019 return NET_RX_DROP; 1075 goto out;
1020 1076
1021 /* not for me */ 1077 /* not for me */
1022 if (!is_my_mac(ethhdr->h_dest)) 1078 if (!is_my_mac(ethhdr->h_dest))
1023 return NET_RX_DROP; 1079 goto out;
1024 1080
1025 icmp_packet = (struct icmp_packet_rr *)skb->data; 1081 icmp_packet = (struct icmp_packet_rr *)skb->data;
1026 1082
@@ -1040,40 +1096,56 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
1040 if (icmp_packet->ttl < 2) 1096 if (icmp_packet->ttl < 2)
1041 return recv_icmp_ttl_exceeded(bat_priv, skb); 1097 return recv_icmp_ttl_exceeded(bat_priv, skb);
1042 1098
1043 ret = NET_RX_DROP;
1044
1045 /* get routing information */ 1099 /* get routing information */
1046 spin_lock_bh(&bat_priv->orig_hash_lock); 1100 spin_lock_bh(&bat_priv->orig_hash_lock);
1047 rcu_read_lock(); 1101 rcu_read_lock();
1048 orig_node = ((struct orig_node *) 1102 orig_node = ((struct orig_node *)
1049 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 1103 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1050 icmp_packet->dst)); 1104 icmp_packet->dst));
1051 rcu_read_unlock(); 1105 if (!orig_node)
1106 goto unlock;
1052 1107
1053 if ((orig_node) && (orig_node->router)) { 1108 kref_get(&orig_node->refcount);
1109 neigh_node = orig_node->router;
1054 1110
1055 /* don't lock while sending the packets ... we therefore 1111 if (!neigh_node)
1056 * copy the required data before sending */ 1112 goto unlock;
1057 batman_if = orig_node->router->if_incoming;
1058 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
1059 spin_unlock_bh(&bat_priv->orig_hash_lock);
1060 1113
1061 /* create a copy of the skb, if needed, to modify it. */ 1114 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
1062 if (skb_cow(skb, sizeof(struct ethhdr)) < 0) 1115 neigh_node = NULL;
1063 return NET_RX_DROP; 1116 goto unlock;
1117 }
1118
1119 rcu_read_unlock();
1064 1120
1065 icmp_packet = (struct icmp_packet_rr *)skb->data; 1121 /* don't lock while sending the packets ... we therefore
1122 * copy the required data before sending */
1123 batman_if = orig_node->router->if_incoming;
1124 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
1125 spin_unlock_bh(&bat_priv->orig_hash_lock);
1066 1126
1067 /* decrement ttl */ 1127 /* create a copy of the skb, if needed, to modify it. */
1068 icmp_packet->ttl--; 1128 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1129 goto out;
1069 1130
1070 /* route it */ 1131 icmp_packet = (struct icmp_packet_rr *)skb->data;
1071 send_skb_packet(skb, batman_if, dstaddr);
1072 ret = NET_RX_SUCCESS;
1073 1132
1074 } else 1133 /* decrement ttl */
1075 spin_unlock_bh(&bat_priv->orig_hash_lock); 1134 icmp_packet->ttl--;
1076 1135
1136 /* route it */
1137 send_skb_packet(skb, batman_if, dstaddr);
1138 ret = NET_RX_SUCCESS;
1139 goto out;
1140
1141unlock:
1142 rcu_read_unlock();
1143 spin_unlock_bh(&bat_priv->orig_hash_lock);
1144out:
1145 if (neigh_node)
1146 neigh_node_free_ref(neigh_node);
1147 if (orig_node)
1148 kref_put(&orig_node->refcount, orig_node_free_ref);
1077 return ret; 1149 return ret;
1078} 1150}
1079 1151
@@ -1104,12 +1176,11 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1104 /* select default router to output */ 1176 /* select default router to output */
1105 router = orig_node->router; 1177 router = orig_node->router;
1106 router_orig = orig_node->router->orig_node; 1178 router_orig = orig_node->router->orig_node;
1107 if (!router_orig) { 1179 if (!router_orig || !atomic_inc_not_zero(&router->refcount)) {
1108 rcu_read_unlock(); 1180 rcu_read_unlock();
1109 return NULL; 1181 return NULL;
1110 } 1182 }
1111 1183
1112
1113 if ((!recv_if) && (!bonding_enabled)) 1184 if ((!recv_if) && (!bonding_enabled))
1114 goto return_router; 1185 goto return_router;
1115 1186
@@ -1142,6 +1213,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1142 * is is not on the interface where the packet came 1213 * is is not on the interface where the packet came
1143 * in. */ 1214 * in. */
1144 1215
1216 neigh_node_free_ref(router);
1145 first_candidate = NULL; 1217 first_candidate = NULL;
1146 router = NULL; 1218 router = NULL;
1147 1219
@@ -1154,16 +1226,23 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1154 if (!first_candidate) 1226 if (!first_candidate)
1155 first_candidate = tmp_neigh_node; 1227 first_candidate = tmp_neigh_node;
1156 /* recv_if == NULL on the first node. */ 1228 /* recv_if == NULL on the first node. */
1157 if (tmp_neigh_node->if_incoming != recv_if) { 1229 if (tmp_neigh_node->if_incoming != recv_if &&
1230 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
1158 router = tmp_neigh_node; 1231 router = tmp_neigh_node;
1159 break; 1232 break;
1160 } 1233 }
1161 } 1234 }
1162 1235
1163 /* use the first candidate if nothing was found. */ 1236 /* use the first candidate if nothing was found. */
1164 if (!router) 1237 if (!router && first_candidate &&
1238 atomic_inc_not_zero(&first_candidate->refcount))
1165 router = first_candidate; 1239 router = first_candidate;
1166 1240
1241 if (!router) {
1242 rcu_read_unlock();
1243 return NULL;
1244 }
1245
1167 /* selected should point to the next element 1246 /* selected should point to the next element
1168 * after the current router */ 1247 * after the current router */
1169 spin_lock_bh(&primary_orig_node->neigh_list_lock); 1248 spin_lock_bh(&primary_orig_node->neigh_list_lock);
@@ -1184,21 +1263,34 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1184 first_candidate = tmp_neigh_node; 1263 first_candidate = tmp_neigh_node;
1185 1264
1186 /* recv_if == NULL on the first node. */ 1265 /* recv_if == NULL on the first node. */
1187 if (tmp_neigh_node->if_incoming != recv_if) 1266 if (tmp_neigh_node->if_incoming == recv_if)
1188 /* if we don't have a router yet 1267 continue;
1189 * or this one is better, choose it. */ 1268
1190 if ((!router) || 1269 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1191 (tmp_neigh_node->tq_avg > router->tq_avg)) { 1270 continue;
1192 router = tmp_neigh_node; 1271
1193 } 1272 /* if we don't have a router yet
1273 * or this one is better, choose it. */
1274 if ((!router) ||
1275 (tmp_neigh_node->tq_avg > router->tq_avg)) {
1276 /* decrement refcount of
1277 * previously selected router */
1278 if (router)
1279 neigh_node_free_ref(router);
1280
1281 router = tmp_neigh_node;
1282 atomic_inc_not_zero(&router->refcount);
1283 }
1284
1285 neigh_node_free_ref(tmp_neigh_node);
1194 } 1286 }
1195 1287
1196 /* use the first candidate if nothing was found. */ 1288 /* use the first candidate if nothing was found. */
1197 if (!router) 1289 if (!router && first_candidate &&
1290 atomic_inc_not_zero(&first_candidate->refcount))
1198 router = first_candidate; 1291 router = first_candidate;
1199 } 1292 }
1200return_router: 1293return_router:
1201 kref_get(&router->refcount);
1202 rcu_read_unlock(); 1294 rcu_read_unlock();
1203 return router; 1295 return router;
1204} 1296}
@@ -1232,13 +1324,13 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1232 int hdr_size) 1324 int hdr_size)
1233{ 1325{
1234 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1326 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1235 struct orig_node *orig_node; 1327 struct orig_node *orig_node = NULL;
1236 struct neigh_node *router; 1328 struct neigh_node *neigh_node = NULL;
1237 struct batman_if *batman_if; 1329 struct batman_if *batman_if;
1238 uint8_t dstaddr[ETH_ALEN]; 1330 uint8_t dstaddr[ETH_ALEN];
1239 struct unicast_packet *unicast_packet; 1331 struct unicast_packet *unicast_packet;
1240 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); 1332 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
1241 int ret; 1333 int ret = NET_RX_DROP;
1242 struct sk_buff *new_skb; 1334 struct sk_buff *new_skb;
1243 1335
1244 unicast_packet = (struct unicast_packet *)skb->data; 1336 unicast_packet = (struct unicast_packet *)skb->data;
@@ -1248,7 +1340,7 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1248 pr_debug("Warning - can't forward unicast packet from %pM to " 1340 pr_debug("Warning - can't forward unicast packet from %pM to "
1249 "%pM: ttl exceeded\n", ethhdr->h_source, 1341 "%pM: ttl exceeded\n", ethhdr->h_source,
1250 unicast_packet->dest); 1342 unicast_packet->dest);
1251 return NET_RX_DROP; 1343 goto out;
1252 } 1344 }
1253 1345
1254 /* get routing information */ 1346 /* get routing information */
@@ -1257,27 +1349,29 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1257 orig_node = ((struct orig_node *) 1349 orig_node = ((struct orig_node *)
1258 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 1350 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1259 unicast_packet->dest)); 1351 unicast_packet->dest));
1352 if (!orig_node)
1353 goto unlock;
1354
1355 kref_get(&orig_node->refcount);
1260 rcu_read_unlock(); 1356 rcu_read_unlock();
1261 1357
1262 /* find_router() increases neigh_nodes refcount if found. */ 1358 /* find_router() increases neigh_nodes refcount if found. */
1263 router = find_router(bat_priv, orig_node, recv_if); 1359 neigh_node = find_router(bat_priv, orig_node, recv_if);
1264 1360
1265 if (!router) { 1361 if (!neigh_node) {
1266 spin_unlock_bh(&bat_priv->orig_hash_lock); 1362 spin_unlock_bh(&bat_priv->orig_hash_lock);
1267 return NET_RX_DROP; 1363 goto out;
1268 } 1364 }
1269 1365
1270 /* don't lock while sending the packets ... we therefore 1366 /* don't lock while sending the packets ... we therefore
1271 * copy the required data before sending */ 1367 * copy the required data before sending */
1272 1368 batman_if = neigh_node->if_incoming;
1273 batman_if = router->if_incoming; 1369 memcpy(dstaddr, neigh_node->addr, ETH_ALEN);
1274 memcpy(dstaddr, router->addr, ETH_ALEN);
1275
1276 spin_unlock_bh(&bat_priv->orig_hash_lock); 1370 spin_unlock_bh(&bat_priv->orig_hash_lock);
1277 1371
1278 /* create a copy of the skb, if needed, to modify it. */ 1372 /* create a copy of the skb, if needed, to modify it. */
1279 if (skb_cow(skb, sizeof(struct ethhdr)) < 0) 1373 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1280 return NET_RX_DROP; 1374 goto out;
1281 1375
1282 unicast_packet = (struct unicast_packet *)skb->data; 1376 unicast_packet = (struct unicast_packet *)skb->data;
1283 1377
@@ -1293,11 +1387,13 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1293 ret = frag_reassemble_skb(skb, bat_priv, &new_skb); 1387 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1294 1388
1295 if (ret == NET_RX_DROP) 1389 if (ret == NET_RX_DROP)
1296 return NET_RX_DROP; 1390 goto out;
1297 1391
1298 /* packet was buffered for late merge */ 1392 /* packet was buffered for late merge */
1299 if (!new_skb) 1393 if (!new_skb) {
1300 return NET_RX_SUCCESS; 1394 ret = NET_RX_SUCCESS;
1395 goto out;
1396 }
1301 1397
1302 skb = new_skb; 1398 skb = new_skb;
1303 unicast_packet = (struct unicast_packet *)skb->data; 1399 unicast_packet = (struct unicast_packet *)skb->data;
@@ -1308,8 +1404,18 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1308 1404
1309 /* route it */ 1405 /* route it */
1310 send_skb_packet(skb, batman_if, dstaddr); 1406 send_skb_packet(skb, batman_if, dstaddr);
1407 ret = NET_RX_SUCCESS;
1408 goto out;
1311 1409
1312 return NET_RX_SUCCESS; 1410unlock:
1411 rcu_read_unlock();
1412 spin_unlock_bh(&bat_priv->orig_hash_lock);
1413out:
1414 if (neigh_node)
1415 neigh_node_free_ref(neigh_node);
1416 if (orig_node)
1417 kref_put(&orig_node->refcount, orig_node_free_ref);
1418 return ret;
1313} 1419}
1314 1420
1315int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) 1421int recv_unicast_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 1f833f04222e..084604a6dcf1 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -117,9 +117,8 @@ struct neigh_node {
117 struct list_head bonding_list; 117 struct list_head bonding_list;
118 unsigned long last_valid; 118 unsigned long last_valid;
119 unsigned long real_bits[NUM_WORDS]; 119 unsigned long real_bits[NUM_WORDS];
120 struct kref refcount; 120 atomic_t refcount;
121 struct rcu_head rcu; 121 struct rcu_head rcu;
122 struct rcu_head rcu_bond;
123 struct orig_node *orig_node; 122 struct orig_node *orig_node;
124 struct batman_if *if_incoming; 123 struct batman_if *if_incoming;
125}; 124};
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 00bfeaf9ece3..7ca994ccac1d 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -285,38 +285,42 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
285 struct unicast_packet *unicast_packet; 285 struct unicast_packet *unicast_packet;
286 struct orig_node *orig_node = NULL; 286 struct orig_node *orig_node = NULL;
287 struct batman_if *batman_if; 287 struct batman_if *batman_if;
288 struct neigh_node *router; 288 struct neigh_node *neigh_node;
289 int data_len = skb->len; 289 int data_len = skb->len;
290 uint8_t dstaddr[6]; 290 uint8_t dstaddr[6];
291 int ret = 1;
291 292
292 spin_lock_bh(&bat_priv->orig_hash_lock); 293 spin_lock_bh(&bat_priv->orig_hash_lock);
293 294
294 /* get routing information */ 295 /* get routing information */
295 if (is_multicast_ether_addr(ethhdr->h_dest)) 296 if (is_multicast_ether_addr(ethhdr->h_dest))
296 orig_node = (struct orig_node *)gw_get_selected(bat_priv); 297 orig_node = (struct orig_node *)gw_get_selected(bat_priv);
298 if (orig_node) {
299 kref_get(&orig_node->refcount);
300 goto find_router;
301 }
297 302
298 /* check for hna host */ 303 /* check for hna host - increases orig_node refcount */
299 if (!orig_node) 304 orig_node = transtable_search(bat_priv, ethhdr->h_dest);
300 orig_node = transtable_search(bat_priv, ethhdr->h_dest);
301 305
306find_router:
302 /* find_router() increases neigh_nodes refcount if found. */ 307 /* find_router() increases neigh_nodes refcount if found. */
303 router = find_router(bat_priv, orig_node, NULL); 308 neigh_node = find_router(bat_priv, orig_node, NULL);
304 309
305 if (!router) 310 if (!neigh_node)
306 goto unlock; 311 goto unlock;
307 312
308 /* don't lock while sending the packets ... we therefore 313 if (neigh_node->if_incoming->if_status != IF_ACTIVE)
309 * copy the required data before sending */ 314 goto unlock;
310 batman_if = router->if_incoming;
311 memcpy(dstaddr, router->addr, ETH_ALEN);
312
313 spin_unlock_bh(&bat_priv->orig_hash_lock);
314
315 if (batman_if->if_status != IF_ACTIVE)
316 goto dropped;
317 315
318 if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0) 316 if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
319 goto dropped; 317 goto unlock;
318
319 /* don't lock while sending the packets ... we therefore
320 * copy the required data before sending */
321 batman_if = neigh_node->if_incoming;
322 memcpy(dstaddr, neigh_node->addr, ETH_ALEN);
323 spin_unlock_bh(&bat_priv->orig_hash_lock);
320 324
321 unicast_packet = (struct unicast_packet *)skb->data; 325 unicast_packet = (struct unicast_packet *)skb->data;
322 326
@@ -330,18 +334,25 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
330 334
331 if (atomic_read(&bat_priv->fragmentation) && 335 if (atomic_read(&bat_priv->fragmentation) &&
332 data_len + sizeof(struct unicast_packet) > 336 data_len + sizeof(struct unicast_packet) >
333 batman_if->net_dev->mtu) { 337 batman_if->net_dev->mtu) {
334 /* send frag skb decreases ttl */ 338 /* send frag skb decreases ttl */
335 unicast_packet->ttl++; 339 unicast_packet->ttl++;
336 return frag_send_skb(skb, bat_priv, batman_if, 340 ret = frag_send_skb(skb, bat_priv, batman_if, dstaddr);
337 dstaddr); 341 goto out;
338 } 342 }
343
339 send_skb_packet(skb, batman_if, dstaddr); 344 send_skb_packet(skb, batman_if, dstaddr);
340 return 0; 345 ret = 0;
346 goto out;
341 347
342unlock: 348unlock:
343 spin_unlock_bh(&bat_priv->orig_hash_lock); 349 spin_unlock_bh(&bat_priv->orig_hash_lock);
344dropped: 350out:
345 kfree_skb(skb); 351 if (neigh_node)
346 return 1; 352 neigh_node_free_ref(neigh_node);
353 if (orig_node)
354 kref_put(&orig_node->refcount, orig_node_free_ref);
355 if (ret == 1)
356 kfree_skb(skb);
357 return ret;
347} 358}
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 8092eadcbdee..9832d8f9ed44 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -764,21 +764,35 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
764 struct vis_info *info) 764 struct vis_info *info)
765{ 765{
766 struct orig_node *orig_node; 766 struct orig_node *orig_node;
767 struct neigh_node *neigh_node = NULL;
767 struct sk_buff *skb; 768 struct sk_buff *skb;
768 struct vis_packet *packet; 769 struct vis_packet *packet;
769 struct batman_if *batman_if; 770 struct batman_if *batman_if;
770 uint8_t dstaddr[ETH_ALEN]; 771 uint8_t dstaddr[ETH_ALEN];
771 772
772 spin_lock_bh(&bat_priv->orig_hash_lock);
773 packet = (struct vis_packet *)info->skb_packet->data; 773 packet = (struct vis_packet *)info->skb_packet->data;
774
775 spin_lock_bh(&bat_priv->orig_hash_lock);
774 rcu_read_lock(); 776 rcu_read_lock();
775 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 777 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
776 compare_orig, choose_orig, 778 compare_orig, choose_orig,
777 packet->target_orig)); 779 packet->target_orig));
778 rcu_read_unlock();
779 780
780 if ((!orig_node) || (!orig_node->router)) 781 if (!orig_node)
781 goto out; 782 goto unlock;
783
784 kref_get(&orig_node->refcount);
785 neigh_node = orig_node->router;
786
787 if (!neigh_node)
788 goto unlock;
789
790 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
791 neigh_node = NULL;
792 goto unlock;
793 }
794
795 rcu_read_unlock();
782 796
783 /* don't lock while sending the packets ... we therefore 797 /* don't lock while sending the packets ... we therefore
784 * copy the required data before sending */ 798 * copy the required data before sending */
@@ -790,10 +804,17 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
790 if (skb) 804 if (skb)
791 send_skb_packet(skb, batman_if, dstaddr); 805 send_skb_packet(skb, batman_if, dstaddr);
792 806
793 return; 807 goto out;
794 808
795out: 809unlock:
810 rcu_read_unlock();
796 spin_unlock_bh(&bat_priv->orig_hash_lock); 811 spin_unlock_bh(&bat_priv->orig_hash_lock);
812out:
813 if (neigh_node)
814 neigh_node_free_ref(neigh_node);
815 if (orig_node)
816 kref_put(&orig_node->refcount, orig_node_free_ref);
817 return;
797} 818}
798 819
799/* only send one vis packet. called from send_vis_packets() */ 820/* only send one vis packet. called from send_vis_packets() */