예제 #1
0
파일: mcast.c 프로젝트: dmgerman/original
int igmp6_event_query(struct sk_buff *skb, struct icmp6hdr *hdr, int len)
{
	struct ifmcaddr6 *ma;
	struct in6_addr *addrp;
	unsigned long resptime;
	struct inet6_dev *idev;


	if (len < sizeof(struct icmp6hdr) + sizeof(struct in6_addr))
		return -EINVAL;

	/* Drop queries with not link local source */
	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
		return -EINVAL;

	resptime = ntohs(hdr->icmp6_maxdelay);
	/* Translate milliseconds to jiffies */
	resptime = (resptime<<10)/(1024000/HZ);

	addrp = (struct in6_addr *) (hdr + 1);

	idev = in6_dev_get(skb->dev);

	if (idev == NULL)
		return 0;

	read_lock(&idev->lock);
	if (ipv6_addr_any(addrp)) {
		for (ma = idev->mc_list; ma; ma=ma->next)
			igmp6_group_queried(ma, resptime);
	} else {
		for (ma = idev->mc_list; ma; ma=ma->next) {
			if (ipv6_addr_cmp(addrp, &ma->mca_addr) == 0) {
				igmp6_group_queried(ma, resptime);
				break;
			}
		}
	}
	read_unlock(&idev->lock);
	in6_dev_put(idev);

	return 0;
}
예제 #2
0
int igmp6_event_query(struct sk_buff *skb)
{
	struct ifmcaddr6 *ma;
	struct in6_addr *addrp;
	unsigned long resptime;
	struct inet6_dev *idev;
	struct icmp6hdr *hdr;
	int addr_type;
#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf1[128], abuf2[128];

	in6_ntop(&skb->nh.ipv6h->saddr, abuf1);
	in6_ntop(&skb->nh.ipv6h->daddr, abuf2);
	MDBG3((KERN_DEBUG
		"igmp6_event_query(skb=%p): saddr=%s, daddr=%s\n",
		skb, abuf1, abuf2));
#endif

	if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
		return -EINVAL;

	hdr = (struct icmp6hdr*) skb->h.raw;

	/* Drop queries with not link local source */
	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
 		return -EINVAL;

	resptime = ntohs(hdr->icmp6_maxdelay);
	addrp = (struct in6_addr *) (hdr + 1);

#ifdef CONFIG_IPV6_MLD6_DEBUG
	in6_ntop(addrp, abuf1);
	MDBG3((KERN_DEBUG
		"igmp6_event_query(): maxdelay=%lu, addr=%s\n",
		resptime, abuf1));
#endif

	/* Translate milliseconds to jiffies */
	resptime = (resptime<<10)/(1024000/HZ);

	addr_type = ipv6_addr_type(addrp);

	if (addr_type == IPV6_ADDR_ANY ||
	    (addr_type & IPV6_ADDR_MULTICAST) == 0)
		goto drop;

	idev = in6_dev_get(skb->dev);

	if (idev == NULL)
		return 0;

	read_lock(&idev->lock);
	if (addr_type == IPV6_ADDR_ANY) {
		for (ma = idev->mc_list; ma; ma=ma->next)
			igmp6_group_queried(ma, resptime);
	} else {
		for (ma = idev->mc_list; ma; ma=ma->next) {
			if (ipv6_addr_cmp(addrp, &ma->mca_addr) == 0) {
				igmp6_group_queried(ma, resptime);
				break;
			}
		}
	}
	read_unlock(&idev->lock);
	in6_dev_put(idev);
  drop:
	return 0;
}