1 /* $KAME: in6.c,v 1.72 2000/03/30 03:45:26 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Copyright (c) 1982, 1986, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
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.
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
64 * @(#)in.c 8.2 (Berkeley) 11/15/93
67 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
71 #include <sys/param.h>
72 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
73 #include <sys/ioctl.h>
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>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
86 #include <net/if_types.h>
87 #include <net/route.h>
90 #include <net/if_gif.h>
92 #include <net/if_dl.h>
94 #include <netinet/in.h>
95 #include <netinet/in_var.h>
97 #include <net/if_ether.h>
99 #include <netinet/if_ether.h>
102 #include <netinet6/nd6.h>
103 #include <netinet/ip6.h>
104 #include <netinet6/ip6_var.h>
105 #include <netinet6/mld6_var.h>
106 #include <netinet6/ip6_mroute.h>
107 #include <netinet6/in6_ifattach.h>
109 #include <net/net_osdep.h>
112 #include <netinet6/mip6.h>
113 #include <netinet6/mip6_common.h>
115 struct nd_prefix
*(*mip6_get_home_prefix_hook
) __P((void));
118 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
119 MALLOC_DEFINE(M_IPMADDR
, "in6_multi", "internet multicast address");
123 * Definitions of some costant IP6 addresses.
125 const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
126 const struct in6_addr in6addr_loopback
= IN6ADDR_LOOPBACK_INIT
;
127 const struct in6_addr in6addr_nodelocal_allnodes
=
128 IN6ADDR_NODELOCAL_ALLNODES_INIT
;
129 const struct in6_addr in6addr_linklocal_allnodes
=
130 IN6ADDR_LINKLOCAL_ALLNODES_INIT
;
131 const struct in6_addr in6addr_linklocal_allrouters
=
132 IN6ADDR_LINKLOCAL_ALLROUTERS_INIT
;
134 const struct in6_addr in6mask0
= IN6MASK0
;
135 const struct in6_addr in6mask32
= IN6MASK32
;
136 const struct in6_addr in6mask64
= IN6MASK64
;
137 const struct in6_addr in6mask96
= IN6MASK96
;
138 const struct in6_addr in6mask128
= IN6MASK128
;
140 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
141 static int in6_lifaddr_ioctl
__P((struct socket
*, u_long
, caddr_t
,
142 struct ifnet
*, struct proc
*));
144 static int in6_lifaddr_ioctl
__P((struct socket
*, u_long
, caddr_t
,
148 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
149 struct in6_multihead in6_multihead
; /* XXX BSS initialization */
152 * This structure is used to keep track of in6_multi chains which belong to
153 * deleted interface addresses.
155 static LIST_HEAD(, multi6_kludge
) in6_mk
; /* XXX BSS initialization */
157 struct multi6_kludge
{
158 LIST_ENTRY(multi6_kludge
) mk_entry
;
159 struct ifnet
*mk_ifp
;
160 struct in6_multihead mk_head
;
165 * Check if the loopback entry will be automatically generated.
166 * if 0 returned, will not be automatically generated.
167 * if 1 returned, will be automatically generated.
170 in6_is_ifloop_auto(struct ifaddr
*ifa
)
172 #define SIN6(s) ((struct sockaddr_in6 *)s)
174 * If RTF_CLONING is unset, or (IFF_LOOPBACK | IFF_POINTOPOINT),
175 * or netmask is all0 or all1, then cloning will not happen,
176 * then we can't rely on its loopback entry generation.
178 if ((ifa
->ifa_flags
& RTF_CLONING
) == 0 ||
179 (ifa
->ifa_ifp
->if_flags
& (IFF_LOOPBACK
| IFF_POINTOPOINT
)) ||
180 (SIN6(ifa
->ifa_netmask
)->sin6_len
== sizeof(struct sockaddr_in6
)
182 IN6_ARE_ADDR_EQUAL(&SIN6(ifa
->ifa_netmask
)->sin6_addr
,
184 ((struct sockaddr_in6
*)ifa
->ifa_netmask
)->sin6_len
== 0)
192 * Subroutine for in6_ifaddloop() and in6_ifremloop().
193 * This routine does actual work.
196 in6_ifloop_request(int cmd
, struct ifaddr
*ifa
)
198 struct sockaddr_in6 lo_sa
;
199 struct sockaddr_in6 all1_sa
;
200 struct rtentry
*nrt
= NULL
;
202 bzero(&lo_sa
, sizeof(lo_sa
));
203 bzero(&all1_sa
, sizeof(all1_sa
));
204 lo_sa
.sin6_family
= AF_INET6
;
205 lo_sa
.sin6_len
= sizeof(struct sockaddr_in6
);
207 lo_sa
.sin6_addr
= in6addr_loopback
;
208 all1_sa
.sin6_addr
= in6mask128
;
210 /* So we add or remove static loopback entry, here. */
211 rtrequest(cmd
, ifa
->ifa_addr
,
212 (struct sockaddr
*)&lo_sa
,
213 (struct sockaddr
*)&all1_sa
,
214 RTF_UP
|RTF_HOST
, &nrt
);
217 * Make sure rt_ifa be equal to IFA, the second argument of the
219 * We need this because when we refer rt_ifa->ia6_flags in ip6_input,
220 * we assume that the rt_ifa points to the address instead of the
223 if (cmd
== RTM_ADD
&& nrt
&& ifa
!= nrt
->rt_ifa
) {
224 IFAFREE(nrt
->rt_ifa
);
227 nrt
->rt_dlt
= ifa
->ifa_dlt
;
234 * Add ownaddr as loopback rtentry, if necessary(ex. on p2p link).
235 * Because, KAME needs loopback rtentry for ownaddr check in
239 in6_ifaddloop(struct ifaddr
*ifa
)
241 if (!in6_is_ifloop_auto(ifa
)) {
244 /* If there is no loopback entry, allocate one. */
245 rt
= rtalloc1(ifa
->ifa_addr
, 0
246 #if defined(__FreeBSD__) || defined (__APPLE__)
248 #endif /* __FreeBSD__ */
250 if (rt
== 0 || (rt
->rt_ifp
->if_flags
& IFF_LOOPBACK
) == 0)
251 in6_ifloop_request(RTM_ADD
, ifa
);
258 * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
262 in6_ifremloop(struct ifaddr
*ifa
)
264 if (!in6_is_ifloop_auto(ifa
)) {
265 struct in6_ifaddr
*ia
;
268 /* If only one ifa for the loopback entry, delete it. */
269 for (ia
= in6_ifaddr
; ia
; ia
= ia
->ia_next
) {
270 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa
),
271 &ia
->ia_addr
.sin6_addr
)) {
278 in6_ifloop_request(RTM_DELETE
, ifa
);
283 in6_ifindex2scopeid(idx
)
288 struct sockaddr_in6
*sin6
;
290 if (idx
< 0 || if_index
< idx
)
292 ifp
= ifindex2ifnet
[idx
];
294 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
295 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
297 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
300 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
302 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
303 if (IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
))
304 return sin6
->sin6_scope_id
& 0xffff;
312 struct in6_addr
*mask
;
316 for (x
= 0; x
< sizeof(*mask
); x
++) {
317 if (mask
->s6_addr8
[x
] != 0xff)
321 if (x
< sizeof(*mask
)) {
322 for (y
= 0; y
< 8; y
++) {
323 if ((mask
->s6_addr8
[x
] & (0x80 >> y
)) == 0)
331 in6_len2mask(mask
, len
)
332 struct in6_addr
*mask
;
337 bzero(mask
, sizeof(*mask
));
338 for (i
= 0; i
< len
/ 8; i
++)
339 mask
->s6_addr8
[i
] = 0xff;
341 mask
->s6_addr8
[i
] = (0xff00 >> (len
% 8)) & 0xff;
344 #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
345 #define ia62ifa(ia6) (&((ia6)->ia_ifa))
348 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
349 in6_control(so
, cmd
, data
, ifp
, p
)
356 in6_control(so
, cmd
, data
, ifp
)
363 struct in6_ifreq
*ifr
= (struct in6_ifreq
*)data
;
364 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
367 struct in6_ifaddr
*ia
= NULL
, *oia
;
368 struct in6_aliasreq
*ifra
= (struct in6_aliasreq
*)data
;
369 struct sockaddr_in6 oldaddr
;
370 #ifdef COMPAT_IN6IFIOCTL
371 struct sockaddr_in6 net
;
373 int error
= 0, hostIsNew
, prefixIsNew
;
375 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
376 time_t time_second
= (time_t)time
.tv_sec
;
382 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
383 if (p
&& !suser(p
->p_ucred
, &p
->p_acflag
))
386 if ((so
->so_state
& SS_PRIV
) != 0)
391 * xxx should prevent processes for link-local addresses?
394 if (ifp
&& ifp
->if_type
== IFT_GIF
) {
396 case SIOCSIFPHYADDR_IN6
:
400 case SIOCGIFPSRCADDR_IN6
:
401 case SIOCGIFPDSTADDR_IN6
:
402 return gif_ioctl(ifp
, cmd
, data
);
407 case SIOCGETSGCNT_IN6
:
408 case SIOCGETMIFCNT_IN6
:
409 return (mrt6_ioctl(cmd
, data
));
412 /* These require root privileges */
414 case SIOCSDEBUG_MIP6
:
415 case SIOCSBCFLUSH_MIP6
:
416 case SIOCSDEFCONFIG_MIP6
:
417 case SIOCSBRUPDATE_MIP6
:
418 case SIOCSENABLEBR_MIP6
:
419 case SIOCSATTACH_MIP6
:
420 case SIOCSRELEASE_MIP6
:
422 case SIOCSHALISTFLUSH_MIP6
:
423 case SIOCSHAPREF_MIP6
:
424 case SIOCSFWDSLUNICAST_MIP6
:
425 case SIOCSFWDSLMULTICAST_MIP6
:
427 case SIOCSFORADDRFLUSH_MIP6
:
428 case SIOCSHADDRFLUSH_MIP6
:
429 case SIOCSBULISTFLUSH_MIP6
:
430 case SIOCACOADDR_MIP6
:
431 case SIOCAHOMEADDR_MIP6
:
432 case SIOCSBULIFETIME_MIP6
:
433 case SIOCSHRLIFETIME_MIP6
:
434 case SIOCDCOADDR_MIP6
:
435 case SIOCSPROMMODE_MIP6
:
436 case SIOCSBU2CN_MIP6
:
437 case SIOCSREVTUNNEL_MIP6
:
438 case SIOCSAUTOCONFIG_MIP6
:
439 case SIOCSEAGERMD_MIP6
:
442 /* Anyone can use these or the user is root */
443 /* case SIOCXVERYSAFECOMMAND_MIP6: */
444 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined(__APPLE__)
445 return mip6_ioctl(so
, cmd
, data
, ifp
, p
);
447 return mip6_ioctl(so
, cmd
, data
, ifp
);
456 case SIOCSNDFLUSH_IN6
:
457 case SIOCSPFXFLUSH_IN6
:
458 case SIOCSRTRFLUSH_IN6
:
459 case SIOCSDEFIFACE_IN6
:
460 case SIOCSIFINFO_FLAGS
:
464 case SIOCGIFINFO_IN6
:
467 case SIOCGNBRINFO_IN6
:
468 case SIOCGDEFIFACE_IN6
:
469 return(nd6_ioctl(cmd
, data
, ifp
));
473 case SIOCSIFPREFIX_IN6
:
474 case SIOCDIFPREFIX_IN6
:
475 case SIOCAIFPREFIX_IN6
:
476 case SIOCCIFPREFIX_IN6
:
477 case SIOCSGIFPREFIX_IN6
:
481 case SIOCGIFPREFIX_IN6
:
482 if (ip6_forwarding
== 0)
484 return(in6_prefix_ioctl(so
, cmd
, data
, ifp
));
494 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
495 return in6_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
);
497 return in6_lifaddr_ioctl(so
, cmd
, data
, ifp
);
502 * Find address for this interface, if it exists.
504 if (ifra
->ifra_addr
.sin6_family
== AF_INET6
) { /* XXX */
505 struct sockaddr_in6
*sa6
=
506 (struct sockaddr_in6
*)&ifra
->ifra_addr
;
508 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
)) {
509 if (sa6
->sin6_addr
.s6_addr16
[1] == 0) {
510 /* interface ID is not embedded by the user */
511 sa6
->sin6_addr
.s6_addr16
[1] =
512 htons(ifp
->if_index
);
513 } else if (sa6
->sin6_addr
.s6_addr16
[1] !=
514 htons(ifp
->if_index
)) {
515 return(EINVAL
); /* ifid is contradict */
517 if (sa6
->sin6_scope_id
) {
518 if (sa6
->sin6_scope_id
!=
519 (u_int32_t
)ifp
->if_index
)
521 sa6
->sin6_scope_id
= 0; /* XXX: good way? */
524 ia
= in6ifa_ifpwithaddr(ifp
, &ifra
->ifra_addr
.sin6_addr
);
529 case SIOCDIFADDR_IN6
:
531 * for IPv4, we look for existing in6_ifaddr here to allow
532 * "ifconfig if0 delete" to remove first IPv4 address on the
533 * interface. For IPv6, as the spec allow multiple interface
534 * address from the day one, we consider "remove the first one"
535 * semantics to be not preferrable.
538 return(EADDRNOTAVAIL
);
540 case SIOCAIFADDR_IN6
:
541 case SIOCSIFADDR_IN6
:
542 #if COMPAT_IN6IFIOCTL
543 case SIOCSIFDSTADDR_IN6
:
544 case SIOCSIFNETMASK_IN6
:
546 * Since IPv6 allows a node to assign multiple addresses
547 * on a single interface, SIOCSIFxxx ioctls are not suitable
548 * and should be unused.
551 if (ifra
->ifra_addr
.sin6_family
!= AF_INET6
)
552 return(EAFNOSUPPORT
);
556 ia
= (struct in6_ifaddr
*)
557 _MALLOC(sizeof(*ia
), M_IFADDR
, M_WAITOK
);
560 bzero((caddr_t
)ia
, sizeof(*ia
));
561 /* Initialize the address and masks */
562 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
563 ia
->ia_addr
.sin6_family
= AF_INET6
;
564 ia
->ia_addr
.sin6_len
= sizeof(ia
->ia_addr
);
565 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
566 ia
->ia_ifa
.ifa_dstaddr
567 = (struct sockaddr
*)&ia
->ia_dstaddr
;
568 ia
->ia_dstaddr
.sin6_family
= AF_INET6
;
569 ia
->ia_dstaddr
.sin6_len
= sizeof(ia
->ia_dstaddr
);
571 ia
->ia_ifa
.ifa_dstaddr
= NULL
;
572 bzero(&ia
->ia_dstaddr
, sizeof(ia
->ia_dstaddr
));
574 ia
->ia_ifa
.ifa_netmask
575 = (struct sockaddr
*)&ia
->ia_prefixmask
;
579 printf("in6_control: Attach dl_tag for if=%s%n\n", ifp
->if_name
, ifp
->if_unit
);
581 if (strcmp(ifp
->if_name
, "en") == 0)
582 dl_tag
= ether_attach_inet6(ifp
);
584 if (strcmp(ifp
->if_name
, "lo") == 0)
585 dl_tag
= lo_attach_inet(ifp
);
587 if (strcmp(ifp
->if_name
, "gif") == 0)
588 dl_tag
= gif_attach_inet(ifp
);
590 /* End of temp code */
591 ia
->ia_ifa
.ifa_dlt
= dl_tag
;
594 if ((oia
= in6_ifaddr
) != NULL
) {
595 for ( ; oia
->ia_next
; oia
= oia
->ia_next
)
600 ia
->ia_ifa
.ifa_refcnt
++;
602 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
603 if ((ifa
= ifp
->if_addrlist
) != NULL
) {
604 for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
606 ifa
->ifa_next
= ia62ifa(ia
);
608 ifp
->if_addrlist
= ia62ifa(ia
);
610 TAILQ_INSERT_TAIL(&ifp
->if_addrlist
, &ia
->ia_ifa
,
613 ia
->ia_ifa
.ifa_refcnt
++;
619 if (cmd
== SIOCAIFADDR_IN6
) {
620 /* sanity for overflow - beware unsigned */
621 struct in6_addrlifetime
*lt
;
622 lt
= &ifra
->ifra_lifetime
;
623 if (lt
->ia6t_vltime
!= ND6_INFINITE_LIFETIME
624 && lt
->ia6t_vltime
+ time_second
< time_second
) {
627 if (lt
->ia6t_pltime
!= ND6_INFINITE_LIFETIME
628 && lt
->ia6t_pltime
+ time_second
< time_second
) {
634 case SIOCGIFADDR_IN6
:
635 /* This interface is basically deprecated. use SIOCGIFCONF. */
637 case SIOCGIFAFLAG_IN6
:
638 case SIOCGIFNETMASK_IN6
:
639 case SIOCGIFDSTADDR_IN6
:
640 case SIOCGIFALIFETIME_IN6
:
641 /* must think again about its semantics */
643 return(EADDRNOTAVAIL
);
645 case SIOCSIFALIFETIME_IN6
:
647 struct in6_addrlifetime
*lt
;
652 return(EADDRNOTAVAIL
);
653 /* sanity for overflow - beware unsigned */
654 lt
= &ifr
->ifr_ifru
.ifru_lifetime
;
655 if (lt
->ia6t_vltime
!= ND6_INFINITE_LIFETIME
656 && lt
->ia6t_vltime
+ time_second
< time_second
) {
659 if (lt
->ia6t_pltime
!= ND6_INFINITE_LIFETIME
660 && lt
->ia6t_pltime
+ time_second
< time_second
) {
669 case SIOCGIFADDR_IN6
:
670 ifr
->ifr_addr
= ia
->ia_addr
;
673 case SIOCGIFDSTADDR_IN6
:
674 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
676 ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
679 case SIOCGIFNETMASK_IN6
:
680 ifr
->ifr_addr
= ia
->ia_prefixmask
;
683 case SIOCGIFAFLAG_IN6
:
684 ifr
->ifr_ifru
.ifru_flags6
= ia
->ia6_flags
;
687 case SIOCGIFSTAT_IN6
:
690 if (in6_ifstat
== NULL
|| ifp
->if_index
>= in6_ifstatmax
691 || in6_ifstat
[ifp
->if_index
] == NULL
) {
692 /* return EAFNOSUPPORT? */
693 bzero(&ifr
->ifr_ifru
.ifru_stat
,
694 sizeof(ifr
->ifr_ifru
.ifru_stat
));
696 ifr
->ifr_ifru
.ifru_stat
= *in6_ifstat
[ifp
->if_index
];
699 case SIOCGIFSTAT_ICMP6
:
702 if (icmp6_ifstat
== NULL
|| ifp
->if_index
>= icmp6_ifstatmax
||
703 icmp6_ifstat
[ifp
->if_index
] == NULL
) {
704 /* return EAFNOSUPPORT? */
705 bzero(&ifr
->ifr_ifru
.ifru_stat
,
706 sizeof(ifr
->ifr_ifru
.ifru_icmp6stat
));
708 ifr
->ifr_ifru
.ifru_icmp6stat
=
709 *icmp6_ifstat
[ifp
->if_index
];
711 #if COMPAT_IN6IFIOCTL /* should be unused */
712 case SIOCSIFDSTADDR_IN6
:
713 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
715 oldaddr
= ia
->ia_dstaddr
;
716 ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
718 /* link-local index check */
719 if (IN6_IS_ADDR_LINKLOCAL(&ia
->ia_dstaddr
.sin6_addr
)) {
720 if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] == 0) {
721 /* interface ID is not embedded by the user */
722 ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1]
723 = htons(ifp
->if_index
);
724 } else if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] !=
725 htons(ifp
->if_index
)) {
726 ia
->ia_dstaddr
= oldaddr
;
727 return(EINVAL
); /* ifid is contradict */
731 error
= dlil_ioctl(0, ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
);
732 if (error
== EOPNOTSUPP
)
735 ia
->ia_dstaddr
= oldaddr
;
739 if (ifp
->if_ioctl
&& (error
= (ifp
->if_ioctl
)
740 (ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
))) {
742 if (ia
->ia_flags
& IFA_ROUTE
) {
743 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
744 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
745 ia
->ia_ifa
.ifa_dstaddr
=
746 (struct sockaddr
*)&ia
->ia_dstaddr
;
747 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
752 case SIOCGIFALIFETIME_IN6
:
753 ifr
->ifr_ifru
.ifru_lifetime
= ia
->ia6_lifetime
;
756 case SIOCSIFALIFETIME_IN6
:
757 ia
->ia6_lifetime
= ifr
->ifr_ifru
.ifru_lifetime
;
759 if (ia
->ia6_lifetime
.ia6t_vltime
!= ND6_INFINITE_LIFETIME
) {
760 ia
->ia6_lifetime
.ia6t_expire
=
761 time_second
+ ia
->ia6_lifetime
.ia6t_vltime
;
763 ia
->ia6_lifetime
.ia6t_expire
= 0;
764 if (ia
->ia6_lifetime
.ia6t_pltime
!= ND6_INFINITE_LIFETIME
) {
765 ia
->ia6_lifetime
.ia6t_preferred
=
766 time_second
+ ia
->ia6_lifetime
.ia6t_pltime
;
768 ia
->ia6_lifetime
.ia6t_preferred
= 0;
771 case SIOCSIFADDR_IN6
:
772 error
= in6_ifinit(ifp
, ia
, &ifr
->ifr_addr
, 1);
775 * the code chokes if we are to assign multiple addresses with
776 * the same address prefix (rtinit() will return EEXIST, which
777 * is not fatal actually). we will get memory leak if we
779 * -> we may want to hide EEXIST from rtinit().
782 if (error
&& newifaddr
) {
783 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
784 if ((ifa
= ifp
->if_addrlist
) == ia62ifa(ia
))
785 ifp
->if_addrlist
= ifa
->ifa_next
;
787 while (ifa
->ifa_next
&&
788 (ifa
->ifa_next
!= ia62ifa(ia
)))
791 ifa
->ifa_next
= ia62ifa(ia
)->ifa_next
;
793 printf("Couldn't unlink in6_ifaddr "
798 TAILQ_REMOVE(&ifp
->if_addrlist
, &ia
->ia_ifa
, ifa_list
);
800 IFAFREE(&ia
->ia_ifa
);
803 if (oia
== (ia
= in6_ifaddr
))
804 in6_ifaddr
= ia
->ia_next
;
806 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
809 ia
->ia_next
= oia
->ia_next
;
811 printf("Didn't unlink in6_ifaddr "
815 IFAFREE(&ia
->ia_ifa
);
820 #if COMPAT_IN6IFIOCTL /* XXX should be unused */
821 case SIOCSIFNETMASK_IN6
:
822 ia
->ia_prefixmask
= ifr
->ifr_addr
;
823 bzero(&net
, sizeof(net
));
824 net
.sin6_len
= sizeof(struct sockaddr_in6
);
825 net
.sin6_family
= AF_INET6
;
826 net
.sin6_port
= htons(0);
827 net
.sin6_flowinfo
= htonl(0);
828 net
.sin6_addr
.s6_addr32
[0]
829 = ia
->ia_addr
.sin6_addr
.s6_addr32
[0] &
830 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[0];
831 net
.sin6_addr
.s6_addr32
[1]
832 = ia
->ia_addr
.sin6_addr
.s6_addr32
[1] &
833 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[1];
834 net
.sin6_addr
.s6_addr32
[2]
835 = ia
->ia_addr
.sin6_addr
.s6_addr32
[2] &
836 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[2];
837 net
.sin6_addr
.s6_addr32
[3]
838 = ia
->ia_addr
.sin6_addr
.s6_addr32
[3] &
839 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[3];
844 case SIOCAIFADDR_IN6
:
848 if (ifra
->ifra_addr
.sin6_len
== 0) {
849 ifra
->ifra_addr
= ia
->ia_addr
;
851 } else if (IN6_ARE_ADDR_EQUAL(&ifra
->ifra_addr
.sin6_addr
,
852 &ia
->ia_addr
.sin6_addr
))
855 /* Validate address families: */
857 * The destination address for a p2p link must have a family
858 * of AF_UNSPEC or AF_INET6.
860 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0 &&
861 ifra
->ifra_dstaddr
.sin6_family
!= AF_INET6
&&
862 ifra
->ifra_dstaddr
.sin6_family
!= AF_UNSPEC
)
863 return(EAFNOSUPPORT
);
865 * The prefixmask must have a family of AF_UNSPEC or AF_INET6.
867 if (ifra
->ifra_prefixmask
.sin6_family
!= AF_INET6
&&
868 ifra
->ifra_prefixmask
.sin6_family
!= AF_UNSPEC
)
869 return(EAFNOSUPPORT
);
871 if (ifra
->ifra_prefixmask
.sin6_len
) {
872 in6_ifscrub(ifp
, ia
);
873 ia
->ia_prefixmask
= ifra
->ifra_prefixmask
;
876 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
877 (ifra
->ifra_dstaddr
.sin6_family
== AF_INET6
)) {
878 in6_ifscrub(ifp
, ia
);
879 oldaddr
= ia
->ia_dstaddr
;
880 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
881 /* link-local index check: should be a separate function? */
882 if (IN6_IS_ADDR_LINKLOCAL(&ia
->ia_dstaddr
.sin6_addr
)) {
883 if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] == 0) {
885 * interface ID is not embedded by
888 ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1]
889 = htons(ifp
->if_index
);
890 } else if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] !=
891 htons(ifp
->if_index
)) {
892 ia
->ia_dstaddr
= oldaddr
;
893 return(EINVAL
); /* ifid is contradict */
896 prefixIsNew
= 1; /* We lie; but effect's the same */
898 if (hostIsNew
|| prefixIsNew
) {
899 error
= in6_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
905 if (hostIsNew
&& (ifp
->if_flags
& IFF_MULTICAST
)) {
909 * join solicited multicast addr for new host id
911 struct in6_addr llsol
;
912 bzero(&llsol
, sizeof(struct in6_addr
));
913 llsol
.s6_addr16
[0] = htons(0xff02);
914 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
915 llsol
.s6_addr32
[1] = 0;
916 llsol
.s6_addr32
[2] = htonl(1);
918 ifra
->ifra_addr
.sin6_addr
.s6_addr32
[3];
919 llsol
.s6_addr8
[12] = 0xff;
920 (void)in6_addmulti(&llsol
, ifp
, &error_local
);
925 ia
->ia6_flags
= ifra
->ifra_flags
;
926 ia
->ia6_flags
&= ~IN6_IFF_DUPLICATED
; /*safety*/
927 ia
->ia6_flags
&= ~IN6_IFF_NODAD
; /* Mobile IPv6 */
929 ia
->ia6_lifetime
= ifra
->ifra_lifetime
;
931 if (ia
->ia6_lifetime
.ia6t_vltime
!= ND6_INFINITE_LIFETIME
) {
932 ia
->ia6_lifetime
.ia6t_expire
=
933 time_second
+ ia
->ia6_lifetime
.ia6t_vltime
;
935 ia
->ia6_lifetime
.ia6t_expire
= 0;
936 if (ia
->ia6_lifetime
.ia6t_pltime
!= ND6_INFINITE_LIFETIME
) {
937 ia
->ia6_lifetime
.ia6t_preferred
=
938 time_second
+ ia
->ia6_lifetime
.ia6t_pltime
;
940 ia
->ia6_lifetime
.ia6t_preferred
= 0;
943 * Perform DAD, if needed.
944 * XXX It may be of use, if we can administratively
947 switch (ifp
->if_type
) {
956 /* Mobile IPv6 modification */
957 if ((ifra
->ifra_flags
& IN6_IFF_NODAD
) == 0) {
958 ia
->ia6_flags
|= IN6_IFF_TENTATIVE
;
959 nd6_dad_start((struct ifaddr
*)ia
, NULL
);
974 iilen
= (sizeof(ia
->ia_prefixmask
.sin6_addr
) << 3) -
975 in6_mask2len(&ia
->ia_prefixmask
.sin6_addr
);
976 error_local
= in6_prefix_add_ifid(iilen
, ia
);
983 case SIOCDIFADDR_IN6
:
984 in6_purgeaddr(&ia
->ia_ifa
, ifp
);
989 error
= dlil_ioctl(0, ifp
, cmd
, (caddr_t
)data
);
990 if (error
== EOPNOTSUPP
)
995 if (ifp
== NULL
|| ifp
->if_ioctl
== 0)
997 return((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
1004 in6_purgeaddr(ifa
, ifp
)
1008 struct in6_ifaddr
*oia
, *ia
= (void *) ifa
;
1010 in6_ifscrub(ifp
, ia
);
1012 if (ifp
->if_flags
& IFF_MULTICAST
) {
1014 * delete solicited multicast addr for deleting host id
1016 struct in6_multi
*in6m
;
1017 struct in6_addr llsol
;
1018 bzero(&llsol
, sizeof(struct in6_addr
));
1019 llsol
.s6_addr16
[0] = htons(0xff02);
1020 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
1021 llsol
.s6_addr32
[1] = 0;
1022 llsol
.s6_addr32
[2] = htonl(1);
1023 llsol
.s6_addr32
[3] =
1024 ia
->ia_addr
.sin6_addr
.s6_addr32
[3];
1025 llsol
.s6_addr8
[12] = 0xff;
1027 IN6_LOOKUP_MULTI(llsol
, ifp
, in6m
);
1032 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1033 if ((ifa
= ifp
->if_addrlist
) == ia62ifa(ia
))
1034 ifp
->if_addrlist
= ifa
->ifa_next
;
1036 while (ifa
->ifa_next
&&
1037 (ifa
->ifa_next
!= ia62ifa(ia
)))
1038 ifa
= ifa
->ifa_next
;
1040 ifa
->ifa_next
= ia62ifa(ia
)->ifa_next
;
1042 printf("Couldn't unlink in6_ifaddr from ifp\n");
1045 TAILQ_REMOVE(&ifp
->if_addrlist
, &ia
->ia_ifa
, ifa_list
);
1047 IFAFREE(&ia
->ia_ifa
);
1050 if (oia
== (ia
= in6_ifaddr
))
1051 in6_ifaddr
= ia
->ia_next
;
1053 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
1056 ia
->ia_next
= oia
->ia_next
;
1058 printf("Didn't unlink in6_ifaddr from list\n");
1063 iilen
= (sizeof(oia
->ia_prefixmask
.sin6_addr
) << 3) -
1064 in6_mask2len(&oia
->ia_prefixmask
.sin6_addr
);
1065 in6_prefix_remove_ifid(iilen
, oia
);
1067 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1068 if (oia
->ia6_multiaddrs
.lh_first
!= NULL
)
1069 in6_savemkludge(oia
);
1072 IFAFREE(&oia
->ia_ifa
);
1077 * SIOCGLIFADDR: get first address. (???)
1078 * SIOCGLIFADDR with IFLR_PREFIX:
1079 * get first address that matches the specified prefix.
1080 * SIOCALIFADDR: add the specified address.
1081 * SIOCALIFADDR with IFLR_PREFIX:
1082 * add the specified prefix, filling hostid part from
1083 * the first link-local address. prefixlen must be <= 64.
1084 * SIOCDLIFADDR: delete the specified address.
1085 * SIOCDLIFADDR with IFLR_PREFIX:
1086 * delete the first address that matches the specified prefix.
1088 * EINVAL on invalid parameters
1089 * EADDRNOTAVAIL on prefix match failed/specified address not found
1090 * other values may be returned from in6_ioctl()
1092 * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
1093 * this is to accomodate address naming scheme other than RFC2374,
1095 * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
1096 * address encoding scheme. (see figure on page 8)
1099 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1100 in6_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
)
1107 in6_lifaddr_ioctl(so
, cmd
, data
, ifp
)
1114 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
1116 struct sockaddr
*sa
;
1119 if (!data
|| !ifp
) {
1120 panic("invalid argument to in6_lifaddr_ioctl");
1126 /* address must be specified on GET with IFLR_PREFIX */
1127 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
1132 /* address must be specified on ADD and DELETE */
1133 sa
= (struct sockaddr
*)&iflr
->addr
;
1134 if (sa
->sa_family
!= AF_INET6
)
1136 if (sa
->sa_len
!= sizeof(struct sockaddr_in6
))
1138 /* XXX need improvement */
1139 sa
= (struct sockaddr
*)&iflr
->dstaddr
;
1140 if (sa
->sa_family
&& sa
->sa_family
!= AF_INET6
)
1142 if (sa
->sa_len
&& sa
->sa_len
!= sizeof(struct sockaddr_in6
))
1145 default: /*shouldn't happen*/
1147 panic("invalid cmd to in6_lifaddr_ioctl");
1153 if (sizeof(struct in6_addr
) * 8 < iflr
->prefixlen
)
1159 struct in6_aliasreq ifra
;
1160 struct in6_addr
*hostid
= NULL
;
1163 if ((iflr
->flags
& IFLR_PREFIX
) != 0) {
1164 struct sockaddr_in6
*sin6
;
1167 * hostid is to fill in the hostid part of the
1168 * address. hostid points to the first link-local
1169 * address attached to the interface.
1171 ifa
= (struct ifaddr
*)in6ifa_ifpforlinklocal(ifp
, 0);
1173 return EADDRNOTAVAIL
;
1174 hostid
= IFA_IN6(ifa
);
1176 /* prefixlen must be <= 64. */
1177 if (64 < iflr
->prefixlen
)
1179 prefixlen
= iflr
->prefixlen
;
1181 /* hostid part must be zero. */
1182 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1183 if (sin6
->sin6_addr
.s6_addr32
[2] != 0
1184 || sin6
->sin6_addr
.s6_addr32
[3] != 0) {
1188 prefixlen
= iflr
->prefixlen
;
1190 /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1191 bzero(&ifra
, sizeof(ifra
));
1192 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1193 sizeof(ifra
.ifra_name
));
1195 bcopy(&iflr
->addr
, &ifra
.ifra_addr
,
1196 ((struct sockaddr
*)&iflr
->addr
)->sa_len
);
1198 /* fill in hostid part */
1199 ifra
.ifra_addr
.sin6_addr
.s6_addr32
[2] =
1200 hostid
->s6_addr32
[2];
1201 ifra
.ifra_addr
.sin6_addr
.s6_addr32
[3] =
1202 hostid
->s6_addr32
[3];
1205 if (((struct sockaddr
*)&iflr
->dstaddr
)->sa_family
) { /*XXX*/
1206 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
1207 ((struct sockaddr
*)&iflr
->dstaddr
)->sa_len
);
1209 ifra
.ifra_dstaddr
.sin6_addr
.s6_addr32
[2] =
1210 hostid
->s6_addr32
[2];
1211 ifra
.ifra_dstaddr
.sin6_addr
.s6_addr32
[3] =
1212 hostid
->s6_addr32
[3];
1216 ifra
.ifra_prefixmask
.sin6_family
= AF_INET6
;
1217 ifra
.ifra_prefixmask
.sin6_len
= sizeof(struct sockaddr_in6
);
1218 in6_len2mask(&ifra
.ifra_prefixmask
.sin6_addr
, prefixlen
);
1220 ifra
.ifra_flags
= iflr
->flags
& ~IFLR_PREFIX
;
1221 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1222 return in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
, ifp
, p
);
1224 return in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
, ifp
);
1230 struct in6_ifaddr
*ia
;
1231 struct in6_addr mask
, candidate
, match
;
1232 struct sockaddr_in6
*sin6
;
1235 bzero(&mask
, sizeof(mask
));
1236 if (iflr
->flags
& IFLR_PREFIX
) {
1237 /* lookup a prefix rather than address. */
1238 in6_len2mask(&mask
, iflr
->prefixlen
);
1240 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1241 bcopy(&sin6
->sin6_addr
, &match
, sizeof(match
));
1242 match
.s6_addr32
[0] &= mask
.s6_addr32
[0];
1243 match
.s6_addr32
[1] &= mask
.s6_addr32
[1];
1244 match
.s6_addr32
[2] &= mask
.s6_addr32
[2];
1245 match
.s6_addr32
[3] &= mask
.s6_addr32
[3];
1247 /* if you set extra bits, that's wrong */
1248 if (bcmp(&match
, &sin6
->sin6_addr
, sizeof(match
)))
1253 if (cmd
== SIOCGLIFADDR
) {
1254 /* on getting an address, take the 1st match */
1257 /* on deleting an address, do exact match */
1258 in6_len2mask(&mask
, 128);
1259 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1260 bcopy(&sin6
->sin6_addr
, &match
, sizeof(match
));
1266 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1267 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1269 for (ifa
= ifp
->if_addrlist
.tqh_first
;
1271 ifa
= ifa
->ifa_list
.tqe_next
)
1274 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1278 bcopy(IFA_IN6(ifa
), &candidate
, sizeof(candidate
));
1279 candidate
.s6_addr32
[0] &= mask
.s6_addr32
[0];
1280 candidate
.s6_addr32
[1] &= mask
.s6_addr32
[1];
1281 candidate
.s6_addr32
[2] &= mask
.s6_addr32
[2];
1282 candidate
.s6_addr32
[3] &= mask
.s6_addr32
[3];
1283 if (IN6_ARE_ADDR_EQUAL(&candidate
, &match
))
1287 return EADDRNOTAVAIL
;
1290 if (cmd
== SIOCGLIFADDR
) {
1291 /* fill in the if_laddrreq structure */
1292 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin6_len
);
1294 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1295 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
1296 ia
->ia_dstaddr
.sin6_len
);
1298 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
1301 in6_mask2len(&ia
->ia_prefixmask
.sin6_addr
);
1303 iflr
->flags
= ia
->ia6_flags
; /*XXX*/
1307 struct in6_aliasreq ifra
;
1309 /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1310 bzero(&ifra
, sizeof(ifra
));
1311 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1312 sizeof(ifra
.ifra_name
));
1314 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
1315 ia
->ia_addr
.sin6_len
);
1316 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1317 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
1318 ia
->ia_dstaddr
.sin6_len
);
1320 bzero(&ifra
.ifra_dstaddr
,
1321 sizeof(ifra
.ifra_dstaddr
));
1323 bcopy(&ia
->ia_prefixmask
, &ifra
.ifra_dstaddr
,
1324 ia
->ia_prefixmask
.sin6_len
);
1326 ifra
.ifra_flags
= ia
->ia6_flags
;
1327 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1328 return in6_control(so
, SIOCDIFADDR_IN6
, (caddr_t
)&ifra
,
1331 return in6_control(so
, SIOCDIFADDR_IN6
, (caddr_t
)&ifra
,
1338 return EOPNOTSUPP
; /*just for safety*/
1342 * Delete any existing route for an interface.
1345 in6_ifscrub(ifp
, ia
)
1346 register struct ifnet
*ifp
;
1347 register struct in6_ifaddr
*ia
;
1349 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1351 if (ifp
->if_flags
& (IFF_LOOPBACK
| IFF_POINTOPOINT
))
1352 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1354 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1355 ia
->ia_flags
&= ~IFA_ROUTE
;
1357 /* Remove ownaddr's loopback rtentry, if it exists. */
1358 in6_ifremloop(&(ia
->ia_ifa
));
1362 * Initialize an interface's intetnet6 address
1363 * and routing table entry.
1366 in6_ifinit(ifp
, ia
, sin6
, scrub
)
1368 struct in6_ifaddr
*ia
;
1369 struct sockaddr_in6
*sin6
;
1372 struct sockaddr_in6 oldaddr
;
1373 int error
, flags
= RTF_UP
;
1377 oldaddr
= ia
->ia_addr
;
1378 ia
->ia_addr
= *sin6
;
1380 * Give the interface a chance to initialize
1381 * if this is its first address,
1382 * and to validate the address if necessary.
1385 error
= dlil_ioctl(0, ifp
, SIOCSIFADDR
, (caddr_t
)ia
) ;
1386 if (error
== EOPNOTSUPP
)
1391 if (ifp
->if_ioctl
&&
1392 (error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, (caddr_t
)ia
))) {
1394 printf("in6_ifinit SIOCSIFADDR for if=%s returns error=%x\n", if_name(ifp
), error
);
1396 ia
->ia_addr
= oldaddr
;
1400 switch (ifp
->if_type
) {
1404 ia
->ia_ifa
.ifa_rtrequest
= nd6_rtrequest
;
1405 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
1408 ia
->ia_ifa
.ifa_rtrequest
= nd6_p2p_rtrequest
;
1409 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
1415 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1416 in6_ifscrub(ifp
, ia
);
1417 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1423 * Add route for the network.
1425 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1426 if (ifp
->if_flags
& IFF_LOOPBACK
) {
1427 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1429 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1430 if (ia
->ia_dstaddr
.sin6_family
!= AF_INET6
)
1434 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1435 ia
->ia_flags
|= IFA_ROUTE
;
1437 /* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
1438 in6_ifaddloop(&(ia
->ia_ifa
));
1440 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1441 if (ifp
->if_flags
& IFF_MULTICAST
)
1442 in6_restoremkludge(ia
, ifp
);
1446 printf("in6_ifinit: Attach dl_tag for if=%s%n\n", ifp
->if_name
, ifp
->if_unit
);
1448 if (strcmp(ifp
->if_name
, "en") == 0)
1449 dl_tag
= ether_attach_inet6(ifp
);
1451 if (strcmp(ifp
->if_name
, "lo") == 0)
1452 dl_tag
= lo_attach_inet(ifp
);
1454 if (strcmp(ifp
->if_name
, "gif") == 0)
1455 dl_tag
= gif_attach_inet(ifp
);
1457 /* End of temp code */
1458 ia
->ia_ifa
.ifa_dlt
= dl_tag
;
1464 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1466 * Multicast address kludge:
1467 * If there were any multicast addresses attached to this interface address,
1468 * either move them to another address on this interface, or save them until
1469 * such time as this interface is reconfigured for IPv6.
1472 in6_savemkludge(oia
)
1473 struct in6_ifaddr
*oia
;
1475 struct in6_ifaddr
*ia
;
1476 struct in6_multi
*in6m
, *next
;
1478 IFP_TO_IA6(oia
->ia_ifp
, ia
);
1479 if (ia
) { /* there is another address */
1480 for (in6m
= oia
->ia6_multiaddrs
.lh_first
; in6m
; in6m
= next
){
1481 next
= in6m
->in6m_entry
.le_next
;
1482 IFAFREE(&in6m
->in6m_ia
->ia_ifa
);
1483 ia
->ia_ifa
.ifa_refcnt
++;
1485 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
, in6m
, in6m_entry
);
1487 } else { /* last address on this if deleted, save */
1488 struct multi6_kludge
*mk
;
1490 mk
= _MALLOC(sizeof(*mk
), M_IPMADDR
, M_WAITOK
);
1492 LIST_INIT(&mk
->mk_head
);
1493 mk
->mk_ifp
= oia
->ia_ifp
;
1495 for (in6m
= oia
->ia6_multiaddrs
.lh_first
; in6m
; in6m
= next
){
1496 next
= in6m
->in6m_entry
.le_next
;
1497 IFAFREE(&in6m
->in6m_ia
->ia_ifa
); /* release reference */
1498 in6m
->in6m_ia
= NULL
;
1499 LIST_INSERT_HEAD(&mk
->mk_head
, in6m
, in6m_entry
);
1502 if (mk
->mk_head
.lh_first
!= NULL
) {
1503 LIST_INSERT_HEAD(&in6_mk
, mk
, mk_entry
);
1505 FREE(mk
, M_IPMADDR
);
1511 * Continuation of multicast address hack:
1512 * If there was a multicast group list previously saved for this interface,
1513 * then we re-attach it to the first address configured on the i/f.
1516 in6_restoremkludge(ia
, ifp
)
1517 struct in6_ifaddr
*ia
;
1520 struct multi6_kludge
*mk
;
1522 for (mk
= in6_mk
.lh_first
; mk
; mk
= mk
->mk_entry
.le_next
) {
1523 if (mk
->mk_ifp
== ifp
) {
1524 struct in6_multi
*in6m
, *next
;
1526 for (in6m
= mk
->mk_head
.lh_first
; in6m
; in6m
= next
){
1527 next
= in6m
->in6m_entry
.le_next
;
1529 ia
->ia_ifa
.ifa_refcnt
++;
1530 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
,
1533 LIST_REMOVE(mk
, mk_entry
);
1534 _FREE(mk
, M_IPMADDR
);
1541 in6_purgemkludge(ifp
)
1544 struct multi6_kludge
*mk
;
1545 struct in6_multi
*in6m
;
1547 for (mk
= in6_mk
.lh_first
; mk
; mk
= mk
->mk_entry
.le_next
) {
1548 if (mk
->mk_ifp
!= ifp
)
1551 /* leave from all multicast groups joined */
1552 while ((in6m
= LIST_FIRST(&mk
->mk_head
)) != NULL
)
1554 LIST_REMOVE(mk
, mk_entry
);
1555 _FREE(mk
, M_IPMADDR
);
1561 * Add an address to the list of IP6 multicast addresses for a
1565 in6_addmulti(maddr6
, ifp
, errorp
)
1566 register struct in6_addr
*maddr6
;
1567 register struct ifnet
*ifp
;
1570 struct in6_ifaddr
*ia
;
1571 struct in6_ifreq ifr
;
1572 struct in6_multi
*in6m
;
1574 int s
= splsoftnet();
1581 * See if address already in list.
1583 IN6_LOOKUP_MULTI(*maddr6
, ifp
, in6m
);
1586 * Found it; just increment the refrence count.
1588 in6m
->in6m_refcount
++;
1591 * New address; allocate a new multicast record
1592 * and link it into the interface's multicast list.
1594 in6m
= (struct in6_multi
*)
1595 _MALLOC(sizeof(*in6m
), M_IPMADDR
, M_NOTWAIT
);
1601 in6m
->in6m_addr
= *maddr6
;
1602 in6m
->in6m_ifp
= ifp
;
1603 in6m
->in6m_refcount
= 1;
1604 IFP_TO_IA6(ifp
, ia
);
1606 _FREE(in6m
, M_IPMADDR
);
1608 *errorp
= EADDRNOTAVAIL
; /* appropriate? */
1612 ia
->ia_ifa
.ifa_refcnt
++; /* gain a reference */
1613 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
, in6m
, in6m_entry
);
1616 * Ask the network driver to update its multicast reception
1617 * filter appropriately for the new address.
1619 bzero(&ifr
.ifr_addr
, sizeof(struct sockaddr_in6
));
1620 ifr
.ifr_addr
.sin6_len
= sizeof(struct sockaddr_in6
);
1621 ifr
.ifr_addr
.sin6_family
= AF_INET6
;
1622 ifr
.ifr_addr
.sin6_addr
= *maddr6
;
1624 *errorp
= dlil_ioctl(0, ifp
, SIOCADDMULTI
, (caddr_t
)&ifr
);
1625 printf("in6_addmulti: if=%s%n dlil_ioctl returns=%d\n", ifp
->if_name
, ifp
->if_unit
, *errorp
);
1626 if (*errorp
== EOPNOTSUPP
)
1630 if (ifp
->if_ioctl
== NULL
)
1631 *errorp
= ENXIO
; /* XXX: appropriate? */
1633 *errorp
= (*ifp
->if_ioctl
)(ifp
, SIOCADDMULTI
,
1637 LIST_REMOVE(in6m
, in6m_entry
);
1638 _FREE(in6m
, M_IPMADDR
);
1643 * Let MLD6 know that we have joined a new IP6 multicast
1646 mld6_start_listening(in6m
);
1653 * Delete a multicast address record.
1657 struct in6_multi
*in6m
;
1659 struct in6_ifreq ifr
;
1661 int s
= splsoftnet();
1666 if (--in6m
->in6m_refcount
== 0) {
1668 * No remaining claims to this record; let MLD6 know
1669 * that we are leaving the multicast group.
1671 mld6_stop_listening(in6m
);
1676 LIST_REMOVE(in6m
, in6m_entry
);
1678 IFAFREE(&in6m
->in6m_ia
->ia_ifa
); /* release reference */
1681 * Notify the network driver to update its multicast
1684 bzero(&ifr
.ifr_addr
, sizeof(struct sockaddr_in6
));
1685 ifr
.ifr_addr
.sin6_len
= sizeof(struct sockaddr_in6
);
1686 ifr
.ifr_addr
.sin6_family
= AF_INET6
;
1687 ifr
.ifr_addr
.sin6_addr
= in6m
->in6m_addr
;
1689 dlil_ioctl(0, in6m
->in6m_ifp
, SIOCDELMULTI
, (caddr_t
)&ifr
);
1691 (*in6m
->in6m_ifp
->if_ioctl
)(in6m
->in6m_ifp
,
1692 SIOCDELMULTI
, (caddr_t
)&ifr
);
1694 _FREE(in6m
, M_IPMADDR
);
1698 #else /* not FreeBSD3 */
1700 * Add an address to the list of IP6 multicast addresses for a
1704 in6_addmulti(maddr6
, ifp
, errorp
)
1705 register struct in6_addr
*maddr6
;
1706 register struct ifnet
*ifp
;
1709 struct in6_multi
*in6m
;
1710 struct sockaddr_in6 sin6
;
1711 struct ifmultiaddr
*ifma
;
1717 * Call generic routine to add membership or increment
1718 * refcount. It wants addresses in the form of a sockaddr,
1719 * so we build one here (being careful to zero the unused bytes).
1721 bzero(&sin6
, sizeof sin6
);
1722 sin6
.sin6_family
= AF_INET6
;
1723 sin6
.sin6_len
= sizeof sin6
;
1724 sin6
.sin6_addr
= *maddr6
;
1725 *errorp
= if_addmulti(ifp
, (struct sockaddr
*)&sin6
, &ifma
);
1732 * If ifma->ifma_protospec is null, then if_addmulti() created
1733 * a new record. Otherwise, we are done.
1735 if (ifma
->ifma_protospec
!= 0)
1736 return ifma
->ifma_protospec
;
1738 /* XXX - if_addmulti uses M_WAITOK. Can this really be called
1739 at interrupt time? If so, need to fix if_addmulti. XXX */
1740 in6m
= (struct in6_multi
*)_MALLOC(sizeof(*in6m
), M_IPMADDR
, M_NOWAIT
);
1746 bzero(in6m
, sizeof *in6m
);
1747 in6m
->in6m_addr
= *maddr6
;
1748 in6m
->in6m_ifp
= ifp
;
1749 in6m
->in6m_ifma
= ifma
;
1750 ifma
->ifma_protospec
= in6m
;
1751 LIST_INSERT_HEAD(&in6_multihead
, in6m
, in6m_entry
);
1754 * Let MLD6 know that we have joined a new IP6 multicast
1757 mld6_start_listening(in6m
);
1763 * Delete a multicast address record.
1767 struct in6_multi
*in6m
;
1769 struct ifmultiaddr
*ifma
= in6m
->in6m_ifma
;
1772 if (ifma
->ifma_refcount
== 1) {
1774 * No remaining claims to this record; let MLD6 know
1775 * that we are leaving the multicast group.
1777 mld6_stop_listening(in6m
);
1778 ifma
->ifma_protospec
= 0;
1779 LIST_REMOVE(in6m
, in6m_entry
);
1780 _FREE(in6m
, M_IPMADDR
);
1782 /* XXX - should be separate API for when we have an ifma? */
1783 if_delmulti(ifma
->ifma_ifp
, ifma
->ifma_addr
);
1786 #endif /* not FreeBSD3 */
1789 * Find an IPv6 interface link-local address specific to an interface.
1792 in6ifa_ifpforlinklocal(ifp
, ignoreflags
)
1796 register struct ifaddr
*ifa
;
1798 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1799 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1801 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
1804 if (ifa
->ifa_addr
== NULL
)
1805 continue; /* just for safety */
1806 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1808 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa
))) {
1809 if ((((struct in6_ifaddr
*)ifa
)->ia6_flags
&
1816 return((struct in6_ifaddr
*)ifa
);
1821 * find the internet address corresponding to a given interface and address.
1824 in6ifa_ifpwithaddr(ifp
, addr
)
1826 struct in6_addr
*addr
;
1828 register struct ifaddr
*ifa
;
1830 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1831 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1833 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
1836 if (ifa
->ifa_addr
== NULL
)
1837 continue; /* just for safety */
1838 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1840 if (IN6_ARE_ADDR_EQUAL(addr
, IFA_IN6(ifa
)))
1844 return((struct in6_ifaddr
*)ifa
);
1848 * Convert IP6 address to printable (loggable) representation.
1850 static char digits
[] = "0123456789abcdef";
1851 static int ip6round
= 0;
1854 register struct in6_addr
*addr
;
1856 static char ip6buf
[8][48];
1859 register u_short
*a
= (u_short
*)addr
;
1863 ip6round
= (ip6round
+ 1) & 7;
1864 cp
= ip6buf
[ip6round
];
1866 for (i
= 0; i
< 8; i
++) {
1877 if (dcolon
== 0 && *(a
+ 1) == 0) {
1890 *cp
++ = digits
[*d
>> 4];
1891 *cp
++ = digits
[*d
++ & 0xf];
1892 *cp
++ = digits
[*d
>> 4];
1893 *cp
++ = digits
[*d
& 0xf];
1898 return(ip6buf
[ip6round
]);
1903 struct in6_addr
*in6
;
1905 struct in6_ifaddr
*ia
;
1907 if (IN6_IS_ADDR_LOOPBACK(in6
) || IN6_IS_ADDR_LINKLOCAL(in6
))
1910 for (ia
= in6_ifaddr
; ia
; ia
= ia
->ia_next
)
1911 if (IN6_ARE_MASKED_ADDR_EQUAL(in6
, &ia
->ia_addr
.sin6_addr
,
1912 &ia
->ia_prefixmask
.sin6_addr
))
1919 * Get a scope of the address. Node-local, link-local, site-local or global.
1922 in6_addrscope (addr
)
1923 struct in6_addr
*addr
;
1927 if (addr
->s6_addr8
[0] == 0xfe) {
1928 scope
= addr
->s6_addr8
[1] & 0xc0;
1932 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1935 return IPV6_ADDR_SCOPE_SITELOCAL
;
1938 return IPV6_ADDR_SCOPE_GLOBAL
; /* just in case */
1944 if (addr
->s6_addr8
[0] == 0xff) {
1945 scope
= addr
->s6_addr8
[1] & 0x0f;
1948 * due to other scope such as reserved,
1949 * return scope doesn't work.
1952 case IPV6_ADDR_SCOPE_NODELOCAL
:
1953 return IPV6_ADDR_SCOPE_NODELOCAL
;
1955 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1956 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1958 case IPV6_ADDR_SCOPE_SITELOCAL
:
1959 return IPV6_ADDR_SCOPE_SITELOCAL
;
1962 return IPV6_ADDR_SCOPE_GLOBAL
;
1967 if (bcmp(&in6addr_loopback
, addr
, sizeof(addr
) - 1) == 0) {
1968 if (addr
->s6_addr8
[15] == 1) /* loopback */
1969 return IPV6_ADDR_SCOPE_NODELOCAL
;
1970 if (addr
->s6_addr8
[15] == 0) /* unspecified */
1971 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1974 return IPV6_ADDR_SCOPE_GLOBAL
;
1978 in6_addr2scopeid(ifp
, addr
)
1979 struct ifnet
*ifp
; /* must not be NULL */
1980 struct in6_addr
*addr
; /* must not be NULL */
1982 int scope
= in6_addrscope(addr
);
1985 case IPV6_ADDR_SCOPE_NODELOCAL
:
1986 return(-1); /* XXX: is this an appropriate value? */
1988 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1989 /* XXX: we do not distinguish between a link and an I/F. */
1990 return(ifp
->if_index
);
1992 case IPV6_ADDR_SCOPE_SITELOCAL
:
1993 return(0); /* XXX: invalid. */
1996 return(0); /* XXX: treat as global. */
2001 * return length of part which dst and src are equal
2006 in6_matchlen(src
, dst
)
2007 struct in6_addr
*src
, *dst
;
2010 u_char
*s
= (u_char
*)src
, *d
= (u_char
*)dst
;
2011 u_char
*lim
= s
+ 16, r
;
2014 if ((r
= (*d
++ ^ *s
++)) != 0) {
2026 in6_are_prefix_equal(p1
, p2
, len
)
2027 struct in6_addr
*p1
, *p2
;
2030 int bytelen
, bitlen
;
2033 if (0 > len
|| len
> 128) {
2034 log(LOG_ERR
, "in6_are_prefix_equal: invalid prefix length(%d)\n",
2042 if (bcmp(&p1
->s6_addr
, &p2
->s6_addr
, bytelen
))
2044 if (p1
->s6_addr
[bytelen
] >> (8 - bitlen
) !=
2045 p2
->s6_addr
[bytelen
] >> (8 - bitlen
))
2052 in6_prefixlen2mask(maskp
, len
)
2053 struct in6_addr
*maskp
;
2056 u_char maskarray
[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
2057 int bytelen
, bitlen
, i
;
2060 if (0 > len
|| len
> 128) {
2061 log(LOG_ERR
, "in6_prefixlen2mask: invalid prefix length(%d)\n",
2066 bzero(maskp
, sizeof(*maskp
));
2069 for (i
= 0; i
< bytelen
; i
++)
2070 maskp
->s6_addr
[i
] = 0xff;
2072 maskp
->s6_addr
[bytelen
] = maskarray
[bitlen
- 1];
2076 * return the best address out of the same scope
2079 in6_ifawithscope(oifp
, dst
)
2080 register struct ifnet
*oifp
;
2081 register struct in6_addr
*dst
;
2083 int dst_scope
= in6_addrscope(dst
), src_scope
, best_scope
= 0;
2087 struct in6_ifaddr
*ifa_best
= NULL
;
2090 printf("in6_ifawithscope: output interface is not specified\n");
2095 * We search for all addresses on all interfaces from the beginning.
2096 * Comparing an interface with the outgoing interface will be done
2097 * only at the final stage of tiebreaking.
2099 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2100 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
2102 for (ifp
= TAILQ_FIRST(&ifnet
); ifp
; ifp
= TAILQ_NEXT(ifp
, if_list
))
2106 * We can never take an address that breaks the scope zone
2107 * of the destination.
2109 if (in6_addr2scopeid(ifp
, dst
) != in6_addr2scopeid(oifp
, dst
))
2112 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2113 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2114 #elif defined(__FreeBSD__) && __FreeBSD__ >= 4
2115 TAILQ_FOREACH(ifa
, &ifp
->if_addrlist
, ifa_list
)
2117 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
;
2118 ifa
= ifa
->ifa_list
.tqe_next
)
2121 int tlen
= -1, dscopecmp
, bscopecmp
, matchcmp
;
2123 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2126 src_scope
= in6_addrscope(IFA_IN6(ifa
));
2128 #if ADDRSELECT_DEBUG /* should be removed after stabilization */
2129 dscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
);
2130 printf("in6_ifawithscope: dst=%s bestaddr=%s, "
2131 "newaddr=%s, scope=%x, dcmp=%d, bcmp=%d, "
2132 "matchlen=%d, flgs=%x\n",
2134 ifa_best
? ip6_sprintf(&ifa_best
->ia_addr
.sin6_addr
) : "none",
2135 ip6_sprintf(IFA_IN6(ifa
)), src_scope
,
2137 ifa_best
? IN6_ARE_SCOPE_CMP(src_scope
, best_scope
) : -1,
2138 in6_matchlen(IFA_IN6(ifa
), dst
),
2139 ((struct in6_ifaddr
*)ifa
)->ia6_flags
);
2143 * Don't use an address before completing DAD
2144 * nor a duplicated address.
2146 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2150 /* XXX: is there any case to allow anycasts? */
2151 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2155 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2160 * If this is the first address we find,
2163 if (ifa_best
== NULL
)
2167 * ifa_best is never NULL beyond this line except
2168 * within the block labeled "replace".
2172 * If ifa_best has a smaller scope than dst and
2173 * the current address has a larger one than
2174 * (or equal to) dst, always replace ifa_best.
2175 * Also, if the current address has a smaller scope
2176 * than dst, ignore it unless ifa_best also has a
2179 if (IN6_ARE_SCOPE_CMP(best_scope
, dst_scope
) < 0 &&
2180 IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
) >= 0)
2182 if (IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
) < 0 &&
2183 IN6_ARE_SCOPE_CMP(best_scope
, dst_scope
) >= 0)
2187 * A deprecated address SHOULD NOT be used in new
2188 * communications if an alternate (non-deprecated)
2189 * address is available and has sufficient scope.
2190 * RFC 2462, Section 5.5.4.
2192 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2193 IN6_IFF_DEPRECATED
) {
2195 * Ignore any deprecated addresses if
2196 * specified by configuration.
2198 if (!ip6_use_deprecated
)
2202 * If we have already found a non-deprecated
2203 * candidate, just ignore deprecated addresses.
2205 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
)
2211 * A non-deprecated address is always preferred
2212 * to a deprecated one regardless of scopes and
2215 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
) &&
2216 (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2217 IN6_IFF_DEPRECATED
) == 0)
2221 * At this point, we have two cases:
2222 * 1. we are looking at a non-deprecated address,
2223 * and ifa_best is also non-deprecated.
2224 * 2. we are looking at a deprecated address,
2225 * and ifa_best is also deprecated.
2226 * Also, we do not have to consider a case where
2227 * the scope of if_best is larger(smaller) than dst and
2228 * the scope of the current address is smaller(larger)
2229 * than dst. Such a case has already been covered.
2230 * Tiebreaking is done according to the following
2232 * - the scope comparison between the address and
2234 * - the scope comparison between the address and
2235 * ifa_best (bscopecmp)
2236 * - if the address match dst longer than ifa_best
2238 * - if the address is on the outgoing I/F (outI/F)
2240 * Roughly speaking, the selection policy is
2241 * - the most important item is scope. The same scope
2242 * is best. Then search for a larger scope.
2243 * Smaller scopes are the last resort.
2244 * - A deprecated address is chosen only when we have
2245 * no address that has an enough scope, but is
2246 * prefered to any addresses of smaller scopes.
2247 * - Longest address match against dst is considered
2248 * only for addresses that has the same scope of dst.
2249 * - If there is no other reasons to choose one,
2250 * addresses on the outgoing I/F are preferred.
2252 * The precise decision table is as follows:
2253 * dscopecmp bscopecmp matchcmp outI/F | replace?
2254 * !equal equal N/A Yes | Yes (1)
2255 * !equal equal N/A No | No (2)
2256 * larger larger N/A N/A | No (3)
2257 * larger smaller N/A N/A | Yes (4)
2258 * smaller larger N/A N/A | Yes (5)
2259 * smaller smaller N/A N/A | No (6)
2260 * equal smaller N/A N/A | Yes (7)
2261 * equal larger (already done)
2262 * equal equal larger N/A | Yes (8)
2263 * equal equal smaller N/A | No (9)
2264 * equal equal equal Yes | Yes (a)
2265 * eaual eqaul equal No | No (b)
2267 dscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
);
2268 bscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, best_scope
);
2270 if (dscopecmp
&& bscopecmp
== 0) {
2271 if (oifp
== ifp
) /* (1) */
2275 if (dscopecmp
> 0) {
2276 if (bscopecmp
> 0) /* (3) */
2278 goto replace
; /* (4) */
2280 if (dscopecmp
< 0) {
2281 if (bscopecmp
> 0) /* (5) */
2286 /* now dscopecmp must be 0 */
2288 goto replace
; /* (7) */
2291 * At last both dscopecmp and bscopecmp must be 0.
2292 * We need address matching against dst for
2295 tlen
= in6_matchlen(IFA_IN6(ifa
), dst
);
2296 matchcmp
= tlen
- blen
;
2297 if (matchcmp
> 0) /* (8) */
2299 if (matchcmp
< 0) /* (9) */
2301 if (oifp
== ifp
) /* (a) */
2306 ifa_best
= (struct in6_ifaddr
*)ifa
;
2307 blen
= tlen
>= 0 ? tlen
:
2308 in6_matchlen(IFA_IN6(ifa
), dst
);
2309 best_scope
= in6_addrscope(&ifa_best
->ia_addr
.sin6_addr
);
2313 /* count statistics for future improvements */
2314 if (ifa_best
== NULL
)
2315 ip6stat
.ip6s_sources_none
++;
2317 if (oifp
== ifa_best
->ia_ifp
)
2318 ip6stat
.ip6s_sources_sameif
[best_scope
]++;
2320 ip6stat
.ip6s_sources_otherif
[best_scope
]++;
2322 if (best_scope
== dst_scope
)
2323 ip6stat
.ip6s_sources_samescope
[best_scope
]++;
2325 ip6stat
.ip6s_sources_otherscope
[best_scope
]++;
2327 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
) != 0)
2328 ip6stat
.ip6s_sources_deprecated
[best_scope
]++;
2335 * return the best address out of the same scope. if no address was
2336 * found, return the first valid address from designated IF.
2340 in6_ifawithifp(ifp
, dst
)
2341 register struct ifnet
*ifp
;
2342 register struct in6_addr
*dst
;
2344 int dst_scope
= in6_addrscope(dst
), blen
= -1, tlen
;
2346 struct in6_ifaddr
*besta
= 0;
2347 struct in6_ifaddr
*dep
[2]; /*last-resort: deprecated*/
2349 dep
[0] = dep
[1] = NULL
;
2354 * This is needed to assure that the Home Address is used for
2355 * outgoing packets when not at home. We can't choose any other
2356 * address if we want to keep connections up during movement.
2358 if (mip6_get_home_prefix_hook
) { /* Only Mobile Node */
2359 struct nd_prefix
*pr
;
2360 if ((pr
= (*mip6_get_home_prefix_hook
)()) &&
2361 !IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
))
2363 if (dst_scope
== in6_addrscope(&pr
->ndpr_addr
)) {
2365 /* Noisy but useful */
2366 mip6_debug("%s: Local address %s is chosen "
2367 "for pcb to dest %s.\n",
2369 ip6_sprintf(&pr
->ndpr_addr
),
2372 return(in6ifa_ifpwithaddr(ifp
, &pr
->ndpr_addr
));
2380 * We first look for addresses in the same scope.
2381 * If there is one, return it.
2382 * If two or more, return one which matches the dst longest.
2383 * If none, return one of global addresses assigned other ifs.
2385 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2386 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2388 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2391 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2393 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_ANYCAST
)
2394 continue; /* XXX: is there any case to allow anycast? */
2395 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_NOTREADY
)
2396 continue; /* don't use this interface */
2397 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DETACHED
)
2399 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DEPRECATED
) {
2400 if (ip6_use_deprecated
)
2401 dep
[0] = (struct in6_ifaddr
*)ifa
;
2405 if (dst_scope
== in6_addrscope(IFA_IN6(ifa
))) {
2407 * call in6_matchlen() as few as possible
2411 blen
= in6_matchlen(&besta
->ia_addr
.sin6_addr
, dst
);
2412 tlen
= in6_matchlen(IFA_IN6(ifa
), dst
);
2415 besta
= (struct in6_ifaddr
*)ifa
;
2418 besta
= (struct in6_ifaddr
*)ifa
;
2424 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2425 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2427 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2430 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2432 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_ANYCAST
)
2433 continue; /* XXX: is there any case to allow anycast? */
2434 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_NOTREADY
)
2435 continue; /* don't use this interface */
2436 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DETACHED
)
2438 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DEPRECATED
) {
2439 if (ip6_use_deprecated
)
2440 dep
[1] = (struct in6_ifaddr
*)ifa
;
2444 return (struct in6_ifaddr
*)ifa
;
2447 /* use the last-resort values, that are, deprecated addresses */
2457 * perform DAD when interface becomes IFF_UP.
2464 struct in6_ifaddr
*ia
;
2465 struct sockaddr_dl
*sdl
;
2468 u_char ea
[ETHER_ADDR_LEN
];
2470 struct ether_addr ea
;
2473 int dad_delay
; /* delay ticks before DAD output */
2475 bzero(&ea
, sizeof(ea
));
2478 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2479 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2481 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2484 if (ifa
->ifa_addr
->sa_family
== AF_INET6
2485 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_addr
)) {
2488 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
2490 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
2494 switch (ifp
->if_type
) {
2496 in6_ifattach(ifp
, IN6_IFT_LOOP
, NULL
, 1);
2504 in6_ifattach(ifp
, type
, 0, 1);
2509 * This is VERY awkward to call nd6_ifattach while we will
2510 * not do ND at all on the interface. It is necessary for
2511 * initializing default hoplimit, and ND mtu.
2522 off
= sdl
->sdl_nlen
;
2523 if (bcmp(&sdl
->sdl_data
[off
], &ea
, sizeof(ea
)) != 0)
2524 in6_ifattach(ifp
, type
, LLADDR(sdl
), 0);
2527 type
= IN6_IFT_ARCNET
;
2530 off
= sdl
->sdl_nlen
;
2531 if (sdl
->sdl_data
[off
] != 0) /* XXX ?: */
2532 in6_ifattach(ifp
, type
, LLADDR(sdl
), 0);
2540 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2541 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2543 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2546 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2548 ia
= (struct in6_ifaddr
*)ifa
;
2549 if (ia
->ia6_flags
& IN6_IFF_TENTATIVE
)
2550 nd6_dad_start(ifa
, &dad_delay
);
2555 * Calculate max IPv6 MTU through all the interfaces and store it
2561 unsigned long maxmtu
= 0;
2564 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2565 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
2567 for (ifp
= TAILQ_FIRST(&ifnet
); ifp
; ifp
= TAILQ_NEXT(ifp
, if_list
))
2570 if ((ifp
->if_flags
& IFF_LOOPBACK
) == 0 &&
2571 nd_ifinfo
[ifp
->if_index
].linkmtu
> maxmtu
)
2572 maxmtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
2574 if (maxmtu
) /* update only when maxmtu is positive */
2575 in6_maxmtu
= maxmtu
;
2578 #if MAPPED_ADDR_ENABLED
2580 * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
2581 * v4 mapped addr or v4 compat addr
2584 in6_sin6_2_sin(struct sockaddr_in
*sin
, struct sockaddr_in6
*sin6
)
2586 bzero(sin
, sizeof(*sin
));
2587 sin
->sin_len
= sizeof(struct sockaddr_in
);
2588 sin
->sin_family
= AF_INET
;
2589 sin
->sin_port
= sin6
->sin6_port
;
2590 sin
->sin_addr
.s_addr
= sin6
->sin6_addr
.s6_addr32
[3];
2593 /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
2595 in6_sin_2_v4mapsin6(struct sockaddr_in
*sin
, struct sockaddr_in6
*sin6
)
2597 bzero(sin6
, sizeof(*sin6
));
2598 sin6
->sin6_len
= sizeof(struct sockaddr_in6
);
2599 sin6
->sin6_family
= AF_INET6
;
2600 sin6
->sin6_port
= sin
->sin_port
;
2601 sin6
->sin6_addr
.s6_addr32
[0] = 0;
2602 sin6
->sin6_addr
.s6_addr32
[1] = 0;
2603 sin6
->sin6_addr
.s6_addr32
[2] = IPV6_ADDR_INT32_SMP
;
2604 sin6
->sin6_addr
.s6_addr32
[3] = sin
->sin_addr
.s_addr
;
2607 /* Convert sockaddr_in6 into sockaddr_in. */
2609 in6_sin6_2_sin_in_sock(struct sockaddr
*nam
)
2611 struct sockaddr_in
*sin_p
;
2612 struct sockaddr_in6 sin6
;
2615 * Save original sockaddr_in6 addr and convert it
2618 sin6
= *(struct sockaddr_in6
*)nam
;
2619 sin_p
= (struct sockaddr_in
*)nam
;
2620 in6_sin6_2_sin(sin_p
, &sin6
);
2623 /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
2625 in6_sin_2_v4mapsin6_in_sock(struct sockaddr
**nam
)
2627 struct sockaddr_in
*sin_p
;
2628 struct sockaddr_in6
*sin6_p
;
2630 MALLOC(sin6_p
, struct sockaddr_in6
*, sizeof *sin6_p
, M_SONAME
,
2632 sin_p
= (struct sockaddr_in
*)*nam
;
2633 in6_sin_2_v4mapsin6(sin_p
, sin6_p
);
2634 FREE(*nam
, M_SONAME
);
2635 *nam
= (struct sockaddr
*)sin6_p
;
2637 #endif /* MAPPED_ADDR_ENABLED */