]>
git.ipfire.org Git - thirdparty/squid.git/blob - compat/getaddrinfo.cc
b74434188e8c32a4b29fc71f6e04174b75c35fcf
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * Shamelessly duplicated from the fetchmail public sources
11 * for use by the Squid Project under GNU Public License.
13 * Update/Maintenance History:
15 * 15-Aug-2007 : Copied from fetchmail 6.3.8
16 * - added protection around library headers
18 * 16-Aug-2007 : Altered configure checks
19 * Un-hacked slightly to use system gethostbyname()
21 * 06-Oct-2007 : Various fixes to allow the build on MinGW
23 * 13-Jan-2015 : Various fixed for C++ and MinGW native build
25 * Original License and code follows.
30 * This file is part of libESMTP, a library for submission of RFC 2822
31 * formatted electronic mail messages using the SMTP protocol described
34 * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
36 * This library is free software; you can redistribute it and/or
37 * modify it under the terms of the GNU Lesser General Public
38 * License as published by the Free Software Foundation; either
39 * version 2.1 of the License, or (at your option) any later version.
41 * This library is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * Lesser General Public License for more details.
46 * You should have received a copy of the GNU Lesser General Public
47 * License along with this library; if not, write to the Free Software
48 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 /* An emulation of the RFC 2553 / Posix getaddrinfo resolver interface.
54 #if !HAVE_DECL_GETADDRINFO
56 /* Need to turn off Posix features in glibc to build this */
57 #undef _POSIX_C_SOURCE
70 #include <sys/socket.h>
73 #include <netinet/in.h>
76 #include <arpa/inet.h>
82 static struct addrinfo
*
83 dup_addrinfo (struct addrinfo
*info
, void *addr
, size_t addrlen
) {
86 ret
= (struct addrinfo
*)malloc(sizeof (struct addrinfo
));
89 memcpy (ret
, info
, sizeof (struct addrinfo
));
90 ret
->ai_addr
= (struct sockaddr
*)malloc(addrlen
);
95 memcpy (ret
->ai_addr
, addr
, addrlen
);
96 ret
->ai_addrlen
= addrlen
;
101 xgetaddrinfo (const char *nodename
, const char *servname
,
102 const struct addrinfo
*hints
, struct addrinfo
**res
)
105 struct servent
*servent
;
106 const char *socktype
;
108 struct addrinfo hint
, result
;
109 struct addrinfo
*ai
, *sai
, *eai
;
112 if (!servname
&& !nodename
)
115 memset (&result
, 0, sizeof result
);
117 /* default for hints */
119 memset (&hint
, 0, sizeof hint
);
120 hint
.ai_family
= PF_UNSPEC
;
127 /* check for tcp or udp sockets only */
128 if (hints
->ai_socktype
== SOCK_STREAM
)
130 else if (hints
->ai_socktype
== SOCK_DGRAM
)
134 result
.ai_socktype
= hints
->ai_socktype
;
136 /* Note: maintain port in host byte order to make debugging easier */
137 if (isdigit (*servname
))
138 port
= strtol (servname
, nullptr, 10);
139 else if ((servent
= getservbyname (servname
, socktype
)))
140 port
= ntohs (servent
->s_port
);
145 /* if !nodename, refer to the local host for a client or any
148 struct sockaddr_in sin
;
150 /* check protocol family is PF_UNSPEC or PF_INET - could try harder
151 for IPv6 but that's more code than I'm prepared to write */
152 if (hints
->ai_family
== PF_UNSPEC
|| hints
->ai_family
== PF_INET
)
153 result
.ai_family
= AF_INET
;
157 sin
.sin_family
= result
.ai_family
;
158 sin
.sin_port
= htons (port
);
159 if (hints
->ai_flags
& AI_PASSIVE
)
160 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
162 sin
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
163 /* Duplicate result and addr and return */
164 *res
= dup_addrinfo (&result
, &sin
, sizeof sin
);
165 return (!*res
) ? EAI_MEMORY
: 0;
168 /* If AI_NUMERIC is specified, use inet_pton to translate numbers and
170 if (hints
->ai_flags
& AI_NUMERICHOST
) {
171 struct sockaddr_in sin
;
173 /* check protocol family is PF_UNSPEC or PF_INET */
174 if (hints
->ai_family
== PF_UNSPEC
|| hints
->ai_family
== PF_INET
)
175 result
.ai_family
= AF_INET
;
179 sin
.sin_family
= result
.ai_family
;
180 sin
.sin_port
= htons (port
);
181 if (inet_pton(result
.ai_family
, nodename
, &sin
.sin_addr
) != 1)
183 sin
.sin_addr
.s_addr
= inet_addr (nodename
);
184 /* Duplicate result and addr and return */
185 *res
= dup_addrinfo (&result
, &sin
, sizeof sin
);
186 return (!*res
) ? EAI_MEMORY
: 0;
193 hp
= gethostbyname(nodename
);
205 #if defined(NO_ADDRESS) && NO_ADDRESS != NO_DATA
219 /* Check that the address family is acceptable.
221 switch (hp
->h_addrtype
) {
223 if (!(hints
->ai_family
== PF_UNSPEC
|| hints
->ai_family
== PF_INET
))
227 if (!(hints
->ai_family
== PF_UNSPEC
|| hints
->ai_family
== PF_INET6
))
234 /* For each element pointed to by hp, create an element in the
235 result linked list. */
237 for (addrs
= hp
->h_addr_list
; *addrs
; addrs
++) {
241 if (hp
->h_length
< 1)
243 sa
.sa_family
= hp
->h_addrtype
;
244 switch (hp
->h_addrtype
) {
246 ((struct sockaddr_in
*) &sa
)->sin_port
= htons (port
);
247 memcpy (&((struct sockaddr_in
*) &sa
)->sin_addr
,
248 *addrs
, hp
->h_length
);
249 addrlen
= sizeof (struct sockaddr_in
);
253 ((struct sockaddr_in6
*) &sa
)->sin6_len
= hp
->h_length
;
255 ((struct sockaddr_in6
*) &sa
)->sin6_port
= htons (port
);
256 memcpy (&((struct sockaddr_in6
*) &sa
)->sin6_addr
,
257 *addrs
, hp
->h_length
);
258 addrlen
= sizeof (struct sockaddr_in6
);
264 result
.ai_family
= hp
->h_addrtype
;
265 ai
= dup_addrinfo (&result
, &sa
, addrlen
);
281 if (hints
->ai_flags
& AI_CANONNAME
) {
282 sai
->ai_canonname
= (char *)malloc(strlen(hp
->h_name
) + 1);
283 if (!sai
->ai_canonname
) {
287 strcpy (sai
->ai_canonname
, hp
->h_name
);
295 xfreeaddrinfo (struct addrinfo
*ai
)
297 struct addrinfo
*next
;
301 if (ai
->ai_canonname
)
302 free (ai
->ai_canonname
);
311 xgai_strerror (int ecode
)
313 static const char *eai_descr
[] = {
315 "address family for nodename not supported", /* EAI_ADDRFAMILY */
316 "temporary failure in name resolution", /* EAI_AGAIN */
317 "invalid value for ai_flags", /* EAI_BADFLAGS */
318 "non-recoverable failure in name resolution", /* EAI_FAIL */
319 "ai_family not supported", /* EAI_FAMILY */
320 "memory allocation failure", /* EAI_MEMORY */
321 "no address associated with nodename", /* EAI_NODATA */
322 "nodename nor servname provided, or not known", /* EAI_NONAME */
323 "servname not supported for ai_socktype", /* EAI_SERVICE */
324 "ai_socktype not supported", /* EAI_SOCKTYPE */
325 "system error returned in errno", /* EAI_SYSTEM */
326 "argument buffer overflow", /* EAI_OVERFLOW */
329 if (ecode
< 0 || ecode
> (int) (sizeof eai_descr
/ sizeof eai_descr
[0]))
330 return "unknown error";
331 return eai_descr
[ecode
];
334 #endif /* HAVE_DECL_GETADDRINFO */