Deleted Added
full compact
in6_ifattach.c (95023) in6_ifattach.c (108172)
1/* $FreeBSD: head/sys/netinet6/in6_ifattach.c 95023 2002-04-19 04:46:24Z suz $ */
1/* $FreeBSD: head/sys/netinet6/in6_ifattach.c 108172 2002-12-22 05:35:03Z hsu $ */
2/* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
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.
19 *
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 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/socket.h>
37#include <sys/sockio.h>
38#include <sys/kernel.h>
39#include <sys/syslog.h>
40#include <sys/md5.h>
41
42#include <net/if.h>
43#include <net/if_dl.h>
44#include <net/if_types.h>
45#include <net/route.h>
46
47#include <netinet/in.h>
48#include <netinet/in_var.h>
49#include <netinet/if_ether.h>
50#include <netinet/in_pcb.h>
51
52#include <netinet/ip6.h>
53#include <netinet6/ip6_var.h>
54#include <netinet6/in6_var.h>
55#include <netinet6/in6_pcb.h>
56#include <netinet6/in6_ifattach.h>
57#include <netinet6/ip6_var.h>
58#include <netinet6/nd6.h>
59#include <netinet6/scope6_var.h>
60
61#include <net/net_osdep.h>
62
63struct in6_ifstat **in6_ifstat = NULL;
64struct icmp6_ifstat **icmp6_ifstat = NULL;
65size_t in6_ifstatmax = 0;
66size_t icmp6_ifstatmax = 0;
67unsigned long in6_maxmtu = 0;
68
69#ifdef IP6_AUTO_LINKLOCAL
70int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
71#else
72int ip6_auto_linklocal = 1; /* enable by default */
73#endif
74
75struct callout in6_tmpaddrtimer_ch;
76
77extern struct inpcbinfo udbinfo;
78extern struct inpcbinfo ripcbinfo;
79
80static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
81static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
82static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
83static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
84static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
85static int in6_ifattach_loopback __P((struct ifnet *));
86
87#define EUI64_GBIT 0x01
88#define EUI64_UBIT 0x02
89#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
90#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
91#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
92#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
93#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
94
95#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
96#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
97
98/*
99 * Generate a last-resort interface identifier, when the machine has no
100 * IEEE802/EUI64 address sources.
101 * The goal here is to get an interface identifier that is
102 * (1) random enough and (2) does not change across reboot.
103 * We currently use MD5(hostname) for it.
104 */
105static int
106get_rand_ifid(ifp, in6)
107 struct ifnet *ifp;
108 struct in6_addr *in6; /* upper 64bits are preserved */
109{
110 MD5_CTX ctxt;
111 u_int8_t digest[16];
112 int hostnamelen = strlen(hostname);
113
114#if 0
115 /* we need at least several letters as seed for ifid */
116 if (hostnamelen < 3)
117 return -1;
118#endif
119
120 /* generate 8 bytes of pseudo-random value. */
121 bzero(&ctxt, sizeof(ctxt));
122 MD5Init(&ctxt);
123 MD5Update(&ctxt, hostname, hostnamelen);
124 MD5Final(digest, &ctxt);
125
126 /* assumes sizeof(digest) > sizeof(ifid) */
127 bcopy(digest, &in6->s6_addr[8], 8);
128
129 /* make sure to set "u" bit to local, and "g" bit to individual. */
130 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
131 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
132
133 /* convert EUI64 into IPv6 interface identifier */
134 EUI64_TO_IFID(in6);
135
136 return 0;
137}
138
139static int
140generate_tmp_ifid(seed0, seed1, ret)
141 u_int8_t *seed0, *ret;
142 const u_int8_t *seed1;
143{
144 MD5_CTX ctxt;
145 u_int8_t seed[16], digest[16], nullbuf[8];
146 u_int32_t val32;
147 struct timeval tv;
148
149 /* If there's no hisotry, start with a random seed. */
150 bzero(nullbuf, sizeof(nullbuf));
151 if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
152 int i;
153
154 for (i = 0; i < 2; i++) {
155 microtime(&tv);
156 val32 = random() ^ tv.tv_usec;
157 bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
158 }
159 } else {
160 bcopy(seed0, seed, 8);
161 }
162
163 /* copy the right-most 64-bits of the given address */
164 /* XXX assumption on the size of IFID */
165 bcopy(seed1, &seed[8], 8);
166
167 if (0) { /* for debugging purposes only */
168 int i;
169
170 printf("generate_tmp_ifid: new randomized ID from: ");
171 for (i = 0; i < 16; i++)
172 printf("%02x", seed[i]);
173 printf(" ");
174 }
175
176 /* generate 16 bytes of pseudo-random value. */
177 bzero(&ctxt, sizeof(ctxt));
178 MD5Init(&ctxt);
179 MD5Update(&ctxt, seed, sizeof(seed));
180 MD5Final(digest, &ctxt);
181
182 /*
183 * RFC 3041 3.2.1. (3)
184 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
185 * left-most bit is numbered 0) to zero.
186 */
187 bcopy(digest, ret, 8);
188 ret[0] &= ~EUI64_UBIT;
189
190 /*
191 * XXX: we'd like to ensure that the generated value is not zero
192 * for simplicity. If the caclculated digest happens to be zero,
193 * use a random non-zero value as the last resort.
194 */
195 if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
196 log(LOG_INFO,
197 "generate_tmp_ifid: computed MD5 value is zero.\n");
198
199 microtime(&tv);
200 val32 = random() ^ tv.tv_usec;
201 val32 = 1 + (val32 % (0xffffffff - 1));
202 }
203
204 /*
205 * RFC 3041 3.2.1. (4)
206 * Take the rightmost 64-bits of the MD5 digest and save them in
207 * stable storage as the history value to be used in the next
208 * iteration of the algorithm.
209 */
210 bcopy(&digest[8], seed0, 8);
211
212 if (0) { /* for debugging purposes only */
213 int i;
214
215 printf("to: ");
216 for (i = 0; i < 16; i++)
217 printf("%02x", digest[i]);
218 printf("\n");
219 }
220
221 return 0;
222}
223
224/*
225 * Get interface identifier for the specified interface.
226 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
227 */
228static int
229get_hw_ifid(ifp, in6)
230 struct ifnet *ifp;
231 struct in6_addr *in6; /* upper 64bits are preserved */
232{
233 struct ifaddr *ifa;
234 struct sockaddr_dl *sdl;
235 u_int8_t *addr;
236 size_t addrlen;
237 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
238 static u_int8_t allone[8] =
239 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
240
241 for (ifa = ifp->if_addrlist.tqh_first;
242 ifa;
243 ifa = ifa->ifa_list.tqe_next)
244 {
245 if (ifa->ifa_addr->sa_family != AF_LINK)
246 continue;
247 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
248 if (sdl == NULL)
249 continue;
250 if (sdl->sdl_alen == 0)
251 continue;
252
253 goto found;
254 }
255
256 return -1;
257
258found:
259 addr = LLADDR(sdl);
260 addrlen = sdl->sdl_alen;
261
262 /* get EUI64 */
263 switch (ifp->if_type) {
264 case IFT_ETHER:
265 case IFT_FDDI:
266 case IFT_ATM:
267 case IFT_IEEE1394:
268#ifdef IFT_IEEE80211
269 case IFT_IEEE80211:
270#endif
271 /* IEEE802/EUI64 cases - what others? */
272 /* IEEE1394 uses 16byte length address starting with EUI64 */
273 if (addrlen > 8)
274 addrlen = 8;
275
276 /* look at IEEE802/EUI64 only */
277 if (addrlen != 8 && addrlen != 6)
278 return -1;
279
280 /*
281 * check for invalid MAC address - on bsdi, we see it a lot
282 * since wildboar configures all-zero MAC on pccard before
283 * card insertion.
284 */
285 if (bcmp(addr, allzero, addrlen) == 0)
286 return -1;
287 if (bcmp(addr, allone, addrlen) == 0)
288 return -1;
289
290 /* make EUI64 address */
291 if (addrlen == 8)
292 bcopy(addr, &in6->s6_addr[8], 8);
293 else if (addrlen == 6) {
294 in6->s6_addr[8] = addr[0];
295 in6->s6_addr[9] = addr[1];
296 in6->s6_addr[10] = addr[2];
297 in6->s6_addr[11] = 0xff;
298 in6->s6_addr[12] = 0xfe;
299 in6->s6_addr[13] = addr[3];
300 in6->s6_addr[14] = addr[4];
301 in6->s6_addr[15] = addr[5];
302 }
303 break;
304
305 case IFT_ARCNET:
306 if (addrlen != 1)
307 return -1;
308 if (!addr[0])
309 return -1;
310
311 bzero(&in6->s6_addr[8], 8);
312 in6->s6_addr[15] = addr[0];
313
314 /*
315 * due to insufficient bitwidth, we mark it local.
316 */
317 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
318 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
319 break;
320
321 case IFT_GIF:
322#ifdef IFT_STF
323 case IFT_STF:
324#endif
325 /*
326 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
327 * however, IPv4 address is not very suitable as unique
328 * identifier source (can be renumbered).
329 * we don't do this.
330 */
331 return -1;
332
333 default:
334 return -1;
335 }
336
337 /* sanity check: g bit must not indicate "group" */
338 if (EUI64_GROUP(in6))
339 return -1;
340
341 /* convert EUI64 into IPv6 interface identifier */
342 EUI64_TO_IFID(in6);
343
344 /*
345 * sanity check: ifid must not be all zero, avoid conflict with
346 * subnet router anycast
347 */
348 if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
349 bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
350 return -1;
351 }
352
353 return 0;
354}
355
356/*
357 * Get interface identifier for the specified interface. If it is not
358 * available on ifp0, borrow interface identifier from other information
359 * sources.
360 */
361static int
362get_ifid(ifp0, altifp, in6)
363 struct ifnet *ifp0;
364 struct ifnet *altifp; /* secondary EUI64 source */
365 struct in6_addr *in6;
366{
367 struct ifnet *ifp;
368
369 /* first, try to get it from the interface itself */
370 if (get_hw_ifid(ifp0, in6) == 0) {
371 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
372 if_name(ifp0)));
373 goto success;
374 }
375
376 /* try secondary EUI64 source. this basically is for ATM PVC */
377 if (altifp && get_hw_ifid(altifp, in6) == 0) {
378 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
379 if_name(ifp0), if_name(altifp)));
380 goto success;
381 }
382
383 /* next, try to get it from some other hardware interface */
2/* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
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.
19 *
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 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/socket.h>
37#include <sys/sockio.h>
38#include <sys/kernel.h>
39#include <sys/syslog.h>
40#include <sys/md5.h>
41
42#include <net/if.h>
43#include <net/if_dl.h>
44#include <net/if_types.h>
45#include <net/route.h>
46
47#include <netinet/in.h>
48#include <netinet/in_var.h>
49#include <netinet/if_ether.h>
50#include <netinet/in_pcb.h>
51
52#include <netinet/ip6.h>
53#include <netinet6/ip6_var.h>
54#include <netinet6/in6_var.h>
55#include <netinet6/in6_pcb.h>
56#include <netinet6/in6_ifattach.h>
57#include <netinet6/ip6_var.h>
58#include <netinet6/nd6.h>
59#include <netinet6/scope6_var.h>
60
61#include <net/net_osdep.h>
62
63struct in6_ifstat **in6_ifstat = NULL;
64struct icmp6_ifstat **icmp6_ifstat = NULL;
65size_t in6_ifstatmax = 0;
66size_t icmp6_ifstatmax = 0;
67unsigned long in6_maxmtu = 0;
68
69#ifdef IP6_AUTO_LINKLOCAL
70int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
71#else
72int ip6_auto_linklocal = 1; /* enable by default */
73#endif
74
75struct callout in6_tmpaddrtimer_ch;
76
77extern struct inpcbinfo udbinfo;
78extern struct inpcbinfo ripcbinfo;
79
80static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
81static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
82static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
83static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
84static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
85static int in6_ifattach_loopback __P((struct ifnet *));
86
87#define EUI64_GBIT 0x01
88#define EUI64_UBIT 0x02
89#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
90#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
91#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
92#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
93#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
94
95#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
96#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
97
98/*
99 * Generate a last-resort interface identifier, when the machine has no
100 * IEEE802/EUI64 address sources.
101 * The goal here is to get an interface identifier that is
102 * (1) random enough and (2) does not change across reboot.
103 * We currently use MD5(hostname) for it.
104 */
105static int
106get_rand_ifid(ifp, in6)
107 struct ifnet *ifp;
108 struct in6_addr *in6; /* upper 64bits are preserved */
109{
110 MD5_CTX ctxt;
111 u_int8_t digest[16];
112 int hostnamelen = strlen(hostname);
113
114#if 0
115 /* we need at least several letters as seed for ifid */
116 if (hostnamelen < 3)
117 return -1;
118#endif
119
120 /* generate 8 bytes of pseudo-random value. */
121 bzero(&ctxt, sizeof(ctxt));
122 MD5Init(&ctxt);
123 MD5Update(&ctxt, hostname, hostnamelen);
124 MD5Final(digest, &ctxt);
125
126 /* assumes sizeof(digest) > sizeof(ifid) */
127 bcopy(digest, &in6->s6_addr[8], 8);
128
129 /* make sure to set "u" bit to local, and "g" bit to individual. */
130 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
131 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
132
133 /* convert EUI64 into IPv6 interface identifier */
134 EUI64_TO_IFID(in6);
135
136 return 0;
137}
138
139static int
140generate_tmp_ifid(seed0, seed1, ret)
141 u_int8_t *seed0, *ret;
142 const u_int8_t *seed1;
143{
144 MD5_CTX ctxt;
145 u_int8_t seed[16], digest[16], nullbuf[8];
146 u_int32_t val32;
147 struct timeval tv;
148
149 /* If there's no hisotry, start with a random seed. */
150 bzero(nullbuf, sizeof(nullbuf));
151 if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
152 int i;
153
154 for (i = 0; i < 2; i++) {
155 microtime(&tv);
156 val32 = random() ^ tv.tv_usec;
157 bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
158 }
159 } else {
160 bcopy(seed0, seed, 8);
161 }
162
163 /* copy the right-most 64-bits of the given address */
164 /* XXX assumption on the size of IFID */
165 bcopy(seed1, &seed[8], 8);
166
167 if (0) { /* for debugging purposes only */
168 int i;
169
170 printf("generate_tmp_ifid: new randomized ID from: ");
171 for (i = 0; i < 16; i++)
172 printf("%02x", seed[i]);
173 printf(" ");
174 }
175
176 /* generate 16 bytes of pseudo-random value. */
177 bzero(&ctxt, sizeof(ctxt));
178 MD5Init(&ctxt);
179 MD5Update(&ctxt, seed, sizeof(seed));
180 MD5Final(digest, &ctxt);
181
182 /*
183 * RFC 3041 3.2.1. (3)
184 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
185 * left-most bit is numbered 0) to zero.
186 */
187 bcopy(digest, ret, 8);
188 ret[0] &= ~EUI64_UBIT;
189
190 /*
191 * XXX: we'd like to ensure that the generated value is not zero
192 * for simplicity. If the caclculated digest happens to be zero,
193 * use a random non-zero value as the last resort.
194 */
195 if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
196 log(LOG_INFO,
197 "generate_tmp_ifid: computed MD5 value is zero.\n");
198
199 microtime(&tv);
200 val32 = random() ^ tv.tv_usec;
201 val32 = 1 + (val32 % (0xffffffff - 1));
202 }
203
204 /*
205 * RFC 3041 3.2.1. (4)
206 * Take the rightmost 64-bits of the MD5 digest and save them in
207 * stable storage as the history value to be used in the next
208 * iteration of the algorithm.
209 */
210 bcopy(&digest[8], seed0, 8);
211
212 if (0) { /* for debugging purposes only */
213 int i;
214
215 printf("to: ");
216 for (i = 0; i < 16; i++)
217 printf("%02x", digest[i]);
218 printf("\n");
219 }
220
221 return 0;
222}
223
224/*
225 * Get interface identifier for the specified interface.
226 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
227 */
228static int
229get_hw_ifid(ifp, in6)
230 struct ifnet *ifp;
231 struct in6_addr *in6; /* upper 64bits are preserved */
232{
233 struct ifaddr *ifa;
234 struct sockaddr_dl *sdl;
235 u_int8_t *addr;
236 size_t addrlen;
237 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
238 static u_int8_t allone[8] =
239 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
240
241 for (ifa = ifp->if_addrlist.tqh_first;
242 ifa;
243 ifa = ifa->ifa_list.tqe_next)
244 {
245 if (ifa->ifa_addr->sa_family != AF_LINK)
246 continue;
247 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
248 if (sdl == NULL)
249 continue;
250 if (sdl->sdl_alen == 0)
251 continue;
252
253 goto found;
254 }
255
256 return -1;
257
258found:
259 addr = LLADDR(sdl);
260 addrlen = sdl->sdl_alen;
261
262 /* get EUI64 */
263 switch (ifp->if_type) {
264 case IFT_ETHER:
265 case IFT_FDDI:
266 case IFT_ATM:
267 case IFT_IEEE1394:
268#ifdef IFT_IEEE80211
269 case IFT_IEEE80211:
270#endif
271 /* IEEE802/EUI64 cases - what others? */
272 /* IEEE1394 uses 16byte length address starting with EUI64 */
273 if (addrlen > 8)
274 addrlen = 8;
275
276 /* look at IEEE802/EUI64 only */
277 if (addrlen != 8 && addrlen != 6)
278 return -1;
279
280 /*
281 * check for invalid MAC address - on bsdi, we see it a lot
282 * since wildboar configures all-zero MAC on pccard before
283 * card insertion.
284 */
285 if (bcmp(addr, allzero, addrlen) == 0)
286 return -1;
287 if (bcmp(addr, allone, addrlen) == 0)
288 return -1;
289
290 /* make EUI64 address */
291 if (addrlen == 8)
292 bcopy(addr, &in6->s6_addr[8], 8);
293 else if (addrlen == 6) {
294 in6->s6_addr[8] = addr[0];
295 in6->s6_addr[9] = addr[1];
296 in6->s6_addr[10] = addr[2];
297 in6->s6_addr[11] = 0xff;
298 in6->s6_addr[12] = 0xfe;
299 in6->s6_addr[13] = addr[3];
300 in6->s6_addr[14] = addr[4];
301 in6->s6_addr[15] = addr[5];
302 }
303 break;
304
305 case IFT_ARCNET:
306 if (addrlen != 1)
307 return -1;
308 if (!addr[0])
309 return -1;
310
311 bzero(&in6->s6_addr[8], 8);
312 in6->s6_addr[15] = addr[0];
313
314 /*
315 * due to insufficient bitwidth, we mark it local.
316 */
317 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
318 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
319 break;
320
321 case IFT_GIF:
322#ifdef IFT_STF
323 case IFT_STF:
324#endif
325 /*
326 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
327 * however, IPv4 address is not very suitable as unique
328 * identifier source (can be renumbered).
329 * we don't do this.
330 */
331 return -1;
332
333 default:
334 return -1;
335 }
336
337 /* sanity check: g bit must not indicate "group" */
338 if (EUI64_GROUP(in6))
339 return -1;
340
341 /* convert EUI64 into IPv6 interface identifier */
342 EUI64_TO_IFID(in6);
343
344 /*
345 * sanity check: ifid must not be all zero, avoid conflict with
346 * subnet router anycast
347 */
348 if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
349 bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
350 return -1;
351 }
352
353 return 0;
354}
355
356/*
357 * Get interface identifier for the specified interface. If it is not
358 * available on ifp0, borrow interface identifier from other information
359 * sources.
360 */
361static int
362get_ifid(ifp0, altifp, in6)
363 struct ifnet *ifp0;
364 struct ifnet *altifp; /* secondary EUI64 source */
365 struct in6_addr *in6;
366{
367 struct ifnet *ifp;
368
369 /* first, try to get it from the interface itself */
370 if (get_hw_ifid(ifp0, in6) == 0) {
371 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
372 if_name(ifp0)));
373 goto success;
374 }
375
376 /* try secondary EUI64 source. this basically is for ATM PVC */
377 if (altifp && get_hw_ifid(altifp, in6) == 0) {
378 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
379 if_name(ifp0), if_name(altifp)));
380 goto success;
381 }
382
383 /* next, try to get it from some other hardware interface */
384 IFNET_RLOCK();
384 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
385 {
386 if (ifp == ifp0)
387 continue;
388 if (get_hw_ifid(ifp, in6) != 0)
389 continue;
390
391 /*
392 * to borrow ifid from other interface, ifid needs to be
393 * globally unique
394 */
395 if (IFID_UNIVERSAL(in6)) {
396 nd6log((LOG_DEBUG,
397 "%s: borrow interface identifier from %s\n",
398 if_name(ifp0), if_name(ifp)));
385 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
386 {
387 if (ifp == ifp0)
388 continue;
389 if (get_hw_ifid(ifp, in6) != 0)
390 continue;
391
392 /*
393 * to borrow ifid from other interface, ifid needs to be
394 * globally unique
395 */
396 if (IFID_UNIVERSAL(in6)) {
397 nd6log((LOG_DEBUG,
398 "%s: borrow interface identifier from %s\n",
399 if_name(ifp0), if_name(ifp)));
400 IFNET_RUNLOCK();
399 goto success;
400 }
401 }
401 goto success;
402 }
403 }
404 IFNET_RUNLOCK();
402
403 /* last resort: get from random number source */
404 if (get_rand_ifid(ifp, in6) == 0) {
405 nd6log((LOG_DEBUG,
406 "%s: interface identifier generated by random number\n",
407 if_name(ifp0)));
408 goto success;
409 }
410
411 printf("%s: failed to get interface identifier\n", if_name(ifp0));
412 return -1;
413
414success:
415 nd6log((LOG_INFO, "%s: ifid: "
416 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
417 if_name(ifp0),
418 in6->s6_addr[8], in6->s6_addr[9],
419 in6->s6_addr[10], in6->s6_addr[11],
420 in6->s6_addr[12], in6->s6_addr[13],
421 in6->s6_addr[14], in6->s6_addr[15]));
422 return 0;
423}
424
425static int
426in6_ifattach_linklocal(ifp, altifp)
427 struct ifnet *ifp;
428 struct ifnet *altifp; /* secondary EUI64 source */
429{
430 struct in6_ifaddr *ia;
431 struct in6_aliasreq ifra;
432 struct nd_prefix pr0;
433 int i, error;
434
435 /*
436 * configure link-local address.
437 */
438 bzero(&ifra, sizeof(ifra));
439
440 /*
441 * in6_update_ifa() does not use ifra_name, but we accurately set it
442 * for safety.
443 */
444 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
445
446 ifra.ifra_addr.sin6_family = AF_INET6;
447 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
448 ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
449#ifdef SCOPEDROUTING
450 ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0
451#else
452 ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */
453#endif
454 ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
455 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
456 ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
457 ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
458 } else {
459 if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
460 nd6log((LOG_ERR,
461 "%s: no ifid available\n", if_name(ifp)));
462 return -1;
463 }
464 }
465#ifdef SCOPEDROUTING
466 ifra.ifra_addr.sin6_scope_id =
467 in6_addr2scopeid(ifp, &ifra.ifra_addr.sin6_addr);
468#endif
469
470 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
471 ifra.ifra_prefixmask.sin6_family = AF_INET6;
472 ifra.ifra_prefixmask.sin6_addr = in6mask64;
473#ifdef SCOPEDROUTING
474 /* take into accound the sin6_scope_id field for routing */
475 ifra.ifra_prefixmask.sin6_scope_id = 0xffffffff;
476#endif
477 /* link-local addresses should NEVER expire. */
478 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
479 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
480
481 /*
482 * Do not let in6_update_ifa() do DAD, since we need a random delay
483 * before sending an NS at the first time the interface becomes up.
484 * Instead, in6_if_up() will start DAD with a proper random delay.
485 */
486 ifra.ifra_flags |= IN6_IFF_NODAD;
487
488 /*
489 * Now call in6_update_ifa() to do a bunch of procedures to configure
490 * a link-local address. We can set NULL to the 3rd argument, because
491 * we know there's no other link-local address on the interface
492 * and therefore we are adding one (instead of updating one).
493 */
494 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
495 /*
496 * XXX: When the interface does not support IPv6, this call
497 * would fail in the SIOCSIFADDR ioctl. I believe the
498 * notification is rather confusing in this case, so just
499 * supress it. (jinmei@kame.net 20010130)
500 */
501 if (error != EAFNOSUPPORT)
502 log(LOG_NOTICE, "in6_ifattach_linklocal: failed to "
503 "configure a link-local address on %s "
504 "(errno=%d)\n",
505 if_name(ifp), error);
506 return(-1);
507 }
508
509 /*
510 * Adjust ia6_flags so that in6_if_up will perform DAD.
511 * XXX: Some P2P interfaces seem not to send packets just after
512 * becoming up, so we skip p2p interfaces for safety.
513 */
514 ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
515#ifdef DIAGNOSTIC
516 if (!ia) {
517 panic("ia == NULL in in6_ifattach_linklocal");
518 /* NOTREACHED */
519 }
520#endif
521 if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) {
522 ia->ia6_flags &= ~IN6_IFF_NODAD;
523 ia->ia6_flags |= IN6_IFF_TENTATIVE;
524 }
525
526 /*
527 * Make the link-local prefix (fe80::/64%link) as on-link.
528 * Since we'd like to manage prefixes separately from addresses,
529 * we make an ND6 prefix structure for the link-local prefix,
530 * and add it to the prefix list as a never-expire prefix.
531 * XXX: this change might affect some existing code base...
532 */
533 bzero(&pr0, sizeof(pr0));
534 pr0.ndpr_ifp = ifp;
535 /* this should be 64 at this moment. */
536 pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
537 pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
538 pr0.ndpr_prefix = ifra.ifra_addr;
539 /* apply the mask for safety. (nd6_prelist_add will apply it again) */
540 for (i = 0; i < 4; i++) {
541 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
542 in6mask64.s6_addr32[i];
543 }
544 /*
545 * Initialize parameters. The link-local prefix must always be
546 * on-link, and its lifetimes never expire.
547 */
548 pr0.ndpr_raf_onlink = 1;
549 pr0.ndpr_raf_auto = 1; /* probably meaningless */
550 pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
551 pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
552 /*
553 * Since there is no other link-local addresses, nd6_prefix_lookup()
554 * probably returns NULL. However, we cannot always expect the result.
555 * For example, if we first remove the (only) existing link-local
556 * address, and then reconfigure another one, the prefix is still
557 * valid with referring to the old link-local address.
558 */
559 if (nd6_prefix_lookup(&pr0) == NULL) {
560 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
561 return(error);
562 }
563
564 return 0;
565}
566
567static int
568in6_ifattach_loopback(ifp)
569 struct ifnet *ifp; /* must be IFT_LOOP */
570{
571 struct in6_aliasreq ifra;
572 int error;
573
574 bzero(&ifra, sizeof(ifra));
575
576 /*
577 * in6_update_ifa() does not use ifra_name, but we accurately set it
578 * for safety.
579 */
580 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
581
582 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
583 ifra.ifra_prefixmask.sin6_family = AF_INET6;
584 ifra.ifra_prefixmask.sin6_addr = in6mask128;
585
586 /*
587 * Always initialize ia_dstaddr (= broadcast address) to loopback
588 * address. Follows IPv4 practice - see in_ifinit().
589 */
590 ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
591 ifra.ifra_dstaddr.sin6_family = AF_INET6;
592 ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
593
594 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
595 ifra.ifra_addr.sin6_family = AF_INET6;
596 ifra.ifra_addr.sin6_addr = in6addr_loopback;
597
598 /* the loopback address should NEVER expire. */
599 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
600 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
601
602 /* we don't need to perform DAD on loopback interfaces. */
603 ifra.ifra_flags |= IN6_IFF_NODAD;
604
605 /* skip registration to the prefix list. XXX should be temporary. */
606 ifra.ifra_flags |= IN6_IFF_NOPFX;
607
608 /*
609 * We are sure that this is a newly assigned address, so we can set
610 * NULL to the 3rd arg.
611 */
612 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
613 log(LOG_ERR, "in6_ifattach_loopback: failed to configure "
614 "the loopback address on %s (errno=%d)\n",
615 if_name(ifp), error);
616 return(-1);
617 }
618
619 return 0;
620}
621
622/*
623 * compute NI group address, based on the current hostname setting.
624 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
625 *
626 * when ifp == NULL, the caller is responsible for filling scopeid.
627 */
628int
629in6_nigroup(ifp, name, namelen, in6)
630 struct ifnet *ifp;
631 const char *name;
632 int namelen;
633 struct in6_addr *in6;
634{
635 const char *p;
636 u_char *q;
637 MD5_CTX ctxt;
638 u_int8_t digest[16];
639 char l;
640 char n[64]; /* a single label must not exceed 63 chars */
641
642 if (!namelen || !name)
643 return -1;
644
645 p = name;
646 while (p && *p && *p != '.' && p - name < namelen)
647 p++;
648 if (p - name > sizeof(n) - 1)
649 return -1; /* label too long */
650 l = p - name;
651 strncpy(n, name, l);
652 n[(int)l] = '\0';
653 for (q = n; *q; q++) {
654 if ('A' <= *q && *q <= 'Z')
655 *q = *q - 'A' + 'a';
656 }
657
658 /* generate 8 bytes of pseudo-random value. */
659 bzero(&ctxt, sizeof(ctxt));
660 MD5Init(&ctxt);
661 MD5Update(&ctxt, &l, sizeof(l));
662 MD5Update(&ctxt, n, l);
663 MD5Final(digest, &ctxt);
664
665 bzero(in6, sizeof(*in6));
666 in6->s6_addr16[0] = htons(0xff02);
667 if (ifp)
668 in6->s6_addr16[1] = htons(ifp->if_index);
669 in6->s6_addr8[11] = 2;
670 bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
671
672 return 0;
673}
674
675void
676in6_nigroup_attach(name, namelen)
677 const char *name;
678 int namelen;
679{
680 struct ifnet *ifp;
681 struct sockaddr_in6 mltaddr;
682 struct in6_multi *in6m;
683 int error;
684
685 bzero(&mltaddr, sizeof(mltaddr));
686 mltaddr.sin6_family = AF_INET6;
687 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
688 if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
689 return;
690
405
406 /* last resort: get from random number source */
407 if (get_rand_ifid(ifp, in6) == 0) {
408 nd6log((LOG_DEBUG,
409 "%s: interface identifier generated by random number\n",
410 if_name(ifp0)));
411 goto success;
412 }
413
414 printf("%s: failed to get interface identifier\n", if_name(ifp0));
415 return -1;
416
417success:
418 nd6log((LOG_INFO, "%s: ifid: "
419 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
420 if_name(ifp0),
421 in6->s6_addr[8], in6->s6_addr[9],
422 in6->s6_addr[10], in6->s6_addr[11],
423 in6->s6_addr[12], in6->s6_addr[13],
424 in6->s6_addr[14], in6->s6_addr[15]));
425 return 0;
426}
427
428static int
429in6_ifattach_linklocal(ifp, altifp)
430 struct ifnet *ifp;
431 struct ifnet *altifp; /* secondary EUI64 source */
432{
433 struct in6_ifaddr *ia;
434 struct in6_aliasreq ifra;
435 struct nd_prefix pr0;
436 int i, error;
437
438 /*
439 * configure link-local address.
440 */
441 bzero(&ifra, sizeof(ifra));
442
443 /*
444 * in6_update_ifa() does not use ifra_name, but we accurately set it
445 * for safety.
446 */
447 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
448
449 ifra.ifra_addr.sin6_family = AF_INET6;
450 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
451 ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
452#ifdef SCOPEDROUTING
453 ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0
454#else
455 ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */
456#endif
457 ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
458 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
459 ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
460 ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
461 } else {
462 if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
463 nd6log((LOG_ERR,
464 "%s: no ifid available\n", if_name(ifp)));
465 return -1;
466 }
467 }
468#ifdef SCOPEDROUTING
469 ifra.ifra_addr.sin6_scope_id =
470 in6_addr2scopeid(ifp, &ifra.ifra_addr.sin6_addr);
471#endif
472
473 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
474 ifra.ifra_prefixmask.sin6_family = AF_INET6;
475 ifra.ifra_prefixmask.sin6_addr = in6mask64;
476#ifdef SCOPEDROUTING
477 /* take into accound the sin6_scope_id field for routing */
478 ifra.ifra_prefixmask.sin6_scope_id = 0xffffffff;
479#endif
480 /* link-local addresses should NEVER expire. */
481 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
482 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
483
484 /*
485 * Do not let in6_update_ifa() do DAD, since we need a random delay
486 * before sending an NS at the first time the interface becomes up.
487 * Instead, in6_if_up() will start DAD with a proper random delay.
488 */
489 ifra.ifra_flags |= IN6_IFF_NODAD;
490
491 /*
492 * Now call in6_update_ifa() to do a bunch of procedures to configure
493 * a link-local address. We can set NULL to the 3rd argument, because
494 * we know there's no other link-local address on the interface
495 * and therefore we are adding one (instead of updating one).
496 */
497 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
498 /*
499 * XXX: When the interface does not support IPv6, this call
500 * would fail in the SIOCSIFADDR ioctl. I believe the
501 * notification is rather confusing in this case, so just
502 * supress it. (jinmei@kame.net 20010130)
503 */
504 if (error != EAFNOSUPPORT)
505 log(LOG_NOTICE, "in6_ifattach_linklocal: failed to "
506 "configure a link-local address on %s "
507 "(errno=%d)\n",
508 if_name(ifp), error);
509 return(-1);
510 }
511
512 /*
513 * Adjust ia6_flags so that in6_if_up will perform DAD.
514 * XXX: Some P2P interfaces seem not to send packets just after
515 * becoming up, so we skip p2p interfaces for safety.
516 */
517 ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
518#ifdef DIAGNOSTIC
519 if (!ia) {
520 panic("ia == NULL in in6_ifattach_linklocal");
521 /* NOTREACHED */
522 }
523#endif
524 if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) {
525 ia->ia6_flags &= ~IN6_IFF_NODAD;
526 ia->ia6_flags |= IN6_IFF_TENTATIVE;
527 }
528
529 /*
530 * Make the link-local prefix (fe80::/64%link) as on-link.
531 * Since we'd like to manage prefixes separately from addresses,
532 * we make an ND6 prefix structure for the link-local prefix,
533 * and add it to the prefix list as a never-expire prefix.
534 * XXX: this change might affect some existing code base...
535 */
536 bzero(&pr0, sizeof(pr0));
537 pr0.ndpr_ifp = ifp;
538 /* this should be 64 at this moment. */
539 pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
540 pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
541 pr0.ndpr_prefix = ifra.ifra_addr;
542 /* apply the mask for safety. (nd6_prelist_add will apply it again) */
543 for (i = 0; i < 4; i++) {
544 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
545 in6mask64.s6_addr32[i];
546 }
547 /*
548 * Initialize parameters. The link-local prefix must always be
549 * on-link, and its lifetimes never expire.
550 */
551 pr0.ndpr_raf_onlink = 1;
552 pr0.ndpr_raf_auto = 1; /* probably meaningless */
553 pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
554 pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
555 /*
556 * Since there is no other link-local addresses, nd6_prefix_lookup()
557 * probably returns NULL. However, we cannot always expect the result.
558 * For example, if we first remove the (only) existing link-local
559 * address, and then reconfigure another one, the prefix is still
560 * valid with referring to the old link-local address.
561 */
562 if (nd6_prefix_lookup(&pr0) == NULL) {
563 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
564 return(error);
565 }
566
567 return 0;
568}
569
570static int
571in6_ifattach_loopback(ifp)
572 struct ifnet *ifp; /* must be IFT_LOOP */
573{
574 struct in6_aliasreq ifra;
575 int error;
576
577 bzero(&ifra, sizeof(ifra));
578
579 /*
580 * in6_update_ifa() does not use ifra_name, but we accurately set it
581 * for safety.
582 */
583 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
584
585 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
586 ifra.ifra_prefixmask.sin6_family = AF_INET6;
587 ifra.ifra_prefixmask.sin6_addr = in6mask128;
588
589 /*
590 * Always initialize ia_dstaddr (= broadcast address) to loopback
591 * address. Follows IPv4 practice - see in_ifinit().
592 */
593 ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
594 ifra.ifra_dstaddr.sin6_family = AF_INET6;
595 ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
596
597 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
598 ifra.ifra_addr.sin6_family = AF_INET6;
599 ifra.ifra_addr.sin6_addr = in6addr_loopback;
600
601 /* the loopback address should NEVER expire. */
602 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
603 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
604
605 /* we don't need to perform DAD on loopback interfaces. */
606 ifra.ifra_flags |= IN6_IFF_NODAD;
607
608 /* skip registration to the prefix list. XXX should be temporary. */
609 ifra.ifra_flags |= IN6_IFF_NOPFX;
610
611 /*
612 * We are sure that this is a newly assigned address, so we can set
613 * NULL to the 3rd arg.
614 */
615 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
616 log(LOG_ERR, "in6_ifattach_loopback: failed to configure "
617 "the loopback address on %s (errno=%d)\n",
618 if_name(ifp), error);
619 return(-1);
620 }
621
622 return 0;
623}
624
625/*
626 * compute NI group address, based on the current hostname setting.
627 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
628 *
629 * when ifp == NULL, the caller is responsible for filling scopeid.
630 */
631int
632in6_nigroup(ifp, name, namelen, in6)
633 struct ifnet *ifp;
634 const char *name;
635 int namelen;
636 struct in6_addr *in6;
637{
638 const char *p;
639 u_char *q;
640 MD5_CTX ctxt;
641 u_int8_t digest[16];
642 char l;
643 char n[64]; /* a single label must not exceed 63 chars */
644
645 if (!namelen || !name)
646 return -1;
647
648 p = name;
649 while (p && *p && *p != '.' && p - name < namelen)
650 p++;
651 if (p - name > sizeof(n) - 1)
652 return -1; /* label too long */
653 l = p - name;
654 strncpy(n, name, l);
655 n[(int)l] = '\0';
656 for (q = n; *q; q++) {
657 if ('A' <= *q && *q <= 'Z')
658 *q = *q - 'A' + 'a';
659 }
660
661 /* generate 8 bytes of pseudo-random value. */
662 bzero(&ctxt, sizeof(ctxt));
663 MD5Init(&ctxt);
664 MD5Update(&ctxt, &l, sizeof(l));
665 MD5Update(&ctxt, n, l);
666 MD5Final(digest, &ctxt);
667
668 bzero(in6, sizeof(*in6));
669 in6->s6_addr16[0] = htons(0xff02);
670 if (ifp)
671 in6->s6_addr16[1] = htons(ifp->if_index);
672 in6->s6_addr8[11] = 2;
673 bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
674
675 return 0;
676}
677
678void
679in6_nigroup_attach(name, namelen)
680 const char *name;
681 int namelen;
682{
683 struct ifnet *ifp;
684 struct sockaddr_in6 mltaddr;
685 struct in6_multi *in6m;
686 int error;
687
688 bzero(&mltaddr, sizeof(mltaddr));
689 mltaddr.sin6_family = AF_INET6;
690 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
691 if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
692 return;
693
694 IFNET_RLOCK();
691 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
692 {
693 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
694 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
695 if (!in6m) {
696 if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error)) {
697 nd6log((LOG_ERR, "%s: failed to join %s "
698 "(errno=%d)\n", if_name(ifp),
699 ip6_sprintf(&mltaddr.sin6_addr),
700 error));
701 }
702 }
703 }
695 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
696 {
697 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
698 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
699 if (!in6m) {
700 if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error)) {
701 nd6log((LOG_ERR, "%s: failed to join %s "
702 "(errno=%d)\n", if_name(ifp),
703 ip6_sprintf(&mltaddr.sin6_addr),
704 error));
705 }
706 }
707 }
708 IFNET_RUNLOCK();
704}
705
706void
707in6_nigroup_detach(name, namelen)
708 const char *name;
709 int namelen;
710{
711 struct ifnet *ifp;
712 struct sockaddr_in6 mltaddr;
713 struct in6_multi *in6m;
714
715 bzero(&mltaddr, sizeof(mltaddr));
716 mltaddr.sin6_family = AF_INET6;
717 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
718 if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
719 return;
720
709}
710
711void
712in6_nigroup_detach(name, namelen)
713 const char *name;
714 int namelen;
715{
716 struct ifnet *ifp;
717 struct sockaddr_in6 mltaddr;
718 struct in6_multi *in6m;
719
720 bzero(&mltaddr, sizeof(mltaddr));
721 mltaddr.sin6_family = AF_INET6;
722 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
723 if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
724 return;
725
726 IFNET_RLOCK();
721 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
722 {
723 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
724 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
725 if (in6m)
726 in6_delmulti(in6m);
727 }
727 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
728 {
729 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
730 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
731 if (in6m)
732 in6_delmulti(in6m);
733 }
734 IFNET_RUNLOCK();
728}
729
730/*
731 * XXX multiple loopback interface needs more care. for instance,
732 * nodelocal address needs to be configured onto only one of them.
733 * XXX multiple link-local address case
734 */
735void
736in6_ifattach(ifp, altifp)
737 struct ifnet *ifp;
738 struct ifnet *altifp; /* secondary EUI64 source */
739{
740 static size_t if_indexlim = 8;
741 struct in6_ifaddr *ia;
742 struct in6_addr in6;
743
744 /* some of the interfaces are inherently not IPv6 capable */
745 switch (ifp->if_type) {
746#ifdef IFT_BRIDGE /*OpenBSD 2.8*/
747 case IFT_BRIDGE:
748 return;
749#endif
750 }
751
752 /*
753 * We have some arrays that should be indexed by if_index.
754 * since if_index will grow dynamically, they should grow too.
755 * struct in6_ifstat **in6_ifstat
756 * struct icmp6_ifstat **icmp6_ifstat
757 */
758 if (in6_ifstat == NULL || icmp6_ifstat == NULL ||
759 if_index >= if_indexlim) {
760 size_t n;
761 caddr_t q;
762 size_t olim;
763
764 olim = if_indexlim;
765 while (if_index >= if_indexlim)
766 if_indexlim <<= 1;
767
768 /* grow in6_ifstat */
769 n = if_indexlim * sizeof(struct in6_ifstat *);
770 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
771 bzero(q, n);
772 if (in6_ifstat) {
773 bcopy((caddr_t)in6_ifstat, q,
774 olim * sizeof(struct in6_ifstat *));
775 free((caddr_t)in6_ifstat, M_IFADDR);
776 }
777 in6_ifstat = (struct in6_ifstat **)q;
778 in6_ifstatmax = if_indexlim;
779
780 /* grow icmp6_ifstat */
781 n = if_indexlim * sizeof(struct icmp6_ifstat *);
782 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
783 bzero(q, n);
784 if (icmp6_ifstat) {
785 bcopy((caddr_t)icmp6_ifstat, q,
786 olim * sizeof(struct icmp6_ifstat *));
787 free((caddr_t)icmp6_ifstat, M_IFADDR);
788 }
789 icmp6_ifstat = (struct icmp6_ifstat **)q;
790 icmp6_ifstatmax = if_indexlim;
791 }
792
793 /* initialize scope identifiers */
794 scope6_ifattach(ifp);
795
796 /*
797 * quirks based on interface type
798 */
799 switch (ifp->if_type) {
800#ifdef IFT_STF
801 case IFT_STF:
802 /*
803 * 6to4 interface is a very special kind of beast.
804 * no multicast, no linklocal. RFC2529 specifies how to make
805 * linklocals for 6to4 interface, but there's no use and
806 * it is rather harmful to have one.
807 */
808 goto statinit;
809#endif
810 default:
811 break;
812 }
813
814 /*
815 * usually, we require multicast capability to the interface
816 */
817 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
818 log(LOG_INFO, "in6_ifattach: "
819 "%s is not multicast capable, IPv6 not enabled\n",
820 if_name(ifp));
821 return;
822 }
823
824 /*
825 * assign loopback address for loopback interface.
826 * XXX multiple loopback interface case.
827 */
828 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
829 in6 = in6addr_loopback;
830 if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
831 if (in6_ifattach_loopback(ifp) != 0)
832 return;
833 }
834 }
835
836 /*
837 * assign a link-local address, if there's none.
838 */
839 if (ip6_auto_linklocal) {
840 ia = in6ifa_ifpforlinklocal(ifp, 0);
841 if (ia == NULL) {
842 if (in6_ifattach_linklocal(ifp, altifp) == 0) {
843 /* linklocal address assigned */
844 } else {
845 /* failed to assign linklocal address. bark? */
846 }
847 }
848 }
849
850#ifdef IFT_STF /* XXX */
851statinit:
852#endif
853
854 /* update dynamically. */
855 if (in6_maxmtu < ifp->if_mtu)
856 in6_maxmtu = ifp->if_mtu;
857
858 if (in6_ifstat[ifp->if_index] == NULL) {
859 in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
860 malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
861 bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
862 }
863 if (icmp6_ifstat[ifp->if_index] == NULL) {
864 icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
865 malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
866 bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
867 }
868
869 /* initialize NDP variables */
870 nd6_ifattach(ifp);
871}
872
873/*
874 * NOTE: in6_ifdetach() does not support loopback if at this moment.
875 * We don't need this function in bsdi, because interfaces are never removed
876 * from the ifnet list in bsdi.
877 */
878void
879in6_ifdetach(ifp)
880 struct ifnet *ifp;
881{
882 struct in6_ifaddr *ia, *oia;
883 struct ifaddr *ifa, *next;
884 struct rtentry *rt;
885 short rtflags;
886 struct sockaddr_in6 sin6;
887 struct in6_multi *in6m;
888 struct in6_multi *in6m_next;
889
890 /* nuke prefix list. this may try to remove some of ifaddrs as well */
891 in6_purgeprefix(ifp);
892
893 /* remove neighbor management table */
894 nd6_purge(ifp);
895
896 /* nuke any of IPv6 addresses we have */
897 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
898 {
899 next = ifa->ifa_list.tqe_next;
900 if (ifa->ifa_addr->sa_family != AF_INET6)
901 continue;
902 in6_purgeaddr(ifa);
903 }
904
905 /* undo everything done by in6_ifattach(), just in case */
906 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
907 {
908 next = ifa->ifa_list.tqe_next;
909
910
911 if (ifa->ifa_addr->sa_family != AF_INET6
912 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
913 continue;
914 }
915
916 ia = (struct in6_ifaddr *)ifa;
917
918 /* remove from the routing table */
919 if ((ia->ia_flags & IFA_ROUTE)
920 && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
921 rtflags = rt->rt_flags;
922 rtfree(rt);
923 rtrequest(RTM_DELETE,
924 (struct sockaddr *)&ia->ia_addr,
925 (struct sockaddr *)&ia->ia_addr,
926 (struct sockaddr *)&ia->ia_prefixmask,
927 rtflags, (struct rtentry **)0);
928 }
929
930 /* remove from the linked list */
931 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
932 IFAFREE(&ia->ia_ifa);
933
934 /* also remove from the IPv6 address chain(itojun&jinmei) */
935 oia = ia;
936 if (oia == (ia = in6_ifaddr))
937 in6_ifaddr = ia->ia_next;
938 else {
939 while (ia->ia_next && (ia->ia_next != oia))
940 ia = ia->ia_next;
941 if (ia->ia_next)
942 ia->ia_next = oia->ia_next;
943 else {
944 nd6log((LOG_ERR,
945 "%s: didn't unlink in6ifaddr from "
946 "list\n", if_name(ifp)));
947 }
948 }
949
950 IFAFREE(&oia->ia_ifa);
951 }
952
953 /* leave from all multicast groups joined */
954 in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
955 in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
956 for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
957 in6m_next = LIST_NEXT(in6m, in6m_entry);
958 if (in6m->in6m_ifp != ifp)
959 continue;
960 in6_delmulti(in6m);
961 in6m = NULL;
962 }
963
964 /*
965 * remove neighbor management table. we call it twice just to make
966 * sure we nuke everything. maybe we need just one call.
967 * XXX: since the first call did not release addresses, some prefixes
968 * might remain. We should call nd6_purge() again to release the
969 * prefixes after removing all addresses above.
970 * (Or can we just delay calling nd6_purge until at this point?)
971 */
972 nd6_purge(ifp);
973
974 /* remove route to link-local allnodes multicast (ff02::1) */
975 bzero(&sin6, sizeof(sin6));
976 sin6.sin6_len = sizeof(struct sockaddr_in6);
977 sin6.sin6_family = AF_INET6;
978 sin6.sin6_addr = in6addr_linklocal_allnodes;
979 sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
980 rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
981 if (rt && rt->rt_ifp == ifp) {
982 rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
983 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
984 rtfree(rt);
985 }
986}
987
988void
989in6_get_tmpifid(ifp, retbuf, baseid, generate)
990 struct ifnet *ifp;
991 u_int8_t *retbuf;
992 const u_int8_t *baseid;
993 int generate;
994{
995 u_int8_t nullbuf[8];
996 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
997
998 bzero(nullbuf, sizeof(nullbuf));
999 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
1000 /* we've never created a random ID. Create a new one. */
1001 generate = 1;
1002 }
1003
1004 if (generate) {
1005 bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
1006
1007 /* generate_tmp_ifid will update seedn and buf */
1008 (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
1009 ndi->randomid);
1010 }
1011 bcopy(ndi->randomid, retbuf, 8);
1012}
1013
1014void
1015in6_tmpaddrtimer(ignored_arg)
1016 void *ignored_arg;
1017{
1018 int i;
1019 struct nd_ifinfo *ndi;
1020 u_int8_t nullbuf[8];
1021 int s = splnet();
1022
1023 callout_reset(&in6_tmpaddrtimer_ch,
1024 (ip6_temp_preferred_lifetime - ip6_desync_factor -
1025 ip6_temp_regen_advance) * hz,
1026 in6_tmpaddrtimer, NULL);
1027
1028 bzero(nullbuf, sizeof(nullbuf));
1029 for (i = 1; i < if_index + 1; i++) {
1030 ndi = &nd_ifinfo[i];
1031 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
1032 /*
1033 * We've been generating a random ID on this interface.
1034 * Create a new one.
1035 */
1036 (void)generate_tmp_ifid(ndi->randomseed0,
1037 ndi->randomseed1,
1038 ndi->randomid);
1039 }
1040 }
1041
1042 splx(s);
1043}
735}
736
737/*
738 * XXX multiple loopback interface needs more care. for instance,
739 * nodelocal address needs to be configured onto only one of them.
740 * XXX multiple link-local address case
741 */
742void
743in6_ifattach(ifp, altifp)
744 struct ifnet *ifp;
745 struct ifnet *altifp; /* secondary EUI64 source */
746{
747 static size_t if_indexlim = 8;
748 struct in6_ifaddr *ia;
749 struct in6_addr in6;
750
751 /* some of the interfaces are inherently not IPv6 capable */
752 switch (ifp->if_type) {
753#ifdef IFT_BRIDGE /*OpenBSD 2.8*/
754 case IFT_BRIDGE:
755 return;
756#endif
757 }
758
759 /*
760 * We have some arrays that should be indexed by if_index.
761 * since if_index will grow dynamically, they should grow too.
762 * struct in6_ifstat **in6_ifstat
763 * struct icmp6_ifstat **icmp6_ifstat
764 */
765 if (in6_ifstat == NULL || icmp6_ifstat == NULL ||
766 if_index >= if_indexlim) {
767 size_t n;
768 caddr_t q;
769 size_t olim;
770
771 olim = if_indexlim;
772 while (if_index >= if_indexlim)
773 if_indexlim <<= 1;
774
775 /* grow in6_ifstat */
776 n = if_indexlim * sizeof(struct in6_ifstat *);
777 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
778 bzero(q, n);
779 if (in6_ifstat) {
780 bcopy((caddr_t)in6_ifstat, q,
781 olim * sizeof(struct in6_ifstat *));
782 free((caddr_t)in6_ifstat, M_IFADDR);
783 }
784 in6_ifstat = (struct in6_ifstat **)q;
785 in6_ifstatmax = if_indexlim;
786
787 /* grow icmp6_ifstat */
788 n = if_indexlim * sizeof(struct icmp6_ifstat *);
789 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
790 bzero(q, n);
791 if (icmp6_ifstat) {
792 bcopy((caddr_t)icmp6_ifstat, q,
793 olim * sizeof(struct icmp6_ifstat *));
794 free((caddr_t)icmp6_ifstat, M_IFADDR);
795 }
796 icmp6_ifstat = (struct icmp6_ifstat **)q;
797 icmp6_ifstatmax = if_indexlim;
798 }
799
800 /* initialize scope identifiers */
801 scope6_ifattach(ifp);
802
803 /*
804 * quirks based on interface type
805 */
806 switch (ifp->if_type) {
807#ifdef IFT_STF
808 case IFT_STF:
809 /*
810 * 6to4 interface is a very special kind of beast.
811 * no multicast, no linklocal. RFC2529 specifies how to make
812 * linklocals for 6to4 interface, but there's no use and
813 * it is rather harmful to have one.
814 */
815 goto statinit;
816#endif
817 default:
818 break;
819 }
820
821 /*
822 * usually, we require multicast capability to the interface
823 */
824 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
825 log(LOG_INFO, "in6_ifattach: "
826 "%s is not multicast capable, IPv6 not enabled\n",
827 if_name(ifp));
828 return;
829 }
830
831 /*
832 * assign loopback address for loopback interface.
833 * XXX multiple loopback interface case.
834 */
835 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
836 in6 = in6addr_loopback;
837 if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
838 if (in6_ifattach_loopback(ifp) != 0)
839 return;
840 }
841 }
842
843 /*
844 * assign a link-local address, if there's none.
845 */
846 if (ip6_auto_linklocal) {
847 ia = in6ifa_ifpforlinklocal(ifp, 0);
848 if (ia == NULL) {
849 if (in6_ifattach_linklocal(ifp, altifp) == 0) {
850 /* linklocal address assigned */
851 } else {
852 /* failed to assign linklocal address. bark? */
853 }
854 }
855 }
856
857#ifdef IFT_STF /* XXX */
858statinit:
859#endif
860
861 /* update dynamically. */
862 if (in6_maxmtu < ifp->if_mtu)
863 in6_maxmtu = ifp->if_mtu;
864
865 if (in6_ifstat[ifp->if_index] == NULL) {
866 in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
867 malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
868 bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
869 }
870 if (icmp6_ifstat[ifp->if_index] == NULL) {
871 icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
872 malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
873 bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
874 }
875
876 /* initialize NDP variables */
877 nd6_ifattach(ifp);
878}
879
880/*
881 * NOTE: in6_ifdetach() does not support loopback if at this moment.
882 * We don't need this function in bsdi, because interfaces are never removed
883 * from the ifnet list in bsdi.
884 */
885void
886in6_ifdetach(ifp)
887 struct ifnet *ifp;
888{
889 struct in6_ifaddr *ia, *oia;
890 struct ifaddr *ifa, *next;
891 struct rtentry *rt;
892 short rtflags;
893 struct sockaddr_in6 sin6;
894 struct in6_multi *in6m;
895 struct in6_multi *in6m_next;
896
897 /* nuke prefix list. this may try to remove some of ifaddrs as well */
898 in6_purgeprefix(ifp);
899
900 /* remove neighbor management table */
901 nd6_purge(ifp);
902
903 /* nuke any of IPv6 addresses we have */
904 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
905 {
906 next = ifa->ifa_list.tqe_next;
907 if (ifa->ifa_addr->sa_family != AF_INET6)
908 continue;
909 in6_purgeaddr(ifa);
910 }
911
912 /* undo everything done by in6_ifattach(), just in case */
913 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
914 {
915 next = ifa->ifa_list.tqe_next;
916
917
918 if (ifa->ifa_addr->sa_family != AF_INET6
919 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
920 continue;
921 }
922
923 ia = (struct in6_ifaddr *)ifa;
924
925 /* remove from the routing table */
926 if ((ia->ia_flags & IFA_ROUTE)
927 && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
928 rtflags = rt->rt_flags;
929 rtfree(rt);
930 rtrequest(RTM_DELETE,
931 (struct sockaddr *)&ia->ia_addr,
932 (struct sockaddr *)&ia->ia_addr,
933 (struct sockaddr *)&ia->ia_prefixmask,
934 rtflags, (struct rtentry **)0);
935 }
936
937 /* remove from the linked list */
938 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
939 IFAFREE(&ia->ia_ifa);
940
941 /* also remove from the IPv6 address chain(itojun&jinmei) */
942 oia = ia;
943 if (oia == (ia = in6_ifaddr))
944 in6_ifaddr = ia->ia_next;
945 else {
946 while (ia->ia_next && (ia->ia_next != oia))
947 ia = ia->ia_next;
948 if (ia->ia_next)
949 ia->ia_next = oia->ia_next;
950 else {
951 nd6log((LOG_ERR,
952 "%s: didn't unlink in6ifaddr from "
953 "list\n", if_name(ifp)));
954 }
955 }
956
957 IFAFREE(&oia->ia_ifa);
958 }
959
960 /* leave from all multicast groups joined */
961 in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
962 in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
963 for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
964 in6m_next = LIST_NEXT(in6m, in6m_entry);
965 if (in6m->in6m_ifp != ifp)
966 continue;
967 in6_delmulti(in6m);
968 in6m = NULL;
969 }
970
971 /*
972 * remove neighbor management table. we call it twice just to make
973 * sure we nuke everything. maybe we need just one call.
974 * XXX: since the first call did not release addresses, some prefixes
975 * might remain. We should call nd6_purge() again to release the
976 * prefixes after removing all addresses above.
977 * (Or can we just delay calling nd6_purge until at this point?)
978 */
979 nd6_purge(ifp);
980
981 /* remove route to link-local allnodes multicast (ff02::1) */
982 bzero(&sin6, sizeof(sin6));
983 sin6.sin6_len = sizeof(struct sockaddr_in6);
984 sin6.sin6_family = AF_INET6;
985 sin6.sin6_addr = in6addr_linklocal_allnodes;
986 sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
987 rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
988 if (rt && rt->rt_ifp == ifp) {
989 rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
990 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
991 rtfree(rt);
992 }
993}
994
995void
996in6_get_tmpifid(ifp, retbuf, baseid, generate)
997 struct ifnet *ifp;
998 u_int8_t *retbuf;
999 const u_int8_t *baseid;
1000 int generate;
1001{
1002 u_int8_t nullbuf[8];
1003 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
1004
1005 bzero(nullbuf, sizeof(nullbuf));
1006 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
1007 /* we've never created a random ID. Create a new one. */
1008 generate = 1;
1009 }
1010
1011 if (generate) {
1012 bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
1013
1014 /* generate_tmp_ifid will update seedn and buf */
1015 (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
1016 ndi->randomid);
1017 }
1018 bcopy(ndi->randomid, retbuf, 8);
1019}
1020
1021void
1022in6_tmpaddrtimer(ignored_arg)
1023 void *ignored_arg;
1024{
1025 int i;
1026 struct nd_ifinfo *ndi;
1027 u_int8_t nullbuf[8];
1028 int s = splnet();
1029
1030 callout_reset(&in6_tmpaddrtimer_ch,
1031 (ip6_temp_preferred_lifetime - ip6_desync_factor -
1032 ip6_temp_regen_advance) * hz,
1033 in6_tmpaddrtimer, NULL);
1034
1035 bzero(nullbuf, sizeof(nullbuf));
1036 for (i = 1; i < if_index + 1; i++) {
1037 ndi = &nd_ifinfo[i];
1038 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
1039 /*
1040 * We've been generating a random ID on this interface.
1041 * Create a new one.
1042 */
1043 (void)generate_tmp_ifid(ndi->randomseed0,
1044 ndi->randomseed1,
1045 ndi->randomid);
1046 }
1047 }
1048
1049 splx(s);
1050}