diff options
Diffstat (limited to 'gl/getaddrinfo.c')
| -rw-r--r-- | gl/getaddrinfo.c | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c index bf5d61f3..2b60377b 100644 --- a/gl/getaddrinfo.c +++ b/gl/getaddrinfo.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Get address information (partial implementation). | 1 | /* Get address information (partial implementation). |
| 2 | Copyright (C) 1997, 2001-2002, 2004-2024 Free Software Foundation, Inc. | 2 | Copyright (C) 1997, 2001-2002, 2004-2026 Free Software Foundation, Inc. |
| 3 | Contributed by Simon Josefsson <simon@josefsson.org>. | 3 | Contributed by Simon Josefsson <simon@josefsson.org>. |
| 4 | 4 | ||
| 5 | This file is free software: you can redistribute it and/or modify | 5 | This file is free software: you can redistribute it and/or modify |
| @@ -40,8 +40,8 @@ | |||
| 40 | #include <stdio.h> | 40 | #include <stdio.h> |
| 41 | 41 | ||
| 42 | #include "gettext.h" | 42 | #include "gettext.h" |
| 43 | #define _(String) gettext (String) | 43 | #define _(msgid) dgettext (GNULIB_TEXT_DOMAIN, msgid) |
| 44 | #define N_(String) String | 44 | #define N_(msgid) msgid |
| 45 | 45 | ||
| 46 | /* BeOS has AF_INET, but not PF_INET. */ | 46 | /* BeOS has AF_INET, but not PF_INET. */ |
| 47 | #ifndef PF_INET | 47 | #ifndef PF_INET |
| @@ -52,9 +52,40 @@ | |||
| 52 | # define PF_UNSPEC 0 | 52 | # define PF_UNSPEC 0 |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | #if defined __sun || !HAVE_GETADDRINFO | ||
| 56 | |||
| 57 | static bool | ||
| 58 | is_numeric_host (const char *host, int family) | ||
| 59 | { | ||
| 60 | # if HAVE_IPV4 | ||
| 61 | if (family == PF_INET || family == PF_UNSPEC) | ||
| 62 | { | ||
| 63 | /* glibc supports IPv4 addresses in numbers-and-dots notation, that is, | ||
| 64 | also hexadecimal and octal number formats and formats that don't | ||
| 65 | require all four bytes to be explicitly written, via inet_aton(). | ||
| 66 | But POSIX doesn't require support for these legacy formats. Therefore | ||
| 67 | we are free to use inet_pton() instead of inet_aton(). */ | ||
| 68 | struct in_addr addr; | ||
| 69 | if (inet_pton (AF_INET, host, &addr)) | ||
| 70 | return true; | ||
| 71 | } | ||
| 72 | # endif | ||
| 73 | # if HAVE_IPV6 | ||
| 74 | if (family == PF_INET6 || family == PF_UNSPEC) | ||
| 75 | { | ||
| 76 | struct in6_addr addr; | ||
| 77 | if (inet_pton (AF_INET6, host, &addr)) | ||
| 78 | return true; | ||
| 79 | } | ||
| 80 | # endif | ||
| 81 | return false; | ||
| 82 | } | ||
| 83 | |||
| 84 | #endif | ||
| 85 | |||
| 55 | #if HAVE_GETADDRINFO | 86 | #if HAVE_GETADDRINFO |
| 56 | 87 | ||
| 57 | /* Override with cdecl calling convention. */ | 88 | /* Override with cdecl calling convention and Windows and Solaris 10 fixes. */ |
| 58 | 89 | ||
| 59 | int | 90 | int |
| 60 | getaddrinfo (const char *restrict nodename, | 91 | getaddrinfo (const char *restrict nodename, |
| @@ -63,6 +94,18 @@ getaddrinfo (const char *restrict nodename, | |||
| 63 | struct addrinfo **restrict res) | 94 | struct addrinfo **restrict res) |
| 64 | # undef getaddrinfo | 95 | # undef getaddrinfo |
| 65 | { | 96 | { |
| 97 | /* Workaround for native Windows. */ | ||
| 98 | if (hints && (hints->ai_flags & AI_NUMERICSERV) != 0 | ||
| 99 | && servname && !(*servname >= '0' && *servname <= '9')) | ||
| 100 | return EAI_NONAME; | ||
| 101 | |||
| 102 | # ifdef __sun | ||
| 103 | /* Workaround for Solaris 10. */ | ||
| 104 | if (hints && (hints->ai_flags & AI_NUMERICHOST) | ||
| 105 | && nodename && !is_numeric_host (nodename, hints->ai_family)) | ||
| 106 | return EAI_NONAME; | ||
| 107 | # endif | ||
| 108 | |||
| 66 | return getaddrinfo (nodename, servname, hints, res); | 109 | return getaddrinfo (nodename, servname, hints, res); |
| 67 | } | 110 | } |
| 68 | 111 | ||
| @@ -110,14 +153,13 @@ static int | |||
| 110 | use_win32_p (void) | 153 | use_win32_p (void) |
| 111 | { | 154 | { |
| 112 | static int done = 0; | 155 | static int done = 0; |
| 113 | HMODULE h; | ||
| 114 | 156 | ||
| 115 | if (done) | 157 | if (done) |
| 116 | return getaddrinfo_ptr ? 1 : 0; | 158 | return getaddrinfo_ptr ? 1 : 0; |
| 117 | 159 | ||
| 118 | done = 1; | 160 | done = 1; |
| 119 | 161 | ||
| 120 | h = GetModuleHandle ("ws2_32.dll"); | 162 | HMODULE h = GetModuleHandle ("ws2_32.dll"); |
| 121 | 163 | ||
| 122 | if (h) | 164 | if (h) |
| 123 | { | 165 | { |
| @@ -169,16 +211,16 @@ validate_family (int family) | |||
| 169 | { | 211 | { |
| 170 | /* FIXME: Support more families. */ | 212 | /* FIXME: Support more families. */ |
| 171 | # if HAVE_IPV4 | 213 | # if HAVE_IPV4 |
| 172 | if (family == PF_INET) | 214 | if (family == PF_INET) |
| 173 | return true; | 215 | return true; |
| 174 | # endif | 216 | # endif |
| 175 | # if HAVE_IPV6 | 217 | # if HAVE_IPV6 |
| 176 | if (family == PF_INET6) | 218 | if (family == PF_INET6) |
| 177 | return true; | 219 | return true; |
| 178 | # endif | 220 | # endif |
| 179 | if (family == PF_UNSPEC) | 221 | if (family == PF_UNSPEC) |
| 180 | return true; | 222 | return true; |
| 181 | return false; | 223 | return false; |
| 182 | } | 224 | } |
| 183 | 225 | ||
| 184 | /* Translate name of a service location and/or a service name to set of | 226 | /* Translate name of a service location and/or a service name to set of |
| @@ -190,11 +232,6 @@ getaddrinfo (const char *restrict nodename, | |||
| 190 | struct addrinfo **restrict res) | 232 | struct addrinfo **restrict res) |
| 191 | #undef getaddrinfo | 233 | #undef getaddrinfo |
| 192 | { | 234 | { |
| 193 | struct addrinfo *tmp; | ||
| 194 | int port = 0; | ||
| 195 | struct hostent *he; | ||
| 196 | void *storage; | ||
| 197 | size_t size; | ||
| 198 | # if HAVE_IPV6 | 235 | # if HAVE_IPV6 |
| 199 | struct v6_pair { | 236 | struct v6_pair { |
| 200 | struct addrinfo addrinfo; | 237 | struct addrinfo addrinfo; |
| @@ -210,10 +247,17 @@ getaddrinfo (const char *restrict nodename, | |||
| 210 | 247 | ||
| 211 | # ifdef WINDOWS_NATIVE | 248 | # ifdef WINDOWS_NATIVE |
| 212 | if (use_win32_p ()) | 249 | if (use_win32_p ()) |
| 213 | return getaddrinfo_ptr (nodename, servname, hints, res); | 250 | { |
| 251 | if (hints && (hints->ai_flags & AI_NUMERICSERV) != 0 | ||
| 252 | && servname && !(*servname >= '0' && *servname <= '9')) | ||
| 253 | return EAI_NONAME; | ||
| 254 | return getaddrinfo_ptr (nodename, servname, hints, res); | ||
| 255 | } | ||
| 214 | # endif | 256 | # endif |
| 215 | 257 | ||
| 216 | if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE))) | 258 | if (hints |
| 259 | && (hints->ai_flags | ||
| 260 | & ~(AI_CANONNAME | AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV))) | ||
| 217 | /* FIXME: Support more flags. */ | 261 | /* FIXME: Support more flags. */ |
| 218 | return EAI_BADFLAGS; | 262 | return EAI_BADFLAGS; |
| 219 | 263 | ||
| @@ -225,18 +269,25 @@ getaddrinfo (const char *restrict nodename, | |||
| 225 | /* FIXME: Support other socktype. */ | 269 | /* FIXME: Support other socktype. */ |
| 226 | return EAI_SOCKTYPE; /* FIXME: Better return code? */ | 270 | return EAI_SOCKTYPE; /* FIXME: Better return code? */ |
| 227 | 271 | ||
| 228 | if (!nodename) | 272 | if (nodename != NULL) |
| 273 | { | ||
| 274 | if (hints && (hints->ai_flags & AI_NUMERICHOST) != 0 | ||
| 275 | && !is_numeric_host (nodename, hints->ai_family)) | ||
| 276 | return EAI_NONAME; | ||
| 277 | } | ||
| 278 | else | ||
| 229 | { | 279 | { |
| 230 | if (!(hints->ai_flags & AI_PASSIVE)) | 280 | if (!(hints->ai_flags & AI_PASSIVE)) |
| 231 | return EAI_NONAME; | 281 | return EAI_NONAME; |
| 232 | 282 | ||
| 233 | # ifdef HAVE_IPV6 | 283 | # if HAVE_IPV6 |
| 234 | nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; | 284 | nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; |
| 235 | # else | 285 | # else |
| 236 | nodename = "0.0.0.0"; | 286 | nodename = "0.0.0.0"; |
| 237 | # endif | 287 | # endif |
| 238 | } | 288 | } |
| 239 | 289 | ||
| 290 | int port = 0; | ||
| 240 | if (servname) | 291 | if (servname) |
| 241 | { | 292 | { |
| 242 | struct servent *se = NULL; | 293 | struct servent *se = NULL; |
| @@ -262,10 +313,11 @@ getaddrinfo (const char *restrict nodename, | |||
| 262 | } | 313 | } |
| 263 | 314 | ||
| 264 | /* FIXME: Use gethostbyname_r if available. */ | 315 | /* FIXME: Use gethostbyname_r if available. */ |
| 265 | he = gethostbyname (nodename); | 316 | struct hostent *he = gethostbyname (nodename); |
| 266 | if (!he || he->h_addr_list[0] == NULL) | 317 | if (!he || he->h_addr_list[0] == NULL) |
| 267 | return EAI_NONAME; | 318 | return EAI_NONAME; |
| 268 | 319 | ||
| 320 | size_t size; | ||
| 269 | switch (he->h_addrtype) | 321 | switch (he->h_addrtype) |
| 270 | { | 322 | { |
| 271 | # if HAVE_IPV6 | 323 | # if HAVE_IPV6 |
| @@ -284,10 +336,11 @@ getaddrinfo (const char *restrict nodename, | |||
| 284 | return EAI_NODATA; | 336 | return EAI_NODATA; |
| 285 | } | 337 | } |
| 286 | 338 | ||
| 287 | storage = calloc (1, size); | 339 | void *storage = calloc (1, size); |
| 288 | if (!storage) | 340 | if (!storage) |
| 289 | return EAI_MEMORY; | 341 | return EAI_MEMORY; |
| 290 | 342 | ||
| 343 | struct addrinfo *tmp; | ||
| 291 | switch (he->h_addrtype) | 344 | switch (he->h_addrtype) |
| 292 | { | 345 | { |
| 293 | # if HAVE_IPV6 | 346 | # if HAVE_IPV6 |
| @@ -402,9 +455,7 @@ freeaddrinfo (struct addrinfo *ai) | |||
| 402 | 455 | ||
| 403 | while (ai) | 456 | while (ai) |
| 404 | { | 457 | { |
| 405 | struct addrinfo *cur; | 458 | struct addrinfo *cur = ai; |
| 406 | |||
| 407 | cur = ai; | ||
| 408 | ai = ai->ai_next; | 459 | ai = ai->ai_next; |
| 409 | 460 | ||
| 410 | free (cur->ai_canonname); | 461 | free (cur->ai_canonname); |
