| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |  * are met: | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |  *    documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * 3. Neither the name of the project nor the names of its contributors | 
					
						
							|  |  |  |  *    may be used to endorse or promote products derived from this software | 
					
						
							|  |  |  |  *    without specific prior written permission. | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 
					
						
							| 
									
										
										
										
											2016-03-07 14:51:59 -05:00
										 |  |  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
					
						
							|  |  |  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 
					
						
							| 
									
										
										
										
											2016-03-07 14:51:59 -05:00
										 |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
					
						
							|  |  |  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
					
						
							| 
									
										
										
										
											2016-03-07 14:51:59 -05:00
										 |  |  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
					
						
							|  |  |  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
					
						
							|  |  |  |  * SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Issues to be discussed: | 
					
						
							|  |  |  |  * - Thread safe-ness must be checked. | 
					
						
							|  |  |  |  * - Return values.  There are nonstandard return values defined and used | 
					
						
							|  |  |  |  *   in the source code.  This is because RFC2133 is silent about which error | 
					
						
							|  |  |  |  *   code must be returned for which situation. | 
					
						
							|  |  |  |  * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/param.h>
 | 
					
						
							|  |  |  | #include <sys/sysctl.h>
 | 
					
						
							|  |  |  | #include <sys/socket.h>
 | 
					
						
							|  |  |  | #include <netinet/in.h>
 | 
					
						
							|  |  |  | #include <arpa/inet.h>
 | 
					
						
							|  |  |  | #include <arpa/nameser.h>
 | 
					
						
							|  |  |  | #include <netdb.h>
 | 
					
						
							|  |  |  | #include <resolv.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stddef.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "addrinfo.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #if defined(__KAME__) && defined(ENABLE_IPV6)
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | # define FAITH
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 08:19:23 +02:00
										 |  |  | #ifdef HAVE_NETDB_H
 | 
					
						
							|  |  |  | #define HAVE_GETADDRINFO 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #define SUCCESS 0
 | 
					
						
							|  |  |  | #define GAI_ANY 0
 | 
					
						
							|  |  |  | #define YES 1
 | 
					
						
							|  |  |  | #define NO  0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef FAITH
 | 
					
						
							|  |  |  | static int translate = NO; | 
					
						
							|  |  |  | static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char in_addrany[] = { 0, 0, 0, 0 }; | 
					
						
							|  |  |  | static const char in6_addrany[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | static const char in_loopback[] = { 127, 0, 0, 1 }; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | static const char in6_loopback[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sockinet { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     u_char      si_len; | 
					
						
							|  |  |  |     u_char      si_family; | 
					
						
							|  |  |  |     u_short     si_port; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct gai_afd { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int a_af; | 
					
						
							|  |  |  |     int a_addrlen; | 
					
						
							|  |  |  |     int a_socklen; | 
					
						
							|  |  |  |     int a_off; | 
					
						
							|  |  |  |     const char *a_addrany; | 
					
						
							|  |  |  |     const char *a_loopback; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } gai_afdl [] = { | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #define N_INET6 0
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {PF_INET6, sizeof(struct in6_addr), | 
					
						
							|  |  |  |      sizeof(struct sockaddr_in6), | 
					
						
							|  |  |  |      offsetof(struct sockaddr_in6, sin6_addr), | 
					
						
							|  |  |  |      in6_addrany, in6_loopback}, | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #define N_INET  1
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define N_INET  0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {PF_INET, sizeof(struct in_addr), | 
					
						
							|  |  |  |      sizeof(struct sockaddr_in), | 
					
						
							|  |  |  |      offsetof(struct sockaddr_in, sin_addr), | 
					
						
							|  |  |  |      in_addrany, in_loopback}, | 
					
						
							|  |  |  |     {0, 0, 0, 0, NULL, NULL}, | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | #define PTON_MAX        16
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | #define PTON_MAX        4
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-07-19 17:37:46 +00:00
										 |  |  | #ifndef IN_MULTICAST
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | #define IN_MULTICAST(i)     (((i) & 0xf0000000U) == 0xe0000000U)
 | 
					
						
							| 
									
										
										
										
											2001-07-19 17:37:46 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef IN_EXPERIMENTAL
 | 
					
						
							|  |  |  | #define IN_EXPERIMENTAL(i)  (((i) & 0xe0000000U) == 0xe0000000U)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef IN_LOOPBACKNET
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | #define IN_LOOPBACKNET      127
 | 
					
						
							| 
									
										
										
										
											2001-07-19 17:37:46 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 19:06:23 +00:00
										 |  |  | static int get_name(const char *, struct gai_afd *, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                           struct addrinfo **, char *, struct addrinfo *, | 
					
						
							|  |  |  |                           int); | 
					
						
							| 
									
										
										
										
											2007-02-27 19:06:23 +00:00
										 |  |  | static int get_addr(const char *, int, struct addrinfo **, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                         struct addrinfo *, int); | 
					
						
							| 
									
										
										
										
											2007-02-27 19:06:23 +00:00
										 |  |  | static int str_isnumber(const char *); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 19:53:18 +02:00
										 |  |  | static const char * const ai_errlist[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     "success.", | 
					
						
							|  |  |  |     "address family for hostname not supported.",       /* EAI_ADDRFAMILY */ | 
					
						
							|  |  |  |     "temporary failure in name resolution.",            /* EAI_AGAIN      */ | 
					
						
							|  |  |  |     "invalid value for ai_flags.",                      /* EAI_BADFLAGS   */ | 
					
						
							|  |  |  |     "non-recoverable failure in name resolution.",      /* EAI_FAIL       */ | 
					
						
							|  |  |  |     "ai_family not supported.",                         /* EAI_FAMILY     */ | 
					
						
							|  |  |  |     "memory allocation failure.",                       /* EAI_MEMORY     */ | 
					
						
							|  |  |  |     "no address associated with hostname.",             /* EAI_NODATA     */ | 
					
						
							|  |  |  |     "hostname nor servname provided, or not known.",/* EAI_NONAME     */ | 
					
						
							|  |  |  |     "servname not supported for ai_socktype.",          /* EAI_SERVICE    */ | 
					
						
							|  |  |  |     "ai_socktype not supported.",                       /* EAI_SOCKTYPE   */ | 
					
						
							|  |  |  |     "system error returned in errno.",                  /* EAI_SYSTEM     */ | 
					
						
							|  |  |  |     "invalid value for hints.",                         /* EAI_BADHINTS   */ | 
					
						
							|  |  |  |     "resolved protocol is unknown.",                    /* EAI_PROTOCOL   */ | 
					
						
							|  |  |  |     "unknown error.",                                   /* EAI_MAX        */ | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_CANONNAME(ai, str) \
 | 
					
						
							|  |  |  | if (pai->ai_flags & AI_CANONNAME) {\ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\ | 
					
						
							|  |  |  |         strcpy((ai)->ai_canonname, (str));\ | 
					
						
							|  |  |  |     } else {\ | 
					
						
							|  |  |  |         error = EAI_MEMORY;\ | 
					
						
							|  |  |  |         goto free;\ | 
					
						
							|  |  |  |     }\ | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_SOCKADDR_SA_LEN
 | 
					
						
							|  |  |  | #define GET_AI(ai, gai_afd, addr, port) {\
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     char *p;\ | 
					
						
							|  |  |  |     if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ | 
					
						
							|  |  |  |                                           ((gai_afd)->a_socklen)))\ | 
					
						
							|  |  |  |         == NULL) goto free;\ | 
					
						
							|  |  |  |     memcpy(ai, pai, sizeof(struct addrinfo));\ | 
					
						
							|  |  |  |     (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ | 
					
						
							|  |  |  |     memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ | 
					
						
							|  |  |  |     (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\ | 
					
						
							|  |  |  |     (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ | 
					
						
							|  |  |  |     ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ | 
					
						
							|  |  |  |     p = (char *)((ai)->ai_addr);\ | 
					
						
							|  |  |  |     memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define GET_AI(ai, gai_afd, addr, port) {\
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     char *p;\ | 
					
						
							|  |  |  |     if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ | 
					
						
							|  |  |  |                                           ((gai_afd)->a_socklen)))\ | 
					
						
							|  |  |  |         == NULL) goto free;\ | 
					
						
							|  |  |  |     memcpy(ai, pai, sizeof(struct addrinfo));\ | 
					
						
							|  |  |  |     (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ | 
					
						
							|  |  |  |     memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ | 
					
						
							|  |  |  |     (ai)->ai_addrlen = (gai_afd)->a_socklen;\ | 
					
						
							|  |  |  |     (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ | 
					
						
							|  |  |  |     ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ | 
					
						
							|  |  |  |     p = (char *)((ai)->ai_addr);\ | 
					
						
							|  |  |  |     memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ERR(err) { error = (err); goto bad; }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | const char * | 
					
						
							| 
									
										
										
										
											2002-07-17 14:33:34 +00:00
										 |  |  | gai_strerror(int ecode) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (ecode < 0 || ecode > EAI_MAX) | 
					
						
							|  |  |  |         ecode = EAI_MAX; | 
					
						
							|  |  |  |     return ai_errlist[ecode]; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2002-07-17 14:33:34 +00:00
										 |  |  | freeaddrinfo(struct addrinfo *ai) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     struct addrinfo *next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         next = ai->ai_next; | 
					
						
							|  |  |  |         if (ai->ai_canonname) | 
					
						
							|  |  |  |             free(ai->ai_canonname); | 
					
						
							|  |  |  |         /* no need to free(ai->ai_addr) */ | 
					
						
							|  |  |  |         free(ai); | 
					
						
							|  |  |  |     } while ((ai = next) != NULL); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-07-17 14:33:34 +00:00
										 |  |  | str_isnumber(const char *p) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     unsigned char *q = (unsigned char *)p; | 
					
						
							|  |  |  |     while (*q) { | 
					
						
							| 
									
										
										
										
											2023-09-01 18:36:53 +02:00
										 |  |  |         if (!Py_ISDIGIT(*q)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return NO; | 
					
						
							| 
									
										
										
										
											2023-09-01 18:36:53 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         q++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return YES; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2001-09-07 16:10:00 +00:00
										 |  |  | getaddrinfo(const char*hostname, const char*servname, | 
					
						
							|  |  |  |             const struct addrinfo *hints, struct addrinfo **res) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     struct addrinfo sentinel; | 
					
						
							|  |  |  |     struct addrinfo *top = NULL; | 
					
						
							|  |  |  |     struct addrinfo *cur; | 
					
						
							|  |  |  |     int i, error = 0; | 
					
						
							|  |  |  |     char pton[PTON_MAX]; | 
					
						
							|  |  |  |     struct addrinfo ai; | 
					
						
							|  |  |  |     struct addrinfo *pai; | 
					
						
							|  |  |  |     u_short port; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef FAITH
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     static int firsttime = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (firsttime) { | 
					
						
							|  |  |  |         /* translator hack */ | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-12-12 13:55:04 +02:00
										 |  |  |             const char *q = getenv("GAI"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) | 
					
						
							|  |  |  |                 translate = YES; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         firsttime = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* initialize file static vars */ | 
					
						
							|  |  |  |     sentinel.ai_next = NULL; | 
					
						
							|  |  |  |     cur = &sentinel; | 
					
						
							|  |  |  |     pai = &ai; | 
					
						
							|  |  |  |     pai->ai_flags = 0; | 
					
						
							|  |  |  |     pai->ai_family = PF_UNSPEC; | 
					
						
							|  |  |  |     pai->ai_socktype = GAI_ANY; | 
					
						
							|  |  |  |     pai->ai_protocol = GAI_ANY; | 
					
						
							|  |  |  |     pai->ai_addrlen = 0; | 
					
						
							|  |  |  |     pai->ai_canonname = NULL; | 
					
						
							|  |  |  |     pai->ai_addr = NULL; | 
					
						
							|  |  |  |     pai->ai_next = NULL; | 
					
						
							|  |  |  |     port = GAI_ANY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hostname == NULL && servname == NULL) | 
					
						
							|  |  |  |         return EAI_NONAME; | 
					
						
							|  |  |  |     if (hints) { | 
					
						
							|  |  |  |         /* error check for hints */ | 
					
						
							|  |  |  |         if (hints->ai_addrlen || hints->ai_canonname || | 
					
						
							|  |  |  |             hints->ai_addr || hints->ai_next) | 
					
						
							|  |  |  |             ERR(EAI_BADHINTS); /* xxx */ | 
					
						
							|  |  |  |         if (hints->ai_flags & ~AI_MASK) | 
					
						
							|  |  |  |             ERR(EAI_BADFLAGS); | 
					
						
							|  |  |  |         switch (hints->ai_family) { | 
					
						
							|  |  |  |         case PF_UNSPEC: | 
					
						
							|  |  |  |         case PF_INET: | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         case PF_INET6: | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             ERR(EAI_FAMILY); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         memcpy(pai, hints, sizeof(*pai)); | 
					
						
							|  |  |  |         switch (pai->ai_socktype) { | 
					
						
							|  |  |  |         case GAI_ANY: | 
					
						
							|  |  |  |             switch (pai->ai_protocol) { | 
					
						
							|  |  |  |             case GAI_ANY: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case IPPROTO_UDP: | 
					
						
							|  |  |  |                 pai->ai_socktype = SOCK_DGRAM; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case IPPROTO_TCP: | 
					
						
							|  |  |  |                 pai->ai_socktype = SOCK_STREAM; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 pai->ai_socktype = SOCK_RAW; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case SOCK_RAW: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case SOCK_DGRAM: | 
					
						
							|  |  |  |             if (pai->ai_protocol != IPPROTO_UDP && | 
					
						
							|  |  |  |                 pai->ai_protocol != GAI_ANY) | 
					
						
							|  |  |  |                 ERR(EAI_BADHINTS);                      /*xxx*/ | 
					
						
							|  |  |  |             pai->ai_protocol = IPPROTO_UDP; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case SOCK_STREAM: | 
					
						
							|  |  |  |             if (pai->ai_protocol != IPPROTO_TCP && | 
					
						
							|  |  |  |                 pai->ai_protocol != GAI_ANY) | 
					
						
							|  |  |  |                 ERR(EAI_BADHINTS);                      /*xxx*/ | 
					
						
							|  |  |  |             pai->ai_protocol = IPPROTO_TCP; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             ERR(EAI_SOCKTYPE); | 
					
						
							|  |  |  |             /* unreachable */ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * service port | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (servname) { | 
					
						
							|  |  |  |         if (str_isnumber(servname)) { | 
					
						
							|  |  |  |             if (pai->ai_socktype == GAI_ANY) { | 
					
						
							|  |  |  |                 /* caller accept *GAI_ANY* socktype */ | 
					
						
							|  |  |  |                 pai->ai_socktype = SOCK_DGRAM; | 
					
						
							|  |  |  |                 pai->ai_protocol = IPPROTO_UDP; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-02-14 02:37:34 +01:00
										 |  |  |             long maybe_port = strtol(servname, NULL, 10); | 
					
						
							|  |  |  |             if (maybe_port < 0 || maybe_port > 0xffff) { | 
					
						
							|  |  |  |                 ERR(EAI_SERVICE); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             port = htons((u_short)maybe_port); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             struct servent *sp; | 
					
						
							| 
									
										
										
										
											2017-11-11 13:06:26 +02:00
										 |  |  |             const char *proto; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-18 14:31:13 +01:00
										 |  |  |             if (pai->ai_flags & AI_NUMERICSERV) { | 
					
						
							| 
									
										
										
										
											2025-03-18 11:26:51 +01:00
										 |  |  |                 ERR(EAI_NONAME); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             proto = NULL; | 
					
						
							|  |  |  |             switch (pai->ai_socktype) { | 
					
						
							|  |  |  |             case GAI_ANY: | 
					
						
							|  |  |  |                 proto = NULL; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case SOCK_DGRAM: | 
					
						
							|  |  |  |                 proto = "udp"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case SOCK_STREAM: | 
					
						
							|  |  |  |                 proto = "tcp"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 fprintf(stderr, "panic!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if ((sp = getservbyname(servname, proto)) == NULL) | 
					
						
							|  |  |  |                 ERR(EAI_SERVICE); | 
					
						
							|  |  |  |             port = sp->s_port; | 
					
						
							|  |  |  |             if (pai->ai_socktype == GAI_ANY) { | 
					
						
							|  |  |  |                 if (strcmp(sp->s_proto, "udp") == 0) { | 
					
						
							|  |  |  |                     pai->ai_socktype = SOCK_DGRAM; | 
					
						
							|  |  |  |                     pai->ai_protocol = IPPROTO_UDP; | 
					
						
							|  |  |  |                 } else if (strcmp(sp->s_proto, "tcp") == 0) { | 
					
						
							|  |  |  |                     pai->ai_socktype = SOCK_STREAM; | 
					
						
							|  |  |  |                     pai->ai_protocol = IPPROTO_TCP; | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                     ERR(EAI_PROTOCOL);                          /*xxx*/ | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * hostname == NULL. | 
					
						
							|  |  |  |      * passive socket -> anyaddr (0.0.0.0 or ::) | 
					
						
							|  |  |  |      * non-passive socket -> localhost (127.0.0.1 or ::1) | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (hostname == NULL) { | 
					
						
							|  |  |  |         struct gai_afd *gai_afd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) { | 
					
						
							|  |  |  |             if (!(pai->ai_family == PF_UNSPEC | 
					
						
							|  |  |  |                || pai->ai_family == gai_afd->a_af)) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (pai->ai_flags & AI_PASSIVE) { | 
					
						
							|  |  |  |                 GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port); | 
					
						
							|  |  |  |                 /* xxx meaningless?
 | 
					
						
							|  |  |  |                  * GET_CANONNAME(cur->ai_next, "anyaddr"); | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback, | 
					
						
							|  |  |  |                     port); | 
					
						
							|  |  |  |                 /* xxx meaningless?
 | 
					
						
							|  |  |  |                  * GET_CANONNAME(cur->ai_next, "localhost"); | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             cur = cur->ai_next; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         top = sentinel.ai_next; | 
					
						
							|  |  |  |         if (top) | 
					
						
							|  |  |  |             goto good; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ERR(EAI_FAMILY); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* hostname as numeric name */ | 
					
						
							|  |  |  |     for (i = 0; gai_afdl[i].a_af; i++) { | 
					
						
							|  |  |  |         if (inet_pton(gai_afdl[i].a_af, hostname, pton)) { | 
					
						
							|  |  |  |             u_long v4a; | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             u_char pfx; | 
					
						
							| 
									
										
										
										
											2001-07-21 09:42:15 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             switch (gai_afdl[i].a_af) { | 
					
						
							|  |  |  |             case AF_INET: | 
					
						
							|  |  |  |                 v4a = ((struct in_addr *)pton)->s_addr; | 
					
						
							|  |  |  |                 v4a = ntohl(v4a); | 
					
						
							|  |  |  |                 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) | 
					
						
							|  |  |  |                     pai->ai_flags &= ~AI_CANONNAME; | 
					
						
							|  |  |  |                 v4a >>= IN_CLASSA_NSHIFT; | 
					
						
							|  |  |  |                 if (v4a == 0 || v4a == IN_LOOPBACKNET) | 
					
						
							|  |  |  |                     pai->ai_flags &= ~AI_CANONNAME; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             case AF_INET6: | 
					
						
							| 
									
										
										
										
											2012-08-02 20:37:12 +02:00
										 |  |  |                 pfx = ((struct in6_addr *)pton)->s6_addr[0]; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                 if (pfx == 0 || pfx == 0xfe || pfx == 0xff) | 
					
						
							|  |  |  |                     pai->ai_flags &= ~AI_CANONNAME; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (pai->ai_family == gai_afdl[i].a_af || | 
					
						
							|  |  |  |                 pai->ai_family == PF_UNSPEC) { | 
					
						
							|  |  |  |                 if (! (pai->ai_flags & AI_CANONNAME)) { | 
					
						
							|  |  |  |                     GET_AI(top, &gai_afdl[i], pton, port); | 
					
						
							|  |  |  |                     goto good; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * if AI_CANONNAME and if reverse lookup | 
					
						
							|  |  |  |                  * fail, return ai anyway to pacify | 
					
						
							|  |  |  |                  * calling application. | 
					
						
							|  |  |  |                  * | 
					
						
							|  |  |  |                  * XXX getaddrinfo() is a name->address | 
					
						
							|  |  |  |                  * translation function, and it looks strange | 
					
						
							|  |  |  |                  * that we do addr->name translation here. | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |                 get_name(pton, &gai_afdl[i], &top, pton, pai, port); | 
					
						
							|  |  |  |                 goto good; | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 ERR(EAI_FAMILY);                        /*xxx*/ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pai->ai_flags & AI_NUMERICHOST) | 
					
						
							|  |  |  |         ERR(EAI_NONAME); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* hostname as alphabetical name */ | 
					
						
							|  |  |  |     error = get_addr(hostname, pai->ai_family, &top, pai, port); | 
					
						
							|  |  |  |     if (error == 0) { | 
					
						
							|  |  |  |         if (top) { | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  good: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             *res = top; | 
					
						
							|  |  |  |             return SUCCESS; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             error = EAI_FAIL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  free: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (top) | 
					
						
							|  |  |  |         freeaddrinfo(top); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  bad: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     *res = NULL; | 
					
						
							|  |  |  |     return error; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2025-03-11 13:06:36 +01:00
										 |  |  | get_name(const char *addr, struct gai_afd *gai_afd, struct addrinfo **res, | 
					
						
							|  |  |  |          char *numaddr, struct addrinfo *pai, int port0) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     u_short port = port0 & 0xffff; | 
					
						
							|  |  |  |     struct hostent *hp; | 
					
						
							|  |  |  |     struct addrinfo *cur; | 
					
						
							|  |  |  |     int error = 0; | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int h_error; | 
					
						
							| 
									
										
										
										
											2001-07-21 09:42:15 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { | 
					
						
							|  |  |  |         GET_AI(cur, gai_afd, hp->h_addr_list[0], port); | 
					
						
							|  |  |  |         GET_CANONNAME(cur, hp->h_name); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         GET_AI(cur, gai_afd, numaddr, port); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (hp) | 
					
						
							|  |  |  |         freehostent(hp); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     *res = cur; | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  free: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (cur) | 
					
						
							|  |  |  |         freeaddrinfo(cur); | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (hp) | 
					
						
							|  |  |  |         freehostent(hp); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |  /* bad: */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     *res = NULL; | 
					
						
							|  |  |  |     return error; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2025-03-11 13:06:36 +01:00
										 |  |  | get_addr(const char *hostname, int af, struct addrinfo **res, | 
					
						
							|  |  |  |          struct addrinfo *pai, int port0) | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     u_short port = port0 & 0xffff; | 
					
						
							|  |  |  |     struct addrinfo sentinel; | 
					
						
							|  |  |  |     struct hostent *hp; | 
					
						
							|  |  |  |     struct addrinfo *top, *cur; | 
					
						
							|  |  |  |     struct gai_afd *gai_afd; | 
					
						
							|  |  |  |     int i, error = 0, h_error; | 
					
						
							|  |  |  |     char *ap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     top = NULL; | 
					
						
							|  |  |  |     sentinel.ai_next = NULL; | 
					
						
							|  |  |  |     cur = &sentinel; | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (af == AF_UNSPEC) { | 
					
						
							|  |  |  |         hp = getipnodebyname(hostname, AF_INET6, | 
					
						
							|  |  |  |                         AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     hp = gethostbyname(hostname); | 
					
						
							|  |  |  |     h_error = h_errno; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (hp == NULL) { | 
					
						
							|  |  |  |         switch (h_error) { | 
					
						
							|  |  |  |         case HOST_NOT_FOUND: | 
					
						
							|  |  |  |         case NO_DATA: | 
					
						
							|  |  |  |             error = EAI_NODATA; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case TRY_AGAIN: | 
					
						
							|  |  |  |             error = EAI_AGAIN; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case NO_RECOVERY: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             error = EAI_FAIL; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         goto free; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || | 
					
						
							|  |  |  |         (hp->h_addr_list[0] == NULL)) { | 
					
						
							|  |  |  |         error = EAI_FAIL; | 
					
						
							|  |  |  |         goto free; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { | 
					
						
							|  |  |  |         switch (af) { | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         case AF_INET6: | 
					
						
							|  |  |  |             gai_afd = &gai_afdl[N_INET6]; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifndef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         default:                /* AF_UNSPEC */ | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         case AF_INET: | 
					
						
							|  |  |  |             gai_afd = &gai_afdl[N_INET]; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         default:                /* AF_UNSPEC */ | 
					
						
							|  |  |  |             if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { | 
					
						
							|  |  |  |                 ap += sizeof(struct in6_addr) - | 
					
						
							|  |  |  |                     sizeof(struct in_addr); | 
					
						
							|  |  |  |                 gai_afd = &gai_afdl[N_INET]; | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 gai_afd = &gai_afdl[N_INET6]; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #ifdef FAITH
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (translate && gai_afd->a_af == AF_INET) { | 
					
						
							|  |  |  |             struct in6_addr *in6; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port); | 
					
						
							|  |  |  |             in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; | 
					
						
							|  |  |  |             memcpy(&in6->s6_addr32[0], &faith_prefix, | 
					
						
							|  |  |  |                 sizeof(struct in6_addr) - sizeof(struct in_addr)); | 
					
						
							|  |  |  |             memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr)); | 
					
						
							|  |  |  |         } else | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif /* FAITH */
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         GET_AI(cur->ai_next, gai_afd, ap, port); | 
					
						
							|  |  |  |         if (cur == &sentinel) { | 
					
						
							|  |  |  |             top = cur->ai_next; | 
					
						
							|  |  |  |             GET_CANONNAME(top, hp->h_name); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         cur = cur->ai_next; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     freehostent(hp); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     *res = top; | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  |  free: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (top) | 
					
						
							|  |  |  |         freeaddrinfo(top); | 
					
						
							| 
									
										
										
										
											2001-12-02 10:15:37 +00:00
										 |  |  | #ifdef ENABLE_IPV6
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (hp) | 
					
						
							|  |  |  |         freehostent(hp); | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-11-07 08:31:03 +00:00
										 |  |  | /* bad: */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     *res = NULL; | 
					
						
							|  |  |  |     return error; | 
					
						
							| 
									
										
										
										
											2001-06-23 16:30:13 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-27 08:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif // HAVE_NETDB_H
 |