Index: if.c =================================================================== --- if.c (revision 193931) +++ if.c (working copy) @@ -1047,7 +1047,7 @@ if_unroute(struct ifnet *ifp, int flag, int fam) ifp->if_flags &= ~flag; getmicrotime(&ifp->if_lastchange); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) - if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) + if (fam == PF_UNSPEC || fam == ifa->ifa_addr->sa_family) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); if_qflush(&ifp->if_snd); #ifdef DEV_CARP @@ -1071,9 +1071,11 @@ if_route(struct ifnet *ifp, int flag, int fam) ifp->if_flags |= flag; getmicrotime(&ifp->if_lastchange); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) - if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) - pfctlinput(PRC_IFUP, ifa->ifa_addr); + if (ifp->if_link_state != LINK_STATE_DOWN) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + if (fam == PF_UNSPEC || fam == ifa->ifa_addr->sa_family) + pfctlinput(PRC_IFUP, ifa->ifa_addr); + } #ifdef DEV_CARP if (ifp->if_carp) carp_carpdev_state(ifp->if_carp); @@ -1108,6 +1110,7 @@ static void do_link_state_change(void *arg, int pending) { struct ifnet *ifp = (struct ifnet *)arg; + struct ifaddr *ifa; int link_state = ifp->if_link_state; int link; @@ -1146,6 +1149,25 @@ do_link_state_change(void *arg, int pending) if (log_link_state_change) log(LOG_NOTICE, "%s: link state changed to %s\n", ifp->if_xname, (link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); + /* + * If the link went away, remove its routing table entries. If it came + * back, bring them back. + */ + if ((ifp->if_flags & IFF_UP) && link_state == LINK_STATE_UP) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + /* + * If ifa_flags == 0, the interface is unusable + * state anyway (no working ARP etc), so don't + * bother. Removing this conditional breaks + * NFS root. + */ + if (ifa->ifa_flags != 0) + pfctlinput(PRC_IFUP, ifa->ifa_addr); + } + } else if (link_state == LINK_STATE_DOWN) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + pfctlinput(PRC_IFDOWN, ifa->ifa_addr); + } } /*