summaryrefslogtreecommitdiff
path: root/net/ipv4/igmp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:11:38 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:11:38 -0800
commit1a0153507ffae9cf3350e76c12d441788c0191e1 (patch)
treed05a502b4fc05202c84c1667019460c08ea088cd /net/ipv4/igmp.c
parentb0683ac8928c4cf40646a6ce3eb6ffe94605acfa (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.c19
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: