Subject: [PATCH] nethost: tag ipv6 address with the nethost From: Eric W. Biederman Date: 1133870458 -0700 --- net/ipv6/addrconf.c | 44 ++++++++++++++++++++++++++++++-------------- 1 files changed, 30 insertions(+), 14 deletions(-) c34e777b9ab0356c1460d985fb1fef64d60adb22 diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4337fb3..5ffc537 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -492,7 +492,7 @@ void inet6_ifa_finish_destroy(struct ine /* On success it returns ifp with increased reference count */ static struct inet6_ifaddr * -ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, +ipv6_add_addr(struct nethost *host, struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, int scope, u32 flags) { struct inet6_ifaddr *ifa = NULL; @@ -530,6 +530,7 @@ ipv6_add_addr(struct inet6_dev *idev, co } memset(ifa, 0, sizeof(struct inet6_ifaddr)); + ifa->host = host; ipv6_addr_copy(&ifa->addr, addr); spin_lock_init(&ifa->lock); @@ -777,7 +778,7 @@ retry: write_unlock(&idev->lock); ift = !max_addresses || ipv6_count_addresses(idev) < max_addresses ? - ipv6_add_addr(idev, &addr, tmp_plen, + ipv6_add_addr(ifp->host, idev, &addr, tmp_plen, ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : NULL; if (!ift || IS_ERR(ift)) { in6_ifa_put(ifp); @@ -1546,7 +1547,7 @@ ok: */ if (!max_addresses || ipv6_count_addresses(in6_dev) < max_addresses) - ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, + ifp = ipv6_add_addr(&init_host, in6_dev, &addr, pinfo->prefix_len, addr_type&IPV6_ADDR_SCOPE_MASK, 0); if (!ifp || IS_ERR(ifp)) { @@ -1678,6 +1679,7 @@ int addrconf_set_dstaddr(void __user *ar if (!(ipv6_addr_type(&ireq.ifr6_addr) & IPV6_ADDR_COMPATv4)) goto err_exit; + /* FIXME current->host */ memset(&p, 0, sizeof(p)); p.iph.daddr = ireq.ifr6_addr.s6_addr32[3]; p.iph.saddr = 0; @@ -1707,7 +1709,7 @@ err_exit: /* * Manual configuration of address on an interface */ -static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) +static int inet6_addr_add(struct nethost *host, int ifindex, struct in6_addr *pfx, int plen) { struct inet6_ifaddr *ifp; struct inet6_dev *idev; @@ -1727,7 +1729,7 @@ static int inet6_addr_add(int ifindex, s scope = ipv6_addr_scope(pfx); - ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); + ifp = ipv6_add_addr(host, idev, pfx, plen, scope, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); @@ -1737,7 +1739,7 @@ static int inet6_addr_add(int ifindex, s return PTR_ERR(ifp); } -static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) +static int inet6_addr_del(struct nethost *host, int ifindex, struct in6_addr *pfx, int plen) { struct inet6_ifaddr *ifp; struct inet6_dev *idev; @@ -1751,6 +1753,8 @@ static int inet6_addr_del(int ifindex, s read_lock_bh(&idev->lock); for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { + if (ifp->host != host) + continue; if (ifp->prefix_len == plen && ipv6_addr_equal(pfx, &ifp->addr)) { in6_ifa_hold(ifp); @@ -1783,7 +1787,7 @@ int addrconf_add_ifaddr(void __user *arg return -EFAULT; rtnl_lock(); - err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); + err = inet6_addr_add(current->host, ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; } @@ -1800,7 +1804,7 @@ int addrconf_del_ifaddr(void __user *arg return -EFAULT; rtnl_lock(); - err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); + err = inet6_addr_del(current->host, ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; } @@ -1825,7 +1829,7 @@ static void sit_add_v4_addrs(struct inet } if (addr.s6_addr32[3]) { - ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT); + ifp = ipv6_add_addr(&init_host, idev, &addr, 128, scope, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { spin_lock_bh(&ifp->lock); ifp->flags &= ~IFA_F_TENTATIVE; @@ -1860,7 +1864,7 @@ static void sit_add_v4_addrs(struct inet else plen = 96; - ifp = ipv6_add_addr(idev, &addr, plen, flag, + ifp = ipv6_add_addr(&init_host, idev, &addr, plen, flag, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { spin_lock_bh(&ifp->lock); @@ -1878,6 +1882,7 @@ static void init_loopback(struct net_dev { struct inet6_dev *idev; struct inet6_ifaddr * ifp; + struct nethost *host; /* ::1 */ @@ -1888,7 +1893,8 @@ static void init_loopback(struct net_dev return; } - ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); + host = container_of(dev, struct nethost, loopback_dev); + ifp = ipv6_add_addr(host, idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { spin_lock_bh(&ifp->lock); ifp->flags &= ~IFA_F_TENTATIVE; @@ -1902,7 +1908,7 @@ static void addrconf_add_linklocal(struc { struct inet6_ifaddr * ifp; - ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); + ifp = ipv6_add_addr(&init_host, idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); @@ -2377,6 +2383,7 @@ static void addrconf_dad_completed(struc #ifdef CONFIG_PROC_FS struct if6_iter_state { + struct nethost *host; int bucket; }; @@ -2387,6 +2394,8 @@ static struct inet6_ifaddr *if6_get_firs for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { ifa = inet6_addr_lst[state->bucket]; + while (ifa && ifa->host != state->host) + ifa = ifa->lst_next; if (ifa) break; } @@ -2399,6 +2408,8 @@ static struct inet6_ifaddr *if6_get_next ifa = ifa->lst_next; try_again: + while (ifa && ifa->host != state->host) + ifa = ifa->lst_next; if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { ifa = inet6_addr_lst[state->bucket]; goto try_again; @@ -2466,6 +2477,7 @@ static int if6_seq_open(struct inode *in if (!s) goto out; memset(s, 0, sizeof(*s)); + s->host = current->host; rc = seq_open(file, &if6_seq_ops); if (rc) @@ -2625,7 +2637,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, s if (pfx == NULL) return -EINVAL; - return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); + return inet6_addr_del(skb->sk->sk_host, ifm->ifa_index, pfx, ifm->ifa_prefixlen); } static int @@ -2649,7 +2661,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, s if (pfx == NULL) return -EINVAL; - return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); + return inet6_addr_add(skb->sk->sk_host, ifm->ifa_index, pfx, ifm->ifa_prefixlen); } static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, @@ -2791,9 +2803,11 @@ static int inet6_dump_addr(struct sk_buf struct inet6_ifaddr *ifa; struct ifmcaddr6 *ifmca; struct ifacaddr6 *ifaca; + struct nethost *host; s_idx = cb->args[0]; s_ip_idx = ip_idx = cb->args[1]; + host = skb->sk->sk_host; read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { @@ -2812,6 +2826,8 @@ static int inet6_dump_addr(struct sk_buf ifa = ifa->if_next, ip_idx++) { if (ip_idx < s_ip_idx) continue; + if (ifa->host != host) + continue; if ((err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR, -- 1.0.GIT