2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
33 * Issues to be discussed:
34 * - Thread safe-ness must be checked.
35 * - Return values. There are nonstandard return values defined and used
36 * in the source code. This is because RFC2133 is silent about which error
37 * code must be returned for which situation.
38 * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
42 #include <sys/types.h>
43 #if !defined(_WIN32) && !defined(__VMS)
44 #include <sys/param.h>
46 # include <net/socket.h>
48 # include <sys/socket.h>
50 #include <netinet/in.h>
51 #if defined(HAVE_ARPA_INET_H)
52 #include <arpa/inet.h>
54 #if defined(HAVE_ARPA_NAMESER_H)
55 #include <arpa/nameser.h>
58 #if defined(HAVE_RESOLV_H)
87 #if defined(__KAME__) && defined(INET6)
97 static int translate
= NO
;
98 static struct in6_addr faith_prefix
= IN6ADDR_ANY_INIT
;
101 static const char in_addrany
[] = { 0, 0, 0, 0 };
102 static const char in6_addrany
[] = {
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
105 static const char in_loopback
[] = { 127, 0, 0, 1 };
106 static const char in6_loopback
[] = {
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
116 static const struct afd
{
121 const char *a_addrany
;
122 const char *a_loopback
;
126 {PF_INET6
, sizeof(struct in6_addr
),
127 sizeof(struct sockaddr_in6
),
128 offsetof(struct sockaddr_in6
, sin6_addr
),
129 in6_addrany
, in6_loopback
},
134 {PF_INET
, sizeof(struct in_addr
),
135 sizeof(struct sockaddr_in
),
136 offsetof(struct sockaddr_in
, sin_addr
),
137 in_addrany
, in_loopback
},
138 {0, 0, 0, 0, NULL
, NULL
},
147 static int get_name
__P((const char *, const struct afd
*,
148 struct addrinfo
**, char *, struct addrinfo
*,
150 static int get_addr
__P((const char *, int, struct addrinfo
**,
151 struct addrinfo
*, int));
152 static int str_isnumber
__P((const char *));
154 static const char *const ai_errlist
[] = {
156 "address family for hostname not supported.", /* EAI_ADDRFAMILY */
157 "temporary failure in name resolution.", /* EAI_AGAIN */
158 "invalid value for ai_flags.", /* EAI_BADFLAGS */
159 "non-recoverable failure in name resolution.", /* EAI_FAIL */
160 "ai_family not supported.", /* EAI_FAMILY */
161 "memory allocation failure.", /* EAI_MEMORY */
162 "no address associated with hostname.", /* EAI_NODATA */
163 "hostname nor servname provided, or not known.",/* EAI_NONAME */
164 "servname not supported for ai_socktype.", /* EAI_SERVICE */
165 "ai_socktype not supported.", /* EAI_SOCKTYPE */
166 "system error returned in errno.", /* EAI_SYSTEM */
167 "invalid value for hints.", /* EAI_BADHINTS */
168 "resolved protocol is unknown.", /* EAI_PROTOCOL */
169 "unknown error.", /* EAI_MAX */
172 #define GET_CANONNAME(ai, str) \
173 if (pai->ai_flags & AI_CANONNAME) {\
174 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
175 strcpy((ai)->ai_canonname, (str));\
182 #define GET_AI(ai, afd, addr, port) {\
184 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
185 ((afd)->a_socklen)))\
190 memcpy(ai, pai, sizeof(struct addrinfo));\
191 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
192 memset((ai)->ai_addr, 0, (afd)->a_socklen);\
193 SET_SA_LEN((ai)->ai_addr, (ai)->ai_addrlen = (afd)->a_socklen);\
194 (ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
195 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
196 p = (char *)((ai)->ai_addr);\
197 memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
200 #define ERR(err) { error = (err); goto bad; }
202 #if defined __UCLIBC__
209 if (ecode
< 0 || ecode
> EAI_MAX
)
211 return (char *)ai_errlist
[ecode
];
218 struct addrinfo
*next
;
222 if (ai
->ai_canonname
)
223 free(ai
->ai_canonname
);
224 /* no need to free(ai->ai_addr) */
226 } while ((ai
= next
) != NULL
);
242 #ifndef HAVE_INET_PTON
245 inet_pton(af
, hostname
, pton
)
247 const char *hostname
;
252 #ifdef HAVE_INET_ATON
253 if (!inet_aton(hostname
, &in
))
259 if (sscanf(hostname
, "%d.%d.%d.%d%c", &d1
, &d2
, &d3
, &d4
, &ch
) == 4 &&
260 0 <= d1
&& d1
<= 255 && 0 <= d2
&& d2
<= 255 &&
261 0 <= d3
&& d3
<= 255 && 0 <= d4
&& d4
<= 255) {
263 ((long) d1
<< 24) | ((long) d2
<< 16) |
264 ((long) d3
<< 8) | ((long) d4
<< 0));
270 memcpy(pton
, &in
, sizeof(in
));
276 getaddrinfo(hostname
, servname
, hints
, res
)
277 const char *hostname
, *servname
;
278 const struct addrinfo
*hints
;
279 struct addrinfo
**res
;
281 struct addrinfo sentinel
;
282 struct addrinfo
*top
= NULL
;
283 struct addrinfo
*cur
;
287 struct addrinfo
*pai
;
291 static int firsttime
= 1;
294 /* translator hack */
296 char *q
= getenv("GAI");
297 if (q
&& inet_pton(AF_INET6
, q
, &faith_prefix
) == 1)
304 /* initialize file static vars */
305 sentinel
.ai_next
= NULL
;
309 pai
->ai_family
= PF_UNSPEC
;
310 pai
->ai_socktype
= ANY
;
311 pai
->ai_protocol
= ANY
;
313 pai
->ai_canonname
= NULL
;
318 if (hostname
== NULL
&& servname
== NULL
)
321 /* error check for hints */
322 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
323 hints
->ai_addr
|| hints
->ai_next
)
324 ERR(EAI_BADHINTS
); /* xxx */
325 if (hints
->ai_flags
& ~AI_MASK
)
327 switch (hints
->ai_family
) {
337 memcpy(pai
, hints
, sizeof(*pai
));
338 switch (pai
->ai_socktype
) {
340 switch (pai
->ai_protocol
) {
344 pai
->ai_socktype
= SOCK_DGRAM
;
347 pai
->ai_socktype
= SOCK_STREAM
;
350 #if defined(SOCK_RAW)
351 pai
->ai_socktype
= SOCK_RAW
;
356 #if defined(SOCK_RAW)
361 if (pai
->ai_protocol
!= IPPROTO_UDP
&&
362 pai
->ai_protocol
!= ANY
)
363 ERR(EAI_BADHINTS
); /*xxx*/
364 pai
->ai_protocol
= IPPROTO_UDP
;
367 if (pai
->ai_protocol
!= IPPROTO_TCP
&&
368 pai
->ai_protocol
!= ANY
)
369 ERR(EAI_BADHINTS
); /*xxx*/
370 pai
->ai_protocol
= IPPROTO_TCP
;
382 if (str_isnumber(servname
)) {
383 if (pai
->ai_socktype
== ANY
) {
384 /* caller accept *ANY* socktype */
385 pai
->ai_socktype
= SOCK_DGRAM
;
386 pai
->ai_protocol
= IPPROTO_UDP
;
388 port
= htons((unsigned short)atoi(servname
));
394 switch (pai
->ai_socktype
) {
405 fprintf(stderr
, "panic!\n");
408 if ((sp
= getservbyname((char*)servname
, proto
)) == NULL
)
411 if (pai
->ai_socktype
== ANY
)
412 if (strcmp(sp
->s_proto
, "udp") == 0) {
413 pai
->ai_socktype
= SOCK_DGRAM
;
414 pai
->ai_protocol
= IPPROTO_UDP
;
415 } else if (strcmp(sp
->s_proto
, "tcp") == 0) {
416 pai
->ai_socktype
= SOCK_STREAM
;
417 pai
->ai_protocol
= IPPROTO_TCP
;
419 ERR(EAI_PROTOCOL
); /*xxx*/
425 * passive socket -> anyaddr (0.0.0.0 or ::)
426 * non-passive socket -> localhost (127.0.0.1 or ::1)
428 if (hostname
== NULL
) {
429 const struct afd
*afd
;
432 for (afd
= &afdl
[0]; afd
->a_af
; afd
++) {
433 if (!(pai
->ai_family
== PF_UNSPEC
434 || pai
->ai_family
== afd
->a_af
)) {
439 * filter out AFs that are not supported by the kernel
442 s
= socket(afd
->a_af
, SOCK_DGRAM
, 0);
445 #if defined(HAVE_CLOSESOCKET)
451 if (pai
->ai_flags
& AI_PASSIVE
) {
452 GET_AI(cur
->ai_next
, afd
, afd
->a_addrany
, port
);
454 * GET_CANONNAME(cur->ai_next, "anyaddr");
457 GET_AI(cur
->ai_next
, afd
, afd
->a_loopback
,
460 * GET_CANONNAME(cur->ai_next, "localhost");
465 top
= sentinel
.ai_next
;
472 /* hostname as numeric name */
473 for (i
= 0; afdl
[i
].a_af
; i
++) {
474 if (inet_pton(afdl
[i
].a_af
, hostname
, pton
)) {
480 switch (afdl
[i
].a_af
) {
482 v4a
= ((struct in_addr
*)pton
)->s_addr
;
483 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
484 pai
->ai_flags
&= ~AI_CANONNAME
;
485 v4a
>>= IN_CLASSA_NSHIFT
;
486 if (v4a
== 0 || v4a
== IN_LOOPBACKNET
)
487 pai
->ai_flags
&= ~AI_CANONNAME
;
492 pfx
= ((struct in6_addr
*)pton
)->s6_addr8
[0];
494 pfx
= ((struct in6_addr
*)pton
)->s6_addr
[0];
496 if (pfx
== 0 || pfx
== 0xfe || pfx
== 0xff)
497 pai
->ai_flags
&= ~AI_CANONNAME
;
502 if (pai
->ai_family
== afdl
[i
].a_af
||
503 pai
->ai_family
== PF_UNSPEC
) {
504 if (! (pai
->ai_flags
& AI_CANONNAME
)) {
505 GET_AI(top
, &afdl
[i
], pton
, port
);
509 * if AI_CANONNAME and if reverse lookup
510 * fail, return ai anyway to pacify
511 * calling application.
513 * XXX getaddrinfo() is a name->address
514 * translation function, and it looks strange
515 * that we do addr->name translation here.
517 get_name(pton
, &afdl
[i
], &top
, pton
, pai
, port
);
520 ERR(EAI_FAMILY
); /*xxx*/
524 if (pai
->ai_flags
& AI_NUMERICHOST
)
527 /* hostname as alphabetical name */
528 error
= get_addr(hostname
, pai
->ai_family
, &top
, pai
, port
);
546 get_name(addr
, afd
, res
, numaddr
, pai
, port0
)
548 const struct afd
*afd
;
549 struct addrinfo
**res
;
551 struct addrinfo
*pai
;
554 u_short port
= port0
& 0xffff;
556 struct addrinfo
*cur
;
563 hp
= getipnodebyaddr(addr
, afd
->a_addrlen
, afd
->a_af
, &h_error
);
565 hp
= gethostbyaddr((char*)addr
, afd
->a_addrlen
, AF_INET
);
567 if (hp
&& hp
->h_name
&& hp
->h_name
[0] && hp
->h_addr_list
[0]) {
568 GET_AI(cur
, afd
, hp
->h_addr_list
[0], port
);
569 GET_CANONNAME(cur
, hp
->h_name
);
571 GET_AI(cur
, afd
, numaddr
, port
);
592 get_addr(hostname
, af
, res
, pai
, port0
)
593 const char *hostname
;
595 struct addrinfo
**res
;
596 struct addrinfo
*pai
;
599 u_short port
= port0
& 0xffff;
600 struct addrinfo sentinel
;
602 struct addrinfo
*top
, *cur
;
603 const struct afd
*afd
;
604 int i
, error
= 0, h_error
;
608 sentinel
.ai_next
= NULL
;
611 if (af
== AF_UNSPEC
) {
612 hp
= getipnodebyname(hostname
, AF_INET6
,
613 AI_ADDRCONFIG
|AI_ALL
|AI_V4MAPPED
, &h_error
);
615 hp
= getipnodebyname(hostname
, af
, AI_ADDRCONFIG
, &h_error
);
617 hp
= gethostbyname((char*)hostname
);
637 if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0) ||
638 (hp
->h_addr_list
[0] == NULL
))
641 for (i
= 0; (ap
= hp
->h_addr_list
[i
]) != NULL
; i
++) {
645 afd
= &afdl
[N_INET6
];
649 default: /* AF_UNSPEC */
655 default: /* AF_UNSPEC */
656 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
657 ap
+= sizeof(struct in6_addr
) -
658 sizeof(struct in_addr
);
661 afd
= &afdl
[N_INET6
];
666 if (translate
&& afd
->a_af
== AF_INET
) {
667 struct in6_addr
*in6
;
669 GET_AI(cur
->ai_next
, &afdl
[N_INET6
], ap
, port
);
670 in6
= &((struct sockaddr_in6
*)cur
->ai_next
->ai_addr
)->sin6_addr
;
671 memcpy(&in6
->s6_addr32
[0], &faith_prefix
,
672 sizeof(struct in6_addr
) - sizeof(struct in_addr
));
673 memcpy(&in6
->s6_addr32
[3], ap
, sizeof(struct in_addr
));
676 GET_AI(cur
->ai_next
, afd
, ap
, port
);
677 if (cur
== &sentinel
) {
679 GET_CANONNAME(top
, hp
->h_name
);