aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-04-20 09:40:58 -0400
committerSven Eckelmann <sven@narfation.org>2011-05-01 16:49:03 -0400
commit32ae9b221e788413ce68feaae2ca39e406211a0a (patch)
treed827f989976a28fea5cdcb349c308baa98182c35
parent71e4aa9c465fd66c110667ab5d620fb6a4ef2157 (diff)
batman-adv: Make bat_priv->primary_if an rcu protected pointer
The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the bat_priv->primary_if need to be used, as well as spin/rcu locking. Otherwise we might end up using a primary_if pointer pointing to already freed memory. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Sven Eckelmann <sven@narfation.org>
-rw-r--r--net/batman-adv/gateway_client.c33
-rw-r--r--net/batman-adv/hard-interface.c83
-rw-r--r--net/batman-adv/hard-interface.h18
-rw-r--r--net/batman-adv/icmp_socket.c19
-rw-r--r--net/batman-adv/originator.c34
-rw-r--r--net/batman-adv/routing.c18
-rw-r--r--net/batman-adv/send.c17
-rw-r--r--net/batman-adv/soft-interface.c64
-rw-r--r--net/batman-adv/translation-table.c57
-rw-r--r--net/batman-adv/types.h2
-rw-r--r--net/batman-adv/unicast.c16
-rw-r--r--net/batman-adv/vis.c37
12 files changed, 280 insertions, 118 deletions
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index af128eff2edf..65f39530799d 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -439,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
439{ 439{
440 struct net_device *net_dev = (struct net_device *)seq->private; 440 struct net_device *net_dev = (struct net_device *)seq->private;
441 struct bat_priv *bat_priv = netdev_priv(net_dev); 441 struct bat_priv *bat_priv = netdev_priv(net_dev);
442 struct hard_iface *primary_if;
442 struct gw_node *gw_node; 443 struct gw_node *gw_node;
443 struct hlist_node *node; 444 struct hlist_node *node;
444 int gw_count = 0; 445 int gw_count = 0, ret = 0;
445 446
446 if (!bat_priv->primary_if) { 447 primary_if = primary_if_get_selected(bat_priv);
447 448 if (!primary_if) {
448 return seq_printf(seq, "BATMAN mesh %s disabled - please " 449 ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
449 "specify interfaces to enable it\n", 450 "specify interfaces to enable it\n",
450 net_dev->name); 451 net_dev->name);
452 goto out;
451 } 453 }
452 454
453 if (bat_priv->primary_if->if_status != IF_ACTIVE) { 455 if (primary_if->if_status != IF_ACTIVE) {
454 456 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
455 return seq_printf(seq, "BATMAN mesh %s disabled - " 457 "primary interface not active\n",
456 "primary interface not active\n", 458 net_dev->name);
457 net_dev->name); 459 goto out;
458 } 460 }
459 461
460 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " 462 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
461 "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", 463 "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
462 "Gateway", "#", TQ_MAX_VALUE, "Nexthop", 464 "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
463 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, 465 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
464 bat_priv->primary_if->net_dev->name, 466 primary_if->net_dev->name,
465 bat_priv->primary_if->net_dev->dev_addr, net_dev->name); 467 primary_if->net_dev->dev_addr, net_dev->name);
466 468
467 rcu_read_lock(); 469 rcu_read_lock();
468 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { 470 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -480,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
480 if (gw_count == 0) 482 if (gw_count == 0)
481 seq_printf(seq, "No gateways in range ...\n"); 483 seq_printf(seq, "No gateways in range ...\n");
482 484
483 return 0; 485out:
486 if (primary_if)
487 hardif_free_ref(primary_if);
488 return ret;
484} 489}
485 490
486int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) 491int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index b3058e46ee6b..3e888f133d75 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -110,47 +110,60 @@ out:
110 return hard_iface; 110 return hard_iface;
111} 111}
112 112
113static void update_primary_addr(struct bat_priv *bat_priv) 113static void primary_if_update_addr(struct bat_priv *bat_priv)
114{ 114{
115 struct vis_packet *vis_packet; 115 struct vis_packet *vis_packet;
116 struct hard_iface *primary_if;
117
118 primary_if = primary_if_get_selected(bat_priv);
119 if (!primary_if)
120 goto out;
116 121
117 vis_packet = (struct vis_packet *) 122 vis_packet = (struct vis_packet *)
118 bat_priv->my_vis_info->skb_packet->data; 123 bat_priv->my_vis_info->skb_packet->data;
119 memcpy(vis_packet->vis_orig, 124 memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
120 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
121 memcpy(vis_packet->sender_orig, 125 memcpy(vis_packet->sender_orig,
122 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 126 primary_if->net_dev->dev_addr, ETH_ALEN);
127
128out:
129 if (primary_if)
130 hardif_free_ref(primary_if);
123} 131}
124 132
125static void set_primary_if(struct bat_priv *bat_priv, 133static void primary_if_select(struct bat_priv *bat_priv,
126 struct hard_iface *hard_iface) 134 struct hard_iface *new_hard_iface)
127{ 135{
136 struct hard_iface *curr_hard_iface;
128 struct batman_packet *batman_packet; 137 struct batman_packet *batman_packet;
129 struct hard_iface *old_if;
130 138
131 if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) 139 spin_lock_bh(&hardif_list_lock);
132 hard_iface = NULL;
133 140
134 old_if = bat_priv->primary_if; 141 if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
135 bat_priv->primary_if = hard_iface; 142 new_hard_iface = NULL;
136 143
137 if (old_if) 144 curr_hard_iface = bat_priv->primary_if;
138 hardif_free_ref(old_if); 145 rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
139 146
140 if (!bat_priv->primary_if) 147 if (curr_hard_iface)
141 return; 148 hardif_free_ref(curr_hard_iface);
142 149
143 batman_packet = (struct batman_packet *)(hard_iface->packet_buff); 150 if (!new_hard_iface)
151 goto out;
152
153 batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff);
144 batman_packet->flags = PRIMARIES_FIRST_HOP; 154 batman_packet->flags = PRIMARIES_FIRST_HOP;
145 batman_packet->ttl = TTL; 155 batman_packet->ttl = TTL;
146 156
147 update_primary_addr(bat_priv); 157 primary_if_update_addr(bat_priv);
148 158
149 /*** 159 /***
150 * hacky trick to make sure that we send the HNA information via 160 * hacky trick to make sure that we send the HNA information via
151 * our new primary interface 161 * our new primary interface
152 */ 162 */
153 atomic_set(&bat_priv->hna_local_changed, 1); 163 atomic_set(&bat_priv->hna_local_changed, 1);
164
165out:
166 spin_unlock_bh(&hardif_list_lock);
154} 167}
155 168
156static bool hardif_is_iface_up(struct hard_iface *hard_iface) 169static bool hardif_is_iface_up(struct hard_iface *hard_iface)
@@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface)
236static void hardif_activate_interface(struct hard_iface *hard_iface) 249static void hardif_activate_interface(struct hard_iface *hard_iface)
237{ 250{
238 struct bat_priv *bat_priv; 251 struct bat_priv *bat_priv;
252 struct hard_iface *primary_if = NULL;
239 253
240 if (hard_iface->if_status != IF_INACTIVE) 254 if (hard_iface->if_status != IF_INACTIVE)
241 return; 255 goto out;
242 256
243 bat_priv = netdev_priv(hard_iface->soft_iface); 257 bat_priv = netdev_priv(hard_iface->soft_iface);
244 258
@@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
249 * the first active interface becomes our primary interface or 263 * the first active interface becomes our primary interface or
250 * the next active interface after the old primay interface was removed 264 * the next active interface after the old primay interface was removed
251 */ 265 */
252 if (!bat_priv->primary_if) 266 primary_if = primary_if_get_selected(bat_priv);
253 set_primary_if(bat_priv, hard_iface); 267 if (!primary_if)
268 primary_if_select(bat_priv, hard_iface);
254 269
255 bat_info(hard_iface->soft_iface, "Interface activated: %s\n", 270 bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
256 hard_iface->net_dev->name); 271 hard_iface->net_dev->name);
257 272
258 update_min_mtu(hard_iface->soft_iface); 273 update_min_mtu(hard_iface->soft_iface);
259 return; 274
275out:
276 if (primary_if)
277 hardif_free_ref(primary_if);
260} 278}
261 279
262static void hardif_deactivate_interface(struct hard_iface *hard_iface) 280static void hardif_deactivate_interface(struct hard_iface *hard_iface)
@@ -386,12 +404,13 @@ err:
386void hardif_disable_interface(struct hard_iface *hard_iface) 404void hardif_disable_interface(struct hard_iface *hard_iface)
387{ 405{
388 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 406 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
407 struct hard_iface *primary_if = NULL;
389 408
390 if (hard_iface->if_status == IF_ACTIVE) 409 if (hard_iface->if_status == IF_ACTIVE)
391 hardif_deactivate_interface(hard_iface); 410 hardif_deactivate_interface(hard_iface);
392 411
393 if (hard_iface->if_status != IF_INACTIVE) 412 if (hard_iface->if_status != IF_INACTIVE)
394 return; 413 goto out;
395 414
396 bat_info(hard_iface->soft_iface, "Removing interface: %s\n", 415 bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
397 hard_iface->net_dev->name); 416 hard_iface->net_dev->name);
@@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
400 bat_priv->num_ifaces--; 419 bat_priv->num_ifaces--;
401 orig_hash_del_if(hard_iface, bat_priv->num_ifaces); 420 orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
402 421
403 if (hard_iface == bat_priv->primary_if) { 422 primary_if = primary_if_get_selected(bat_priv);
423 if (hard_iface == primary_if) {
404 struct hard_iface *new_if; 424 struct hard_iface *new_if;
405 425
406 new_if = hardif_get_active(hard_iface->soft_iface); 426 new_if = hardif_get_active(hard_iface->soft_iface);
407 set_primary_if(bat_priv, new_if); 427 primary_if_select(bat_priv, new_if);
408 428
409 if (new_if) 429 if (new_if)
410 hardif_free_ref(new_if); 430 hardif_free_ref(new_if);
@@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
425 445
426 hard_iface->soft_iface = NULL; 446 hard_iface->soft_iface = NULL;
427 hardif_free_ref(hard_iface); 447 hardif_free_ref(hard_iface);
448
449out:
450 if (primary_if)
451 hardif_free_ref(primary_if);
428} 452}
429 453
430static struct hard_iface *hardif_add_interface(struct net_device *net_dev) 454static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
@@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this,
514{ 538{
515 struct net_device *net_dev = (struct net_device *)ptr; 539 struct net_device *net_dev = (struct net_device *)ptr;
516 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); 540 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
541 struct hard_iface *primary_if = NULL;
517 struct bat_priv *bat_priv; 542 struct bat_priv *bat_priv;
518 543
519 if (!hard_iface && event == NETDEV_REGISTER) 544 if (!hard_iface && event == NETDEV_REGISTER)
@@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this,
549 update_mac_addresses(hard_iface); 574 update_mac_addresses(hard_iface);
550 575
551 bat_priv = netdev_priv(hard_iface->soft_iface); 576 bat_priv = netdev_priv(hard_iface->soft_iface);
552 if (hard_iface == bat_priv->primary_if) 577 primary_if = primary_if_get_selected(bat_priv);
553 update_primary_addr(bat_priv); 578 if (!primary_if)
579 goto hardif_put;
580
581 if (hard_iface == primary_if)
582 primary_if_update_addr(bat_priv);
554 break; 583 break;
555 default: 584 default:
556 break; 585 break;
@@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this,
559hardif_put: 588hardif_put:
560 hardif_free_ref(hard_iface); 589 hardif_free_ref(hard_iface);
561out: 590out:
591 if (primary_if)
592 hardif_free_ref(primary_if);
562 return NOTIFY_DONE; 593 return NOTIFY_DONE;
563} 594}
564 595
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index a9ddf36e51c8..64265991460b 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface)
45 call_rcu(&hard_iface->rcu, hardif_free_rcu); 45 call_rcu(&hard_iface->rcu, hardif_free_rcu);
46} 46}
47 47
48static inline struct hard_iface *primary_if_get_selected(
49 struct bat_priv *bat_priv)
50{
51 struct hard_iface *hard_iface;
52
53 rcu_read_lock();
54 hard_iface = rcu_dereference(bat_priv->primary_if);
55 if (!hard_iface)
56 goto out;
57
58 if (!atomic_inc_not_zero(&hard_iface->refcount))
59 hard_iface = NULL;
60
61out:
62 rcu_read_unlock();
63 return hard_iface;
64}
65
48#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ 66#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 49079c254476..fa22ba2bb832 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
153{ 153{
154 struct socket_client *socket_client = file->private_data; 154 struct socket_client *socket_client = file->private_data;
155 struct bat_priv *bat_priv = socket_client->bat_priv; 155 struct bat_priv *bat_priv = socket_client->bat_priv;
156 struct hard_iface *primary_if = NULL;
156 struct sk_buff *skb; 157 struct sk_buff *skb;
157 struct icmp_packet_rr *icmp_packet; 158 struct icmp_packet_rr *icmp_packet;
158 159
@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
167 return -EINVAL; 168 return -EINVAL;
168 } 169 }
169 170
170 if (!bat_priv->primary_if) 171 primary_if = primary_if_get_selected(bat_priv);
171 return -EFAULT; 172
173 if (!primary_if) {
174 len = -EFAULT;
175 goto out;
176 }
172 177
173 if (len >= sizeof(struct icmp_packet_rr)) 178 if (len >= sizeof(struct icmp_packet_rr))
174 packet_len = sizeof(struct icmp_packet_rr); 179 packet_len = sizeof(struct icmp_packet_rr);
175 180
176 skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); 181 skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
177 if (!skb) 182 if (!skb) {
178 return -ENOMEM; 183 len = -ENOMEM;
184 goto out;
185 }
179 186
180 skb_reserve(skb, sizeof(struct ethhdr)); 187 skb_reserve(skb, sizeof(struct ethhdr));
181 icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); 188 icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
@@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
233 goto dst_unreach; 240 goto dst_unreach;
234 241
235 memcpy(icmp_packet->orig, 242 memcpy(icmp_packet->orig,
236 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 243 primary_if->net_dev->dev_addr, ETH_ALEN);
237 244
238 if (packet_len == sizeof(struct icmp_packet_rr)) 245 if (packet_len == sizeof(struct icmp_packet_rr))
239 memcpy(icmp_packet->rr, 246 memcpy(icmp_packet->rr,
@@ -248,6 +255,8 @@ dst_unreach:
248free_skb: 255free_skb:
249 kfree_skb(skb); 256 kfree_skb(skb);
250out: 257out:
258 if (primary_if)
259 hardif_free_ref(primary_if);
251 if (neigh_node) 260 if (neigh_node)
252 neigh_node_free_ref(neigh_node); 261 neigh_node_free_ref(neigh_node);
253 if (orig_node) 262 if (orig_node)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 5b8fe32043da..ef4a9be7613a 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -405,29 +405,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
405 struct hashtable_t *hash = bat_priv->orig_hash; 405 struct hashtable_t *hash = bat_priv->orig_hash;
406 struct hlist_node *node, *node_tmp; 406 struct hlist_node *node, *node_tmp;
407 struct hlist_head *head; 407 struct hlist_head *head;
408 struct hard_iface *primary_if;
408 struct orig_node *orig_node; 409 struct orig_node *orig_node;
409 struct neigh_node *neigh_node, *neigh_node_tmp; 410 struct neigh_node *neigh_node, *neigh_node_tmp;
410 int batman_count = 0; 411 int batman_count = 0;
411 int last_seen_secs; 412 int last_seen_secs;
412 int last_seen_msecs; 413 int last_seen_msecs;
413 int i; 414 int i, ret = 0;
415
416 primary_if = primary_if_get_selected(bat_priv);
414 417
415 if ((!bat_priv->primary_if) || 418 if (!primary_if) {
416 (bat_priv->primary_if->if_status != IF_ACTIVE)) { 419 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
417 if (!bat_priv->primary_if) 420 "please specify interfaces to enable it\n",
418 return seq_printf(seq, "BATMAN mesh %s disabled - " 421 net_dev->name);
419 "please specify interfaces to enable it\n", 422 goto out;
420 net_dev->name); 423 }
421 424
422 return seq_printf(seq, "BATMAN mesh %s " 425 if (primary_if->if_status != IF_ACTIVE) {
423 "disabled - primary interface not active\n", 426 ret = seq_printf(seq, "BATMAN mesh %s "
424 net_dev->name); 427 "disabled - primary interface not active\n",
428 net_dev->name);
429 goto out;
425 } 430 }
426 431
427 seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", 432 seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
428 SOURCE_VERSION, REVISION_VERSION_STR, 433 SOURCE_VERSION, REVISION_VERSION_STR,
429 bat_priv->primary_if->net_dev->name, 434 primary_if->net_dev->name,
430 bat_priv->primary_if->net_dev->dev_addr, net_dev->name); 435 primary_if->net_dev->dev_addr, net_dev->name);
431 seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", 436 seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
432 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", 437 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
433 "outgoingIF", "Potential nexthops"); 438 "outgoingIF", "Potential nexthops");
@@ -474,7 +479,10 @@ next:
474 if (batman_count == 0) 479 if (batman_count == 0)
475 seq_printf(seq, "No batman nodes in range ...\n"); 480 seq_printf(seq, "No batman nodes in range ...\n");
476 481
477 return 0; 482out:
483 if (primary_if)
484 hardif_free_ref(primary_if);
485 return ret;
478} 486}
479 487
480static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) 488static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 2d77bd3a3e9a..49f571553050 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -904,6 +904,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
904static int recv_my_icmp_packet(struct bat_priv *bat_priv, 904static int recv_my_icmp_packet(struct bat_priv *bat_priv,
905 struct sk_buff *skb, size_t icmp_len) 905 struct sk_buff *skb, size_t icmp_len)
906{ 906{
907 struct hard_iface *primary_if = NULL;
907 struct orig_node *orig_node = NULL; 908 struct orig_node *orig_node = NULL;
908 struct neigh_node *router = NULL; 909 struct neigh_node *router = NULL;
909 struct icmp_packet_rr *icmp_packet; 910 struct icmp_packet_rr *icmp_packet;
@@ -917,7 +918,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
917 goto out; 918 goto out;
918 } 919 }
919 920
920 if (!bat_priv->primary_if) 921 primary_if = primary_if_get_selected(bat_priv);
922 if (!primary_if)
921 goto out; 923 goto out;
922 924
923 /* answer echo request (ping) */ 925 /* answer echo request (ping) */
@@ -937,8 +939,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
937 icmp_packet = (struct icmp_packet_rr *)skb->data; 939 icmp_packet = (struct icmp_packet_rr *)skb->data;
938 940
939 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 941 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
940 memcpy(icmp_packet->orig, 942 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
941 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
942 icmp_packet->msg_type = ECHO_REPLY; 943 icmp_packet->msg_type = ECHO_REPLY;
943 icmp_packet->ttl = TTL; 944 icmp_packet->ttl = TTL;
944 945
@@ -946,6 +947,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
946 ret = NET_RX_SUCCESS; 947 ret = NET_RX_SUCCESS;
947 948
948out: 949out:
950 if (primary_if)
951 hardif_free_ref(primary_if);
949 if (router) 952 if (router)
950 neigh_node_free_ref(router); 953 neigh_node_free_ref(router);
951 if (orig_node) 954 if (orig_node)
@@ -956,6 +959,7 @@ out:
956static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, 959static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
957 struct sk_buff *skb) 960 struct sk_buff *skb)
958{ 961{
962 struct hard_iface *primary_if = NULL;
959 struct orig_node *orig_node = NULL; 963 struct orig_node *orig_node = NULL;
960 struct neigh_node *router = NULL; 964 struct neigh_node *router = NULL;
961 struct icmp_packet *icmp_packet; 965 struct icmp_packet *icmp_packet;
@@ -971,7 +975,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
971 goto out; 975 goto out;
972 } 976 }
973 977
974 if (!bat_priv->primary_if) 978 primary_if = primary_if_get_selected(bat_priv);
979 if (!primary_if)
975 goto out; 980 goto out;
976 981
977 /* get routing information */ 982 /* get routing information */
@@ -990,8 +995,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
990 icmp_packet = (struct icmp_packet *)skb->data; 995 icmp_packet = (struct icmp_packet *)skb->data;
991 996
992 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 997 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
993 memcpy(icmp_packet->orig, 998 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
994 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
995 icmp_packet->msg_type = TTL_EXCEEDED; 999 icmp_packet->msg_type = TTL_EXCEEDED;
996 icmp_packet->ttl = TTL; 1000 icmp_packet->ttl = TTL;
997 1001
@@ -999,6 +1003,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
999 ret = NET_RX_SUCCESS; 1003 ret = NET_RX_SUCCESS;
1000 1004
1001out: 1005out:
1006 if (primary_if)
1007 hardif_free_ref(primary_if);
1002 if (router) 1008 if (router)
1003 neigh_node_free_ref(router); 1009 neigh_node_free_ref(router);
1004 if (orig_node) 1010 if (orig_node)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 7650e2bf187d..02b541a6dfef 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
244void schedule_own_packet(struct hard_iface *hard_iface) 244void schedule_own_packet(struct hard_iface *hard_iface)
245{ 245{
246 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 246 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
247 struct hard_iface *primary_if;
247 unsigned long send_time; 248 unsigned long send_time;
248 struct batman_packet *batman_packet; 249 struct batman_packet *batman_packet;
249 int vis_server; 250 int vis_server;
@@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
253 return; 254 return;
254 255
255 vis_server = atomic_read(&bat_priv->vis_mode); 256 vis_server = atomic_read(&bat_priv->vis_mode);
257 primary_if = primary_if_get_selected(bat_priv);
256 258
257 /** 259 /**
258 * the interface gets activated here to avoid race conditions between 260 * the interface gets activated here to avoid race conditions between
@@ -266,7 +268,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
266 268
267 /* if local hna has changed and interface is a primary interface */ 269 /* if local hna has changed and interface is a primary interface */
268 if ((atomic_read(&bat_priv->hna_local_changed)) && 270 if ((atomic_read(&bat_priv->hna_local_changed)) &&
269 (hard_iface == bat_priv->primary_if)) 271 (hard_iface == primary_if))
270 rebuild_batman_packet(bat_priv, hard_iface); 272 rebuild_batman_packet(bat_priv, hard_iface);
271 273
272 /** 274 /**
@@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
284 else 286 else
285 batman_packet->flags &= ~VIS_SERVER; 287 batman_packet->flags &= ~VIS_SERVER;
286 288
287 if ((hard_iface == bat_priv->primary_if) && 289 if ((hard_iface == primary_if) &&
288 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) 290 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
289 batman_packet->gw_flags = 291 batman_packet->gw_flags =
290 (uint8_t)atomic_read(&bat_priv->gw_bandwidth); 292 (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
@@ -299,6 +301,9 @@ void schedule_own_packet(struct hard_iface *hard_iface)
299 hard_iface->packet_buff, 301 hard_iface->packet_buff,
300 hard_iface->packet_len, 302 hard_iface->packet_len,
301 hard_iface, 1, send_time); 303 hard_iface, 1, send_time);
304
305 if (primary_if)
306 hardif_free_ref(primary_if);
302} 307}
303 308
304void schedule_forward_packet(struct orig_node *orig_node, 309void schedule_forward_packet(struct orig_node *orig_node,
@@ -403,6 +408,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
403 * skb is freed. */ 408 * skb is freed. */
404int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) 409int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
405{ 410{
411 struct hard_iface *primary_if = NULL;
406 struct forw_packet *forw_packet; 412 struct forw_packet *forw_packet;
407 struct bcast_packet *bcast_packet; 413 struct bcast_packet *bcast_packet;
408 414
@@ -411,7 +417,8 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
411 goto out; 417 goto out;
412 } 418 }
413 419
414 if (!bat_priv->primary_if) 420 primary_if = primary_if_get_selected(bat_priv);
421 if (!primary_if)
415 goto out; 422 goto out;
416 423
417 forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); 424 forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
@@ -430,7 +437,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
430 skb_reset_mac_header(skb); 437 skb_reset_mac_header(skb);
431 438
432 forw_packet->skb = skb; 439 forw_packet->skb = skb;
433 forw_packet->if_incoming = bat_priv->primary_if; 440 forw_packet->if_incoming = primary_if;
434 441
435 /* how often did we send the bcast packet ? */ 442 /* how often did we send the bcast packet ? */
436 forw_packet->num_packets = 0; 443 forw_packet->num_packets = 0;
@@ -443,6 +450,8 @@ packet_free:
443out_and_inc: 450out_and_inc:
444 atomic_inc(&bat_priv->bcast_queue_left); 451 atomic_inc(&bat_priv->bcast_queue_left);
445out: 452out:
453 if (primary_if)
454 hardif_free_ref(primary_if);
446 return NETDEV_TX_BUSY; 455 return NETDEV_TX_BUSY;
447} 456}
448 457
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 58ce4400d581..ea5e58c252f0 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -215,13 +215,24 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
215 struct net_device *net_dev = (struct net_device *)seq->private; 215 struct net_device *net_dev = (struct net_device *)seq->private;
216 struct bat_priv *bat_priv = netdev_priv(net_dev); 216 struct bat_priv *bat_priv = netdev_priv(net_dev);
217 struct softif_neigh *softif_neigh; 217 struct softif_neigh *softif_neigh;
218 struct hard_iface *primary_if;
218 struct hlist_node *node; 219 struct hlist_node *node;
219 struct softif_neigh *curr_softif_neigh; 220 struct softif_neigh *curr_softif_neigh;
221 int ret = 0;
220 222
221 if (!bat_priv->primary_if) { 223 primary_if = primary_if_get_selected(bat_priv);
222 return seq_printf(seq, "BATMAN mesh %s disabled - " 224 if (!primary_if) {
223 "please specify interfaces to enable it\n", 225 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
224 net_dev->name); 226 "please specify interfaces to enable it\n",
227 net_dev->name);
228 goto out;
229 }
230
231 if (primary_if->if_status != IF_ACTIVE) {
232 ret = seq_printf(seq, "BATMAN mesh %s "
233 "disabled - primary interface not active\n",
234 net_dev->name);
235 goto out;
225 } 236 }
226 237
227 seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); 238 seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
@@ -238,7 +249,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
238 if (curr_softif_neigh) 249 if (curr_softif_neigh)
239 softif_neigh_free_ref(curr_softif_neigh); 250 softif_neigh_free_ref(curr_softif_neigh);
240 251
241 return 0; 252out:
253 if (primary_if)
254 hardif_free_ref(primary_if);
255 return ret;
242} 256}
243 257
244static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, 258static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
@@ -247,7 +261,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
247 struct bat_priv *bat_priv = netdev_priv(dev); 261 struct bat_priv *bat_priv = netdev_priv(dev);
248 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 262 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
249 struct batman_packet *batman_packet; 263 struct batman_packet *batman_packet;
250 struct softif_neigh *softif_neigh; 264 struct softif_neigh *softif_neigh = NULL;
265 struct hard_iface *primary_if = NULL;
251 struct softif_neigh *curr_softif_neigh = NULL; 266 struct softif_neigh *curr_softif_neigh = NULL;
252 267
253 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) 268 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
@@ -257,28 +272,34 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
257 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); 272 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
258 273
259 if (batman_packet->version != COMPAT_VERSION) 274 if (batman_packet->version != COMPAT_VERSION)
260 goto err; 275 goto out;
261 276
262 if (batman_packet->packet_type != BAT_PACKET) 277 if (batman_packet->packet_type != BAT_PACKET)
263 goto err; 278 goto out;
264 279
265 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) 280 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
266 goto err; 281 goto out;
267 282
268 if (is_my_mac(batman_packet->orig)) 283 if (is_my_mac(batman_packet->orig))
269 goto err; 284 goto out;
270 285
271 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); 286 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
272
273 if (!softif_neigh) 287 if (!softif_neigh)
274 goto err; 288 goto out;
275 289
276 curr_softif_neigh = softif_neigh_get_selected(bat_priv); 290 curr_softif_neigh = softif_neigh_get_selected(bat_priv);
291 if (!curr_softif_neigh)
292 goto out;
293
277 if (curr_softif_neigh == softif_neigh) 294 if (curr_softif_neigh == softif_neigh)
278 goto out; 295 goto out;
279 296
297 primary_if = primary_if_get_selected(bat_priv);
298 if (!primary_if)
299 goto out;
300
280 /* we got a neighbor but its mac is 'bigger' than ours */ 301 /* we got a neighbor but its mac is 'bigger' than ours */
281 if (memcmp(bat_priv->primary_if->net_dev->dev_addr, 302 if (memcmp(primary_if->net_dev->dev_addr,
282 softif_neigh->addr, ETH_ALEN) < 0) 303 softif_neigh->addr, ETH_ALEN) < 0)
283 goto out; 304 goto out;
284 305
@@ -300,7 +321,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
300 /* close own batX device and use softif_neigh as exit node */ 321 /* close own batX device and use softif_neigh as exit node */
301 if ((!curr_softif_neigh) && 322 if ((!curr_softif_neigh) &&
302 (memcmp(softif_neigh->addr, 323 (memcmp(softif_neigh->addr,
303 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { 324 primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
304 bat_dbg(DBG_ROUTES, bat_priv, 325 bat_dbg(DBG_ROUTES, bat_priv,
305 "Setting mesh exit point to %pM (vid: %d).\n", 326 "Setting mesh exit point to %pM (vid: %d).\n",
306 softif_neigh->addr, softif_neigh->vid); 327 softif_neigh->addr, softif_neigh->vid);
@@ -310,12 +331,13 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
310 } 331 }
311 332
312out: 333out:
313 softif_neigh_free_ref(softif_neigh);
314err:
315 kfree_skb(skb); 334 kfree_skb(skb);
335 if (softif_neigh)
336 softif_neigh_free_ref(softif_neigh);
316 if (curr_softif_neigh) 337 if (curr_softif_neigh)
317 softif_neigh_free_ref(curr_softif_neigh); 338 softif_neigh_free_ref(curr_softif_neigh);
318 339 if (primary_if)
340 hardif_free_ref(primary_if);
319 return; 341 return;
320} 342}
321 343
@@ -371,6 +393,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
371{ 393{
372 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 394 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
373 struct bat_priv *bat_priv = netdev_priv(soft_iface); 395 struct bat_priv *bat_priv = netdev_priv(soft_iface);
396 struct hard_iface *primary_if = NULL;
374 struct bcast_packet *bcast_packet; 397 struct bcast_packet *bcast_packet;
375 struct vlan_ethhdr *vhdr; 398 struct vlan_ethhdr *vhdr;
376 struct softif_neigh *curr_softif_neigh = NULL; 399 struct softif_neigh *curr_softif_neigh = NULL;
@@ -420,7 +443,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
420 443
421 /* ethernet packet should be broadcasted */ 444 /* ethernet packet should be broadcasted */
422 if (do_bcast) { 445 if (do_bcast) {
423 if (!bat_priv->primary_if) 446 primary_if = primary_if_get_selected(bat_priv);
447 if (!primary_if)
424 goto dropped; 448 goto dropped;
425 449
426 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) 450 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
@@ -436,7 +460,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
436 /* hw address of first interface is the orig mac because only 460 /* hw address of first interface is the orig mac because only
437 * this mac is known throughout the mesh */ 461 * this mac is known throughout the mesh */
438 memcpy(bcast_packet->orig, 462 memcpy(bcast_packet->orig,
439 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 463 primary_if->net_dev->dev_addr, ETH_ALEN);
440 464
441 /* set broadcast sequence number */ 465 /* set broadcast sequence number */
442 bcast_packet->seqno = 466 bcast_packet->seqno =
@@ -466,6 +490,8 @@ dropped_freed:
466end: 490end:
467 if (curr_softif_neigh) 491 if (curr_softif_neigh)
468 softif_neigh_free_ref(curr_softif_neigh); 492 softif_neigh_free_ref(curr_softif_neigh);
493 if (primary_if)
494 hardif_free_ref(primary_if);
469 return NETDEV_TX_OK; 495 return NETDEV_TX_OK;
470} 496}
471 497
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 8d15b48d1692..f931830d630e 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -22,6 +22,7 @@
22#include "main.h" 22#include "main.h"
23#include "translation-table.h" 23#include "translation-table.h"
24#include "soft-interface.h" 24#include "soft-interface.h"
25#include "hard-interface.h"
25#include "hash.h" 26#include "hash.h"
26#include "originator.h" 27#include "originator.h"
27 28
@@ -237,16 +238,26 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
237 struct bat_priv *bat_priv = netdev_priv(net_dev); 238 struct bat_priv *bat_priv = netdev_priv(net_dev);
238 struct hashtable_t *hash = bat_priv->hna_local_hash; 239 struct hashtable_t *hash = bat_priv->hna_local_hash;
239 struct hna_local_entry *hna_local_entry; 240 struct hna_local_entry *hna_local_entry;
241 struct hard_iface *primary_if;
240 struct hlist_node *node; 242 struct hlist_node *node;
241 struct hlist_head *head; 243 struct hlist_head *head;
242 size_t buf_size, pos; 244 size_t buf_size, pos;
243 char *buff; 245 char *buff;
244 int i; 246 int i, ret = 0;
245 247
246 if (!bat_priv->primary_if) { 248 primary_if = primary_if_get_selected(bat_priv);
247 return seq_printf(seq, "BATMAN mesh %s disabled - " 249 if (!primary_if) {
248 "please specify interfaces to enable it\n", 250 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
249 net_dev->name); 251 "please specify interfaces to enable it\n",
252 net_dev->name);
253 goto out;
254 }
255
256 if (primary_if->if_status != IF_ACTIVE) {
257 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
258 "primary interface not active\n",
259 net_dev->name);
260 goto out;
250 } 261 }
251 262
252 seq_printf(seq, "Locally retrieved addresses (from %s) " 263 seq_printf(seq, "Locally retrieved addresses (from %s) "
@@ -269,7 +280,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
269 buff = kmalloc(buf_size, GFP_ATOMIC); 280 buff = kmalloc(buf_size, GFP_ATOMIC);
270 if (!buff) { 281 if (!buff) {
271 spin_unlock_bh(&bat_priv->hna_lhash_lock); 282 spin_unlock_bh(&bat_priv->hna_lhash_lock);
272 return -ENOMEM; 283 ret = -ENOMEM;
284 goto out;
273 } 285 }
274 286
275 buff[0] = '\0'; 287 buff[0] = '\0';
@@ -291,7 +303,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
291 303
292 seq_printf(seq, "%s", buff); 304 seq_printf(seq, "%s", buff);
293 kfree(buff); 305 kfree(buff);
294 return 0; 306out:
307 if (primary_if)
308 hardif_free_ref(primary_if);
309 return ret;
295} 310}
296 311
297static void _hna_local_del(struct hlist_node *node, void *arg) 312static void _hna_local_del(struct hlist_node *node, void *arg)
@@ -468,16 +483,26 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
468 struct bat_priv *bat_priv = netdev_priv(net_dev); 483 struct bat_priv *bat_priv = netdev_priv(net_dev);
469 struct hashtable_t *hash = bat_priv->hna_global_hash; 484 struct hashtable_t *hash = bat_priv->hna_global_hash;
470 struct hna_global_entry *hna_global_entry; 485 struct hna_global_entry *hna_global_entry;
486 struct hard_iface *primary_if;
471 struct hlist_node *node; 487 struct hlist_node *node;
472 struct hlist_head *head; 488 struct hlist_head *head;
473 size_t buf_size, pos; 489 size_t buf_size, pos;
474 char *buff; 490 char *buff;
475 int i; 491 int i, ret = 0;
476 492
477 if (!bat_priv->primary_if) { 493 primary_if = primary_if_get_selected(bat_priv);
478 return seq_printf(seq, "BATMAN mesh %s disabled - " 494 if (!primary_if) {
479 "please specify interfaces to enable it\n", 495 ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
480 net_dev->name); 496 "specify interfaces to enable it\n",
497 net_dev->name);
498 goto out;
499 }
500
501 if (primary_if->if_status != IF_ACTIVE) {
502 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
503 "primary interface not active\n",
504 net_dev->name);
505 goto out;
481 } 506 }
482 507
483 seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", 508 seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
@@ -499,7 +524,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
499 buff = kmalloc(buf_size, GFP_ATOMIC); 524 buff = kmalloc(buf_size, GFP_ATOMIC);
500 if (!buff) { 525 if (!buff) {
501 spin_unlock_bh(&bat_priv->hna_ghash_lock); 526 spin_unlock_bh(&bat_priv->hna_ghash_lock);
502 return -ENOMEM; 527 ret = -ENOMEM;
528 goto out;
503 } 529 }
504 buff[0] = '\0'; 530 buff[0] = '\0';
505 pos = 0; 531 pos = 0;
@@ -522,7 +548,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
522 548
523 seq_printf(seq, "%s", buff); 549 seq_printf(seq, "%s", buff);
524 kfree(buff); 550 kfree(buff);
525 return 0; 551out:
552 if (primary_if)
553 hardif_free_ref(primary_if);
554 return ret;
526} 555}
527 556
528static void _hna_global_del_orig(struct bat_priv *bat_priv, 557static void _hna_global_del_orig(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 75123b1ae0de..947bafc6431a 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -149,7 +149,6 @@ struct bat_priv {
149 struct hlist_head softif_neigh_list; 149 struct hlist_head softif_neigh_list;
150 struct softif_neigh __rcu *softif_neigh; 150 struct softif_neigh __rcu *softif_neigh;
151 struct debug_log *debug_log; 151 struct debug_log *debug_log;
152 struct hard_iface *primary_if;
153 struct kobject *mesh_obj; 152 struct kobject *mesh_obj;
154 struct dentry *debug_dir; 153 struct dentry *debug_dir;
155 struct hlist_head forw_bat_list; 154 struct hlist_head forw_bat_list;
@@ -174,6 +173,7 @@ struct bat_priv {
174 struct delayed_work orig_work; 173 struct delayed_work orig_work;
175 struct delayed_work vis_work; 174 struct delayed_work vis_work;
176 struct gw_node __rcu *curr_gw; /* rcu protected pointer */ 175 struct gw_node __rcu *curr_gw; /* rcu protected pointer */
176 struct hard_iface __rcu *primary_if; /* rcu protected pointer */
177 struct vis_info *my_vis_info; 177 struct vis_info *my_vis_info;
178}; 178};
179 179
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index d46acc815138..b46cbf1507e4 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
221 struct hard_iface *hard_iface, uint8_t dstaddr[]) 221 struct hard_iface *hard_iface, uint8_t dstaddr[])
222{ 222{
223 struct unicast_packet tmp_uc, *unicast_packet; 223 struct unicast_packet tmp_uc, *unicast_packet;
224 struct hard_iface *primary_if;
224 struct sk_buff *frag_skb; 225 struct sk_buff *frag_skb;
225 struct unicast_frag_packet *frag1, *frag2; 226 struct unicast_frag_packet *frag1, *frag2;
226 int uc_hdr_len = sizeof(struct unicast_packet); 227 int uc_hdr_len = sizeof(struct unicast_packet);
227 int ucf_hdr_len = sizeof(struct unicast_frag_packet); 228 int ucf_hdr_len = sizeof(struct unicast_frag_packet);
228 int data_len = skb->len - uc_hdr_len; 229 int data_len = skb->len - uc_hdr_len;
229 int large_tail = 0; 230 int large_tail = 0, ret = NET_RX_DROP;
230 uint16_t seqno; 231 uint16_t seqno;
231 232
232 if (!bat_priv->primary_if) 233 primary_if = primary_if_get_selected(bat_priv);
234 if (!primary_if)
233 goto dropped; 235 goto dropped;
234 236
235 frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); 237 frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
@@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
254 frag1->version = COMPAT_VERSION; 256 frag1->version = COMPAT_VERSION;
255 frag1->packet_type = BAT_UNICAST_FRAG; 257 frag1->packet_type = BAT_UNICAST_FRAG;
256 258
257 memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 259 memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
258 memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); 260 memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
259 261
260 if (data_len & 1) 262 if (data_len & 1)
@@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
269 271
270 send_skb_packet(skb, hard_iface, dstaddr); 272 send_skb_packet(skb, hard_iface, dstaddr);
271 send_skb_packet(frag_skb, hard_iface, dstaddr); 273 send_skb_packet(frag_skb, hard_iface, dstaddr);
272 return NET_RX_SUCCESS; 274 ret = NET_RX_SUCCESS;
275 goto out;
273 276
274drop_frag: 277drop_frag:
275 kfree_skb(frag_skb); 278 kfree_skb(frag_skb);
276dropped: 279dropped:
277 kfree_skb(skb); 280 kfree_skb(skb);
278 return NET_RX_DROP; 281out:
282 if (primary_if)
283 hardif_free_ref(primary_if);
284 return ret;
279} 285}
280 286
281int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) 287int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index d4cc4f5399f4..c8f571d3b5d4 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
204 204
205int vis_seq_print_text(struct seq_file *seq, void *offset) 205int vis_seq_print_text(struct seq_file *seq, void *offset)
206{ 206{
207 struct hard_iface *primary_if;
207 struct hlist_node *node; 208 struct hlist_node *node;
208 struct hlist_head *head; 209 struct hlist_head *head;
209 struct vis_info *info; 210 struct vis_info *info;
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
215 HLIST_HEAD(vis_if_list); 216 HLIST_HEAD(vis_if_list);
216 struct if_list_entry *entry; 217 struct if_list_entry *entry;
217 struct hlist_node *pos, *n; 218 struct hlist_node *pos, *n;
218 int i, j; 219 int i, j, ret = 0;
219 int vis_server = atomic_read(&bat_priv->vis_mode); 220 int vis_server = atomic_read(&bat_priv->vis_mode);
220 size_t buff_pos, buf_size; 221 size_t buff_pos, buf_size;
221 char *buff; 222 char *buff;
222 int compare; 223 int compare;
223 224
224 if ((!bat_priv->primary_if) || 225 primary_if = primary_if_get_selected(bat_priv);
225 (vis_server == VIS_TYPE_CLIENT_UPDATE)) 226 if (!primary_if)
226 return 0; 227 goto out;
228
229 if (vis_server == VIS_TYPE_CLIENT_UPDATE)
230 goto out;
227 231
228 buf_size = 1; 232 buf_size = 1;
229 /* Estimate length */ 233 /* Estimate length */
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
270 buff = kmalloc(buf_size, GFP_ATOMIC); 274 buff = kmalloc(buf_size, GFP_ATOMIC);
271 if (!buff) { 275 if (!buff) {
272 spin_unlock_bh(&bat_priv->vis_hash_lock); 276 spin_unlock_bh(&bat_priv->vis_hash_lock);
273 return -ENOMEM; 277 ret = -ENOMEM;
278 goto out;
274 } 279 }
275 buff[0] = '\0'; 280 buff[0] = '\0';
276 buff_pos = 0; 281 buff_pos = 0;
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
328 seq_printf(seq, "%s", buff); 333 seq_printf(seq, "%s", buff);
329 kfree(buff); 334 kfree(buff);
330 335
331 return 0; 336out:
337 if (primary_if)
338 hardif_free_ref(primary_if);
339 return ret;
332} 340}
333 341
334/* add the info packet to the send list, if it was not 342/* add the info packet to the send list, if it was not
@@ -815,16 +823,20 @@ out:
815/* only send one vis packet. called from send_vis_packets() */ 823/* only send one vis packet. called from send_vis_packets() */
816static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) 824static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
817{ 825{
826 struct hard_iface *primary_if;
818 struct vis_packet *packet; 827 struct vis_packet *packet;
819 828
829 primary_if = primary_if_get_selected(bat_priv);
830 if (!primary_if)
831 goto out;
832
820 packet = (struct vis_packet *)info->skb_packet->data; 833 packet = (struct vis_packet *)info->skb_packet->data;
821 if (packet->ttl < 2) { 834 if (packet->ttl < 2) {
822 pr_debug("Error - can't send vis packet: ttl exceeded\n"); 835 pr_debug("Error - can't send vis packet: ttl exceeded\n");
823 return; 836 goto out;
824 } 837 }
825 838
826 memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, 839 memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
827 ETH_ALEN);
828 packet->ttl--; 840 packet->ttl--;
829 841
830 if (is_broadcast_ether_addr(packet->target_orig)) 842 if (is_broadcast_ether_addr(packet->target_orig))
@@ -832,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
832 else 844 else
833 unicast_vis_packet(bat_priv, info); 845 unicast_vis_packet(bat_priv, info);
834 packet->ttl++; /* restore TTL */ 846 packet->ttl++; /* restore TTL */
847
848out:
849 if (primary_if)
850 hardif_free_ref(primary_if);
835} 851}
836 852
837/* called from timer; send (and maybe generate) vis packet. */ 853/* called from timer; send (and maybe generate) vis packet. */
@@ -858,8 +874,7 @@ static void send_vis_packets(struct work_struct *work)
858 kref_get(&info->refcount); 874 kref_get(&info->refcount);
859 spin_unlock_bh(&bat_priv->vis_hash_lock); 875 spin_unlock_bh(&bat_priv->vis_hash_lock);
860 876
861 if (bat_priv->primary_if) 877 send_vis_packet(bat_priv, info);
862 send_vis_packet(bat_priv, info);
863 878
864 spin_lock_bh(&bat_priv->vis_hash_lock); 879 spin_lock_bh(&bat_priv->vis_hash_lock);
865 send_list_del(info); 880 send_list_del(info);