version 1.1.2.2, 1999/11/30 13:35:50 |
version 1.2, 1999/07/01 08:12:54 |
|
|
#include <sys/malloc.h> |
#include <sys/malloc.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/sockio.h> |
#include <sys/sockio.h> |
#include <sys/kernel.h> |
|
#ifdef __bsdi__ |
|
#include <crypto/md5.h> |
|
#elif defined(__OpenBSD__) |
|
#include <sys/md5k.h> |
|
#else |
|
#include <sys/md5.h> |
|
#endif |
|
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
|
|
#include <netinet/if_ether.h> |
#include <netinet/if_ether.h> |
#endif |
#endif |
|
|
|
#include <netinet6/in6.h> |
#include <netinet6/ip6.h> |
#include <netinet6/ip6.h> |
#include <netinet6/ip6_var.h> |
#include <netinet6/ip6_var.h> |
#include <netinet6/in6_ifattach.h> |
#include <netinet6/in6_ifattach.h> |
|
|
#include <netinet6/ip6_var.h> |
#include <netinet6/ip6_var.h> |
#include <netinet6/nd6.h> |
#include <netinet6/nd6.h> |
|
|
#include <net/net_osdep.h> |
|
|
|
static struct in6_addr llsol; |
static struct in6_addr llsol; |
|
|
struct in6_ifstat **in6_ifstat = NULL; |
struct in6_addr **in6_iflladdr = NULL; |
struct icmp6_ifstat **icmp6_ifstat = NULL; |
|
size_t in6_ifstatmax = 0; |
|
size_t icmp6_ifstatmax = 0; |
|
unsigned long in6_maxmtu = 0; |
unsigned long in6_maxmtu = 0; |
|
|
int found_first_ifid = 0; |
int found_first_ifid = 0; |
#define IFID_LEN 8 |
#define IFID_LEN 8 |
static char first_ifid[IFID_LEN]; |
static char first_ifid[IFID_LEN]; |
|
|
static int laddr_to_eui64 __P((u_int8_t *, u_int8_t *, size_t)); |
static void ieee802_to_eui64 __P((u_int8_t *, u_int8_t *)); |
static int gen_rand_eui64 __P((u_int8_t *)); |
|
|
|
static int |
static void |
laddr_to_eui64(dst, src, len) |
ieee802_to_eui64(dst, src) |
u_int8_t *dst; |
u_int8_t *dst; |
u_int8_t *src; |
u_int8_t *src; |
size_t len; |
|
{ |
{ |
static u_int8_t zero[8]; |
dst[0] = src[0]; |
|
dst[1] = src[1]; |
bzero(zero, sizeof(zero)); |
dst[2] = src[2]; |
|
dst[3] = 0xff; |
switch (len) { |
dst[4] = 0xfe; |
case 6: |
dst[5] = src[3]; |
if (bcmp(zero, src, 6) == 0) |
dst[6] = src[4]; |
return EINVAL; |
dst[7] = src[5]; |
dst[0] = src[0]; |
|
dst[1] = src[1]; |
|
dst[2] = src[2]; |
|
dst[3] = 0xff; |
|
dst[4] = 0xfe; |
|
dst[5] = src[3]; |
|
dst[6] = src[4]; |
|
dst[7] = src[5]; |
|
break; |
|
case 8: |
|
if (bcmp(zero, src, 8) == 0) |
|
return EINVAL; |
|
bcopy(src, dst, len); |
|
break; |
|
default: |
|
return EINVAL; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
|
* Generate a last-resort interface identifier, when the machine has no |
|
* IEEE802/EUI64 address sources. |
|
* The address should be random, and should not change across reboot. |
|
*/ |
|
static int |
|
gen_rand_eui64(dst) |
|
u_int8_t *dst; |
|
{ |
|
MD5_CTX ctxt; |
|
u_int8_t digest[16]; |
|
#ifdef __FreeBSD__ |
|
int hostnamelen = strlen(hostname); |
|
#endif |
|
|
|
/* generate 8bytes of pseudo-random value. */ |
|
bzero(&ctxt, sizeof(ctxt)); |
|
MD5Init(&ctxt); |
|
MD5Update(&ctxt, hostname, hostnamelen); |
|
MD5Final(digest, &ctxt); |
|
|
|
/* assumes sizeof(digest) > sizeof(first_ifid) */ |
|
bcopy(digest, dst, 8); |
|
|
|
/* make sure to set "u" bit to local, and "g" bit to individual. */ |
|
dst[0] &= 0xfe; |
|
dst[0] |= 0x02; /* EUI64 "local" */ |
|
|
|
return 0; |
|
} |
} |
|
|
/* |
/* |
* Find first ifid on list of interfaces. |
* find first ifid on list of interfaces. |
* This is assumed that ifp0's interface token (for example, IEEE802 MAC) |
|
* is globally unique. We may need to have a flag parameter in the future. |
|
*/ |
*/ |
int |
int |
in6_ifattach_getifid(ifp0) |
in6_ifattach_getifid(ifp0) |
Line 160 in6_ifattach_getifid(ifp0) |
|
Line 94 in6_ifattach_getifid(ifp0) |
|
if (found_first_ifid) |
if (found_first_ifid) |
return 0; |
return 0; |
|
|
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { |
for (ifp = ifnet; ifp; ifp = ifp->if_next) |
|
#else |
|
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) |
|
#endif |
|
{ |
|
if (ifp0 != NULL && ifp0 != ifp) |
if (ifp0 != NULL && ifp0 != ifp) |
continue; |
continue; |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) |
|
#else |
|
for (ifa = ifp->if_addrlist.tqh_first; |
for (ifa = ifp->if_addrlist.tqh_first; |
ifa; |
ifa; |
ifa = ifa->ifa_list.tqe_next) |
ifa = ifa->ifa_list.tqe_next) { |
#endif |
|
{ |
|
if (ifa->ifa_addr->sa_family != AF_LINK) |
if (ifa->ifa_addr->sa_family != AF_LINK) |
continue; |
continue; |
sdl = (struct sockaddr_dl *)ifa->ifa_addr; |
sdl = (struct sockaddr_dl *)ifa->ifa_addr; |
Line 187 in6_ifattach_getifid(ifp0) |
|
Line 111 in6_ifattach_getifid(ifp0) |
|
case IFT_ETHER: |
case IFT_ETHER: |
case IFT_FDDI: |
case IFT_FDDI: |
case IFT_ATM: |
case IFT_ATM: |
/* IEEE802/EUI64 cases - what others? */ |
/* what others? */ |
addr = LLADDR(sdl); |
addr = LLADDR(sdl); |
addrlen = sdl->sdl_alen; |
addrlen = sdl->sdl_alen; |
/* |
|
* to copy ifid from IEEE802/EUI64 interface, |
|
* u bit of the source needs to be 0. |
|
*/ |
|
if ((addr[0] & 0x02) != 0) |
|
break; |
|
goto found; |
goto found; |
case IFT_ARCNET: |
|
/* |
|
* ARCnet interface token cannot be used as |
|
* globally unique identifier due to its |
|
* small bitwidth. |
|
*/ |
|
break; |
|
default: |
default: |
break; |
break; |
} |
} |
} |
} |
} |
} |
#ifdef DEBUG |
printf("failed to get EUI64"); |
printf("in6_ifattach_getifid: failed to get EUI64"); |
|
#endif |
|
return EADDRNOTAVAIL; |
return EADDRNOTAVAIL; |
|
|
found: |
found: |
if (laddr_to_eui64(first_ifid, addr, addrlen) == 0) |
switch (addrlen) { |
|
case 6: |
|
ieee802_to_eui64(first_ifid, addr); |
found_first_ifid = 1; |
found_first_ifid = 1; |
|
break; |
|
case 8: |
|
bcopy(addr, first_ifid, 8); |
|
found_first_ifid = 1; |
|
break; |
|
default: |
|
break; |
|
} |
|
|
if (found_first_ifid) { |
if (found_first_ifid) { |
printf("%s: supplying EUI64: " |
printf("got EUI64 from %s, " |
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
"value %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
if_name(ifp), |
ifp->if_xname, |
first_ifid[0] & 0xff, first_ifid[1] & 0xff, |
first_ifid[0] & 0xff, first_ifid[1] & 0xff, |
first_ifid[2] & 0xff, first_ifid[3] & 0xff, |
first_ifid[2] & 0xff, first_ifid[3] & 0xff, |
first_ifid[4] & 0xff, first_ifid[5] & 0xff, |
first_ifid[4] & 0xff, first_ifid[5] & 0xff, |
first_ifid[6] & 0xff, first_ifid[7] & 0xff); |
first_ifid[6] & 0xff, first_ifid[7] & 0xff); |
|
|
/* invert u bit to convert EUI64 to RFC2373 interface ID. */ |
|
first_ifid[0] ^= 0x02; |
|
|
|
return 0; |
return 0; |
} else { |
} else { |
#ifdef DEBUG |
printf("failed to get EUI64"); |
printf("in6_ifattach_getifid: failed to get EUI64"); |
|
#endif |
|
return EADDRNOTAVAIL; |
return EADDRNOTAVAIL; |
} |
} |
} |
} |
|
|
/* |
/* |
* add link-local address to *pseudo* p2p interfaces. |
* add link-local address to *pseudo* p2p interfaces. |
* get called when the first MAC address is made available in in6_ifattach(). |
* get called when the first MAC address is made available in in6_ifattach(). |
* |
|
* XXX I start considering this loop as a bad idea. (itojun) |
|
*/ |
*/ |
void |
void |
in6_ifattach_p2p() |
in6_ifattach_p2p() |
Line 251 in6_ifattach_p2p() |
|
Line 162 in6_ifattach_p2p() |
|
struct ifnet *ifp; |
struct ifnet *ifp; |
|
|
/* prevent infinite loop. just in case. */ |
/* prevent infinite loop. just in case. */ |
if (found_first_ifid == 0) |
if (! found_first_ifid) |
return; |
return; |
|
|
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { |
for (ifp = ifnet; ifp; ifp = ifp->if_next) |
|
#else |
|
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) |
|
#endif |
|
{ |
|
switch (ifp->if_type) { |
switch (ifp->if_type) { |
case IFT_GIF: |
case IFT_GIF: |
|
case IFT_FAITH: |
/* pseudo interfaces - safe to initialize here */ |
/* pseudo interfaces - safe to initialize here */ |
in6_ifattach(ifp, IN6_IFT_P2P, 0, 0); |
in6_ifattach(ifp, IN6_IFT_P2P, 0, 0); |
break; |
break; |
case IFT_DUMMY: |
|
case IFT_FAITH: |
|
/* this mistakingly becomes IFF_UP */ |
|
break; |
|
case IFT_SLIP: |
case IFT_SLIP: |
/* IPv6 is not supported */ |
/* IPv6 is not supported */ |
break; |
break; |
Line 286 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 189 in6_ifattach(ifp, type, laddr, noloop) |
|
struct ifnet *ifp; |
struct ifnet *ifp; |
u_int type; |
u_int type; |
caddr_t laddr; |
caddr_t laddr; |
/* size_t laddrlen; */ |
|
int noloop; |
int noloop; |
|
/* xxx sizeof(laddr) */ |
{ |
{ |
static size_t if_indexlim = 8; |
static size_t if_indexlim = 8; |
struct sockaddr_in6 mltaddr; |
struct sockaddr_in6 mltaddr; |
struct sockaddr_in6 mltmask; |
struct sockaddr_in6 mltmask; |
struct sockaddr_in6 gate; |
struct sockaddr_in6 gate; |
struct sockaddr_in6 mask; |
struct sockaddr_in6 mask; |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
struct ifaddr **ifap; |
|
#endif |
|
|
|
struct in6_ifaddr *ia, *ib, *oia; |
struct in6_ifaddr *ia, *ib, *oia; |
struct ifaddr *ifa; |
struct ifaddr *ifa; |
int rtflag = 0; |
int rtflag = 0; |
|
|
if (type == IN6_IFT_P2P && found_first_ifid == 0) { |
if (type == IN6_IFT_P2P && found_first_ifid == 0) { |
printf("%s: no ifid available for IPv6 link-local address\n", |
printf("%s: no ifid available yet for IPv6 link-local address\n", |
if_name(ifp)); |
ifp->if_xname); |
#if 0 |
|
return; |
return; |
#else |
|
/* last resort */ |
|
if (gen_rand_eui64(first_ifid) == 0) { |
|
printf("%s: using random value as EUI64: " |
|
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
|
if_name(ifp), |
|
first_ifid[0] & 0xff, first_ifid[1] & 0xff, |
|
first_ifid[2] & 0xff, first_ifid[3] & 0xff, |
|
first_ifid[4] & 0xff, first_ifid[5] & 0xff, |
|
first_ifid[6] & 0xff, first_ifid[7] & 0xff); |
|
/* |
|
* invert u bit to convert EUI64 to RFC2373 interface |
|
* ID. |
|
*/ |
|
first_ifid[0] ^= 0x02; |
|
|
|
found_first_ifid = 1; |
|
} |
|
#endif |
|
} |
} |
|
|
if ((ifp->if_flags & IFF_MULTICAST) == 0) { |
if ((ifp->if_flags & IFF_MULTICAST) == 0) { |
printf("%s: not multicast capable, IPv6 not enabled\n", |
printf("%s: no multicast allowed, IPv6 is not enabled\n", |
if_name(ifp)); |
ifp->if_xname); |
return; |
return; |
} |
} |
|
|
/* |
/* |
* We have some arrays that should be indexed by if_index. |
* We have some arrays that should be indexed by if_index. |
* since if_index will grow dynamically, they should grow too. |
* since if_index will grow dynamically, they should grow too. |
* struct in6_ifstat **in6_ifstat |
* struct in6_addr **in6_iflladdr |
* struct icmp6_ifstat **icmp6_ifstat |
|
*/ |
*/ |
if (in6_ifstat == NULL || icmp6_ifstat == NULL |
if (in6_iflladdr == NULL || if_index >= if_indexlim) { |
|| if_index >= if_indexlim) { |
|
size_t n; |
size_t n; |
caddr_t q; |
caddr_t q; |
size_t olim; |
|
|
|
olim = if_indexlim; |
while(if_index >= if_indexlim) |
while (if_index >= if_indexlim) |
|
if_indexlim <<= 1; |
if_indexlim <<= 1; |
|
|
/* grow in6_ifstat */ |
/* grow in6_iflladdr */ |
n = if_indexlim * sizeof(struct in6_ifstat *); |
n = if_indexlim * sizeof(struct in6_addr *); |
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); |
|
bzero(q, n); |
|
if (in6_ifstat) { |
|
bcopy((caddr_t)in6_ifstat, q, |
|
olim * sizeof(struct in6_ifstat *)); |
|
free((caddr_t)in6_ifstat, M_IFADDR); |
|
} |
|
in6_ifstat = (struct in6_ifstat **)q; |
|
in6_ifstatmax = if_indexlim; |
|
|
|
/* grow icmp6_ifstat */ |
|
n = if_indexlim * sizeof(struct icmp6_ifstat *); |
|
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); |
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); |
bzero(q, n); |
bzero(q, n); |
if (icmp6_ifstat) { |
if (in6_iflladdr) { |
bcopy((caddr_t)icmp6_ifstat, q, |
bcopy((caddr_t)in6_iflladdr, q, n/2); |
olim * sizeof(struct icmp6_ifstat *)); |
free((caddr_t)in6_iflladdr, M_IFADDR); |
free((caddr_t)icmp6_ifstat, M_IFADDR); |
|
} |
} |
icmp6_ifstat = (struct icmp6_ifstat **)q; |
in6_iflladdr = (struct in6_addr **)q; |
icmp6_ifstatmax = if_indexlim; |
|
} |
} |
|
|
/* |
/* |
Line 380 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 242 in6_ifattach(ifp, type, laddr, noloop) |
|
* cards multiple times. |
* cards multiple times. |
* This is lengthy for P2P and LOOP but works. |
* This is lengthy for P2P and LOOP but works. |
*/ |
*/ |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
ifa = ifp->if_addrlist; |
|
if (ifa != NULL) { |
|
for ( ; ifa; ifa = ifa->ifa_next) { |
|
ifap = &ifa->ifa_next; |
|
if (ifa->ifa_addr->sa_family != AF_INET6) |
|
continue; |
|
if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr)) |
|
return; |
|
} |
|
} else |
|
ifap = &ifp->if_addrlist; |
|
#else |
|
ifa = TAILQ_FIRST(&ifp->if_addrlist); |
ifa = TAILQ_FIRST(&ifp->if_addrlist); |
if (ifa != NULL) { |
if (ifa != NULL) { |
for ( ; ifa; ifa = TAILQ_NEXT(ifa, ifa_list)) { |
for ( ; ifa; ifa = TAILQ_NEXT(ifa, ifa_list)) { |
Line 401 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 250 in6_ifattach(ifp, type, laddr, noloop) |
|
if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr)) |
if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr)) |
return; |
return; |
} |
} |
} else { |
} else |
TAILQ_INIT(&ifp->if_addrlist); |
TAILQ_INIT(&ifp->if_addrlist); |
} |
|
#endif |
|
|
|
/* |
/* |
* link-local address |
* link-local address |
Line 415 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 262 in6_ifattach(ifp, type, laddr, noloop) |
|
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; |
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; |
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; |
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; |
ia->ia_ifp = ifp; |
ia->ia_ifp = ifp; |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
*ifap = (struct ifaddr *)ia; |
|
#else |
|
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
#endif |
|
/* |
/* |
* Also link into the IPv6 address chain beginning with in6_ifaddr. |
* Also link into the IPv6 address chain beginning with in6_ifaddr. |
* kazu opposed it, but itojun & jinmei wanted. |
* kazu opposed it, but itojun & jinmei wanted. |
Line 455 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 298 in6_ifattach(ifp, type, laddr, noloop) |
|
case IN6_IFT_P2P802: |
case IN6_IFT_P2P802: |
if (laddr == NULL) |
if (laddr == NULL) |
break; |
break; |
/* XXX use laddrlen */ |
ieee802_to_eui64(&ia->ia_addr.sin6_addr.s6_addr8[8], laddr); |
if (laddr_to_eui64(&ia->ia_addr.sin6_addr.s6_addr8[8], |
/* set global bit */ |
laddr, 6) != 0) { |
ia->ia_addr.sin6_addr.s6_addr8[8] |= 0x02; |
break; |
if (! found_first_ifid) { |
} |
|
/* invert u bit to convert EUI64 to RFC2373 interface ID. */ |
|
ia->ia_addr.sin6_addr.s6_addr8[8] ^= 0x02; |
|
if (found_first_ifid == 0) { |
|
if (in6_ifattach_getifid(ifp) == 0) |
if (in6_ifattach_getifid(ifp) == 0) |
in6_ifattach_p2p(); |
in6_ifattach_p2p(); |
} |
} |
Line 472 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 311 in6_ifattach(ifp, type, laddr, noloop) |
|
(caddr_t)&ia->ia_addr.sin6_addr.s6_addr8[8], |
(caddr_t)&ia->ia_addr.sin6_addr.s6_addr8[8], |
IFID_LEN); |
IFID_LEN); |
break; |
break; |
case IN6_IFT_ARCNET: |
|
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; |
|
ia->ia_ifa.ifa_flags |= RTF_CLONING; |
|
rtflag = RTF_CLONING; |
|
if (laddr == NULL) |
|
break; |
|
|
|
/* make non-global IF id out of link-level address */ |
|
bzero(&ia->ia_addr.sin6_addr.s6_addr8[8], 7); |
|
ia->ia_addr.sin6_addr.s6_addr8[15] = *laddr; |
|
} |
} |
|
|
ia->ia_ifa.ifa_metric = ifp->if_metric; |
ia->ia_ifa.ifa_metric = ifp->if_metric; |
Line 501 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 330 in6_ifattach(ifp, type, laddr, noloop) |
|
if (error) { |
if (error) { |
switch (error) { |
switch (error) { |
case EAFNOSUPPORT: |
case EAFNOSUPPORT: |
printf("%s: IPv6 not supported\n", |
printf("%s: IPv6 is not supported\n", |
if_name(ifp)); |
ifp->if_xname); |
break; |
break; |
default: |
default: |
printf("%s: SIOCSIFADDR error %d\n", |
printf("SIOCSIFADDR(%s) returned %d\n", |
if_name(ifp), error); |
ifp->if_xname, error); |
break; |
break; |
} |
} |
|
|
/* undo changes */ |
/* undo changes */ |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
*ifap = NULL; |
|
#else |
|
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
#endif |
|
if (oia) |
if (oia) |
oia->ia_next = ia->ia_next; |
oia->ia_next = ia->ia_next; |
else |
else |
Line 534 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 359 in6_ifattach(ifp, type, laddr, noloop) |
|
(struct rtentry **)0); |
(struct rtentry **)0); |
ia->ia_flags |= IFA_ROUTE; |
ia->ia_flags |= IFA_ROUTE; |
|
|
|
|
if (type == IN6_IFT_P2P || type == IN6_IFT_P2P802) { |
if (type == IN6_IFT_P2P || type == IN6_IFT_P2P802) { |
/* |
/* |
* route local address to loopback |
* route local address to loopback |
Line 568 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 394 in6_ifattach(ifp, type, laddr, noloop) |
|
ib->ia_ifp = ifp; |
ib->ia_ifp = ifp; |
|
|
ia->ia_next = ib; |
ia->ia_next = ib; |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
ia->ia_ifa.ifa_next = (struct ifaddr *)ib; |
|
#else |
|
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ib, |
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ib, |
ifa_list); |
ifa_list); |
#endif |
|
|
|
ib->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); |
ib->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); |
ib->ia_prefixmask.sin6_family = AF_INET6; |
ib->ia_prefixmask.sin6_family = AF_INET6; |
Line 611 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 433 in6_ifattach(ifp, type, laddr, noloop) |
|
if (ifp->if_flags & IFF_MULTICAST) { |
if (ifp->if_flags & IFF_MULTICAST) { |
int error; /* not used */ |
int error; /* not used */ |
|
|
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) |
#if !defined(__FreeBSD__) || __FreeBSD__ < 3 |
/* Restore saved multicast addresses(if any). */ |
/* Restore saved multicast addresses(if any). */ |
in6_restoremkludge(ia, ifp); |
in6_restoremkludge(ia, ifp); |
#endif |
#endif |
Line 665 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 487 in6_ifattach(ifp, type, laddr, noloop) |
|
} |
} |
|
|
/* update dynamically. */ |
/* update dynamically. */ |
|
in6_iflladdr[ifp->if_index] = &ia->ia_addr.sin6_addr; |
if (in6_maxmtu < ifp->if_mtu) |
if (in6_maxmtu < ifp->if_mtu) |
in6_maxmtu = ifp->if_mtu; |
in6_maxmtu = ifp->if_mtu; |
|
|
if (in6_ifstat[ifp->if_index] == NULL) { |
|
in6_ifstat[ifp->if_index] = (struct in6_ifstat *) |
|
malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK); |
|
bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat)); |
|
} |
|
if (icmp6_ifstat[ifp->if_index] == NULL) { |
|
icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *) |
|
malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK); |
|
bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat)); |
|
} |
|
|
|
/* initialize NDP variables */ |
/* initialize NDP variables */ |
nd6_ifattach(ifp); |
nd6_ifattach(ifp); |
|
|
/* mark the address TENTATIVE, if needed. */ |
/* mark the address TENTATIVE, if needed. */ |
switch (ifp->if_type) { |
switch (ifp->if_type) { |
case IFT_ARCNET: |
|
case IFT_ETHER: |
case IFT_ETHER: |
case IFT_FDDI: |
case IFT_FDDI: |
#if 0 |
#if 0 |
Line 695 in6_ifattach(ifp, type, laddr, noloop) |
|
Line 506 in6_ifattach(ifp, type, laddr, noloop) |
|
ia->ia6_flags |= IN6_IFF_TENTATIVE; |
ia->ia6_flags |= IN6_IFF_TENTATIVE; |
/* nd6_dad_start() will be called in in6_if_up */ |
/* nd6_dad_start() will be called in in6_if_up */ |
break; |
break; |
case IFT_DUMMY: |
case IFT_GIF: |
case IFT_GIF: /*XXX*/ |
|
case IFT_LOOP: |
case IFT_LOOP: |
case IFT_FAITH: |
case IFT_FAITH: |
default: |
default: |
Line 712 in6_ifdetach(ifp) |
|
Line 522 in6_ifdetach(ifp) |
|
{ |
{ |
struct in6_ifaddr *ia, *oia; |
struct in6_ifaddr *ia, *oia; |
struct ifaddr *ifa; |
struct ifaddr *ifa; |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
struct ifaddr *ifaprev = NULL; |
|
#endif |
|
struct rtentry *rt; |
struct rtentry *rt; |
short rtflags; |
short rtflags; |
|
|
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) |
|
#else |
|
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) |
|
#endif |
|
{ |
|
if (ifa->ifa_addr->sa_family != AF_INET6 |
if (ifa->ifa_addr->sa_family != AF_INET6 |
|| !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { |
|| !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
ifaprev = ifa; |
|
#endif |
|
continue; |
continue; |
} |
} |
|
|
Line 736 in6_ifdetach(ifp) |
|
Line 535 in6_ifdetach(ifp) |
|
|
|
/* remove from the routing table */ |
/* remove from the routing table */ |
if ((ia->ia_flags & IFA_ROUTE) |
if ((ia->ia_flags & IFA_ROUTE) |
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0 |
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) { |
#ifdef __FreeBSD__ |
|
, 0UL |
|
#endif |
|
))) { |
|
rtflags = rt->rt_flags; |
rtflags = rt->rt_flags; |
rtfree(rt); |
rtfree(rt); |
rtrequest(RTM_DELETE, |
rtrequest(RTM_DELETE, |
Line 751 in6_ifdetach(ifp) |
|
Line 546 in6_ifdetach(ifp) |
|
} |
} |
|
|
/* remove from the linked list */ |
/* remove from the linked list */ |
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) |
|
if (ifaprev) |
|
ifaprev->ifa_next = ifa->ifa_next; |
|
else |
|
ifp->if_addrlist = ifa->ifa_next; |
|
#else |
|
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); |
#endif |
|
|
|
/* also remove from the IPv6 address chain(itojun&jinmei) */ |
/* also remove from the IPv6 address chain(itojun&jinmei) */ |
oia = ia; |
oia = ia; |
Line 769 in6_ifdetach(ifp) |
|
Line 557 in6_ifdetach(ifp) |
|
ia = ia->ia_next; |
ia = ia->ia_next; |
if (ia->ia_next) |
if (ia->ia_next) |
ia->ia_next = oia->ia_next; |
ia->ia_next = oia->ia_next; |
#ifdef DEBUG |
|
else |
else |
printf("%s: didn't unlink in6ifaddr from " |
printf("Didn't unlink in6ifaddr from list\n"); |
"list\n", if_name(ifp)); |
|
#endif |
|
} |
} |
|
|
free(ia, M_IFADDR); |
free(ia, M_IFADDR); |