示例#1
0
文件: igmp.c 项目: GNUHurdTR/hurd
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;
}