X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetaddrinfo.c;h=f523f7658ed9eb059806ccbcee686b5247967394;hb=bbdcfead98c6d3536215c3f0f603e4f92a28d26b;hp=a058949a40d8f061be33c6bb4331f5718837273f;hpb=633351a9c79940c871ce6ed4d182844239c1ef72;p=gnulib.git diff --git a/lib/getaddrinfo.c b/lib/getaddrinfo.c index a058949a4..f523f7658 100644 --- a/lib/getaddrinfo.c +++ b/lib/getaddrinfo.c @@ -1,5 +1,6 @@ /* Get address information (partial implementation). - Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software + Foundation, Inc. Contributed by Simon Josefsson . This program is free software; you can redistribute it and/or modify @@ -16,9 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include #include "getaddrinfo.h" @@ -38,14 +37,29 @@ #define _(String) gettext (String) #define N_(String) String +#include "inet_ntop.h" +#include "snprintf.h" #include "strdup.h" -#ifdef _WIN32 -typedef void WSAAPI (*freeaddrinfo_func) (struct addrinfo*); -typedef int WSAAPI (*getaddrinfo_func) (const char*, const char*, +/* BeOS has AF_INET, but not PF_INET. */ +#ifndef PF_INET +# define PF_INET AF_INET +#endif +/* BeOS also lacks PF_UNSPEC. */ +#ifndef PF_UNSPEC +# define PF_UNSPEC 0 +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_NATIVE +#endif + +#ifdef WIN32_NATIVE +typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, const struct addrinfo*, struct addrinfo**); -typedef int WSAAPI (*getnameinfo_func) (const struct sockaddr*, +typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*); +typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*, socklen_t, char*, DWORD, char*, DWORD, int); @@ -53,7 +67,8 @@ static getaddrinfo_func getaddrinfo_ptr = NULL; static freeaddrinfo_func freeaddrinfo_ptr = NULL; static getnameinfo_func getnameinfo_ptr = NULL; -int use_win32_p (void) +static int +use_win32_p (void) { static int done = 0; HMODULE h; @@ -67,9 +82,9 @@ int use_win32_p (void) if (h) { - getaddrinfo_ptr = GetProcAddress (h, "getaddrinfo"); - freeaddrinfo_ptr = GetProcAddress (h, "freeaddrinfo"); - getnameinfo_ptr = GetProcAddress (h, "getnameinfo"); + getaddrinfo_ptr = (getaddrinfo_func) GetProcAddress (h, "getaddrinfo"); + freeaddrinfo_ptr = (freeaddrinfo_func) GetProcAddress (h, "freeaddrinfo"); + getnameinfo_ptr = (getnameinfo_func) GetProcAddress (h, "getnameinfo"); } /* If either is missing, something is odd. */ @@ -128,12 +143,12 @@ getaddrinfo (const char *restrict nodename, }; #endif -#ifdef _WIN32 +#ifdef WIN32_NATIVE if (use_win32_p ()) return getaddrinfo_ptr (nodename, servname, hints, res); #endif - if (hints && (hints->ai_flags & ~AI_CANONNAME)) + if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE))) /* FIXME: Support more flags. */ return EAI_BADFLAGS; @@ -146,8 +161,16 @@ getaddrinfo (const char *restrict nodename, return EAI_SOCKTYPE; /* FIXME: Better return code? */ if (!nodename) - /* FIXME: Support server bind mode. */ - return EAI_NONAME; + { + if (!(hints->ai_flags & AI_PASSIVE)) + return EAI_NONAME; + +#ifdef HAVE_IPV6 + nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; +#else + nodename = "0.0.0.0"; +#endif + } if (servname) { @@ -162,8 +185,10 @@ getaddrinfo (const char *restrict nodename, if (!se) { char *c; + if (!(*servname >= '0' && *servname <= '9')) + return EAI_NONAME; port = strtoul (servname, &c, 10); - if (*c) + if (*c || port > 0xffff) return EAI_NONAME; port = htons (port); } @@ -285,9 +310,12 @@ getaddrinfo (const char *restrict nodename, void freeaddrinfo (struct addrinfo *ai) { -#ifdef _WIN32 +#ifdef WIN32_NATIVE if (use_win32_p ()) - return freeaddrinfo_ptr (ai); + { + freeaddrinfo_ptr (ai); + return; + } #endif while (ai) @@ -307,7 +335,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, char *restrict service, socklen_t servicelen, int flags) { -#if _WIN32 +#ifdef WIN32_NATIVE if (use_win32_p ()) return getnameinfo_ptr (sa, salen, node, nodelen, service, servicelen, flags); @@ -347,7 +375,6 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, #if HAVE_IPV4 case AF_INET: if (!inet_ntop (AF_INET, - (const void *) &(((const struct sockaddr_in *) sa)->sin_addr), node, nodelen)) return EAI_SYSTEM; @@ -357,7 +384,6 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, #if HAVE_IPV6 case AF_INET6: if (!inet_ntop (AF_INET6, - (const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr), node, nodelen)) return EAI_SYSTEM; @@ -378,10 +404,12 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, #if HAVE_IPV6 case AF_INET6: #endif - if (snprintf (service, servicelen, "%d", - ntohs (((const struct sockaddr_in *) sa)->sin_port)) - + 1 > servicelen) - return EAI_OVERFLOW; + { + unsigned short int port + = ntohs (((const struct sockaddr_in *) sa)->sin_port); + if (servicelen <= snprintf (service, servicelen, "%u", port)) + return EAI_OVERFLOW; + } break; }