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 * GAI_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 GAI_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 GAI_ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN GAI_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 #include <sys/param.h>
44 #include <sys/sysctl.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <arpa/nameser.h>
60 #if defined(__KAME__) && defined(ENABLE_IPV6)
70 static int translate
= NO
;
71 static struct in6_addr faith_prefix
= IN6ADDR_GAI_ANY_INIT
;
74 static const char in_addrany
[] = { 0, 0, 0, 0 };
75 static const char in6_addrany
[] = {
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
78 static const char in_loopback
[] = { 127, 0, 0, 1 };
79 static const char in6_loopback
[] = {
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
89 static struct gai_afd
{
94 const char *a_addrany
;
95 const char *a_loopback
;
99 {PF_INET6
, sizeof(struct in6_addr
),
100 sizeof(struct sockaddr_in6
),
101 offsetof(struct sockaddr_in6
, sin6_addr
),
102 in6_addrany
, in6_loopback
},
107 {PF_INET
, sizeof(struct in_addr
),
108 sizeof(struct sockaddr_in
),
109 offsetof(struct sockaddr_in
, sin_addr
),
110 in_addrany
, in_loopback
},
111 {0, 0, 0, 0, NULL
, NULL
},
121 #define IN_MULTICAST(i) (((i) & 0xf0000000U) == 0xe0000000U)
124 #ifndef IN_EXPERIMENTAL
125 #define IN_EXPERIMENTAL(i) (((i) & 0xe0000000U) == 0xe0000000U)
128 #ifndef IN_LOOPBACKNET
129 #define IN_LOOPBACKNET 127
132 static int get_name
Py_PROTO((const char *, struct gai_afd
*,
133 struct addrinfo
**, char *, struct addrinfo
*,
135 static int get_addr
Py_PROTO((const char *, int, struct addrinfo
**,
136 struct addrinfo
*, int));
137 static int str_isnumber
Py_PROTO((const char *));
139 static char *ai_errlist
[] = {
141 "address family for hostname not supported.", /* EAI_ADDRFAMILY */
142 "temporary failure in name resolution.", /* EAI_AGAIN */
143 "invalid value for ai_flags.", /* EAI_BADFLAGS */
144 "non-recoverable failure in name resolution.", /* EAI_FAIL */
145 "ai_family not supported.", /* EAI_FAMILY */
146 "memory allocation failure.", /* EAI_MEMORY */
147 "no address associated with hostname.", /* EAI_NODATA */
148 "hostname nor servname provided, or not known.",/* EAI_NONAME */
149 "servname not supported for ai_socktype.", /* EAI_SERVICE */
150 "ai_socktype not supported.", /* EAI_SOCKTYPE */
151 "system error returned in errno.", /* EAI_SYSTEM */
152 "invalid value for hints.", /* EAI_BADHINTS */
153 "resolved protocol is unknown.", /* EAI_PROTOCOL */
154 "unknown error.", /* EAI_MAX */
157 #define GET_CANONNAME(ai, str) \
158 if (pai->ai_flags & AI_CANONNAME) {\
159 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
160 strcpy((ai)->ai_canonname, (str));\
167 #ifdef HAVE_SOCKADDR_SA_LEN
168 #define GET_AI(ai, gai_afd, addr, port) {\
170 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
171 ((gai_afd)->a_socklen)))\
173 memcpy(ai, pai, sizeof(struct addrinfo));\
174 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
175 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
176 (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\
177 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
178 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
179 p = (char *)((ai)->ai_addr);\
180 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
183 #define GET_AI(ai, gai_afd, addr, port) {\
185 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
186 ((gai_afd)->a_socklen)))\
188 memcpy(ai, pai, sizeof(struct addrinfo));\
189 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
190 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
191 (ai)->ai_addrlen = (gai_afd)->a_socklen;\
192 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
193 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
194 p = (char *)((ai)->ai_addr);\
195 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
199 #define ERR(err) { error = (err); goto bad; }
202 gai_strerror(int ecode
)
204 if (ecode
< 0 || ecode
> EAI_MAX
)
206 return ai_errlist
[ecode
];
210 freeaddrinfo(struct addrinfo
*ai
)
212 struct addrinfo
*next
;
216 if (ai
->ai_canonname
)
217 free(ai
->ai_canonname
);
218 /* no need to free(ai->ai_addr) */
220 } while ((ai
= next
) != NULL
);
224 str_isnumber(const char *p
)
226 unsigned char *q
= (unsigned char *)p
;
236 getaddrinfo(const char*hostname
, const char*servname
,
237 const struct addrinfo
*hints
, struct addrinfo
**res
)
239 struct addrinfo sentinel
;
240 struct addrinfo
*top
= NULL
;
241 struct addrinfo
*cur
;
245 struct addrinfo
*pai
;
249 static int firsttime
= 1;
252 /* translator hack */
254 char *q
= getenv("GAI");
255 if (q
&& inet_pton(AF_INET6
, q
, &faith_prefix
) == 1)
262 /* initialize file static vars */
263 sentinel
.ai_next
= NULL
;
267 pai
->ai_family
= PF_UNSPEC
;
268 pai
->ai_socktype
= GAI_ANY
;
269 pai
->ai_protocol
= GAI_ANY
;
271 pai
->ai_canonname
= NULL
;
276 if (hostname
== NULL
&& servname
== NULL
)
279 /* error check for hints */
280 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
281 hints
->ai_addr
|| hints
->ai_next
)
282 ERR(EAI_BADHINTS
); /* xxx */
283 if (hints
->ai_flags
& ~AI_MASK
)
285 switch (hints
->ai_family
) {
295 memcpy(pai
, hints
, sizeof(*pai
));
296 switch (pai
->ai_socktype
) {
298 switch (pai
->ai_protocol
) {
302 pai
->ai_socktype
= SOCK_DGRAM
;
305 pai
->ai_socktype
= SOCK_STREAM
;
308 pai
->ai_socktype
= SOCK_RAW
;
315 if (pai
->ai_protocol
!= IPPROTO_UDP
&&
316 pai
->ai_protocol
!= GAI_ANY
)
317 ERR(EAI_BADHINTS
); /*xxx*/
318 pai
->ai_protocol
= IPPROTO_UDP
;
321 if (pai
->ai_protocol
!= IPPROTO_TCP
&&
322 pai
->ai_protocol
!= GAI_ANY
)
323 ERR(EAI_BADHINTS
); /*xxx*/
324 pai
->ai_protocol
= IPPROTO_TCP
;
336 if (str_isnumber(servname
)) {
337 if (pai
->ai_socktype
== GAI_ANY
) {
338 /* caller accept *GAI_ANY* socktype */
339 pai
->ai_socktype
= SOCK_DGRAM
;
340 pai
->ai_protocol
= IPPROTO_UDP
;
342 port
= htons((u_short
)atoi(servname
));
348 switch (pai
->ai_socktype
) {
359 fprintf(stderr
, "panic!\n");
362 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
365 if (pai
->ai_socktype
== GAI_ANY
) {
366 if (strcmp(sp
->s_proto
, "udp") == 0) {
367 pai
->ai_socktype
= SOCK_DGRAM
;
368 pai
->ai_protocol
= IPPROTO_UDP
;
369 } else if (strcmp(sp
->s_proto
, "tcp") == 0) {
370 pai
->ai_socktype
= SOCK_STREAM
;
371 pai
->ai_protocol
= IPPROTO_TCP
;
373 ERR(EAI_PROTOCOL
); /*xxx*/
380 * passive socket -> anyaddr (0.0.0.0 or ::)
381 * non-passive socket -> localhost (127.0.0.1 or ::1)
383 if (hostname
== NULL
) {
384 struct gai_afd
*gai_afd
;
386 for (gai_afd
= &gai_afdl
[0]; gai_afd
->a_af
; gai_afd
++) {
387 if (!(pai
->ai_family
== PF_UNSPEC
388 || pai
->ai_family
== gai_afd
->a_af
)) {
392 if (pai
->ai_flags
& AI_PASSIVE
) {
393 GET_AI(cur
->ai_next
, gai_afd
, gai_afd
->a_addrany
, port
);
395 * GET_CANONNAME(cur->ai_next, "anyaddr");
398 GET_AI(cur
->ai_next
, gai_afd
, gai_afd
->a_loopback
,
401 * GET_CANONNAME(cur->ai_next, "localhost");
406 top
= sentinel
.ai_next
;
413 /* hostname as numeric name */
414 for (i
= 0; gai_afdl
[i
].a_af
; i
++) {
415 if (inet_pton(gai_afdl
[i
].a_af
, hostname
, pton
)) {
421 switch (gai_afdl
[i
].a_af
) {
423 v4a
= ((struct in_addr
*)pton
)->s_addr
;
425 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
426 pai
->ai_flags
&= ~AI_CANONNAME
;
427 v4a
>>= IN_CLASSA_NSHIFT
;
428 if (v4a
== 0 || v4a
== IN_LOOPBACKNET
)
429 pai
->ai_flags
&= ~AI_CANONNAME
;
433 pfx
= ((struct in6_addr
*)pton
)->s6_addr8
[0];
434 if (pfx
== 0 || pfx
== 0xfe || pfx
== 0xff)
435 pai
->ai_flags
&= ~AI_CANONNAME
;
440 if (pai
->ai_family
== gai_afdl
[i
].a_af
||
441 pai
->ai_family
== PF_UNSPEC
) {
442 if (! (pai
->ai_flags
& AI_CANONNAME
)) {
443 GET_AI(top
, &gai_afdl
[i
], pton
, port
);
447 * if AI_CANONNAME and if reverse lookup
448 * fail, return ai anyway to pacify
449 * calling application.
451 * XXX getaddrinfo() is a name->address
452 * translation function, and it looks strange
453 * that we do addr->name translation here.
455 get_name(pton
, &gai_afdl
[i
], &top
, pton
, pai
, port
);
458 ERR(EAI_FAMILY
); /*xxx*/
462 if (pai
->ai_flags
& AI_NUMERICHOST
)
465 /* hostname as alphabetical name */
466 error
= get_addr(hostname
, pai
->ai_family
, &top
, pai
, port
);
484 get_name(addr
, gai_afd
, res
, numaddr
, pai
, port0
)
486 struct gai_afd
*gai_afd
;
487 struct addrinfo
**res
;
489 struct addrinfo
*pai
;
492 u_short port
= port0
& 0xffff;
494 struct addrinfo
*cur
;
501 hp
= getipnodebyaddr(addr
, gai_afd
->a_addrlen
, gai_afd
->a_af
, &h_error
);
503 hp
= gethostbyaddr(addr
, gai_afd
->a_addrlen
, AF_INET
);
505 if (hp
&& hp
->h_name
&& hp
->h_name
[0] && hp
->h_addr_list
[0]) {
506 GET_AI(cur
, gai_afd
, hp
->h_addr_list
[0], port
);
507 GET_CANONNAME(cur
, hp
->h_name
);
509 GET_AI(cur
, gai_afd
, numaddr
, port
);
530 get_addr(hostname
, af
, res
, pai
, port0
)
531 const char *hostname
;
533 struct addrinfo
**res
;
534 struct addrinfo
*pai
;
537 u_short port
= port0
& 0xffff;
538 struct addrinfo sentinel
;
540 struct addrinfo
*top
, *cur
;
541 struct gai_afd
*gai_afd
;
542 int i
, error
= 0, h_error
;
546 sentinel
.ai_next
= NULL
;
549 if (af
== AF_UNSPEC
) {
550 hp
= getipnodebyname(hostname
, AF_INET6
,
551 AI_ADDRCONFIG
|AI_ALL
|AI_V4MAPPED
, &h_error
);
553 hp
= getipnodebyname(hostname
, af
, AI_ADDRCONFIG
, &h_error
);
555 hp
= gethostbyname(hostname
);
575 if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0) ||
576 (hp
->h_addr_list
[0] == NULL
)) {
581 for (i
= 0; (ap
= hp
->h_addr_list
[i
]) != NULL
; i
++) {
585 gai_afd
= &gai_afdl
[N_INET6
];
589 default: /* AF_UNSPEC */
592 gai_afd
= &gai_afdl
[N_INET
];
595 default: /* AF_UNSPEC */
596 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
597 ap
+= sizeof(struct in6_addr
) -
598 sizeof(struct in_addr
);
599 gai_afd
= &gai_afdl
[N_INET
];
601 gai_afd
= &gai_afdl
[N_INET6
];
606 if (translate
&& gai_afd
->a_af
== AF_INET
) {
607 struct in6_addr
*in6
;
609 GET_AI(cur
->ai_next
, &gai_afdl
[N_INET6
], ap
, port
);
610 in6
= &((struct sockaddr_in6
*)cur
->ai_next
->ai_addr
)->sin6_addr
;
611 memcpy(&in6
->s6_addr32
[0], &faith_prefix
,
612 sizeof(struct in6_addr
) - sizeof(struct in_addr
));
613 memcpy(&in6
->s6_addr32
[3], ap
, sizeof(struct in_addr
));
616 GET_AI(cur
->ai_next
, gai_afd
, ap
, port
);
617 if (cur
== &sentinel
) {
619 GET_CANONNAME(top
, hp
->h_name
);