diff options
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r-- | gl/getaddrinfo.c | 180 |
1 files changed, 120 insertions, 60 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c index 58d28115..6586ee58 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 | |||
59 | int | ||
60 | getaddrinfo (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 | |||
69 | void | ||
70 | freeaddrinfo (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 | ||
65 | typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, | 97 | typedef 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 | |||
145 | static int | ||
146 | use_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 | ||
112 | static bool | 167 | static bool |
113 | validate_family (int family) | 168 | validate_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. */ |
335 | void | 391 | void |
336 | freeaddrinfo (struct addrinfo *ai) | 392 | freeaddrinfo (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 | ||