FreeBSD/sys/netinet6/in6_ifattach.c
/*
 * Get interface identifier for the specified interface.
 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
 *
 * in6 - upper 64bits are preserved
 */
Get interface identifier for the specified interface.
XXX assumes single sockaddr_dl (AF_LINK address) per an interface

upper 64bits are preserved
Get interface identifier for the specified interface . XXX assumes single sockaddr_dl ( AF_LINK address ) per an interface upper 64bits are preserved
int
in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
{
	struct ifaddr *ifa;
	struct sockaddr_dl *sdl;
	u_int8_t *addr;
	size_t addrlen;
	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	static u_int8_t allone[8] =
		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	IF_ADDR_RLOCK(ifp);
	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
		if (ifa->ifa_addr->sa_family != AF_LINK)
			continue;
		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
		if (sdl == NULL)
			continue;
		if (sdl->sdl_alen == 0)
			continue;
		goto found;
	}
	IF_ADDR_RUNLOCK(ifp);
	return -1;
found:
	IF_ADDR_LOCK_ASSERT(ifp);
	addr = LLADDR(sdl);
	addrlen = sdl->sdl_alen;
	switch (ifp->if_type) {
	case IFT_BRIDGE:
	case IFT_ETHER:
	case IFT_L2VLAN:
	case IFT_FDDI:
	case IFT_ISO88025:
	case IFT_ATM:
	case IFT_IEEE1394:
	case IFT_IEEE80211:
		if (addrlen > 8)
			addrlen = 8;
		if (addrlen != 8 && addrlen != 6) {
			IF_ADDR_RUNLOCK(ifp);
			return -1;
		}
		if (bcmp(addr, allzero, addrlen) == 0) {
			IF_ADDR_RUNLOCK(ifp);
			return -1;
		}
		if (bcmp(addr, allone, addrlen) == 0) {
			IF_ADDR_RUNLOCK(ifp);
			return -1;
		}
		if (addrlen == 8)
			bcopy(addr, &in6->s6_addr[8], 8);
		else if (addrlen == 6) {
			in6->s6_addr[8] = addr[0];
			in6->s6_addr[9] = addr[1];
			in6->s6_addr[10] = addr[2];
			in6->s6_addr[11] = 0xff;
			in6->s6_addr[12] = 0xfe;
			in6->s6_addr[13] = addr[3];
			in6->s6_addr[14] = addr[4];
			in6->s6_addr[15] = addr[5];
		}
		break;
	case IFT_ARCNET:
		if (addrlen != 1) {
			IF_ADDR_RUNLOCK(ifp);
			return -1;
		}
		if (!addr[0]) {
			IF_ADDR_RUNLOCK(ifp);
			return -1;
		}
		bzero(&in6->s6_addr[8], 8);
		in6->s6_addr[15] = addr[0];
		in6->s6_addr[8] &= ~EUI64_GBIT;	
		in6->s6_addr[8] |= EUI64_UBIT;	
		break;
	case IFT_GIF:
	case IFT_STF:
		IF_ADDR_RUNLOCK(ifp);
		return -1;
	default:
		IF_ADDR_RUNLOCK(ifp);
		return -1;
	}
	if (EUI64_GROUP(in6)) {
		IF_ADDR_RUNLOCK(ifp);
		return -1;
	}
	EUI64_TO_IFID(in6);
	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
		IF_ADDR_RUNLOCK(ifp);
		return -1;
	}
	IF_ADDR_RUNLOCK(ifp);
	return 0;
}
int in6_get_hw_ifid ( struct ifnet * ifp , struct in6_addr * in6 ) { struct ifaddr * ifa ; struct sockaddr_dl * sdl ; u_int8_t * addr ; size_t addrlen ; static u_int8_t allzero [ 8 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ; static u_int8_t allone [ 8 ] = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff } ; IF_ADDR_RLOCK ( ifp ) ; TAILQ_FOREACH ( ifa , & ifp -> if_addrhead , ifa_link ) { if ( ifa -> ifa_addr -> sa_family != AF_LINK ) continue ; sdl = ( struct sockaddr_dl * ) ifa -> ifa_addr ; if ( sdl == NULL ) continue ; if ( sdl -> sdl_alen == 0 ) continue ; goto found ; } IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; found : IF_ADDR_LOCK_ASSERT ( ifp ) ; addr = LLADDR ( sdl ) ; addrlen = sdl -> sdl_alen ; switch ( ifp -> if_type ) { case IFT_BRIDGE : case IFT_ETHER : case IFT_L2VLAN : case IFT_FDDI : case IFT_ISO88025 : case IFT_ATM : case IFT_IEEE1394 : case IFT_IEEE80211 : if ( addrlen > 8 ) addrlen = 8 ; if ( addrlen != 8 && addrlen != 6 ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } if ( bcmp ( addr , allzero , addrlen ) == 0 ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } if ( bcmp ( addr , allone , addrlen ) == 0 ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } if ( addrlen == 8 ) bcopy ( addr , & in6 -> s6_addr [ 8 ] , 8 ) ; else if ( addrlen == 6 ) { in6 -> s6_addr [ 8 ] = addr [ 0 ] ; in6 -> s6_addr [ 9 ] = addr [ 1 ] ; in6 -> s6_addr [ 10 ] = addr [ 2 ] ; in6 -> s6_addr [ 11 ] = 0xff ; in6 -> s6_addr [ 12 ] = 0xfe ; in6 -> s6_addr [ 13 ] = addr [ 3 ] ; in6 -> s6_addr [ 14 ] = addr [ 4 ] ; in6 -> s6_addr [ 15 ] = addr [ 5 ] ; } break ; case IFT_ARCNET : if ( addrlen != 1 ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } if ( ! addr [ 0 ] ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } bzero ( & in6 -> s6_addr [ 8 ] , 8 ) ; in6 -> s6_addr [ 15 ] = addr [ 0 ] ; in6 -> s6_addr [ 8 ] &= ~ EUI64_GBIT ; in6 -> s6_addr [ 8 ] |= EUI64_UBIT ; break ; case IFT_GIF : case IFT_STF : IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; default : IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } if ( EUI64_GROUP ( in6 ) ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } EUI64_TO_IFID ( in6 ) ; if ( ( in6 -> s6_addr [ 8 ] & ~ ( EUI64_GBIT | EUI64_UBIT ) ) == 0x00 && bcmp ( & in6 -> s6_addr [ 9 ] , allzero , 7 ) == 0 ) { IF_ADDR_RUNLOCK ( ifp ) ; return -1 ; } IF_ADDR_RUNLOCK ( ifp ) ; return 0 ; }
Get interface identifier for the specified interface.
Get interface identifier for the specified interface .
/* get EUI64 */ /* IEEE802/EUI64 cases - what others? */ /* IEEE1394 uses 16byte length address starting with EUI64 */ /* look at IEEE802/EUI64 only */ /*
		 * check for invalid MAC address - on bsdi, we see it a lot
		 * since wildboar configures all-zero MAC on pccard before
		 * card insertion.
		 */ /* make EUI64 address */ /*
		 * due to insufficient bitwidth, we mark it local.
		 */ /* g bit to "individual" */ /* u bit to "local" */ /*
		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
		 * however, IPv4 address is not very suitable as unique
		 * identifier source (can be renumbered).
		 * we don't do this.
		 */ /* sanity check: g bit must not indicate "group" */ /* convert EUI64 into IPv6 interface identifier */ /*
	 * sanity check: ifid must not be all zero, avoid conflict with
	 * subnet router anycast
	 */