Index: etc/rc.d/dhclient =================================================================== --- etc/rc.d/dhclient (revision 254415) +++ etc/rc.d/dhclient (working copy) @@ -15,8 +15,15 @@ rcvar= pidfile="/var/run/${name}.${ifn}.pid" start_precmd="dhclient_prestart" +start_postcmd="dhclient_poststart" stop_precmd="dhclient_pre_check" +# Allow specifying a FIB on a per-interface basis for DHCP interfaces. If a +# global dhclient_fib is set, it will be overridden for that interface. +load_rc_config $name +_dhclient_fib=$(get_if_var $ifn dhclient_fib_IF) +[ -n "$_dhclient_fib" ] && dhclient_fib=$_dhclient_fib + # rc_force check can only be done at the run_rc_command # time, so we're testing it in the pre* hooks. dhclient_pre_check() @@ -51,7 +58,13 @@ rc_flags="${rc_flags} ${ifn}" } -load_rc_config $name +dhclient_poststart() +{ + # Just because our process was assigned a fib doesn't mean the + # interface inherited it. XXX: Bug in interface code? + [ -n "$dhclient_fib" ] && do_ifconfig $ifn fib $dhclient_fib +} + load_rc_config network if [ -z $ifn ] ; then Index: etc/rc.d/routing =================================================================== --- etc/rc.d/routing (revision 254415) +++ etc/rc.d/routing (working copy) @@ -132,12 +132,26 @@ return 0 } +get_fibmod() +{ + local fibs + + fibs=$((`${SYSCTL_N} net.fibs` - 1)) + if [ ${fibs} -gt 0 ]; then + echo "-fib 0-${fibs}" + else + echo + fi +} + static_inet() { - local _action _if _skip + local _action _if _skip fibmod _action=$1 _if=$2 + fibmod=$(get_fibmod) + # Add default route. case ${defaultrouter} in [Nn][Oo] | '') @@ -148,6 +162,10 @@ ;; esac + # Provide loopback route in all routing tables. + static_routes="_loopback ${static_routes}" + route__loopback="-inet 127.0.0.1/8 -iface lo0 ${fibmod}" + # Install configured routes. if [ -n "${static_routes}" ]; then for i in ${static_routes}; do @@ -172,17 +190,11 @@ static_inet6() { - local _action _if _skip fibmod fibs + local _action _if _skip fibmod _action=$1 _if=$2 - # get the number of FIBs supported. - fibs=$((`${SYSCTL_N} net.fibs` - 1)) - if [ "$fibs" -gt 0 ]; then - fibmod="-fib 0-$fibs" - else - fibmod= - fi + fibmod=$(get_fibmod) # Add pre-defined static routes first. ipv6_static_routes="_v4mapped _v4compat ${ipv6_static_routes}" @@ -200,6 +212,10 @@ ipv6_route__lla="fe80:: -prefixlen 10 ::1 -reject ${fibmod}" ipv6_route__llma="ff02:: -prefixlen 16 ::1 -reject ${fibmod}" + # Provide loopback route in all routing tables. + ipv6_static_routes="_loopback ${ipv6_static_routes}" + ipv6_route__loopback="::1 -prefixlen 128 -iface lo0 ${fibmod}" + # Add default route. case ${ipv6_defaultrouter} in [Nn][Oo] | '') Index: sbin/ifconfig/iffib.c =================================================================== --- sbin/ifconfig/iffib.c (revision 254415) +++ sbin/ifconfig/iffib.c (working copy) @@ -76,6 +76,8 @@ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_fib = fib; + if (setfib(fib) != 0) + warn("setfib"); if (ioctl(s, SIOCSIFFIB, (caddr_t)&ifr) < 0) warn("ioctl (SIOCSIFFIB)"); } Index: share/man/man5/rc.conf.5 =================================================================== --- share/man/man5/rc.conf.5 (revision 254415) +++ share/man/man5/rc.conf.5 (working copy) @@ -428,6 +428,16 @@ only. When specified, this variable overrides .Va dhclient_flags . +.It Va dhclient_fib_ Ns Aq Ar iface +.Pq Vt int +When specified, this variable overrides the +.Va dhclient_fib +variable for interface +.Ar iface +only. +See documentation for the variable +.Ao Ar name Ac Ns Va _fib +for more information. .It Va background_dhclient .Pq Vt bool Set to Index: sys/net/if.c =================================================================== --- sys/net/if.c (revision 254415) +++ sys/net/if.c (working copy) @@ -1456,7 +1456,7 @@ info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC; info.rti_info[RTAX_DST] = ia; info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; - error = rtrequest1_fib(RTM_ADD, &info, &rt, 0); + error = rtrequest1_fib(RTM_ADD, &info, &rt, ifa->ifa_ifp->if_fib); if (error == 0 && rt != NULL) { RT_LOCK(rt); @@ -1488,7 +1488,7 @@ info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC; info.rti_info[RTAX_DST] = ia; info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; - error = rtrequest1_fib(RTM_DELETE, &info, NULL, 0); + error = rtrequest1_fib(RTM_DELETE, &info, NULL, ifa->ifa_ifp->if_fib); if (error != 0) log(LOG_DEBUG, "%s: deletion failed: %u\n", __func__, error); @@ -1605,7 +1605,7 @@ */ /*ARGSUSED*/ struct ifaddr * -ifa_ifwithdstaddr(struct sockaddr *addr) +ifa_ifwithdstaddr(struct sockaddr *addr, int fibnum) { struct ifnet *ifp; struct ifaddr *ifa; @@ -1614,6 +1614,8 @@ TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0) continue; + if ((ifp->if_fib != fibnum)) + continue; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) @@ -1638,7 +1640,7 @@ * is most specific found. */ struct ifaddr * -ifa_ifwithnet(struct sockaddr *addr, int ignore_ptp) +ifa_ifwithnet(struct sockaddr *addr, int ignore_ptp, int fibnum) { struct ifnet *ifp; struct ifaddr *ifa; @@ -1658,12 +1660,14 @@ /* * Scan though each interface, looking for ones that have addresses - * in this address family. Maintain a reference on ifa_maybe once - * we find one, as we release the IF_ADDR_RLOCK() that kept it stable - * when we move onto the next interface. + * in this address family and the requested fib. Maintain a reference + * on ifa_maybe once we find one, as we release the IF_ADDR_RLOCK() that + * kept it stable when we move onto the next interface. */ IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + if (ifp->if_fib != fibnum) + continue; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { char *cp, *cp2, *cp3; Index: sys/net/if_var.h =================================================================== --- sys/net/if_var.h (revision 254415) +++ sys/net/if_var.h (working copy) @@ -940,8 +940,8 @@ struct ifaddr *ifa_ifwithaddr(struct sockaddr *); int ifa_ifwithaddr_check(struct sockaddr *); struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *); -struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); -struct ifaddr *ifa_ifwithnet(struct sockaddr *, int); +struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *, int); +struct ifaddr *ifa_ifwithnet(struct sockaddr *, int, int); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *); struct ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int); struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); Index: sys/net/route.c =================================================================== --- sys/net/route.c (revision 254415) +++ sys/net/route.c (working copy) @@ -535,7 +535,7 @@ } /* verify the gateway is directly reachable */ - if ((ifa = ifa_ifwithnet(gateway, 0)) == NULL) { + if ((ifa = ifa_ifwithnet(gateway, 0, fibnum)) == NULL) { error = ENETUNREACH; goto out; } @@ -612,7 +612,7 @@ RADIX_NODE_HEAD_LOCK(rnh); RT_LOCK(rt); rt_setgate(rt, rt_key(rt), gateway); - gwrt = rtalloc1(gateway, 1, RTF_RNH_LOCKED); + gwrt = rtalloc1_fib(gateway, 1, RTF_RNH_LOCKED, fibnum); RADIX_NODE_HEAD_UNLOCK(rnh); EVENTHANDLER_INVOKE(route_redirect_event, rt, gwrt, dst); RTFREE_LOCKED(gwrt); @@ -692,7 +692,7 @@ */ ifa = NULL; if (flags & RTF_HOST) - ifa = ifa_ifwithdstaddr(dst); + ifa = ifa_ifwithdstaddr(dst, fibnum); if (ifa == NULL) ifa = ifa_ifwithaddr(gateway); } else { @@ -701,12 +701,13 @@ * or host, the gateway may still be on the * other end of a pt to pt link. */ - ifa = ifa_ifwithdstaddr(gateway); + ifa = ifa_ifwithdstaddr(gateway, fibnum); } if (ifa == NULL) - ifa = ifa_ifwithnet(gateway, 0); + ifa = ifa_ifwithnet(gateway, 0, fibnum); if (ifa == NULL) { - struct rtentry *rt = rtalloc1_fib(gateway, 0, RTF_RNH_LOCKED, fibnum); + struct rtentry *rt; + rt = rtalloc1_fib(gateway, 0, RTF_RNH_LOCKED, fibnum); if (rt == NULL) return (NULL); /* @@ -818,7 +819,7 @@ */ if (info->rti_ifp == NULL && ifpaddr != NULL && ifpaddr->sa_family == AF_LINK && - (ifa = ifa_ifwithnet(ifpaddr, 0)) != NULL) { + (ifa = ifa_ifwithnet(ifpaddr, 0, fibnum)) != NULL) { info->rti_ifp = ifa->ifa_ifp; ifa_free(ifa); } Index: sys/net/rtsock.c =================================================================== --- sys/net/rtsock.c (revision 254415) +++ sys/net/rtsock.c (working copy) @@ -764,7 +764,8 @@ rt->rt_ifp->if_type == IFT_PROPVIRTUAL) { struct ifaddr *ifa; - ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1); + ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1, + RT_DEFAULT_FIB); if (ifa != NULL) rt_maskedcopy(ifa->ifa_addr, &laddr, Index: sys/netinet/if_ether.c =================================================================== --- sys/netinet/if_ether.c (revision 254415) +++ sys/netinet/if_ether.c (working copy) @@ -337,8 +337,8 @@ if (la == NULL) { if (flags & LLE_CREATE) log(LOG_DEBUG, - "arpresolve: can't allocate llinfo for %s\n", - inet_ntoa(SIN(dst)->sin_addr)); + "arpresolve: can't allocate llinfo for %s on %s\n", + inet_ntoa(SIN(dst)->sin_addr), ifp->if_xname); m_freem(m); return (EINVAL); } Index: sys/netinet/in.c =================================================================== --- sys/netinet/in.c (revision 254415) +++ sys/netinet/in.c (working copy) @@ -1037,10 +1037,12 @@ (target->ia_flags & IFA_RTSELF)) { struct route ia_ro; int freeit = 0; + int fib; bzero(&ia_ro, sizeof(ia_ro)); *((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr; - rtalloc_ign_fib(&ia_ro, 0, 0); + fib = target->ia_ifa.ifa_ifp->if_fib; + rtalloc_ign_fib(&ia_ro, 0, fib); if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) && (ia_ro.ro_rt->rt_ifp == V_loif)) { RT_LOCK(ia_ro.ro_rt); @@ -1079,6 +1081,7 @@ } IN_IFADDR_RLOCK(); + /* Look for an existing address with the same prefix, mask, and fib */ TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if (rtinitflags(ia)) { p = ia->ia_dstaddr.sin_addr; @@ -1094,6 +1097,8 @@ mask.s_addr != m.s_addr) continue; } + if (target->ia_ifp->if_fib != ia->ia_ifp->if_fib) + continue; if ((ia->ia_ifp->if_flags & IFF_UP) == 0) continue; @@ -1338,7 +1343,8 @@ ("sin_family %d", l3addr->sa_family)); /* XXX rtalloc1 should take a const param */ - rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0); + rt = rtalloc1_fib(__DECONST(struct sockaddr *, l3addr), 0, 0, + ifp->if_fib); if (rt == NULL) return (EINVAL); Index: sys/netinet/in_pcb.c =================================================================== --- sys/netinet/in_pcb.c (revision 254415) +++ sys/netinet/in_pcb.c (working copy) @@ -745,9 +745,11 @@ struct in_ifaddr *ia; struct ifnet *ifp; - ia = ifatoia(ifa_ifwithdstaddr((struct sockaddr *)sin)); + ia = ifatoia(ifa_ifwithdstaddr((struct sockaddr *)sin, + RT_DEFAULT_FIB)); if (ia == NULL) - ia = ifatoia(ifa_ifwithnet((struct sockaddr *)sin, 0)); + ia = ifatoia(ifa_ifwithnet((struct sockaddr *)sin, 0, + RT_DEFAULT_FIB)); if (ia == NULL) { error = ENETUNREACH; goto done; @@ -862,9 +864,10 @@ sain.sin_len = sizeof(struct sockaddr_in); sain.sin_addr.s_addr = faddr->s_addr; - ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain))); + ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain), RT_DEFAULT_FIB)); if (ia == NULL) - ia = ifatoia(ifa_ifwithnet(sintosa(&sain), 0)); + ia = ifatoia(ifa_ifwithnet(sintosa(&sain), 0, + RT_DEFAULT_FIB)); if (ia == NULL) ia = ifatoia(ifa_ifwithaddr(sintosa(&sain))); Index: sys/netinet/ip_options.c =================================================================== --- sys/netinet/ip_options.c (revision 254415) +++ sys/netinet/ip_options.c (working copy) @@ -227,8 +227,11 @@ if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * #define SA struct sockaddr * - if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == NULL) - ia = (INA)ifa_ifwithnet((SA)&ipaddr, 0); + if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr, + RT_DEFAULT_FIB)) == NULL) { + ia = (INA)ifa_ifwithnet((SA)&ipaddr, 0, + RT_DEFAULT_FIB); + } } else /* XXX MRT 0 for routing */ ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m)); Index: sys/netinet/ip_output.c =================================================================== --- sys/netinet/ip_output.c (revision 254415) +++ sys/netinet/ip_output.c (working copy) @@ -231,7 +231,8 @@ */ if (flags & IP_SENDONES) { if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL && - (ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL) { + (ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst), + RT_DEFAULT_FIB))) == NULL) { IPSTAT_INC(ips_noroute); error = ENETUNREACH; goto bad; @@ -242,8 +243,10 @@ ip->ip_ttl = 1; isbroadcast = 1; } else if (flags & IP_ROUTETOIF) { - if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL && - (ia = ifatoia(ifa_ifwithnet(sintosa(dst), 0))) == NULL) { + if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst), + RT_DEFAULT_FIB))) == NULL && + (ia = ifatoia(ifa_ifwithnet(sintosa(dst), 0, + RT_DEFAULT_FIB))) == NULL) { IPSTAT_INC(ips_noroute); error = ENETUNREACH; goto bad; Index: sys/netinet6/nd6.c =================================================================== --- sys/netinet6/nd6.c (revision 254415) +++ sys/netinet6/nd6.c (working copy) @@ -941,7 +941,7 @@ * If the address is assigned on the node of the other side of * a p2p interface, the address should be a neighbor. */ - dstaddr = ifa_ifwithdstaddr((struct sockaddr *)addr); + dstaddr = ifa_ifwithdstaddr((struct sockaddr *)addr, RT_DEFAULT_FIB); if (dstaddr != NULL) { if (dstaddr->ifa_ifp == ifp) { ifa_free(dstaddr); Index: sys/netipx/ipx_pcb.c =================================================================== --- sys/netipx/ipx_pcb.c (revision 254415) +++ sys/netipx/ipx_pcb.c (working copy) @@ -235,7 +235,8 @@ u_short fport = sipx->sipx_addr.x_port; sipx->sipx_addr.x_port = 0; ia = (struct ipx_ifaddr *) - ifa_ifwithdstaddr((struct sockaddr *)sipx); + ifa_ifwithdstaddr((struct sockaddr *)sipx, + RT_DEFAULT_FIB); sipx->sipx_addr.x_port = fport; if (ia == NULL) { IPX_IFADDR_RLOCK(); @@ -282,7 +283,8 @@ u_short fport = sipx->sipx_addr.x_port; sipx->sipx_addr.x_port = 0; ia = (struct ipx_ifaddr *) - ifa_ifwithdstaddr((struct sockaddr *)sipx); + ifa_ifwithdstaddr((struct sockaddr *)sipx, + RT_DEFAULT_FIB); sipx->sipx_addr.x_port = fport; if (ia == NULL) { IPX_IFADDR_RLOCK();