Ejemplo n.º 1
0
/*
 *	device multicast group inc (add if not found)
 */
int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev *idev;

	idev = in6_dev_get(dev);

	if (idev == NULL)
		return -EINVAL;

	write_lock_bh(&idev->lock);
	if (idev->dead) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENODEV;
	}

	for (mc = idev->mc_list; mc; mc = mc->next) {
		if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
			mc->mca_users++;
			write_unlock_bh(&idev->lock);
			in6_dev_put(idev);
			return 0;
		}
	}

	/*
	 *	not found: create a new one.
	 */

	mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);

	if (mc == NULL) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	memset(mc, 0, sizeof(struct ifmcaddr6));
	mc->mca_timer.function = igmp6_timer_handler;
	mc->mca_timer.data = (unsigned long) mc;

	memcpy(&mc->mca_addr, addr, sizeof(struct in6_addr));
	mc->idev = idev;
	mc->mca_users = 1;
	atomic_set(&mc->mca_refcnt, 2);
	mc->mca_lock = SPIN_LOCK_UNLOCKED;

	mc->next = idev->mc_list;
	idev->mc_list = mc;
	write_unlock_bh(&idev->lock);

	igmp6_group_added(mc);
	ma_put(mc);
	return 0;
}
Ejemplo n.º 2
0
void ipv6_mc_up(struct inet6_dev *idev)
{
	struct ifmcaddr6 *i;

	/* Install multicast list, except for all-nodes (already installed) */

	read_lock_bh(&idev->lock);
	for (i = idev->mc_list; i; i=i->next)
		igmp6_group_added(i);
	read_unlock_bh(&idev->lock);
}
Ejemplo n.º 3
0
void ipv6_mc_up(struct inet6_dev *idev)
{
	struct ifmcaddr6 *i;
	struct in6_addr maddr;

	/* Add all-nodes address. */

	ipv6_addr_all_nodes(&maddr);
	ipv6_dev_mc_inc(idev->dev, &maddr);

	/* Install multicast list, except for all-nodes (already installed) */

	for (i = idev->mc_list; i; i=i->if_next)
		igmp6_group_added(i);
}
Ejemplo n.º 4
0
/*
 *	device multicast group inc (add if not found)
 */
int ipv6_dev_mc_inc(struct device *dev, struct in6_addr *addr)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev    *idev;
	int hash;

	idev = ipv6_get_idev(dev);

	if (idev == NULL)
		return -EINVAL;

	hash = ipv6_addr_hash(addr);

	for (mc = inet6_mcast_lst[hash]; mc; mc = mc->next) {
		if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0 && mc->dev == dev) {
			atomic_inc(&mc->mca_users);
			return 0;
		}
	}

	/*
	 *	not found: create a new one.
	 */

	mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);

	if (mc == NULL)
		return -ENOMEM;

	memset(mc, 0, sizeof(struct ifmcaddr6));
	mc->mca_timer.function = igmp6_timer_handler;
	mc->mca_timer.data = (unsigned long) mc;

	memcpy(&mc->mca_addr, addr, sizeof(struct in6_addr));
	mc->dev = dev;
	atomic_set(&mc->mca_users, 1);

	mc->next = inet6_mcast_lst[hash];
	inet6_mcast_lst[hash] = mc;

	mc->if_next = idev->mc_list;
	idev->mc_list = mc;

	igmp6_group_added(mc);

	return 0;
}
Ejemplo n.º 5
0
/*
 *	device multicast group inc (add if not found)
 */
int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev *idev;

#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(addr, abuf);

	MDBG3((KERN_DEBUG
		"ipv6_dev_mc_inc(dev=%p(%s), addr=%s)\n",
		dev, dev->name ? dev->name :"<null>", abuf));
#endif

	idev = in6_dev_get(dev);

	if (idev == NULL)
		return -EINVAL;

	write_lock_bh(&idev->lock);
	if (idev->dead) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENODEV;
	}

	for (mc = idev->mc_list; mc; mc = mc->next) {
		if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
			mc->mca_users++;
			write_unlock_bh(&idev->lock);
			in6_dev_put(idev);
			return 0;
		}
	}

	/*
	 *	not found: create a new one.
	 */

	mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);

	if (mc == NULL) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	memset(mc, 0, sizeof(struct ifmcaddr6));
	mc->mca_timer.function = igmp6_timer_handler;
	mc->mca_timer.data = (unsigned long) mc;

	ipv6_addr_copy(&mc->mca_addr, addr);
	mc->idev = idev;
	mc->mca_users = 1;
	atomic_set(&mc->mca_refcnt, 2);
	mc->mca_lock = SPIN_LOCK_UNLOCKED;

	mc->next = idev->mc_list;
	idev->mc_list = mc;
	write_unlock_bh(&idev->lock);

	igmp6_group_added(mc);
	ma_put(mc);
	return 0;
}