void ipv6_sock_mc_close(struct sock *sk) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_mc_socklist *mc_lst; MDBG3((KERN_DEBUG "ipv6_sock_mc_close(sk=%p)\n", sk)); write_lock_bh(&ipv6_sk_mc_lock); while ((mc_lst = np->ipv6_mc_list) != NULL) { struct net_device *dev; np->ipv6_mc_list = mc_lst->next; write_unlock_bh(&ipv6_sk_mc_lock); dev = dev_get_by_index(mc_lst->ifindex); if (dev) { ipv6_dev_mc_dec(dev, &mc_lst->addr); dev_put(dev); } sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); write_lock_bh(&ipv6_sk_mc_lock); } write_unlock_bh(&ipv6_sk_mc_lock); }
static void addrconf_leave_solict(struct device *dev, struct in6_addr *addr) { struct in6_addr maddr; if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) return; #ifndef CONFIG_IPV6_NO_PB addrconf_addr_solict_mult_old(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); #endif #ifdef CONFIG_IPV6_EUI64 addrconf_addr_solict_mult_new(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); #endif }
/* * socket leave on multicast group */ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_mc_socklist *mc_lst, **lnk; #ifdef CONFIG_IPV6_MLD6_DEBUG char abuf[128]; in6_ntop(addr, abuf); MDBG3((KERN_DEBUG "ipv6_sock_mc_drop(sk=%p, ifindex=%d, addr=%s)\n", sk, ifindex, abuf)); #endif write_lock_bh(&ipv6_sk_mc_lock); for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { if ((ifindex == 0 || mc_lst->ifindex == ifindex) && ipv6_addr_cmp(&mc_lst->addr, addr) == 0) { struct net_device *dev; *lnk = mc_lst->next; write_unlock_bh(&ipv6_sk_mc_lock); /* Note: mc_lst->ifindex != 0 */ if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { ipv6_dev_mc_dec(dev, &mc_lst->addr); dev_put(dev); } sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return 0; } } write_unlock_bh(&ipv6_sk_mc_lock); return -ENOENT; }
/* * socket leave on multicast group */ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_mc_socklist *mc_lst, **lnk; write_lock_bh(&ipv6_sk_mc_lock); for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { if (mc_lst->ifindex == ifindex && ipv6_addr_cmp(&mc_lst->addr, addr) == 0) { struct net_device *dev; *lnk = mc_lst->next; write_unlock_bh(&ipv6_sk_mc_lock); if ((dev = dev_get_by_index(ifindex)) != NULL) { ipv6_dev_mc_dec(dev, &mc_lst->addr); dev_put(dev); } sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return 0; } } write_unlock_bh(&ipv6_sk_mc_lock); return -ENOENT; }
static void pndisc_destructor(struct pneigh_entry *n) { struct in6_addr *addr = (struct in6_addr*)&n->key; struct in6_addr maddr; struct net_device *dev = n->dev; if (dev == NULL || __in6_dev_get(dev) == NULL) return; #ifndef CONFIG_IPV6_NO_PB addrconf_addr_solict_mult_old(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); #endif #ifdef CONFIG_IPV6_EUI64 addrconf_addr_solict_mult_new(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); #endif }
static void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr) { struct in6_addr maddr; if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) return; addrconf_addr_solict_mult(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); }
static void pndisc_destructor(struct pneigh_entry *n) { struct in6_addr *addr = (struct in6_addr*)&n->key; struct in6_addr maddr; struct net_device *dev = n->dev; if (dev == NULL || __in6_dev_get(dev) == NULL) return; addrconf_addr_solict_mult(addr, &maddr); ipv6_dev_mc_dec(dev, &maddr); }
void ipv6_mc_down(struct inet6_dev *idev) { struct ifmcaddr6 *i; struct in6_addr maddr; /* Withdraw multicast list */ for (i = idev->mc_list; i; i=i->if_next) igmp6_group_dropped(i); /* Delete all-nodes address. */ ipv6_addr_all_nodes(&maddr); ipv6_dev_mc_dec(idev->dev, &maddr); }
void ipv6_sock_mc_close(struct sock *sk) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_mc_socklist *mc_lst; while ((mc_lst = np->ipv6_mc_list) != NULL) { struct device *dev = dev_get_by_index(mc_lst->ifindex); if (dev) ipv6_dev_mc_dec(dev, &mc_lst->addr); np->ipv6_mc_list = mc_lst->next; sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); } }
void ipv6_mc_destroy_dev(struct inet6_dev *idev) { struct ifmcaddr6 *i; struct in6_addr maddr; MDBG3((KERN_DEBUG "ipv6_mc_destroy_dev(idev=%p)\n", idev)); /* Delete all-nodes address. */ ipv6_addr_all_nodes(&maddr); ipv6_dev_mc_dec(idev->dev, &maddr); write_lock_bh(&idev->lock); while ((i = idev->mc_list) != NULL) { idev->mc_list = i->next; write_unlock_bh(&idev->lock); igmp6_group_dropped(i); ma_put(i); write_lock_bh(&idev->lock); } write_unlock_bh(&idev->lock); }