Annotation of src/sys/netinet6/in6_ifattach.c, Revision 1.96
1.96 ! ozaki-r 1: /* $NetBSD: in6_ifattach.c,v 1.95 2015/02/23 19:15:59 martin Exp $ */
1.37 itojun 2: /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
1.3 thorpej 3:
1.2 itojun 4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
1.24 itojun 7: *
1.2 itojun 8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
1.24 itojun 19: *
1.2 itojun 20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
1.39 lukem 32:
33: #include <sys/cdefs.h>
1.96 ! ozaki-r 34: __KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.95 2015/02/23 19:15:59 martin Exp $");
1.2 itojun 35:
36: #include <sys/param.h>
37: #include <sys/systm.h>
1.83 dyoung 38: #include <sys/kmem.h>
1.2 itojun 39: #include <sys/socket.h>
40: #include <sys/sockio.h>
1.13 itojun 41: #include <sys/kernel.h>
1.34 itojun 42: #include <sys/syslog.h>
1.13 itojun 43: #include <sys/md5.h>
1.80 ad 44: #include <sys/socketvar.h>
1.86 tls 45: #include <sys/cprng.h>
1.2 itojun 46:
47: #include <net/if.h>
48: #include <net/if_dl.h>
49: #include <net/if_types.h>
50: #include <net/route.h>
51:
52: #include <netinet/in.h>
53: #include <netinet/in_var.h>
54:
1.19 itojun 55: #include <netinet/ip6.h>
1.2 itojun 56: #include <netinet6/in6_ifattach.h>
57: #include <netinet6/ip6_var.h>
58: #include <netinet6/nd6.h>
1.55 itojun 59: #include <netinet6/ip6_mroute.h>
1.63 rpaulo 60: #include <netinet6/scope6_var.h>
1.2 itojun 61:
1.13 itojun 62: #include <net/net_osdep.h>
63:
1.2 itojun 64: unsigned long in6_maxmtu = 0;
65:
1.48 itojun 66: int ip6_auto_linklocal = 1; /* enable by default */
67:
1.72 ad 68: callout_t in6_tmpaddrtimer_ch;
1.64 rpaulo 69:
70:
71: #if 0
1.74 dyoung 72: static int get_hostid_ifid(struct ifnet *, struct in6_addr *);
1.64 rpaulo 73: #endif
1.74 dyoung 74: static int get_rand_ifid(struct ifnet *, struct in6_addr *);
75: static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
76: static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
77: static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
78: static int in6_ifattach_loopback(struct ifnet *);
1.25 itojun 79:
80: #define EUI64_GBIT 0x01
81: #define EUI64_UBIT 0x02
1.54 perry 82: #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (/*CONSTCOND*/ 0)
1.25 itojun 83: #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
84: #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
85: #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
86: #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
87:
88: #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
89: #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
90:
1.64 rpaulo 91: #define GEN_TEMPID_RETRY_MAX 5
92:
93: #if 0
94: /*
95: * Generate a last-resort interface identifier from hostid.
96: * works only for certain architectures (like sparc).
97: * also, using hostid itself may constitute a privacy threat, much worse
98: * than MAC addresses (hostids are used for software licensing).
99: * maybe we should use MD5(hostid) instead.
1.71 christos 100: *
101: * in6 - upper 64bits are preserved
1.64 rpaulo 102: */
103: static int
1.71 christos 104: get_hostid_ifid(struct ifnet *ifp, struct in6_addr *in6)
1.64 rpaulo 105: {
106: int off, len;
107: static const uint8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
108: static const uint8_t allone[8] =
109: { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
110:
111: if (!hostid)
112: return -1;
113:
114: /* get up to 8 bytes from the hostid field - should we get */
115: len = (sizeof(hostid) > 8) ? 8 : sizeof(hostid);
116: off = sizeof(*in6) - len;
117: memcpy(&in6->s6_addr[off], &hostid, len);
118:
119: /* make sure we do not return anything bogus */
120: if (memcmp(&in6->s6_addr[8], allzero, sizeof(allzero)))
121: return -1;
122: if (memcmp(&in6->s6_addr[8], allone, sizeof(allone)))
123: return -1;
124:
125: /* make sure to set "u" bit to local, and "g" bit to individual. */
126: in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
127: in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
128:
129: /* convert EUI64 into IPv6 interface identifier */
130: EUI64_TO_IFID(in6);
131:
132: return 0;
133: }
134: #endif
135:
1.25 itojun 136: /*
137: * Generate a last-resort interface identifier, when the machine has no
138: * IEEE802/EUI64 address sources.
139: * The goal here is to get an interface identifier that is
140: * (1) random enough and (2) does not change across reboot.
141: * We currently use MD5(hostname) for it.
142: */
143: static int
1.67 christos 144: get_rand_ifid(struct ifnet *ifp,
1.66 christos 145: struct in6_addr *in6) /* upper 64bits are preserved */
1.25 itojun 146: {
147: MD5_CTX ctxt;
148: u_int8_t digest[16];
149:
150: #if 0
151: /* we need at least several letters as seed for ifid */
152: if (hostnamelen < 3)
153: return -1;
154: #endif
155:
156: /* generate 8 bytes of pseudo-random value. */
1.64 rpaulo 157: memset(&ctxt, 0, sizeof(ctxt));
1.25 itojun 158: MD5Init(&ctxt);
1.50 itojun 159: MD5Update(&ctxt, (u_char *)hostname, hostnamelen);
1.25 itojun 160: MD5Final(digest, &ctxt);
161:
162: /* assumes sizeof(digest) > sizeof(ifid) */
1.64 rpaulo 163: memcpy(&in6->s6_addr[8], digest, 8);
1.2 itojun 164:
1.25 itojun 165: /* make sure to set "u" bit to local, and "g" bit to individual. */
166: in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
167: in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
168:
169: /* convert EUI64 into IPv6 interface identifier */
170: EUI64_TO_IFID(in6);
171:
172: return 0;
173: }
1.2 itojun 174:
1.64 rpaulo 175: static int
1.71 christos 176: generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
1.64 rpaulo 177: {
178: MD5_CTX ctxt;
179: u_int8_t seed[16], digest[16], nullbuf[8];
180: /*
181: * interface ID for subnet anycast addresses.
182: * XXX: we assume the unicast address range that requires IDs
183: * in EUI-64 format.
184: */
185: static const uint8_t anycast_id[8] = { 0xfd, 0xff, 0xff, 0xff,
186: 0xff, 0xff, 0xff, 0x80 };
187: static const uint8_t isatap_id[4] = { 0x00, 0x00, 0x5e, 0xfe };
188: int badid, retry = 0;
189:
190: /* If there's no hisotry, start with a random seed. */
191: memset(nullbuf, 0, sizeof(nullbuf));
192: if (memcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
1.86 tls 193: cprng_fast(seed, sizeof(seed));
1.64 rpaulo 194: } else
195: memcpy(seed, seed0, 8);
196:
197: /* copy the right-most 64-bits of the given address */
198: /* XXX assumption on the size of IFID */
199: memcpy(&seed[8], seed1, 8);
200:
201: again:
202: /* for debugging purposes only */
203: #if 0
204: {
205: int i;
206:
207: printf("generate_tmp_ifid: new randomized ID from: ");
208: for (i = 0; i < 16; i++)
209: printf("%02x", seed[i]);
210: printf(" ");
211: }
212: #endif
213:
214: /* generate 16 bytes of pseudo-random value. */
215: memset(&ctxt, 0, sizeof(ctxt));
216: MD5Init(&ctxt);
217: MD5Update(&ctxt, seed, sizeof(seed));
218: MD5Final(digest, &ctxt);
219:
220: /*
221: * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (3)
222: * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
223: * left-most bit is numbered 0) to zero.
224: */
225: memcpy(ret, digest, 8);
226: ret[0] &= ~EUI64_UBIT;
227:
228: /*
229: * Reject inappropriate identifiers according to
230: * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (4)
231: * At this moment, we reject following cases:
232: * - all 0 identifier
233: * - identifiers that conflict with reserved subnet anycast addresses,
234: * which are defined in RFC 2526.
235: * - identifiers that conflict with ISATAP addresses
236: * - identifiers used in our own addresses
237: */
238: badid = 0;
239: if (memcmp(nullbuf, ret, sizeof(nullbuf)) == 0)
240: badid = 1;
241: else if (memcmp(anycast_id, ret, 7) == 0 &&
242: (anycast_id[7] & ret[7]) == anycast_id[7]) {
243: badid = 1;
244: } else if (memcmp(isatap_id, ret, sizeof(isatap_id)) == 0)
245: badid = 1;
246: else {
247: struct in6_ifaddr *ia;
248:
249: for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
250: if (!memcmp(&ia->ia_addr.sin6_addr.s6_addr[8],
251: ret, 8)) {
252: badid = 1;
253: break;
254: }
255: }
256: }
257:
258: /*
259: * In the event that an unacceptable identifier has been generated,
260: * restart the process, using the right-most 64 bits of the MD5 digest
261: * obtained in place of the history value.
262: */
263: if (badid) {
264: /* for debugging purposes only */
265: #if 0
266: {
267: int i;
268:
269: printf("unacceptable random ID: ");
270: for (i = 0; i < 16; i++)
271: printf("%02x", digest[i]);
272: printf("\n");
273: }
274: #endif
275:
276: if (++retry < GEN_TEMPID_RETRY_MAX) {
277: memcpy(seed, &digest[8], 8);
278: goto again;
279: } else {
280: /*
281: * We're so unlucky. Give up for now, and return
282: * all 0 IDs to tell the caller not to make a
283: * temporary address.
284: */
1.96 ! ozaki-r 285: nd6log(LOG_NOTICE, "never found a good ID\n");
1.64 rpaulo 286: memset(ret, 0, 8);
287: }
288: }
289:
290: /*
291: * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (6)
292: * Take the rightmost 64-bits of the MD5 digest and save them in
293: * stable storage as the history value to be used in the next
294: * iteration of the algorithm.
295: */
296: memcpy(seed0, &digest[8], 8);
297:
298: /* for debugging purposes only */
299: #if 0
300: {
301: int i;
302:
303: printf("to: ");
304: for (i = 0; i < 16; i++)
305: printf("%02x", digest[i]);
306: printf("\n");
307: }
308: #endif
309:
310: return 0;
311: }
1.81 dyoung 312:
1.25 itojun 313: /*
314: * Get interface identifier for the specified interface.
1.71 christos 315: *
316: * in6 - upper 64bits are preserved
1.25 itojun 317: */
1.64 rpaulo 318: int
1.71 christos 319: in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
1.2 itojun 320: {
1.25 itojun 321: struct ifaddr *ifa;
1.81 dyoung 322: const struct sockaddr_dl *sdl = NULL, *tsdl;
1.73 dyoung 323: const char *addr;
1.25 itojun 324: size_t addrlen;
325: static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
326: static u_int8_t allone[8] =
327: { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
328:
1.76 dyoung 329: IFADDR_FOREACH(ifa, ifp) {
1.25 itojun 330: if (ifa->ifa_addr->sa_family != AF_LINK)
331: continue;
1.81 dyoung 332: tsdl = satocsdl(ifa->ifa_addr);
333: if (tsdl == NULL || tsdl->sdl_alen == 0)
1.25 itojun 334: continue;
1.81 dyoung 335: if (sdl == NULL || ifa == ifp->if_dl || ifa == ifp->if_hwdl)
336: sdl = tsdl;
337: if (ifa == ifp->if_hwdl)
338: break;
1.25 itojun 339: }
340:
1.81 dyoung 341: if (sdl == NULL)
342: return -1;
1.25 itojun 343:
1.73 dyoung 344: addr = CLLADDR(sdl);
1.25 itojun 345: addrlen = sdl->sdl_alen;
346:
1.48 itojun 347: switch (ifp->if_type) {
348: case IFT_IEEE1394:
349: case IFT_IEEE80211:
350: /* IEEE1394 uses 16byte length address starting with EUI64 */
351: if (addrlen > 8)
352: addrlen = 8;
353: break;
354: default:
355: break;
356: }
357:
1.25 itojun 358: /* get EUI64 */
359: switch (ifp->if_type) {
1.48 itojun 360: /* IEEE802/EUI64 cases - what others? */
1.25 itojun 361: case IFT_ETHER:
362: case IFT_FDDI:
363: case IFT_ATM:
1.32 onoe 364: case IFT_IEEE1394:
1.48 itojun 365: case IFT_IEEE80211:
1.25 itojun 366: /* look at IEEE802/EUI64 only */
367: if (addrlen != 8 && addrlen != 6)
368: return -1;
1.13 itojun 369:
1.25 itojun 370: /*
371: * check for invalid MAC address - on bsdi, we see it a lot
372: * since wildboar configures all-zero MAC on pccard before
373: * card insertion.
374: */
1.64 rpaulo 375: if (memcmp(addr, allzero, addrlen) == 0)
1.25 itojun 376: return -1;
1.64 rpaulo 377: if (memcmp(addr, allone, addrlen) == 0)
1.25 itojun 378: return -1;
379:
380: /* make EUI64 address */
381: if (addrlen == 8)
1.64 rpaulo 382: memcpy(&in6->s6_addr[8], addr, 8);
1.25 itojun 383: else if (addrlen == 6) {
384: in6->s6_addr[8] = addr[0];
385: in6->s6_addr[9] = addr[1];
386: in6->s6_addr[10] = addr[2];
387: in6->s6_addr[11] = 0xff;
1.26 itojun 388: in6->s6_addr[12] = 0xfe;
1.25 itojun 389: in6->s6_addr[13] = addr[3];
390: in6->s6_addr[14] = addr[4];
391: in6->s6_addr[15] = addr[5];
392: }
1.7 itojun 393: break;
1.25 itojun 394:
395: case IFT_ARCNET:
396: if (addrlen != 1)
397: return -1;
398: if (!addr[0])
399: return -1;
400:
1.64 rpaulo 401: memset(&in6->s6_addr[8], 0, 8);
1.25 itojun 402: in6->s6_addr[15] = addr[0];
403:
1.27 itojun 404: /*
405: * due to insufficient bitwidth, we mark it local.
406: */
1.25 itojun 407: in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
408: in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
1.7 itojun 409: break;
1.25 itojun 410:
411: case IFT_GIF:
412: #ifdef IFT_STF
413: case IFT_STF:
414: #endif
415: /*
1.34 itojun 416: * RFC2893 says: "SHOULD use IPv4 address as ifid source".
1.27 itojun 417: * however, IPv4 address is not very suitable as unique
418: * identifier source (can be renumbered).
419: * we don't do this.
1.25 itojun 420: */
421: return -1;
422:
1.7 itojun 423: default:
1.25 itojun 424: return -1;
425: }
426:
427: /* sanity check: g bit must not indicate "group" */
428: if (EUI64_GROUP(in6))
429: return -1;
430:
431: /* convert EUI64 into IPv6 interface identifier */
432: EUI64_TO_IFID(in6);
433:
434: /*
435: * sanity check: ifid must not be all zero, avoid conflict with
436: * subnet router anycast
437: */
438: if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
1.64 rpaulo 439: memcmp(&in6->s6_addr[9], allzero, 7) == 0) {
1.25 itojun 440: return -1;
1.7 itojun 441: }
442:
443: return 0;
1.2 itojun 444: }
445:
446: /*
1.25 itojun 447: * Get interface identifier for the specified interface. If it is not
448: * available on ifp0, borrow interface identifier from other information
449: * sources.
1.71 christos 450: *
451: * altifp - secondary EUI64 source
1.13 itojun 452: */
453: static int
1.71 christos 454: get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
455: struct in6_addr *in6)
1.13 itojun 456: {
1.25 itojun 457: struct ifnet *ifp;
458:
459: /* first, try to get it from the interface itself */
1.64 rpaulo 460: if (in6_get_hw_ifid(ifp0, in6) == 0) {
1.96 ! ozaki-r 461: nd6log(LOG_DEBUG, "%s: got interface identifier from itself\n",
! 462: if_name(ifp0));
1.25 itojun 463: goto success;
464: }
465:
466: /* try secondary EUI64 source. this basically is for ATM PVC */
1.64 rpaulo 467: if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
1.96 ! ozaki-r 468: nd6log(LOG_DEBUG, "%s: got interface identifier from %s\n",
! 469: if_name(ifp0), if_name(altifp));
1.25 itojun 470: goto success;
471: }
472:
473: /* next, try to get it from some other hardware interface */
1.90 rmind 474: IFNET_FOREACH(ifp) {
1.25 itojun 475: if (ifp == ifp0)
476: continue;
1.64 rpaulo 477: if (in6_get_hw_ifid(ifp, in6) != 0)
1.25 itojun 478: continue;
1.27 itojun 479:
1.25 itojun 480: /*
481: * to borrow ifid from other interface, ifid needs to be
482: * globally unique
483: */
484: if (IFID_UNIVERSAL(in6)) {
1.96 ! ozaki-r 485: nd6log(LOG_DEBUG,
1.34 itojun 486: "%s: borrow interface identifier from %s\n",
1.96 ! ozaki-r 487: if_name(ifp0), if_name(ifp));
1.25 itojun 488: goto success;
489: }
490: }
1.13 itojun 491:
1.64 rpaulo 492: #if 0
493: /* get from hostid - only for certain architectures */
494: if (get_hostid_ifid(ifp, in6) == 0) {
1.96 ! ozaki-r 495: nd6log(LOG_DEBUG,
1.64 rpaulo 496: "%s: interface identifier generated by hostid\n",
1.96 ! ozaki-r 497: if_name(ifp0));
1.64 rpaulo 498: goto success;
499: }
500: #endif
501:
1.25 itojun 502: /* last resort: get from random number source */
503: if (get_rand_ifid(ifp, in6) == 0) {
1.96 ! ozaki-r 504: nd6log(LOG_DEBUG,
1.34 itojun 505: "%s: interface identifier generated by random number\n",
1.96 ! ozaki-r 506: if_name(ifp0));
1.25 itojun 507: goto success;
508: }
1.13 itojun 509:
1.31 itojun 510: printf("%s: failed to get interface identifier\n", if_name(ifp0));
1.25 itojun 511: return -1;
1.13 itojun 512:
1.25 itojun 513: success:
1.96 ! ozaki-r 514: nd6log(LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
1.47 itojun 515: if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
516: in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
1.96 ! ozaki-r 517: in6->s6_addr[14], in6->s6_addr[15]);
1.13 itojun 518: return 0;
519: }
520:
1.71 christos 521: /*
522: * altifp - secondary EUI64 source
523: */
524:
1.25 itojun 525: static int
1.71 christos 526: in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
1.48 itojun 527: {
1.89 martin 528: struct in6_ifaddr *ia __diagused;
1.48 itojun 529: struct in6_aliasreq ifra;
1.92 matt 530: struct nd_prefixctl prc0;
1.48 itojun 531: int i, error;
1.25 itojun 532:
533: /*
1.48 itojun 534: * configure link-local address.
1.25 itojun 535: */
1.64 rpaulo 536: memset(&ifra, 0, sizeof(ifra));
1.2 itojun 537:
1.25 itojun 538: /*
1.48 itojun 539: * in6_update_ifa() does not use ifra_name, but we accurately set it
540: * for safety.
1.25 itojun 541: */
1.48 itojun 542: strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
1.2 itojun 543:
1.48 itojun 544: ifra.ifra_addr.sin6_family = AF_INET6;
545: ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
1.63 rpaulo 546: ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
1.48 itojun 547: ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
548: if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
549: ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
550: ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
551: } else {
552: if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
1.96 ! ozaki-r 553: nd6log(LOG_ERR,
! 554: "%s: no ifid available\n", if_name(ifp));
1.69 dyoung 555: return -1;
1.25 itojun 556: }
557: }
1.63 rpaulo 558: if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
1.69 dyoung 559: return -1;
1.25 itojun 560:
1.75 dyoung 561: sockaddr_in6_init(&ifra.ifra_prefixmask, &in6mask64, 0, 0, 0);
1.48 itojun 562: /* link-local addresses should NEVER expire. */
563: ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
564: ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1.25 itojun 565:
1.48 itojun 566: /*
567: * Now call in6_update_ifa() to do a bunch of procedures to configure
1.70 dyoung 568: * a link-local address. We can set the 3rd argument to NULL, because
1.48 itojun 569: * we know there's no other link-local address on the interface
570: * and therefore we are adding one (instead of updating one).
571: */
1.64 rpaulo 572: if ((error = in6_update_ifa(ifp, &ifra, NULL,
573: IN6_IFAUPDATE_DADDELAY)) != 0) {
1.25 itojun 574: /*
1.48 itojun 575: * XXX: When the interface does not support IPv6, this call
1.82 dyoung 576: * would fail in the SIOCINITIFADDR ioctl. I believe the
1.48 itojun 577: * notification is rather confusing in this case, so just
578: * suppress it. (jinmei@kame.net 20010130)
1.25 itojun 579: */
1.48 itojun 580: if (error != EAFNOSUPPORT)
1.96 ! ozaki-r 581: nd6log(LOG_NOTICE,
! 582: "failed to configure a link-local address on %s "
1.48 itojun 583: "(errno=%d)\n",
1.96 ! ozaki-r 584: if_name(ifp), error);
1.69 dyoung 585: return -1;
1.25 itojun 586: }
587:
1.48 itojun 588: ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
1.88 mrg 589: KASSERTMSG(ia, "ia == NULL in in6_ifattach_linklocal");
1.25 itojun 590:
1.48 itojun 591: /*
592: * Make the link-local prefix (fe80::/64%link) as on-link.
593: * Since we'd like to manage prefixes separately from addresses,
594: * we make an ND6 prefix structure for the link-local prefix,
595: * and add it to the prefix list as a never-expire prefix.
596: * XXX: this change might affect some existing code base...
597: */
1.92 matt 598: memset(&prc0, 0, sizeof(prc0));
599: prc0.ndprc_ifp = ifp;
1.48 itojun 600: /* this should be 64 at this moment. */
1.92 matt 601: prc0.ndprc_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
602: prc0.ndprc_prefix = ifra.ifra_addr;
1.48 itojun 603: /* apply the mask for safety. (nd6_prelist_add will apply it again) */
604: for (i = 0; i < 4; i++) {
1.92 matt 605: prc0.ndprc_prefix.sin6_addr.s6_addr32[i] &=
1.48 itojun 606: in6mask64.s6_addr32[i];
607: }
608: /*
609: * Initialize parameters. The link-local prefix must always be
610: * on-link, and its lifetimes never expire.
611: */
1.92 matt 612: prc0.ndprc_raf_onlink = 1;
613: prc0.ndprc_raf_auto = 1; /* probably meaningless */
614: prc0.ndprc_vltime = ND6_INFINITE_LIFETIME;
615: prc0.ndprc_pltime = ND6_INFINITE_LIFETIME;
1.48 itojun 616: /*
617: * Since there is no other link-local addresses, nd6_prefix_lookup()
618: * probably returns NULL. However, we cannot always expect the result.
619: * For example, if we first remove the (only) existing link-local
620: * address, and then reconfigure another one, the prefix is still
621: * valid with referring to the old link-local address.
622: */
1.92 matt 623: if (nd6_prefix_lookup(&prc0) == NULL) {
624: if ((error = nd6_prelist_add(&prc0, NULL, NULL)) != 0)
1.69 dyoung 625: return error;
1.25 itojun 626: }
627:
628: return 0;
629: }
630:
1.71 christos 631: /*
632: * ifp - mut be IFT_LOOP
633: */
634:
1.25 itojun 635: static int
1.71 christos 636: in6_ifattach_loopback(struct ifnet *ifp)
1.25 itojun 637: {
1.48 itojun 638: struct in6_aliasreq ifra;
639: int error;
640:
1.64 rpaulo 641: memset(&ifra, 0, sizeof(ifra));
1.25 itojun 642:
643: /*
1.48 itojun 644: * in6_update_ifa() does not use ifra_name, but we accurately set it
645: * for safety.
1.25 itojun 646: */
1.48 itojun 647: strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
648:
1.75 dyoung 649: sockaddr_in6_init(&ifra.ifra_prefixmask, &in6mask128, 0, 0, 0);
1.25 itojun 650:
651: /*
652: * Always initialize ia_dstaddr (= broadcast address) to loopback
1.48 itojun 653: * address. Follows IPv4 practice - see in_ifinit().
654: */
1.75 dyoung 655: sockaddr_in6_init(&ifra.ifra_dstaddr, &in6addr_loopback, 0, 0, 0);
1.48 itojun 656:
1.75 dyoung 657: sockaddr_in6_init(&ifra.ifra_addr, &in6addr_loopback, 0, 0, 0);
1.48 itojun 658:
659: /* the loopback address should NEVER expire. */
660: ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
661: ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
662:
663: /* we don't need to perform DAD on loopback interfaces. */
664: ifra.ifra_flags |= IN6_IFF_NODAD;
665:
666: /*
667: * We are sure that this is a newly assigned address, so we can set
668: * NULL to the 3rd arg.
669: */
1.64 rpaulo 670: if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
1.96 ! ozaki-r 671: nd6log(LOG_ERR, "failed to configure "
1.48 itojun 672: "the loopback address on %s (errno=%d)\n",
1.96 ! ozaki-r 673: if_name(ifp), error);
1.69 dyoung 674: return -1;
1.48 itojun 675: }
1.25 itojun 676:
1.48 itojun 677: return 0;
678: }
679:
680: /*
681: * compute NI group address, based on the current hostname setting.
682: * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
683: *
684: * when ifp == NULL, the caller is responsible for filling scopeid.
685: */
686: int
1.71 christos 687: in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
688: struct sockaddr_in6 *sa6)
1.48 itojun 689: {
690: const char *p;
1.52 itojun 691: u_int8_t *q;
1.48 itojun 692: MD5_CTX ctxt;
693: u_int8_t digest[16];
1.50 itojun 694: u_int8_t l;
695: u_int8_t n[64]; /* a single label must not exceed 63 chars */
1.25 itojun 696:
1.48 itojun 697: if (!namelen || !name)
1.25 itojun 698: return -1;
1.48 itojun 699:
700: p = name;
701: while (p && *p && *p != '.' && p - name < namelen)
702: p++;
703: if (p - name > sizeof(n) - 1)
704: return -1; /* label too long */
705: l = p - name;
1.50 itojun 706: strncpy((char *)n, name, l);
1.48 itojun 707: n[(int)l] = '\0';
708: for (q = n; *q; q++) {
709: if ('A' <= *q && *q <= 'Z')
710: *q = *q - 'A' + 'a';
1.2 itojun 711: }
1.25 itojun 712:
1.48 itojun 713: /* generate 8 bytes of pseudo-random value. */
1.64 rpaulo 714: memset(&ctxt, 0, sizeof(ctxt));
1.48 itojun 715: MD5Init(&ctxt);
716: MD5Update(&ctxt, &l, sizeof(l));
717: MD5Update(&ctxt, n, l);
718: MD5Final(digest, &ctxt);
719:
1.64 rpaulo 720: memset(sa6, 0, sizeof(*sa6));
1.48 itojun 721: sa6->sin6_family = AF_INET6;
722: sa6->sin6_len = sizeof(*sa6);
723: sa6->sin6_addr.s6_addr16[0] = htons(0xff02);
724: sa6->sin6_addr.s6_addr8[11] = 2;
1.64 rpaulo 725: memcpy(&sa6->sin6_addr.s6_addr32[3], digest,
1.48 itojun 726: sizeof(sa6->sin6_addr.s6_addr32[3]));
1.63 rpaulo 727: if (in6_setscope(&sa6->sin6_addr, ifp, NULL))
1.69 dyoung 728: return -1; /* XXX: should not fail */
1.48 itojun 729:
1.25 itojun 730: return 0;
1.2 itojun 731: }
732:
1.17 itojun 733: /*
734: * XXX multiple loopback interface needs more care. for instance,
735: * nodelocal address needs to be configured onto only one of them.
1.25 itojun 736: * XXX multiple link-local address case
1.71 christos 737: *
738: * altifp - secondary EUI64 source
1.17 itojun 739: */
1.2 itojun 740: void
1.71 christos 741: in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
1.2 itojun 742: {
1.85 christos 743: struct in6_ifaddr *ia;
744: struct in6_addr in6;
1.13 itojun 745:
1.38 itojun 746: /* some of the interfaces are inherently not IPv6 capable */
747: switch (ifp->if_type) {
1.42 itojun 748: case IFT_BRIDGE:
1.59 christos 749: #ifdef IFT_PFLOG
1.58 itojun 750: case IFT_PFLOG:
1.59 christos 751: #endif
752: #ifdef IFT_PFSYNC
1.58 itojun 753: case IFT_PFSYNC:
1.59 christos 754: #endif
1.91 roy 755: ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
756: ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1.42 itojun 757: return;
1.38 itojun 758: }
759:
1.46 itojun 760: /*
761: * if link mtu is too small, don't try to configure IPv6.
762: * remember there could be some link-layer that has special
763: * fragmentation logic.
764: */
1.49 itojun 765: if (ifp->if_mtu < IPV6_MMTU) {
1.96 ! ozaki-r 766: nd6log(LOG_INFO, "%s has too small MTU, IPv6 not enabled\n",
! 767: if_name(ifp));
1.46 itojun 768: return;
1.49 itojun 769: }
1.46 itojun 770:
1.37 itojun 771: /* create a multicast kludge storage (if we have not had one) */
772: in6_createmkludge(ifp);
1.2 itojun 773:
774: /*
1.25 itojun 775: * quirks based on interface type
1.2 itojun 776: */
1.25 itojun 777: switch (ifp->if_type) {
778: #ifdef IFT_STF
779: case IFT_STF:
780: /*
1.38 itojun 781: * 6to4 interface is a very special kind of beast.
782: * no multicast, no linklocal. RFC2529 specifies how to make
783: * linklocals for 6to4 interface, but there's no use and
784: * it is rather harmful to have one.
1.25 itojun 785: */
1.91 roy 786: ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
1.46 itojun 787: return;
1.25 itojun 788: #endif
1.65 liamjfoy 789: case IFT_CARP:
790: return;
1.25 itojun 791: default:
792: break;
1.7 itojun 793: }
1.2 itojun 794:
795: /*
1.25 itojun 796: * usually, we require multicast capability to the interface
1.2 itojun 797: */
1.25 itojun 798: if ((ifp->if_flags & IFF_MULTICAST) == 0) {
1.96 ! ozaki-r 799: nd6log(LOG_INFO,
1.38 itojun 800: "%s is not multicast capable, IPv6 not enabled\n",
1.96 ! ozaki-r 801: if_name(ifp));
1.25 itojun 802: return;
803: }
1.15 thorpej 804:
1.2 itojun 805: /*
1.48 itojun 806: * assign loopback address for loopback interface.
807: * XXX multiple loopback interface case.
1.2 itojun 808: */
1.48 itojun 809: if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
810: in6 = in6addr_loopback;
1.25 itojun 811: if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
812: if (in6_ifattach_loopback(ifp) != 0)
813: return;
814: }
815: }
1.2 itojun 816:
817: /*
1.48 itojun 818: * assign a link-local address, if there's none.
1.2 itojun 819: */
1.91 roy 820: if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
821: ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)
822: {
1.48 itojun 823: ia = in6ifa_ifpforlinklocal(ifp, 0);
1.70 dyoung 824: if (ia == NULL && in6_ifattach_linklocal(ifp, altifp) != 0) {
825: printf("%s: cannot assign link-local address\n",
826: ifp->if_xname);
1.2 itojun 827: }
828: }
829: }
830:
1.17 itojun 831: /*
832: * NOTE: in6_ifdetach() does not support loopback if at this moment.
1.41 itojun 833: * We don't need this function in bsdi, because interfaces are never removed
834: * from the ifnet list in bsdi.
1.17 itojun 835: */
1.2 itojun 836: void
1.71 christos 837: in6_ifdetach(struct ifnet *ifp)
1.2 itojun 838: {
839: struct in6_ifaddr *ia, *oia;
1.30 itojun 840: struct ifaddr *ifa, *next;
1.2 itojun 841: struct rtentry *rt;
842: short rtflags;
1.48 itojun 843: struct in6_multi_mship *imm;
1.55 itojun 844:
845: /* remove ip6_mrouter stuff */
846: ip6_mrouter_detach(ifp);
1.18 itojun 847:
848: /* remove neighbor management table */
1.95 martin 849: nd6_purge(ifp, NULL);
1.18 itojun 850:
1.76 dyoung 851: /* XXX this code is duplicated in in6_purgeif() --dyoung */
1.30 itojun 852: /* nuke any of IPv6 addresses we have */
1.78 dyoung 853: if_purgeaddrs(ifp, AF_INET6, in6_purgeaddr);
1.30 itojun 854:
1.76 dyoung 855: /* XXX isn't this code is redundant, given the above? --dyoung */
856: /* XXX doesn't this code replicate code in in6_purgeaddr() ? --dyoung */
1.30 itojun 857: /* undo everything done by in6_ifattach(), just in case */
1.77 dyoung 858: for (ifa = IFADDR_FIRST(ifp); ifa != NULL; ifa = next) {
859: next = IFADDR_NEXT(ifa);
1.30 itojun 860:
1.2 itojun 861: if (ifa->ifa_addr->sa_family != AF_INET6
862: || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
863: continue;
864: }
865:
866: ia = (struct in6_ifaddr *)ifa;
867:
1.48 itojun 868: /*
869: * leave from multicast groups we have joined for the interface
870: */
1.68 dyoung 871: while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
1.48 itojun 872: LIST_REMOVE(imm, i6mm_chain);
873: in6_leavegroup(imm);
874: }
875:
1.2 itojun 876: /* remove from the routing table */
1.48 itojun 877: if ((ia->ia_flags & IFA_ROUTE) &&
878: (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
1.2 itojun 879: rtflags = rt->rt_flags;
880: rtfree(rt);
1.47 itojun 881: rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
882: (struct sockaddr *)&ia->ia_addr,
883: (struct sockaddr *)&ia->ia_prefixmask,
1.87 christos 884: rtflags, NULL);
1.2 itojun 885: }
886:
887: /* remove from the linked list */
1.79 dyoung 888: ifa_remove(ifp, &ia->ia_ifa);
1.2 itojun 889:
890: /* also remove from the IPv6 address chain(itojun&jinmei) */
891: oia = ia;
892: if (oia == (ia = in6_ifaddr))
893: in6_ifaddr = ia->ia_next;
894: else {
895: while (ia->ia_next && (ia->ia_next != oia))
896: ia = ia->ia_next;
897: if (ia->ia_next)
898: ia->ia_next = oia->ia_next;
1.34 itojun 899: else {
1.96 ! ozaki-r 900: nd6log(LOG_ERR,
1.47 itojun 901: "%s: didn't unlink in6ifaddr from list\n",
1.96 ! ozaki-r 902: if_name(ifp));
1.34 itojun 903: }
1.2 itojun 904: }
905:
1.93 rmind 906: ifafree(&oia->ia_ifa);
1.16 itojun 907: }
908:
1.17 itojun 909: /* cleanup multicast address kludge table, if there is any */
910: in6_purgemkludge(ifp);
1.30 itojun 911:
1.41 itojun 912: /*
913: * remove neighbor management table. we call it twice just to make
914: * sure we nuke everything. maybe we need just one call.
915: * XXX: since the first call did not release addresses, some prefixes
916: * might remain. We should call nd6_purge() again to release the
917: * prefixes after removing all addresses above.
918: * (Or can we just delay calling nd6_purge until at this point?)
919: */
1.95 martin 920: nd6_purge(ifp, NULL);
1.2 itojun 921: }
1.64 rpaulo 922:
923: int
1.71 christos 924: in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
925: const u_int8_t *baseid, int generate)
1.64 rpaulo 926: {
927: u_int8_t nullbuf[8];
928: struct nd_ifinfo *ndi = ND_IFINFO(ifp);
929:
930: memset(nullbuf, 0, sizeof(nullbuf));
931: if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
932: /* we've never created a random ID. Create a new one. */
933: generate = 1;
934: }
935:
936: if (generate) {
937: memcpy(ndi->randomseed1, baseid, sizeof(ndi->randomseed1));
938:
939: /* generate_tmp_ifid will update seedn and buf */
940: (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
941: ndi->randomid);
942: }
943: memcpy(retbuf, ndi->randomid, 8);
944: if (generate && memcmp(retbuf, nullbuf, sizeof(nullbuf)) == 0) {
945: /* generate_tmp_ifid could not found a good ID. */
1.69 dyoung 946: return -1;
1.64 rpaulo 947: }
948:
1.69 dyoung 949: return 0;
1.64 rpaulo 950: }
951:
952: void
1.67 christos 953: in6_tmpaddrtimer(void *ignored_arg)
1.64 rpaulo 954: {
955: struct nd_ifinfo *ndi;
956: u_int8_t nullbuf[8];
957: struct ifnet *ifp;
1.80 ad 958:
959: mutex_enter(softnet_lock);
960: KERNEL_LOCK(1, NULL);
1.64 rpaulo 961:
962: callout_reset(&in6_tmpaddrtimer_ch,
963: (ip6_temp_preferred_lifetime - ip6_desync_factor -
964: ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
965:
966: memset(nullbuf, 0, sizeof(nullbuf));
1.90 rmind 967: IFNET_FOREACH(ifp) {
1.64 rpaulo 968: ndi = ND_IFINFO(ifp);
969: if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
970: /*
971: * We've been generating a random ID on this interface.
972: * Create a new one.
973: */
974: (void)generate_tmp_ifid(ndi->randomseed0,
975: ndi->randomseed1, ndi->randomid);
976: }
977: }
978:
1.80 ad 979: KERNEL_UNLOCK_ONE(NULL);
980: mutex_exit(softnet_lock);
1.64 rpaulo 981: }
CVSweb <webmaster@jp.NetBSD.org>