diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2132,18 +2132,11 @@ static void if_unroute(struct ifnet *ifp, int flag, int fam) { - struct ifaddr *ifa; - struct epoch_tracker et; KASSERT(flag == IFF_UP, ("if_unroute: flag != IFF_UP")); ifp->if_flags &= ~flag; getmicrotime(&ifp->if_lastchange); - NET_EPOCH_ENTER(et); - CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) - if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) - pfctlinput(PRC_IFDOWN, ifa->ifa_addr); - NET_EPOCH_EXIT(et); ifp->if_qflush(ifp); if (ifp->if_carp) @@ -2158,18 +2151,11 @@ static void if_route(struct ifnet *ifp, int flag, int fam) { - struct ifaddr *ifa; - struct epoch_tracker et; KASSERT(flag == IFF_UP, ("if_route: flag != IFF_UP")); ifp->if_flags |= flag; getmicrotime(&ifp->if_lastchange); - NET_EPOCH_ENTER(et); - CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) - if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) - pfctlinput(PRC_IFUP, ifa->ifa_addr); - NET_EPOCH_EXIT(et); if (ifp->if_carp) (*carp_linkstate_p)(ifp); rt_ifmsg(ifp); diff --git a/sys/netinet/in.c b/sys/netinet/in.c --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -954,7 +954,7 @@ * Adds or delete interface "prefix" route corresponding to @ifa. * Returns 0 on success or errno. */ -int +static int in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia) { struct ifaddr *ifa = &ia->ia_ifa; @@ -1303,6 +1303,61 @@ inm_release_wait(NULL); } +static void +in_ifnet_event(void *arg __unused, struct ifnet *ifp, int event) +{ + struct epoch_tracker et; + struct ifaddr *ifa; + struct in_ifaddr *ia; + int error; + + NET_EPOCH_ENTER(et); + switch (event) { + case IFNET_EVENT_DOWN: + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = (struct in_ifaddr *)ifa; + if ((ia->ia_flags & IFA_ROUTE) == 0) + continue; + ifa_ref(ifa); + /* + * in_scrubprefix() kills the interface route. + */ + in_scrubprefix(ia, 0); + /* + * in_ifadown gets rid of all the rest of the + * routes. This is not quite the right thing + * to do, but at least if we are running a + * routing process they will come back. + */ + in_ifadown(ifa, 0); + ifa_free(ifa); + } + break; + + case IFNET_EVENT_UP: + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = (struct in_ifaddr *)ifa; + if (ia->ia_flags & IFA_ROUTE) + continue; + ifa_ref(ifa); + error = ifa_del_loopback_route(ifa, ifa->ifa_addr); + rt_addrmsg(RTM_ADD, ifa, ifa->ifa_ifp->if_fib); + error = in_handle_ifaddr_route(RTM_ADD, ia); + if (error == 0) + ia->ia_flags |= IFA_ROUTE; + error = ifa_add_loopback_route(ifa, ifa->ifa_addr); + ifa_free(ifa); + } + break; + } + NET_EPOCH_EXIT(et); +} +EVENTHANDLER_DEFINE(ifnet_event, in_ifnet_event, NULL, EVENTHANDLER_PRI_ANY); + /* * Delete all IPv4 multicast address records, and associated link-layer * multicast address records, associated with ifp. diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -449,7 +449,6 @@ int in_addprefix(struct in_ifaddr *); int in_scrubprefix(struct in_ifaddr *, u_int); void in_ifscrub_all(void); -int in_handle_ifaddr_route(int, struct in_ifaddr *); void ip_input(struct mbuf *); void ip_direct_input(struct mbuf *); void in_ifadown(struct ifaddr *ifa, int); diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -769,64 +769,11 @@ return (error); } -/* - * This function exists solely to receive the PRC_IFDOWN messages which are - * sent by if_down(). It looks for an ifaddr whose ifa_addr is sa, and calls - * in_ifadown() to remove all routes corresponding to that address. It also - * receives the PRC_IFUP messages from if_up() and reinstalls the interface - * routes. - */ void rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) { - struct in_ifaddr *ia; - int err; - - NET_EPOCH_ASSERT(); switch (cmd) { - case PRC_IFDOWN: - CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { - if (ia->ia_ifa.ifa_addr == sa - && (ia->ia_flags & IFA_ROUTE)) { - ifa_ref(&ia->ia_ifa); - /* - * in_scrubprefix() kills the interface route. - */ - in_scrubprefix(ia, 0); - /* - * in_ifadown gets rid of all the rest of the - * routes. This is not quite the right thing - * to do, but at least if we are running a - * routing process they will come back. - */ - in_ifadown(&ia->ia_ifa, 0); - ifa_free(&ia->ia_ifa); - break; - } - } - break; - - case PRC_IFUP: - CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { - if (ia->ia_ifa.ifa_addr == sa) - break; - } - if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) - return; - ifa_ref(&ia->ia_ifa); - - err = ifa_del_loopback_route((struct ifaddr *)ia, sa); - - rt_addrmsg(RTM_ADD, &ia->ia_ifa, ia->ia_ifp->if_fib); - err = in_handle_ifaddr_route(RTM_ADD, ia); - if (err == 0) - ia->ia_flags |= IFA_ROUTE; - - err = ifa_add_loopback_route((struct ifaddr *)ia, sa); - - ifa_free(&ia->ia_ifa); - break; #if defined(IPSEC) || defined(IPSEC_SUPPORT) case PRC_MSGSIZE: if (IPSEC_ENABLED(ipv4)) diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -282,9 +282,7 @@ * where cmd is one of the commands below, sa is a pointer to a sockaddr, * and arg is a `void *' argument used within a protocol family. */ -#define PRC_IFDOWN 0 /* interface transition */ #define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ -#define PRC_IFUP 2 /* interface has come back up */ /* was PRC_QUENCH2 3 DEC congestion bit says slow down */ /* was PRC_QUENCH 4 Deprecated by RFC 6633 */ #define PRC_MSGSIZE 5 /* message size forced drop */