in6_ifattach.c revision 1.1.2.2 1 1.1.2.1 itojun /*
2 1.1.2.1 itojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 1.1.2.1 itojun * All rights reserved.
4 1.1.2.1 itojun *
5 1.1.2.1 itojun * Redistribution and use in source and binary forms, with or without
6 1.1.2.1 itojun * modification, are permitted provided that the following conditions
7 1.1.2.1 itojun * are met:
8 1.1.2.1 itojun * 1. Redistributions of source code must retain the above copyright
9 1.1.2.1 itojun * notice, this list of conditions and the following disclaimer.
10 1.1.2.1 itojun * 2. Redistributions in binary form must reproduce the above copyright
11 1.1.2.1 itojun * notice, this list of conditions and the following disclaimer in the
12 1.1.2.1 itojun * documentation and/or other materials provided with the distribution.
13 1.1.2.1 itojun * 3. Neither the name of the project nor the names of its contributors
14 1.1.2.1 itojun * may be used to endorse or promote products derived from this software
15 1.1.2.1 itojun * without specific prior written permission.
16 1.1.2.1 itojun *
17 1.1.2.1 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 1.1.2.1 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1.2.1 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1.2.1 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 1.1.2.1 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1.2.1 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1.2.1 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1.2.1 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1.2.1 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1.2.1 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1.2.1 itojun * SUCH DAMAGE.
28 1.1.2.1 itojun */
29 1.1.2.1 itojun
30 1.1.2.1 itojun #include <sys/param.h>
31 1.1.2.1 itojun #include <sys/systm.h>
32 1.1.2.1 itojun #include <sys/malloc.h>
33 1.1.2.1 itojun #include <sys/socket.h>
34 1.1.2.1 itojun #include <sys/sockio.h>
35 1.1.2.2 itojun #include <sys/kernel.h>
36 1.1.2.2 itojun #ifdef __bsdi__
37 1.1.2.2 itojun #include <crypto/md5.h>
38 1.1.2.2 itojun #elif defined(__OpenBSD__)
39 1.1.2.2 itojun #include <sys/md5k.h>
40 1.1.2.2 itojun #else
41 1.1.2.2 itojun #include <sys/md5.h>
42 1.1.2.2 itojun #endif
43 1.1.2.1 itojun
44 1.1.2.1 itojun #include <net/if.h>
45 1.1.2.1 itojun #include <net/if_dl.h>
46 1.1.2.1 itojun #include <net/if_types.h>
47 1.1.2.1 itojun #include <net/route.h>
48 1.1.2.1 itojun
49 1.1.2.1 itojun #include <netinet/in.h>
50 1.1.2.1 itojun #include <netinet/in_var.h>
51 1.1.2.1 itojun #ifndef __NetBSD__
52 1.1.2.1 itojun #include <netinet/if_ether.h>
53 1.1.2.1 itojun #endif
54 1.1.2.1 itojun
55 1.1.2.1 itojun #include <netinet6/ip6.h>
56 1.1.2.1 itojun #include <netinet6/ip6_var.h>
57 1.1.2.1 itojun #include <netinet6/in6_ifattach.h>
58 1.1.2.1 itojun #include <netinet6/ip6.h>
59 1.1.2.1 itojun #include <netinet6/ip6_var.h>
60 1.1.2.1 itojun #include <netinet6/nd6.h>
61 1.1.2.1 itojun
62 1.1.2.2 itojun #include <net/net_osdep.h>
63 1.1.2.2 itojun
64 1.1.2.1 itojun static struct in6_addr llsol;
65 1.1.2.1 itojun
66 1.1.2.2 itojun struct in6_ifstat **in6_ifstat = NULL;
67 1.1.2.2 itojun struct icmp6_ifstat **icmp6_ifstat = NULL;
68 1.1.2.2 itojun size_t in6_ifstatmax = 0;
69 1.1.2.2 itojun size_t icmp6_ifstatmax = 0;
70 1.1.2.1 itojun unsigned long in6_maxmtu = 0;
71 1.1.2.1 itojun
72 1.1.2.1 itojun int found_first_ifid = 0;
73 1.1.2.1 itojun #define IFID_LEN 8
74 1.1.2.1 itojun static char first_ifid[IFID_LEN];
75 1.1.2.1 itojun
76 1.1.2.2 itojun static int laddr_to_eui64 __P((u_int8_t *, u_int8_t *, size_t));
77 1.1.2.2 itojun static int gen_rand_eui64 __P((u_int8_t *));
78 1.1.2.1 itojun
79 1.1.2.2 itojun static int
80 1.1.2.2 itojun laddr_to_eui64(dst, src, len)
81 1.1.2.1 itojun u_int8_t *dst;
82 1.1.2.1 itojun u_int8_t *src;
83 1.1.2.2 itojun size_t len;
84 1.1.2.1 itojun {
85 1.1.2.2 itojun static u_int8_t zero[8];
86 1.1.2.2 itojun
87 1.1.2.2 itojun bzero(zero, sizeof(zero));
88 1.1.2.2 itojun
89 1.1.2.2 itojun switch (len) {
90 1.1.2.2 itojun case 6:
91 1.1.2.2 itojun if (bcmp(zero, src, 6) == 0)
92 1.1.2.2 itojun return EINVAL;
93 1.1.2.2 itojun dst[0] = src[0];
94 1.1.2.2 itojun dst[1] = src[1];
95 1.1.2.2 itojun dst[2] = src[2];
96 1.1.2.2 itojun dst[3] = 0xff;
97 1.1.2.2 itojun dst[4] = 0xfe;
98 1.1.2.2 itojun dst[5] = src[3];
99 1.1.2.2 itojun dst[6] = src[4];
100 1.1.2.2 itojun dst[7] = src[5];
101 1.1.2.2 itojun break;
102 1.1.2.2 itojun case 8:
103 1.1.2.2 itojun if (bcmp(zero, src, 8) == 0)
104 1.1.2.2 itojun return EINVAL;
105 1.1.2.2 itojun bcopy(src, dst, len);
106 1.1.2.2 itojun break;
107 1.1.2.2 itojun default:
108 1.1.2.2 itojun return EINVAL;
109 1.1.2.2 itojun }
110 1.1.2.2 itojun
111 1.1.2.2 itojun return 0;
112 1.1.2.2 itojun }
113 1.1.2.2 itojun
114 1.1.2.2 itojun /*
115 1.1.2.2 itojun * Generate a last-resort interface identifier, when the machine has no
116 1.1.2.2 itojun * IEEE802/EUI64 address sources.
117 1.1.2.2 itojun * The address should be random, and should not change across reboot.
118 1.1.2.2 itojun */
119 1.1.2.2 itojun static int
120 1.1.2.2 itojun gen_rand_eui64(dst)
121 1.1.2.2 itojun u_int8_t *dst;
122 1.1.2.2 itojun {
123 1.1.2.2 itojun MD5_CTX ctxt;
124 1.1.2.2 itojun u_int8_t digest[16];
125 1.1.2.2 itojun #ifdef __FreeBSD__
126 1.1.2.2 itojun int hostnamelen = strlen(hostname);
127 1.1.2.2 itojun #endif
128 1.1.2.2 itojun
129 1.1.2.2 itojun /* generate 8bytes of pseudo-random value. */
130 1.1.2.2 itojun bzero(&ctxt, sizeof(ctxt));
131 1.1.2.2 itojun MD5Init(&ctxt);
132 1.1.2.2 itojun MD5Update(&ctxt, hostname, hostnamelen);
133 1.1.2.2 itojun MD5Final(digest, &ctxt);
134 1.1.2.2 itojun
135 1.1.2.2 itojun /* assumes sizeof(digest) > sizeof(first_ifid) */
136 1.1.2.2 itojun bcopy(digest, dst, 8);
137 1.1.2.2 itojun
138 1.1.2.2 itojun /* make sure to set "u" bit to local, and "g" bit to individual. */
139 1.1.2.2 itojun dst[0] &= 0xfe;
140 1.1.2.2 itojun dst[0] |= 0x02; /* EUI64 "local" */
141 1.1.2.2 itojun
142 1.1.2.2 itojun return 0;
143 1.1.2.1 itojun }
144 1.1.2.1 itojun
145 1.1.2.1 itojun /*
146 1.1.2.2 itojun * Find first ifid on list of interfaces.
147 1.1.2.2 itojun * This is assumed that ifp0's interface token (for example, IEEE802 MAC)
148 1.1.2.2 itojun * is globally unique. We may need to have a flag parameter in the future.
149 1.1.2.1 itojun */
150 1.1.2.1 itojun int
151 1.1.2.1 itojun in6_ifattach_getifid(ifp0)
152 1.1.2.1 itojun struct ifnet *ifp0;
153 1.1.2.1 itojun {
154 1.1.2.1 itojun struct ifnet *ifp;
155 1.1.2.1 itojun struct ifaddr *ifa;
156 1.1.2.1 itojun u_int8_t *addr = NULL;
157 1.1.2.1 itojun int addrlen = 0;
158 1.1.2.1 itojun struct sockaddr_dl *sdl;
159 1.1.2.1 itojun
160 1.1.2.1 itojun if (found_first_ifid)
161 1.1.2.1 itojun return 0;
162 1.1.2.1 itojun
163 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
164 1.1.2.2 itojun for (ifp = ifnet; ifp; ifp = ifp->if_next)
165 1.1.2.2 itojun #else
166 1.1.2.2 itojun for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
167 1.1.2.2 itojun #endif
168 1.1.2.2 itojun {
169 1.1.2.1 itojun if (ifp0 != NULL && ifp0 != ifp)
170 1.1.2.1 itojun continue;
171 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
172 1.1.2.2 itojun for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
173 1.1.2.2 itojun #else
174 1.1.2.1 itojun for (ifa = ifp->if_addrlist.tqh_first;
175 1.1.2.1 itojun ifa;
176 1.1.2.2 itojun ifa = ifa->ifa_list.tqe_next)
177 1.1.2.2 itojun #endif
178 1.1.2.2 itojun {
179 1.1.2.1 itojun if (ifa->ifa_addr->sa_family != AF_LINK)
180 1.1.2.1 itojun continue;
181 1.1.2.1 itojun sdl = (struct sockaddr_dl *)ifa->ifa_addr;
182 1.1.2.1 itojun if (sdl == NULL)
183 1.1.2.1 itojun continue;
184 1.1.2.1 itojun if (sdl->sdl_alen == 0)
185 1.1.2.1 itojun continue;
186 1.1.2.1 itojun switch (ifp->if_type) {
187 1.1.2.1 itojun case IFT_ETHER:
188 1.1.2.1 itojun case IFT_FDDI:
189 1.1.2.1 itojun case IFT_ATM:
190 1.1.2.2 itojun /* IEEE802/EUI64 cases - what others? */
191 1.1.2.1 itojun addr = LLADDR(sdl);
192 1.1.2.1 itojun addrlen = sdl->sdl_alen;
193 1.1.2.2 itojun /*
194 1.1.2.2 itojun * to copy ifid from IEEE802/EUI64 interface,
195 1.1.2.2 itojun * u bit of the source needs to be 0.
196 1.1.2.2 itojun */
197 1.1.2.2 itojun if ((addr[0] & 0x02) != 0)
198 1.1.2.2 itojun break;
199 1.1.2.1 itojun goto found;
200 1.1.2.2 itojun case IFT_ARCNET:
201 1.1.2.2 itojun /*
202 1.1.2.2 itojun * ARCnet interface token cannot be used as
203 1.1.2.2 itojun * globally unique identifier due to its
204 1.1.2.2 itojun * small bitwidth.
205 1.1.2.2 itojun */
206 1.1.2.2 itojun break;
207 1.1.2.1 itojun default:
208 1.1.2.1 itojun break;
209 1.1.2.1 itojun }
210 1.1.2.1 itojun }
211 1.1.2.1 itojun }
212 1.1.2.2 itojun #ifdef DEBUG
213 1.1.2.2 itojun printf("in6_ifattach_getifid: failed to get EUI64");
214 1.1.2.2 itojun #endif
215 1.1.2.1 itojun return EADDRNOTAVAIL;
216 1.1.2.1 itojun
217 1.1.2.1 itojun found:
218 1.1.2.2 itojun if (laddr_to_eui64(first_ifid, addr, addrlen) == 0)
219 1.1.2.1 itojun found_first_ifid = 1;
220 1.1.2.1 itojun
221 1.1.2.1 itojun if (found_first_ifid) {
222 1.1.2.2 itojun printf("%s: supplying EUI64: "
223 1.1.2.2 itojun "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
224 1.1.2.2 itojun if_name(ifp),
225 1.1.2.1 itojun first_ifid[0] & 0xff, first_ifid[1] & 0xff,
226 1.1.2.1 itojun first_ifid[2] & 0xff, first_ifid[3] & 0xff,
227 1.1.2.1 itojun first_ifid[4] & 0xff, first_ifid[5] & 0xff,
228 1.1.2.1 itojun first_ifid[6] & 0xff, first_ifid[7] & 0xff);
229 1.1.2.2 itojun
230 1.1.2.2 itojun /* invert u bit to convert EUI64 to RFC2373 interface ID. */
231 1.1.2.2 itojun first_ifid[0] ^= 0x02;
232 1.1.2.2 itojun
233 1.1.2.1 itojun return 0;
234 1.1.2.1 itojun } else {
235 1.1.2.2 itojun #ifdef DEBUG
236 1.1.2.2 itojun printf("in6_ifattach_getifid: failed to get EUI64");
237 1.1.2.2 itojun #endif
238 1.1.2.1 itojun return EADDRNOTAVAIL;
239 1.1.2.1 itojun }
240 1.1.2.1 itojun }
241 1.1.2.1 itojun
242 1.1.2.1 itojun /*
243 1.1.2.1 itojun * add link-local address to *pseudo* p2p interfaces.
244 1.1.2.1 itojun * get called when the first MAC address is made available in in6_ifattach().
245 1.1.2.2 itojun *
246 1.1.2.2 itojun * XXX I start considering this loop as a bad idea. (itojun)
247 1.1.2.1 itojun */
248 1.1.2.1 itojun void
249 1.1.2.1 itojun in6_ifattach_p2p()
250 1.1.2.1 itojun {
251 1.1.2.1 itojun struct ifnet *ifp;
252 1.1.2.1 itojun
253 1.1.2.1 itojun /* prevent infinite loop. just in case. */
254 1.1.2.2 itojun if (found_first_ifid == 0)
255 1.1.2.1 itojun return;
256 1.1.2.1 itojun
257 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
258 1.1.2.2 itojun for (ifp = ifnet; ifp; ifp = ifp->if_next)
259 1.1.2.2 itojun #else
260 1.1.2.2 itojun for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
261 1.1.2.2 itojun #endif
262 1.1.2.2 itojun {
263 1.1.2.1 itojun switch (ifp->if_type) {
264 1.1.2.1 itojun case IFT_GIF:
265 1.1.2.1 itojun /* pseudo interfaces - safe to initialize here */
266 1.1.2.1 itojun in6_ifattach(ifp, IN6_IFT_P2P, 0, 0);
267 1.1.2.1 itojun break;
268 1.1.2.2 itojun case IFT_DUMMY:
269 1.1.2.2 itojun case IFT_FAITH:
270 1.1.2.2 itojun /* this mistakingly becomes IFF_UP */
271 1.1.2.2 itojun break;
272 1.1.2.1 itojun case IFT_SLIP:
273 1.1.2.1 itojun /* IPv6 is not supported */
274 1.1.2.1 itojun break;
275 1.1.2.1 itojun case IFT_PPP:
276 1.1.2.1 itojun /* this is not a pseudo interface, skip it */
277 1.1.2.1 itojun break;
278 1.1.2.1 itojun default:
279 1.1.2.1 itojun break;
280 1.1.2.1 itojun }
281 1.1.2.1 itojun }
282 1.1.2.1 itojun }
283 1.1.2.1 itojun
284 1.1.2.1 itojun void
285 1.1.2.1 itojun in6_ifattach(ifp, type, laddr, noloop)
286 1.1.2.1 itojun struct ifnet *ifp;
287 1.1.2.1 itojun u_int type;
288 1.1.2.1 itojun caddr_t laddr;
289 1.1.2.2 itojun /* size_t laddrlen; */
290 1.1.2.1 itojun int noloop;
291 1.1.2.1 itojun {
292 1.1.2.1 itojun static size_t if_indexlim = 8;
293 1.1.2.1 itojun struct sockaddr_in6 mltaddr;
294 1.1.2.1 itojun struct sockaddr_in6 mltmask;
295 1.1.2.1 itojun struct sockaddr_in6 gate;
296 1.1.2.1 itojun struct sockaddr_in6 mask;
297 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
298 1.1.2.2 itojun struct ifaddr **ifap;
299 1.1.2.2 itojun #endif
300 1.1.2.1 itojun
301 1.1.2.1 itojun struct in6_ifaddr *ia, *ib, *oia;
302 1.1.2.1 itojun struct ifaddr *ifa;
303 1.1.2.1 itojun int rtflag = 0;
304 1.1.2.1 itojun
305 1.1.2.1 itojun if (type == IN6_IFT_P2P && found_first_ifid == 0) {
306 1.1.2.2 itojun printf("%s: no ifid available for IPv6 link-local address\n",
307 1.1.2.2 itojun if_name(ifp));
308 1.1.2.2 itojun #if 0
309 1.1.2.1 itojun return;
310 1.1.2.2 itojun #else
311 1.1.2.2 itojun /* last resort */
312 1.1.2.2 itojun if (gen_rand_eui64(first_ifid) == 0) {
313 1.1.2.2 itojun printf("%s: using random value as EUI64: "
314 1.1.2.2 itojun "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
315 1.1.2.2 itojun if_name(ifp),
316 1.1.2.2 itojun first_ifid[0] & 0xff, first_ifid[1] & 0xff,
317 1.1.2.2 itojun first_ifid[2] & 0xff, first_ifid[3] & 0xff,
318 1.1.2.2 itojun first_ifid[4] & 0xff, first_ifid[5] & 0xff,
319 1.1.2.2 itojun first_ifid[6] & 0xff, first_ifid[7] & 0xff);
320 1.1.2.2 itojun /*
321 1.1.2.2 itojun * invert u bit to convert EUI64 to RFC2373 interface
322 1.1.2.2 itojun * ID.
323 1.1.2.2 itojun */
324 1.1.2.2 itojun first_ifid[0] ^= 0x02;
325 1.1.2.2 itojun
326 1.1.2.2 itojun found_first_ifid = 1;
327 1.1.2.2 itojun }
328 1.1.2.2 itojun #endif
329 1.1.2.1 itojun }
330 1.1.2.1 itojun
331 1.1.2.1 itojun if ((ifp->if_flags & IFF_MULTICAST) == 0) {
332 1.1.2.2 itojun printf("%s: not multicast capable, IPv6 not enabled\n",
333 1.1.2.2 itojun if_name(ifp));
334 1.1.2.1 itojun return;
335 1.1.2.1 itojun }
336 1.1.2.2 itojun
337 1.1.2.1 itojun /*
338 1.1.2.1 itojun * We have some arrays that should be indexed by if_index.
339 1.1.2.1 itojun * since if_index will grow dynamically, they should grow too.
340 1.1.2.2 itojun * struct in6_ifstat **in6_ifstat
341 1.1.2.2 itojun * struct icmp6_ifstat **icmp6_ifstat
342 1.1.2.1 itojun */
343 1.1.2.2 itojun if (in6_ifstat == NULL || icmp6_ifstat == NULL
344 1.1.2.2 itojun || if_index >= if_indexlim) {
345 1.1.2.1 itojun size_t n;
346 1.1.2.1 itojun caddr_t q;
347 1.1.2.2 itojun size_t olim;
348 1.1.2.1 itojun
349 1.1.2.2 itojun olim = if_indexlim;
350 1.1.2.2 itojun while (if_index >= if_indexlim)
351 1.1.2.1 itojun if_indexlim <<= 1;
352 1.1.2.1 itojun
353 1.1.2.2 itojun /* grow in6_ifstat */
354 1.1.2.2 itojun n = if_indexlim * sizeof(struct in6_ifstat *);
355 1.1.2.2 itojun q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
356 1.1.2.2 itojun bzero(q, n);
357 1.1.2.2 itojun if (in6_ifstat) {
358 1.1.2.2 itojun bcopy((caddr_t)in6_ifstat, q,
359 1.1.2.2 itojun olim * sizeof(struct in6_ifstat *));
360 1.1.2.2 itojun free((caddr_t)in6_ifstat, M_IFADDR);
361 1.1.2.2 itojun }
362 1.1.2.2 itojun in6_ifstat = (struct in6_ifstat **)q;
363 1.1.2.2 itojun in6_ifstatmax = if_indexlim;
364 1.1.2.2 itojun
365 1.1.2.2 itojun /* grow icmp6_ifstat */
366 1.1.2.2 itojun n = if_indexlim * sizeof(struct icmp6_ifstat *);
367 1.1.2.1 itojun q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
368 1.1.2.1 itojun bzero(q, n);
369 1.1.2.2 itojun if (icmp6_ifstat) {
370 1.1.2.2 itojun bcopy((caddr_t)icmp6_ifstat, q,
371 1.1.2.2 itojun olim * sizeof(struct icmp6_ifstat *));
372 1.1.2.2 itojun free((caddr_t)icmp6_ifstat, M_IFADDR);
373 1.1.2.1 itojun }
374 1.1.2.2 itojun icmp6_ifstat = (struct icmp6_ifstat **)q;
375 1.1.2.2 itojun icmp6_ifstatmax = if_indexlim;
376 1.1.2.1 itojun }
377 1.1.2.1 itojun
378 1.1.2.1 itojun /*
379 1.1.2.1 itojun * To prevent to assign link-local address to PnP network
380 1.1.2.1 itojun * cards multiple times.
381 1.1.2.1 itojun * This is lengthy for P2P and LOOP but works.
382 1.1.2.1 itojun */
383 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
384 1.1.2.2 itojun ifa = ifp->if_addrlist;
385 1.1.2.2 itojun if (ifa != NULL) {
386 1.1.2.2 itojun for ( ; ifa; ifa = ifa->ifa_next) {
387 1.1.2.2 itojun ifap = &ifa->ifa_next;
388 1.1.2.2 itojun if (ifa->ifa_addr->sa_family != AF_INET6)
389 1.1.2.2 itojun continue;
390 1.1.2.2 itojun if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr))
391 1.1.2.2 itojun return;
392 1.1.2.2 itojun }
393 1.1.2.2 itojun } else
394 1.1.2.2 itojun ifap = &ifp->if_addrlist;
395 1.1.2.2 itojun #else
396 1.1.2.1 itojun ifa = TAILQ_FIRST(&ifp->if_addrlist);
397 1.1.2.1 itojun if (ifa != NULL) {
398 1.1.2.1 itojun for ( ; ifa; ifa = TAILQ_NEXT(ifa, ifa_list)) {
399 1.1.2.1 itojun if (ifa->ifa_addr->sa_family != AF_INET6)
400 1.1.2.1 itojun continue;
401 1.1.2.1 itojun if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr))
402 1.1.2.1 itojun return;
403 1.1.2.1 itojun }
404 1.1.2.2 itojun } else {
405 1.1.2.1 itojun TAILQ_INIT(&ifp->if_addrlist);
406 1.1.2.2 itojun }
407 1.1.2.2 itojun #endif
408 1.1.2.1 itojun
409 1.1.2.1 itojun /*
410 1.1.2.1 itojun * link-local address
411 1.1.2.1 itojun */
412 1.1.2.1 itojun ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
413 1.1.2.1 itojun bzero((caddr_t)ia, sizeof(*ia));
414 1.1.2.1 itojun ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
415 1.1.2.1 itojun ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
416 1.1.2.1 itojun ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
417 1.1.2.1 itojun ia->ia_ifp = ifp;
418 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
419 1.1.2.2 itojun *ifap = (struct ifaddr *)ia;
420 1.1.2.2 itojun #else
421 1.1.2.1 itojun TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
422 1.1.2.2 itojun #endif
423 1.1.2.1 itojun /*
424 1.1.2.1 itojun * Also link into the IPv6 address chain beginning with in6_ifaddr.
425 1.1.2.1 itojun * kazu opposed it, but itojun & jinmei wanted.
426 1.1.2.1 itojun */
427 1.1.2.1 itojun if ((oia = in6_ifaddr) != NULL) {
428 1.1.2.1 itojun for (; oia->ia_next; oia = oia->ia_next)
429 1.1.2.1 itojun continue;
430 1.1.2.1 itojun oia->ia_next = ia;
431 1.1.2.1 itojun } else
432 1.1.2.1 itojun in6_ifaddr = ia;
433 1.1.2.1 itojun
434 1.1.2.1 itojun ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
435 1.1.2.1 itojun ia->ia_prefixmask.sin6_family = AF_INET6;
436 1.1.2.1 itojun ia->ia_prefixmask.sin6_addr = in6mask64;
437 1.1.2.1 itojun
438 1.1.2.1 itojun bzero(&ia->ia_addr, sizeof(struct sockaddr_in6));
439 1.1.2.1 itojun ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
440 1.1.2.1 itojun ia->ia_addr.sin6_family = AF_INET6;
441 1.1.2.1 itojun ia->ia_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
442 1.1.2.1 itojun ia->ia_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
443 1.1.2.1 itojun ia->ia_addr.sin6_addr.s6_addr32[1] = 0;
444 1.1.2.1 itojun
445 1.1.2.1 itojun switch (type) {
446 1.1.2.1 itojun case IN6_IFT_LOOP:
447 1.1.2.1 itojun ia->ia_addr.sin6_addr.s6_addr32[2] = 0;
448 1.1.2.1 itojun ia->ia_addr.sin6_addr.s6_addr32[3] = htonl(1);
449 1.1.2.1 itojun break;
450 1.1.2.1 itojun case IN6_IFT_802:
451 1.1.2.1 itojun ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
452 1.1.2.1 itojun ia->ia_ifa.ifa_flags |= RTF_CLONING;
453 1.1.2.1 itojun rtflag = RTF_CLONING;
454 1.1.2.1 itojun /* fall through */
455 1.1.2.1 itojun case IN6_IFT_P2P802:
456 1.1.2.1 itojun if (laddr == NULL)
457 1.1.2.1 itojun break;
458 1.1.2.2 itojun /* XXX use laddrlen */
459 1.1.2.2 itojun if (laddr_to_eui64(&ia->ia_addr.sin6_addr.s6_addr8[8],
460 1.1.2.2 itojun laddr, 6) != 0) {
461 1.1.2.2 itojun break;
462 1.1.2.2 itojun }
463 1.1.2.2 itojun /* invert u bit to convert EUI64 to RFC2373 interface ID. */
464 1.1.2.2 itojun ia->ia_addr.sin6_addr.s6_addr8[8] ^= 0x02;
465 1.1.2.2 itojun if (found_first_ifid == 0) {
466 1.1.2.1 itojun if (in6_ifattach_getifid(ifp) == 0)
467 1.1.2.1 itojun in6_ifattach_p2p();
468 1.1.2.1 itojun }
469 1.1.2.1 itojun break;
470 1.1.2.1 itojun case IN6_IFT_P2P:
471 1.1.2.1 itojun bcopy((caddr_t)first_ifid,
472 1.1.2.1 itojun (caddr_t)&ia->ia_addr.sin6_addr.s6_addr8[8],
473 1.1.2.1 itojun IFID_LEN);
474 1.1.2.1 itojun break;
475 1.1.2.2 itojun case IN6_IFT_ARCNET:
476 1.1.2.2 itojun ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
477 1.1.2.2 itojun ia->ia_ifa.ifa_flags |= RTF_CLONING;
478 1.1.2.2 itojun rtflag = RTF_CLONING;
479 1.1.2.2 itojun if (laddr == NULL)
480 1.1.2.2 itojun break;
481 1.1.2.2 itojun
482 1.1.2.2 itojun /* make non-global IF id out of link-level address */
483 1.1.2.2 itojun bzero(&ia->ia_addr.sin6_addr.s6_addr8[8], 7);
484 1.1.2.2 itojun ia->ia_addr.sin6_addr.s6_addr8[15] = *laddr;
485 1.1.2.1 itojun }
486 1.1.2.1 itojun
487 1.1.2.1 itojun ia->ia_ifa.ifa_metric = ifp->if_metric;
488 1.1.2.1 itojun
489 1.1.2.1 itojun if (ifp->if_ioctl != NULL) {
490 1.1.2.1 itojun int s;
491 1.1.2.1 itojun int error;
492 1.1.2.1 itojun
493 1.1.2.1 itojun /*
494 1.1.2.1 itojun * give the interface a chance to initialize, in case this
495 1.1.2.1 itojun * is the first address to be added.
496 1.1.2.1 itojun */
497 1.1.2.1 itojun s = splimp();
498 1.1.2.1 itojun error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
499 1.1.2.1 itojun splx(s);
500 1.1.2.1 itojun
501 1.1.2.1 itojun if (error) {
502 1.1.2.1 itojun switch (error) {
503 1.1.2.1 itojun case EAFNOSUPPORT:
504 1.1.2.2 itojun printf("%s: IPv6 not supported\n",
505 1.1.2.2 itojun if_name(ifp));
506 1.1.2.1 itojun break;
507 1.1.2.1 itojun default:
508 1.1.2.2 itojun printf("%s: SIOCSIFADDR error %d\n",
509 1.1.2.2 itojun if_name(ifp), error);
510 1.1.2.1 itojun break;
511 1.1.2.1 itojun }
512 1.1.2.1 itojun
513 1.1.2.1 itojun /* undo changes */
514 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
515 1.1.2.2 itojun *ifap = NULL;
516 1.1.2.2 itojun #else
517 1.1.2.1 itojun TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
518 1.1.2.2 itojun #endif
519 1.1.2.1 itojun if (oia)
520 1.1.2.1 itojun oia->ia_next = ia->ia_next;
521 1.1.2.1 itojun else
522 1.1.2.1 itojun in6_ifaddr = ia->ia_next;
523 1.1.2.1 itojun free(ia, M_IFADDR);
524 1.1.2.1 itojun return;
525 1.1.2.1 itojun }
526 1.1.2.1 itojun }
527 1.1.2.1 itojun
528 1.1.2.1 itojun /* add route to the interface. */
529 1.1.2.1 itojun rtrequest(RTM_ADD,
530 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
531 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
532 1.1.2.1 itojun (struct sockaddr *)&ia->ia_prefixmask,
533 1.1.2.1 itojun RTF_UP|rtflag,
534 1.1.2.1 itojun (struct rtentry **)0);
535 1.1.2.1 itojun ia->ia_flags |= IFA_ROUTE;
536 1.1.2.1 itojun
537 1.1.2.1 itojun if (type == IN6_IFT_P2P || type == IN6_IFT_P2P802) {
538 1.1.2.1 itojun /*
539 1.1.2.1 itojun * route local address to loopback
540 1.1.2.1 itojun */
541 1.1.2.1 itojun bzero(&gate, sizeof(gate));
542 1.1.2.1 itojun gate.sin6_len = sizeof(struct sockaddr_in6);
543 1.1.2.1 itojun gate.sin6_family = AF_INET6;
544 1.1.2.1 itojun gate.sin6_addr = in6addr_loopback;
545 1.1.2.1 itojun bzero(&mask, sizeof(mask));
546 1.1.2.1 itojun mask.sin6_len = sizeof(struct sockaddr_in6);
547 1.1.2.1 itojun mask.sin6_family = AF_INET6;
548 1.1.2.1 itojun mask.sin6_addr = in6mask64;
549 1.1.2.1 itojun rtrequest(RTM_ADD,
550 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
551 1.1.2.1 itojun (struct sockaddr *)&gate,
552 1.1.2.1 itojun (struct sockaddr *)&mask,
553 1.1.2.1 itojun RTF_UP|RTF_HOST,
554 1.1.2.1 itojun (struct rtentry **)0);
555 1.1.2.1 itojun }
556 1.1.2.1 itojun
557 1.1.2.1 itojun /*
558 1.1.2.1 itojun * loopback address
559 1.1.2.1 itojun */
560 1.1.2.1 itojun ib = (struct in6_ifaddr *)NULL;
561 1.1.2.1 itojun if (type == IN6_IFT_LOOP) {
562 1.1.2.1 itojun ib = (struct in6_ifaddr *)
563 1.1.2.1 itojun malloc(sizeof(*ib), M_IFADDR, M_WAITOK);
564 1.1.2.1 itojun bzero((caddr_t)ib, sizeof(*ib));
565 1.1.2.1 itojun ib->ia_ifa.ifa_addr = (struct sockaddr *)&ib->ia_addr;
566 1.1.2.1 itojun ib->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ib->ia_dstaddr;
567 1.1.2.1 itojun ib->ia_ifa.ifa_netmask = (struct sockaddr *)&ib->ia_prefixmask;
568 1.1.2.1 itojun ib->ia_ifp = ifp;
569 1.1.2.1 itojun
570 1.1.2.1 itojun ia->ia_next = ib;
571 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
572 1.1.2.2 itojun ia->ia_ifa.ifa_next = (struct ifaddr *)ib;
573 1.1.2.2 itojun #else
574 1.1.2.1 itojun TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ib,
575 1.1.2.1 itojun ifa_list);
576 1.1.2.2 itojun #endif
577 1.1.2.1 itojun
578 1.1.2.1 itojun ib->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
579 1.1.2.1 itojun ib->ia_prefixmask.sin6_family = AF_INET6;
580 1.1.2.1 itojun ib->ia_prefixmask.sin6_addr = in6mask128;
581 1.1.2.1 itojun ib->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
582 1.1.2.1 itojun ib->ia_addr.sin6_family = AF_INET6;
583 1.1.2.1 itojun ib->ia_addr.sin6_addr = in6addr_loopback;
584 1.1.2.1 itojun #ifdef __bsdi__
585 1.1.2.1 itojun /*
586 1.1.2.1 itojun * It is necessary to set the loopback address to the dstaddr
587 1.1.2.1 itojun * field at least for BSDI. Without this setting, the BSDI
588 1.1.2.1 itojun * version of ifa_ifwithroute() rejects to add a route
589 1.1.2.1 itojun * to the loopback interface.
590 1.1.2.1 itojun */
591 1.1.2.1 itojun ib->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
592 1.1.2.1 itojun ib->ia_dstaddr.sin6_family = AF_INET6;
593 1.1.2.1 itojun ib->ia_dstaddr.sin6_addr = in6addr_loopback;
594 1.1.2.1 itojun #endif /* __bsdi__ */
595 1.1.2.1 itojun
596 1.1.2.1 itojun ib->ia_ifa.ifa_metric = ifp->if_metric;
597 1.1.2.1 itojun
598 1.1.2.1 itojun rtrequest(RTM_ADD,
599 1.1.2.1 itojun (struct sockaddr *)&ib->ia_addr,
600 1.1.2.1 itojun (struct sockaddr *)&ib->ia_addr,
601 1.1.2.1 itojun (struct sockaddr *)&ib->ia_prefixmask,
602 1.1.2.1 itojun RTF_UP|RTF_HOST,
603 1.1.2.1 itojun (struct rtentry **)0);
604 1.1.2.1 itojun
605 1.1.2.1 itojun ib->ia_flags |= IFA_ROUTE;
606 1.1.2.1 itojun }
607 1.1.2.1 itojun
608 1.1.2.1 itojun /*
609 1.1.2.1 itojun * join multicast
610 1.1.2.1 itojun */
611 1.1.2.1 itojun if (ifp->if_flags & IFF_MULTICAST) {
612 1.1.2.1 itojun int error; /* not used */
613 1.1.2.1 itojun
614 1.1.2.2 itojun #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
615 1.1.2.1 itojun /* Restore saved multicast addresses(if any). */
616 1.1.2.1 itojun in6_restoremkludge(ia, ifp);
617 1.1.2.1 itojun #endif
618 1.1.2.1 itojun
619 1.1.2.1 itojun bzero(&mltmask, sizeof(mltmask));
620 1.1.2.1 itojun mltmask.sin6_len = sizeof(struct sockaddr_in6);
621 1.1.2.1 itojun mltmask.sin6_family = AF_INET6;
622 1.1.2.1 itojun mltmask.sin6_addr = in6mask32;
623 1.1.2.1 itojun
624 1.1.2.1 itojun /*
625 1.1.2.1 itojun * join link-local all-nodes address
626 1.1.2.1 itojun */
627 1.1.2.1 itojun bzero(&mltaddr, sizeof(mltaddr));
628 1.1.2.1 itojun mltaddr.sin6_len = sizeof(struct sockaddr_in6);
629 1.1.2.1 itojun mltaddr.sin6_family = AF_INET6;
630 1.1.2.1 itojun mltaddr.sin6_addr = in6addr_linklocal_allnodes;
631 1.1.2.1 itojun mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
632 1.1.2.1 itojun rtrequest(RTM_ADD,
633 1.1.2.1 itojun (struct sockaddr *)&mltaddr,
634 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
635 1.1.2.1 itojun (struct sockaddr *)&mltmask,
636 1.1.2.1 itojun RTF_UP|RTF_CLONING, /* xxx */
637 1.1.2.1 itojun (struct rtentry **)0);
638 1.1.2.1 itojun (void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
639 1.1.2.1 itojun
640 1.1.2.1 itojun if (type == IN6_IFT_LOOP) {
641 1.1.2.1 itojun /*
642 1.1.2.1 itojun * join node-local all-nodes address
643 1.1.2.1 itojun */
644 1.1.2.1 itojun mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
645 1.1.2.1 itojun rtrequest(RTM_ADD,
646 1.1.2.1 itojun (struct sockaddr *)&mltaddr,
647 1.1.2.1 itojun (struct sockaddr *)&ib->ia_addr,
648 1.1.2.1 itojun (struct sockaddr *)&mltmask,
649 1.1.2.1 itojun RTF_UP,
650 1.1.2.1 itojun (struct rtentry **)0);
651 1.1.2.1 itojun (void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
652 1.1.2.1 itojun } else {
653 1.1.2.1 itojun /*
654 1.1.2.1 itojun * join solicited multicast address
655 1.1.2.1 itojun */
656 1.1.2.1 itojun bzero(&llsol, sizeof(llsol));
657 1.1.2.1 itojun llsol.s6_addr16[0] = htons(0xff02);
658 1.1.2.1 itojun llsol.s6_addr16[1] = htons(ifp->if_index);
659 1.1.2.1 itojun llsol.s6_addr32[1] = 0;
660 1.1.2.1 itojun llsol.s6_addr32[2] = htonl(1);
661 1.1.2.1 itojun llsol.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
662 1.1.2.1 itojun llsol.s6_addr8[12] = 0xff;
663 1.1.2.1 itojun (void)in6_addmulti(&llsol, ifp, &error);
664 1.1.2.1 itojun }
665 1.1.2.1 itojun }
666 1.1.2.1 itojun
667 1.1.2.1 itojun /* update dynamically. */
668 1.1.2.1 itojun if (in6_maxmtu < ifp->if_mtu)
669 1.1.2.1 itojun in6_maxmtu = ifp->if_mtu;
670 1.1.2.1 itojun
671 1.1.2.2 itojun if (in6_ifstat[ifp->if_index] == NULL) {
672 1.1.2.2 itojun in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
673 1.1.2.2 itojun malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
674 1.1.2.2 itojun bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
675 1.1.2.2 itojun }
676 1.1.2.2 itojun if (icmp6_ifstat[ifp->if_index] == NULL) {
677 1.1.2.2 itojun icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
678 1.1.2.2 itojun malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
679 1.1.2.2 itojun bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
680 1.1.2.2 itojun }
681 1.1.2.2 itojun
682 1.1.2.1 itojun /* initialize NDP variables */
683 1.1.2.1 itojun nd6_ifattach(ifp);
684 1.1.2.1 itojun
685 1.1.2.1 itojun /* mark the address TENTATIVE, if needed. */
686 1.1.2.1 itojun switch (ifp->if_type) {
687 1.1.2.2 itojun case IFT_ARCNET:
688 1.1.2.1 itojun case IFT_ETHER:
689 1.1.2.1 itojun case IFT_FDDI:
690 1.1.2.1 itojun #if 0
691 1.1.2.1 itojun case IFT_ATM:
692 1.1.2.1 itojun case IFT_SLIP:
693 1.1.2.1 itojun case IFT_PPP:
694 1.1.2.1 itojun #endif
695 1.1.2.1 itojun ia->ia6_flags |= IN6_IFF_TENTATIVE;
696 1.1.2.1 itojun /* nd6_dad_start() will be called in in6_if_up */
697 1.1.2.1 itojun break;
698 1.1.2.1 itojun case IFT_DUMMY:
699 1.1.2.2 itojun case IFT_GIF: /*XXX*/
700 1.1.2.1 itojun case IFT_LOOP:
701 1.1.2.1 itojun case IFT_FAITH:
702 1.1.2.1 itojun default:
703 1.1.2.1 itojun break;
704 1.1.2.1 itojun }
705 1.1.2.1 itojun
706 1.1.2.1 itojun return;
707 1.1.2.1 itojun }
708 1.1.2.1 itojun
709 1.1.2.1 itojun void
710 1.1.2.1 itojun in6_ifdetach(ifp)
711 1.1.2.1 itojun struct ifnet *ifp;
712 1.1.2.1 itojun {
713 1.1.2.1 itojun struct in6_ifaddr *ia, *oia;
714 1.1.2.1 itojun struct ifaddr *ifa;
715 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
716 1.1.2.2 itojun struct ifaddr *ifaprev = NULL;
717 1.1.2.2 itojun #endif
718 1.1.2.1 itojun struct rtentry *rt;
719 1.1.2.1 itojun short rtflags;
720 1.1.2.1 itojun
721 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
722 1.1.2.2 itojun for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
723 1.1.2.2 itojun #else
724 1.1.2.2 itojun for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
725 1.1.2.2 itojun #endif
726 1.1.2.2 itojun {
727 1.1.2.1 itojun if (ifa->ifa_addr->sa_family != AF_INET6
728 1.1.2.1 itojun || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
729 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
730 1.1.2.2 itojun ifaprev = ifa;
731 1.1.2.2 itojun #endif
732 1.1.2.1 itojun continue;
733 1.1.2.1 itojun }
734 1.1.2.1 itojun
735 1.1.2.1 itojun ia = (struct in6_ifaddr *)ifa;
736 1.1.2.1 itojun
737 1.1.2.1 itojun /* remove from the routing table */
738 1.1.2.1 itojun if ((ia->ia_flags & IFA_ROUTE)
739 1.1.2.2 itojun && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0
740 1.1.2.2 itojun #ifdef __FreeBSD__
741 1.1.2.2 itojun , 0UL
742 1.1.2.2 itojun #endif
743 1.1.2.2 itojun ))) {
744 1.1.2.1 itojun rtflags = rt->rt_flags;
745 1.1.2.1 itojun rtfree(rt);
746 1.1.2.1 itojun rtrequest(RTM_DELETE,
747 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
748 1.1.2.1 itojun (struct sockaddr *)&ia->ia_addr,
749 1.1.2.1 itojun (struct sockaddr *)&ia->ia_prefixmask,
750 1.1.2.1 itojun rtflags, (struct rtentry **)0);
751 1.1.2.1 itojun }
752 1.1.2.1 itojun
753 1.1.2.1 itojun /* remove from the linked list */
754 1.1.2.2 itojun #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
755 1.1.2.2 itojun if (ifaprev)
756 1.1.2.2 itojun ifaprev->ifa_next = ifa->ifa_next;
757 1.1.2.2 itojun else
758 1.1.2.2 itojun ifp->if_addrlist = ifa->ifa_next;
759 1.1.2.2 itojun #else
760 1.1.2.1 itojun TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
761 1.1.2.2 itojun #endif
762 1.1.2.1 itojun
763 1.1.2.1 itojun /* also remove from the IPv6 address chain(itojun&jinmei) */
764 1.1.2.1 itojun oia = ia;
765 1.1.2.1 itojun if (oia == (ia = in6_ifaddr))
766 1.1.2.1 itojun in6_ifaddr = ia->ia_next;
767 1.1.2.1 itojun else {
768 1.1.2.1 itojun while (ia->ia_next && (ia->ia_next != oia))
769 1.1.2.1 itojun ia = ia->ia_next;
770 1.1.2.1 itojun if (ia->ia_next)
771 1.1.2.1 itojun ia->ia_next = oia->ia_next;
772 1.1.2.2 itojun #ifdef DEBUG
773 1.1.2.1 itojun else
774 1.1.2.2 itojun printf("%s: didn't unlink in6ifaddr from "
775 1.1.2.2 itojun "list\n", if_name(ifp));
776 1.1.2.2 itojun #endif
777 1.1.2.1 itojun }
778 1.1.2.1 itojun
779 1.1.2.1 itojun free(ia, M_IFADDR);
780 1.1.2.1 itojun }
781 1.1.2.1 itojun }
782