diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/gre.c | 21 |
1 files changed, 6 insertions, 15 deletions
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 9dbe10875fbd..dbfc21de3479 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kmod.h> | 15 | #include <linux/kmod.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/in.h> | 17 | #include <linux/in.h> |
18 | #include <linux/ip.h> | ||
18 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
20 | #include <net/protocol.h> | 21 | #include <net/protocol.h> |
@@ -96,27 +97,17 @@ drop: | |||
96 | static void gre_err(struct sk_buff *skb, u32 info) | 97 | static void gre_err(struct sk_buff *skb, u32 info) |
97 | { | 98 | { |
98 | const struct gre_protocol *proto; | 99 | const struct gre_protocol *proto; |
99 | u8 ver; | 100 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
100 | 101 | u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f; | |
101 | if (!pskb_may_pull(skb, 12)) | ||
102 | goto drop; | ||
103 | 102 | ||
104 | ver = skb->data[1]&0x7f; | ||
105 | if (ver >= GREPROTO_MAX) | 103 | if (ver >= GREPROTO_MAX) |
106 | goto drop; | 104 | return; |
107 | 105 | ||
108 | rcu_read_lock(); | 106 | rcu_read_lock(); |
109 | proto = rcu_dereference(gre_proto[ver]); | 107 | proto = rcu_dereference(gre_proto[ver]); |
110 | if (!proto || !proto->err_handler) | 108 | if (proto && proto->err_handler) |
111 | goto drop_unlock; | 109 | proto->err_handler(skb, info); |
112 | proto->err_handler(skb, info); | ||
113 | rcu_read_unlock(); | ||
114 | return; | ||
115 | |||
116 | drop_unlock: | ||
117 | rcu_read_unlock(); | 110 | rcu_read_unlock(); |
118 | drop: | ||
119 | kfree_skb(skb); | ||
120 | } | 111 | } |
121 | 112 | ||
122 | static const struct net_protocol net_gre_protocol = { | 113 | static const struct net_protocol net_gre_protocol = { |