summaryrefslogtreecommitdiffstats
path: root/gl/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r--gl/getaddrinfo.c178
1 files changed, 120 insertions, 58 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c
index 58d2811..0c42d1b 100644
--- a/gl/getaddrinfo.c
+++ b/gl/getaddrinfo.c
@@ -1,19 +1,19 @@
1/* Get address information (partial implementation). 1/* Get address information (partial implementation).
2 Copyright (C) 1997, 2001-2002, 2004-2013 Free Software Foundation, Inc. 2 Copyright (C) 1997, 2001-2002, 2004-2021 Free Software Foundation, Inc.
3 Contributed by Simon Josefsson <simon@josefsson.org>. 3 Contributed by Simon Josefsson <simon@josefsson.org>.
4 4
5 This program is free software; you can redistribute it and/or modify 5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU Lesser General Public License as
7 the Free Software Foundation; either version 3, or (at your option) 7 published by the Free Software Foundation; either version 2.1 of the
8 any later version. 8 License, or (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 13 GNU Lesser General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */ 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 17
18/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc 18/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
19 optimizes away the sa == NULL test below. */ 19 optimizes away the sa == NULL test below. */
@@ -54,14 +54,48 @@
54# define PF_UNSPEC 0 54# define PF_UNSPEC 0
55#endif 55#endif
56 56
57#if defined _WIN32 || defined __WIN32__ 57#if HAVE_GETADDRINFO
58# define WINDOWS_NATIVE 58
59#endif 59/* Override with cdecl calling convention. */
60
61int
62getaddrinfo (const char *restrict nodename,
63 const char *restrict servname,
64 const struct addrinfo *restrict hints,
65 struct addrinfo **restrict res)
66# undef getaddrinfo
67{
68 return getaddrinfo (nodename, servname, hints, res);
69}
70
71void
72freeaddrinfo (struct addrinfo *ai)
73# undef freeaddrinfo
74{
75 freeaddrinfo (ai);
76}
77
78#else
79
80# if defined _WIN32 && !defined __CYGWIN__
81# define WINDOWS_NATIVE
82# endif
60 83
61/* gl_sockets_startup */ 84/* gl_sockets_startup */
62#include "sockets.h" 85# include "sockets.h"
86
87# ifdef WINDOWS_NATIVE
88
89/* Don't assume that UNICODE is not defined. */
90# undef GetModuleHandle
91# define GetModuleHandle GetModuleHandleA
92
93# if !(_WIN32_WINNT >= _WIN32_WINNT_WINXP)
94
95/* Avoid warnings from gcc -Wcast-function-type. */
96# define GetProcAddress \
97 (void *) GetProcAddress
63 98
64#ifdef WINDOWS_NATIVE
65typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, 99typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
66 const struct addrinfo*, 100 const struct addrinfo*,
67 struct addrinfo**); 101 struct addrinfo**);
@@ -107,20 +141,43 @@ use_win32_p (void)
107 141
108 return 1; 142 return 1;
109} 143}
110#endif 144
145# else
146
147static int
148use_win32_p (void)
149{
150 static int done = 0;
151
152 if (!done)
153 {
154 done = 1;
155
156 gl_sockets_startup (SOCKETS_1_1);
157 }
158
159 return 1;
160}
161
162# define getaddrinfo_ptr getaddrinfo
163# define freeaddrinfo_ptr freeaddrinfo
164# define getnameinfo_ptr getnameinfo
165
166# endif
167# endif
111 168
112static bool 169static bool
113validate_family (int family) 170validate_family (int family)
114{ 171{
115 /* FIXME: Support more families. */ 172 /* FIXME: Support more families. */
116#if HAVE_IPV4 173# if HAVE_IPV4
117 if (family == PF_INET) 174 if (family == PF_INET)
118 return true; 175 return true;
119#endif 176# endif
120#if HAVE_IPV6 177# if HAVE_IPV6
121 if (family == PF_INET6) 178 if (family == PF_INET6)
122 return true; 179 return true;
123#endif 180# endif
124 if (family == PF_UNSPEC) 181 if (family == PF_UNSPEC)
125 return true; 182 return true;
126 return false; 183 return false;
@@ -133,29 +190,30 @@ getaddrinfo (const char *restrict nodename,
133 const char *restrict servname, 190 const char *restrict servname,
134 const struct addrinfo *restrict hints, 191 const struct addrinfo *restrict hints,
135 struct addrinfo **restrict res) 192 struct addrinfo **restrict res)
193#undef getaddrinfo
136{ 194{
137 struct addrinfo *tmp; 195 struct addrinfo *tmp;
138 int port = 0; 196 int port = 0;
139 struct hostent *he; 197 struct hostent *he;
140 void *storage; 198 void *storage;
141 size_t size; 199 size_t size;
142#if HAVE_IPV6 200# if HAVE_IPV6
143 struct v6_pair { 201 struct v6_pair {
144 struct addrinfo addrinfo; 202 struct addrinfo addrinfo;
145 struct sockaddr_in6 sockaddr_in6; 203 struct sockaddr_in6 sockaddr_in6;
146 }; 204 };
147#endif 205# endif
148#if HAVE_IPV4 206# if HAVE_IPV4
149 struct v4_pair { 207 struct v4_pair {
150 struct addrinfo addrinfo; 208 struct addrinfo addrinfo;
151 struct sockaddr_in sockaddr_in; 209 struct sockaddr_in sockaddr_in;
152 }; 210 };
153#endif 211# endif
154 212
155#ifdef WINDOWS_NATIVE 213# ifdef WINDOWS_NATIVE
156 if (use_win32_p ()) 214 if (use_win32_p ())
157 return getaddrinfo_ptr (nodename, servname, hints, res); 215 return getaddrinfo_ptr (nodename, servname, hints, res);
158#endif 216# endif
159 217
160 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE))) 218 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
161 /* FIXME: Support more flags. */ 219 /* FIXME: Support more flags. */
@@ -174,11 +232,11 @@ getaddrinfo (const char *restrict nodename,
174 if (!(hints->ai_flags & AI_PASSIVE)) 232 if (!(hints->ai_flags & AI_PASSIVE))
175 return EAI_NONAME; 233 return EAI_NONAME;
176 234
177#ifdef HAVE_IPV6 235# ifdef HAVE_IPV6
178 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; 236 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
179#else 237# else
180 nodename = "0.0.0.0"; 238 nodename = "0.0.0.0";
181#endif 239# endif
182 } 240 }
183 241
184 if (servname) 242 if (servname)
@@ -212,17 +270,17 @@ getaddrinfo (const char *restrict nodename,
212 270
213 switch (he->h_addrtype) 271 switch (he->h_addrtype)
214 { 272 {
215#if HAVE_IPV6 273# if HAVE_IPV6
216 case PF_INET6: 274 case PF_INET6:
217 size = sizeof (struct v6_pair); 275 size = sizeof (struct v6_pair);
218 break; 276 break;
219#endif 277# endif
220 278
221#if HAVE_IPV4 279# if HAVE_IPV4
222 case PF_INET: 280 case PF_INET:
223 size = sizeof (struct v4_pair); 281 size = sizeof (struct v4_pair);
224 break; 282 break;
225#endif 283# endif
226 284
227 default: 285 default:
228 return EAI_NODATA; 286 return EAI_NODATA;
@@ -234,7 +292,7 @@ getaddrinfo (const char *restrict nodename,
234 292
235 switch (he->h_addrtype) 293 switch (he->h_addrtype)
236 { 294 {
237#if HAVE_IPV6 295# if HAVE_IPV6
238 case PF_INET6: 296 case PF_INET6:
239 { 297 {
240 struct v6_pair *p = storage; 298 struct v6_pair *p = storage;
@@ -256,9 +314,9 @@ getaddrinfo (const char *restrict nodename,
256 tmp->ai_addrlen = sizeof *sinp; 314 tmp->ai_addrlen = sizeof *sinp;
257 } 315 }
258 break; 316 break;
259#endif 317# endif
260 318
261#if HAVE_IPV4 319# if HAVE_IPV4
262 case PF_INET: 320 case PF_INET:
263 { 321 {
264 struct v4_pair *p = storage; 322 struct v4_pair *p = storage;
@@ -280,7 +338,7 @@ getaddrinfo (const char *restrict nodename,
280 tmp->ai_addrlen = sizeof *sinp; 338 tmp->ai_addrlen = sizeof *sinp;
281 } 339 }
282 break; 340 break;
283#endif 341# endif
284 342
285 default: 343 default:
286 free (storage); 344 free (storage);
@@ -308,21 +366,21 @@ getaddrinfo (const char *restrict nodename,
308 tmp->ai_addr->sa_family = he->h_addrtype; 366 tmp->ai_addr->sa_family = he->h_addrtype;
309 tmp->ai_family = he->h_addrtype; 367 tmp->ai_family = he->h_addrtype;
310 368
311#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 369# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
312 switch (he->h_addrtype) 370 switch (he->h_addrtype)
313 { 371 {
314#if HAVE_IPV4 372# if HAVE_IPV4
315 case AF_INET: 373 case AF_INET:
316 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in); 374 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in);
317 break; 375 break;
318#endif 376# endif
319#if HAVE_IPV6 377# if HAVE_IPV6
320 case AF_INET6: 378 case AF_INET6:
321 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6); 379 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6);
322 break; 380 break;
323#endif 381# endif
324 } 382 }
325#endif 383# endif
326 384
327 /* FIXME: If more than one address, create linked list of addrinfo's. */ 385 /* FIXME: If more than one address, create linked list of addrinfo's. */
328 386
@@ -334,14 +392,15 @@ getaddrinfo (const char *restrict nodename,
334/* Free 'addrinfo' structure AI including associated storage. */ 392/* Free 'addrinfo' structure AI including associated storage. */
335void 393void
336freeaddrinfo (struct addrinfo *ai) 394freeaddrinfo (struct addrinfo *ai)
395#undef freeaddrinfo
337{ 396{
338#ifdef WINDOWS_NATIVE 397# ifdef WINDOWS_NATIVE
339 if (use_win32_p ()) 398 if (use_win32_p ())
340 { 399 {
341 freeaddrinfo_ptr (ai); 400 freeaddrinfo_ptr (ai);
342 return; 401 return;
343 } 402 }
344#endif 403# endif
345 404
346 while (ai) 405 while (ai)
347 { 406 {
@@ -360,12 +419,13 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
360 char *restrict node, socklen_t nodelen, 419 char *restrict node, socklen_t nodelen,
361 char *restrict service, socklen_t servicelen, 420 char *restrict service, socklen_t servicelen,
362 int flags) 421 int flags)
422#undef getnameinfo
363{ 423{
364#ifdef WINDOWS_NATIVE 424# ifdef WINDOWS_NATIVE
365 if (use_win32_p ()) 425 if (use_win32_p ())
366 return getnameinfo_ptr (sa, salen, node, nodelen, 426 return getnameinfo_ptr (sa, salen, node, nodelen,
367 service, servicelen, flags); 427 service, servicelen, flags);
368#endif 428# endif
369 429
370 /* FIXME: Support other flags. */ 430 /* FIXME: Support other flags. */
371 if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) || 431 if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
@@ -378,18 +438,18 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
378 438
379 switch (sa->sa_family) 439 switch (sa->sa_family)
380 { 440 {
381#if HAVE_IPV4 441# if HAVE_IPV4
382 case AF_INET: 442 case AF_INET:
383 if (salen < sizeof (struct sockaddr_in)) 443 if (salen < sizeof (struct sockaddr_in))
384 return EAI_FAMILY; 444 return EAI_FAMILY;
385 break; 445 break;
386#endif 446# endif
387#if HAVE_IPV6 447# if HAVE_IPV6
388 case AF_INET6: 448 case AF_INET6:
389 if (salen < sizeof (struct sockaddr_in6)) 449 if (salen < sizeof (struct sockaddr_in6))
390 return EAI_FAMILY; 450 return EAI_FAMILY;
391 break; 451 break;
392#endif 452# endif
393 default: 453 default:
394 return EAI_FAMILY; 454 return EAI_FAMILY;
395 } 455 }
@@ -398,23 +458,23 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
398 { 458 {
399 switch (sa->sa_family) 459 switch (sa->sa_family)
400 { 460 {
401#if HAVE_IPV4 461# if HAVE_IPV4
402 case AF_INET: 462 case AF_INET:
403 if (!inet_ntop (AF_INET, 463 if (!inet_ntop (AF_INET,
404 &(((const struct sockaddr_in *) sa)->sin_addr), 464 &(((const struct sockaddr_in *) sa)->sin_addr),
405 node, nodelen)) 465 node, nodelen))
406 return EAI_SYSTEM; 466 return EAI_SYSTEM;
407 break; 467 break;
408#endif 468# endif
409 469
410#if HAVE_IPV6 470# if HAVE_IPV6
411 case AF_INET6: 471 case AF_INET6:
412 if (!inet_ntop (AF_INET6, 472 if (!inet_ntop (AF_INET6,
413 &(((const struct sockaddr_in6 *) sa)->sin6_addr), 473 &(((const struct sockaddr_in6 *) sa)->sin6_addr),
414 node, nodelen)) 474 node, nodelen))
415 return EAI_SYSTEM; 475 return EAI_SYSTEM;
416 break; 476 break;
417#endif 477# endif
418 478
419 default: 479 default:
420 return EAI_FAMILY; 480 return EAI_FAMILY;
@@ -424,12 +484,12 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
424 if (service && servicelen > 0 && flags & NI_NUMERICSERV) 484 if (service && servicelen > 0 && flags & NI_NUMERICSERV)
425 switch (sa->sa_family) 485 switch (sa->sa_family)
426 { 486 {
427#if HAVE_IPV4 487# if HAVE_IPV4
428 case AF_INET: 488 case AF_INET:
429#endif 489# endif
430#if HAVE_IPV6 490# if HAVE_IPV6
431 case AF_INET6: 491 case AF_INET6:
432#endif 492# endif
433 { 493 {
434 unsigned short int port 494 unsigned short int port
435 = ntohs (((const struct sockaddr_in *) sa)->sin_port); 495 = ntohs (((const struct sockaddr_in *) sa)->sin_port);
@@ -441,3 +501,5 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
441 501
442 return 0; 502 return 0;
443} 503}
504
505#endif