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; }
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; }