FreeBSD/sys/netinet6/in6.c
/*
 * Allocate a new ifaddr and link it into chains.
 */
Allocate a new ifaddr and link it into chains.
Allocate a new ifaddr and link it into chains .
static struct in6_ifaddr *
in6_alloc_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int flags)
{
	struct in6_ifaddr *ia;
	ia = (struct in6_ifaddr *)ifa_alloc(sizeof(*ia), M_NOWAIT);
	if (ia == NULL)
		return (NULL);
	LIST_INIT(&ia->ia6_memberships);
	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
	ia->ia_addr.sin6_family = AF_INET6;
	ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
	ia->ia_addr = ifra->ifra_addr;
	ia->ia6_createtime = time_uptime;
	if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
		ia->ia_ifa.ifa_dstaddr =
		    (struct sockaddr *)&ia->ia_dstaddr;
	} else {
		ia->ia_ifa.ifa_dstaddr = NULL;
	}
	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
	if (ifra->ifra_prefixmask.sin6_len != 0) {
		ia->ia_prefixmask.sin6_family = AF_INET6;
		ia->ia_prefixmask.sin6_len = ifra->ifra_prefixmask.sin6_len;
		ia->ia_prefixmask.sin6_addr = ifra->ifra_prefixmask.sin6_addr;
	}
	ia->ia_ifp = ifp;
	ifa_ref(&ia->ia_ifa);			
	IF_ADDR_WLOCK(ifp);
	TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
	IF_ADDR_WUNLOCK(ifp);
	ifa_ref(&ia->ia_ifa);			
	IN6_IFADDR_WLOCK();
	TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
	LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash);
	IN6_IFADDR_WUNLOCK();
	return (ia);
}
static struct in6_ifaddr * in6_alloc_ifa ( struct ifnet * ifp , struct in6_aliasreq * ifra , int flags ) { struct in6_ifaddr * ia ; ia = ( struct in6_ifaddr * ) ifa_alloc ( sizeof ( * ia ) , M_NOWAIT ) ; if ( ia == NULL ) return ( NULL ) ; LIST_INIT ( & ia -> ia6_memberships ) ; ia -> ia_ifa . ifa_addr = ( struct sockaddr * ) & ia -> ia_addr ; ia -> ia_addr . sin6_family = AF_INET6 ; ia -> ia_addr . sin6_len = sizeof ( ia -> ia_addr ) ; ia -> ia_addr = ifra -> ifra_addr ; ia -> ia6_createtime = time_uptime ; if ( ( ifp -> if_flags & ( IFF_POINTOPOINT | IFF_LOOPBACK ) ) != 0 ) { ia -> ia_ifa . ifa_dstaddr = ( struct sockaddr * ) & ia -> ia_dstaddr ; } else { ia -> ia_ifa . ifa_dstaddr = NULL ; } ia -> ia_ifa . ifa_netmask = ( struct sockaddr * ) & ia -> ia_prefixmask ; if ( ifra -> ifra_prefixmask . sin6_len != 0 ) { ia -> ia_prefixmask . sin6_family = AF_INET6 ; ia -> ia_prefixmask . sin6_len = ifra -> ifra_prefixmask . sin6_len ; ia -> ia_prefixmask . sin6_addr = ifra -> ifra_prefixmask . sin6_addr ; } ia -> ia_ifp = ifp ; ifa_ref ( & ia -> ia_ifa ) ; IF_ADDR_WLOCK ( ifp ) ; TAILQ_INSERT_TAIL ( & ifp -> if_addrhead , & ia -> ia_ifa , ifa_link ) ; IF_ADDR_WUNLOCK ( ifp ) ; ifa_ref ( & ia -> ia_ifa ) ; IN6_IFADDR_WLOCK ( ) ; TAILQ_INSERT_TAIL ( & V_in6_ifaddrhead , ia , ia_link ) ; LIST_INSERT_HEAD ( IN6ADDR_HASH ( & ia -> ia_addr . sin6_addr ) , ia , ia6_hash ) ; IN6_IFADDR_WUNLOCK ( ) ; return ( ia ) ; }
Allocate a new ifaddr and link it into chains.
Allocate a new ifaddr and link it into chains .
/*
	 * When in6_alloc_ifa() is called in a process of a received
	 * RA, it is called under an interrupt context.  So, we should
	 * call malloc with M_NOWAIT.
	 */ /* Initialize the address and masks, and put time stamp */ /* XXX: Can we assign ,sin6_addr and skip the rest? */ /*
		 * Some functions expect that ifa_dstaddr is not
		 * NULL for p2p interfaces.
		 */ /* set prefix mask if any */ /* if_addrhead */ /* in6_ifaddrhead */