diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:11:38 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:11:38 -0800 |
| commit | 1a0153507ffae9cf3350e76c12d441788c0191e1 (patch) | |
| tree | d05a502b4fc05202c84c1667019460c08ea088cd /net/ipv4/igmp.c | |
| parent | b0683ac8928c4cf40646a6ce3eb6ffe94605acfa (diff) | |
v2.4.3.2 -> v2.4.3.3
- Hui-Fen Hsu: sis900 driver update
- NIIBE Yutaka: Super-H update
- Alan Cox: more resyncs (ARM down, but more to go)
- David Miller: network zerocopy, Sparc sync, qlogic,FC fix, etc.
- David Miller/me: get rid of various drivers hacks to do mmap
alignment behind the back of the VM layer. Create a real
protocol for it.
Diffstat (limited to 'net/ipv4/igmp.c')
| -rw-r--r-- | net/ipv4/igmp.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 81fae9233744..f2e69603ce4b 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -8,7 +8,7 @@ * the older version didn't come out right using gcc 2.5.8, the newer one * seems to fall out with gcc 2.6.2. * - * Version: $Id: igmp.c,v 1.41 2000/08/31 23:39:12 davem Exp $ + * Version: $Id: igmp.c,v 1.45 2001/02/23 06:32:11 davem Exp $ * * Authors: * Alan Cox <Alan.Cox@linux.org> @@ -235,7 +235,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) iph->saddr = rt->rt_src; iph->protocol = IPPROTO_IGMP; iph->tot_len = htons(IGMP_SIZE); - ip_select_ident(iph, &rt->u.dst); + ip_select_ident(iph, &rt->u.dst, NULL); ((u8*)&iph[1])[0] = IPOPT_RA; ((u8*)&iph[1])[1] = 4; ((u8*)&iph[1])[2] = 0; @@ -341,23 +341,32 @@ static void igmp_heard_query(struct in_device *in_dev, unsigned char max_resp_ti read_unlock(&in_dev->lock); } -int igmp_rcv(struct sk_buff *skb, unsigned short len) +int igmp_rcv(struct sk_buff *skb) { /* This basically follows the spec line by line -- see RFC1112 */ struct igmphdr *ih = skb->h.igmph; struct in_device *in_dev = in_dev_get(skb->dev); + int len = skb->len; if (in_dev==NULL) { kfree_skb(skb); return 0; } + if (skb_is_nonlinear(skb)) { + if (skb_linearize(skb, GFP_ATOMIC) != 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); kfree_skb(skb); return 0; } - + switch (ih->type) { case IGMP_HOST_MEMBERSHIP_QUERY: igmp_heard_query(in_dev, ih->code, ih->group); @@ -372,7 +381,7 @@ int igmp_rcv(struct sk_buff *skb, unsigned short len) case IGMP_PIM: #ifdef CONFIG_IP_PIMSM_V1 in_dev_put(in_dev); - return pim_rcv_v1(skb, len); + return pim_rcv_v1(skb); #endif case IGMP_DVMRP: case IGMP_TRACE: |
