FreeBSD/sys/netinet/in.c
/*
 * If there is no other address in the system that can serve a route to the
 * same prefix, remove the route.  Hand over the route to the new address
 * otherwise.
 */
If there is no other address in the system that can serve a route to the
same prefix, remove the route.  Hand over the route to the new address
otherwise.
If there is no other address in the system that can serve a route to the same prefix remove the route . Hand over the route to the new address otherwise .
int
in_scrubprefix(struct in_ifaddr *target, u_int flags)
{
	struct rm_priotracker in_ifa_tracker;
	struct in_ifaddr *ia;
	struct in_addr prefix, mask, p, m;
	int error = 0;
	if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
	    !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
	    (flags & LLE_STATIC)) {
		struct in_ifaddr *eia;
		eia = in_localip_more(target);
		if (eia != NULL) {
			error = ifa_switch_loopback_route((struct ifaddr *)eia,
			    (struct sockaddr *)&target->ia_addr);
			ifa_free(&eia->ia_ifa);
		} else {
			error = ifa_del_loopback_route((struct ifaddr *)target,
			    (struct sockaddr *)&target->ia_addr);
		}
	}
	if (rtinitflags(target)) {
		prefix = target->ia_dstaddr.sin_addr;
		mask.s_addr = 0;
	} else {
		prefix = target->ia_addr.sin_addr;
		mask = target->ia_sockmask.sin_addr;
		prefix.s_addr &= mask.s_addr;
	}
	if ((target->ia_flags & IFA_ROUTE) == 0) {
		int fibnum;
		fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
			target->ia_ifp->if_fib;
		rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
		in_scrubprefixlle(target, 0, flags);
		return (0);
	}
	IN_IFADDR_RLOCK(&in_ifa_tracker);
	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
		if (rtinitflags(ia)) {
			p = ia->ia_dstaddr.sin_addr;
			if (prefix.s_addr != p.s_addr)
				continue;
		} else {
			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 ((ia->ia_ifp->if_flags & IFF_UP) == 0)
			continue;
		if ((ia->ia_flags & IFA_ROUTE) == 0) {
			ifa_ref(&ia->ia_ifa);
			IN_IFADDR_RUNLOCK(&in_ifa_tracker);
			error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
			    rtinitflags(target));
			if (error == 0)
				target->ia_flags &= ~IFA_ROUTE;
			else
				log(LOG_INFO, "in_scrubprefix: err=%d, old prefix delete failed\n",
					error);
			in_scrubprefixlle(target, target->ia_ifp != ia->ia_ifp,
			    flags);
			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
			    rtinitflags(ia) | RTF_UP);
			if (error == 0)
				ia->ia_flags |= IFA_ROUTE;
			else
				log(LOG_INFO, "in_scrubprefix: err=%d, new prefix add failed\n",
					error);
			ifa_free(&ia->ia_ifa);
			return (error);
		}
	}
	IN_IFADDR_RUNLOCK(&in_ifa_tracker);
	in_scrubprefixlle(target, 1, flags);
	error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
	if (error == 0)
		target->ia_flags &= ~IFA_ROUTE;
	else
		log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error);
	return (error);
}
int in_scrubprefix ( struct in_ifaddr * target , u_int flags ) { struct rm_priotracker in_ifa_tracker ; struct in_ifaddr * ia ; struct in_addr prefix , mask , p , m ; int error = 0 ; if ( ( target -> ia_addr . sin_addr . s_addr != INADDR_ANY ) && ! ( target -> ia_ifp -> if_flags & IFF_LOOPBACK ) && ( flags & LLE_STATIC ) ) { struct in_ifaddr * eia ; eia = in_localip_more ( target ) ; if ( eia != NULL ) { error = ifa_switch_loopback_route ( ( struct ifaddr * ) eia , ( struct sockaddr * ) & target -> ia_addr ) ; ifa_free ( & eia -> ia_ifa ) ; } else { error = ifa_del_loopback_route ( ( struct ifaddr * ) target , ( struct sockaddr * ) & target -> ia_addr ) ; } } if ( rtinitflags ( target ) ) { prefix = target -> ia_dstaddr . sin_addr ; mask . s_addr = 0 ; } else { prefix = target -> ia_addr . sin_addr ; mask = target -> ia_sockmask . sin_addr ; prefix . s_addr &= mask . s_addr ; } if ( ( target -> ia_flags & IFA_ROUTE ) == 0 ) { int fibnum ; fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : target -> ia_ifp -> if_fib ; rt_addrmsg ( RTM_DELETE , & target -> ia_ifa , fibnum ) ; in_scrubprefixlle ( target , 0 , flags ) ; return ( 0 ) ; } IN_IFADDR_RLOCK ( & in_ifa_tracker ) ; TAILQ_FOREACH ( ia , & V_in_ifaddrhead , ia_link ) { if ( rtinitflags ( ia ) ) { p = ia -> ia_dstaddr . sin_addr ; if ( prefix . s_addr != p . s_addr ) continue ; } else { 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 ( ( ia -> ia_ifp -> if_flags & IFF_UP ) == 0 ) continue ; if ( ( ia -> ia_flags & IFA_ROUTE ) == 0 ) { ifa_ref ( & ia -> ia_ifa ) ; IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; error = rtinit ( & ( target -> ia_ifa ) , ( int ) RTM_DELETE , rtinitflags ( target ) ) ; if ( error == 0 ) target -> ia_flags &= ~ IFA_ROUTE ; else log ( LOG_INFO , " \n " , error ) ; in_scrubprefixlle ( target , target -> ia_ifp != ia -> ia_ifp , flags ) ; error = rtinit ( & ia -> ia_ifa , ( int ) RTM_ADD , rtinitflags ( ia ) | RTF_UP ) ; if ( error == 0 ) ia -> ia_flags |= IFA_ROUTE ; else log ( LOG_INFO , " \n " , error ) ; ifa_free ( & ia -> ia_ifa ) ; return ( error ) ; } } IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; in_scrubprefixlle ( target , 1 , flags ) ; error = rtinit ( & ( target -> ia_ifa ) , ( int ) RTM_DELETE , rtinitflags ( target ) ) ; if ( error == 0 ) target -> ia_flags &= ~ IFA_ROUTE ; else log ( LOG_INFO , " \n " , error ) ; return ( error ) ; }
If there is no other address in the system that can serve a route to the
 same prefix, remove the route.
If there is no other address in the system that can serve a route to the same prefix remove the route .
/*
	 * Remove the loopback route to the interface address.
	 */ /*
		 * XXXME: add fib-aware in_localip.
		 * We definitely don't want to switch between
		 * prefixes in different fibs.
		 */ /*
		 * Removing address from !IFF_UP interface or
		 * prefix which exists on other interface (along with route).
		 * No entries should exist here except target addr.
		 * Given that, delete this entry only.
		 */ /*
		 * If we got a matching prefix address, move IFA_ROUTE and
		 * the route itself to it.  Make sure that routing daemons
		 * get a heads-up.
		 */ /* Scrub all entries IFF interface is different */ /*
	 * remove all L2 entries on the given prefix
	 */ /*
	 * As no-one seem to have this prefix, we can remove the route.
	 */