summaryrefslogtreecommitdiffstats
path: root/gl/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r--gl/getaddrinfo.c174
1 files changed, 89 insertions, 85 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c
index f09cf9ee..6aa676c8 100644
--- a/gl/getaddrinfo.c
+++ b/gl/getaddrinfo.c
@@ -1,6 +1,5 @@
1/* Get address information (partial implementation). 1/* Get address information (partial implementation).
2 Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006, 2007, 2008 Free Software 2 Copyright (C) 1997, 2001-2002, 2004-2010 Free Software Foundation, Inc.
3 Foundation, Inc.
4 Contributed by Simon Josefsson <simon@josefsson.org>. 3 Contributed by Simon Josefsson <simon@josefsson.org>.
5 4
6 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
@@ -19,6 +18,10 @@
19 18
20#include <config.h> 19#include <config.h>
21 20
21/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
22 optimizes away the sa == NULL test below. */
23#define _GL_ARG_NONNULL(params)
24
22#include <netdb.h> 25#include <netdb.h>
23 26
24#if HAVE_NETINET_IN_H 27#if HAVE_NETINET_IN_H
@@ -58,12 +61,12 @@
58 61
59#ifdef WIN32_NATIVE 62#ifdef WIN32_NATIVE
60typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, 63typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
61 const struct addrinfo*, 64 const struct addrinfo*,
62 struct addrinfo**); 65 struct addrinfo**);
63typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*); 66typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*);
64typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*, 67typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*,
65 socklen_t, char*, DWORD, 68 socklen_t, char*, DWORD,
66 char*, DWORD, int); 69 char*, DWORD, int);
67 70
68static getaddrinfo_func getaddrinfo_ptr = NULL; 71static getaddrinfo_func getaddrinfo_ptr = NULL;
69static freeaddrinfo_func freeaddrinfo_ptr = NULL; 72static freeaddrinfo_func freeaddrinfo_ptr = NULL;
@@ -123,9 +126,9 @@ validate_family (int family)
123 socket addresses. */ 126 socket addresses. */
124int 127int
125getaddrinfo (const char *restrict nodename, 128getaddrinfo (const char *restrict nodename,
126 const char *restrict servname, 129 const char *restrict servname,
127 const struct addrinfo *restrict hints, 130 const struct addrinfo *restrict hints,
128 struct addrinfo **restrict res) 131 struct addrinfo **restrict res)
129{ 132{
130 struct addrinfo *tmp; 133 struct addrinfo *tmp;
131 int port = 0; 134 int port = 0;
@@ -165,7 +168,7 @@ getaddrinfo (const char *restrict nodename,
165 if (!nodename) 168 if (!nodename)
166 { 169 {
167 if (!(hints->ai_flags & AI_PASSIVE)) 170 if (!(hints->ai_flags & AI_PASSIVE))
168 return EAI_NONAME; 171 return EAI_NONAME;
169 172
170#ifdef HAVE_IPV6 173#ifdef HAVE_IPV6
171 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; 174 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
@@ -178,24 +181,24 @@ getaddrinfo (const char *restrict nodename,
178 { 181 {
179 struct servent *se = NULL; 182 struct servent *se = NULL;
180 const char *proto = 183 const char *proto =
181 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp"; 184 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
182 185
183 if (hints == NULL || !(hints->ai_flags & AI_NUMERICSERV)) 186 if (hints == NULL || !(hints->ai_flags & AI_NUMERICSERV))
184 /* FIXME: Use getservbyname_r if available. */ 187 /* FIXME: Use getservbyname_r if available. */
185 se = getservbyname (servname, proto); 188 se = getservbyname (servname, proto);
186 189
187 if (!se) 190 if (!se)
188 { 191 {
189 char *c; 192 char *c;
190 if (!(*servname >= '0' && *servname <= '9')) 193 if (!(*servname >= '0' && *servname <= '9'))
191 return EAI_NONAME; 194 return EAI_NONAME;
192 port = strtoul (servname, &c, 10); 195 port = strtoul (servname, &c, 10);
193 if (*c || port > 0xffff) 196 if (*c || port > 0xffff)
194 return EAI_NONAME; 197 return EAI_NONAME;
195 port = htons (port); 198 port = htons (port);
196 } 199 }
197 else 200 else
198 port = se->s_port; 201 port = se->s_port;
199 } 202 }
200 203
201 /* FIXME: Use gethostbyname_r if available. */ 204 /* FIXME: Use gethostbyname_r if available. */
@@ -230,23 +233,23 @@ getaddrinfo (const char *restrict nodename,
230#if HAVE_IPV6 233#if HAVE_IPV6
231 case PF_INET6: 234 case PF_INET6:
232 { 235 {
233 struct v6_pair *p = storage; 236 struct v6_pair *p = storage;
234 struct sockaddr_in6 *sinp = &p->sockaddr_in6; 237 struct sockaddr_in6 *sinp = &p->sockaddr_in6;
235 tmp = &p->addrinfo; 238 tmp = &p->addrinfo;
236 239
237 if (port) 240 if (port)
238 sinp->sin6_port = port; 241 sinp->sin6_port = port;
239 242
240 if (he->h_length != sizeof (sinp->sin6_addr)) 243 if (he->h_length != sizeof (sinp->sin6_addr))
241 { 244 {
242 free (storage); 245 free (storage);
243 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ 246 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
244 } 247 }
245 248
246 memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr); 249 memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr);
247 250
248 tmp->ai_addr = (struct sockaddr *) sinp; 251 tmp->ai_addr = (struct sockaddr *) sinp;
249 tmp->ai_addrlen = sizeof *sinp; 252 tmp->ai_addrlen = sizeof *sinp;
250 } 253 }
251 break; 254 break;
252#endif 255#endif
@@ -254,23 +257,23 @@ getaddrinfo (const char *restrict nodename,
254#if HAVE_IPV4 257#if HAVE_IPV4
255 case PF_INET: 258 case PF_INET:
256 { 259 {
257 struct v4_pair *p = storage; 260 struct v4_pair *p = storage;
258 struct sockaddr_in *sinp = &p->sockaddr_in; 261 struct sockaddr_in *sinp = &p->sockaddr_in;
259 tmp = &p->addrinfo; 262 tmp = &p->addrinfo;
260 263
261 if (port) 264 if (port)
262 sinp->sin_port = port; 265 sinp->sin_port = port;
263 266
264 if (he->h_length != sizeof (sinp->sin_addr)) 267 if (he->h_length != sizeof (sinp->sin_addr))
265 { 268 {
266 free (storage); 269 free (storage);
267 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ 270 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
268 } 271 }
269 272
270 memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr); 273 memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr);
271 274
272 tmp->ai_addr = (struct sockaddr *) sinp; 275 tmp->ai_addr = (struct sockaddr *) sinp;
273 tmp->ai_addrlen = sizeof *sinp; 276 tmp->ai_addrlen = sizeof *sinp;
274 } 277 }
275 break; 278 break;
276#endif 279#endif
@@ -284,16 +287,16 @@ getaddrinfo (const char *restrict nodename,
284 { 287 {
285 const char *cn; 288 const char *cn;
286 if (he->h_name) 289 if (he->h_name)
287 cn = he->h_name; 290 cn = he->h_name;
288 else 291 else
289 cn = nodename; 292 cn = nodename;
290 293
291 tmp->ai_canonname = strdup (cn); 294 tmp->ai_canonname = strdup (cn);
292 if (!tmp->ai_canonname) 295 if (!tmp->ai_canonname)
293 { 296 {
294 free (storage); 297 free (storage);
295 return EAI_MEMORY; 298 return EAI_MEMORY;
296 } 299 }
297 } 300 }
298 301
299 tmp->ai_protocol = (hints) ? hints->ai_protocol : 0; 302 tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
@@ -348,15 +351,16 @@ freeaddrinfo (struct addrinfo *ai)
348 } 351 }
349} 352}
350 353
351int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, 354int
352 char *restrict node, socklen_t nodelen, 355getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
353 char *restrict service, socklen_t servicelen, 356 char *restrict node, socklen_t nodelen,
354 int flags) 357 char *restrict service, socklen_t servicelen,
358 int flags)
355{ 359{
356#ifdef WIN32_NATIVE 360#ifdef WIN32_NATIVE
357 if (use_win32_p ()) 361 if (use_win32_p ())
358 return getnameinfo_ptr (sa, salen, node, nodelen, 362 return getnameinfo_ptr (sa, salen, node, nodelen,
359 service, servicelen, flags); 363 service, servicelen, flags);
360#endif 364#endif
361 365
362 /* FIXME: Support other flags. */ 366 /* FIXME: Support other flags. */
@@ -373,13 +377,13 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
373#if HAVE_IPV4 377#if HAVE_IPV4
374 case AF_INET: 378 case AF_INET:
375 if (salen < sizeof (struct sockaddr_in)) 379 if (salen < sizeof (struct sockaddr_in))
376 return EAI_FAMILY; 380 return EAI_FAMILY;
377 break; 381 break;
378#endif 382#endif
379#if HAVE_IPV6 383#if HAVE_IPV6
380 case AF_INET6: 384 case AF_INET6:
381 if (salen < sizeof (struct sockaddr_in6)) 385 if (salen < sizeof (struct sockaddr_in6))
382 return EAI_FAMILY; 386 return EAI_FAMILY;
383 break; 387 break;
384#endif 388#endif
385 default: 389 default:
@@ -389,28 +393,28 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
389 if (node && nodelen > 0 && flags & NI_NUMERICHOST) 393 if (node && nodelen > 0 && flags & NI_NUMERICHOST)
390 { 394 {
391 switch (sa->sa_family) 395 switch (sa->sa_family)
392 { 396 {
393#if HAVE_IPV4 397#if HAVE_IPV4
394 case AF_INET: 398 case AF_INET:
395 if (!inet_ntop (AF_INET, 399 if (!inet_ntop (AF_INET,
396 &(((const struct sockaddr_in *) sa)->sin_addr), 400 &(((const struct sockaddr_in *) sa)->sin_addr),
397 node, nodelen)) 401 node, nodelen))
398 return EAI_SYSTEM; 402 return EAI_SYSTEM;
399 break; 403 break;
400#endif 404#endif
401 405
402#if HAVE_IPV6 406#if HAVE_IPV6
403 case AF_INET6: 407 case AF_INET6:
404 if (!inet_ntop (AF_INET6, 408 if (!inet_ntop (AF_INET6,
405 &(((const struct sockaddr_in6 *) sa)->sin6_addr), 409 &(((const struct sockaddr_in6 *) sa)->sin6_addr),
406 node, nodelen)) 410 node, nodelen))
407 return EAI_SYSTEM; 411 return EAI_SYSTEM;
408 break; 412 break;
409#endif 413#endif
410 414
411 default: 415 default:
412 return EAI_FAMILY; 416 return EAI_FAMILY;
413 } 417 }
414 } 418 }
415 419
416 if (service && servicelen > 0 && flags & NI_NUMERICSERV) 420 if (service && servicelen > 0 && flags & NI_NUMERICSERV)
@@ -422,13 +426,13 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
422#if HAVE_IPV6 426#if HAVE_IPV6
423 case AF_INET6: 427 case AF_INET6:
424#endif 428#endif
425 { 429 {
426 unsigned short int port 430 unsigned short int port
427 = ntohs (((const struct sockaddr_in *) sa)->sin_port); 431 = ntohs (((const struct sockaddr_in *) sa)->sin_port);
428 if (servicelen <= snprintf (service, servicelen, "%u", port)) 432 if (servicelen <= snprintf (service, servicelen, "%u", port))
429 return EAI_OVERFLOW; 433 return EAI_OVERFLOW;
430 } 434 }
431 break; 435 break;
432 } 436 }
433 437
434 return 0; 438 return 0;