/* * 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; }
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); }
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); }
/* * 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; }
/* * 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; }