FreeBSD/sys/netinet6/in6.c
/*
 * Notifies other subsystems about address change/arrival:
 * 1) Notifies device handler on the first IPv6 address assignment
 * 2) Handle routing table changes for P2P links and route
 * 3) Handle routing table changes for address host route
 */
Notifies other subsystems about address change/arrival:
1) Notifies device handler on the first IPv6 address assignment
2) Handle routing table changes for P2P links and route
3) Handle routing table changes for address host route
Notifies other subsystems about address change / arrival : 1 ) Notifies device handler on the first IPv6 address assignment 2 ) Handle routing table changes for P2P links and route 3 ) Handle routing table changes for address host route
static int
in6_notify_ifa(struct ifnet *ifp, struct in6_ifaddr *ia,
    struct in6_aliasreq *ifra, int hostIsNew)
{
	int	error = 0, plen, ifacount = 0;
	struct ifaddr *ifa;
	struct sockaddr_in6 *pdst;
	char ip6buf[INET6_ADDRSTRLEN];
	if (hostIsNew != 0) {
		IF_ADDR_RLOCK(ifp);
		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
			if (ifa->ifa_addr->sa_family != AF_INET6)
				continue;
			ifacount++;
		}
		IF_ADDR_RUNLOCK(ifp);
	}
	if (ifacount <= 1 && ifp->if_ioctl) {
		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
		if (error)
			return (error);
	}
	pdst = &ifra->ifra_dstaddr;
	if (pdst->sin6_family == AF_INET6 &&
	    !IN6_ARE_ADDR_EQUAL(&pdst->sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
		    (rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST) != 0)) {
			nd6log((LOG_ERR, "in6_update_ifa_internal: failed to "
			    "remove a route to the old destination: %s\n",
			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
		} else
			ia->ia_flags &= ~IFA_ROUTE;
		ia->ia_dstaddr = *pdst;
	}
	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); 
	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
	    ia->ia_dstaddr.sin6_family == AF_INET6) {
		int rtflags = RTF_UP | RTF_HOST;
		if (ifp->if_flags & IFF_LOOPBACK)
			ia->ia_flags |= IFA_RTSELF;
		error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags);
		if (error)
			return (error);
		ia->ia_flags |= IFA_ROUTE;
	}
	if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) {
		error = ifa_add_loopback_route((struct ifaddr *)ia,
		    (struct sockaddr *)&ia->ia_addr);
		if (error == 0)
			ia->ia_flags |= IFA_RTSELF;
	}
	return (error);
}
static int in6_notify_ifa ( struct ifnet * ifp , struct in6_ifaddr * ia , struct in6_aliasreq * ifra , int hostIsNew ) { int error = 0 , plen , ifacount = 0 ; struct ifaddr * ifa ; struct sockaddr_in6 * pdst ; char ip6buf [ INET6_ADDRSTRLEN ] ; if ( hostIsNew != 0 ) { IF_ADDR_RLOCK ( ifp ) ; TAILQ_FOREACH ( ifa , & ifp -> if_addrhead , ifa_link ) { if ( ifa -> ifa_addr -> sa_family != AF_INET6 ) continue ; ifacount ++ ; } IF_ADDR_RUNLOCK ( ifp ) ; } if ( ifacount <= 1 && ifp -> if_ioctl ) { error = ( * ifp -> if_ioctl ) ( ifp , SIOCSIFADDR , ( caddr_t ) ia ) ; if ( error ) return ( error ) ; } pdst = & ifra -> ifra_dstaddr ; if ( pdst -> sin6_family == AF_INET6 && ! IN6_ARE_ADDR_EQUAL ( & pdst -> sin6_addr , & ia -> ia_dstaddr . sin6_addr ) ) { if ( ( ia -> ia_flags & IFA_ROUTE ) != 0 && ( rtinit ( & ( ia -> ia_ifa ) , ( int ) RTM_DELETE , RTF_HOST ) != 0 ) ) { nd6log ( ( LOG_ERR , " " " \n " , ip6_sprintf ( ip6buf , & ia -> ia_addr . sin6_addr ) ) ) ; } else ia -> ia_flags &= ~ IFA_ROUTE ; ia -> ia_dstaddr = * pdst ; } plen = in6_mask2len ( & ia -> ia_prefixmask . sin6_addr , NULL ) ; if ( ! ( ia -> ia_flags & IFA_ROUTE ) && plen == 128 && ia -> ia_dstaddr . sin6_family == AF_INET6 ) { int rtflags = RTF_UP | RTF_HOST ; if ( ifp -> if_flags & IFF_LOOPBACK ) ia -> ia_flags |= IFA_RTSELF ; error = rtinit ( & ia -> ia_ifa , RTM_ADD , ia -> ia_flags | rtflags ) ; if ( error ) return ( error ) ; ia -> ia_flags |= IFA_ROUTE ; } if ( ! ( ia -> ia_flags & IFA_RTSELF ) && V_nd6_useloopback ) { error = ifa_add_loopback_route ( ( struct ifaddr * ) ia , ( struct sockaddr * ) & ia -> ia_addr ) ; if ( error == 0 ) ia -> ia_flags |= IFA_RTSELF ; } return ( error ) ; }
Notifies other subsystems about address change/arrival:
 1) Notifies device handler on the first IPv6 address assignment
 2) Handle routing table changes for P2P links and route
 3) Handle routing table changes for address host route
Notifies other subsystems about address change / arrival : 1 ) Notifies device handler on the first IPv6 address assignment 2 ) Handle routing table changes for P2P links and route 3 ) Handle routing table changes for address host route
/*
	 * Give the interface a chance to initialize
	 * if this is its first address,
	 */ /*
	 * If a new destination address is specified, scrub the old one and
	 * install the new destination.  Note that the interface must be
	 * p2p or loopback.
	 */ /* proceed anyway... */ /*
	 * If a new destination address is specified for a point-to-point
	 * interface, install a route to the destination as an interface
	 * direct route.
	 * XXX: the logic below rejects assigning multiple addresses on a p2p
	 * interface that share the same destination.
	 */ /* XXX */ /*
		 * Handle the case for ::1 .
		 */ /*
	 * add a loopback route to self if not exists
	 */