summaryrefslogtreecommitdiffstats
path: root/gl/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r--gl/getaddrinfo.c74
1 files changed, 59 insertions, 15 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c
index bf5d61f3..a8c45c21 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-2025 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", 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
@@ -54,7 +54,7 @@
54 54
55#if HAVE_GETADDRINFO 55#if HAVE_GETADDRINFO
56 56
57/* Override with cdecl calling convention. */ 57/* Override with cdecl calling convention and mingw fix. */
58 58
59int 59int
60getaddrinfo (const char *restrict nodename, 60getaddrinfo (const char *restrict nodename,
@@ -63,6 +63,10 @@ getaddrinfo (const char *restrict nodename,
63 struct addrinfo **restrict res) 63 struct addrinfo **restrict res)
64# undef getaddrinfo 64# undef getaddrinfo
65{ 65{
66 if (hints && (hints->ai_flags & AI_NUMERICSERV) != 0
67 && servname && !(*servname >= '0' && *servname <= '9'))
68 return EAI_NONAME;
69
66 return getaddrinfo (nodename, servname, hints, res); 70 return getaddrinfo (nodename, servname, hints, res);
67} 71}
68 72
@@ -169,16 +173,43 @@ validate_family (int family)
169{ 173{
170 /* FIXME: Support more families. */ 174 /* FIXME: Support more families. */
171# if HAVE_IPV4 175# if HAVE_IPV4
172 if (family == PF_INET) 176 if (family == PF_INET)
173 return true; 177 return true;
174# endif 178# endif
175# if HAVE_IPV6 179# if HAVE_IPV6
176 if (family == PF_INET6) 180 if (family == PF_INET6)
177 return true; 181 return true;
178# endif 182# endif
179 if (family == PF_UNSPEC) 183 if (family == PF_UNSPEC)
180 return true; 184 return true;
181 return false; 185 return false;
186}
187
188static bool
189is_numeric_host (const char *host, int family)
190{
191# if HAVE_IPV4
192 if (family == PF_INET || family == PF_UNSPEC)
193 {
194 /* glibc supports IPv4 addresses in numbers-and-dots notation, that is,
195 also hexadecimal and octal number formats and formats that don't
196 require all four bytes to be explicitly written, via inet_aton().
197 But POSIX doesn't require support for these legacy formats. Therefore
198 we are free to use inet_pton() instead of inet_aton(). */
199 struct in_addr addr;
200 if (inet_pton (AF_INET, host, &addr))
201 return true;
202 }
203# endif
204# if HAVE_IPV6
205 if (family == PF_INET6 || family == PF_UNSPEC)
206 {
207 struct in6_addr addr;
208 if (inet_pton (AF_INET6, host, &addr))
209 return true;
210 }
211# endif
212 return false;
182} 213}
183 214
184/* Translate name of a service location and/or a service name to set of 215/* Translate name of a service location and/or a service name to set of
@@ -210,10 +241,17 @@ getaddrinfo (const char *restrict nodename,
210 241
211# ifdef WINDOWS_NATIVE 242# ifdef WINDOWS_NATIVE
212 if (use_win32_p ()) 243 if (use_win32_p ())
213 return getaddrinfo_ptr (nodename, servname, hints, res); 244 {
245 if (hints && (hints->ai_flags & AI_NUMERICSERV) != 0
246 && servname && !(*servname >= '0' && *servname <= '9'))
247 return EAI_NONAME;
248 return getaddrinfo_ptr (nodename, servname, hints, res);
249 }
214# endif 250# endif
215 251
216 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE))) 252 if (hints
253 && (hints->ai_flags
254 & ~(AI_CANONNAME | AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV)))
217 /* FIXME: Support more flags. */ 255 /* FIXME: Support more flags. */
218 return EAI_BADFLAGS; 256 return EAI_BADFLAGS;
219 257
@@ -225,12 +263,18 @@ getaddrinfo (const char *restrict nodename,
225 /* FIXME: Support other socktype. */ 263 /* FIXME: Support other socktype. */
226 return EAI_SOCKTYPE; /* FIXME: Better return code? */ 264 return EAI_SOCKTYPE; /* FIXME: Better return code? */
227 265
228 if (!nodename) 266 if (nodename != NULL)
267 {
268 if (hints && (hints->ai_flags & AI_NUMERICHOST) != 0
269 && !is_numeric_host (nodename, hints->ai_family))
270 return EAI_NONAME;
271 }
272 else
229 { 273 {
230 if (!(hints->ai_flags & AI_PASSIVE)) 274 if (!(hints->ai_flags & AI_PASSIVE))
231 return EAI_NONAME; 275 return EAI_NONAME;
232 276
233# ifdef HAVE_IPV6 277# if HAVE_IPV6
234 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; 278 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
235# else 279# else
236 nodename = "0.0.0.0"; 280 nodename = "0.0.0.0";