Skip to content

Commit

Permalink
can: Fix can_send() handling on dev_queue_xmit() failures
Browse files Browse the repository at this point in the history
The tx packet counting and the local loopback of CAN frames should
only happen in the case that the CAN frame has been enqueued to the
netdevice tx queue successfully.

Thanks to Andre Naujoks <[email protected]> for reporting this issue.

Signed-off-by: Oliver Hartkopp <[email protected]>
Signed-off-by: Urs Thuermann <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Oliver Hartkopp authored and davem330 committed May 8, 2008
1 parent 33f9936 commit c2ab7ac
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions net/can/af_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
*/
int can_send(struct sk_buff *skb, int loop)
{
struct sk_buff *newskb = NULL;
int err;

if (skb->dev->type != ARPHRD_CAN) {
Expand Down Expand Up @@ -244,8 +245,7 @@ int can_send(struct sk_buff *skb, int loop)
* If the interface is not capable to do loopback
* itself, we do it here.
*/
struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);

newskb = skb_clone(skb, GFP_ATOMIC);
if (!newskb) {
kfree_skb(skb);
return -ENOMEM;
Expand All @@ -254,7 +254,6 @@ int can_send(struct sk_buff *skb, int loop)
newskb->sk = skb->sk;
newskb->ip_summed = CHECKSUM_UNNECESSARY;
newskb->pkt_type = PACKET_BROADCAST;
netif_rx(newskb);
}
} else {
/* indication for the CAN driver: no loopback required */
Expand All @@ -266,11 +265,20 @@ int can_send(struct sk_buff *skb, int loop)
if (err > 0)
err = net_xmit_errno(err);

if (err) {
if (newskb)
kfree_skb(newskb);
return err;
}

if (newskb)
netif_rx(newskb);

/* update statistics */
can_stats.tx_frames++;
can_stats.tx_frames_delta++;

return err;
return 0;
}
EXPORT_SYMBOL(can_send);

Expand Down

0 comments on commit c2ab7ac

Please sign in to comment.