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