1 /* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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
32 * ++Copyright++ 1985, 1988, 1993
34 * Copyright (c) 1985, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
63 * Permission to use, copy, modify, and distribute this software for any
64 * purpose with or without fee is hereby granted, provided that the above
65 * copyright notice and this permission notice appear in all copies, and that
66 * the name of Digital Equipment Corporation not be used in advertising or
67 * publicity pertaining to distribution of the document or software without
68 * specific, written prior permission.
70 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
71 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
72 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
73 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
74 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
75 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
76 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
81 * $FreeBSD: src/lib/libc/net/name6.c,v 1.62 2007/07/31 16:09:41 bushman Exp $
85 * Atsushi Onoe <onoe@sm.sony.co.jp>
88 #include "namespace.h"
89 #include <sys/param.h>
90 #include <sys/socket.h>
92 #include <sys/queue.h>
93 #include <netinet/in.h>
96 #include <net/if_var.h>
97 #include <sys/sysctl.h>
98 #include <sys/ioctl.h>
99 #include <netinet6/in6_var.h> /* XXX */
102 #include <arpa/inet.h>
103 #include <arpa/nameser.h>
112 #include <nsswitch.h>
114 #include "un-namespace.h"
115 #include "netdb_private.h"
116 #include "res_private.h"
119 #define MAXALIASES 10
125 #define MAXDNAME 1025
129 #define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
130 sizeof(struct in_addr))
132 #define ADDRLEN(af) sizeof(struct in_addr)
135 #define MAPADDR(ab, ina) \
137 memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
138 memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
139 memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
141 #define MAPADDRENABLED(flags) \
142 (((flags) & AI_V4MAPPED) || \
143 (((flags) & AI_V4MAPPED_CFG)))
146 struct in_addr in_addr
;
148 struct in6_addr in6_addr
;
153 struct in_addr mau_inaddr
;
155 #define map_zero map_addr_un.mau_zero
156 #define map_one map_addr_un.mau_one
157 #define map_inaddr map_addr_un.mau_inaddr
161 TAILQ_ENTRY(policyqueue
) pc_entry
;
163 struct in6_addrpolicy pc_policy
;
166 TAILQ_HEAD(policyhead
, policyqueue
);
168 #define AIO_SRCFLAG_DEPRECATED 0x1
172 struct sockaddr_storage aiou_ss
;
173 struct sockaddr aiou_sa
;
175 #define aio_srcsa aio_src_un.aiou_sa
176 u_int32_t aio_srcflag
;
179 struct policyqueue
*aio_srcpolicy
;
180 struct policyqueue
*aio_dstpolicy
;
182 struct sockaddr_storage aiou_ss
;
183 struct sockaddr aiou_sa
;
185 #define aio_sa aio_un.aiou_sa
190 static struct hostent
*_hpcopy(struct hostent
*, int *);
191 static struct hostent
*_hpaddr(int, const char *, void *, int *);
193 static struct hostent
*_hpmerge(struct hostent
*, struct hostent
*, int *);
194 static struct hostent
*_hpmapv6(struct hostent
*, int *);
196 static struct hostent
*_hpsort(struct hostent
*, res_state
);
198 static struct hostent
*_hpreorder(struct hostent
*);
199 static int get_addrselectpolicy(struct policyhead
*);
200 static void free_addrselectpolicy(struct policyhead
*);
201 static struct policyqueue
*match_addrselectpolicy(struct sockaddr
*,
202 struct policyhead
*);
203 static void set_source(struct hp_order
*, struct policyhead
*);
204 static int matchlen(struct sockaddr
*, struct sockaddr
*);
205 static int comp_dst(const void *, const void *);
206 static int gai_addr2scopetype(struct sockaddr
*);
209 * Functions defined in RFC2553
210 * getipnodebyname, getipnodebyaddr, freehostent
214 getipnodebyname(const char *name
, int af
, int flags
, int *errp
)
217 union inx_addr addrbuf
;
232 if (flags
& AI_ADDRCONFIG
) {
235 if ((s
= _socket(af
, SOCK_DGRAM
, 0)) < 0)
239 * Note that implementation dependent test for address
240 * configuration should be done everytime called
241 * (or apropriate interval),
242 * because addresses will be dynamically assigned or deleted.
248 /* special case for literal address */
249 if (inet_pton(AF_INET6
, name
, &addrbuf
) == 1) {
250 if (af
!= AF_INET6
) {
251 *errp
= HOST_NOT_FOUND
;
254 return _hpaddr(af
, name
, &addrbuf
, errp
);
257 if (inet_aton(name
, (struct in_addr
*)&addrbuf
) == 1) {
259 if (MAPADDRENABLED(flags
)) {
260 MAPADDR(&addrbuf
, &addrbuf
.in_addr
);
262 *errp
= HOST_NOT_FOUND
;
266 return _hpaddr(af
, name
, &addrbuf
, errp
);
270 statp
= __res_state();
271 if ((statp
->options
& RES_INIT
) == 0) {
272 if (res_ninit(statp
) < 0) {
273 *errp
= NETDB_INTERNAL
;
278 options
= statp
->options
;
279 statp
->options
&= ~RES_USE_INET6
;
281 hp
= gethostbyname2(name
, af
);
282 hp
= _hpcopy(hp
, errp
);
285 if (af
== AF_INET6
&& ((flags
& AI_ALL
) || hp
== NULL
) &&
286 MAPADDRENABLED(flags
)) {
287 struct hostent
*hp2
= gethostbyname2(name
, AF_INET
);
290 *errp
= statp
->res_h_errno
;
292 hp
= _hpmapv6(hp2
, errp
);
294 if (hp2
&& strcmp(hp
->h_name
, hp2
->h_name
) == 0) {
295 struct hostent
*hpb
= hp
;
296 hp
= _hpmerge(hpb
, hp2
, errp
);
304 *errp
= statp
->res_h_errno
;
306 statp
->options
= options
;
307 return _hpreorder(_hpsort(hp
, statp
));
311 getipnodebyaddr(const void *src
, size_t len
, int af
, int *errp
)
318 struct in6_addr addrbuf
;
320 struct in_addr addrbuf
;
325 if (len
!= sizeof(struct in_addr
)) {
329 if ((long)src
& ~(sizeof(struct in_addr
) - 1)) {
330 memcpy(&addrbuf
, src
, len
);
333 if (((struct in_addr
*)src
)->s_addr
== 0)
338 if (len
!= sizeof(struct in6_addr
)) {
342 if ((long)src
& ~(sizeof(struct in6_addr
) / 2 - 1)) { /*XXX*/
343 memcpy(&addrbuf
, src
, len
);
346 if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr
*)src
))
348 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)src
)
349 || IN6_IS_ADDR_V4COMPAT((struct in6_addr
*)src
)) {
351 (sizeof(struct in6_addr
) - sizeof(struct in_addr
));
353 len
= sizeof(struct in_addr
);
362 statp
= __res_state();
363 if ((statp
->options
& RES_INIT
) == 0) {
364 if (res_ninit(statp
) < 0) {
365 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
370 options
= statp
->options
;
371 statp
->options
&= ~RES_USE_INET6
;
373 hp
= gethostbyaddr(src
, len
, af
);
375 *errp
= statp
->res_h_errno
;
377 statp
->options
= options
;
378 return (_hpcopy(hp
, errp
));
382 freehostent(struct hostent
*ptr
)
388 * Private utility functions
392 * _hpcopy: allocate and copy hostent structure
394 static struct hostent
*
395 _hpcopy(struct hostent
*hp
, int *errp
)
400 int nalias
= 0, naddr
= 0;
407 /* count size to be allocated */
408 size
= sizeof(struct hostent
);
409 if (hp
->h_name
!= NULL
)
410 size
+= strlen(hp
->h_name
) + 1;
411 if ((pp
= hp
->h_aliases
) != NULL
) {
412 for (i
= 0; *pp
!= NULL
; i
++, pp
++) {
414 size
+= strlen(*pp
) + 1;
419 /* adjust alignment */
422 size
+= sizeof(char *) * (nalias
+ 1);
423 addrsize
= ALIGN(hp
->h_length
);
424 if ((pp
= hp
->h_addr_list
) != NULL
) {
425 while (*pp
++ != NULL
)
428 size
+= addrsize
* naddr
;
429 size
+= sizeof(char *) * (naddr
+ 1);
432 if ((nhp
= (struct hostent
*)malloc(size
)) == NULL
) {
436 cp
= (char *)&nhp
[1];
437 if (hp
->h_name
!= NULL
) {
439 strcpy(cp
, hp
->h_name
);
440 cp
+= strlen(cp
) + 1;
443 nhp
->h_aliases
= (char **)((char *)nhp
+ al_off
);
444 if ((pp
= hp
->h_aliases
) != NULL
) {
445 for (i
= 0; *pp
!= NULL
; pp
++) {
447 nhp
->h_aliases
[i
++] = cp
;
449 cp
+= strlen(cp
) + 1;
453 nhp
->h_aliases
[nalias
] = NULL
;
454 cp
= (char *)&nhp
->h_aliases
[nalias
+ 1];
455 nhp
->h_addrtype
= hp
->h_addrtype
;
456 nhp
->h_length
= hp
->h_length
;
457 nhp
->h_addr_list
= (char **)cp
;
458 if ((pp
= hp
->h_addr_list
) != NULL
) {
459 cp
= (char *)&nhp
->h_addr_list
[naddr
+ 1];
460 for (i
= 0; *pp
!= NULL
; pp
++) {
461 nhp
->h_addr_list
[i
++] = cp
;
462 memcpy(cp
, *pp
, hp
->h_length
);
466 nhp
->h_addr_list
[naddr
] = NULL
;
471 * _hpaddr: construct hostent structure with one address
473 static struct hostent
*
474 _hpaddr(int af
, const char *name
, void *addr
, int *errp
)
476 struct hostent
*hp
, hpbuf
;
480 hp
->h_name
= (char *)name
;
481 hp
->h_aliases
= NULL
;
483 hp
->h_length
= ADDRLEN(af
);
484 hp
->h_addr_list
= addrs
;
485 addrs
[0] = (char *)addr
;
487 return (_hpcopy(hp
, errp
));
492 * _hpmerge: merge 2 hostent structure, arguments will be freed
494 static struct hostent
*
495 _hpmerge(struct hostent
*hp1
, struct hostent
*hp2
, int *errp
)
500 struct hostent
*hp
, hpbuf
;
501 char *aliases
[MAXALIASES
+ 1], *addrs
[MAXADDRS
+ 1];
502 union inx_addr addrbuf
[MAXADDRS
];
505 return _hpcopy(hp2
, errp
);
507 return _hpcopy(hp1
, errp
);
509 #define HP(i) (i == 1 ? hp1 : hp2)
511 hp
->h_name
= (hp1
->h_name
!= NULL
? hp1
->h_name
: hp2
->h_name
);
512 hp
->h_aliases
= aliases
;
514 for (i
= 1; i
<= 2; i
++) {
515 if ((pp
= HP(i
)->h_aliases
) == NULL
)
517 for (; nalias
< MAXALIASES
&& *pp
!= NULL
; pp
++) {
518 /* check duplicates */
519 for (j
= 0; j
< nalias
; j
++)
520 if (strcasecmp(*pp
, aliases
[j
]) == 0)
523 aliases
[nalias
++] = *pp
;
526 aliases
[nalias
] = NULL
;
527 if (hp1
->h_length
!= hp2
->h_length
) {
528 hp
->h_addrtype
= AF_INET6
;
529 hp
->h_length
= sizeof(struct in6_addr
);
531 hp
->h_addrtype
= hp1
->h_addrtype
;
532 hp
->h_length
= hp1
->h_length
;
535 hp
->h_addr_list
= addrs
;
537 for (i
= 1; i
<= 2; i
++) {
538 if ((pp
= HP(i
)->h_addr_list
) == NULL
)
540 if (HP(i
)->h_length
== hp
->h_length
) {
541 while (naddr
< MAXADDRS
&& *pp
!= NULL
)
542 addrs
[naddr
++] = *pp
++;
544 /* copy IPv4 addr as mapped IPv6 addr */
545 while (naddr
< MAXADDRS
&& *pp
!= NULL
) {
546 MAPADDR(&addrbuf
[naddr
], *pp
++);
547 addrs
[naddr
] = (char *)&addrbuf
[naddr
];
553 return (_hpcopy(hp
, errp
));
558 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
561 static struct hostent
*
562 _hpmapv6(struct hostent
*hp
, int *errp
)
568 if (hp
->h_addrtype
== AF_INET6
)
569 return _hpcopy(hp
, errp
);
571 memset(&hp6
, 0, sizeof(struct hostent
));
572 hp6
.h_addrtype
= AF_INET6
;
573 hp6
.h_length
= sizeof(struct in6_addr
);
574 return _hpmerge(&hp6
, hp
, errp
);
579 * _hpsort: sort address by sortlist
581 static struct hostent
*
582 _hpsort(struct hostent
*hp
, res_state statp
)
585 u_char
*ap
, *sp
, *mp
, **pp
;
587 char order
[MAXADDRS
];
588 int nsort
= statp
->nsort
;
590 if (hp
== NULL
|| hp
->h_addr_list
[1] == NULL
|| nsort
== 0)
592 for (i
= 0; (ap
= (u_char
*)hp
->h_addr_list
[i
]); i
++) {
593 for (j
= 0; j
< nsort
; j
++) {
595 if (statp
->_u
._ext
.ext
->sort_list
[j
].af
!=
598 sp
= (u_char
*)&statp
->_u
._ext
.ext
->sort_list
[j
].addr
;
599 mp
= (u_char
*)&statp
->_u
._ext
.ext
->sort_list
[j
].mask
;
601 sp
= (u_char
*)&statp
->sort_list
[j
].addr
;
602 mp
= (u_char
*)&statp
->sort_list
[j
].mask
;
604 for (n
= 0; n
< hp
->h_length
; n
++) {
605 if ((ap
[n
] & mp
[n
]) != sp
[n
])
608 if (n
== hp
->h_length
)
614 pp
= (u_char
**)hp
->h_addr_list
;
615 for (i
= 0; i
< n
- 1; i
++) {
616 for (j
= i
+ 1; j
< n
; j
++) {
617 if (order
[i
] > order
[j
]) {
631 * _hpreorder: sort address by default address selection
633 static struct hostent
*
634 _hpreorder(struct hostent
*hp
)
636 struct hp_order
*aio
;
640 struct policyhead policyhead
;
645 switch (hp
->h_addrtype
) {
652 free_addrselectpolicy(&policyhead
);
656 /* count the number of addrinfo elements for sorting. */
657 for (n
= 0; hp
->h_addr_list
[n
] != NULL
; n
++)
661 * If the number is small enough, we can skip the reordering process.
666 /* allocate a temporary array for sort and initialization of it. */
667 if ((aio
= malloc(sizeof(*aio
) * n
)) == NULL
)
668 return hp
; /* give up reordering */
669 memset(aio
, 0, sizeof(*aio
) * n
);
671 /* retrieve address selection policy from the kernel */
672 TAILQ_INIT(&policyhead
);
673 if (!get_addrselectpolicy(&policyhead
)) {
674 /* no policy is installed into kernel, we don't sort. */
679 for (i
= 0; i
< n
; i
++) {
680 ap
= hp
->h_addr_list
[i
];
681 aio
[i
].aio_h_addr
= ap
;
683 switch (hp
->h_addrtype
) {
685 sa
->sa_family
= AF_INET
;
686 sa
->sa_len
= sizeof(struct sockaddr_in
);
687 memcpy(&((struct sockaddr_in
*)sa
)->sin_addr
, ap
,
688 sizeof(struct in_addr
));
692 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
693 sa
->sa_family
= AF_INET
;
694 sa
->sa_len
= sizeof(struct sockaddr_in
);
695 memcpy(&((struct sockaddr_in
*)sa
)->sin_addr
,
696 &ap
[12], sizeof(struct in_addr
));
698 sa
->sa_family
= AF_INET6
;
699 sa
->sa_len
= sizeof(struct sockaddr_in6
);
700 memcpy(&((struct sockaddr_in6
*)sa
)->sin6_addr
,
701 ap
, sizeof(struct in6_addr
));
706 aio
[i
].aio_dstscope
= gai_addr2scopetype(sa
);
707 aio
[i
].aio_dstpolicy
= match_addrselectpolicy(sa
, &policyhead
);
708 set_source(&aio
[i
], &policyhead
);
711 /* perform sorting. */
712 qsort(aio
, n
, sizeof(*aio
), comp_dst
);
714 /* reorder the h_addr_list. */
715 for (i
= 0; i
< n
; i
++)
716 hp
->h_addr_list
[i
] = aio
[i
].aio_h_addr
;
718 /* cleanup and return */
720 free_addrselectpolicy(&policyhead
);
725 get_addrselectpolicy(struct policyhead
*head
)
728 int mib
[] = { CTL_NET
, PF_INET6
, IPPROTO_IPV6
, IPV6CTL_ADDRCTLPOLICY
};
731 struct in6_addrpolicy
*pol
, *ep
;
733 if (sysctl(mib
, NELEM(mib
), NULL
, &l
, NULL
, 0) < 0)
735 if ((buf
= malloc(l
)) == NULL
)
737 if (sysctl(mib
, NELEM(mib
), buf
, &l
, NULL
, 0) < 0) {
742 ep
= (struct in6_addrpolicy
*)(buf
+ l
);
743 for (pol
= (struct in6_addrpolicy
*)buf
; pol
+ 1 <= ep
; pol
++) {
744 struct policyqueue
*new;
746 if ((new = malloc(sizeof(*new))) == NULL
) {
747 free_addrselectpolicy(head
); /* make the list empty */
750 new->pc_policy
= *pol
;
751 TAILQ_INSERT_TAIL(head
, new, pc_entry
);
762 free_addrselectpolicy(struct policyhead
*head
)
764 struct policyqueue
*ent
, *nent
;
766 for (ent
= TAILQ_FIRST(head
); ent
; ent
= nent
) {
767 nent
= TAILQ_NEXT(ent
, pc_entry
);
768 TAILQ_REMOVE(head
, ent
, pc_entry
);
773 static struct policyqueue
*
774 match_addrselectpolicy(struct sockaddr
*addr
, struct policyhead
*head
)
777 struct policyqueue
*ent
, *bestent
= NULL
;
778 struct in6_addrpolicy
*pol
;
779 int matchlen
, bestmatchlen
= -1;
780 u_char
*mp
, *ep
, *k
, *p
, m
;
781 struct sockaddr_in6 key
;
783 switch(addr
->sa_family
) {
785 key
= *(struct sockaddr_in6
*)addr
;
788 /* convert the address into IPv4-mapped IPv6 address. */
789 memset(&key
, 0, sizeof(key
));
790 key
.sin6_family
= AF_INET6
;
791 key
.sin6_len
= sizeof(key
);
792 key
.sin6_addr
.s6_addr
[10] = 0xff;
793 key
.sin6_addr
.s6_addr
[11] = 0xff;
794 memcpy(&key
.sin6_addr
.s6_addr
[12],
795 &((struct sockaddr_in
*)addr
)->sin_addr
, 4);
801 for (ent
= TAILQ_FIRST(head
); ent
; ent
= TAILQ_NEXT(ent
, pc_entry
)) {
802 pol
= &ent
->pc_policy
;
805 mp
= (u_char
*)&pol
->addrmask
.sin6_addr
;
806 ep
= mp
+ 16; /* XXX: scope field? */
807 k
= (u_char
*)&key
.sin6_addr
;
808 p
= (u_char
*)&pol
->addr
.sin6_addr
;
809 for (; mp
< ep
&& *mp
; mp
++, k
++, p
++) {
812 goto next
; /* not match */
813 if (m
== 0xff) /* short cut for a typical case */
823 /* matched. check if this is better than the current best. */
824 if (matchlen
> bestmatchlen
) {
826 bestmatchlen
= matchlen
;
841 set_source(struct hp_order
*aio
, struct policyhead
*ph
)
843 struct sockaddr_storage ss
= aio
->aio_un
.aiou_ss
;
847 /* set unspec ("no source is available"), just in case */
848 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
849 aio
->aio_srcscope
= -1;
851 switch(ss
.ss_family
) {
853 ((struct sockaddr_in
*)&ss
)->sin_port
= htons(1);
857 ((struct sockaddr_in6
*)&ss
)->sin6_port
= htons(1);
860 default: /* ignore unsupported AFs explicitly */
864 /* open a socket to get the source address for the given dst */
865 if ((s
= _socket(ss
.ss_family
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
866 return; /* give up */
867 if (_connect(s
, (struct sockaddr
*)&ss
, ss
.ss_len
) < 0)
870 if (_getsockname(s
, &aio
->aio_srcsa
, &srclen
) < 0) {
871 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
874 aio
->aio_srcscope
= gai_addr2scopetype(&aio
->aio_srcsa
);
875 aio
->aio_srcpolicy
= match_addrselectpolicy(&aio
->aio_srcsa
, ph
);
876 aio
->aio_matchlen
= matchlen(&aio
->aio_srcsa
, (struct sockaddr
*)&ss
);
878 if (ss
.ss_family
== AF_INET6
) {
879 struct in6_ifreq ifr6
;
882 /* XXX: interface name should not be hardcoded */
883 strncpy(ifr6
.ifr_name
, "lo0", sizeof(ifr6
.ifr_name
));
884 memset(&ifr6
, 0, sizeof(ifr6
));
885 memcpy(&ifr6
.ifr_addr
, &ss
, ss
.ss_len
);
886 if (_ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) == 0) {
887 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
888 if ((flags6
& IN6_IFF_DEPRECATED
))
889 aio
->aio_srcflag
|= AIO_SRCFLAG_DEPRECATED
;
900 matchlen(struct sockaddr
*src
, struct sockaddr
*dst
)
907 switch (src
->sa_family
) {
910 s
= (u_char
*)&((struct sockaddr_in6
*)src
)->sin6_addr
;
911 d
= (u_char
*)&((struct sockaddr_in6
*)dst
)->sin6_addr
;
912 addrlen
= sizeof(struct in6_addr
);
917 s
= (u_char
*)&((struct sockaddr_in
*)src
)->sin_addr
;
918 d
= (u_char
*)&((struct sockaddr_in
*)dst
)->sin_addr
;
919 addrlen
= sizeof(struct in_addr
);
927 if ((r
= (*d
++ ^ *s
++)) != 0) {
928 while (r
< addrlen
* 8) {
939 comp_dst(const void *arg1
, const void *arg2
)
941 const struct hp_order
*dst1
= arg1
, *dst2
= arg2
;
944 * Rule 1: Avoid unusable destinations.
945 * XXX: we currently do not consider if an appropriate route exists.
947 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
948 dst2
->aio_srcsa
.sa_family
== AF_UNSPEC
) {
951 if (dst1
->aio_srcsa
.sa_family
== AF_UNSPEC
&&
952 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
956 /* Rule 2: Prefer matching scope. */
957 if (dst1
->aio_dstscope
== dst1
->aio_srcscope
&&
958 dst2
->aio_dstscope
!= dst2
->aio_srcscope
) {
961 if (dst1
->aio_dstscope
!= dst1
->aio_srcscope
&&
962 dst2
->aio_dstscope
== dst2
->aio_srcscope
) {
966 /* Rule 3: Avoid deprecated addresses. */
967 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
968 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
969 if (!(dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
970 (dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
973 if ((dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
974 !(dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
979 /* Rule 4: Prefer home addresses. */
980 /* XXX: not implemented yet */
982 /* Rule 5: Prefer matching label. */
984 if (dst1
->aio_srcpolicy
&& dst1
->aio_dstpolicy
&&
985 dst1
->aio_srcpolicy
->pc_policy
.label
==
986 dst1
->aio_dstpolicy
->pc_policy
.label
&&
987 (dst2
->aio_srcpolicy
== NULL
|| dst2
->aio_dstpolicy
== NULL
||
988 dst2
->aio_srcpolicy
->pc_policy
.label
!=
989 dst2
->aio_dstpolicy
->pc_policy
.label
)) {
992 if (dst2
->aio_srcpolicy
&& dst2
->aio_dstpolicy
&&
993 dst2
->aio_srcpolicy
->pc_policy
.label
==
994 dst2
->aio_dstpolicy
->pc_policy
.label
&&
995 (dst1
->aio_srcpolicy
== NULL
|| dst1
->aio_dstpolicy
== NULL
||
996 dst1
->aio_srcpolicy
->pc_policy
.label
!=
997 dst1
->aio_dstpolicy
->pc_policy
.label
)) {
1002 /* Rule 6: Prefer higher precedence. */
1004 if (dst1
->aio_dstpolicy
&&
1005 (dst2
->aio_dstpolicy
== NULL
||
1006 dst1
->aio_dstpolicy
->pc_policy
.preced
>
1007 dst2
->aio_dstpolicy
->pc_policy
.preced
)) {
1010 if (dst2
->aio_dstpolicy
&&
1011 (dst1
->aio_dstpolicy
== NULL
||
1012 dst2
->aio_dstpolicy
->pc_policy
.preced
>
1013 dst1
->aio_dstpolicy
->pc_policy
.preced
)) {
1018 /* Rule 7: Prefer native transport. */
1019 /* XXX: not implemented yet */
1021 /* Rule 8: Prefer smaller scope. */
1022 if (dst1
->aio_dstscope
>= 0 &&
1023 dst1
->aio_dstscope
< dst2
->aio_dstscope
) {
1026 if (dst2
->aio_dstscope
>= 0 &&
1027 dst2
->aio_dstscope
< dst1
->aio_dstscope
) {
1032 * Rule 9: Use longest matching prefix.
1033 * We compare the match length in a same AF only.
1035 if (dst1
->aio_sa
.sa_family
== dst2
->aio_sa
.sa_family
) {
1036 if (dst1
->aio_matchlen
> dst2
->aio_matchlen
) {
1039 if (dst1
->aio_matchlen
< dst2
->aio_matchlen
) {
1044 /* Rule 10: Otherwise, leave the order unchanged. */
1049 * Copy from scope.c.
1050 * XXX: we should standardize the functions and link them as standard
1054 gai_addr2scopetype(struct sockaddr
*sa
)
1057 struct sockaddr_in6
*sa6
;
1059 struct sockaddr_in
*sa4
;
1061 switch(sa
->sa_family
) {
1064 sa6
= (struct sockaddr_in6
*)sa
;
1065 if (IN6_IS_ADDR_MULTICAST(&sa6
->sin6_addr
)) {
1066 /* just use the scope field of the multicast address */
1067 return(sa6
->sin6_addr
.s6_addr
[2] & 0x0f);
1070 * Unicast addresses: map scope type to corresponding scope
1071 * value defined for multcast addresses.
1072 * XXX: hardcoded scope type values are bad...
1074 if (IN6_IS_ADDR_LOOPBACK(&sa6
->sin6_addr
))
1075 return(1); /* node local scope */
1076 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
))
1077 return(2); /* link-local scope */
1078 if (IN6_IS_ADDR_SITELOCAL(&sa6
->sin6_addr
))
1079 return(5); /* site-local scope */
1080 return(14); /* global scope */
1085 * IPv4 pseudo scoping according to RFC 3484.
1087 sa4
= (struct sockaddr_in
*)sa
;
1088 /* IPv4 autoconfiguration addresses have link-local scope. */
1089 if (((u_char
*)&sa4
->sin_addr
)[0] == 169 &&
1090 ((u_char
*)&sa4
->sin_addr
)[1] == 254)
1092 /* Private addresses have site-local scope. */
1093 if (((u_char
*)&sa4
->sin_addr
)[0] == 10 ||
1094 (((u_char
*)&sa4
->sin_addr
)[0] == 172 &&
1095 (((u_char
*)&sa4
->sin_addr
)[1] & 0xf0) == 16) ||
1096 (((u_char
*)&sa4
->sin_addr
)[0] == 192 &&
1097 ((u_char
*)&sa4
->sin_addr
)[1] == 168))
1098 return(14); /* XXX: It should be 5 unless NAT */
1099 /* Loopback addresses have link-local scope. */
1100 if (((u_char
*)&sa4
->sin_addr
)[0] == 127)
1105 errno
= EAFNOSUPPORT
; /* is this a good error? */