diff options
Diffstat (limited to 'gl/getaddrinfo.c')
-rw-r--r-- | gl/getaddrinfo.c | 174 |
1 files changed, 89 insertions, 85 deletions
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c index f09cf9e..6aa676c 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 |
60 | typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, | 63 | typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, |
61 | const struct addrinfo*, | 64 | const struct addrinfo*, |
62 | struct addrinfo**); | 65 | struct addrinfo**); |
63 | typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*); | 66 | typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*); |
64 | typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*, | 67 | typedef 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 | ||
68 | static getaddrinfo_func getaddrinfo_ptr = NULL; | 71 | static getaddrinfo_func getaddrinfo_ptr = NULL; |
69 | static freeaddrinfo_func freeaddrinfo_ptr = NULL; | 72 | static freeaddrinfo_func freeaddrinfo_ptr = NULL; |
@@ -123,9 +126,9 @@ validate_family (int family) | |||
123 | socket addresses. */ | 126 | socket addresses. */ |
124 | int | 127 | int |
125 | getaddrinfo (const char *restrict nodename, | 128 | getaddrinfo (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 | ||
351 | int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, | 354 | int |
352 | char *restrict node, socklen_t nodelen, | 355 | getnameinfo (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; |