diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2014-01-30 04:11:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-30 19:25:49 -0500 |
commit | 0ae89beb283a0db5980d1d4781c7d7be2f2810d6 (patch) | |
tree | 70260be9219b03dbc8e96f852a8900db7845cbc9 /include/linux/can | |
parent | 920a0fde5a32fd40b4d3c94ad72f7fc7039db8e3 (diff) |
can: add destructor for self generated skbs
Self generated skbuffs in net/can/bcm.c are setting a skb->sk reference but
no explicit destructor which is enforced since Linux 3.11 with commit
376c7311bdb6 (net: add a temporary sanity check in skb_orphan()).
This patch adds some helper functions to make sure that a destructor is
properly defined when a sock reference is assigned to a CAN related skb.
To create an unshared skb owned by the original sock a common helper function
has been introduced to replace open coded functions to create CAN echo skbs.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Tested-by: Andre Naujoks <nautsch2@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/can')
-rw-r--r-- | include/linux/can/skb.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 2f0543f7510c..f9bbbb472663 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h | |||
@@ -11,7 +11,9 @@ | |||
11 | #define CAN_SKB_H | 11 | #define CAN_SKB_H |
12 | 12 | ||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/skbuff.h> | ||
14 | #include <linux/can.h> | 15 | #include <linux/can.h> |
16 | #include <net/sock.h> | ||
15 | 17 | ||
16 | /* | 18 | /* |
17 | * The struct can_skb_priv is used to transport additional information along | 19 | * The struct can_skb_priv is used to transport additional information along |
@@ -42,4 +44,40 @@ static inline void can_skb_reserve(struct sk_buff *skb) | |||
42 | skb_reserve(skb, sizeof(struct can_skb_priv)); | 44 | skb_reserve(skb, sizeof(struct can_skb_priv)); |
43 | } | 45 | } |
44 | 46 | ||
47 | static inline void can_skb_destructor(struct sk_buff *skb) | ||
48 | { | ||
49 | sock_put(skb->sk); | ||
50 | } | ||
51 | |||
52 | static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) | ||
53 | { | ||
54 | if (sk) { | ||
55 | sock_hold(sk); | ||
56 | skb->destructor = can_skb_destructor; | ||
57 | skb->sk = sk; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * returns an unshared skb owned by the original sock to be echo'ed back | ||
63 | */ | ||
64 | static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) | ||
65 | { | ||
66 | if (skb_shared(skb)) { | ||
67 | struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); | ||
68 | |||
69 | if (likely(nskb)) { | ||
70 | can_skb_set_owner(nskb, skb->sk); | ||
71 | consume_skb(skb); | ||
72 | return nskb; | ||
73 | } else { | ||
74 | kfree_skb(skb); | ||
75 | return NULL; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* we can assume to have an unshared skb with proper owner */ | ||
80 | return skb; | ||
81 | } | ||
82 | |||
45 | #endif /* CAN_SKB_H */ | 83 | #endif /* CAN_SKB_H */ |