Commit 0c12c24b authored by Stephen Hemminger's avatar Stephen Hemminger

[NET] remove skb_linearize from igmp.c

parent 344fd4e1
...@@ -757,9 +757,10 @@ static void igmp_heard_report(struct in_device *in_dev, u32 group) ...@@ -757,9 +757,10 @@ static void igmp_heard_report(struct in_device *in_dev, u32 group)
read_unlock(&in_dev->lock); read_unlock(&in_dev->lock);
} }
static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih, static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
int len) int len)
{ {
struct igmphdr *ih = skb->h.igmph;
struct igmpv3_query *ih3 = (struct igmpv3_query *)ih; struct igmpv3_query *ih3 = (struct igmpv3_query *)ih;
struct ip_mc_list *im; struct ip_mc_list *im;
u32 group = ih->group; u32 group = ih->group;
...@@ -790,6 +791,17 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih, ...@@ -790,6 +791,17 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
} else if (len < 12) { } else if (len < 12) {
return; /* ignore bogus packet; freed by caller */ return; /* ignore bogus packet; freed by caller */
} else { /* v3 */ } else { /* v3 */
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
return;
ih3 = (struct igmpv3_query *) skb->h.raw;
if (ih3->nsrcs) {
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
+ ntohs(ih3->nsrcs)*sizeof(__u32)))
return;
ih3 = (struct igmpv3_query *) skb->h.raw;
}
max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
if (!max_delay) if (!max_delay)
max_delay = 1; /* can't mod w/ 0 */ max_delay = 1; /* can't mod w/ 0 */
...@@ -838,7 +850,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih, ...@@ -838,7 +850,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
int igmp_rcv(struct sk_buff *skb) int igmp_rcv(struct sk_buff *skb)
{ {
/* This basically follows the spec line by line -- see RFC1112 */ /* This basically follows the spec line by line -- see RFC1112 */
struct igmphdr *ih = skb->h.igmph; struct igmphdr *ih;
struct in_device *in_dev = in_dev_get(skb->dev); struct in_device *in_dev = in_dev_get(skb->dev);
int len = skb->len; int len = skb->len;
...@@ -847,23 +859,17 @@ int igmp_rcv(struct sk_buff *skb) ...@@ -847,23 +859,17 @@ int igmp_rcv(struct sk_buff *skb)
return 0; return 0;
} }
if (skb_is_nonlinear(skb)) { if (!pskb_may_pull(skb, sizeof(struct igmphdr)) ||
if (skb_linearize(skb, GFP_ATOMIC) != 0) { (u16)csum_fold(skb_checksum(skb, 0, len, 0))) {
kfree_skb(skb);
return -ENOMEM;
}
ih = skb->h.igmph;
}
if (len < sizeof(struct igmphdr) || ip_compute_csum((void *)ih, len)) {
in_dev_put(in_dev); in_dev_put(in_dev);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
ih = skb->h.igmph;
switch (ih->type) { switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_QUERY: case IGMP_HOST_MEMBERSHIP_QUERY:
igmp_heard_query(in_dev, ih, len); igmp_heard_query(in_dev, skb, len);
break; break;
case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment