summaryrefslogtreecommitdiffstats
path: root/gl/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r--gl/getaddrinfo.c105
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
57static bool
58is_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
59int 90int
60getaddrinfo (const char *restrict nodename, 91getaddrinfo (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
110use_win32_p (void) 153use_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);