]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/in6.c
ab8b787e43e29452e3e6678e63d88cc046ac2c94
[apple/xnu.git] / bsd / netinet6 / in6.c
1 /* $KAME: in6.c,v 1.72 2000/03/30 03:45:26 itojun Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1982, 1986, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)in.c 8.2 (Berkeley) 11/15/93
65 */
66
67 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
68 #include "opt_inet.h"
69 #endif
70
71 #include <sys/param.h>
72 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
73 #include <sys/ioctl.h>
74 #endif
75 #include <sys/errno.h>
76 #include <sys/malloc.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/sockio.h>
80 #include <sys/systm.h>
81 #include <sys/time.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84
85 #include <net/if.h>
86 #include <net/if_types.h>
87 #include <net/route.h>
88 #include "gif.h"
89 #if NGIF > 0
90 #include <net/if_gif.h>
91 #endif
92 #include <net/if_dl.h>
93
94 #include <netinet/in.h>
95 #include <netinet/in_var.h>
96 #if __NetBSD__
97 #include <net/if_ether.h>
98 #else
99 #include <netinet/if_ether.h>
100 #endif
101
102 #include <netinet6/nd6.h>
103 #include <netinet/ip6.h>
104 #include <netinet6/ip6_var.h>
105 #include <netinet6/mld6_var.h>
106 #include <netinet6/ip6_mroute.h>
107 #include <netinet6/in6_ifattach.h>
108
109 #include <net/net_osdep.h>
110
111 #if MIP6
112 #include <netinet6/mip6.h>
113 #include <netinet6/mip6_common.h>
114
115 struct nd_prefix *(*mip6_get_home_prefix_hook) __P((void));
116 #endif /* MIP6 */
117
118 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
119 MALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
120 #endif
121
122 /*
123 * Definitions of some costant IP6 addresses.
124 */
125 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
126 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
127 const struct in6_addr in6addr_nodelocal_allnodes =
128 IN6ADDR_NODELOCAL_ALLNODES_INIT;
129 const struct in6_addr in6addr_linklocal_allnodes =
130 IN6ADDR_LINKLOCAL_ALLNODES_INIT;
131 const struct in6_addr in6addr_linklocal_allrouters =
132 IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
133
134 const struct in6_addr in6mask0 = IN6MASK0;
135 const struct in6_addr in6mask32 = IN6MASK32;
136 const struct in6_addr in6mask64 = IN6MASK64;
137 const struct in6_addr in6mask96 = IN6MASK96;
138 const struct in6_addr in6mask128 = IN6MASK128;
139
140 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
141 static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
142 struct ifnet *, struct proc *));
143 #else
144 static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
145 struct ifnet *));
146 #endif
147
148 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
149 struct in6_multihead in6_multihead; /* XXX BSS initialization */
150 #else
151 /*
152 * This structure is used to keep track of in6_multi chains which belong to
153 * deleted interface addresses.
154 */
155 static LIST_HEAD(, multi6_kludge) in6_mk; /* XXX BSS initialization */
156
157 struct multi6_kludge {
158 LIST_ENTRY(multi6_kludge) mk_entry;
159 struct ifnet *mk_ifp;
160 struct in6_multihead mk_head;
161 };
162 #endif
163
164 /*
165 * Check if the loopback entry will be automatically generated.
166 * if 0 returned, will not be automatically generated.
167 * if 1 returned, will be automatically generated.
168 */
169 static int
170 in6_is_ifloop_auto(struct ifaddr *ifa)
171 {
172 #define SIN6(s) ((struct sockaddr_in6 *)s)
173 /*
174 * If RTF_CLONING is unset, or (IFF_LOOPBACK | IFF_POINTOPOINT),
175 * or netmask is all0 or all1, then cloning will not happen,
176 * then we can't rely on its loopback entry generation.
177 */
178 if ((ifa->ifa_flags & RTF_CLONING) == 0 ||
179 (ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) ||
180 (SIN6(ifa->ifa_netmask)->sin6_len == sizeof(struct sockaddr_in6)
181 &&
182 IN6_ARE_ADDR_EQUAL(&SIN6(ifa->ifa_netmask)->sin6_addr,
183 &in6mask128)) ||
184 ((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_len == 0)
185 return 0;
186 else
187 return 1;
188 #undef SIN6
189 }
190
191 /*
192 * Subroutine for in6_ifaddloop() and in6_ifremloop().
193 * This routine does actual work.
194 */
195 static void
196 in6_ifloop_request(int cmd, struct ifaddr *ifa)
197 {
198 struct sockaddr_in6 lo_sa;
199 struct sockaddr_in6 all1_sa;
200 struct rtentry *nrt = NULL;
201
202 bzero(&lo_sa, sizeof(lo_sa));
203 bzero(&all1_sa, sizeof(all1_sa));
204 lo_sa.sin6_family = AF_INET6;
205 lo_sa.sin6_len = sizeof(struct sockaddr_in6);
206 all1_sa = lo_sa;
207 lo_sa.sin6_addr = in6addr_loopback;
208 all1_sa.sin6_addr = in6mask128;
209
210 /* So we add or remove static loopback entry, here. */
211 rtrequest(cmd, ifa->ifa_addr,
212 (struct sockaddr *)&lo_sa,
213 (struct sockaddr *)&all1_sa,
214 RTF_UP|RTF_HOST, &nrt);
215
216 /*
217 * Make sure rt_ifa be equal to IFA, the second argument of the
218 * function.
219 * We need this because when we refer rt_ifa->ia6_flags in ip6_input,
220 * we assume that the rt_ifa points to the address instead of the
221 * loopback address.
222 */
223 if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
224 IFAFREE(nrt->rt_ifa);
225 ifa->ifa_refcnt++;
226 nrt->rt_ifa = ifa;
227 nrt->rt_dlt = ifa->ifa_dlt;
228 }
229 if (nrt)
230 nrt->rt_refcnt--;
231 }
232
233 /*
234 * Add ownaddr as loopback rtentry, if necessary(ex. on p2p link).
235 * Because, KAME needs loopback rtentry for ownaddr check in
236 * ip6_input().
237 */
238 static void
239 in6_ifaddloop(struct ifaddr *ifa)
240 {
241 if (!in6_is_ifloop_auto(ifa)) {
242 struct rtentry *rt;
243
244 /* If there is no loopback entry, allocate one. */
245 rt = rtalloc1(ifa->ifa_addr, 0
246 #if defined(__FreeBSD__) || defined (__APPLE__)
247 , 0
248 #endif /* __FreeBSD__ */
249 );
250 if (rt == 0 || (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
251 in6_ifloop_request(RTM_ADD, ifa);
252 if (rt)
253 rt->rt_refcnt--;
254 }
255 }
256
257 /*
258 * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
259 * if it exists.
260 */
261 static void
262 in6_ifremloop(struct ifaddr *ifa)
263 {
264 if (!in6_is_ifloop_auto(ifa)) {
265 struct in6_ifaddr *ia;
266 int ia_count = 0;
267
268 /* If only one ifa for the loopback entry, delete it. */
269 for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
270 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa),
271 &ia->ia_addr.sin6_addr)) {
272 ia_count++;
273 if (ia_count > 1)
274 break;
275 }
276 }
277 if (ia_count == 1)
278 in6_ifloop_request(RTM_DELETE, ifa);
279 }
280 }
281
282 int
283 in6_ifindex2scopeid(idx)
284 int idx;
285 {
286 struct ifnet *ifp;
287 struct ifaddr *ifa;
288 struct sockaddr_in6 *sin6;
289
290 if (idx < 0 || if_index < idx)
291 return -1;
292 ifp = ifindex2ifnet[idx];
293
294 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
295 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
296 #else
297 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
298 #endif
299 {
300 if (ifa->ifa_addr->sa_family != AF_INET6)
301 continue;
302 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
303 if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
304 return sin6->sin6_scope_id & 0xffff;
305 }
306
307 return -1;
308 }
309
310 int
311 in6_mask2len(mask)
312 struct in6_addr *mask;
313 {
314 int x, y;
315
316 for (x = 0; x < sizeof(*mask); x++) {
317 if (mask->s6_addr8[x] != 0xff)
318 break;
319 }
320 y = 0;
321 if (x < sizeof(*mask)) {
322 for (y = 0; y < 8; y++) {
323 if ((mask->s6_addr8[x] & (0x80 >> y)) == 0)
324 break;
325 }
326 }
327 return x * 8 + y;
328 }
329
330 void
331 in6_len2mask(mask, len)
332 struct in6_addr *mask;
333 int len;
334 {
335 int i;
336
337 bzero(mask, sizeof(*mask));
338 for (i = 0; i < len / 8; i++)
339 mask->s6_addr8[i] = 0xff;
340 if (len % 8)
341 mask->s6_addr8[i] = (0xff00 >> (len % 8)) & 0xff;
342 }
343
344 #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
345 #define ia62ifa(ia6) (&((ia6)->ia_ifa))
346
347 int
348 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
349 in6_control(so, cmd, data, ifp, p)
350 struct socket *so;
351 u_long cmd;
352 caddr_t data;
353 struct ifnet *ifp;
354 struct proc *p;
355 #else
356 in6_control(so, cmd, data, ifp)
357 struct socket *so;
358 u_long cmd;
359 caddr_t data;
360 struct ifnet *ifp;
361 #endif
362 {
363 struct in6_ifreq *ifr = (struct in6_ifreq *)data;
364 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
365 struct ifaddr *ifa;
366 #endif
367 struct in6_ifaddr *ia = NULL, *oia;
368 struct in6_aliasreq *ifra = (struct in6_aliasreq *)data;
369 struct sockaddr_in6 oldaddr;
370 #ifdef COMPAT_IN6IFIOCTL
371 struct sockaddr_in6 net;
372 #endif
373 int error = 0, hostIsNew, prefixIsNew;
374 int newifaddr;
375 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
376 time_t time_second = (time_t)time.tv_sec;
377 #endif
378 int privileged;
379 u_long dl_tag;
380
381 privileged = 0;
382 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
383 if (p && !suser(p->p_ucred, &p->p_acflag))
384 privileged++;
385 #else
386 if ((so->so_state & SS_PRIV) != 0)
387 privileged++;
388 #endif
389
390 /*
391 * xxx should prevent processes for link-local addresses?
392 */
393 #if NGIF > 0
394 if (ifp && ifp->if_type == IFT_GIF) {
395 switch (cmd) {
396 case SIOCSIFPHYADDR_IN6:
397 if (!privileged)
398 return(EPERM);
399 /*fall through*/
400 case SIOCGIFPSRCADDR_IN6:
401 case SIOCGIFPDSTADDR_IN6:
402 return gif_ioctl(ifp, cmd, data);
403 }
404 }
405 #endif
406 switch (cmd) {
407 case SIOCGETSGCNT_IN6:
408 case SIOCGETMIFCNT_IN6:
409 return (mrt6_ioctl(cmd, data));
410 }
411 #if MIP6
412 /* These require root privileges */
413 switch (cmd) {
414 case SIOCSDEBUG_MIP6:
415 case SIOCSBCFLUSH_MIP6:
416 case SIOCSDEFCONFIG_MIP6:
417 case SIOCSBRUPDATE_MIP6:
418 case SIOCSENABLEBR_MIP6:
419 case SIOCSATTACH_MIP6:
420 case SIOCSRELEASE_MIP6:
421
422 case SIOCSHALISTFLUSH_MIP6:
423 case SIOCSHAPREF_MIP6:
424 case SIOCSFWDSLUNICAST_MIP6:
425 case SIOCSFWDSLMULTICAST_MIP6:
426
427 case SIOCSFORADDRFLUSH_MIP6:
428 case SIOCSHADDRFLUSH_MIP6:
429 case SIOCSBULISTFLUSH_MIP6:
430 case SIOCACOADDR_MIP6:
431 case SIOCAHOMEADDR_MIP6:
432 case SIOCSBULIFETIME_MIP6:
433 case SIOCSHRLIFETIME_MIP6:
434 case SIOCDCOADDR_MIP6:
435 case SIOCSPROMMODE_MIP6:
436 case SIOCSBU2CN_MIP6:
437 case SIOCSREVTUNNEL_MIP6:
438 case SIOCSAUTOCONFIG_MIP6:
439 case SIOCSEAGERMD_MIP6:
440 if (!privileged)
441 return(EPERM);
442 /* Anyone can use these or the user is root */
443 /* case SIOCXVERYSAFECOMMAND_MIP6: */
444 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined(__APPLE__)
445 return mip6_ioctl(so, cmd, data, ifp, p);
446 #else
447 return mip6_ioctl(so, cmd, data, ifp);
448 #endif
449 }
450 #endif /* MIP6 */
451
452 if (ifp == NULL)
453 return(EOPNOTSUPP);
454
455 switch (cmd) {
456 case SIOCSNDFLUSH_IN6:
457 case SIOCSPFXFLUSH_IN6:
458 case SIOCSRTRFLUSH_IN6:
459 case SIOCSDEFIFACE_IN6:
460 case SIOCSIFINFO_FLAGS:
461 if (!privileged)
462 return(EPERM);
463 /*fall through*/
464 case SIOCGIFINFO_IN6:
465 case SIOCGDRLST_IN6:
466 case SIOCGPRLST_IN6:
467 case SIOCGNBRINFO_IN6:
468 case SIOCGDEFIFACE_IN6:
469 return(nd6_ioctl(cmd, data, ifp));
470 }
471
472 switch (cmd) {
473 case SIOCSIFPREFIX_IN6:
474 case SIOCDIFPREFIX_IN6:
475 case SIOCAIFPREFIX_IN6:
476 case SIOCCIFPREFIX_IN6:
477 case SIOCSGIFPREFIX_IN6:
478 if (!privileged)
479 return(EPERM);
480 /*fall through*/
481 case SIOCGIFPREFIX_IN6:
482 if (ip6_forwarding == 0)
483 return(EPERM);
484 return(in6_prefix_ioctl(so, cmd, data, ifp));
485 }
486
487 switch (cmd) {
488 case SIOCALIFADDR:
489 case SIOCDLIFADDR:
490 if (!privileged)
491 return(EPERM);
492 /*fall through*/
493 case SIOCGLIFADDR:
494 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
495 return in6_lifaddr_ioctl(so, cmd, data, ifp, p);
496 #else
497 return in6_lifaddr_ioctl(so, cmd, data, ifp);
498 #endif
499 }
500
501 /*
502 * Find address for this interface, if it exists.
503 */
504 if (ifra->ifra_addr.sin6_family == AF_INET6) { /* XXX */
505 struct sockaddr_in6 *sa6 =
506 (struct sockaddr_in6 *)&ifra->ifra_addr;
507
508 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
509 if (sa6->sin6_addr.s6_addr16[1] == 0) {
510 /* interface ID is not embedded by the user */
511 sa6->sin6_addr.s6_addr16[1] =
512 htons(ifp->if_index);
513 } else if (sa6->sin6_addr.s6_addr16[1] !=
514 htons(ifp->if_index)) {
515 return(EINVAL); /* ifid is contradict */
516 }
517 if (sa6->sin6_scope_id) {
518 if (sa6->sin6_scope_id !=
519 (u_int32_t)ifp->if_index)
520 return(EINVAL);
521 sa6->sin6_scope_id = 0; /* XXX: good way? */
522 }
523 }
524 ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
525 }
526
527 switch (cmd) {
528
529 case SIOCDIFADDR_IN6:
530 /*
531 * for IPv4, we look for existing in6_ifaddr here to allow
532 * "ifconfig if0 delete" to remove first IPv4 address on the
533 * interface. For IPv6, as the spec allow multiple interface
534 * address from the day one, we consider "remove the first one"
535 * semantics to be not preferrable.
536 */
537 if (ia == NULL)
538 return(EADDRNOTAVAIL);
539 /* FALLTHROUGH */
540 case SIOCAIFADDR_IN6:
541 case SIOCSIFADDR_IN6:
542 #if COMPAT_IN6IFIOCTL
543 case SIOCSIFDSTADDR_IN6:
544 case SIOCSIFNETMASK_IN6:
545 /*
546 * Since IPv6 allows a node to assign multiple addresses
547 * on a single interface, SIOCSIFxxx ioctls are not suitable
548 * and should be unused.
549 */
550 #endif
551 if (ifra->ifra_addr.sin6_family != AF_INET6)
552 return(EAFNOSUPPORT);
553 if (!privileged)
554 return(EPERM);
555 if (ia == NULL) {
556 ia = (struct in6_ifaddr *)
557 _MALLOC(sizeof(*ia), M_IFADDR, M_WAITOK);
558 if (ia == NULL)
559 return (ENOBUFS);
560 bzero((caddr_t)ia, sizeof(*ia));
561 /* Initialize the address and masks */
562 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
563 ia->ia_addr.sin6_family = AF_INET6;
564 ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
565 if (ifp->if_flags & IFF_POINTOPOINT) {
566 ia->ia_ifa.ifa_dstaddr
567 = (struct sockaddr *)&ia->ia_dstaddr;
568 ia->ia_dstaddr.sin6_family = AF_INET6;
569 ia->ia_dstaddr.sin6_len = sizeof(ia->ia_dstaddr);
570 } else {
571 ia->ia_ifa.ifa_dstaddr = NULL;
572 bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr));
573 }
574 ia->ia_ifa.ifa_netmask
575 = (struct sockaddr *)&ia->ia_prefixmask;
576
577 ia->ia_ifp = ifp;
578
579 printf("in6_control: Attach dl_tag for if=%s%n\n", ifp->if_name, ifp->if_unit);
580
581 if (strcmp(ifp->if_name, "en") == 0)
582 dl_tag = ether_attach_inet6(ifp);
583
584 if (strcmp(ifp->if_name, "lo") == 0)
585 dl_tag = lo_attach_inet(ifp);
586
587 if (strcmp(ifp->if_name, "gif") == 0)
588 dl_tag = gif_attach_inet(ifp);
589 /* End of temp code */
590 ia->ia_ifa.ifa_dlt = dl_tag;
591
592
593 if ((oia = in6_ifaddr) != NULL) {
594 for ( ; oia->ia_next; oia = oia->ia_next)
595 continue;
596 oia->ia_next = ia;
597 } else
598 in6_ifaddr = ia;
599 ia->ia_ifa.ifa_refcnt++;
600
601 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
602 if ((ifa = ifp->if_addrlist) != NULL) {
603 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
604 continue;
605 ifa->ifa_next = ia62ifa(ia);
606 } else
607 ifp->if_addrlist = ia62ifa(ia);
608 #else
609 TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
610 ifa_list);
611 #endif
612 ia->ia_ifa.ifa_refcnt++;
613
614 newifaddr = 1;
615 } else
616 newifaddr = 0;
617
618 if (cmd == SIOCAIFADDR_IN6) {
619 /* sanity for overflow - beware unsigned */
620 struct in6_addrlifetime *lt;
621 lt = &ifra->ifra_lifetime;
622 if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
623 && lt->ia6t_vltime + time_second < time_second) {
624 return EINVAL;
625 }
626 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
627 && lt->ia6t_pltime + time_second < time_second) {
628 return EINVAL;
629 }
630 }
631 break;
632
633 case SIOCGIFADDR_IN6:
634 /* This interface is basically deprecated. use SIOCGIFCONF. */
635 /* fall through */
636 case SIOCGIFAFLAG_IN6:
637 case SIOCGIFNETMASK_IN6:
638 case SIOCGIFDSTADDR_IN6:
639 case SIOCGIFALIFETIME_IN6:
640 /* must think again about its semantics */
641 if (ia == NULL)
642 return(EADDRNOTAVAIL);
643 break;
644 case SIOCSIFALIFETIME_IN6:
645 {
646 struct in6_addrlifetime *lt;
647
648 if (!privileged)
649 return(EPERM);
650 if (ia == NULL)
651 return(EADDRNOTAVAIL);
652 /* sanity for overflow - beware unsigned */
653 lt = &ifr->ifr_ifru.ifru_lifetime;
654 if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
655 && lt->ia6t_vltime + time_second < time_second) {
656 return EINVAL;
657 }
658 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
659 && lt->ia6t_pltime + time_second < time_second) {
660 return EINVAL;
661 }
662 break;
663 }
664 }
665
666 switch (cmd) {
667
668 case SIOCGIFADDR_IN6:
669 ifr->ifr_addr = ia->ia_addr;
670 break;
671
672 case SIOCGIFDSTADDR_IN6:
673 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
674 return(EINVAL);
675 ifr->ifr_dstaddr = ia->ia_dstaddr;
676 break;
677
678 case SIOCGIFNETMASK_IN6:
679 ifr->ifr_addr = ia->ia_prefixmask;
680 break;
681
682 case SIOCGIFAFLAG_IN6:
683 ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
684 break;
685
686 case SIOCGIFSTAT_IN6:
687 if (ifp == NULL)
688 return EINVAL;
689 if (in6_ifstat == NULL || ifp->if_index >= in6_ifstatmax
690 || in6_ifstat[ifp->if_index] == NULL) {
691 /* return EAFNOSUPPORT? */
692 bzero(&ifr->ifr_ifru.ifru_stat,
693 sizeof(ifr->ifr_ifru.ifru_stat));
694 } else
695 ifr->ifr_ifru.ifru_stat = *in6_ifstat[ifp->if_index];
696 break;
697
698 case SIOCGIFSTAT_ICMP6:
699 if (ifp == NULL)
700 return EINVAL;
701 if (icmp6_ifstat == NULL || ifp->if_index >= icmp6_ifstatmax ||
702 icmp6_ifstat[ifp->if_index] == NULL) {
703 /* return EAFNOSUPPORT? */
704 bzero(&ifr->ifr_ifru.ifru_stat,
705 sizeof(ifr->ifr_ifru.ifru_icmp6stat));
706 } else
707 ifr->ifr_ifru.ifru_icmp6stat =
708 *icmp6_ifstat[ifp->if_index];
709 break;
710 #if COMPAT_IN6IFIOCTL /* should be unused */
711 case SIOCSIFDSTADDR_IN6:
712 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
713 return(EINVAL);
714 oldaddr = ia->ia_dstaddr;
715 ia->ia_dstaddr = ifr->ifr_dstaddr;
716
717 /* link-local index check */
718 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
719 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
720 /* interface ID is not embedded by the user */
721 ia->ia_dstaddr.sin6_addr.s6_addr16[1]
722 = htons(ifp->if_index);
723 } else if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
724 htons(ifp->if_index)) {
725 ia->ia_dstaddr = oldaddr;
726 return(EINVAL); /* ifid is contradict */
727 }
728 }
729 #ifdef __APPLE__
730 error = dlil_ioctl(0, ifp, SIOCSIFDSTADDR, (caddr_t)ia);
731 if (error == EOPNOTSUPP)
732 error = 0;
733 if (error) {
734 ia->ia_dstaddr = oldaddr;
735 return(error);
736 }
737 #else
738 if (ifp->if_ioctl && (error = (ifp->if_ioctl)
739 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
740 #endif
741 if (ia->ia_flags & IFA_ROUTE) {
742 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
743 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
744 ia->ia_ifa.ifa_dstaddr =
745 (struct sockaddr *)&ia->ia_dstaddr;
746 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
747 }
748 break;
749
750 #endif
751 case SIOCGIFALIFETIME_IN6:
752 ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
753 break;
754
755 case SIOCSIFALIFETIME_IN6:
756 ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
757 /* for sanity */
758 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
759 ia->ia6_lifetime.ia6t_expire =
760 time_second + ia->ia6_lifetime.ia6t_vltime;
761 } else
762 ia->ia6_lifetime.ia6t_expire = 0;
763 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
764 ia->ia6_lifetime.ia6t_preferred =
765 time_second + ia->ia6_lifetime.ia6t_pltime;
766 } else
767 ia->ia6_lifetime.ia6t_preferred = 0;
768 break;
769
770 case SIOCSIFADDR_IN6:
771 error = in6_ifinit(ifp, ia, &ifr->ifr_addr, 1);
772 #if 0
773 /*
774 * the code chokes if we are to assign multiple addresses with
775 * the same address prefix (rtinit() will return EEXIST, which
776 * is not fatal actually). we will get memory leak if we
777 * don't do it.
778 * -> we may want to hide EEXIST from rtinit().
779 */
780 undo:
781 if (error && newifaddr) {
782 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
783 if ((ifa = ifp->if_addrlist) == ia62ifa(ia))
784 ifp->if_addrlist = ifa->ifa_next;
785 else {
786 while (ifa->ifa_next &&
787 (ifa->ifa_next != ia62ifa(ia)))
788 ifa = ifa->ifa_next;
789 if (ifa->ifa_next)
790 ifa->ifa_next = ia62ifa(ia)->ifa_next;
791 else {
792 printf("Couldn't unlink in6_ifaddr "
793 "from ifp\n");
794 }
795 }
796 #else
797 TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
798 #endif
799 IFAFREE(&ia->ia_ifa);
800
801 oia = ia;
802 if (oia == (ia = in6_ifaddr))
803 in6_ifaddr = ia->ia_next;
804 else {
805 while (ia->ia_next && (ia->ia_next != oia))
806 ia = ia->ia_next;
807 if (ia->ia_next)
808 ia->ia_next = oia->ia_next;
809 else {
810 printf("Didn't unlink in6_ifaddr "
811 "from list\n");
812 }
813 }
814 IFAFREE(&ia->ia_ifa);
815 }
816 #endif
817 return error;
818
819 #if COMPAT_IN6IFIOCTL /* XXX should be unused */
820 case SIOCSIFNETMASK_IN6:
821 ia->ia_prefixmask = ifr->ifr_addr;
822 bzero(&net, sizeof(net));
823 net.sin6_len = sizeof(struct sockaddr_in6);
824 net.sin6_family = AF_INET6;
825 net.sin6_port = htons(0);
826 net.sin6_flowinfo = htonl(0);
827 net.sin6_addr.s6_addr32[0]
828 = ia->ia_addr.sin6_addr.s6_addr32[0] &
829 ia->ia_prefixmask.sin6_addr.s6_addr32[0];
830 net.sin6_addr.s6_addr32[1]
831 = ia->ia_addr.sin6_addr.s6_addr32[1] &
832 ia->ia_prefixmask.sin6_addr.s6_addr32[1];
833 net.sin6_addr.s6_addr32[2]
834 = ia->ia_addr.sin6_addr.s6_addr32[2] &
835 ia->ia_prefixmask.sin6_addr.s6_addr32[2];
836 net.sin6_addr.s6_addr32[3]
837 = ia->ia_addr.sin6_addr.s6_addr32[3] &
838 ia->ia_prefixmask.sin6_addr.s6_addr32[3];
839 ia->ia_net = net;
840 break;
841 #endif
842
843 case SIOCAIFADDR_IN6:
844 prefixIsNew = 0;
845 hostIsNew = 1;
846
847 if (ifra->ifra_addr.sin6_len == 0) {
848 ifra->ifra_addr = ia->ia_addr;
849 hostIsNew = 0;
850 } else if (IN6_ARE_ADDR_EQUAL(&ifra->ifra_addr.sin6_addr,
851 &ia->ia_addr.sin6_addr))
852 hostIsNew = 0;
853
854 /* Validate address families: */
855 /*
856 * The destination address for a p2p link must have a family
857 * of AF_UNSPEC or AF_INET6.
858 */
859 if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
860 ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
861 ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
862 return(EAFNOSUPPORT);
863 /*
864 * The prefixmask must have a family of AF_UNSPEC or AF_INET6.
865 */
866 if (ifra->ifra_prefixmask.sin6_family != AF_INET6 &&
867 ifra->ifra_prefixmask.sin6_family != AF_UNSPEC)
868 return(EAFNOSUPPORT);
869
870 if (ifra->ifra_prefixmask.sin6_len) {
871 in6_ifscrub(ifp, ia);
872 ia->ia_prefixmask = ifra->ifra_prefixmask;
873 prefixIsNew = 1;
874 }
875 if ((ifp->if_flags & IFF_POINTOPOINT) &&
876 (ifra->ifra_dstaddr.sin6_family == AF_INET6)) {
877 in6_ifscrub(ifp, ia);
878 oldaddr = ia->ia_dstaddr;
879 ia->ia_dstaddr = ifra->ifra_dstaddr;
880 /* link-local index check: should be a separate function? */
881 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
882 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
883 /*
884 * interface ID is not embedded by
885 * the user
886 */
887 ia->ia_dstaddr.sin6_addr.s6_addr16[1]
888 = htons(ifp->if_index);
889 } else if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
890 htons(ifp->if_index)) {
891 ia->ia_dstaddr = oldaddr;
892 return(EINVAL); /* ifid is contradict */
893 }
894 }
895 prefixIsNew = 1; /* We lie; but effect's the same */
896 }
897 if (hostIsNew || prefixIsNew) {
898 error = in6_ifinit(ifp, ia, &ifra->ifra_addr, 0);
899 #if 0
900 if (error)
901 goto undo;
902 #endif
903 }
904 if (hostIsNew && (ifp->if_flags & IFF_MULTICAST)) {
905 int error_local = 0;
906
907 /*
908 * join solicited multicast addr for new host id
909 */
910 struct in6_addr llsol;
911 bzero(&llsol, sizeof(struct in6_addr));
912 llsol.s6_addr16[0] = htons(0xff02);
913 llsol.s6_addr16[1] = htons(ifp->if_index);
914 llsol.s6_addr32[1] = 0;
915 llsol.s6_addr32[2] = htonl(1);
916 llsol.s6_addr32[3] =
917 ifra->ifra_addr.sin6_addr.s6_addr32[3];
918 llsol.s6_addr8[12] = 0xff;
919 (void)in6_addmulti(&llsol, ifp, &error_local);
920 if (error == 0)
921 error = error_local;
922 }
923
924 ia->ia6_flags = ifra->ifra_flags;
925 ia->ia6_flags &= ~IN6_IFF_DUPLICATED; /*safety*/
926 ia->ia6_flags &= ~IN6_IFF_NODAD; /* Mobile IPv6 */
927
928 ia->ia6_lifetime = ifra->ifra_lifetime;
929 /* for sanity */
930 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
931 ia->ia6_lifetime.ia6t_expire =
932 time_second + ia->ia6_lifetime.ia6t_vltime;
933 } else
934 ia->ia6_lifetime.ia6t_expire = 0;
935 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
936 ia->ia6_lifetime.ia6t_preferred =
937 time_second + ia->ia6_lifetime.ia6t_pltime;
938 } else
939 ia->ia6_lifetime.ia6t_preferred = 0;
940
941 /*
942 * Perform DAD, if needed.
943 * XXX It may be of use, if we can administratively
944 * disable DAD.
945 */
946 switch (ifp->if_type) {
947 case IFT_ARCNET:
948 case IFT_ETHER:
949 case IFT_FDDI:
950 #if 0
951 case IFT_ATM:
952 case IFT_SLIP:
953 case IFT_PPP:
954 #endif
955 /* Mobile IPv6 modification */
956 if ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) {
957 ia->ia6_flags |= IN6_IFF_TENTATIVE;
958 nd6_dad_start((struct ifaddr *)ia, NULL);
959 }
960 break;
961 case IFT_DUMMY:
962 case IFT_FAITH:
963 case IFT_GIF:
964 case IFT_LOOP:
965 default:
966 break;
967 }
968
969 if (hostIsNew) {
970 int iilen;
971 int error_local = 0;
972
973 iilen = (sizeof(ia->ia_prefixmask.sin6_addr) << 3) -
974 in6_mask2len(&ia->ia_prefixmask.sin6_addr);
975 error_local = in6_prefix_add_ifid(iilen, ia);
976 if (error == 0)
977 error = error_local;
978 }
979
980 return(error);
981
982 case SIOCDIFADDR_IN6:
983 in6_purgeaddr(&ia->ia_ifa, ifp);
984 break;
985
986 default:
987 #ifdef __APPLE__
988 error = dlil_ioctl(0, ifp, cmd, (caddr_t)data);
989 if (error == EOPNOTSUPP)
990 error = 0;
991 return error;
992
993 #else
994 if (ifp == NULL || ifp->if_ioctl == 0)
995 return(EOPNOTSUPP);
996 return((*ifp->if_ioctl)(ifp, cmd, data));
997 #endif
998 }
999 return(0);
1000 }
1001
1002 void
1003 in6_purgeaddr(ifa, ifp)
1004 struct ifaddr *ifa;
1005 struct ifnet *ifp;
1006 {
1007 struct in6_ifaddr *oia, *ia = (void *) ifa;
1008
1009 in6_ifscrub(ifp, ia);
1010
1011 if (ifp->if_flags & IFF_MULTICAST) {
1012 /*
1013 * delete solicited multicast addr for deleting host id
1014 */
1015 struct in6_multi *in6m;
1016 struct in6_addr llsol;
1017 bzero(&llsol, sizeof(struct in6_addr));
1018 llsol.s6_addr16[0] = htons(0xff02);
1019 llsol.s6_addr16[1] = htons(ifp->if_index);
1020 llsol.s6_addr32[1] = 0;
1021 llsol.s6_addr32[2] = htonl(1);
1022 llsol.s6_addr32[3] =
1023 ia->ia_addr.sin6_addr.s6_addr32[3];
1024 llsol.s6_addr8[12] = 0xff;
1025
1026 IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1027 if (in6m)
1028 in6_delmulti(in6m);
1029 }
1030
1031 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1032 if ((ifa = ifp->if_addrlist) == ia62ifa(ia))
1033 ifp->if_addrlist = ifa->ifa_next;
1034 else {
1035 while (ifa->ifa_next &&
1036 (ifa->ifa_next != ia62ifa(ia)))
1037 ifa = ifa->ifa_next;
1038 if (ifa->ifa_next)
1039 ifa->ifa_next = ia62ifa(ia)->ifa_next;
1040 else
1041 printf("Couldn't unlink in6_ifaddr from ifp\n");
1042 }
1043 #else
1044 TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
1045 #endif
1046 IFAFREE(&ia->ia_ifa);
1047
1048 oia = ia;
1049 if (oia == (ia = in6_ifaddr))
1050 in6_ifaddr = ia->ia_next;
1051 else {
1052 while (ia->ia_next && (ia->ia_next != oia))
1053 ia = ia->ia_next;
1054 if (ia->ia_next)
1055 ia->ia_next = oia->ia_next;
1056 else
1057 printf("Didn't unlink in6_ifaddr from list\n");
1058 }
1059 {
1060 int iilen;
1061
1062 iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
1063 in6_mask2len(&oia->ia_prefixmask.sin6_addr);
1064 in6_prefix_remove_ifid(iilen, oia);
1065 }
1066 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1067 if (oia->ia6_multiaddrs.lh_first != NULL)
1068 in6_savemkludge(oia);
1069 #endif
1070
1071 IFAFREE(&oia->ia_ifa);
1072 }
1073
1074 /*
1075 * SIOC[GAD]LIFADDR.
1076 * SIOCGLIFADDR: get first address. (???)
1077 * SIOCGLIFADDR with IFLR_PREFIX:
1078 * get first address that matches the specified prefix.
1079 * SIOCALIFADDR: add the specified address.
1080 * SIOCALIFADDR with IFLR_PREFIX:
1081 * add the specified prefix, filling hostid part from
1082 * the first link-local address. prefixlen must be <= 64.
1083 * SIOCDLIFADDR: delete the specified address.
1084 * SIOCDLIFADDR with IFLR_PREFIX:
1085 * delete the first address that matches the specified prefix.
1086 * return values:
1087 * EINVAL on invalid parameters
1088 * EADDRNOTAVAIL on prefix match failed/specified address not found
1089 * other values may be returned from in6_ioctl()
1090 *
1091 * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
1092 * this is to accomodate address naming scheme other than RFC2374,
1093 * in the future.
1094 * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
1095 * address encoding scheme. (see figure on page 8)
1096 */
1097 static int
1098 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1099 in6_lifaddr_ioctl(so, cmd, data, ifp, p)
1100 struct socket *so;
1101 u_long cmd;
1102 caddr_t data;
1103 struct ifnet *ifp;
1104 struct proc *p;
1105 #else
1106 in6_lifaddr_ioctl(so, cmd, data, ifp)
1107 struct socket *so;
1108 u_long cmd;
1109 caddr_t data;
1110 struct ifnet *ifp;
1111 #endif
1112 {
1113 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
1114 struct ifaddr *ifa;
1115 struct sockaddr *sa;
1116
1117 /* sanity checks */
1118 if (!data || !ifp) {
1119 panic("invalid argument to in6_lifaddr_ioctl");
1120 /*NOTRECHED*/
1121 }
1122
1123 switch (cmd) {
1124 case SIOCGLIFADDR:
1125 /* address must be specified on GET with IFLR_PREFIX */
1126 if ((iflr->flags & IFLR_PREFIX) == 0)
1127 break;
1128 /*FALLTHROUGH*/
1129 case SIOCALIFADDR:
1130 case SIOCDLIFADDR:
1131 /* address must be specified on ADD and DELETE */
1132 sa = (struct sockaddr *)&iflr->addr;
1133 if (sa->sa_family != AF_INET6)
1134 return EINVAL;
1135 if (sa->sa_len != sizeof(struct sockaddr_in6))
1136 return EINVAL;
1137 /* XXX need improvement */
1138 sa = (struct sockaddr *)&iflr->dstaddr;
1139 if (sa->sa_family && sa->sa_family != AF_INET6)
1140 return EINVAL;
1141 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
1142 return EINVAL;
1143 break;
1144 default: /*shouldn't happen*/
1145 #if 0
1146 panic("invalid cmd to in6_lifaddr_ioctl");
1147 /*NOTREACHED*/
1148 #else
1149 return EOPNOTSUPP;
1150 #endif
1151 }
1152 if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
1153 return EINVAL;
1154
1155 switch (cmd) {
1156 case SIOCALIFADDR:
1157 {
1158 struct in6_aliasreq ifra;
1159 struct in6_addr *hostid = NULL;
1160 int prefixlen;
1161
1162 if ((iflr->flags & IFLR_PREFIX) != 0) {
1163 struct sockaddr_in6 *sin6;
1164
1165 /*
1166 * hostid is to fill in the hostid part of the
1167 * address. hostid points to the first link-local
1168 * address attached to the interface.
1169 */
1170 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
1171 if (!ifa)
1172 return EADDRNOTAVAIL;
1173 hostid = IFA_IN6(ifa);
1174
1175 /* prefixlen must be <= 64. */
1176 if (64 < iflr->prefixlen)
1177 return EINVAL;
1178 prefixlen = iflr->prefixlen;
1179
1180 /* hostid part must be zero. */
1181 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1182 if (sin6->sin6_addr.s6_addr32[2] != 0
1183 || sin6->sin6_addr.s6_addr32[3] != 0) {
1184 return EINVAL;
1185 }
1186 } else
1187 prefixlen = iflr->prefixlen;
1188
1189 /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1190 bzero(&ifra, sizeof(ifra));
1191 bcopy(iflr->iflr_name, ifra.ifra_name,
1192 sizeof(ifra.ifra_name));
1193
1194 bcopy(&iflr->addr, &ifra.ifra_addr,
1195 ((struct sockaddr *)&iflr->addr)->sa_len);
1196 if (hostid) {
1197 /* fill in hostid part */
1198 ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1199 hostid->s6_addr32[2];
1200 ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1201 hostid->s6_addr32[3];
1202 }
1203
1204 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/
1205 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1206 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
1207 if (hostid) {
1208 ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1209 hostid->s6_addr32[2];
1210 ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1211 hostid->s6_addr32[3];
1212 }
1213 }
1214
1215 ifra.ifra_prefixmask.sin6_family = AF_INET6;
1216 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1217 in6_len2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
1218
1219 ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1220 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1221 return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);
1222 #else
1223 return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp);
1224 #endif
1225 }
1226 case SIOCGLIFADDR:
1227 case SIOCDLIFADDR:
1228 {
1229 struct in6_ifaddr *ia;
1230 struct in6_addr mask, candidate, match;
1231 struct sockaddr_in6 *sin6;
1232 int cmp;
1233
1234 bzero(&mask, sizeof(mask));
1235 if (iflr->flags & IFLR_PREFIX) {
1236 /* lookup a prefix rather than address. */
1237 in6_len2mask(&mask, iflr->prefixlen);
1238
1239 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1240 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1241 match.s6_addr32[0] &= mask.s6_addr32[0];
1242 match.s6_addr32[1] &= mask.s6_addr32[1];
1243 match.s6_addr32[2] &= mask.s6_addr32[2];
1244 match.s6_addr32[3] &= mask.s6_addr32[3];
1245
1246 /* if you set extra bits, that's wrong */
1247 if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
1248 return EINVAL;
1249
1250 cmp = 1;
1251 } else {
1252 if (cmd == SIOCGLIFADDR) {
1253 /* on getting an address, take the 1st match */
1254 cmp = 0; /*XXX*/
1255 } else {
1256 /* on deleting an address, do exact match */
1257 in6_len2mask(&mask, 128);
1258 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1259 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1260
1261 cmp = 1;
1262 }
1263 }
1264
1265 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1266 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1267 #else
1268 for (ifa = ifp->if_addrlist.tqh_first;
1269 ifa;
1270 ifa = ifa->ifa_list.tqe_next)
1271 #endif
1272 {
1273 if (ifa->ifa_addr->sa_family != AF_INET6)
1274 continue;
1275 if (!cmp)
1276 break;
1277 bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1278 candidate.s6_addr32[0] &= mask.s6_addr32[0];
1279 candidate.s6_addr32[1] &= mask.s6_addr32[1];
1280 candidate.s6_addr32[2] &= mask.s6_addr32[2];
1281 candidate.s6_addr32[3] &= mask.s6_addr32[3];
1282 if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
1283 break;
1284 }
1285 if (!ifa)
1286 return EADDRNOTAVAIL;
1287 ia = ifa2ia6(ifa);
1288
1289 if (cmd == SIOCGLIFADDR) {
1290 /* fill in the if_laddrreq structure */
1291 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1292
1293 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1294 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1295 ia->ia_dstaddr.sin6_len);
1296 } else
1297 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1298
1299 iflr->prefixlen =
1300 in6_mask2len(&ia->ia_prefixmask.sin6_addr);
1301
1302 iflr->flags = ia->ia6_flags; /*XXX*/
1303
1304 return 0;
1305 } else {
1306 struct in6_aliasreq ifra;
1307
1308 /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1309 bzero(&ifra, sizeof(ifra));
1310 bcopy(iflr->iflr_name, ifra.ifra_name,
1311 sizeof(ifra.ifra_name));
1312
1313 bcopy(&ia->ia_addr, &ifra.ifra_addr,
1314 ia->ia_addr.sin6_len);
1315 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1316 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1317 ia->ia_dstaddr.sin6_len);
1318 } else {
1319 bzero(&ifra.ifra_dstaddr,
1320 sizeof(ifra.ifra_dstaddr));
1321 }
1322 bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1323 ia->ia_prefixmask.sin6_len);
1324
1325 ifra.ifra_flags = ia->ia6_flags;
1326 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1327 return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1328 ifp, p);
1329 #else
1330 return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1331 ifp);
1332 #endif
1333 }
1334 }
1335 }
1336
1337 return EOPNOTSUPP; /*just for safety*/
1338 }
1339
1340 /*
1341 * Delete any existing route for an interface.
1342 */
1343 void
1344 in6_ifscrub(ifp, ia)
1345 register struct ifnet *ifp;
1346 register struct in6_ifaddr *ia;
1347 {
1348 if ((ia->ia_flags & IFA_ROUTE) == 0)
1349 return;
1350 if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1351 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1352 else
1353 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1354 ia->ia_flags &= ~IFA_ROUTE;
1355
1356 /* Remove ownaddr's loopback rtentry, if it exists. */
1357 in6_ifremloop(&(ia->ia_ifa));
1358 }
1359
1360 /*
1361 * Initialize an interface's intetnet6 address
1362 * and routing table entry.
1363 */
1364 int
1365 in6_ifinit(ifp, ia, sin6, scrub)
1366 struct ifnet *ifp;
1367 struct in6_ifaddr *ia;
1368 struct sockaddr_in6 *sin6;
1369 int scrub;
1370 {
1371 struct sockaddr_in6 oldaddr;
1372 int error, flags = RTF_UP;
1373 u_long dl_tag;
1374 int s = splimp();
1375
1376 oldaddr = ia->ia_addr;
1377 ia->ia_addr = *sin6;
1378 /*
1379 * Give the interface a chance to initialize
1380 * if this is its first address,
1381 * and to validate the address if necessary.
1382 */
1383 #ifdef __APPLE__
1384 error = dlil_ioctl(0, ifp, SIOCSIFADDR, (caddr_t)ia) ;
1385 if (error == EOPNOTSUPP)
1386 error = 0;
1387 if (error) {
1388
1389 #else
1390 if (ifp->if_ioctl &&
1391 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
1392 #endif
1393 printf("in6_ifinit SIOCSIFADDR for if=%s returns error=%x\n", if_name(ifp), error);
1394 splx(s);
1395 ia->ia_addr = oldaddr;
1396 return(error);
1397 }
1398
1399 switch (ifp->if_type) {
1400 case IFT_ARCNET:
1401 case IFT_ETHER:
1402 case IFT_FDDI:
1403 ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1404 ia->ia_ifa.ifa_flags |= RTF_CLONING;
1405 break;
1406 case IFT_PPP:
1407 ia->ia_ifa.ifa_rtrequest = nd6_p2p_rtrequest;
1408 ia->ia_ifa.ifa_flags |= RTF_CLONING;
1409 break;
1410 }
1411
1412 splx(s);
1413 if (scrub) {
1414 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1415 in6_ifscrub(ifp, ia);
1416 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1417 }
1418 /* xxx
1419 * in_socktrim
1420 */
1421 /*
1422 * Add route for the network.
1423 */
1424 ia->ia_ifa.ifa_metric = ifp->if_metric;
1425 if (ifp->if_flags & IFF_LOOPBACK) {
1426 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1427 flags |= RTF_HOST;
1428 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1429 if (ia->ia_dstaddr.sin6_family != AF_INET6)
1430 return(0);
1431 flags |= RTF_HOST;
1432 }
1433 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1434 ia->ia_flags |= IFA_ROUTE;
1435
1436 /* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
1437 in6_ifaddloop(&(ia->ia_ifa));
1438
1439 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1440 if (ifp->if_flags & IFF_MULTICAST)
1441 in6_restoremkludge(ia, ifp);
1442 #endif
1443
1444 #ifdef __APPLE__
1445 printf("in6_ifinit: Attach dl_tag for if=%s%n\n", ifp->if_name, ifp->if_unit);
1446
1447 if (strcmp(ifp->if_name, "en") == 0)
1448 dl_tag = ether_attach_inet6(ifp);
1449
1450 if (strcmp(ifp->if_name, "lo") == 0)
1451 dl_tag = lo_attach_inet(ifp);
1452
1453 if (strcmp(ifp->if_name, "gif") == 0)
1454 dl_tag = gif_attach_inet(ifp);
1455 /* End of temp code */
1456 ia->ia_ifa.ifa_dlt = dl_tag;
1457 #endif
1458
1459 return(error);
1460 }
1461
1462 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1463 /*
1464 * Multicast address kludge:
1465 * If there were any multicast addresses attached to this interface address,
1466 * either move them to another address on this interface, or save them until
1467 * such time as this interface is reconfigured for IPv6.
1468 */
1469 void
1470 in6_savemkludge(oia)
1471 struct in6_ifaddr *oia;
1472 {
1473 struct in6_ifaddr *ia;
1474 struct in6_multi *in6m, *next;
1475
1476 IFP_TO_IA6(oia->ia_ifp, ia);
1477 if (ia) { /* there is another address */
1478 for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
1479 next = in6m->in6m_entry.le_next;
1480 IFAFREE(&in6m->in6m_ia->ia_ifa);
1481 ia->ia_ifa.ifa_refcnt++;
1482 in6m->in6m_ia = ia;
1483 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1484 }
1485 } else { /* last address on this if deleted, save */
1486 struct multi6_kludge *mk;
1487
1488 mk = _MALLOC(sizeof(*mk), M_IPMADDR, M_WAITOK);
1489
1490 LIST_INIT(&mk->mk_head);
1491 mk->mk_ifp = oia->ia_ifp;
1492
1493 for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
1494 next = in6m->in6m_entry.le_next;
1495 IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
1496 in6m->in6m_ia = NULL;
1497 LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
1498 }
1499
1500 if (mk->mk_head.lh_first != NULL) {
1501 LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
1502 } else {
1503 FREE(mk, M_IPMADDR);
1504 }
1505 }
1506 }
1507
1508 /*
1509 * Continuation of multicast address hack:
1510 * If there was a multicast group list previously saved for this interface,
1511 * then we re-attach it to the first address configured on the i/f.
1512 */
1513 void
1514 in6_restoremkludge(ia, ifp)
1515 struct in6_ifaddr *ia;
1516 struct ifnet *ifp;
1517 {
1518 struct multi6_kludge *mk;
1519
1520 for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
1521 if (mk->mk_ifp == ifp) {
1522 struct in6_multi *in6m, *next;
1523
1524 for (in6m = mk->mk_head.lh_first; in6m; in6m = next){
1525 next = in6m->in6m_entry.le_next;
1526 in6m->in6m_ia = ia;
1527 ia->ia_ifa.ifa_refcnt++;
1528 LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
1529 in6m, in6m_entry);
1530 }
1531 LIST_REMOVE(mk, mk_entry);
1532 _FREE(mk, M_IPMADDR);
1533 break;
1534 }
1535 }
1536 }
1537
1538 void
1539 in6_purgemkludge(ifp)
1540 struct ifnet *ifp;
1541 {
1542 struct multi6_kludge *mk;
1543 struct in6_multi *in6m;
1544
1545 for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
1546 if (mk->mk_ifp != ifp)
1547 continue;
1548
1549 /* leave from all multicast groups joined */
1550 while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL)
1551 in6_delmulti(in6m);
1552 LIST_REMOVE(mk, mk_entry);
1553 _FREE(mk, M_IPMADDR);
1554 break;
1555 }
1556 }
1557
1558 /*
1559 * Add an address to the list of IP6 multicast addresses for a
1560 * given interface.
1561 */
1562 struct in6_multi *
1563 in6_addmulti(maddr6, ifp, errorp)
1564 register struct in6_addr *maddr6;
1565 register struct ifnet *ifp;
1566 int *errorp;
1567 {
1568 struct in6_ifaddr *ia;
1569 struct in6_ifreq ifr;
1570 struct in6_multi *in6m;
1571 #if __NetBSD__
1572 int s = splsoftnet();
1573 #else
1574 int s = splnet();
1575 #endif
1576
1577 *errorp = 0;
1578 /*
1579 * See if address already in list.
1580 */
1581 IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
1582 if (in6m != NULL) {
1583 /*
1584 * Found it; just increment the refrence count.
1585 */
1586 in6m->in6m_refcount++;
1587 } else {
1588 /*
1589 * New address; allocate a new multicast record
1590 * and link it into the interface's multicast list.
1591 */
1592 in6m = (struct in6_multi *)
1593 _MALLOC(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1594 if (in6m == NULL) {
1595 splx(s);
1596 *errorp = ENOBUFS;
1597 return(NULL);
1598 }
1599 in6m->in6m_addr = *maddr6;
1600 in6m->in6m_ifp = ifp;
1601 in6m->in6m_refcount = 1;
1602 IFP_TO_IA6(ifp, ia);
1603 if (ia == NULL) {
1604 _FREE(in6m, M_IPMADDR);
1605 splx(s);
1606 *errorp = EADDRNOTAVAIL; /* appropriate? */
1607 return(NULL);
1608 }
1609 in6m->in6m_ia = ia;
1610 ia->ia_ifa.ifa_refcnt++; /* gain a reference */
1611 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1612
1613 /*
1614 * Ask the network driver to update its multicast reception
1615 * filter appropriately for the new address.
1616 */
1617 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1618 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1619 ifr.ifr_addr.sin6_family = AF_INET6;
1620 ifr.ifr_addr.sin6_addr = *maddr6;
1621 #ifdef __APPLE__
1622 *errorp = dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t)&ifr);
1623 printf("in6_addmulti: if=%s%n dlil_ioctl returns=%d\n", ifp->if_name, ifp->if_unit, *errorp);
1624 if (*errorp == EOPNOTSUPP)
1625 *errorp = 0;
1626
1627 #else
1628 if (ifp->if_ioctl == NULL)
1629 *errorp = ENXIO; /* XXX: appropriate? */
1630 else
1631 *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,
1632 (caddr_t)&ifr);
1633 #endif
1634 if (*errorp) {
1635 LIST_REMOVE(in6m, in6m_entry);
1636 _FREE(in6m, M_IPMADDR);
1637 splx(s);
1638 return(NULL);
1639 }
1640 /*
1641 * Let MLD6 know that we have joined a new IP6 multicast
1642 * group.
1643 */
1644 mld6_start_listening(in6m);
1645 }
1646 splx(s);
1647 return(in6m);
1648 }
1649
1650 /*
1651 * Delete a multicast address record.
1652 */
1653 void
1654 in6_delmulti(in6m)
1655 struct in6_multi *in6m;
1656 {
1657 struct in6_ifreq ifr;
1658 #if __NetBSD__
1659 int s = splsoftnet();
1660 #else
1661 int s = splnet();
1662 #endif
1663
1664 if (--in6m->in6m_refcount == 0) {
1665 /*
1666 * No remaining claims to this record; let MLD6 know
1667 * that we are leaving the multicast group.
1668 */
1669 mld6_stop_listening(in6m);
1670
1671 /*
1672 * Unlink from list.
1673 */
1674 LIST_REMOVE(in6m, in6m_entry);
1675 if (in6m->in6m_ia)
1676 IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
1677
1678 /*
1679 * Notify the network driver to update its multicast
1680 * reception filter.
1681 */
1682 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1683 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1684 ifr.ifr_addr.sin6_family = AF_INET6;
1685 ifr.ifr_addr.sin6_addr = in6m->in6m_addr;
1686 #ifdef __APPLE__
1687 dlil_ioctl(0, in6m->in6m_ifp, SIOCDELMULTI, (caddr_t)&ifr);
1688 #else
1689 (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,
1690 SIOCDELMULTI, (caddr_t)&ifr);
1691 #endif
1692 _FREE(in6m, M_IPMADDR);
1693 }
1694 splx(s);
1695 }
1696 #else /* not FreeBSD3 */
1697 /*
1698 * Add an address to the list of IP6 multicast addresses for a
1699 * given interface.
1700 */
1701 struct in6_multi *
1702 in6_addmulti(maddr6, ifp, errorp)
1703 register struct in6_addr *maddr6;
1704 register struct ifnet *ifp;
1705 int *errorp;
1706 {
1707 struct in6_multi *in6m;
1708 struct sockaddr_in6 sin6;
1709 struct ifmultiaddr *ifma;
1710 int s = splnet();
1711
1712 *errorp = 0;
1713
1714 /*
1715 * Call generic routine to add membership or increment
1716 * refcount. It wants addresses in the form of a sockaddr,
1717 * so we build one here (being careful to zero the unused bytes).
1718 */
1719 bzero(&sin6, sizeof sin6);
1720 sin6.sin6_family = AF_INET6;
1721 sin6.sin6_len = sizeof sin6;
1722 sin6.sin6_addr = *maddr6;
1723 *errorp = if_addmulti(ifp, (struct sockaddr *)&sin6, &ifma);
1724 if (*errorp) {
1725 splx(s);
1726 return 0;
1727 }
1728
1729 /*
1730 * If ifma->ifma_protospec is null, then if_addmulti() created
1731 * a new record. Otherwise, we are done.
1732 */
1733 if (ifma->ifma_protospec != 0)
1734 return ifma->ifma_protospec;
1735
1736 /* XXX - if_addmulti uses M_WAITOK. Can this really be called
1737 at interrupt time? If so, need to fix if_addmulti. XXX */
1738 in6m = (struct in6_multi *)_MALLOC(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1739 if (in6m == NULL) {
1740 splx(s);
1741 return (NULL);
1742 }
1743
1744 bzero(in6m, sizeof *in6m);
1745 in6m->in6m_addr = *maddr6;
1746 in6m->in6m_ifp = ifp;
1747 in6m->in6m_ifma = ifma;
1748 ifma->ifma_protospec = in6m;
1749 LIST_INSERT_HEAD(&in6_multihead, in6m, in6m_entry);
1750
1751 /*
1752 * Let MLD6 know that we have joined a new IP6 multicast
1753 * group.
1754 */
1755 mld6_start_listening(in6m);
1756 splx(s);
1757 return(in6m);
1758 }
1759
1760 /*
1761 * Delete a multicast address record.
1762 */
1763 void
1764 in6_delmulti(in6m)
1765 struct in6_multi *in6m;
1766 {
1767 struct ifmultiaddr *ifma = in6m->in6m_ifma;
1768 int s = splnet();
1769
1770 if (ifma->ifma_refcount == 1) {
1771 /*
1772 * No remaining claims to this record; let MLD6 know
1773 * that we are leaving the multicast group.
1774 */
1775 mld6_stop_listening(in6m);
1776 ifma->ifma_protospec = 0;
1777 LIST_REMOVE(in6m, in6m_entry);
1778 _FREE(in6m, M_IPMADDR);
1779 }
1780 /* XXX - should be separate API for when we have an ifma? */
1781 if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
1782 splx(s);
1783 }
1784 #endif /* not FreeBSD3 */
1785
1786 /*
1787 * Find an IPv6 interface link-local address specific to an interface.
1788 */
1789 struct in6_ifaddr *
1790 in6ifa_ifpforlinklocal(ifp, ignoreflags)
1791 struct ifnet *ifp;
1792 int ignoreflags;
1793 {
1794 register struct ifaddr *ifa;
1795
1796 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1797 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1798 #else
1799 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1800 #endif
1801 {
1802 if (ifa->ifa_addr == NULL)
1803 continue; /* just for safety */
1804 if (ifa->ifa_addr->sa_family != AF_INET6)
1805 continue;
1806 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1807 if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1808 ignoreflags) != 0)
1809 continue;
1810 break;
1811 }
1812 }
1813
1814 return((struct in6_ifaddr *)ifa);
1815 }
1816
1817
1818 /*
1819 * find the internet address corresponding to a given interface and address.
1820 */
1821 struct in6_ifaddr *
1822 in6ifa_ifpwithaddr(ifp, addr)
1823 struct ifnet *ifp;
1824 struct in6_addr *addr;
1825 {
1826 register struct ifaddr *ifa;
1827
1828 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1829 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1830 #else
1831 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1832 #endif
1833 {
1834 if (ifa->ifa_addr == NULL)
1835 continue; /* just for safety */
1836 if (ifa->ifa_addr->sa_family != AF_INET6)
1837 continue;
1838 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1839 break;
1840 }
1841
1842 return((struct in6_ifaddr *)ifa);
1843 }
1844
1845 /*
1846 * Convert IP6 address to printable (loggable) representation.
1847 */
1848 static char digits[] = "0123456789abcdef";
1849 static int ip6round = 0;
1850 char *
1851 ip6_sprintf(addr)
1852 register struct in6_addr *addr;
1853 {
1854 static char ip6buf[8][48];
1855 register int i;
1856 register char *cp;
1857 register u_short *a = (u_short *)addr;
1858 register u_char *d;
1859 int dcolon = 0;
1860
1861 ip6round = (ip6round + 1) & 7;
1862 cp = ip6buf[ip6round];
1863
1864 for (i = 0; i < 8; i++) {
1865 if (dcolon == 1) {
1866 if (*a == 0) {
1867 if (i == 7)
1868 *cp++ = ':';
1869 a++;
1870 continue;
1871 } else
1872 dcolon = 2;
1873 }
1874 if (*a == 0) {
1875 if (dcolon == 0 && *(a + 1) == 0) {
1876 if (i == 0)
1877 *cp++ = ':';
1878 *cp++ = ':';
1879 dcolon = 1;
1880 } else {
1881 *cp++ = '0';
1882 *cp++ = ':';
1883 }
1884 a++;
1885 continue;
1886 }
1887 d = (u_char *)a;
1888 *cp++ = digits[*d >> 4];
1889 *cp++ = digits[*d++ & 0xf];
1890 *cp++ = digits[*d >> 4];
1891 *cp++ = digits[*d & 0xf];
1892 *cp++ = ':';
1893 a++;
1894 }
1895 *--cp = 0;
1896 return(ip6buf[ip6round]);
1897 }
1898
1899 int
1900 in6_localaddr(in6)
1901 struct in6_addr *in6;
1902 {
1903 struct in6_ifaddr *ia;
1904
1905 if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
1906 return 1;
1907
1908 for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1909 if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1910 &ia->ia_prefixmask.sin6_addr))
1911 return 1;
1912
1913 return (0);
1914 }
1915
1916 /*
1917 * Get a scope of the address. Node-local, link-local, site-local or global.
1918 */
1919 int
1920 in6_addrscope (addr)
1921 struct in6_addr *addr;
1922 {
1923 int scope;
1924
1925 if (addr->s6_addr8[0] == 0xfe) {
1926 scope = addr->s6_addr8[1] & 0xc0;
1927
1928 switch (scope) {
1929 case 0x80:
1930 return IPV6_ADDR_SCOPE_LINKLOCAL;
1931 break;
1932 case 0xc0:
1933 return IPV6_ADDR_SCOPE_SITELOCAL;
1934 break;
1935 default:
1936 return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
1937 break;
1938 }
1939 }
1940
1941
1942 if (addr->s6_addr8[0] == 0xff) {
1943 scope = addr->s6_addr8[1] & 0x0f;
1944
1945 /*
1946 * due to other scope such as reserved,
1947 * return scope doesn't work.
1948 */
1949 switch (scope) {
1950 case IPV6_ADDR_SCOPE_NODELOCAL:
1951 return IPV6_ADDR_SCOPE_NODELOCAL;
1952 break;
1953 case IPV6_ADDR_SCOPE_LINKLOCAL:
1954 return IPV6_ADDR_SCOPE_LINKLOCAL;
1955 break;
1956 case IPV6_ADDR_SCOPE_SITELOCAL:
1957 return IPV6_ADDR_SCOPE_SITELOCAL;
1958 break;
1959 default:
1960 return IPV6_ADDR_SCOPE_GLOBAL;
1961 break;
1962 }
1963 }
1964
1965 if (bcmp(&in6addr_loopback, addr, sizeof(addr) - 1) == 0) {
1966 if (addr->s6_addr8[15] == 1) /* loopback */
1967 return IPV6_ADDR_SCOPE_NODELOCAL;
1968 if (addr->s6_addr8[15] == 0) /* unspecified */
1969 return IPV6_ADDR_SCOPE_LINKLOCAL;
1970 }
1971
1972 return IPV6_ADDR_SCOPE_GLOBAL;
1973 }
1974
1975 int
1976 in6_addr2scopeid(ifp, addr)
1977 struct ifnet *ifp; /* must not be NULL */
1978 struct in6_addr *addr; /* must not be NULL */
1979 {
1980 int scope = in6_addrscope(addr);
1981
1982 switch(scope) {
1983 case IPV6_ADDR_SCOPE_NODELOCAL:
1984 return(-1); /* XXX: is this an appropriate value? */
1985
1986 case IPV6_ADDR_SCOPE_LINKLOCAL:
1987 /* XXX: we do not distinguish between a link and an I/F. */
1988 return(ifp->if_index);
1989
1990 case IPV6_ADDR_SCOPE_SITELOCAL:
1991 return(0); /* XXX: invalid. */
1992
1993 default:
1994 return(0); /* XXX: treat as global. */
1995 }
1996 }
1997
1998 /*
1999 * return length of part which dst and src are equal
2000 * hard coding...
2001 */
2002
2003 int
2004 in6_matchlen(src, dst)
2005 struct in6_addr *src, *dst;
2006 {
2007 int match = 0;
2008 u_char *s = (u_char *)src, *d = (u_char *)dst;
2009 u_char *lim = s + 16, r;
2010
2011 while (s < lim)
2012 if ((r = (*d++ ^ *s++)) != 0) {
2013 while (r < 128) {
2014 match++;
2015 r <<= 1;
2016 }
2017 break;
2018 } else
2019 match += 8;
2020 return match;
2021 }
2022
2023 int
2024 in6_are_prefix_equal(p1, p2, len)
2025 struct in6_addr *p1, *p2;
2026 int len;
2027 {
2028 int bytelen, bitlen;
2029
2030 /* sanity check */
2031 if (0 > len || len > 128) {
2032 log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
2033 len);
2034 return(0);
2035 }
2036
2037 bytelen = len / 8;
2038 bitlen = len % 8;
2039
2040 if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
2041 return(0);
2042 if (p1->s6_addr[bytelen] >> (8 - bitlen) !=
2043 p2->s6_addr[bytelen] >> (8 - bitlen))
2044 return(0);
2045
2046 return(1);
2047 }
2048
2049 void
2050 in6_prefixlen2mask(maskp, len)
2051 struct in6_addr *maskp;
2052 int len;
2053 {
2054 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
2055 int bytelen, bitlen, i;
2056
2057 /* sanity check */
2058 if (0 > len || len > 128) {
2059 log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
2060 len);
2061 return;
2062 }
2063
2064 bzero(maskp, sizeof(*maskp));
2065 bytelen = len / 8;
2066 bitlen = len % 8;
2067 for (i = 0; i < bytelen; i++)
2068 maskp->s6_addr[i] = 0xff;
2069 if (bitlen)
2070 maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
2071 }
2072
2073 /*
2074 * return the best address out of the same scope
2075 */
2076 struct in6_ifaddr *
2077 in6_ifawithscope(oifp, dst)
2078 register struct ifnet *oifp;
2079 register struct in6_addr *dst;
2080 {
2081 int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0;
2082 int blen = -1;
2083 struct ifaddr *ifa;
2084 struct ifnet *ifp;
2085 struct in6_ifaddr *ifa_best = NULL;
2086
2087 if (oifp == NULL) {
2088 printf("in6_ifawithscope: output interface is not specified\n");
2089 return(NULL);
2090 }
2091
2092 /*
2093 * We search for all addresses on all interfaces from the beginning.
2094 * Comparing an interface with the outgoing interface will be done
2095 * only at the final stage of tiebreaking.
2096 */
2097 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2098 for (ifp = ifnet; ifp; ifp = ifp->if_next)
2099 #else
2100 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
2101 #endif
2102 {
2103 /*
2104 * We can never take an address that breaks the scope zone
2105 * of the destination.
2106 */
2107 if (in6_addr2scopeid(ifp, dst) != in6_addr2scopeid(oifp, dst))
2108 continue;
2109
2110 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2111 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2112 #elif defined(__FreeBSD__) && __FreeBSD__ >= 4
2113 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
2114 #else
2115 for (ifa = ifp->if_addrlist.tqh_first; ifa;
2116 ifa = ifa->ifa_list.tqe_next)
2117 #endif
2118 {
2119 int tlen = -1, dscopecmp, bscopecmp, matchcmp;
2120
2121 if (ifa->ifa_addr->sa_family != AF_INET6)
2122 continue;
2123
2124 src_scope = in6_addrscope(IFA_IN6(ifa));
2125
2126 #if ADDRSELECT_DEBUG /* should be removed after stabilization */
2127 dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
2128 printf("in6_ifawithscope: dst=%s bestaddr=%s, "
2129 "newaddr=%s, scope=%x, dcmp=%d, bcmp=%d, "
2130 "matchlen=%d, flgs=%x\n",
2131 ip6_sprintf(dst),
2132 ifa_best ? ip6_sprintf(&ifa_best->ia_addr.sin6_addr) : "none",
2133 ip6_sprintf(IFA_IN6(ifa)), src_scope,
2134 dscopecmp,
2135 ifa_best ? IN6_ARE_SCOPE_CMP(src_scope, best_scope) : -1,
2136 in6_matchlen(IFA_IN6(ifa), dst),
2137 ((struct in6_ifaddr *)ifa)->ia6_flags);
2138 #endif
2139
2140 /*
2141 * Don't use an address before completing DAD
2142 * nor a duplicated address.
2143 */
2144 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2145 IN6_IFF_NOTREADY)
2146 continue;
2147
2148 /* XXX: is there any case to allow anycasts? */
2149 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2150 IN6_IFF_ANYCAST)
2151 continue;
2152
2153 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2154 IN6_IFF_DETACHED)
2155 continue;
2156
2157 /*
2158 * If this is the first address we find,
2159 * keep it anyway.
2160 */
2161 if (ifa_best == NULL)
2162 goto replace;
2163
2164 /*
2165 * ifa_best is never NULL beyond this line except
2166 * within the block labeled "replace".
2167 */
2168
2169 /*
2170 * If ifa_best has a smaller scope than dst and
2171 * the current address has a larger one than
2172 * (or equal to) dst, always replace ifa_best.
2173 * Also, if the current address has a smaller scope
2174 * than dst, ignore it unless ifa_best also has a
2175 * smaller scope.
2176 */
2177 if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
2178 IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0)
2179 goto replace;
2180 if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
2181 IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0)
2182 continue;
2183
2184 /*
2185 * A deprecated address SHOULD NOT be used in new
2186 * communications if an alternate (non-deprecated)
2187 * address is available and has sufficient scope.
2188 * RFC 2462, Section 5.5.4.
2189 */
2190 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2191 IN6_IFF_DEPRECATED) {
2192 /*
2193 * Ignore any deprecated addresses if
2194 * specified by configuration.
2195 */
2196 if (!ip6_use_deprecated)
2197 continue;
2198
2199 /*
2200 * If we have already found a non-deprecated
2201 * candidate, just ignore deprecated addresses.
2202 */
2203 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
2204 == 0)
2205 continue;
2206 }
2207
2208 /*
2209 * A non-deprecated address is always preferred
2210 * to a deprecated one regardless of scopes and
2211 * address matching.
2212 */
2213 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
2214 (((struct in6_ifaddr *)ifa)->ia6_flags &
2215 IN6_IFF_DEPRECATED) == 0)
2216 goto replace;
2217
2218 /*
2219 * At this point, we have two cases:
2220 * 1. we are looking at a non-deprecated address,
2221 * and ifa_best is also non-deprecated.
2222 * 2. we are looking at a deprecated address,
2223 * and ifa_best is also deprecated.
2224 * Also, we do not have to consider a case where
2225 * the scope of if_best is larger(smaller) than dst and
2226 * the scope of the current address is smaller(larger)
2227 * than dst. Such a case has already been covered.
2228 * Tiebreaking is done according to the following
2229 * items:
2230 * - the scope comparison between the address and
2231 * dst (dscopecmp)
2232 * - the scope comparison between the address and
2233 * ifa_best (bscopecmp)
2234 * - if the address match dst longer than ifa_best
2235 * (matchcmp)
2236 * - if the address is on the outgoing I/F (outI/F)
2237 *
2238 * Roughly speaking, the selection policy is
2239 * - the most important item is scope. The same scope
2240 * is best. Then search for a larger scope.
2241 * Smaller scopes are the last resort.
2242 * - A deprecated address is chosen only when we have
2243 * no address that has an enough scope, but is
2244 * prefered to any addresses of smaller scopes.
2245 * - Longest address match against dst is considered
2246 * only for addresses that has the same scope of dst.
2247 * - If there is no other reasons to choose one,
2248 * addresses on the outgoing I/F are preferred.
2249 *
2250 * The precise decision table is as follows:
2251 * dscopecmp bscopecmp matchcmp outI/F | replace?
2252 * !equal equal N/A Yes | Yes (1)
2253 * !equal equal N/A No | No (2)
2254 * larger larger N/A N/A | No (3)
2255 * larger smaller N/A N/A | Yes (4)
2256 * smaller larger N/A N/A | Yes (5)
2257 * smaller smaller N/A N/A | No (6)
2258 * equal smaller N/A N/A | Yes (7)
2259 * equal larger (already done)
2260 * equal equal larger N/A | Yes (8)
2261 * equal equal smaller N/A | No (9)
2262 * equal equal equal Yes | Yes (a)
2263 * eaual eqaul equal No | No (b)
2264 */
2265 dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
2266 bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
2267
2268 if (dscopecmp && bscopecmp == 0) {
2269 if (oifp == ifp) /* (1) */
2270 goto replace;
2271 continue; /* (2) */
2272 }
2273 if (dscopecmp > 0) {
2274 if (bscopecmp > 0) /* (3) */
2275 continue;
2276 goto replace; /* (4) */
2277 }
2278 if (dscopecmp < 0) {
2279 if (bscopecmp > 0) /* (5) */
2280 goto replace;
2281 continue; /* (6) */
2282 }
2283
2284 /* now dscopecmp must be 0 */
2285 if (bscopecmp < 0)
2286 goto replace; /* (7) */
2287
2288 /*
2289 * At last both dscopecmp and bscopecmp must be 0.
2290 * We need address matching against dst for
2291 * tiebreaking.
2292 */
2293 tlen = in6_matchlen(IFA_IN6(ifa), dst);
2294 matchcmp = tlen - blen;
2295 if (matchcmp > 0) /* (8) */
2296 goto replace;
2297 if (matchcmp < 0) /* (9) */
2298 continue;
2299 if (oifp == ifp) /* (a) */
2300 goto replace;
2301 continue; /* (b) */
2302
2303 replace:
2304 ifa_best = (struct in6_ifaddr *)ifa;
2305 blen = tlen >= 0 ? tlen :
2306 in6_matchlen(IFA_IN6(ifa), dst);
2307 best_scope = in6_addrscope(&ifa_best->ia_addr.sin6_addr);
2308 }
2309 }
2310
2311 /* count statistics for future improvements */
2312 if (ifa_best == NULL)
2313 ip6stat.ip6s_sources_none++;
2314 else {
2315 if (oifp == ifa_best->ia_ifp)
2316 ip6stat.ip6s_sources_sameif[best_scope]++;
2317 else
2318 ip6stat.ip6s_sources_otherif[best_scope]++;
2319
2320 if (best_scope == dst_scope)
2321 ip6stat.ip6s_sources_samescope[best_scope]++;
2322 else
2323 ip6stat.ip6s_sources_otherscope[best_scope]++;
2324
2325 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
2326 ip6stat.ip6s_sources_deprecated[best_scope]++;
2327 }
2328
2329 return(ifa_best);
2330 }
2331
2332 /*
2333 * return the best address out of the same scope. if no address was
2334 * found, return the first valid address from designated IF.
2335 */
2336
2337 struct in6_ifaddr *
2338 in6_ifawithifp(ifp, dst)
2339 register struct ifnet *ifp;
2340 register struct in6_addr *dst;
2341 {
2342 int dst_scope = in6_addrscope(dst), blen = -1, tlen;
2343 struct ifaddr *ifa;
2344 struct in6_ifaddr *besta = 0;
2345 struct in6_ifaddr *dep[2]; /*last-resort: deprecated*/
2346
2347 dep[0] = dep[1] = NULL;
2348
2349 #if 0
2350 #if MIP6
2351 /*
2352 * This is needed to assure that the Home Address is used for
2353 * outgoing packets when not at home. We can't choose any other
2354 * address if we want to keep connections up during movement.
2355 */
2356 if (mip6_get_home_prefix_hook) { /* Only Mobile Node */
2357 struct nd_prefix *pr;
2358 if ((pr = (*mip6_get_home_prefix_hook)()) &&
2359 !IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
2360 {
2361 if (dst_scope == in6_addrscope(&pr->ndpr_addr)) {
2362 #if MIP6_DEBUG
2363 /* Noisy but useful */
2364 mip6_debug("%s: Local address %s is chosen "
2365 "for pcb to dest %s.\n",
2366 __FUNCTION__,
2367 ip6_sprintf(&pr->ndpr_addr),
2368 ip6_sprintf(dst));
2369 #endif
2370 return(in6ifa_ifpwithaddr(ifp, &pr->ndpr_addr));
2371 }
2372 }
2373 }
2374 #endif /* MIP6 */
2375 #endif /* 0 */
2376
2377 /*
2378 * We first look for addresses in the same scope.
2379 * If there is one, return it.
2380 * If two or more, return one which matches the dst longest.
2381 * If none, return one of global addresses assigned other ifs.
2382 */
2383 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2384 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2385 #else
2386 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2387 #endif
2388 {
2389 if (ifa->ifa_addr->sa_family != AF_INET6)
2390 continue;
2391 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2392 continue; /* XXX: is there any case to allow anycast? */
2393 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2394 continue; /* don't use this interface */
2395 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2396 continue;
2397 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2398 if (ip6_use_deprecated)
2399 dep[0] = (struct in6_ifaddr *)ifa;
2400 continue;
2401 }
2402
2403 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
2404 /*
2405 * call in6_matchlen() as few as possible
2406 */
2407 if (besta) {
2408 if (blen == -1)
2409 blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
2410 tlen = in6_matchlen(IFA_IN6(ifa), dst);
2411 if (tlen > blen) {
2412 blen = tlen;
2413 besta = (struct in6_ifaddr *)ifa;
2414 }
2415 } else
2416 besta = (struct in6_ifaddr *)ifa;
2417 }
2418 }
2419 if (besta)
2420 return(besta);
2421
2422 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2423 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2424 #else
2425 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2426 #endif
2427 {
2428 if (ifa->ifa_addr->sa_family != AF_INET6)
2429 continue;
2430 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2431 continue; /* XXX: is there any case to allow anycast? */
2432 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2433 continue; /* don't use this interface */
2434 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2435 continue;
2436 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2437 if (ip6_use_deprecated)
2438 dep[1] = (struct in6_ifaddr *)ifa;
2439 continue;
2440 }
2441
2442 return (struct in6_ifaddr *)ifa;
2443 }
2444
2445 /* use the last-resort values, that are, deprecated addresses */
2446 if (dep[0])
2447 return dep[0];
2448 if (dep[1])
2449 return dep[1];
2450
2451 return NULL;
2452 }
2453
2454 /*
2455 * perform DAD when interface becomes IFF_UP.
2456 */
2457 void
2458 in6_if_up(ifp)
2459 struct ifnet *ifp;
2460 {
2461 struct ifaddr *ifa;
2462 struct in6_ifaddr *ia;
2463 struct sockaddr_dl *sdl;
2464 int type;
2465 #if __bsdi__
2466 u_char ea[ETHER_ADDR_LEN];
2467 #else
2468 struct ether_addr ea;
2469 #endif
2470 int off;
2471 int dad_delay; /* delay ticks before DAD output */
2472
2473 bzero(&ea, sizeof(ea));
2474 sdl = NULL;
2475
2476 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2477 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2478 #else
2479 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2480 #endif
2481 {
2482 if (ifa->ifa_addr->sa_family == AF_INET6
2483 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
2484 goto dad;
2485 }
2486 if (ifa->ifa_addr->sa_family != AF_LINK)
2487 continue;
2488 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
2489 break;
2490 }
2491
2492 switch (ifp->if_type) {
2493 case IFT_LOOP:
2494 in6_ifattach(ifp, IN6_IFT_LOOP, NULL, 1);
2495 break;
2496 case IFT_SLIP:
2497 case IFT_PPP:
2498 case IFT_DUMMY:
2499 case IFT_GIF:
2500 case IFT_FAITH:
2501 type = IN6_IFT_P2P;
2502 in6_ifattach(ifp, type, 0, 1);
2503 break;
2504 #if IFT_STF
2505 case IFT_STF:
2506 /*
2507 * This is VERY awkward to call nd6_ifattach while we will
2508 * not do ND at all on the interface. It is necessary for
2509 * initializing default hoplimit, and ND mtu.
2510 */
2511 nd6_ifattach(ifp);
2512 break;
2513 #endif
2514 case IFT_ETHER:
2515 case IFT_FDDI:
2516 case IFT_ATM:
2517 type = IN6_IFT_802;
2518 if (sdl == NULL)
2519 break;
2520 off = sdl->sdl_nlen;
2521 if (bcmp(&sdl->sdl_data[off], &ea, sizeof(ea)) != 0)
2522 in6_ifattach(ifp, type, LLADDR(sdl), 0);
2523 break;
2524 case IFT_ARCNET:
2525 type = IN6_IFT_ARCNET;
2526 if (sdl == NULL)
2527 break;
2528 off = sdl->sdl_nlen;
2529 if (sdl->sdl_data[off] != 0) /* XXX ?: */
2530 in6_ifattach(ifp, type, LLADDR(sdl), 0);
2531 break;
2532 default:
2533 break;
2534 }
2535
2536 dad:
2537 dad_delay = 0;
2538 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2539 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2540 #else
2541 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2542 #endif
2543 {
2544 if (ifa->ifa_addr->sa_family != AF_INET6)
2545 continue;
2546 ia = (struct in6_ifaddr *)ifa;
2547 if (ia->ia6_flags & IN6_IFF_TENTATIVE)
2548 nd6_dad_start(ifa, &dad_delay);
2549 }
2550 }
2551
2552 /*
2553 * Calculate max IPv6 MTU through all the interfaces and store it
2554 * to in6_maxmtu.
2555 */
2556 void
2557 in6_setmaxmtu()
2558 {
2559 unsigned long maxmtu = 0;
2560 struct ifnet *ifp;
2561
2562 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2563 for (ifp = ifnet; ifp; ifp = ifp->if_next)
2564 #else
2565 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
2566 #endif
2567 {
2568 if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2569 nd_ifinfo[ifp->if_index].linkmtu > maxmtu)
2570 maxmtu = nd_ifinfo[ifp->if_index].linkmtu;
2571 }
2572 if (maxmtu) /* update only when maxmtu is positive */
2573 in6_maxmtu = maxmtu;
2574 }
2575
2576 #if MAPPED_ADDR_ENABLED
2577 /*
2578 * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
2579 * v4 mapped addr or v4 compat addr
2580 */
2581 void
2582 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
2583 {
2584 bzero(sin, sizeof(*sin));
2585 sin->sin_len = sizeof(struct sockaddr_in);
2586 sin->sin_family = AF_INET;
2587 sin->sin_port = sin6->sin6_port;
2588 sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
2589 }
2590
2591 /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
2592 void
2593 in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
2594 {
2595 bzero(sin6, sizeof(*sin6));
2596 sin6->sin6_len = sizeof(struct sockaddr_in6);
2597 sin6->sin6_family = AF_INET6;
2598 sin6->sin6_port = sin->sin_port;
2599 sin6->sin6_addr.s6_addr32[0] = 0;
2600 sin6->sin6_addr.s6_addr32[1] = 0;
2601 sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
2602 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
2603 }
2604
2605 /* Convert sockaddr_in6 into sockaddr_in. */
2606 void
2607 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
2608 {
2609 struct sockaddr_in *sin_p;
2610 struct sockaddr_in6 sin6;
2611
2612 /*
2613 * Save original sockaddr_in6 addr and convert it
2614 * to sockaddr_in.
2615 */
2616 sin6 = *(struct sockaddr_in6 *)nam;
2617 sin_p = (struct sockaddr_in *)nam;
2618 in6_sin6_2_sin(sin_p, &sin6);
2619 }
2620
2621 /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
2622 void
2623 in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
2624 {
2625 struct sockaddr_in *sin_p;
2626 struct sockaddr_in6 *sin6_p;
2627
2628 MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2629 M_WAITOK);
2630 sin_p = (struct sockaddr_in *)*nam;
2631 in6_sin_2_v4mapsin6(sin_p, sin6_p);
2632 FREE(*nam, M_SONAME);
2633 *nam = (struct sockaddr *)sin6_p;
2634 }
2635 #endif /* MAPPED_ADDR_ENABLED */
2636