diff options
author | Joonwoo Park <joonwpark81@gmail.com> | 2008-04-01 00:02:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-01 00:02:47 -0400 |
commit | f83f1768f833cb45bc93429fdc552252a4f55ac3 (patch) | |
tree | 15de7d2df2fc3a35e0a6b933bb37aefcba2cc3ef /net/llc/llc_sap.c | |
parent | b50660f1fe4ebd6129064e4fba0bd882b60c2425 (diff) |
[LLC]: skb allocation size for responses
Allocate the skb for llc responses with the received packet size by
using the size adjustable llc_frame_alloc.
Don't allocate useless extra payload.
Cleanup magic numbers.
So, this fixes oops.
Reported by Jim Westfall:
kernel: skb_over_panic: text:c0541fc7 len:1000 put:997 head:c166ac00 data:c166ac2f tail:0xc166b017 end:0xc166ac80 dev:eth0
kernel: ------------[ cut here ]------------
kernel: kernel BUG at net/core/skbuff.c:95!
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/llc/llc_sap.c')
-rw-r--r-- | net/llc/llc_sap.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 2525165e2e8f..e2ddde755019 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c | |||
@@ -24,20 +24,41 @@ | |||
24 | #include <net/tcp_states.h> | 24 | #include <net/tcp_states.h> |
25 | #include <linux/llc.h> | 25 | #include <linux/llc.h> |
26 | 26 | ||
27 | static int llc_mac_header_len(unsigned short devtype) | ||
28 | { | ||
29 | switch (devtype) { | ||
30 | case ARPHRD_ETHER: | ||
31 | case ARPHRD_LOOPBACK: | ||
32 | return sizeof(struct ethhdr); | ||
33 | #ifdef CONFIG_TR | ||
34 | case ARPHRD_IEEE802_TR: | ||
35 | return sizeof(struct trh_hdr); | ||
36 | #endif | ||
37 | } | ||
38 | return 0; | ||
39 | } | ||
40 | |||
27 | /** | 41 | /** |
28 | * llc_alloc_frame - allocates sk_buff for frame | 42 | * llc_alloc_frame - allocates sk_buff for frame |
29 | * @dev: network device this skb will be sent over | 43 | * @dev: network device this skb will be sent over |
44 | * @type: pdu type to allocate | ||
45 | * @data_size: data size to allocate | ||
30 | * | 46 | * |
31 | * Allocates an sk_buff for frame and initializes sk_buff fields. | 47 | * Allocates an sk_buff for frame and initializes sk_buff fields. |
32 | * Returns allocated skb or %NULL when out of memory. | 48 | * Returns allocated skb or %NULL when out of memory. |
33 | */ | 49 | */ |
34 | struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) | 50 | struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, |
51 | u8 type, u32 data_size) | ||
35 | { | 52 | { |
36 | struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); | 53 | int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; |
54 | struct sk_buff *skb; | ||
55 | |||
56 | hlen += llc_mac_header_len(dev->type); | ||
57 | skb = alloc_skb(hlen + data_size, GFP_ATOMIC); | ||
37 | 58 | ||
38 | if (skb) { | 59 | if (skb) { |
39 | skb_reset_mac_header(skb); | 60 | skb_reset_mac_header(skb); |
40 | skb_reserve(skb, 50); | 61 | skb_reserve(skb, hlen); |
41 | skb_reset_network_header(skb); | 62 | skb_reset_network_header(skb); |
42 | skb_reset_transport_header(skb); | 63 | skb_reset_transport_header(skb); |
43 | skb->protocol = htons(ETH_P_802_2); | 64 | skb->protocol = htons(ETH_P_802_2); |