Diff below remove the last use of the global IPv4 list of addresses. The code using it is a hack to move the unique cloning route of a subnet from one ifa to another. I know a proper fix would be to use multipath for that, but this is not possible feasible right now because we cannot select multipath route entries based on a different ifa.
In the meantime this allow us to simplify in_ifinit() which still needs better error handling. ok? Index: netinet/in.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.114 diff -u -p -r1.114 in.c --- netinet/in.c 5 Jan 2015 10:21:58 -0000 1.114 +++ netinet/in.c 6 Jan 2015 11:36:28 -0000 @@ -607,9 +607,6 @@ in_ifinit(struct ifnet *ifp, struct in_i splsoftassert(IPL_SOFTNET); - if (newaddr) - TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list); - /* * Always remove the address from the tree to make sure its * position gets updated in case the key changes. @@ -629,9 +626,18 @@ in_ifinit(struct ifnet *ifp, struct in_i if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia->ia_addr = oldaddr; - goto out; } + /* + * Add the address to the local list and the global tree. If an + * error occured, put back the original address. + */ + ifa_add(ifp, &ia->ia_ifa); + rt_ifa_addlocal(&ia->ia_ifa); + + if (error) + goto out; + if (ia->ia_netmask == 0) { if (IN_CLASSA(i)) ia->ia_netmask = IN_CLASSA_NET; @@ -678,18 +684,6 @@ in_ifinit(struct ifnet *ifp, struct in_i } out: - /* - * Add the address to the local list and the global tree - * even if an error occured to make sure the various - * global structures are consistent. - * - * XXX This is necessary because we added the address - * to the global list in the first place because of - * carp(4). - */ - ifa_add(ifp, &ia->ia_ifa); - rt_ifa_addlocal(&ia->ia_ifa); - if (error && newaddr) in_purgeaddr(&ia->ia_ifa); @@ -709,7 +703,6 @@ in_purgeaddr(struct ifaddr *ifa) rt_ifa_dellocal(&ia->ia_ifa); ifa_del(ifp, &ia->ia_ifa); - TAILQ_REMOVE(&in_ifaddr, ia, ia_list); if (ia->ia_allhosts != NULL) { in_delmulti(ia->ia_allhosts); ia->ia_allhosts = NULL; @@ -775,6 +768,8 @@ in_remove_prefix(struct in_ifaddr *ia) int in_addprefix(struct in_ifaddr *ia0) { + struct ifnet *ifp; + struct ifaddr *ifa; struct in_ifaddr *ia; struct in_addr prefix, mask, p, m; @@ -782,36 +777,44 @@ in_addprefix(struct in_ifaddr *ia0) mask = ia0->ia_sockmask.sin_addr; prefix.s_addr &= mask.s_addr; - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { - if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain) - continue; - - if ((ia->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) continue; - if ((ia->ia_flags & IFA_ROUTE) == 0) + if (ifp->if_rdomain != ia0->ia_ifp->if_rdomain) continue; - p = ia->ia_addr.sin_addr; - m = ia->ia_sockmask.sin_addr; - p.s_addr &= m.s_addr; - - if (prefix.s_addr != p.s_addr || mask.s_addr != m.s_addr) - continue; + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + ia = ifatoia(ifa); + + if ((ia->ia_flags & IFA_ROUTE) == 0) + continue; + + p = ia->ia_addr.sin_addr; + m = ia->ia_sockmask.sin_addr; + p.s_addr &= m.s_addr; + + if (prefix.s_addr != p.s_addr || + mask.s_addr != m.s_addr) + continue; #if NCARP > 0 - /* move to a real interface instead of carp interface */ - if (ia->ia_ifp->if_type == IFT_CARP && - ia0->ia_ifp->if_type != IFT_CARP) { - in_remove_prefix(ia); - break; - } + /* move to a real interface instead of carp interface */ + if (ia->ia_ifp->if_type == IFT_CARP && + ia0->ia_ifp->if_type != IFT_CARP) { + in_remove_prefix(ia); + break; + } #endif - /* - * if we got a matching prefix route inserted by other - * interface address, we don't need to bother - */ - return 0; + /* + * If we got a matching prefix route inserted by other + * interface address, we don't need to bother + */ + return (0); + } } /* @@ -828,6 +831,8 @@ in_addprefix(struct in_ifaddr *ia0) int in_scrubprefix(struct in_ifaddr *ia0) { + struct ifnet *ifp; + struct ifaddr *ifa; struct in_ifaddr *ia; struct in_addr prefix, mask, p, m; @@ -838,28 +843,34 @@ in_scrubprefix(struct in_ifaddr *ia0) mask = ia0->ia_sockmask.sin_addr; prefix.s_addr &= mask.s_addr; - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { - if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain) - continue; - - if ((ia->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) continue; - if ((ia->ia_flags & IFA_ROUTE) != 0) + if (ifp->if_rdomain != ia0->ia_ifp->if_rdomain) continue; - p = ia->ia_addr.sin_addr; - m = ia->ia_sockmask.sin_addr; - p.s_addr &= m.s_addr; - - if (prefix.s_addr != p.s_addr || mask.s_addr != m.s_addr) - continue; - - /* - * if we got a matching prefix route, move IFA_ROUTE to him - */ - in_remove_prefix(ia0); - return in_insert_prefix(ia); + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + ia = ifatoia(ifa); + + if ((ia->ia_flags & IFA_ROUTE) != 0) + continue; + + p = ia->ia_addr.sin_addr; + m = ia->ia_sockmask.sin_addr; + p.s_addr &= m.s_addr; + + if (prefix.s_addr != p.s_addr || + mask.s_addr != m.s_addr) + continue; + + /* Move IFA_ROUTE to the matching prefix route. */ + in_remove_prefix(ia0); + return (in_insert_prefix(ia)); + } } /* Index: netinet/in_var.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_var.h,v retrieving revision 1.34 diff -u -p -r1.34 in_var.h --- netinet/in_var.h 27 Mar 2014 10:39:23 -0000 1.34 +++ netinet/in_var.h 6 Jan 2015 11:36:28 -0000 @@ -77,9 +77,6 @@ struct in_aliasreq { #ifdef _KERNEL -TAILQ_HEAD(in_ifaddrhead, in_ifaddr); -extern struct in_ifaddrhead in_ifaddr; - /* * Macro for finding the internet address structure (in_ifaddr) corresponding * to a given interface (ifnet structure). Index: netinet/ip_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v retrieving revision 1.243 diff -u -p -r1.243 ip_input.c --- netinet/ip_input.c 5 Dec 2014 15:50:04 -0000 1.243 +++ netinet/ip_input.c 6 Jan 2015 11:36:28 -0000 @@ -114,7 +114,6 @@ int ip_frags = 0; int *ipctl_vars[IPCTL_MAXID] = IPCTL_VARS; -struct in_ifaddrhead in_ifaddr; struct ifqueue ipintrq; struct pool ipqent_pool; @@ -172,7 +171,6 @@ ip_init(void) ip_protox[pr->pr_protocol] = pr - inetsw; LIST_INIT(&ipq); IFQ_SET_MAXLEN(&ipintrq, IFQ_MAXLEN); - TAILQ_INIT(&in_ifaddr); if (ip_mtudisc != 0) ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout);