summaryrefslogtreecommitdiffstats
path: root/gl/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r--gl/getaddrinfo.c180
1 files changed, 120 insertions, 60 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c
index 58d2811..6586ee5 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-2023 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. */
@@ -39,8 +39,6 @@
39/* Get snprintf. */ 39/* Get snprintf. */
40#include <stdio.h> 40#include <stdio.h>
41 41
42#include <stdbool.h>
43
44#include "gettext.h" 42#include "gettext.h"
45#define _(String) gettext (String) 43#define _(String) gettext (String)
46#define N_(String) String 44#define N_(String) String
@@ -54,14 +52,48 @@
54# define PF_UNSPEC 0 52# define PF_UNSPEC 0
55#endif 53#endif
56 54
57#if defined _WIN32 || defined __WIN32__ 55#if HAVE_GETADDRINFO
58# define WINDOWS_NATIVE 56
59#endif 57/* Override with cdecl calling convention. */
58
59int
60getaddrinfo (const char *restrict nodename,
61 const char *restrict servname,
62 const struct addrinfo *restrict hints,
63 struct addrinfo **restrict res)
64# undef getaddrinfo
65{
66 return getaddrinfo (nodename, servname, hints, res);
67}
68
69void
70freeaddrinfo (struct addrinfo *ai)
71# undef freeaddrinfo
72{
73 freeaddrinfo (ai);
74}
75
76#else
77
78# if defined _WIN32 && !defined __CYGWIN__
79# define WINDOWS_NATIVE
80# endif
60 81
61/* gl_sockets_startup */ 82/* gl_sockets_startup */
62#include "sockets.h" 83# include "sockets.h"
84
85# ifdef WINDOWS_NATIVE
86
87/* Don't assume that UNICODE is not defined. */
88# undef GetModuleHandle
89# define GetModuleHandle GetModuleHandleA
90
91# if !(_WIN32_WINNT >= _WIN32_WINNT_WINXP)
92
93/* Avoid warnings from gcc -Wcast-function-type. */
94# define GetProcAddress \
95 (void *) GetProcAddress
63 96
64#ifdef WINDOWS_NATIVE
65typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, 97typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
66 const struct addrinfo*, 98 const struct addrinfo*,
67 struct addrinfo**); 99 struct addrinfo**);
@@ -107,20 +139,43 @@ use_win32_p (void)
107 139
108 return 1; 140 return 1;
109} 141}
110#endif 142
143# else
144
145static int
146use_win32_p (void)
147{
148 static int done = 0;
149
150 if (!done)
151 {
152 done = 1;
153
154 gl_sockets_startup (SOCKETS_1_1);
155 }
156
157 return 1;
158}
159
160# define getaddrinfo_ptr getaddrinfo
161# define freeaddrinfo_ptr freeaddrinfo
162# define getnameinfo_ptr getnameinfo
163
164# endif
165# endif
111 166
112static bool 167static bool
113validate_family (int family) 168validate_family (int family)
114{ 169{
115 /* FIXME: Support more families. */ 170 /* FIXME: Support more families. */
116#if HAVE_IPV4 171# if HAVE_IPV4
117 if (family == PF_INET) 172 if (family == PF_INET)
118 return true; 173 return true;
119#endif 174# endif
120#if HAVE_IPV6 175# if HAVE_IPV6
121 if (family == PF_INET6) 176 if (family == PF_INET6)
122 return true; 177 return true;
123#endif 178# endif
124 if (family == PF_UNSPEC) 179 if (family == PF_UNSPEC)
125 return true; 180 return true;
126 return false; 181 return false;
@@ -133,29 +188,30 @@ getaddrinfo (const char *restrict nodename,
133 const char *restrict servname, 188 const char *restrict servname,
134 const struct addrinfo *restrict hints, 189 const struct addrinfo *restrict hints,
135 struct addrinfo **restrict res) 190 struct addrinfo **restrict res)
191#undef getaddrinfo
136{ 192{
137 struct addrinfo *tmp; 193 struct addrinfo *tmp;
138 int port = 0; 194 int port = 0;
139 struct hostent *he; 195 struct hostent *he;
140 void *storage; 196 void *storage;
141 size_t size; 197 size_t size;
142#if HAVE_IPV6 198# if HAVE_IPV6
143 struct v6_pair { 199 struct v6_pair {
144 struct addrinfo addrinfo; 200 struct addrinfo addrinfo;
145 struct sockaddr_in6 sockaddr_in6; 201 struct sockaddr_in6 sockaddr_in6;
146 }; 202 };
147#endif 203# endif
148#if HAVE_IPV4 204# if HAVE_IPV4
149 struct v4_pair { 205 struct v4_pair {
150 struct addrinfo addrinfo; 206 struct addrinfo addrinfo;
151 struct sockaddr_in sockaddr_in; 207 struct sockaddr_in sockaddr_in;
152 }; 208 };
153#endif 209# endif
154 210
155#ifdef WINDOWS_NATIVE 211# ifdef WINDOWS_NATIVE
156 if (use_win32_p ()) 212 if (use_win32_p ())
157 return getaddrinfo_ptr (nodename, servname, hints, res); 213 return getaddrinfo_ptr (nodename, servname, hints, res);
158#endif 214# endif
159 215
160 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE))) 216 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
161 /* FIXME: Support more flags. */ 217 /* FIXME: Support more flags. */
@@ -174,11 +230,11 @@ getaddrinfo (const char *restrict nodename,
174 if (!(hints->ai_flags & AI_PASSIVE)) 230 if (!(hints->ai_flags & AI_PASSIVE))
175 return EAI_NONAME; 231 return EAI_NONAME;
176 232
177#ifdef HAVE_IPV6 233# ifdef HAVE_IPV6
178 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; 234 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
179#else 235# else
180 nodename = "0.0.0.0"; 236 nodename = "0.0.0.0";
181#endif 237# endif
182 } 238 }
183 239
184 if (servname) 240 if (servname)
@@ -212,17 +268,17 @@ getaddrinfo (const char *restrict nodename,
212 268
213 switch (he->h_addrtype) 269 switch (he->h_addrtype)
214 { 270 {
215#if HAVE_IPV6 271# if HAVE_IPV6
216 case PF_INET6: 272 case PF_INET6:
217 size = sizeof (struct v6_pair); 273 size = sizeof (struct v6_pair);
218 break; 274 break;
219#endif 275# endif
220 276
221#if HAVE_IPV4 277# if HAVE_IPV4
222 case PF_INET: 278 case PF_INET:
223 size = sizeof (struct v4_pair); 279 size = sizeof (struct v4_pair);
224 break; 280 break;
225#endif 281# endif
226 282
227 default: 283 default:
228 return EAI_NODATA; 284 return EAI_NODATA;
@@ -234,7 +290,7 @@ getaddrinfo (const char *restrict nodename,
234 290
235 switch (he->h_addrtype) 291 switch (he->h_addrtype)
236 { 292 {
237#if HAVE_IPV6 293# if HAVE_IPV6
238 case PF_INET6: 294 case PF_INET6:
239 { 295 {
240 struct v6_pair *p = storage; 296 struct v6_pair *p = storage;
@@ -256,9 +312,9 @@ getaddrinfo (const char *restrict nodename,
256 tmp->ai_addrlen = sizeof *sinp; 312 tmp->ai_addrlen = sizeof *sinp;
257 } 313 }
258 break; 314 break;
259#endif 315# endif
260 316
261#if HAVE_IPV4 317# if HAVE_IPV4
262 case PF_INET: 318 case PF_INET:
263 { 319 {
264 struct v4_pair *p = storage; 320 struct v4_pair *p = storage;
@@ -280,7 +336,7 @@ getaddrinfo (const char *restrict nodename,
280 tmp->ai_addrlen = sizeof *sinp; 336 tmp->ai_addrlen = sizeof *sinp;
281 } 337 }
282 break; 338 break;
283#endif 339# endif
284 340
285 default: 341 default:
286 free (storage); 342 free (storage);
@@ -308,21 +364,21 @@ getaddrinfo (const char *restrict nodename,
308 tmp->ai_addr->sa_family = he->h_addrtype; 364 tmp->ai_addr->sa_family = he->h_addrtype;
309 tmp->ai_family = he->h_addrtype; 365 tmp->ai_family = he->h_addrtype;
310 366
311#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 367# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
312 switch (he->h_addrtype) 368 switch (he->h_addrtype)
313 { 369 {
314#if HAVE_IPV4 370# if HAVE_IPV4
315 case AF_INET: 371 case AF_INET:
316 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in); 372 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in);
317 break; 373 break;
318#endif 374# endif
319#if HAVE_IPV6 375# if HAVE_IPV6
320 case AF_INET6: 376 case AF_INET6:
321 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6); 377 tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6);
322 break; 378 break;
323#endif 379# endif
324 } 380 }
325#endif 381# endif
326 382
327 /* FIXME: If more than one address, create linked list of addrinfo's. */ 383 /* FIXME: If more than one address, create linked list of addrinfo's. */
328 384
@@ -334,14 +390,15 @@ getaddrinfo (const char *restrict nodename,
334/* Free 'addrinfo' structure AI including associated storage. */ 390/* Free 'addrinfo' structure AI including associated storage. */
335void 391void
336freeaddrinfo (struct addrinfo *ai) 392freeaddrinfo (struct addrinfo *ai)
393#undef freeaddrinfo
337{ 394{
338#ifdef WINDOWS_NATIVE 395# ifdef WINDOWS_NATIVE
339 if (use_win32_p ()) 396 if (use_win32_p ())
340 { 397 {
341 freeaddrinfo_ptr (ai); 398 freeaddrinfo_ptr (ai);
342 return; 399 return;
343 } 400 }
344#endif 401# endif
345 402
346 while (ai) 403 while (ai)
347 { 404 {
@@ -360,12 +417,13 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
360 char *restrict node, socklen_t nodelen, 417 char *restrict node, socklen_t nodelen,
361 char *restrict service, socklen_t servicelen, 418 char *restrict service, socklen_t servicelen,
362 int flags) 419 int flags)
420#undef getnameinfo
363{ 421{
364#ifdef WINDOWS_NATIVE 422# ifdef WINDOWS_NATIVE
365 if (use_win32_p ()) 423 if (use_win32_p ())
366 return getnameinfo_ptr (sa, salen, node, nodelen, 424 return getnameinfo_ptr (sa, salen, node, nodelen,
367 service, servicelen, flags); 425 service, servicelen, flags);
368#endif 426# endif
369 427
370 /* FIXME: Support other flags. */ 428 /* FIXME: Support other flags. */
371 if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) || 429 if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
@@ -378,18 +436,18 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
378 436
379 switch (sa->sa_family) 437 switch (sa->sa_family)
380 { 438 {
381#if HAVE_IPV4 439# if HAVE_IPV4
382 case AF_INET: 440 case AF_INET:
383 if (salen < sizeof (struct sockaddr_in)) 441 if (salen < sizeof (struct sockaddr_in))
384 return EAI_FAMILY; 442 return EAI_FAMILY;
385 break; 443 break;
386#endif 444# endif
387#if HAVE_IPV6 445# if HAVE_IPV6
388 case AF_INET6: 446 case AF_INET6:
389 if (salen < sizeof (struct sockaddr_in6)) 447 if (salen < sizeof (struct sockaddr_in6))
390 return EAI_FAMILY; 448 return EAI_FAMILY;
391 break; 449 break;
392#endif 450# endif
393 default: 451 default:
394 return EAI_FAMILY; 452 return EAI_FAMILY;
395 } 453 }
@@ -398,23 +456,23 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
398 { 456 {
399 switch (sa->sa_family) 457 switch (sa->sa_family)
400 { 458 {
401#if HAVE_IPV4 459# if HAVE_IPV4
402 case AF_INET: 460 case AF_INET:
403 if (!inet_ntop (AF_INET, 461 if (!inet_ntop (AF_INET,
404 &(((const struct sockaddr_in *) sa)->sin_addr), 462 &(((const struct sockaddr_in *) sa)->sin_addr),
405 node, nodelen)) 463 node, nodelen))
406 return EAI_SYSTEM; 464 return EAI_SYSTEM;
407 break; 465 break;
408#endif 466# endif
409 467
410#if HAVE_IPV6 468# if HAVE_IPV6
411 case AF_INET6: 469 case AF_INET6:
412 if (!inet_ntop (AF_INET6, 470 if (!inet_ntop (AF_INET6,
413 &(((const struct sockaddr_in6 *) sa)->sin6_addr), 471 &(((const struct sockaddr_in6 *) sa)->sin6_addr),
414 node, nodelen)) 472 node, nodelen))
415 return EAI_SYSTEM; 473 return EAI_SYSTEM;
416 break; 474 break;
417#endif 475# endif
418 476
419 default: 477 default:
420 return EAI_FAMILY; 478 return EAI_FAMILY;
@@ -424,12 +482,12 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
424 if (service && servicelen > 0 && flags & NI_NUMERICSERV) 482 if (service && servicelen > 0 && flags & NI_NUMERICSERV)
425 switch (sa->sa_family) 483 switch (sa->sa_family)
426 { 484 {
427#if HAVE_IPV4 485# if HAVE_IPV4
428 case AF_INET: 486 case AF_INET:
429#endif 487# endif
430#if HAVE_IPV6 488# if HAVE_IPV6
431 case AF_INET6: 489 case AF_INET6:
432#endif 490# endif
433 { 491 {
434 unsigned short int port 492 unsigned short int port
435 = ntohs (((const struct sockaddr_in *) sa)->sin_port); 493 = ntohs (((const struct sockaddr_in *) sa)->sin_port);
@@ -441,3 +499,5 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
441 499
442 return 0; 500 return 0;
443} 501}
502
503#endif