in6.c revision 1.8 1 /* $NetBSD: in6.c,v 1.8 1999/12/13 15:17:21 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 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
82 #include <sys/proc.h>
83 #endif
84 #include <sys/time.h>
85 #include <sys/kernel.h>
86 #include <sys/syslog.h>
87
88 #include <net/if.h>
89 #include <net/if_types.h>
90 #include <net/route.h>
91 #include "gif.h"
92 #if NGIF > 0
93 #include <net/if_gif.h>
94 #endif
95 #include <net/if_dl.h>
96
97 #include <netinet/in.h>
98 #include <netinet/in_var.h>
99 #ifdef __NetBSD__
100 #include <net/if_ether.h>
101 #else
102 #include <netinet/if_ether.h>
103 #endif
104
105 #include <netinet6/nd6.h>
106 #include <netinet6/ip6.h>
107 #include <netinet6/ip6_var.h>
108 #include <netinet6/mld6_var.h>
109 #include <netinet6/ip6_mroute.h>
110 #include <netinet6/in6_ifattach.h>
111
112 #include <net/net_osdep.h>
113
114 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
115 MALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
116 #endif
117
118 /*
119 * Definitions of some costant IP6 addresses.
120 */
121 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
122 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
123 const struct in6_addr in6addr_nodelocal_allnodes =
124 IN6ADDR_NODELOCAL_ALLNODES_INIT;
125 const struct in6_addr in6addr_linklocal_allnodes =
126 IN6ADDR_LINKLOCAL_ALLNODES_INIT;
127 const struct in6_addr in6addr_linklocal_allrouters =
128 IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
129
130 const struct in6_addr in6mask0 = IN6MASK0;
131 const struct in6_addr in6mask32 = IN6MASK32;
132 const struct in6_addr in6mask64 = IN6MASK64;
133 const struct in6_addr in6mask96 = IN6MASK96;
134 const struct in6_addr in6mask128 = IN6MASK128;
135
136 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
137 static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
138 struct ifnet *, struct proc *));
139 #else
140 static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
141 struct ifnet *));
142 #endif
143
144 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
145 struct in6_multihead in6_multihead; /* XXX BSS initialization */
146 #else
147 /*
148 * This structure is used to keep track of in6_multi chains which belong to
149 * deleted interface addresses.
150 */
151 static LIST_HEAD(, multi6_kludge) in6_mk; /* XXX BSS initialization */
152
153 struct multi6_kludge {
154 LIST_ENTRY(multi6_kludge) mk_entry;
155 struct ifnet *mk_ifp;
156 struct in6_multihead mk_head;
157 };
158 #endif
159
160 /*
161 * Determine whether an IP6 address is in a reserved set of addresses
162 * that may not be forwarded, or whether datagrams to that destination
163 * may be forwarded.
164 */
165 int
166 in6_canforward(src, dst)
167 struct in6_addr *src, *dst;
168 {
169 if (IN6_IS_ADDR_LINKLOCAL(src) ||
170 IN6_IS_ADDR_LINKLOCAL(dst) ||
171 IN6_IS_ADDR_MULTICAST(dst))
172 return(0);
173 return(1);
174 }
175
176 /*
177 * Check if the loopback entry will be automatically generated.
178 * if 0 returned, will not be automatically generated.
179 * if 1 returned, will be automatically generated.
180 */
181 static int
182 in6_is_ifloop_auto(struct ifaddr *ifa)
183 {
184 #ifdef __OpenBSD__
185 return 0;
186 #else
187 #define SIN6(s) ((struct sockaddr_in6 *)s)
188 /*
189 * If RTF_CLONING is unset, or (IFF_LOOPBACK | IFF_POINTOPOINT),
190 * or netmask is all0 or all1, then cloning will not happen,
191 * then we can't rely on its loopback entry generation.
192 */
193 if ((ifa->ifa_flags & RTF_CLONING) == 0 ||
194 (ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) ||
195 (SIN6(ifa->ifa_netmask)->sin6_len == sizeof(struct sockaddr_in6)
196 &&
197 IN6_ARE_ADDR_EQUAL(&SIN6(ifa->ifa_netmask)->sin6_addr,
198 &in6mask128)) ||
199 ((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_len == 0)
200 return 0;
201 else
202 return 1;
203 #undef SIN6
204 #endif
205 }
206
207 /*
208 * Subroutine for in6_ifaddloop() and in6_ifremloop().
209 * This routine does actual work.
210 */
211 static void
212 in6_ifloop_request(int cmd, struct ifaddr *ifa)
213 {
214 struct sockaddr_in6 lo_sa;
215 struct sockaddr_in6 all1_sa;
216 struct rtentry *nrt = NULL;
217
218 bzero(&lo_sa, sizeof(lo_sa));
219 bzero(&all1_sa, sizeof(all1_sa));
220 lo_sa.sin6_family = AF_INET6;
221 lo_sa.sin6_len = sizeof(struct sockaddr_in6);
222 all1_sa = lo_sa;
223 lo_sa.sin6_addr = in6addr_loopback;
224 all1_sa.sin6_addr = in6mask128;
225
226 /* So we add or remove static loopback entry, here. */
227 rtrequest(cmd, ifa->ifa_addr,
228 (struct sockaddr *)&lo_sa,
229 (struct sockaddr *)&all1_sa,
230 RTF_UP|RTF_HOST, &nrt);
231
232 /*
233 * Make sure rt_ifa be equal to IFA, the second argument of the
234 * function.
235 * We need this because when we refer rt_ifa->ia6_flags in ip6_input,
236 * we assume that the rt_ifa points to the address instead of the
237 * loopback address.
238 */
239 if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
240 nrt->rt_ifa->ifa_refcnt--;
241 ifa->ifa_refcnt++;
242 nrt->rt_ifa = ifa;
243 }
244 if (nrt)
245 nrt->rt_refcnt--;
246 }
247
248 /*
249 * Add ownaddr as loopback rtentry, if necessary(ex. on p2p link).
250 * Because, KAME needs loopback rtentry for ownaddr check in
251 * ip6_input().
252 */
253 static void
254 in6_ifaddloop(struct ifaddr *ifa)
255 {
256 if (!in6_is_ifloop_auto(ifa)) {
257 struct rtentry *rt;
258
259 /* If there is no loopback entry, allocate one. */
260 rt = rtalloc1(ifa->ifa_addr, 0
261 #ifdef __FreeBSD__
262 , 0
263 #endif /* __FreeBSD__ */
264 );
265 if (rt == 0 || (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
266 in6_ifloop_request(RTM_ADD, ifa);
267 if (rt)
268 rt->rt_refcnt--;
269 }
270 }
271
272 /*
273 * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
274 * if it exists.
275 */
276 static void
277 in6_ifremloop(struct ifaddr *ifa)
278 {
279 if (!in6_is_ifloop_auto(ifa)) {
280 struct in6_ifaddr *ia;
281 int ia_count = 0;
282
283 /* If only one ifa for the loopback entry, delete it. */
284 for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
285 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa),
286 &ia->ia_addr.sin6_addr)) {
287 ia_count++;
288 if (ia_count > 1)
289 break;
290 }
291 }
292 if (ia_count == 1)
293 in6_ifloop_request(RTM_DELETE, ifa);
294 }
295 }
296
297 /*
298 * Subroutine for in6_ifaddproxy() and in6_ifremproxy().
299 * This routine does actual work.
300 * call in6_addmulti() when cmd == 1.
301 * call in6_delmulti() when cmd == 2.
302 */
303 static int
304 in6_ifproxy_request(int cmd, struct in6_ifaddr *ia)
305 {
306 int error = 0;
307
308 /*
309 * If we have an IPv6 dstaddr on adding p2p interface,
310 * join dstaddr's solicited multicast on necessary interface.
311 */
312 if ((ia->ia_ifp->if_flags & IFF_POINTOPOINT) &&
313 ia->ia_dstaddr.sin6_family == AF_INET6 &&
314 !IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
315 struct in6_ifaddr *ia_lan;
316
317 /*
318 * TODO: Join only on some specified interfaces by some
319 * configuration.
320 * Unsolicited Neighbor Advertisements will be also necessary.
321 *
322 * Now, join on interfaces which meets following.
323 * -IFF_BROADCAST and IFF_MULTICAST
324 * (NBMA is out of scope)
325 * -the prefix value is same as p2p dstaddr
326 */
327 for (ia_lan = in6_ifaddr; ia_lan; ia_lan = ia_lan->ia_next) {
328 struct in6_addr llsol;
329
330 if ((ia_lan->ia_ifp->if_flags &
331 (IFF_BROADCAST|IFF_MULTICAST)) !=
332 (IFF_BROADCAST|IFF_MULTICAST))
333 continue;
334 if (!IN6_ARE_MASKED_ADDR_EQUAL(IA6_IN6(ia),
335 IA6_IN6(ia_lan),
336 IA6_MASKIN6(ia_lan)))
337 continue;
338 if (ia_lan->ia_ifp == ia->ia_ifp)
339 continue;
340
341 /* init llsol */
342 bzero(&llsol, sizeof(struct in6_addr));
343 llsol.s6_addr16[0] = htons(0xff02);
344 llsol.s6_addr16[1] = htons(ia_lan->ia_ifp->if_index);
345 llsol.s6_addr32[1] = 0;
346 llsol.s6_addr32[2] = htonl(1);
347 llsol.s6_addr32[3] =
348 ia->ia_dstaddr.sin6_addr.s6_addr32[3];
349 llsol.s6_addr8[12] = 0xff;
350
351 if (cmd == 1)
352 (void)in6_addmulti(&llsol,
353 ia_lan->ia_ifp,
354 &error);
355 else if (cmd == 2) {
356 struct in6_multi *in6m;
357
358 IN6_LOOKUP_MULTI(llsol,
359 ia_lan->ia_ifp,
360 in6m);
361 if (in6m)
362 in6_delmulti(in6m);
363 }
364 }
365 }
366 return error;
367 }
368
369 static int
370 in6_ifaddproxy(struct in6_ifaddr *ia)
371 {
372 return(in6_ifproxy_request(1, ia));
373 }
374
375 static void
376 in6_ifremproxy(struct in6_ifaddr *ia)
377 {
378 in6_ifproxy_request(2, ia);
379 }
380
381 int
382 in6_ifindex2scopeid(idx)
383 int idx;
384 {
385 struct ifnet *ifp;
386 struct ifaddr *ifa;
387 struct sockaddr_in6 *sin6;
388
389 if (idx < 0 || if_index < idx)
390 return -1;
391 ifp = ifindex2ifnet[idx];
392
393 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
394 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
395 #else
396 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
397 #endif
398 {
399 if (ifa->ifa_addr->sa_family != AF_INET6)
400 continue;
401 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
402 if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
403 return sin6->sin6_scope_id & 0xffff;
404 }
405
406 return -1;
407 }
408
409 int
410 in6_mask2len(mask)
411 struct in6_addr *mask;
412 {
413 int x, y;
414
415 for (x = 0; x < sizeof(*mask); x++) {
416 if (mask->s6_addr8[x] != 0xff)
417 break;
418 }
419 y = 0;
420 if (x < sizeof(*mask)) {
421 for (y = 0; y < 8; y++) {
422 if ((mask->s6_addr8[x] & (0x80 >> y)) == 0)
423 break;
424 }
425 }
426 return x * 8 + y;
427 }
428
429 void
430 in6_len2mask(mask, len)
431 struct in6_addr *mask;
432 int len;
433 {
434 int i;
435
436 bzero(mask, sizeof(*mask));
437 for (i = 0; i < len / 8; i++)
438 mask->s6_addr8[i] = 0xff;
439 if (len % 8)
440 mask->s6_addr8[i] = (0xff00 >> (len % 8)) & 0xff;
441 }
442
443 int in6_interfaces; /* number of external internet interfaces */
444
445 #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
446 #define ia62ifa(ia6) ((struct ifaddr *)(ia6))
447
448 int
449 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
450 in6_control(so, cmd, data, ifp, p)
451 struct socket *so;
452 u_long cmd;
453 caddr_t data;
454 struct ifnet *ifp;
455 struct proc *p;
456 #else
457 in6_control(so, cmd, data, ifp)
458 struct socket *so;
459 u_long cmd;
460 caddr_t data;
461 struct ifnet *ifp;
462 #endif
463 {
464 struct in6_ifreq *ifr = (struct in6_ifreq *)data;
465 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
466 struct ifaddr *ifa;
467 #endif
468 struct in6_ifaddr *ia, *oia;
469 struct in6_aliasreq *ifra = (struct in6_aliasreq *)data;
470 struct sockaddr_in6 oldaddr, net;
471 int error = 0, hostIsNew, prefixIsNew;
472 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
473 time_t time_second = (time_t)time.tv_sec;
474 #endif
475 int privileged;
476
477 privileged = 0;
478 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
479 if (p && !suser(p->p_ucred, &p->p_acflag))
480 privileged++;
481 #else
482 if ((so->so_state & SS_PRIV) != 0)
483 privileged++;
484 #endif
485
486 /*
487 * xxx should prevent processes for link-local addresses?
488 */
489 #if NGIF > 0
490 if (ifp && ifp->if_type == IFT_GIF) {
491 switch (cmd) {
492 case SIOCSIFPHYADDR_IN6:
493 if (!privileged)
494 return(EPERM);
495 /*fall through*/
496 case SIOCGIFPSRCADDR_IN6:
497 case SIOCGIFPDSTADDR_IN6:
498 return gif_ioctl(ifp, cmd, data);
499 }
500 }
501 #endif
502 switch (cmd) {
503 case SIOCGETSGCNT_IN6:
504 case SIOCGETMIFCNT_IN6:
505 return (mrt6_ioctl(cmd, data));
506 }
507
508 if (ifp == 0)
509 return(EOPNOTSUPP);
510
511 switch (cmd) {
512 case SIOCSNDFLUSH_IN6:
513 case SIOCSPFXFLUSH_IN6:
514 case SIOCSRTRFLUSH_IN6:
515 case SIOCSDEFIFACE_IN6:
516 if (!privileged)
517 return(EPERM);
518 /*fall through*/
519 case SIOCGIFINFO_IN6:
520 case SIOCGDRLST_IN6:
521 case SIOCGPRLST_IN6:
522 case SIOCGNBRINFO_IN6:
523 case SIOCGDEFIFACE_IN6:
524 return(nd6_ioctl(cmd, data, ifp));
525 }
526
527 switch (cmd) {
528 case SIOCSIFPREFIX_IN6:
529 case SIOCDIFPREFIX_IN6:
530 case SIOCAIFPREFIX_IN6:
531 case SIOCCIFPREFIX_IN6:
532 case SIOCSGIFPREFIX_IN6:
533 if (!privileged)
534 return(EPERM);
535 /*fall through*/
536 case SIOCGIFPREFIX_IN6:
537 return(in6_prefix_ioctl(so, cmd, data, ifp));
538 }
539
540 switch (cmd) {
541 case SIOCALIFADDR:
542 case SIOCDLIFADDR:
543 if (!privileged)
544 return(EPERM);
545 /*fall through*/
546 case SIOCGLIFADDR:
547 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
548 return in6_lifaddr_ioctl(so, cmd, data, ifp, p);
549 #else
550 return in6_lifaddr_ioctl(so, cmd, data, ifp);
551 #endif
552 }
553
554 /*
555 * Find address for this interface, if it exists.
556 */
557 {
558
559 struct sockaddr_in6 *sa6 =
560 (struct sockaddr_in6 *)&ifra->ifra_addr;
561
562 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
563 if (sa6->sin6_addr.s6_addr16[1] == 0) {
564 /* interface ID is not embedded by the user */
565 sa6->sin6_addr.s6_addr16[1] =
566 htons(ifp->if_index);
567 }
568 else
569 if (sa6->sin6_addr.s6_addr16[1] !=
570 htons(ifp->if_index))
571 return(EINVAL); /* ifid is contradict */
572 if (sa6->sin6_scope_id) {
573 if (sa6->sin6_scope_id !=
574 (u_int32_t)ifp->if_index)
575 return(EINVAL);
576 sa6->sin6_scope_id = 0; /* XXX: good way? */
577 }
578 }
579 }
580 #if 0
581 if (ifra->ifra_addr.sin6_family == AF_INET6) {
582 ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
583 }
584 #else
585 ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
586 #endif
587
588 switch (cmd) {
589
590 case SIOCDIFADDR_IN6:
591 if (ia == 0)
592 return(EADDRNOTAVAIL);
593 /* FALLTHROUGH */
594 case SIOCAIFADDR_IN6:
595 case SIOCSIFADDR_IN6:
596 case SIOCSIFNETMASK_IN6:
597 case SIOCSIFDSTADDR_IN6:
598 if (!privileged)
599 return(EPERM);
600 if (ia == 0) {
601 ia = (struct in6_ifaddr *)
602 malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
603 if (ia == NULL)
604 return (ENOBUFS);
605 bzero((caddr_t)ia, sizeof(*ia));
606 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
607 ia->ia_ifa.ifa_dstaddr
608 = (struct sockaddr *)&ia->ia_dstaddr;
609 ia->ia_ifa.ifa_netmask
610 = (struct sockaddr *)&ia->ia_prefixmask;
611
612 ia->ia_ifp = ifp;
613 if ((oia = in6_ifaddr) != NULL) {
614 for ( ; oia->ia_next; oia = oia->ia_next)
615 continue;
616 oia->ia_next = ia;
617 } else
618 in6_ifaddr = ia;
619 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
620 if ((ifa = ifp->if_addrlist) != NULL) {
621 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
622 continue;
623 ifa->ifa_next = ia62ifa(ia);
624 } else
625 ifp->if_addrlist = ia62ifa(ia);
626 #else
627 TAILQ_INSERT_TAIL(&ifp->if_addrlist,
628 (struct ifaddr *)ia, ifa_list);
629 #endif
630 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
631 in6_interfaces++; /*XXX*/
632 }
633
634 if (cmd == SIOCAIFADDR_IN6) {
635 /* sanity for overflow - beware unsigned */
636 struct in6_addrlifetime *lt;
637 lt = &ifra->ifra_lifetime;
638 if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
639 && lt->ia6t_vltime + time_second < time_second) {
640 return EINVAL;
641 }
642 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
643 && lt->ia6t_pltime + time_second < time_second) {
644 return EINVAL;
645 }
646 }
647 break;
648
649 case SIOCGIFADDR_IN6:
650 /* This interface is basically deprecated. use SIOCGIFCONF. */
651 /* fall through */
652 case SIOCGIFAFLAG_IN6:
653 case SIOCGIFNETMASK_IN6:
654 case SIOCGIFDSTADDR_IN6:
655 case SIOCGIFALIFETIME_IN6:
656 /* must think again about its semantics */
657 if (ia == 0)
658 return(EADDRNOTAVAIL);
659 break;
660 case SIOCSIFALIFETIME_IN6:
661 {
662 struct in6_addrlifetime *lt;
663
664 if (!privileged)
665 return(EPERM);
666 if (ia == 0)
667 return(EADDRNOTAVAIL);
668 /* sanity for overflow - beware unsigned */
669 lt = &ifr->ifr_ifru.ifru_lifetime;
670 if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
671 && lt->ia6t_vltime + time_second < time_second) {
672 return EINVAL;
673 }
674 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
675 && lt->ia6t_pltime + time_second < time_second) {
676 return EINVAL;
677 }
678 break;
679 }
680 }
681
682 switch (cmd) {
683
684 case SIOCGIFADDR_IN6:
685 ifr->ifr_addr = ia->ia_addr;
686 break;
687
688 case SIOCGIFDSTADDR_IN6:
689 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
690 return(EINVAL);
691 ifr->ifr_dstaddr = ia->ia_dstaddr;
692 break;
693
694 case SIOCGIFNETMASK_IN6:
695 ifr->ifr_addr = ia->ia_prefixmask;
696 break;
697
698 case SIOCGIFAFLAG_IN6:
699 ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
700 break;
701
702 case SIOCGIFSTAT_IN6:
703 if (ifp == NULL)
704 return EINVAL;
705 if (in6_ifstat == NULL || ifp->if_index >= in6_ifstatmax
706 || in6_ifstat[ifp->if_index] == NULL) {
707 /* return EAFNOSUPPORT? */
708 bzero(&ifr->ifr_ifru.ifru_stat,
709 sizeof(ifr->ifr_ifru.ifru_stat));
710 } else
711 ifr->ifr_ifru.ifru_stat = *in6_ifstat[ifp->if_index];
712 break;
713
714 case SIOCGIFSTAT_ICMP6:
715 if (ifp == NULL)
716 return EINVAL;
717 if (icmp6_ifstat == NULL || ifp->if_index >= icmp6_ifstatmax ||
718 icmp6_ifstat[ifp->if_index] == NULL) {
719 /* return EAFNOSUPPORT? */
720 bzero(&ifr->ifr_ifru.ifru_stat,
721 sizeof(ifr->ifr_ifru.ifru_icmp6stat));
722 } else
723 ifr->ifr_ifru.ifru_icmp6stat =
724 *icmp6_ifstat[ifp->if_index];
725 break;
726
727 case SIOCSIFDSTADDR_IN6:
728 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
729 return(EINVAL);
730 oldaddr = ia->ia_dstaddr;
731 ia->ia_dstaddr = ifr->ifr_dstaddr;
732
733 /* link-local index check */
734 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
735 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
736 /* interface ID is not embedded by the user */
737 ia->ia_dstaddr.sin6_addr.s6_addr16[1]
738 = htons(ifp->if_index);
739 }
740 else
741 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
742 htons(ifp->if_index)) {
743 ia->ia_dstaddr = oldaddr;
744 return(EINVAL); /* ifid is contradict */
745 }
746 }
747
748 if (ifp->if_ioctl && (error = (ifp->if_ioctl)
749 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
750 ia->ia_dstaddr = oldaddr;
751 return(error);
752 }
753 if (ia->ia_flags & IFA_ROUTE) {
754 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
755 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
756 ia->ia_ifa.ifa_dstaddr =
757 (struct sockaddr *)&ia->ia_dstaddr;
758 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
759 }
760 break;
761
762 case SIOCGIFALIFETIME_IN6:
763 ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
764 break;
765
766 case SIOCSIFALIFETIME_IN6:
767 ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
768 /* for sanity */
769 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
770 ia->ia6_lifetime.ia6t_expire =
771 time_second + ia->ia6_lifetime.ia6t_vltime;
772 } else
773 ia->ia6_lifetime.ia6t_expire = 0;
774 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
775 ia->ia6_lifetime.ia6t_preferred =
776 time_second + ia->ia6_lifetime.ia6t_pltime;
777 } else
778 ia->ia6_lifetime.ia6t_preferred = 0;
779 break;
780
781 case SIOCSIFADDR_IN6:
782 return(in6_ifinit(ifp, ia, &ifr->ifr_addr, 1));
783
784 case SIOCSIFNETMASK_IN6:
785 ia->ia_prefixmask = ifr->ifr_addr;
786 bzero(&net, sizeof(net));
787 net.sin6_len = sizeof(struct sockaddr_in6);
788 net.sin6_family = AF_INET6;
789 net.sin6_port = htons(0);
790 net.sin6_flowinfo = htonl(0);
791 net.sin6_addr.s6_addr32[0]
792 = ia->ia_addr.sin6_addr.s6_addr32[0] &
793 ia->ia_prefixmask.sin6_addr.s6_addr32[0];
794 net.sin6_addr.s6_addr32[1]
795 = ia->ia_addr.sin6_addr.s6_addr32[1] &
796 ia->ia_prefixmask.sin6_addr.s6_addr32[1];
797 net.sin6_addr.s6_addr32[2]
798 = ia->ia_addr.sin6_addr.s6_addr32[2] &
799 ia->ia_prefixmask.sin6_addr.s6_addr32[2];
800 net.sin6_addr.s6_addr32[3]
801 = ia->ia_addr.sin6_addr.s6_addr32[3] &
802 ia->ia_prefixmask.sin6_addr.s6_addr32[3];
803 ia->ia_net = net;
804 break;
805
806 case SIOCAIFADDR_IN6:
807 prefixIsNew = 0;
808 hostIsNew = 1;
809
810 if (ifra->ifra_addr.sin6_len == 0) {
811 ifra->ifra_addr = ia->ia_addr;
812 hostIsNew = 0;
813 } else if (IN6_ARE_ADDR_EQUAL(&ifra->ifra_addr.sin6_addr,
814 &ia->ia_addr.sin6_addr))
815 hostIsNew = 0;
816
817 if (ifra->ifra_prefixmask.sin6_len) {
818 in6_ifscrub(ifp, ia);
819 ia->ia_prefixmask = ifra->ifra_prefixmask;
820 prefixIsNew = 1;
821 }
822 if ((ifp->if_flags & IFF_POINTOPOINT) &&
823 (ifra->ifra_dstaddr.sin6_family == AF_INET6)) {
824 in6_ifscrub(ifp, ia);
825 ia->ia_dstaddr = ifra->ifra_dstaddr;
826 /* link-local index check: should be a separate function? */
827 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
828 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
829 /*
830 * interface ID is not embedded by
831 * the user
832 */
833 ia->ia_dstaddr.sin6_addr.s6_addr16[1]
834 = htons(ifp->if_index);
835 }
836 else
837 if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
838 htons(ifp->if_index)) {
839 ia->ia_dstaddr = oldaddr;
840 return(EINVAL); /* ifid is contradict */
841 }
842 }
843 prefixIsNew = 1; /* We lie; but effect's the same */
844 }
845 if (ifra->ifra_addr.sin6_family == AF_INET6 &&
846 (hostIsNew || prefixIsNew))
847 error = in6_ifinit(ifp, ia, &ifra->ifra_addr, 0);
848 if (ifra->ifra_addr.sin6_family == AF_INET6
849 && hostIsNew && (ifp->if_flags & IFF_MULTICAST)) {
850 int error_local = 0;
851
852 /*
853 * join solicited multicast addr for new host id
854 */
855 struct in6_addr llsol;
856 bzero(&llsol, sizeof(struct in6_addr));
857 llsol.s6_addr16[0] = htons(0xff02);
858 llsol.s6_addr16[1] = htons(ifp->if_index);
859 llsol.s6_addr32[1] = 0;
860 llsol.s6_addr32[2] = htonl(1);
861 llsol.s6_addr32[3] =
862 ifra->ifra_addr.sin6_addr.s6_addr32[3];
863 llsol.s6_addr8[12] = 0xff;
864 (void)in6_addmulti(&llsol, ifp, &error_local);
865 if (error == 0)
866 error = error_local;
867 }
868 /* Join dstaddr's solicited multicast if necessary. */
869 if (nd6_proxyall && hostIsNew) {
870 int error_local;
871
872 error_local = in6_ifaddproxy(ia);
873 if (error == 0)
874 error = error_local;
875 }
876
877 ia->ia6_flags = ifra->ifra_flags;
878 ia->ia6_flags &= ~IN6_IFF_DUPLICATED; /*safety*/
879
880 ia->ia6_lifetime = ifra->ifra_lifetime;
881 /* for sanity */
882 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
883 ia->ia6_lifetime.ia6t_expire =
884 time_second + ia->ia6_lifetime.ia6t_vltime;
885 } else
886 ia->ia6_lifetime.ia6t_expire = 0;
887 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
888 ia->ia6_lifetime.ia6t_preferred =
889 time_second + ia->ia6_lifetime.ia6t_pltime;
890 } else
891 ia->ia6_lifetime.ia6t_preferred = 0;
892
893 /*
894 * Perform DAD, if needed.
895 * XXX It may be of use, if we can administratively
896 * disable DAD.
897 */
898 switch (ifp->if_type) {
899 case IFT_ARCNET:
900 case IFT_ETHER:
901 case IFT_FDDI:
902 #if 0
903 case IFT_ATM:
904 case IFT_SLIP:
905 case IFT_PPP:
906 #endif
907 ia->ia6_flags |= IN6_IFF_TENTATIVE;
908 nd6_dad_start((struct ifaddr *)ia, NULL);
909 break;
910 case IFT_FAITH:
911 case IFT_GIF:
912 case IFT_LOOP:
913 default:
914 break;
915 }
916
917 if (hostIsNew) {
918 int iilen;
919 int error_local = 0;
920
921 iilen = (sizeof(ia->ia_prefixmask.sin6_addr) << 3) -
922 in6_mask2len(&ia->ia_prefixmask.sin6_addr);
923 error_local = in6_prefix_add_ifid(iilen, ia);
924 if (error == 0)
925 error = error_local;
926 }
927
928 return(error);
929
930 case SIOCDIFADDR_IN6:
931 in6_ifscrub(ifp, ia);
932
933 if (ifp->if_flags & IFF_MULTICAST) {
934 /*
935 * delete solicited multicast addr for deleting host id
936 */
937 struct in6_multi *in6m;
938 struct in6_addr llsol;
939 bzero(&llsol, sizeof(struct in6_addr));
940 llsol.s6_addr16[0] = htons(0xff02);
941 llsol.s6_addr16[1] = htons(ifp->if_index);
942 llsol.s6_addr32[1] = 0;
943 llsol.s6_addr32[2] = htonl(1);
944 llsol.s6_addr32[3] =
945 ia->ia_addr.sin6_addr.s6_addr32[3];
946 llsol.s6_addr8[12] = 0xff;
947
948 IN6_LOOKUP_MULTI(llsol, ifp, in6m);
949 if (in6m)
950 in6_delmulti(in6m);
951 }
952 /* Leave dstaddr's solicited multicast if necessary. */
953 if (nd6_proxyall)
954 in6_ifremproxy(ia);
955
956 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
957 if ((ifa = ifp->if_addrlist) == ia62ifa(ia))
958 ifp->if_addrlist = ifa->ifa_next;
959 else {
960 while (ifa->ifa_next &&
961 (ifa->ifa_next != ia62ifa(ia)))
962 ifa = ifa->ifa_next;
963 if (ifa->ifa_next)
964 ifa->ifa_next = ia62ifa(ia)->ifa_next;
965 else
966 printf("Couldn't unlink in6_ifaddr from ifp\n");
967 }
968 #else
969 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
970 #endif
971 oia = ia;
972 if (oia == (ia = in6_ifaddr))
973 in6_ifaddr = ia->ia_next;
974 else {
975 while (ia->ia_next && (ia->ia_next != oia))
976 ia = ia->ia_next;
977 if (ia->ia_next)
978 ia->ia_next = oia->ia_next;
979 else
980 printf("Didn't unlink in6_ifaddr from list\n");
981 }
982 {
983 int iilen;
984
985 iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
986 in6_mask2len(&oia->ia_prefixmask.sin6_addr);
987 in6_prefix_remove_ifid(iilen, oia);
988 }
989 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
990 if (oia->ia6_multiaddrs.lh_first == NULL) {
991 IFAFREE(&oia->ia_ifa);
992 break;
993 }
994 else
995 in6_savemkludge(oia);
996 #endif
997
998 IFAFREE((&oia->ia_ifa));
999 break;
1000
1001 default:
1002 if (ifp == 0 || ifp->if_ioctl == 0)
1003 return(EOPNOTSUPP);
1004 return((*ifp->if_ioctl)(ifp, cmd, data));
1005 }
1006 return(0);
1007 }
1008
1009 /*
1010 * SIOC[GAD]LIFADDR.
1011 * SIOCGLIFADDR: get first address. (???)
1012 * SIOCGLIFADDR with IFLR_PREFIX:
1013 * get first address that matches the specified prefix.
1014 * SIOCALIFADDR: add the specified address.
1015 * SIOCALIFADDR with IFLR_PREFIX:
1016 * add the specified prefix, filling hostid part from
1017 * the first link-local address. prefixlen must be <= 64.
1018 * SIOCDLIFADDR: delete the specified address.
1019 * SIOCDLIFADDR with IFLR_PREFIX:
1020 * delete the first address that matches the specified prefix.
1021 * return values:
1022 * EINVAL on invalid parameters
1023 * EADDRNOTAVAIL on prefix match failed/specified address not found
1024 * other values may be returned from in6_ioctl()
1025 *
1026 * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
1027 * this is to accomodate address naming scheme other than RFC2374,
1028 * in the future.
1029 * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
1030 * address encoding scheme. (see figure on page 8)
1031 */
1032 static int
1033 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
1034 in6_lifaddr_ioctl(so, cmd, data, ifp, p)
1035 struct socket *so;
1036 u_long cmd;
1037 caddr_t data;
1038 struct ifnet *ifp;
1039 struct proc *p;
1040 #else
1041 in6_lifaddr_ioctl(so, cmd, data, ifp)
1042 struct socket *so;
1043 u_long cmd;
1044 caddr_t data;
1045 struct ifnet *ifp;
1046 #endif
1047 {
1048 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
1049 struct ifaddr *ifa;
1050 struct sockaddr *sa;
1051
1052 /* sanity checks */
1053 if (!data || !ifp) {
1054 panic("invalid argument to in6_lifaddr_ioctl");
1055 /*NOTRECHED*/
1056 }
1057
1058 switch (cmd) {
1059 case SIOCGLIFADDR:
1060 /* address must be specified on GET with IFLR_PREFIX */
1061 if ((iflr->flags & IFLR_PREFIX) == 0)
1062 break;
1063 /*FALLTHROUGH*/
1064 case SIOCALIFADDR:
1065 case SIOCDLIFADDR:
1066 /* address must be specified on ADD and DELETE */
1067 sa = (struct sockaddr *)&iflr->addr;
1068 if (sa->sa_family != AF_INET6)
1069 return EINVAL;
1070 if (sa->sa_len != sizeof(struct sockaddr_in6))
1071 return EINVAL;
1072 /* XXX need improvement */
1073 sa = (struct sockaddr *)&iflr->dstaddr;
1074 if (sa->sa_family && sa->sa_family != AF_INET6)
1075 return EINVAL;
1076 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
1077 return EINVAL;
1078 break;
1079 default: /*shouldn't happen*/
1080 #if 0
1081 panic("invalid cmd to in6_lifaddr_ioctl");
1082 /*NOTREACHED*/
1083 #else
1084 return EOPNOTSUPP;
1085 #endif
1086 }
1087 if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
1088 return EINVAL;
1089
1090 switch (cmd) {
1091 case SIOCALIFADDR:
1092 {
1093 struct in6_aliasreq ifra;
1094 struct in6_addr *hostid = NULL;
1095 int prefixlen;
1096
1097 if ((iflr->flags & IFLR_PREFIX) != 0) {
1098 struct sockaddr_in6 *sin6;
1099
1100 /*
1101 * hostid is to fill in the hostid part of the
1102 * address. hostid points to the first link-local
1103 * address attached to the interface.
1104 */
1105 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
1106 if (!ifa)
1107 return EADDRNOTAVAIL;
1108 hostid = IFA_IN6(ifa);
1109
1110 /* prefixlen must be <= 64. */
1111 if (64 < iflr->prefixlen)
1112 return EINVAL;
1113 prefixlen = iflr->prefixlen;
1114
1115 /* hostid part must be zero. */
1116 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1117 if (sin6->sin6_addr.s6_addr32[2] != 0
1118 || sin6->sin6_addr.s6_addr32[3] != 0) {
1119 return EINVAL;
1120 }
1121 } else
1122 prefixlen = iflr->prefixlen;
1123
1124 /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1125 bzero(&ifra, sizeof(ifra));
1126 bcopy(iflr->iflr_name, ifra.ifra_name,
1127 sizeof(ifra.ifra_name));
1128
1129 bcopy(&iflr->addr, &ifra.ifra_addr,
1130 ((struct sockaddr *)&iflr->addr)->sa_len);
1131 if (hostid) {
1132 /* fill in hostid part */
1133 ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1134 hostid->s6_addr32[2];
1135 ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1136 hostid->s6_addr32[3];
1137 }
1138
1139 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/
1140 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1141 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
1142 if (hostid) {
1143 ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1144 hostid->s6_addr32[2];
1145 ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1146 hostid->s6_addr32[3];
1147 }
1148 }
1149
1150 ifra.ifra_prefixmask.sin6_family = AF_INET6;
1151 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1152 in6_len2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
1153
1154 ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1155 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
1156 return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);
1157 #else
1158 return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp);
1159 #endif
1160 }
1161 case SIOCGLIFADDR:
1162 case SIOCDLIFADDR:
1163 {
1164 struct in6_ifaddr *ia;
1165 struct in6_addr mask, candidate, match;
1166 struct sockaddr_in6 *sin6;
1167 int cmp;
1168
1169 bzero(&mask, sizeof(mask));
1170 if (iflr->flags & IFLR_PREFIX) {
1171 /* lookup a prefix rather than address. */
1172 in6_len2mask(&mask, iflr->prefixlen);
1173
1174 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1175 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1176 match.s6_addr32[0] &= mask.s6_addr32[0];
1177 match.s6_addr32[1] &= mask.s6_addr32[1];
1178 match.s6_addr32[2] &= mask.s6_addr32[2];
1179 match.s6_addr32[3] &= mask.s6_addr32[3];
1180
1181 /* if you set extra bits, that's wrong */
1182 if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
1183 return EINVAL;
1184
1185 cmp = 1;
1186 } else {
1187 if (cmd == SIOCGLIFADDR) {
1188 /* on getting an address, take the 1st match */
1189 cmp = 0; /*XXX*/
1190 } else {
1191 /* on deleting an address, do exact match */
1192 in6_len2mask(&mask, 128);
1193 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1194 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1195
1196 cmp = 1;
1197 }
1198 }
1199
1200 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1201 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1202 #else
1203 for (ifa = ifp->if_addrlist.tqh_first;
1204 ifa;
1205 ifa = ifa->ifa_list.tqe_next)
1206 #endif
1207 {
1208 if (ifa->ifa_addr->sa_family != AF_INET6)
1209 continue;
1210 if (!cmp)
1211 break;
1212 bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1213 candidate.s6_addr32[0] &= mask.s6_addr32[0];
1214 candidate.s6_addr32[1] &= mask.s6_addr32[1];
1215 candidate.s6_addr32[2] &= mask.s6_addr32[2];
1216 candidate.s6_addr32[3] &= mask.s6_addr32[3];
1217 if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
1218 break;
1219 }
1220 if (!ifa)
1221 return EADDRNOTAVAIL;
1222 ia = ifa2ia6(ifa);
1223
1224 if (cmd == SIOCGLIFADDR) {
1225 /* fill in the if_laddrreq structure */
1226 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1227
1228 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1229 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1230 ia->ia_dstaddr.sin6_len);
1231 } else
1232 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1233
1234 iflr->prefixlen =
1235 in6_mask2len(&ia->ia_prefixmask.sin6_addr);
1236
1237 iflr->flags = ia->ia6_flags; /*XXX*/
1238
1239 return 0;
1240 } else {
1241 struct in6_aliasreq ifra;
1242
1243 /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1244 bzero(&ifra, sizeof(ifra));
1245 bcopy(iflr->iflr_name, ifra.ifra_name,
1246 sizeof(ifra.ifra_name));
1247
1248 bcopy(&ia->ia_addr, &ifra.ifra_addr,
1249 ia->ia_addr.sin6_len);
1250 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1251 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1252 ia->ia_dstaddr.sin6_len);
1253 }
1254 bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1255 ia->ia_prefixmask.sin6_len);
1256
1257 ifra.ifra_flags = ia->ia6_flags;
1258 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
1259 return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1260 ifp, p);
1261 #else
1262 return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1263 ifp);
1264 #endif
1265 }
1266 }
1267 }
1268
1269 return EOPNOTSUPP; /*just for safety*/
1270 }
1271
1272 /*
1273 * Delete any existing route for an interface.
1274 */
1275 void
1276 in6_ifscrub(ifp, ia)
1277 register struct ifnet *ifp;
1278 register struct in6_ifaddr *ia;
1279 {
1280 if ((ia->ia_flags & IFA_ROUTE) == 0)
1281 return;
1282 if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1283 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1284 else
1285 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1286 ia->ia_flags &= ~IFA_ROUTE;
1287
1288 /* Remove ownaddr's loopback rtentry, if it exists. */
1289 in6_ifremloop(&(ia->ia_ifa));
1290 }
1291
1292 /*
1293 * Initialize an interface's intetnet6 address
1294 * and routing table entry.
1295 */
1296 int
1297 in6_ifinit(ifp, ia, sin6, scrub)
1298 struct ifnet *ifp;
1299 struct in6_ifaddr *ia;
1300 struct sockaddr_in6 *sin6;
1301 int scrub;
1302 {
1303 struct sockaddr_in6 oldaddr;
1304 int error, flags = RTF_UP;
1305 int s = splimp();
1306
1307 oldaddr = ia->ia_addr;
1308 ia->ia_addr = *sin6;
1309 /*
1310 * Give the interface a chance to initialize
1311 * if this is its first address,
1312 * and to validate the address if necessary.
1313 */
1314 if (ifp->if_ioctl &&
1315 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
1316 splx(s);
1317 ia->ia_addr = oldaddr;
1318 return(error);
1319 }
1320
1321 switch (ifp->if_type) {
1322 case IFT_ARCNET:
1323 case IFT_ETHER:
1324 case IFT_FDDI:
1325 ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1326 ia->ia_ifa.ifa_flags |= RTF_CLONING;
1327 break;
1328 case IFT_PPP:
1329 ia->ia_ifa.ifa_rtrequest = nd6_p2p_rtrequest;
1330 ia->ia_ifa.ifa_flags |= RTF_CLONING;
1331 break;
1332 }
1333
1334 splx(s);
1335 if (scrub) {
1336 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1337 in6_ifscrub(ifp, ia);
1338 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1339 }
1340 /* xxx
1341 * in_socktrim
1342 */
1343 /*
1344 * Add route for the network.
1345 */
1346 ia->ia_ifa.ifa_metric = ifp->if_metric;
1347 if (ifp->if_flags & IFF_LOOPBACK) {
1348 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1349 flags |= RTF_HOST;
1350 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1351 if (ia->ia_dstaddr.sin6_family != AF_INET6)
1352 return(0);
1353 flags |= RTF_HOST;
1354 }
1355 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1356 ia->ia_flags |= IFA_ROUTE;
1357
1358 /* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
1359 in6_ifaddloop(&(ia->ia_ifa));
1360
1361 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1362 if (ifp->if_flags & IFF_MULTICAST)
1363 in6_restoremkludge(ia, ifp);
1364 #endif
1365
1366 return(error);
1367 }
1368
1369 /*
1370 * Multicast address kludge:
1371 * If there were any multicast addresses attached to this interface address,
1372 * either move them to another address on this interface, or save them until
1373 * such time as this interface is reconfigured for IPv6.
1374 */
1375 void
1376 in6_savemkludge(oia)
1377 struct in6_ifaddr *oia;
1378 {
1379 struct in6_ifaddr *ia;
1380 struct in6_multi *in6m, *next;
1381
1382 IFP_TO_IA6(oia->ia_ifp, ia);
1383 if (ia) { /* there is another address */
1384 for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
1385 next = in6m->in6m_entry.le_next;
1386 IFAFREE(&in6m->in6m_ia->ia_ifa);
1387 ia->ia_ifa.ifa_refcnt++;
1388 in6m->in6m_ia = ia;
1389 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1390 }
1391 } else { /* last address on this if deleted, save */
1392 struct multi6_kludge *mk;
1393
1394 mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);
1395
1396 LIST_INIT(&mk->mk_head);
1397 mk->mk_ifp = oia->ia_ifp;
1398
1399 for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
1400 next = in6m->in6m_entry.le_next;
1401 LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
1402 }
1403
1404 if (mk->mk_head.lh_first != NULL) {
1405 LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
1406 }
1407 else {
1408 FREE(mk, M_IPMADDR);
1409 }
1410 }
1411 }
1412
1413 /*
1414 * Continuation of multicast address hack:
1415 * If there was a multicast group list previously saved for this interface,
1416 * then we re-attach it to the first address configured on the i/f.
1417 */
1418 void
1419 in6_restoremkludge(ia, ifp)
1420 struct in6_ifaddr *ia;
1421 struct ifnet *ifp;
1422 {
1423 struct multi6_kludge *mk;
1424
1425 for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
1426 if (mk->mk_ifp == ifp) {
1427 struct in6_multi *in6m, *next;
1428
1429 for (in6m = mk->mk_head.lh_first; in6m; in6m = next){
1430 next = in6m->in6m_entry.le_next;
1431 LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
1432 in6m, in6m_entry);
1433 }
1434 LIST_REMOVE(mk, mk_entry);
1435 free(mk, M_IPMADDR);
1436 break;
1437 }
1438 }
1439 }
1440
1441 /*
1442 * Add an address to the list of IP6 multicast addresses for a
1443 * given interface.
1444 */
1445 struct in6_multi *
1446 in6_addmulti(maddr6, ifp, errorp)
1447 register struct in6_addr *maddr6;
1448 register struct ifnet *ifp;
1449 int *errorp;
1450 {
1451 struct in6_ifaddr *ia;
1452 struct in6_ifreq ifr;
1453 struct in6_multi *in6m;
1454 #ifdef __NetBSD__
1455 int s = splsoftnet();
1456 #else
1457 int s = splnet();
1458 #endif
1459
1460 *errorp = 0;
1461 /*
1462 * See if address already in list.
1463 */
1464 IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
1465 if (in6m != NULL) {
1466 /*
1467 * Found it; just increment the refrence count.
1468 */
1469 in6m->in6m_refcount++;
1470 } else {
1471 /*
1472 * New address; allocate a new multicast record
1473 * and link it into the interface's multicast list.
1474 */
1475 in6m = (struct in6_multi *)
1476 malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1477 if (in6m == NULL) {
1478 splx(s);
1479 *errorp = ENOBUFS;
1480 return(NULL);
1481 }
1482 in6m->in6m_addr = *maddr6;
1483 in6m->in6m_ifp = ifp;
1484 in6m->in6m_refcount = 1;
1485 IFP_TO_IA6(ifp, ia);
1486 if (ia == NULL) {
1487 free(in6m, M_IPMADDR);
1488 splx(s);
1489 *errorp = EADDRNOTAVAIL; /* appropriate? */
1490 return(NULL);
1491 }
1492 in6m->in6m_ia = ia;
1493 ia->ia_ifa.ifa_refcnt++; /* gain a reference */
1494 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1495
1496 /*
1497 * Ask the network driver to update its multicast reception
1498 * filter appropriately for the new address.
1499 */
1500 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1501 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1502 ifr.ifr_addr.sin6_family = AF_INET6;
1503 ifr.ifr_addr.sin6_addr = *maddr6;
1504 if (ifp->if_ioctl == NULL)
1505 *errorp = ENXIO; /* XXX: appropriate? */
1506 else
1507 *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,
1508 (caddr_t)&ifr);
1509 if (*errorp) {
1510 LIST_REMOVE(in6m, in6m_entry);
1511 free(in6m, M_IPMADDR);
1512 splx(s);
1513 return(NULL);
1514 }
1515 /*
1516 * Let MLD6 know that we have joined a new IP6 multicast
1517 * group.
1518 */
1519 mld6_start_listening(in6m);
1520 }
1521 splx(s);
1522 return(in6m);
1523 }
1524
1525 /*
1526 * Delete a multicast address record.
1527 */
1528 void
1529 in6_delmulti(in6m)
1530 struct in6_multi *in6m;
1531 {
1532 struct in6_ifreq ifr;
1533 #ifdef __NetBSD__
1534 int s = splsoftnet();
1535 #else
1536 int s = splnet();
1537 #endif
1538
1539 if (--in6m->in6m_refcount == 0) {
1540 /*
1541 * No remaining claims to this record; let MLD6 know
1542 * that we are leaving the multicast group.
1543 */
1544 mld6_stop_listening(in6m);
1545
1546 /*
1547 * Unlink from list.
1548 */
1549 LIST_REMOVE(in6m, in6m_entry);
1550 IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
1551
1552 /*
1553 * Notify the network driver to update its multicast
1554 * reception filter.
1555 */
1556 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1557 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1558 ifr.ifr_addr.sin6_family = AF_INET6;
1559 ifr.ifr_addr.sin6_addr = in6m->in6m_addr;
1560 (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,
1561 SIOCDELMULTI, (caddr_t)&ifr);
1562 free(in6m, M_IPMADDR);
1563 }
1564 splx(s);
1565 }
1566
1567 /*
1568 * Find an IPv6 interface link-local address specific to an interface.
1569 */
1570 struct in6_ifaddr *
1571 in6ifa_ifpforlinklocal(ifp)
1572 struct ifnet *ifp;
1573 {
1574 register struct ifaddr *ifa;
1575
1576 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1577 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1578 #else
1579 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1580 #endif
1581 {
1582 if (ifa->ifa_addr == NULL)
1583 continue; /* just for safety */
1584 if (ifa->ifa_addr->sa_family != AF_INET6)
1585 continue;
1586 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa)))
1587 break;
1588 }
1589
1590 return((struct in6_ifaddr *)ifa);
1591 }
1592
1593
1594 /*
1595 * find the internet address corresponding to a given interface and address.
1596 */
1597 struct in6_ifaddr *
1598 in6ifa_ifpwithaddr(ifp, addr)
1599 struct ifnet *ifp;
1600 struct in6_addr *addr;
1601 {
1602 register struct ifaddr *ifa;
1603
1604 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1605 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1606 #else
1607 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1608 #endif
1609 {
1610 if (ifa->ifa_addr == NULL)
1611 continue; /* just for safety */
1612 if (ifa->ifa_addr->sa_family != AF_INET6)
1613 continue;
1614 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1615 break;
1616 }
1617
1618 return((struct in6_ifaddr *)ifa);
1619 }
1620
1621 /*
1622 * Convert IP6 address to printable (loggable) representation.
1623 */
1624 static char digits[] = "0123456789abcdef";
1625 static int ip6round = 0;
1626 char *
1627 ip6_sprintf(addr)
1628 register struct in6_addr *addr;
1629 {
1630 static char ip6buf[8][48];
1631 register int i;
1632 register char *cp;
1633 register u_short *a = (u_short *)addr;
1634 register u_char *d;
1635 int dcolon = 0;
1636
1637 ip6round = (ip6round + 1) & 7;
1638 cp = ip6buf[ip6round];
1639
1640 for (i = 0; i < 8; i++) {
1641 if (dcolon == 1) {
1642 if (*a == 0) {
1643 if (i == 7)
1644 *cp++ = ':';
1645 a++;
1646 continue;
1647 } else
1648 dcolon = 2;
1649 }
1650 if (*a == 0) {
1651 if (dcolon == 0 && *(a + 1) == 0) {
1652 if (i == 0)
1653 *cp++ = ':';
1654 *cp++ = ':';
1655 dcolon = 1;
1656 } else {
1657 *cp++ = '0';
1658 *cp++ = ':';
1659 }
1660 a++;
1661 continue;
1662 }
1663 d = (u_char *)a;
1664 *cp++ = digits[*d >> 4];
1665 *cp++ = digits[*d++ & 0xf];
1666 *cp++ = digits[*d >> 4];
1667 *cp++ = digits[*d & 0xf];
1668 *cp++ = ':';
1669 a++;
1670 }
1671 *--cp = 0;
1672 return(ip6buf[ip6round]);
1673 }
1674
1675 int
1676 in6_localaddr(in6)
1677 struct in6_addr *in6;
1678 {
1679 struct in6_ifaddr *ia;
1680
1681 if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
1682 return 1;
1683
1684 for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1685 if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1686 &ia->ia_prefixmask.sin6_addr))
1687 return 1;
1688
1689 return (0);
1690 }
1691
1692 /*
1693 * Get a scope of the address. Node-local, link-local, site-local or global.
1694 */
1695 int
1696 in6_addrscope (addr)
1697 struct in6_addr *addr;
1698 {
1699 int scope;
1700
1701 if (addr->s6_addr8[0] == 0xfe) {
1702 scope = addr->s6_addr8[1] & 0xc0;
1703
1704 switch (scope) {
1705 case 0x80:
1706 return IPV6_ADDR_SCOPE_LINKLOCAL;
1707 break;
1708 case 0xc0:
1709 return IPV6_ADDR_SCOPE_SITELOCAL;
1710 break;
1711 default:
1712 return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
1713 break;
1714 }
1715 }
1716
1717
1718 if (addr->s6_addr8[0] == 0xff) {
1719 scope = addr->s6_addr8[1] & 0x0f;
1720
1721 /*
1722 * due to other scope such as reserved,
1723 * return scope doesn't work.
1724 */
1725 switch (scope) {
1726 case IPV6_ADDR_SCOPE_NODELOCAL:
1727 return IPV6_ADDR_SCOPE_NODELOCAL;
1728 break;
1729 case IPV6_ADDR_SCOPE_LINKLOCAL:
1730 return IPV6_ADDR_SCOPE_LINKLOCAL;
1731 break;
1732 case IPV6_ADDR_SCOPE_SITELOCAL:
1733 return IPV6_ADDR_SCOPE_SITELOCAL;
1734 break;
1735 default:
1736 return IPV6_ADDR_SCOPE_GLOBAL;
1737 break;
1738 }
1739 }
1740
1741 if (bcmp(&in6addr_loopback, addr, sizeof(addr) - 1) == 0) {
1742 if (addr->s6_addr8[15] == 1) /* loopback */
1743 return IPV6_ADDR_SCOPE_NODELOCAL;
1744 if (addr->s6_addr8[15] == 0) /* unspecified */
1745 return IPV6_ADDR_SCOPE_LINKLOCAL;
1746 }
1747
1748 return IPV6_ADDR_SCOPE_GLOBAL;
1749 }
1750
1751 /*
1752 * return length of part which dst and src are equal
1753 * hard coding...
1754 */
1755
1756 int
1757 in6_matchlen(src, dst)
1758 struct in6_addr *src, *dst;
1759 {
1760 int match = 0;
1761 u_char *s = (u_char *)src, *d = (u_char *)dst;
1762 u_char *lim = s + 16, r;
1763
1764 while (s < lim)
1765 if ((r = (*d++ ^ *s++)) != 0) {
1766 while (r < 128) {
1767 match++;
1768 r <<= 1;
1769 }
1770 break;
1771 } else
1772 match += 8;
1773 return match;
1774 }
1775
1776 int
1777 in6_are_prefix_equal(p1, p2, len)
1778 struct in6_addr *p1, *p2;
1779 int len;
1780 {
1781 int bytelen, bitlen;
1782
1783 /* sanity check */
1784 if (0 > len || len > 128) {
1785 log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
1786 len);
1787 return(0);
1788 }
1789
1790 bytelen = len / 8;
1791 bitlen = len % 8;
1792
1793 if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1794 return(0);
1795 if (p1->s6_addr[bytelen] >> (8 - bitlen) !=
1796 p2->s6_addr[bytelen] >> (8 - bitlen))
1797 return(0);
1798
1799 return(1);
1800 }
1801
1802 void
1803 in6_prefixlen2mask(maskp, len)
1804 struct in6_addr *maskp;
1805 int len;
1806 {
1807 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1808 int bytelen, bitlen, i;
1809
1810 /* sanity check */
1811 if (0 > len || len > 128) {
1812 log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
1813 len);
1814 return;
1815 }
1816
1817 bzero(maskp, sizeof(*maskp));
1818 bytelen = len / 8;
1819 bitlen = len % 8;
1820 for (i = 0; i < bytelen; i++)
1821 maskp->s6_addr[i] = 0xff;
1822 if (bitlen)
1823 maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
1824 }
1825
1826 /*
1827 * return the best address out of the same scope
1828 */
1829
1830 struct in6_ifaddr *
1831 in6_ifawithscope(ifp, dst)
1832 register struct ifnet *ifp;
1833 register struct in6_addr *dst;
1834 {
1835 int dst_scope = in6_addrscope(dst), blen = -1, tlen;
1836 struct ifaddr *ifa;
1837 struct in6_ifaddr *besta = NULL, *ia;
1838 struct in6_ifaddr *dep[2]; /*last-resort: deprecated*/
1839
1840 dep[0] = dep[1] = NULL;
1841
1842 /*
1843 * We first look for addresses in the same scope.
1844 * If there is one, return it.
1845 * If two or more, return one which matches the dst longest.
1846 * If none, return one of global addresses assigned other ifs.
1847 */
1848 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1849 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1850 #else
1851 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1852 #endif
1853 {
1854 if (ifa->ifa_addr->sa_family != AF_INET6)
1855 continue;
1856 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1857 continue; /* XXX: is there any case to allow anycast? */
1858 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1859 continue; /* don't use this interface */
1860 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1861 continue;
1862 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1863 if (ip6_use_deprecated)
1864 dep[0] = (struct in6_ifaddr *)ifa;
1865 continue;
1866 }
1867
1868 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
1869 /*
1870 * call in6_matchlen() as few as possible
1871 */
1872 if (besta) {
1873 if (blen == -1)
1874 blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
1875 tlen = in6_matchlen(IFA_IN6(ifa), dst);
1876 if (tlen > blen) {
1877 blen = tlen;
1878 besta = (struct in6_ifaddr *)ifa;
1879 }
1880 } else
1881 besta = (struct in6_ifaddr *)ifa;
1882 }
1883 }
1884 if (besta)
1885 return besta;
1886
1887 for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
1888 if (IPV6_ADDR_SCOPE_GLOBAL !=
1889 in6_addrscope(&(ia->ia_addr.sin6_addr)))
1890 continue;
1891 /* XXX: is there any case to allow anycast? */
1892 if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0)
1893 continue;
1894 if ((ia->ia6_flags & IN6_IFF_NOTREADY) != 0)
1895 continue;
1896 if ((ia->ia6_flags & IN6_IFF_DETACHED) != 0)
1897 continue;
1898 if ((ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
1899 if (ip6_use_deprecated)
1900 dep[1] = (struct in6_ifaddr *)ifa;
1901 continue;
1902 }
1903 return ia;
1904 }
1905
1906 /* use the last-resort values, that are, deprecated addresses */
1907 if (dep[0])
1908 return dep[0];
1909 if (dep[1])
1910 return dep[1];
1911
1912 return NULL;
1913 }
1914
1915 /*
1916 * return the best address out of the same scope. if no address was
1917 * found, return the first valid address from designated IF.
1918 */
1919
1920 struct in6_ifaddr *
1921 in6_ifawithifp(ifp, dst)
1922 register struct ifnet *ifp;
1923 register struct in6_addr *dst;
1924 {
1925 int dst_scope = in6_addrscope(dst), blen = -1, tlen;
1926 struct ifaddr *ifa;
1927 struct in6_ifaddr *besta = 0;
1928 struct in6_ifaddr *dep[2]; /*last-resort: deprecated*/
1929
1930 dep[0] = dep[1] = NULL;
1931
1932 /*
1933 * We first look for addresses in the same scope.
1934 * If there is one, return it.
1935 * If two or more, return one which matches the dst longest.
1936 * If none, return one of global addresses assigned other ifs.
1937 */
1938 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1939 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1940 #else
1941 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1942 #endif
1943 {
1944 if (ifa->ifa_addr->sa_family != AF_INET6)
1945 continue;
1946 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1947 continue; /* XXX: is there any case to allow anycast? */
1948 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1949 continue; /* don't use this interface */
1950 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1951 continue;
1952 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1953 if (ip6_use_deprecated)
1954 dep[0] = (struct in6_ifaddr *)ifa;
1955 continue;
1956 }
1957
1958 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
1959 /*
1960 * call in6_matchlen() as few as possible
1961 */
1962 if (besta) {
1963 if (blen == -1)
1964 blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
1965 tlen = in6_matchlen(IFA_IN6(ifa), dst);
1966 if (tlen > blen) {
1967 blen = tlen;
1968 besta = (struct in6_ifaddr *)ifa;
1969 }
1970 } else
1971 besta = (struct in6_ifaddr *)ifa;
1972 }
1973 }
1974 if (besta)
1975 return(besta);
1976
1977 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1978 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1979 #else
1980 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1981 #endif
1982 {
1983 if (ifa->ifa_addr->sa_family != AF_INET6)
1984 continue;
1985 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1986 continue; /* XXX: is there any case to allow anycast? */
1987 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1988 continue; /* don't use this interface */
1989 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1990 continue;
1991 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1992 if (ip6_use_deprecated)
1993 dep[1] = (struct in6_ifaddr *)ifa;
1994 continue;
1995 }
1996
1997 return (struct in6_ifaddr *)ifa;
1998 }
1999
2000 /* use the last-resort values, that are, deprecated addresses */
2001 if (dep[0])
2002 return dep[0];
2003 if (dep[1])
2004 return dep[1];
2005
2006 return NULL;
2007 }
2008
2009 /*
2010 * perform DAD when interface becomes IFF_UP.
2011 */
2012 void
2013 in6_if_up(ifp)
2014 struct ifnet *ifp;
2015 {
2016 struct ifaddr *ifa;
2017 struct in6_ifaddr *ia;
2018 struct sockaddr_dl *sdl;
2019 int type;
2020 #ifdef __bsdi__
2021 u_char ea[ETHER_ADDR_LEN];
2022 #else
2023 struct ether_addr ea;
2024 #endif
2025 int off;
2026 int dad_delay; /* delay ticks before DAD output */
2027
2028 bzero(&ea, sizeof(ea));
2029 sdl = NULL;
2030
2031 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2032 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2033 #else
2034 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2035 #endif
2036 {
2037 if (ifa->ifa_addr->sa_family == AF_INET6
2038 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
2039 goto dad;
2040 }
2041 if (ifa->ifa_addr->sa_family != AF_LINK)
2042 continue;
2043 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
2044 break;
2045 }
2046
2047 switch (ifp->if_type) {
2048 case IFT_LOOP:
2049 in6_ifattach(ifp, IN6_IFT_LOOP, NULL, 1);
2050 break;
2051 case IFT_SLIP:
2052 case IFT_PPP:
2053 case IFT_GIF:
2054 case IFT_FAITH:
2055 type = IN6_IFT_P2P;
2056 in6_ifattach(ifp, type, 0, 1);
2057 break;
2058 case IFT_ETHER:
2059 case IFT_FDDI:
2060 case IFT_ATM:
2061 type = IN6_IFT_802;
2062 if (sdl == NULL)
2063 break;
2064 off = sdl->sdl_nlen;
2065 if (bcmp(&sdl->sdl_data[off], &ea, sizeof(ea)) != 0)
2066 in6_ifattach(ifp, type, LLADDR(sdl), 0);
2067 break;
2068 case IFT_ARCNET:
2069 type = IN6_IFT_ARCNET;
2070 if (sdl == NULL)
2071 break;
2072 off = sdl->sdl_nlen;
2073 if (sdl->sdl_data[off] != 0) /* XXX ?: */
2074 in6_ifattach(ifp, type, LLADDR(sdl), 0);
2075 break;
2076 default:
2077 break;
2078 }
2079
2080 dad:
2081 dad_delay = 0;
2082 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2083 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2084 #else
2085 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
2086 #endif
2087 {
2088 if (ifa->ifa_addr->sa_family != AF_INET6)
2089 continue;
2090 ia = (struct in6_ifaddr *)ifa;
2091 if (ia->ia6_flags & IN6_IFF_TENTATIVE)
2092 nd6_dad_start(ifa, &dad_delay);
2093 }
2094 }
2095
2096 /*
2097 * Calculate max IPv6 MTU through all the interfaces and store it
2098 * to in6_maxmtu.
2099 */
2100 void
2101 in6_setmaxmtu()
2102 {
2103 unsigned long maxmtu = 0;
2104 struct ifnet *ifp;
2105
2106 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2107 for (ifp = ifnet; ifp; ifp = ifp->if_next)
2108 #else
2109 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
2110 #endif
2111 {
2112 if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2113 nd_ifinfo[ifp->if_index].linkmtu > maxmtu)
2114 maxmtu = nd_ifinfo[ifp->if_index].linkmtu;
2115 }
2116 if (maxmtu) /* update only when maxmtu is positive */
2117 in6_maxmtu = maxmtu;
2118 }
2119