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
);
589 /* End of temp code */
590 ia
->ia_ifa
.ifa_dlt
= dl_tag
;
593 if ((oia
= in6_ifaddr
) != NULL
) {
594 for ( ; oia
->ia_next
; oia
= oia
->ia_next
)
599 ia
->ia_ifa
.ifa_refcnt
++;
601 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
602 if ((ifa
= ifp
->if_addrlist
) != NULL
) {
603 for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
605 ifa
->ifa_next
= ia62ifa(ia
);
607 ifp
->if_addrlist
= ia62ifa(ia
);
609 TAILQ_INSERT_TAIL(&ifp
->if_addrlist
, &ia
->ia_ifa
,
612 ia
->ia_ifa
.ifa_refcnt
++;
618 if (cmd
== SIOCAIFADDR_IN6
) {
619 /* sanity for overflow - beware unsigned */
620 struct in6_addrlifetime
*lt
;
621 lt
= &ifra
->ifra_lifetime
;
622 if (lt
->ia6t_vltime
!= ND6_INFINITE_LIFETIME
623 && lt
->ia6t_vltime
+ time_second
< time_second
) {
626 if (lt
->ia6t_pltime
!= ND6_INFINITE_LIFETIME
627 && lt
->ia6t_pltime
+ time_second
< time_second
) {
633 case SIOCGIFADDR_IN6
:
634 /* This interface is basically deprecated. use SIOCGIFCONF. */
636 case SIOCGIFAFLAG_IN6
:
637 case SIOCGIFNETMASK_IN6
:
638 case SIOCGIFDSTADDR_IN6
:
639 case SIOCGIFALIFETIME_IN6
:
640 /* must think again about its semantics */
642 return(EADDRNOTAVAIL
);
644 case SIOCSIFALIFETIME_IN6
:
646 struct in6_addrlifetime
*lt
;
651 return(EADDRNOTAVAIL
);
652 /* sanity for overflow - beware unsigned */
653 lt
= &ifr
->ifr_ifru
.ifru_lifetime
;
654 if (lt
->ia6t_vltime
!= ND6_INFINITE_LIFETIME
655 && lt
->ia6t_vltime
+ time_second
< time_second
) {
658 if (lt
->ia6t_pltime
!= ND6_INFINITE_LIFETIME
659 && lt
->ia6t_pltime
+ time_second
< time_second
) {
668 case SIOCGIFADDR_IN6
:
669 ifr
->ifr_addr
= ia
->ia_addr
;
672 case SIOCGIFDSTADDR_IN6
:
673 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
675 ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
678 case SIOCGIFNETMASK_IN6
:
679 ifr
->ifr_addr
= ia
->ia_prefixmask
;
682 case SIOCGIFAFLAG_IN6
:
683 ifr
->ifr_ifru
.ifru_flags6
= ia
->ia6_flags
;
686 case SIOCGIFSTAT_IN6
:
689 if (in6_ifstat
== NULL
|| ifp
->if_index
>= in6_ifstatmax
690 || in6_ifstat
[ifp
->if_index
] == NULL
) {
691 /* return EAFNOSUPPORT? */
692 bzero(&ifr
->ifr_ifru
.ifru_stat
,
693 sizeof(ifr
->ifr_ifru
.ifru_stat
));
695 ifr
->ifr_ifru
.ifru_stat
= *in6_ifstat
[ifp
->if_index
];
698 case SIOCGIFSTAT_ICMP6
:
701 if (icmp6_ifstat
== NULL
|| ifp
->if_index
>= icmp6_ifstatmax
||
702 icmp6_ifstat
[ifp
->if_index
] == NULL
) {
703 /* return EAFNOSUPPORT? */
704 bzero(&ifr
->ifr_ifru
.ifru_stat
,
705 sizeof(ifr
->ifr_ifru
.ifru_icmp6stat
));
707 ifr
->ifr_ifru
.ifru_icmp6stat
=
708 *icmp6_ifstat
[ifp
->if_index
];
710 #if COMPAT_IN6IFIOCTL /* should be unused */
711 case SIOCSIFDSTADDR_IN6
:
712 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
714 oldaddr
= ia
->ia_dstaddr
;
715 ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
717 /* link-local index check */
718 if (IN6_IS_ADDR_LINKLOCAL(&ia
->ia_dstaddr
.sin6_addr
)) {
719 if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] == 0) {
720 /* interface ID is not embedded by the user */
721 ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1]
722 = htons(ifp
->if_index
);
723 } else if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] !=
724 htons(ifp
->if_index
)) {
725 ia
->ia_dstaddr
= oldaddr
;
726 return(EINVAL
); /* ifid is contradict */
730 error
= dlil_ioctl(0, ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
);
731 if (error
== EOPNOTSUPP
)
734 ia
->ia_dstaddr
= oldaddr
;
738 if (ifp
->if_ioctl
&& (error
= (ifp
->if_ioctl
)
739 (ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
))) {
741 if (ia
->ia_flags
& IFA_ROUTE
) {
742 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
743 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
744 ia
->ia_ifa
.ifa_dstaddr
=
745 (struct sockaddr
*)&ia
->ia_dstaddr
;
746 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
751 case SIOCGIFALIFETIME_IN6
:
752 ifr
->ifr_ifru
.ifru_lifetime
= ia
->ia6_lifetime
;
755 case SIOCSIFALIFETIME_IN6
:
756 ia
->ia6_lifetime
= ifr
->ifr_ifru
.ifru_lifetime
;
758 if (ia
->ia6_lifetime
.ia6t_vltime
!= ND6_INFINITE_LIFETIME
) {
759 ia
->ia6_lifetime
.ia6t_expire
=
760 time_second
+ ia
->ia6_lifetime
.ia6t_vltime
;
762 ia
->ia6_lifetime
.ia6t_expire
= 0;
763 if (ia
->ia6_lifetime
.ia6t_pltime
!= ND6_INFINITE_LIFETIME
) {
764 ia
->ia6_lifetime
.ia6t_preferred
=
765 time_second
+ ia
->ia6_lifetime
.ia6t_pltime
;
767 ia
->ia6_lifetime
.ia6t_preferred
= 0;
770 case SIOCSIFADDR_IN6
:
771 error
= in6_ifinit(ifp
, ia
, &ifr
->ifr_addr
, 1);
774 * the code chokes if we are to assign multiple addresses with
775 * the same address prefix (rtinit() will return EEXIST, which
776 * is not fatal actually). we will get memory leak if we
778 * -> we may want to hide EEXIST from rtinit().
781 if (error
&& newifaddr
) {
782 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
783 if ((ifa
= ifp
->if_addrlist
) == ia62ifa(ia
))
784 ifp
->if_addrlist
= ifa
->ifa_next
;
786 while (ifa
->ifa_next
&&
787 (ifa
->ifa_next
!= ia62ifa(ia
)))
790 ifa
->ifa_next
= ia62ifa(ia
)->ifa_next
;
792 printf("Couldn't unlink in6_ifaddr "
797 TAILQ_REMOVE(&ifp
->if_addrlist
, &ia
->ia_ifa
, ifa_list
);
799 IFAFREE(&ia
->ia_ifa
);
802 if (oia
== (ia
= in6_ifaddr
))
803 in6_ifaddr
= ia
->ia_next
;
805 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
808 ia
->ia_next
= oia
->ia_next
;
810 printf("Didn't unlink in6_ifaddr "
814 IFAFREE(&ia
->ia_ifa
);
819 #if COMPAT_IN6IFIOCTL /* XXX should be unused */
820 case SIOCSIFNETMASK_IN6
:
821 ia
->ia_prefixmask
= ifr
->ifr_addr
;
822 bzero(&net
, sizeof(net
));
823 net
.sin6_len
= sizeof(struct sockaddr_in6
);
824 net
.sin6_family
= AF_INET6
;
825 net
.sin6_port
= htons(0);
826 net
.sin6_flowinfo
= htonl(0);
827 net
.sin6_addr
.s6_addr32
[0]
828 = ia
->ia_addr
.sin6_addr
.s6_addr32
[0] &
829 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[0];
830 net
.sin6_addr
.s6_addr32
[1]
831 = ia
->ia_addr
.sin6_addr
.s6_addr32
[1] &
832 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[1];
833 net
.sin6_addr
.s6_addr32
[2]
834 = ia
->ia_addr
.sin6_addr
.s6_addr32
[2] &
835 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[2];
836 net
.sin6_addr
.s6_addr32
[3]
837 = ia
->ia_addr
.sin6_addr
.s6_addr32
[3] &
838 ia
->ia_prefixmask
.sin6_addr
.s6_addr32
[3];
843 case SIOCAIFADDR_IN6
:
847 if (ifra
->ifra_addr
.sin6_len
== 0) {
848 ifra
->ifra_addr
= ia
->ia_addr
;
850 } else if (IN6_ARE_ADDR_EQUAL(&ifra
->ifra_addr
.sin6_addr
,
851 &ia
->ia_addr
.sin6_addr
))
854 /* Validate address families: */
856 * The destination address for a p2p link must have a family
857 * of AF_UNSPEC or AF_INET6.
859 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0 &&
860 ifra
->ifra_dstaddr
.sin6_family
!= AF_INET6
&&
861 ifra
->ifra_dstaddr
.sin6_family
!= AF_UNSPEC
)
862 return(EAFNOSUPPORT
);
864 * The prefixmask must have a family of AF_UNSPEC or AF_INET6.
866 if (ifra
->ifra_prefixmask
.sin6_family
!= AF_INET6
&&
867 ifra
->ifra_prefixmask
.sin6_family
!= AF_UNSPEC
)
868 return(EAFNOSUPPORT
);
870 if (ifra
->ifra_prefixmask
.sin6_len
) {
871 in6_ifscrub(ifp
, ia
);
872 ia
->ia_prefixmask
= ifra
->ifra_prefixmask
;
875 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
876 (ifra
->ifra_dstaddr
.sin6_family
== AF_INET6
)) {
877 in6_ifscrub(ifp
, ia
);
878 oldaddr
= ia
->ia_dstaddr
;
879 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
880 /* link-local index check: should be a separate function? */
881 if (IN6_IS_ADDR_LINKLOCAL(&ia
->ia_dstaddr
.sin6_addr
)) {
882 if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] == 0) {
884 * interface ID is not embedded by
887 ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1]
888 = htons(ifp
->if_index
);
889 } else if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] !=
890 htons(ifp
->if_index
)) {
891 ia
->ia_dstaddr
= oldaddr
;
892 return(EINVAL
); /* ifid is contradict */
895 prefixIsNew
= 1; /* We lie; but effect's the same */
897 if (hostIsNew
|| prefixIsNew
) {
898 error
= in6_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
904 if (hostIsNew
&& (ifp
->if_flags
& IFF_MULTICAST
)) {
908 * join solicited multicast addr for new host id
910 struct in6_addr llsol
;
911 bzero(&llsol
, sizeof(struct in6_addr
));
912 llsol
.s6_addr16
[0] = htons(0xff02);
913 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
914 llsol
.s6_addr32
[1] = 0;
915 llsol
.s6_addr32
[2] = htonl(1);
917 ifra
->ifra_addr
.sin6_addr
.s6_addr32
[3];
918 llsol
.s6_addr8
[12] = 0xff;
919 (void)in6_addmulti(&llsol
, ifp
, &error_local
);
924 ia
->ia6_flags
= ifra
->ifra_flags
;
925 ia
->ia6_flags
&= ~IN6_IFF_DUPLICATED
; /*safety*/
926 ia
->ia6_flags
&= ~IN6_IFF_NODAD
; /* Mobile IPv6 */
928 ia
->ia6_lifetime
= ifra
->ifra_lifetime
;
930 if (ia
->ia6_lifetime
.ia6t_vltime
!= ND6_INFINITE_LIFETIME
) {
931 ia
->ia6_lifetime
.ia6t_expire
=
932 time_second
+ ia
->ia6_lifetime
.ia6t_vltime
;
934 ia
->ia6_lifetime
.ia6t_expire
= 0;
935 if (ia
->ia6_lifetime
.ia6t_pltime
!= ND6_INFINITE_LIFETIME
) {
936 ia
->ia6_lifetime
.ia6t_preferred
=
937 time_second
+ ia
->ia6_lifetime
.ia6t_pltime
;
939 ia
->ia6_lifetime
.ia6t_preferred
= 0;
942 * Perform DAD, if needed.
943 * XXX It may be of use, if we can administratively
946 switch (ifp
->if_type
) {
955 /* Mobile IPv6 modification */
956 if ((ifra
->ifra_flags
& IN6_IFF_NODAD
) == 0) {
957 ia
->ia6_flags
|= IN6_IFF_TENTATIVE
;
958 nd6_dad_start((struct ifaddr
*)ia
, NULL
);
973 iilen
= (sizeof(ia
->ia_prefixmask
.sin6_addr
) << 3) -
974 in6_mask2len(&ia
->ia_prefixmask
.sin6_addr
);
975 error_local
= in6_prefix_add_ifid(iilen
, ia
);
982 case SIOCDIFADDR_IN6
:
983 in6_purgeaddr(&ia
->ia_ifa
, ifp
);
988 error
= dlil_ioctl(0, ifp
, cmd
, (caddr_t
)data
);
989 if (error
== EOPNOTSUPP
)
994 if (ifp
== NULL
|| ifp
->if_ioctl
== 0)
996 return((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
1003 in6_purgeaddr(ifa
, ifp
)
1007 struct in6_ifaddr
*oia
, *ia
= (void *) ifa
;
1009 in6_ifscrub(ifp
, ia
);
1011 if (ifp
->if_flags
& IFF_MULTICAST
) {
1013 * delete solicited multicast addr for deleting host id
1015 struct in6_multi
*in6m
;
1016 struct in6_addr llsol
;
1017 bzero(&llsol
, sizeof(struct in6_addr
));
1018 llsol
.s6_addr16
[0] = htons(0xff02);
1019 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
1020 llsol
.s6_addr32
[1] = 0;
1021 llsol
.s6_addr32
[2] = htonl(1);
1022 llsol
.s6_addr32
[3] =
1023 ia
->ia_addr
.sin6_addr
.s6_addr32
[3];
1024 llsol
.s6_addr8
[12] = 0xff;
1026 IN6_LOOKUP_MULTI(llsol
, ifp
, in6m
);
1031 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1032 if ((ifa
= ifp
->if_addrlist
) == ia62ifa(ia
))
1033 ifp
->if_addrlist
= ifa
->ifa_next
;
1035 while (ifa
->ifa_next
&&
1036 (ifa
->ifa_next
!= ia62ifa(ia
)))
1037 ifa
= ifa
->ifa_next
;
1039 ifa
->ifa_next
= ia62ifa(ia
)->ifa_next
;
1041 printf("Couldn't unlink in6_ifaddr from ifp\n");
1044 TAILQ_REMOVE(&ifp
->if_addrlist
, &ia
->ia_ifa
, ifa_list
);
1046 IFAFREE(&ia
->ia_ifa
);
1049 if (oia
== (ia
= in6_ifaddr
))
1050 in6_ifaddr
= ia
->ia_next
;
1052 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
1055 ia
->ia_next
= oia
->ia_next
;
1057 printf("Didn't unlink in6_ifaddr from list\n");
1062 iilen
= (sizeof(oia
->ia_prefixmask
.sin6_addr
) << 3) -
1063 in6_mask2len(&oia
->ia_prefixmask
.sin6_addr
);
1064 in6_prefix_remove_ifid(iilen
, oia
);
1066 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1067 if (oia
->ia6_multiaddrs
.lh_first
!= NULL
)
1068 in6_savemkludge(oia
);
1071 IFAFREE(&oia
->ia_ifa
);
1076 * SIOCGLIFADDR: get first address. (???)
1077 * SIOCGLIFADDR with IFLR_PREFIX:
1078 * get first address that matches the specified prefix.
1079 * SIOCALIFADDR: add the specified address.
1080 * SIOCALIFADDR with IFLR_PREFIX:
1081 * add the specified prefix, filling hostid part from
1082 * the first link-local address. prefixlen must be <= 64.
1083 * SIOCDLIFADDR: delete the specified address.
1084 * SIOCDLIFADDR with IFLR_PREFIX:
1085 * delete the first address that matches the specified prefix.
1087 * EINVAL on invalid parameters
1088 * EADDRNOTAVAIL on prefix match failed/specified address not found
1089 * other values may be returned from in6_ioctl()
1091 * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
1092 * this is to accomodate address naming scheme other than RFC2374,
1094 * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
1095 * address encoding scheme. (see figure on page 8)
1098 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1099 in6_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
)
1106 in6_lifaddr_ioctl(so
, cmd
, data
, ifp
)
1113 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
1115 struct sockaddr
*sa
;
1118 if (!data
|| !ifp
) {
1119 panic("invalid argument to in6_lifaddr_ioctl");
1125 /* address must be specified on GET with IFLR_PREFIX */
1126 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
1131 /* address must be specified on ADD and DELETE */
1132 sa
= (struct sockaddr
*)&iflr
->addr
;
1133 if (sa
->sa_family
!= AF_INET6
)
1135 if (sa
->sa_len
!= sizeof(struct sockaddr_in6
))
1137 /* XXX need improvement */
1138 sa
= (struct sockaddr
*)&iflr
->dstaddr
;
1139 if (sa
->sa_family
&& sa
->sa_family
!= AF_INET6
)
1141 if (sa
->sa_len
&& sa
->sa_len
!= sizeof(struct sockaddr_in6
))
1144 default: /*shouldn't happen*/
1146 panic("invalid cmd to in6_lifaddr_ioctl");
1152 if (sizeof(struct in6_addr
) * 8 < iflr
->prefixlen
)
1158 struct in6_aliasreq ifra
;
1159 struct in6_addr
*hostid
= NULL
;
1162 if ((iflr
->flags
& IFLR_PREFIX
) != 0) {
1163 struct sockaddr_in6
*sin6
;
1166 * hostid is to fill in the hostid part of the
1167 * address. hostid points to the first link-local
1168 * address attached to the interface.
1170 ifa
= (struct ifaddr
*)in6ifa_ifpforlinklocal(ifp
, 0);
1172 return EADDRNOTAVAIL
;
1173 hostid
= IFA_IN6(ifa
);
1175 /* prefixlen must be <= 64. */
1176 if (64 < iflr
->prefixlen
)
1178 prefixlen
= iflr
->prefixlen
;
1180 /* hostid part must be zero. */
1181 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1182 if (sin6
->sin6_addr
.s6_addr32
[2] != 0
1183 || sin6
->sin6_addr
.s6_addr32
[3] != 0) {
1187 prefixlen
= iflr
->prefixlen
;
1189 /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1190 bzero(&ifra
, sizeof(ifra
));
1191 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1192 sizeof(ifra
.ifra_name
));
1194 bcopy(&iflr
->addr
, &ifra
.ifra_addr
,
1195 ((struct sockaddr
*)&iflr
->addr
)->sa_len
);
1197 /* fill in hostid part */
1198 ifra
.ifra_addr
.sin6_addr
.s6_addr32
[2] =
1199 hostid
->s6_addr32
[2];
1200 ifra
.ifra_addr
.sin6_addr
.s6_addr32
[3] =
1201 hostid
->s6_addr32
[3];
1204 if (((struct sockaddr
*)&iflr
->dstaddr
)->sa_family
) { /*XXX*/
1205 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
1206 ((struct sockaddr
*)&iflr
->dstaddr
)->sa_len
);
1208 ifra
.ifra_dstaddr
.sin6_addr
.s6_addr32
[2] =
1209 hostid
->s6_addr32
[2];
1210 ifra
.ifra_dstaddr
.sin6_addr
.s6_addr32
[3] =
1211 hostid
->s6_addr32
[3];
1215 ifra
.ifra_prefixmask
.sin6_family
= AF_INET6
;
1216 ifra
.ifra_prefixmask
.sin6_len
= sizeof(struct sockaddr_in6
);
1217 in6_len2mask(&ifra
.ifra_prefixmask
.sin6_addr
, prefixlen
);
1219 ifra
.ifra_flags
= iflr
->flags
& ~IFLR_PREFIX
;
1220 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1221 return in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
, ifp
, p
);
1223 return in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
, ifp
);
1229 struct in6_ifaddr
*ia
;
1230 struct in6_addr mask
, candidate
, match
;
1231 struct sockaddr_in6
*sin6
;
1234 bzero(&mask
, sizeof(mask
));
1235 if (iflr
->flags
& IFLR_PREFIX
) {
1236 /* lookup a prefix rather than address. */
1237 in6_len2mask(&mask
, iflr
->prefixlen
);
1239 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1240 bcopy(&sin6
->sin6_addr
, &match
, sizeof(match
));
1241 match
.s6_addr32
[0] &= mask
.s6_addr32
[0];
1242 match
.s6_addr32
[1] &= mask
.s6_addr32
[1];
1243 match
.s6_addr32
[2] &= mask
.s6_addr32
[2];
1244 match
.s6_addr32
[3] &= mask
.s6_addr32
[3];
1246 /* if you set extra bits, that's wrong */
1247 if (bcmp(&match
, &sin6
->sin6_addr
, sizeof(match
)))
1252 if (cmd
== SIOCGLIFADDR
) {
1253 /* on getting an address, take the 1st match */
1256 /* on deleting an address, do exact match */
1257 in6_len2mask(&mask
, 128);
1258 sin6
= (struct sockaddr_in6
*)&iflr
->addr
;
1259 bcopy(&sin6
->sin6_addr
, &match
, sizeof(match
));
1265 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1266 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1268 for (ifa
= ifp
->if_addrlist
.tqh_first
;
1270 ifa
= ifa
->ifa_list
.tqe_next
)
1273 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1277 bcopy(IFA_IN6(ifa
), &candidate
, sizeof(candidate
));
1278 candidate
.s6_addr32
[0] &= mask
.s6_addr32
[0];
1279 candidate
.s6_addr32
[1] &= mask
.s6_addr32
[1];
1280 candidate
.s6_addr32
[2] &= mask
.s6_addr32
[2];
1281 candidate
.s6_addr32
[3] &= mask
.s6_addr32
[3];
1282 if (IN6_ARE_ADDR_EQUAL(&candidate
, &match
))
1286 return EADDRNOTAVAIL
;
1289 if (cmd
== SIOCGLIFADDR
) {
1290 /* fill in the if_laddrreq structure */
1291 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin6_len
);
1293 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1294 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
1295 ia
->ia_dstaddr
.sin6_len
);
1297 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
1300 in6_mask2len(&ia
->ia_prefixmask
.sin6_addr
);
1302 iflr
->flags
= ia
->ia6_flags
; /*XXX*/
1306 struct in6_aliasreq ifra
;
1308 /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1309 bzero(&ifra
, sizeof(ifra
));
1310 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1311 sizeof(ifra
.ifra_name
));
1313 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
1314 ia
->ia_addr
.sin6_len
);
1315 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1316 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
1317 ia
->ia_dstaddr
.sin6_len
);
1319 bzero(&ifra
.ifra_dstaddr
,
1320 sizeof(ifra
.ifra_dstaddr
));
1322 bcopy(&ia
->ia_prefixmask
, &ifra
.ifra_dstaddr
,
1323 ia
->ia_prefixmask
.sin6_len
);
1325 ifra
.ifra_flags
= ia
->ia6_flags
;
1326 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1327 return in6_control(so
, SIOCDIFADDR_IN6
, (caddr_t
)&ifra
,
1330 return in6_control(so
, SIOCDIFADDR_IN6
, (caddr_t
)&ifra
,
1337 return EOPNOTSUPP
; /*just for safety*/
1341 * Delete any existing route for an interface.
1344 in6_ifscrub(ifp
, ia
)
1345 register struct ifnet
*ifp
;
1346 register struct in6_ifaddr
*ia
;
1348 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1350 if (ifp
->if_flags
& (IFF_LOOPBACK
| IFF_POINTOPOINT
))
1351 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1353 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1354 ia
->ia_flags
&= ~IFA_ROUTE
;
1356 /* Remove ownaddr's loopback rtentry, if it exists. */
1357 in6_ifremloop(&(ia
->ia_ifa
));
1361 * Initialize an interface's intetnet6 address
1362 * and routing table entry.
1365 in6_ifinit(ifp
, ia
, sin6
, scrub
)
1367 struct in6_ifaddr
*ia
;
1368 struct sockaddr_in6
*sin6
;
1371 struct sockaddr_in6 oldaddr
;
1372 int error
, flags
= RTF_UP
;
1376 oldaddr
= ia
->ia_addr
;
1377 ia
->ia_addr
= *sin6
;
1379 * Give the interface a chance to initialize
1380 * if this is its first address,
1381 * and to validate the address if necessary.
1384 error
= dlil_ioctl(0, ifp
, SIOCSIFADDR
, (caddr_t
)ia
) ;
1385 if (error
== EOPNOTSUPP
)
1390 if (ifp
->if_ioctl
&&
1391 (error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, (caddr_t
)ia
))) {
1393 printf("in6_ifinit SIOCSIFADDR for if=%s returns error=%x\n", if_name(ifp
), error
);
1395 ia
->ia_addr
= oldaddr
;
1399 switch (ifp
->if_type
) {
1403 ia
->ia_ifa
.ifa_rtrequest
= nd6_rtrequest
;
1404 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
1407 ia
->ia_ifa
.ifa_rtrequest
= nd6_p2p_rtrequest
;
1408 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
1414 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1415 in6_ifscrub(ifp
, ia
);
1416 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1422 * Add route for the network.
1424 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1425 if (ifp
->if_flags
& IFF_LOOPBACK
) {
1426 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1428 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1429 if (ia
->ia_dstaddr
.sin6_family
!= AF_INET6
)
1433 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1434 ia
->ia_flags
|= IFA_ROUTE
;
1436 /* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
1437 in6_ifaddloop(&(ia
->ia_ifa
));
1439 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1440 if (ifp
->if_flags
& IFF_MULTICAST
)
1441 in6_restoremkludge(ia
, ifp
);
1445 printf("in6_ifinit: Attach dl_tag for if=%s%n\n", ifp
->if_name
, ifp
->if_unit
);
1447 if (strcmp(ifp
->if_name
, "en") == 0)
1448 dl_tag
= ether_attach_inet6(ifp
);
1450 if (strcmp(ifp
->if_name
, "lo") == 0)
1451 dl_tag
= lo_attach_inet(ifp
);
1453 if (strcmp(ifp
->if_name
, "gif") == 0)
1454 dl_tag
= gif_attach_inet(ifp
);
1455 /* End of temp code */
1456 ia
->ia_ifa
.ifa_dlt
= dl_tag
;
1462 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1464 * Multicast address kludge:
1465 * If there were any multicast addresses attached to this interface address,
1466 * either move them to another address on this interface, or save them until
1467 * such time as this interface is reconfigured for IPv6.
1470 in6_savemkludge(oia
)
1471 struct in6_ifaddr
*oia
;
1473 struct in6_ifaddr
*ia
;
1474 struct in6_multi
*in6m
, *next
;
1476 IFP_TO_IA6(oia
->ia_ifp
, ia
);
1477 if (ia
) { /* there is another address */
1478 for (in6m
= oia
->ia6_multiaddrs
.lh_first
; in6m
; in6m
= next
){
1479 next
= in6m
->in6m_entry
.le_next
;
1480 IFAFREE(&in6m
->in6m_ia
->ia_ifa
);
1481 ia
->ia_ifa
.ifa_refcnt
++;
1483 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
, in6m
, in6m_entry
);
1485 } else { /* last address on this if deleted, save */
1486 struct multi6_kludge
*mk
;
1488 mk
= _MALLOC(sizeof(*mk
), M_IPMADDR
, M_WAITOK
);
1490 LIST_INIT(&mk
->mk_head
);
1491 mk
->mk_ifp
= oia
->ia_ifp
;
1493 for (in6m
= oia
->ia6_multiaddrs
.lh_first
; in6m
; in6m
= next
){
1494 next
= in6m
->in6m_entry
.le_next
;
1495 IFAFREE(&in6m
->in6m_ia
->ia_ifa
); /* release reference */
1496 in6m
->in6m_ia
= NULL
;
1497 LIST_INSERT_HEAD(&mk
->mk_head
, in6m
, in6m_entry
);
1500 if (mk
->mk_head
.lh_first
!= NULL
) {
1501 LIST_INSERT_HEAD(&in6_mk
, mk
, mk_entry
);
1503 FREE(mk
, M_IPMADDR
);
1509 * Continuation of multicast address hack:
1510 * If there was a multicast group list previously saved for this interface,
1511 * then we re-attach it to the first address configured on the i/f.
1514 in6_restoremkludge(ia
, ifp
)
1515 struct in6_ifaddr
*ia
;
1518 struct multi6_kludge
*mk
;
1520 for (mk
= in6_mk
.lh_first
; mk
; mk
= mk
->mk_entry
.le_next
) {
1521 if (mk
->mk_ifp
== ifp
) {
1522 struct in6_multi
*in6m
, *next
;
1524 for (in6m
= mk
->mk_head
.lh_first
; in6m
; in6m
= next
){
1525 next
= in6m
->in6m_entry
.le_next
;
1527 ia
->ia_ifa
.ifa_refcnt
++;
1528 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
,
1531 LIST_REMOVE(mk
, mk_entry
);
1532 _FREE(mk
, M_IPMADDR
);
1539 in6_purgemkludge(ifp
)
1542 struct multi6_kludge
*mk
;
1543 struct in6_multi
*in6m
;
1545 for (mk
= in6_mk
.lh_first
; mk
; mk
= mk
->mk_entry
.le_next
) {
1546 if (mk
->mk_ifp
!= ifp
)
1549 /* leave from all multicast groups joined */
1550 while ((in6m
= LIST_FIRST(&mk
->mk_head
)) != NULL
)
1552 LIST_REMOVE(mk
, mk_entry
);
1553 _FREE(mk
, M_IPMADDR
);
1559 * Add an address to the list of IP6 multicast addresses for a
1563 in6_addmulti(maddr6
, ifp
, errorp
)
1564 register struct in6_addr
*maddr6
;
1565 register struct ifnet
*ifp
;
1568 struct in6_ifaddr
*ia
;
1569 struct in6_ifreq ifr
;
1570 struct in6_multi
*in6m
;
1572 int s
= splsoftnet();
1579 * See if address already in list.
1581 IN6_LOOKUP_MULTI(*maddr6
, ifp
, in6m
);
1584 * Found it; just increment the refrence count.
1586 in6m
->in6m_refcount
++;
1589 * New address; allocate a new multicast record
1590 * and link it into the interface's multicast list.
1592 in6m
= (struct in6_multi
*)
1593 _MALLOC(sizeof(*in6m
), M_IPMADDR
, M_NOWAIT
);
1599 in6m
->in6m_addr
= *maddr6
;
1600 in6m
->in6m_ifp
= ifp
;
1601 in6m
->in6m_refcount
= 1;
1602 IFP_TO_IA6(ifp
, ia
);
1604 _FREE(in6m
, M_IPMADDR
);
1606 *errorp
= EADDRNOTAVAIL
; /* appropriate? */
1610 ia
->ia_ifa
.ifa_refcnt
++; /* gain a reference */
1611 LIST_INSERT_HEAD(&ia
->ia6_multiaddrs
, in6m
, in6m_entry
);
1614 * Ask the network driver to update its multicast reception
1615 * filter appropriately for the new address.
1617 bzero(&ifr
.ifr_addr
, sizeof(struct sockaddr_in6
));
1618 ifr
.ifr_addr
.sin6_len
= sizeof(struct sockaddr_in6
);
1619 ifr
.ifr_addr
.sin6_family
= AF_INET6
;
1620 ifr
.ifr_addr
.sin6_addr
= *maddr6
;
1622 *errorp
= dlil_ioctl(0, ifp
, SIOCADDMULTI
, (caddr_t
)&ifr
);
1623 printf("in6_addmulti: if=%s%n dlil_ioctl returns=%d\n", ifp
->if_name
, ifp
->if_unit
, *errorp
);
1624 if (*errorp
== EOPNOTSUPP
)
1628 if (ifp
->if_ioctl
== NULL
)
1629 *errorp
= ENXIO
; /* XXX: appropriate? */
1631 *errorp
= (*ifp
->if_ioctl
)(ifp
, SIOCADDMULTI
,
1635 LIST_REMOVE(in6m
, in6m_entry
);
1636 _FREE(in6m
, M_IPMADDR
);
1641 * Let MLD6 know that we have joined a new IP6 multicast
1644 mld6_start_listening(in6m
);
1651 * Delete a multicast address record.
1655 struct in6_multi
*in6m
;
1657 struct in6_ifreq ifr
;
1659 int s
= splsoftnet();
1664 if (--in6m
->in6m_refcount
== 0) {
1666 * No remaining claims to this record; let MLD6 know
1667 * that we are leaving the multicast group.
1669 mld6_stop_listening(in6m
);
1674 LIST_REMOVE(in6m
, in6m_entry
);
1676 IFAFREE(&in6m
->in6m_ia
->ia_ifa
); /* release reference */
1679 * Notify the network driver to update its multicast
1682 bzero(&ifr
.ifr_addr
, sizeof(struct sockaddr_in6
));
1683 ifr
.ifr_addr
.sin6_len
= sizeof(struct sockaddr_in6
);
1684 ifr
.ifr_addr
.sin6_family
= AF_INET6
;
1685 ifr
.ifr_addr
.sin6_addr
= in6m
->in6m_addr
;
1687 dlil_ioctl(0, in6m
->in6m_ifp
, SIOCDELMULTI
, (caddr_t
)&ifr
);
1689 (*in6m
->in6m_ifp
->if_ioctl
)(in6m
->in6m_ifp
,
1690 SIOCDELMULTI
, (caddr_t
)&ifr
);
1692 _FREE(in6m
, M_IPMADDR
);
1696 #else /* not FreeBSD3 */
1698 * Add an address to the list of IP6 multicast addresses for a
1702 in6_addmulti(maddr6
, ifp
, errorp
)
1703 register struct in6_addr
*maddr6
;
1704 register struct ifnet
*ifp
;
1707 struct in6_multi
*in6m
;
1708 struct sockaddr_in6 sin6
;
1709 struct ifmultiaddr
*ifma
;
1715 * Call generic routine to add membership or increment
1716 * refcount. It wants addresses in the form of a sockaddr,
1717 * so we build one here (being careful to zero the unused bytes).
1719 bzero(&sin6
, sizeof sin6
);
1720 sin6
.sin6_family
= AF_INET6
;
1721 sin6
.sin6_len
= sizeof sin6
;
1722 sin6
.sin6_addr
= *maddr6
;
1723 *errorp
= if_addmulti(ifp
, (struct sockaddr
*)&sin6
, &ifma
);
1730 * If ifma->ifma_protospec is null, then if_addmulti() created
1731 * a new record. Otherwise, we are done.
1733 if (ifma
->ifma_protospec
!= 0)
1734 return ifma
->ifma_protospec
;
1736 /* XXX - if_addmulti uses M_WAITOK. Can this really be called
1737 at interrupt time? If so, need to fix if_addmulti. XXX */
1738 in6m
= (struct in6_multi
*)_MALLOC(sizeof(*in6m
), M_IPMADDR
, M_NOWAIT
);
1744 bzero(in6m
, sizeof *in6m
);
1745 in6m
->in6m_addr
= *maddr6
;
1746 in6m
->in6m_ifp
= ifp
;
1747 in6m
->in6m_ifma
= ifma
;
1748 ifma
->ifma_protospec
= in6m
;
1749 LIST_INSERT_HEAD(&in6_multihead
, in6m
, in6m_entry
);
1752 * Let MLD6 know that we have joined a new IP6 multicast
1755 mld6_start_listening(in6m
);
1761 * Delete a multicast address record.
1765 struct in6_multi
*in6m
;
1767 struct ifmultiaddr
*ifma
= in6m
->in6m_ifma
;
1770 if (ifma
->ifma_refcount
== 1) {
1772 * No remaining claims to this record; let MLD6 know
1773 * that we are leaving the multicast group.
1775 mld6_stop_listening(in6m
);
1776 ifma
->ifma_protospec
= 0;
1777 LIST_REMOVE(in6m
, in6m_entry
);
1778 _FREE(in6m
, M_IPMADDR
);
1780 /* XXX - should be separate API for when we have an ifma? */
1781 if_delmulti(ifma
->ifma_ifp
, ifma
->ifma_addr
);
1784 #endif /* not FreeBSD3 */
1787 * Find an IPv6 interface link-local address specific to an interface.
1790 in6ifa_ifpforlinklocal(ifp
, ignoreflags
)
1794 register struct ifaddr
*ifa
;
1796 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1797 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1799 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
1802 if (ifa
->ifa_addr
== NULL
)
1803 continue; /* just for safety */
1804 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1806 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa
))) {
1807 if ((((struct in6_ifaddr
*)ifa
)->ia6_flags
&
1814 return((struct in6_ifaddr
*)ifa
);
1819 * find the internet address corresponding to a given interface and address.
1822 in6ifa_ifpwithaddr(ifp
, addr
)
1824 struct in6_addr
*addr
;
1826 register struct ifaddr
*ifa
;
1828 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1829 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
1831 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
1834 if (ifa
->ifa_addr
== NULL
)
1835 continue; /* just for safety */
1836 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1838 if (IN6_ARE_ADDR_EQUAL(addr
, IFA_IN6(ifa
)))
1842 return((struct in6_ifaddr
*)ifa
);
1846 * Convert IP6 address to printable (loggable) representation.
1848 static char digits
[] = "0123456789abcdef";
1849 static int ip6round
= 0;
1852 register struct in6_addr
*addr
;
1854 static char ip6buf
[8][48];
1857 register u_short
*a
= (u_short
*)addr
;
1861 ip6round
= (ip6round
+ 1) & 7;
1862 cp
= ip6buf
[ip6round
];
1864 for (i
= 0; i
< 8; i
++) {
1875 if (dcolon
== 0 && *(a
+ 1) == 0) {
1888 *cp
++ = digits
[*d
>> 4];
1889 *cp
++ = digits
[*d
++ & 0xf];
1890 *cp
++ = digits
[*d
>> 4];
1891 *cp
++ = digits
[*d
& 0xf];
1896 return(ip6buf
[ip6round
]);
1901 struct in6_addr
*in6
;
1903 struct in6_ifaddr
*ia
;
1905 if (IN6_IS_ADDR_LOOPBACK(in6
) || IN6_IS_ADDR_LINKLOCAL(in6
))
1908 for (ia
= in6_ifaddr
; ia
; ia
= ia
->ia_next
)
1909 if (IN6_ARE_MASKED_ADDR_EQUAL(in6
, &ia
->ia_addr
.sin6_addr
,
1910 &ia
->ia_prefixmask
.sin6_addr
))
1917 * Get a scope of the address. Node-local, link-local, site-local or global.
1920 in6_addrscope (addr
)
1921 struct in6_addr
*addr
;
1925 if (addr
->s6_addr8
[0] == 0xfe) {
1926 scope
= addr
->s6_addr8
[1] & 0xc0;
1930 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1933 return IPV6_ADDR_SCOPE_SITELOCAL
;
1936 return IPV6_ADDR_SCOPE_GLOBAL
; /* just in case */
1942 if (addr
->s6_addr8
[0] == 0xff) {
1943 scope
= addr
->s6_addr8
[1] & 0x0f;
1946 * due to other scope such as reserved,
1947 * return scope doesn't work.
1950 case IPV6_ADDR_SCOPE_NODELOCAL
:
1951 return IPV6_ADDR_SCOPE_NODELOCAL
;
1953 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1954 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1956 case IPV6_ADDR_SCOPE_SITELOCAL
:
1957 return IPV6_ADDR_SCOPE_SITELOCAL
;
1960 return IPV6_ADDR_SCOPE_GLOBAL
;
1965 if (bcmp(&in6addr_loopback
, addr
, sizeof(addr
) - 1) == 0) {
1966 if (addr
->s6_addr8
[15] == 1) /* loopback */
1967 return IPV6_ADDR_SCOPE_NODELOCAL
;
1968 if (addr
->s6_addr8
[15] == 0) /* unspecified */
1969 return IPV6_ADDR_SCOPE_LINKLOCAL
;
1972 return IPV6_ADDR_SCOPE_GLOBAL
;
1976 in6_addr2scopeid(ifp
, addr
)
1977 struct ifnet
*ifp
; /* must not be NULL */
1978 struct in6_addr
*addr
; /* must not be NULL */
1980 int scope
= in6_addrscope(addr
);
1983 case IPV6_ADDR_SCOPE_NODELOCAL
:
1984 return(-1); /* XXX: is this an appropriate value? */
1986 case IPV6_ADDR_SCOPE_LINKLOCAL
:
1987 /* XXX: we do not distinguish between a link and an I/F. */
1988 return(ifp
->if_index
);
1990 case IPV6_ADDR_SCOPE_SITELOCAL
:
1991 return(0); /* XXX: invalid. */
1994 return(0); /* XXX: treat as global. */
1999 * return length of part which dst and src are equal
2004 in6_matchlen(src
, dst
)
2005 struct in6_addr
*src
, *dst
;
2008 u_char
*s
= (u_char
*)src
, *d
= (u_char
*)dst
;
2009 u_char
*lim
= s
+ 16, r
;
2012 if ((r
= (*d
++ ^ *s
++)) != 0) {
2024 in6_are_prefix_equal(p1
, p2
, len
)
2025 struct in6_addr
*p1
, *p2
;
2028 int bytelen
, bitlen
;
2031 if (0 > len
|| len
> 128) {
2032 log(LOG_ERR
, "in6_are_prefix_equal: invalid prefix length(%d)\n",
2040 if (bcmp(&p1
->s6_addr
, &p2
->s6_addr
, bytelen
))
2042 if (p1
->s6_addr
[bytelen
] >> (8 - bitlen
) !=
2043 p2
->s6_addr
[bytelen
] >> (8 - bitlen
))
2050 in6_prefixlen2mask(maskp
, len
)
2051 struct in6_addr
*maskp
;
2054 u_char maskarray
[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
2055 int bytelen
, bitlen
, i
;
2058 if (0 > len
|| len
> 128) {
2059 log(LOG_ERR
, "in6_prefixlen2mask: invalid prefix length(%d)\n",
2064 bzero(maskp
, sizeof(*maskp
));
2067 for (i
= 0; i
< bytelen
; i
++)
2068 maskp
->s6_addr
[i
] = 0xff;
2070 maskp
->s6_addr
[bytelen
] = maskarray
[bitlen
- 1];
2074 * return the best address out of the same scope
2077 in6_ifawithscope(oifp
, dst
)
2078 register struct ifnet
*oifp
;
2079 register struct in6_addr
*dst
;
2081 int dst_scope
= in6_addrscope(dst
), src_scope
, best_scope
= 0;
2085 struct in6_ifaddr
*ifa_best
= NULL
;
2088 printf("in6_ifawithscope: output interface is not specified\n");
2093 * We search for all addresses on all interfaces from the beginning.
2094 * Comparing an interface with the outgoing interface will be done
2095 * only at the final stage of tiebreaking.
2097 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2098 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
2100 for (ifp
= TAILQ_FIRST(&ifnet
); ifp
; ifp
= TAILQ_NEXT(ifp
, if_list
))
2104 * We can never take an address that breaks the scope zone
2105 * of the destination.
2107 if (in6_addr2scopeid(ifp
, dst
) != in6_addr2scopeid(oifp
, dst
))
2110 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2111 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2112 #elif defined(__FreeBSD__) && __FreeBSD__ >= 4
2113 TAILQ_FOREACH(ifa
, &ifp
->if_addrlist
, ifa_list
)
2115 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
;
2116 ifa
= ifa
->ifa_list
.tqe_next
)
2119 int tlen
= -1, dscopecmp
, bscopecmp
, matchcmp
;
2121 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2124 src_scope
= in6_addrscope(IFA_IN6(ifa
));
2126 #if ADDRSELECT_DEBUG /* should be removed after stabilization */
2127 dscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
);
2128 printf("in6_ifawithscope: dst=%s bestaddr=%s, "
2129 "newaddr=%s, scope=%x, dcmp=%d, bcmp=%d, "
2130 "matchlen=%d, flgs=%x\n",
2132 ifa_best
? ip6_sprintf(&ifa_best
->ia_addr
.sin6_addr
) : "none",
2133 ip6_sprintf(IFA_IN6(ifa
)), src_scope
,
2135 ifa_best
? IN6_ARE_SCOPE_CMP(src_scope
, best_scope
) : -1,
2136 in6_matchlen(IFA_IN6(ifa
), dst
),
2137 ((struct in6_ifaddr
*)ifa
)->ia6_flags
);
2141 * Don't use an address before completing DAD
2142 * nor a duplicated address.
2144 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2148 /* XXX: is there any case to allow anycasts? */
2149 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2153 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2158 * If this is the first address we find,
2161 if (ifa_best
== NULL
)
2165 * ifa_best is never NULL beyond this line except
2166 * within the block labeled "replace".
2170 * If ifa_best has a smaller scope than dst and
2171 * the current address has a larger one than
2172 * (or equal to) dst, always replace ifa_best.
2173 * Also, if the current address has a smaller scope
2174 * than dst, ignore it unless ifa_best also has a
2177 if (IN6_ARE_SCOPE_CMP(best_scope
, dst_scope
) < 0 &&
2178 IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
) >= 0)
2180 if (IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
) < 0 &&
2181 IN6_ARE_SCOPE_CMP(best_scope
, dst_scope
) >= 0)
2185 * A deprecated address SHOULD NOT be used in new
2186 * communications if an alternate (non-deprecated)
2187 * address is available and has sufficient scope.
2188 * RFC 2462, Section 5.5.4.
2190 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2191 IN6_IFF_DEPRECATED
) {
2193 * Ignore any deprecated addresses if
2194 * specified by configuration.
2196 if (!ip6_use_deprecated
)
2200 * If we have already found a non-deprecated
2201 * candidate, just ignore deprecated addresses.
2203 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
)
2209 * A non-deprecated address is always preferred
2210 * to a deprecated one regardless of scopes and
2213 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
) &&
2214 (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
2215 IN6_IFF_DEPRECATED
) == 0)
2219 * At this point, we have two cases:
2220 * 1. we are looking at a non-deprecated address,
2221 * and ifa_best is also non-deprecated.
2222 * 2. we are looking at a deprecated address,
2223 * and ifa_best is also deprecated.
2224 * Also, we do not have to consider a case where
2225 * the scope of if_best is larger(smaller) than dst and
2226 * the scope of the current address is smaller(larger)
2227 * than dst. Such a case has already been covered.
2228 * Tiebreaking is done according to the following
2230 * - the scope comparison between the address and
2232 * - the scope comparison between the address and
2233 * ifa_best (bscopecmp)
2234 * - if the address match dst longer than ifa_best
2236 * - if the address is on the outgoing I/F (outI/F)
2238 * Roughly speaking, the selection policy is
2239 * - the most important item is scope. The same scope
2240 * is best. Then search for a larger scope.
2241 * Smaller scopes are the last resort.
2242 * - A deprecated address is chosen only when we have
2243 * no address that has an enough scope, but is
2244 * prefered to any addresses of smaller scopes.
2245 * - Longest address match against dst is considered
2246 * only for addresses that has the same scope of dst.
2247 * - If there is no other reasons to choose one,
2248 * addresses on the outgoing I/F are preferred.
2250 * The precise decision table is as follows:
2251 * dscopecmp bscopecmp matchcmp outI/F | replace?
2252 * !equal equal N/A Yes | Yes (1)
2253 * !equal equal N/A No | No (2)
2254 * larger larger N/A N/A | No (3)
2255 * larger smaller N/A N/A | Yes (4)
2256 * smaller larger N/A N/A | Yes (5)
2257 * smaller smaller N/A N/A | No (6)
2258 * equal smaller N/A N/A | Yes (7)
2259 * equal larger (already done)
2260 * equal equal larger N/A | Yes (8)
2261 * equal equal smaller N/A | No (9)
2262 * equal equal equal Yes | Yes (a)
2263 * eaual eqaul equal No | No (b)
2265 dscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, dst_scope
);
2266 bscopecmp
= IN6_ARE_SCOPE_CMP(src_scope
, best_scope
);
2268 if (dscopecmp
&& bscopecmp
== 0) {
2269 if (oifp
== ifp
) /* (1) */
2273 if (dscopecmp
> 0) {
2274 if (bscopecmp
> 0) /* (3) */
2276 goto replace
; /* (4) */
2278 if (dscopecmp
< 0) {
2279 if (bscopecmp
> 0) /* (5) */
2284 /* now dscopecmp must be 0 */
2286 goto replace
; /* (7) */
2289 * At last both dscopecmp and bscopecmp must be 0.
2290 * We need address matching against dst for
2293 tlen
= in6_matchlen(IFA_IN6(ifa
), dst
);
2294 matchcmp
= tlen
- blen
;
2295 if (matchcmp
> 0) /* (8) */
2297 if (matchcmp
< 0) /* (9) */
2299 if (oifp
== ifp
) /* (a) */
2304 ifa_best
= (struct in6_ifaddr
*)ifa
;
2305 blen
= tlen
>= 0 ? tlen
:
2306 in6_matchlen(IFA_IN6(ifa
), dst
);
2307 best_scope
= in6_addrscope(&ifa_best
->ia_addr
.sin6_addr
);
2311 /* count statistics for future improvements */
2312 if (ifa_best
== NULL
)
2313 ip6stat
.ip6s_sources_none
++;
2315 if (oifp
== ifa_best
->ia_ifp
)
2316 ip6stat
.ip6s_sources_sameif
[best_scope
]++;
2318 ip6stat
.ip6s_sources_otherif
[best_scope
]++;
2320 if (best_scope
== dst_scope
)
2321 ip6stat
.ip6s_sources_samescope
[best_scope
]++;
2323 ip6stat
.ip6s_sources_otherscope
[best_scope
]++;
2325 if ((ifa_best
->ia6_flags
& IN6_IFF_DEPRECATED
) != 0)
2326 ip6stat
.ip6s_sources_deprecated
[best_scope
]++;
2333 * return the best address out of the same scope. if no address was
2334 * found, return the first valid address from designated IF.
2338 in6_ifawithifp(ifp
, dst
)
2339 register struct ifnet
*ifp
;
2340 register struct in6_addr
*dst
;
2342 int dst_scope
= in6_addrscope(dst
), blen
= -1, tlen
;
2344 struct in6_ifaddr
*besta
= 0;
2345 struct in6_ifaddr
*dep
[2]; /*last-resort: deprecated*/
2347 dep
[0] = dep
[1] = NULL
;
2352 * This is needed to assure that the Home Address is used for
2353 * outgoing packets when not at home. We can't choose any other
2354 * address if we want to keep connections up during movement.
2356 if (mip6_get_home_prefix_hook
) { /* Only Mobile Node */
2357 struct nd_prefix
*pr
;
2358 if ((pr
= (*mip6_get_home_prefix_hook
)()) &&
2359 !IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
))
2361 if (dst_scope
== in6_addrscope(&pr
->ndpr_addr
)) {
2363 /* Noisy but useful */
2364 mip6_debug("%s: Local address %s is chosen "
2365 "for pcb to dest %s.\n",
2367 ip6_sprintf(&pr
->ndpr_addr
),
2370 return(in6ifa_ifpwithaddr(ifp
, &pr
->ndpr_addr
));
2378 * We first look for addresses in the same scope.
2379 * If there is one, return it.
2380 * If two or more, return one which matches the dst longest.
2381 * If none, return one of global addresses assigned other ifs.
2383 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2384 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2386 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2389 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2391 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_ANYCAST
)
2392 continue; /* XXX: is there any case to allow anycast? */
2393 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_NOTREADY
)
2394 continue; /* don't use this interface */
2395 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DETACHED
)
2397 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DEPRECATED
) {
2398 if (ip6_use_deprecated
)
2399 dep
[0] = (struct in6_ifaddr
*)ifa
;
2403 if (dst_scope
== in6_addrscope(IFA_IN6(ifa
))) {
2405 * call in6_matchlen() as few as possible
2409 blen
= in6_matchlen(&besta
->ia_addr
.sin6_addr
, dst
);
2410 tlen
= in6_matchlen(IFA_IN6(ifa
), dst
);
2413 besta
= (struct in6_ifaddr
*)ifa
;
2416 besta
= (struct in6_ifaddr
*)ifa
;
2422 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2423 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2425 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2428 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2430 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_ANYCAST
)
2431 continue; /* XXX: is there any case to allow anycast? */
2432 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_NOTREADY
)
2433 continue; /* don't use this interface */
2434 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DETACHED
)
2436 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_DEPRECATED
) {
2437 if (ip6_use_deprecated
)
2438 dep
[1] = (struct in6_ifaddr
*)ifa
;
2442 return (struct in6_ifaddr
*)ifa
;
2445 /* use the last-resort values, that are, deprecated addresses */
2455 * perform DAD when interface becomes IFF_UP.
2462 struct in6_ifaddr
*ia
;
2463 struct sockaddr_dl
*sdl
;
2466 u_char ea
[ETHER_ADDR_LEN
];
2468 struct ether_addr ea
;
2471 int dad_delay
; /* delay ticks before DAD output */
2473 bzero(&ea
, sizeof(ea
));
2476 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2477 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2479 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2482 if (ifa
->ifa_addr
->sa_family
== AF_INET6
2483 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_addr
)) {
2486 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
2488 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
2492 switch (ifp
->if_type
) {
2494 in6_ifattach(ifp
, IN6_IFT_LOOP
, NULL
, 1);
2502 in6_ifattach(ifp
, type
, 0, 1);
2507 * This is VERY awkward to call nd6_ifattach while we will
2508 * not do ND at all on the interface. It is necessary for
2509 * initializing default hoplimit, and ND mtu.
2520 off
= sdl
->sdl_nlen
;
2521 if (bcmp(&sdl
->sdl_data
[off
], &ea
, sizeof(ea
)) != 0)
2522 in6_ifattach(ifp
, type
, LLADDR(sdl
), 0);
2525 type
= IN6_IFT_ARCNET
;
2528 off
= sdl
->sdl_nlen
;
2529 if (sdl
->sdl_data
[off
] != 0) /* XXX ?: */
2530 in6_ifattach(ifp
, type
, LLADDR(sdl
), 0);
2538 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2539 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2541 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
; ifa
= ifa
->ifa_list
.tqe_next
)
2544 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2546 ia
= (struct in6_ifaddr
*)ifa
;
2547 if (ia
->ia6_flags
& IN6_IFF_TENTATIVE
)
2548 nd6_dad_start(ifa
, &dad_delay
);
2553 * Calculate max IPv6 MTU through all the interfaces and store it
2559 unsigned long maxmtu
= 0;
2562 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2563 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
2565 for (ifp
= TAILQ_FIRST(&ifnet
); ifp
; ifp
= TAILQ_NEXT(ifp
, if_list
))
2568 if ((ifp
->if_flags
& IFF_LOOPBACK
) == 0 &&
2569 nd_ifinfo
[ifp
->if_index
].linkmtu
> maxmtu
)
2570 maxmtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
2572 if (maxmtu
) /* update only when maxmtu is positive */
2573 in6_maxmtu
= maxmtu
;
2576 #if MAPPED_ADDR_ENABLED
2578 * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
2579 * v4 mapped addr or v4 compat addr
2582 in6_sin6_2_sin(struct sockaddr_in
*sin
, struct sockaddr_in6
*sin6
)
2584 bzero(sin
, sizeof(*sin
));
2585 sin
->sin_len
= sizeof(struct sockaddr_in
);
2586 sin
->sin_family
= AF_INET
;
2587 sin
->sin_port
= sin6
->sin6_port
;
2588 sin
->sin_addr
.s_addr
= sin6
->sin6_addr
.s6_addr32
[3];
2591 /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
2593 in6_sin_2_v4mapsin6(struct sockaddr_in
*sin
, struct sockaddr_in6
*sin6
)
2595 bzero(sin6
, sizeof(*sin6
));
2596 sin6
->sin6_len
= sizeof(struct sockaddr_in6
);
2597 sin6
->sin6_family
= AF_INET6
;
2598 sin6
->sin6_port
= sin
->sin_port
;
2599 sin6
->sin6_addr
.s6_addr32
[0] = 0;
2600 sin6
->sin6_addr
.s6_addr32
[1] = 0;
2601 sin6
->sin6_addr
.s6_addr32
[2] = IPV6_ADDR_INT32_SMP
;
2602 sin6
->sin6_addr
.s6_addr32
[3] = sin
->sin_addr
.s_addr
;
2605 /* Convert sockaddr_in6 into sockaddr_in. */
2607 in6_sin6_2_sin_in_sock(struct sockaddr
*nam
)
2609 struct sockaddr_in
*sin_p
;
2610 struct sockaddr_in6 sin6
;
2613 * Save original sockaddr_in6 addr and convert it
2616 sin6
= *(struct sockaddr_in6
*)nam
;
2617 sin_p
= (struct sockaddr_in
*)nam
;
2618 in6_sin6_2_sin(sin_p
, &sin6
);
2621 /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
2623 in6_sin_2_v4mapsin6_in_sock(struct sockaddr
**nam
)
2625 struct sockaddr_in
*sin_p
;
2626 struct sockaddr_in6
*sin6_p
;
2628 MALLOC(sin6_p
, struct sockaddr_in6
*, sizeof *sin6_p
, M_SONAME
,
2630 sin_p
= (struct sockaddr_in
*)*nam
;
2631 in6_sin_2_v4mapsin6(sin_p
, sin6_p
);
2632 FREE(*nam
, M_SONAME
);
2633 *nam
= (struct sockaddr
*)sin6_p
;
2635 #endif /* MAPPED_ADDR_ENABLED */