diff options
author | David S. Miller <davem@davemloft.net> | 2011-05-02 18:04:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-02 18:04:46 -0400 |
commit | dcfd9cdc1222f14d6180514e533289493a0716fb (patch) | |
tree | 8a60386e7e55c44fc08c02506380989a3c83a166 /net/batman-adv/soft-interface.c | |
parent | 5615787257742aab42ecf17c11e3244d9536a48d (diff) | |
parent | 32ae9b221e788413ce68feaae2ca39e406211a0a (diff) |
Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r-- | net/batman-adv/soft-interface.c | 64 |
1 files changed, 45 insertions, 19 deletions
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; | 248 | out: |
249 | if (primary_if) | ||
250 | hardif_free_ref(primary_if); | ||
251 | return ret; | ||
238 | } | 252 | } |
239 | 253 | ||
240 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | 254 | static 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 | ||
308 | out: | 329 | out: |
309 | softif_neigh_free_ref(softif_neigh); | ||
310 | err: | ||
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: | |||
462 | end: | 486 | end: |
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 | ||