int igmp_rcv(struct sk_buff *skb, unsigned short len) { /* This basically follows the spec line by line -- see RFC1112 */ struct igmphdr *ih = skb->h.igmph; struct in_device *in_dev = skb->dev->ip_ptr; if (len < sizeof(struct igmphdr) || ip_compute_csum((void *)ih, len) || in_dev==NULL) { kfree_skb(skb); return 0; } switch (ih->type) { case IGMP_HOST_MEMBERSHIP_QUERY: igmp_heard_query(in_dev, ih->code, ih->group); break; case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_NEW_MEMBERSHIP_REPORT: /* Is it our report looped back? */ if (((struct rtable*)skb->dst)->key.iif == 0) break; igmp_heard_report(in_dev, ih->group); break; case IGMP_PIM: #ifdef CONFIG_IP_PIMSM_V1 return pim_rcv_v1(skb, len); #endif case IGMP_DVMRP: case IGMP_TRACE: case IGMP_HOST_LEAVE_MESSAGE: case IGMP_MTRACE: case IGMP_MTRACE_RESP: break; default: NETDEBUG(printk(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type)); } kfree_skb(skb); return 0; }
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; } #ifdef CONFIG_RG_IGMP_PROXY igmprx_recv(skb); #endif #ifdef CONFIG_RG_IGMP_PROXY_MODULE if (igmp_proxy_recv) igmp_proxy_recv(skb); #endif switch (ih->type) { case IGMP_HOST_MEMBERSHIP_QUERY: igmp_heard_query(in_dev, ih->code, ih->group); break; case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_NEW_MEMBERSHIP_REPORT: /* Is it our report looped back? */ if (((struct rtable*)skb->dst)->key.iif == 0) break; igmp_heard_report(in_dev, ih->group); break; case IGMP_PIM: #ifdef CONFIG_IP_PIMSM_V1 in_dev_put(in_dev); return pim_rcv_v1(skb); #endif case IGMP_DVMRP: case IGMP_TRACE: case IGMP_HOST_LEAVE_MESSAGE: case IGMP_MTRACE: case IGMP_MTRACE_RESP: break; default: // NETDEBUG(printk(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type)); ; } in_dev_put(in_dev); kfree_skb(skb); return 0; }