Ejemplo n.º 1
0
static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
{
	unsigned long delay = resptime;

	MDBG3((KERN_DEBUG
		"igmp6_group_queried(ma=%p, resptime=%lu)\n",
		ma, resptime));

	/* Do not start timer for addresses with reserved/host scope */
	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
		return;

	spin_lock(&ma->mca_lock);
	if (del_timer(&ma->mca_timer)) {
		atomic_dec(&ma->mca_refcnt);
		delay = ma->mca_timer.expires - jiffies;
	}

	if (delay >= resptime) {
		if (resptime) {
			get_random_bytes(&delay, sizeof(delay));
			delay %= resptime;
		} else
			delay = 1;
	}

	ma->mca_timer.expires = jiffies + delay;
	if (!mod_timer(&ma->mca_timer, jiffies + delay))
		atomic_inc(&ma->mca_refcnt);
	spin_unlock(&ma->mca_lock);
}
Ejemplo n.º 2
0
static void igmp6_join_group(struct ifmcaddr6 *ma)
{
	unsigned long delay;
#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(&ma->mca_addr, abuf);

	MDBG3((KERN_DEBUG
		"igmp6_join_group(ma=%p): mca_addr=%s\n",
		ma, abuf));
#endif

	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
		return;

	igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);

	get_random_bytes(&delay, sizeof(delay));
	delay %= IGMP6_UNSOLICITED_IVAL;

	spin_lock_bh(&ma->mca_lock);
	if (del_timer(&ma->mca_timer)) {
		atomic_dec(&ma->mca_refcnt);
		delay = ma->mca_timer.expires - jiffies;
	}

	if (!mod_timer(&ma->mca_timer, jiffies + delay))
		atomic_inc(&ma->mca_refcnt);
	ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
	spin_unlock_bh(&ma->mca_lock);
}
Ejemplo n.º 3
0
static int ipv6_mc_check_mld_query(struct sk_buff *skb)
{
	unsigned int transport_len = ipv6_transport_len(skb);
	struct mld_msg *mld;
	unsigned int len;

	/* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
	if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL))
		return -EINVAL;

	/* MLDv1? */
	if (transport_len != sizeof(struct mld_msg)) {
		/* or MLDv2? */
		if (transport_len < sizeof(struct mld2_query))
			return -EINVAL;

		len = skb_transport_offset(skb) + sizeof(struct mld2_query);
		if (!ipv6_mc_may_pull(skb, len))
			return -EINVAL;
	}

	mld = (struct mld_msg *)skb_transport_header(skb);

	/* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
	 * all-nodes destination address (ff02::1) for general queries
	 */
	if (ipv6_addr_any(&mld->mld_mca) &&
	    !ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr))
		return -EINVAL;

	return 0;
}
Ejemplo n.º 4
0
static void igmp6_leave_group(struct ifmcaddr6 *ma)
{
#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(&ma->mca_addr, abuf);

	MDBG3((KERN_DEBUG
		"igmp6_leave_group(ma=%p): mca_addr=%s\n",
		ma, abuf));
#endif

	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
		return;

	if (ma->mca_flags & MAF_LAST_REPORTER)
		igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REDUCTION);

	spin_lock_bh(&ma->mca_lock);
	if (del_timer(&ma->mca_timer))
		atomic_dec(&ma->mca_refcnt);
	spin_unlock_bh(&ma->mca_lock);
}