diff options
Diffstat (limited to 'net/phonet')
-rw-r--r-- | net/phonet/af_phonet.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index cc2eef169a8b..66737aa995ea 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
@@ -394,6 +394,38 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
394 | send_obj_unreachable(skb); | 394 | send_obj_unreachable(skb); |
395 | send_reset_indications(skb); | 395 | send_reset_indications(skb); |
396 | } | 396 | } |
397 | } else if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) | ||
398 | goto out; /* Race between address deletion and loopback */ | ||
399 | else { | ||
400 | /* Phonet packet routing */ | ||
401 | struct net_device *out_dev; | ||
402 | |||
403 | out_dev = phonet_route_output(net, pn_sockaddr_get_addr(&sa)); | ||
404 | if (!out_dev) { | ||
405 | LIMIT_NETDEBUG(KERN_WARNING"No Phonet route to %02X\n", | ||
406 | pn_sockaddr_get_addr(&sa)); | ||
407 | goto out; | ||
408 | } | ||
409 | |||
410 | __skb_push(skb, sizeof(struct phonethdr)); | ||
411 | skb->dev = out_dev; | ||
412 | if (out_dev == dev) { | ||
413 | LIMIT_NETDEBUG(KERN_ERR"Phonet loop to %02X on %s\n", | ||
414 | pn_sockaddr_get_addr(&sa), dev->name); | ||
415 | goto out_dev; | ||
416 | } | ||
417 | /* Some drivers (e.g. TUN) do not allocate HW header space */ | ||
418 | if (skb_cow_head(skb, out_dev->hard_header_len)) | ||
419 | goto out_dev; | ||
420 | |||
421 | if (dev_hard_header(skb, out_dev, ETH_P_PHONET, NULL, NULL, | ||
422 | skb->len) < 0) | ||
423 | goto out_dev; | ||
424 | dev_queue_xmit(skb); | ||
425 | dev_put(out_dev); | ||
426 | return NET_RX_SUCCESS; | ||
427 | out_dev: | ||
428 | dev_put(out_dev); | ||
397 | } | 429 | } |
398 | 430 | ||
399 | out: | 431 | out: |