FreeBSD/sys/netinet/raw_ip.c
/*
 * 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.
 */
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.
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 rm_priotracker in_ifa_tracker;
	struct in_ifaddr *ia;
	struct ifnet *ifp;
	int err;
	int flags;
	switch (cmd) {
	case PRC_IFDOWN:
		IN_IFADDR_RLOCK(&in_ifa_tracker);
		TAILQ_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_IFADDR_RUNLOCK(&in_ifa_tracker);
				in_scrubprefix(ia, 0);
				in_ifadown(&ia->ia_ifa, 0);
				ifa_free(&ia->ia_ifa);
				break;
			}
		}
		if (ia == NULL)		
			IN_IFADDR_RUNLOCK(&in_ifa_tracker);
		break;
	case PRC_IFUP:
		IN_IFADDR_RLOCK(&in_ifa_tracker);
		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
			if (ia->ia_ifa.ifa_addr == sa)
				break;
		}
		if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) {
			IN_IFADDR_RUNLOCK(&in_ifa_tracker);
			return;
		}
		ifa_ref(&ia->ia_ifa);
		IN_IFADDR_RUNLOCK(&in_ifa_tracker);
		flags = RTF_UP;
		ifp = ia->ia_ifa.ifa_ifp;
		if ((ifp->if_flags & IFF_LOOPBACK)
		    || (ifp->if_flags & IFF_POINTOPOINT))
			flags |= RTF_HOST;
		err = ifa_del_loopback_route((struct ifaddr *)ia, sa);
		err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
		if (err == 0)
			ia->ia_flags |= IFA_ROUTE;
		err = ifa_add_loopback_route((struct ifaddr *)ia, sa);
		ifa_free(&ia->ia_ifa);
		break;
	}
}
void rip_ctlinput ( int cmd , struct sockaddr * sa , void * vip ) { struct rm_priotracker in_ifa_tracker ; struct in_ifaddr * ia ; struct ifnet * ifp ; int err ; int flags ; switch ( cmd ) { case PRC_IFDOWN : IN_IFADDR_RLOCK ( & in_ifa_tracker ) ; TAILQ_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_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; in_scrubprefix ( ia , 0 ) ; in_ifadown ( & ia -> ia_ifa , 0 ) ; ifa_free ( & ia -> ia_ifa ) ; break ; } } if ( ia == NULL ) IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; break ; case PRC_IFUP : IN_IFADDR_RLOCK ( & in_ifa_tracker ) ; TAILQ_FOREACH ( ia , & V_in_ifaddrhead , ia_link ) { if ( ia -> ia_ifa . ifa_addr == sa ) break ; } if ( ia == NULL || ( ia -> ia_flags & IFA_ROUTE ) ) { IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; return ; } ifa_ref ( & ia -> ia_ifa ) ; IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; flags = RTF_UP ; ifp = ia -> ia_ifa . ifa_ifp ; if ( ( ifp -> if_flags & IFF_LOOPBACK ) || ( ifp -> if_flags & IFF_POINTOPOINT ) ) flags |= RTF_HOST ; err = ifa_del_loopback_route ( ( struct ifaddr * ) ia , sa ) ; err = rtinit ( & ia -> ia_ifa , RTM_ADD , flags ) ; if ( err == 0 ) ia -> ia_flags |= IFA_ROUTE ; err = ifa_add_loopback_route ( ( struct ifaddr * ) ia , sa ) ; ifa_free ( & ia -> ia_ifa ) ; break ; } }
This function exists solely to receive the PRC_IFDOWN messages which are
 sent by if_down().
This function exists solely to receive the PRC_IFDOWN messages which are sent by if_down () .
/*
				 * in_scrubprefix() kills the interface route.
				 */ /*
				 * 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.
				 */ /* If ia matched, already unlocked. */