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