diff options
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r-- | gl/getaddrinfo.c | 178 |
1 files changed, 120 insertions, 58 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c index 58d28115..0c42d1b7 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 | |||
61 | int | ||
62 | getaddrinfo (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 | |||
71 | void | ||
72 | freeaddrinfo (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 | ||
65 | typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, | 99 | typedef 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 | |||
147 | static int | ||
148 | use_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 | ||
112 | static bool | 169 | static bool |
113 | validate_family (int family) | 170 | validate_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. */ |
335 | void | 393 | void |
336 | freeaddrinfo (struct addrinfo *ai) | 394 | freeaddrinfo (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 | ||