aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-05-02 18:04:46 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-02 18:04:46 -0400
commitdcfd9cdc1222f14d6180514e533289493a0716fb (patch)
tree8a60386e7e55c44fc08c02506380989a3c83a166 /net/batman-adv
parent5615787257742aab42ecf17c11e3244d9536a48d (diff)
parent32ae9b221e788413ce68feaae2ca39e406211a0a (diff)
Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/aggregation.c1
-rw-r--r--net/batman-adv/gateway_client.c45
-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/main.h2
-rw-r--r--net/batman-adv/originator.c34
-rw-r--r--net/batman-adv/routing.c34
-rw-r--r--net/batman-adv/send.c18
-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
14 files changed, 292 insertions, 138 deletions
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
index af45d6b2031f..c11788c4c1a1 100644
--- a/net/batman-adv/aggregation.c
+++ b/net/batman-adv/aggregation.c
@@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
95 return false; 95 return false;
96} 96}
97 97
98#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
99/* create a new aggregated packet and add this packet to it */ 98/* create a new aggregated packet and add this packet to it */
100static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, 99static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
101 unsigned long send_time, bool direct_link, 100 unsigned long send_time, bool direct_link,
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 2acd7a666bda..65f39530799d 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv)
127 return; 127 return;
128 128
129 curr_gw = gw_get_selected_gw_node(bat_priv); 129 curr_gw = gw_get_selected_gw_node(bat_priv);
130 if (!curr_gw) 130 if (curr_gw)
131 goto out; 131 goto out;
132 132
133 rcu_read_lock(); 133 rcu_read_lock();
@@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv,
310 struct hlist_node *node; 310 struct hlist_node *node;
311 struct gw_node *gw_node, *curr_gw; 311 struct gw_node *gw_node, *curr_gw;
312 312
313 /**
314 * Note: We don't need a NULL check here, since curr_gw never gets
315 * dereferenced. If curr_gw is NULL we also should not exit as we may
316 * have this gateway in our list (duplication check!) even though we
317 * have no currently selected gateway.
318 */
313 curr_gw = gw_get_selected_gw_node(bat_priv); 319 curr_gw = gw_get_selected_gw_node(bat_priv);
314 if (!curr_gw)
315 goto out;
316 320
317 rcu_read_lock(); 321 rcu_read_lock();
318 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { 322 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -350,7 +354,7 @@ deselect:
350 gw_deselect(bat_priv); 354 gw_deselect(bat_priv);
351unlock: 355unlock:
352 rcu_read_unlock(); 356 rcu_read_unlock();
353out: 357
354 if (curr_gw) 358 if (curr_gw)
355 gw_node_free_ref(curr_gw); 359 gw_node_free_ref(curr_gw);
356} 360}
@@ -435,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
435{ 439{
436 struct net_device *net_dev = (struct net_device *)seq->private; 440 struct net_device *net_dev = (struct net_device *)seq->private;
437 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;
438 struct gw_node *gw_node; 443 struct gw_node *gw_node;
439 struct hlist_node *node; 444 struct hlist_node *node;
440 int gw_count = 0; 445 int gw_count = 0, ret = 0;
441 446
442 if (!bat_priv->primary_if) { 447 primary_if = primary_if_get_selected(bat_priv);
443 448 if (!primary_if) {
444 return seq_printf(seq, "BATMAN mesh %s disabled - please " 449 ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
445 "specify interfaces to enable it\n", 450 "specify interfaces to enable it\n",
446 net_dev->name); 451 net_dev->name);
452 goto out;
447 } 453 }
448 454
449 if (bat_priv->primary_if->if_status != IF_ACTIVE) { 455 if (primary_if->if_status != IF_ACTIVE) {
450 456 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
451 return seq_printf(seq, "BATMAN mesh %s disabled - " 457 "primary interface not active\n",
452 "primary interface not active\n", 458 net_dev->name);
453 net_dev->name); 459 goto out;
454 } 460 }
455 461
456 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " 462 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
457 "[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",
458 "Gateway", "#", TQ_MAX_VALUE, "Nexthop", 464 "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
459 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, 465 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
460 bat_priv->primary_if->net_dev->name, 466 primary_if->net_dev->name,
461 bat_priv->primary_if->net_dev->dev_addr, net_dev->name); 467 primary_if->net_dev->dev_addr, net_dev->name);
462 468
463 rcu_read_lock(); 469 rcu_read_lock();
464 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) {
@@ -476,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
476 if (gw_count == 0) 482 if (gw_count == 0)
477 seq_printf(seq, "No gateways in range ...\n"); 483 seq_printf(seq, "No gateways in range ...\n");
478 484
479 return 0; 485out:
486 if (primary_if)
487 hardif_free_ref(primary_if);
488 return ret;
480} 489}
481 490
482int 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/main.h b/net/batman-adv/main.h
index dc248697de71..ace72852ed7b 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -175,4 +175,6 @@ static inline int compare_eth(void *data1, void *data2)
175 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); 175 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
176} 176}
177 177
178#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
179
178#endif /* _NET_BATMAN_ADV_MAIN_H_ */ 180#endif /* _NET_BATMAN_ADV_MAIN_H_ */
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 f6c642246972..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)
@@ -1310,13 +1316,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
1310 } 1316 }
1311 1317
1312 /* get routing information */ 1318 /* get routing information */
1313 rcu_read_lock();
1314 orig_node = orig_hash_find(bat_priv, unicast_packet->dest); 1319 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1315 1320
1316 if (!orig_node) 1321 if (!orig_node)
1317 goto unlock; 1322 goto out;
1318
1319 rcu_read_unlock();
1320 1323
1321 /* find_router() increases neigh_nodes refcount if found. */ 1324 /* find_router() increases neigh_nodes refcount if found. */
1322 neigh_node = find_router(bat_priv, orig_node, recv_if); 1325 neigh_node = find_router(bat_priv, orig_node, recv_if);
@@ -1362,10 +1365,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
1362 /* route it */ 1365 /* route it */
1363 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 1366 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1364 ret = NET_RX_SUCCESS; 1367 ret = NET_RX_SUCCESS;
1365 goto out;
1366 1368
1367unlock:
1368 rcu_read_unlock();
1369out: 1369out:
1370 if (neigh_node) 1370 if (neigh_node)
1371 neigh_node_free_ref(neigh_node); 1371 neigh_node_free_ref(neigh_node);
@@ -1464,13 +1464,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
1464 if (bcast_packet->ttl < 2) 1464 if (bcast_packet->ttl < 2)
1465 goto out; 1465 goto out;
1466 1466
1467 rcu_read_lock();
1468 orig_node = orig_hash_find(bat_priv, bcast_packet->orig); 1467 orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
1469 1468
1470 if (!orig_node) 1469 if (!orig_node)
1471 goto rcu_unlock; 1470 goto out;
1472
1473 rcu_read_unlock();
1474 1471
1475 spin_lock_bh(&orig_node->bcast_seqno_lock); 1472 spin_lock_bh(&orig_node->bcast_seqno_lock);
1476 1473
@@ -1501,9 +1498,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
1501 ret = NET_RX_SUCCESS; 1498 ret = NET_RX_SUCCESS;
1502 goto out; 1499 goto out;
1503 1500
1504rcu_unlock:
1505 rcu_read_unlock();
1506 goto out;
1507spin_unlock: 1501spin_unlock:
1508 spin_unlock_bh(&orig_node->bcast_seqno_lock); 1502 spin_unlock_bh(&orig_node->bcast_seqno_lock);
1509out: 1503out:
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index e78670c3c4b7..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,
@@ -393,7 +398,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
393 send_time); 398 send_time);
394} 399}
395 400
396#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
397/* add a broadcast packet to the queue and setup timers. broadcast packets 401/* add a broadcast packet to the queue and setup timers. broadcast packets
398 * are sent multiple times to increase probability for beeing received. 402 * are sent multiple times to increase probability for beeing received.
399 * 403 *
@@ -404,6 +408,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
404 * skb is freed. */ 408 * skb is freed. */
405int 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)
406{ 410{
411 struct hard_iface *primary_if = NULL;
407 struct forw_packet *forw_packet; 412 struct forw_packet *forw_packet;
408 struct bcast_packet *bcast_packet; 413 struct bcast_packet *bcast_packet;
409 414
@@ -412,7 +417,8 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
412 goto out; 417 goto out;
413 } 418 }
414 419
415 if (!bat_priv->primary_if) 420 primary_if = primary_if_get_selected(bat_priv);
421 if (!primary_if)
416 goto out; 422 goto out;
417 423
418 forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); 424 forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
@@ -431,7 +437,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
431 skb_reset_mac_header(skb); 437 skb_reset_mac_header(skb);
432 438
433 forw_packet->skb = skb; 439 forw_packet->skb = skb;
434 forw_packet->if_incoming = bat_priv->primary_if; 440 forw_packet->if_incoming = primary_if;
435 441
436 /* how often did we send the bcast packet ? */ 442 /* how often did we send the bcast packet ? */
437 forw_packet->num_packets = 0; 443 forw_packet->num_packets = 0;
@@ -444,6 +450,8 @@ packet_free:
444out_and_inc: 450out_and_inc:
445 atomic_inc(&bat_priv->bcast_queue_left); 451 atomic_inc(&bat_priv->bcast_queue_left);
446out: 452out:
453 if (primary_if)
454 hardif_free_ref(primary_if);
447 return NETDEV_TX_BUSY; 455 return NETDEV_TX_BUSY;
448} 456}
449 457
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index eeabbb89172c..9e5fcd1596cf 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -211,13 +211,24 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
211 struct net_device *net_dev = (struct net_device *)seq->private; 211 struct net_device *net_dev = (struct net_device *)seq->private;
212 struct bat_priv *bat_priv = netdev_priv(net_dev); 212 struct bat_priv *bat_priv = netdev_priv(net_dev);
213 struct softif_neigh *softif_neigh; 213 struct softif_neigh *softif_neigh;
214 struct hard_iface *primary_if;
214 struct hlist_node *node; 215 struct hlist_node *node;
215 struct softif_neigh *curr_softif_neigh; 216 struct softif_neigh *curr_softif_neigh;
217 int ret = 0;
216 218
217 if (!bat_priv->primary_if) { 219 primary_if = primary_if_get_selected(bat_priv);
218 return seq_printf(seq, "BATMAN mesh %s disabled - " 220 if (!primary_if) {
219 "please specify interfaces to enable it\n", 221 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
220 net_dev->name); 222 "please specify interfaces to enable it\n",
223 net_dev->name);
224 goto out;
225 }
226
227 if (primary_if->if_status != IF_ACTIVE) {
228 ret = seq_printf(seq, "BATMAN mesh %s "
229 "disabled - primary interface not active\n",
230 net_dev->name);
231 goto out;
221 } 232 }
222 233
223 seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); 234 seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
@@ -234,7 +245,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
234 if (curr_softif_neigh) 245 if (curr_softif_neigh)
235 softif_neigh_free_ref(curr_softif_neigh); 246 softif_neigh_free_ref(curr_softif_neigh);
236 247
237 return 0; 248out:
249 if (primary_if)
250 hardif_free_ref(primary_if);
251 return ret;
238} 252}
239 253
240static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, 254static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
@@ -243,7 +257,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
243 struct bat_priv *bat_priv = netdev_priv(dev); 257 struct bat_priv *bat_priv = netdev_priv(dev);
244 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 258 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
245 struct batman_packet *batman_packet; 259 struct batman_packet *batman_packet;
246 struct softif_neigh *softif_neigh; 260 struct softif_neigh *softif_neigh = NULL;
261 struct hard_iface *primary_if = NULL;
247 struct softif_neigh *curr_softif_neigh = NULL; 262 struct softif_neigh *curr_softif_neigh = NULL;
248 263
249 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) 264 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
@@ -253,28 +268,34 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
253 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); 268 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
254 269
255 if (batman_packet->version != COMPAT_VERSION) 270 if (batman_packet->version != COMPAT_VERSION)
256 goto err; 271 goto out;
257 272
258 if (batman_packet->packet_type != BAT_PACKET) 273 if (batman_packet->packet_type != BAT_PACKET)
259 goto err; 274 goto out;
260 275
261 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) 276 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
262 goto err; 277 goto out;
263 278
264 if (is_my_mac(batman_packet->orig)) 279 if (is_my_mac(batman_packet->orig))
265 goto err; 280 goto out;
266 281
267 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); 282 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
268
269 if (!softif_neigh) 283 if (!softif_neigh)
270 goto err; 284 goto out;
271 285
272 curr_softif_neigh = softif_neigh_get_selected(bat_priv); 286 curr_softif_neigh = softif_neigh_get_selected(bat_priv);
287 if (!curr_softif_neigh)
288 goto out;
289
273 if (curr_softif_neigh == softif_neigh) 290 if (curr_softif_neigh == softif_neigh)
274 goto out; 291 goto out;
275 292
293 primary_if = primary_if_get_selected(bat_priv);
294 if (!primary_if)
295 goto out;
296
276 /* we got a neighbor but its mac is 'bigger' than ours */ 297 /* we got a neighbor but its mac is 'bigger' than ours */
277 if (memcmp(bat_priv->primary_if->net_dev->dev_addr, 298 if (memcmp(primary_if->net_dev->dev_addr,
278 softif_neigh->addr, ETH_ALEN) < 0) 299 softif_neigh->addr, ETH_ALEN) < 0)
279 goto out; 300 goto out;
280 301
@@ -296,7 +317,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
296 /* close own batX device and use softif_neigh as exit node */ 317 /* close own batX device and use softif_neigh as exit node */
297 if ((!curr_softif_neigh) && 318 if ((!curr_softif_neigh) &&
298 (memcmp(softif_neigh->addr, 319 (memcmp(softif_neigh->addr,
299 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { 320 primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
300 bat_dbg(DBG_ROUTES, bat_priv, 321 bat_dbg(DBG_ROUTES, bat_priv,
301 "Setting mesh exit point to %pM (vid: %d).\n", 322 "Setting mesh exit point to %pM (vid: %d).\n",
302 softif_neigh->addr, softif_neigh->vid); 323 softif_neigh->addr, softif_neigh->vid);
@@ -306,12 +327,13 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
306 } 327 }
307 328
308out: 329out:
309 softif_neigh_free_ref(softif_neigh);
310err:
311 kfree_skb(skb); 330 kfree_skb(skb);
331 if (softif_neigh)
332 softif_neigh_free_ref(softif_neigh);
312 if (curr_softif_neigh) 333 if (curr_softif_neigh)
313 softif_neigh_free_ref(curr_softif_neigh); 334 softif_neigh_free_ref(curr_softif_neigh);
314 335 if (primary_if)
336 hardif_free_ref(primary_if);
315 return; 337 return;
316} 338}
317 339
@@ -367,6 +389,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
367{ 389{
368 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 390 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
369 struct bat_priv *bat_priv = netdev_priv(soft_iface); 391 struct bat_priv *bat_priv = netdev_priv(soft_iface);
392 struct hard_iface *primary_if = NULL;
370 struct bcast_packet *bcast_packet; 393 struct bcast_packet *bcast_packet;
371 struct vlan_ethhdr *vhdr; 394 struct vlan_ethhdr *vhdr;
372 struct softif_neigh *curr_softif_neigh = NULL; 395 struct softif_neigh *curr_softif_neigh = NULL;
@@ -416,7 +439,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
416 439
417 /* ethernet packet should be broadcasted */ 440 /* ethernet packet should be broadcasted */
418 if (do_bcast) { 441 if (do_bcast) {
419 if (!bat_priv->primary_if) 442 primary_if = primary_if_get_selected(bat_priv);
443 if (!primary_if)
420 goto dropped; 444 goto dropped;
421 445
422 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) 446 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
@@ -432,7 +456,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
432 /* hw address of first interface is the orig mac because only 456 /* hw address of first interface is the orig mac because only
433 * this mac is known throughout the mesh */ 457 * this mac is known throughout the mesh */
434 memcpy(bcast_packet->orig, 458 memcpy(bcast_packet->orig,
435 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 459 primary_if->net_dev->dev_addr, ETH_ALEN);
436 460
437 /* set broadcast sequence number */ 461 /* set broadcast sequence number */
438 bcast_packet->seqno = 462 bcast_packet->seqno =
@@ -462,6 +486,8 @@ dropped_freed:
462end: 486end:
463 if (curr_softif_neigh) 487 if (curr_softif_neigh)
464 softif_neigh_free_ref(curr_softif_neigh); 488 softif_neigh_free_ref(curr_softif_neigh);
489 if (primary_if)
490 hardif_free_ref(primary_if);
465 return NETDEV_TX_OK; 491 return NETDEV_TX_OK;
466} 492}
467 493
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);