X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetaddrinfo.c;h=a6a4066323bd7edc3c82e3679645eb661de829d0;hb=533101a268dc5015a140ff4695d8eeb04fbe57b6;hp=9003abf60ac7e145ac755153de2897df22e7837c;hpb=361c5154c63de94ec3571612225de4a6933189b7;p=gnulib.git diff --git a/lib/getaddrinfo.c b/lib/getaddrinfo.c index 9003abf60..a6a406632 100644 --- a/lib/getaddrinfo.c +++ b/lib/getaddrinfo.c @@ -1,5 +1,5 @@ /* Get address information (partial implementation). - Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 2001-2002, 2004-2013 Free Software Foundation, Inc. Contributed by Simon Josefsson . This program is free software; you can redistribute it and/or modify @@ -13,47 +13,62 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program; if not, see . */ -#ifdef HAVE_CONFIG_H -# include -#endif +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the sa == NULL test below. */ +#define _GL_ARG_NONNULL(params) + +#include -#include "getaddrinfo.h" +#include #if HAVE_NETINET_IN_H # include #endif +/* Get inet_ntop. */ +#include + /* Get calloc. */ #include -/* Get memcpy. */ +/* Get memcpy, strdup. */ #include +/* Get snprintf. */ +#include + #include #include "gettext.h" #define _(String) gettext (String) #define N_(String) String -#include "inet_ntop.h" -#include "snprintf.h" -#include "strdup.h" +/* 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 +# define WINDOWS_NATIVE #endif -#ifdef WIN32_NATIVE +/* gl_sockets_startup */ +#include "sockets.h" + +#ifdef WINDOWS_NATIVE typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*, - const struct addrinfo*, - struct addrinfo**); + const struct addrinfo*, + struct addrinfo**); typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*); typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*, - socklen_t, char*, DWORD, - char*, DWORD, int); + socklen_t, char*, DWORD, + char*, DWORD, int); static getaddrinfo_func getaddrinfo_ptr = NULL; static freeaddrinfo_func freeaddrinfo_ptr = NULL; @@ -88,11 +103,13 @@ use_win32_p (void) return 0; } + gl_sockets_startup (SOCKETS_1_1); + return 1; } #endif -static inline bool +static bool validate_family (int family) { /* FIXME: Support more families. */ @@ -113,9 +130,9 @@ validate_family (int family) socket addresses. */ int getaddrinfo (const char *restrict nodename, - const char *restrict servname, - const struct addrinfo *restrict hints, - struct addrinfo **restrict res) + const char *restrict servname, + const struct addrinfo *restrict hints, + struct addrinfo **restrict res) { struct addrinfo *tmp; int port = 0; @@ -135,7 +152,7 @@ getaddrinfo (const char *restrict nodename, }; #endif -#ifdef WIN32_NATIVE +#ifdef WINDOWS_NATIVE if (use_win32_p ()) return getaddrinfo_ptr (nodename, servname, hints, res); #endif @@ -155,10 +172,10 @@ getaddrinfo (const char *restrict nodename, if (!nodename) { if (!(hints->ai_flags & AI_PASSIVE)) - return EAI_NONAME; + return EAI_NONAME; #ifdef HAVE_IPV6 - nodename = (hint->ai_family == AF_INET6) ? "::" : "0.0.0.0"; + nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0"; #else nodename = "0.0.0.0"; #endif @@ -168,24 +185,24 @@ getaddrinfo (const char *restrict nodename, { struct servent *se = NULL; const char *proto = - (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp"; + (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp"; - if (!(hints->ai_flags & AI_NUMERICSERV)) - /* FIXME: Use getservbyname_r if available. */ - se = getservbyname (servname, proto); + if (hints == NULL || !(hints->ai_flags & AI_NUMERICSERV)) + /* FIXME: Use getservbyname_r if available. */ + se = getservbyname (servname, proto); if (!se) - { - char *c; - if (!(*servname >= '0' && *servname <= '9')) - return EAI_NONAME; - port = strtoul (servname, &c, 10); - if (*c || port > 0xffff) - return EAI_NONAME; - port = htons (port); - } + { + char *c; + if (!(*servname >= '0' && *servname <= '9')) + return EAI_NONAME; + port = strtoul (servname, &c, 10); + if (*c || port > 0xffff) + return EAI_NONAME; + port = htons (port); + } else - port = se->s_port; + port = se->s_port; } /* FIXME: Use gethostbyname_r if available. */ @@ -220,23 +237,23 @@ getaddrinfo (const char *restrict nodename, #if HAVE_IPV6 case PF_INET6: { - struct v6_pair *p = storage; - struct sockaddr_in6 *sinp = &p->sockaddr_in6; - tmp = &p->addrinfo; + struct v6_pair *p = storage; + struct sockaddr_in6 *sinp = &p->sockaddr_in6; + tmp = &p->addrinfo; - if (port) - sinp->sin6_port = port; + if (port) + sinp->sin6_port = port; - if (he->h_length != sizeof (sinp->sin6_addr)) - { - free (storage); - return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ - } + if (he->h_length != sizeof (sinp->sin6_addr)) + { + free (storage); + return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ + } - memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr); + memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr); - tmp->ai_addr = (struct sockaddr *) sinp; - tmp->ai_addrlen = sizeof *sinp; + tmp->ai_addr = (struct sockaddr *) sinp; + tmp->ai_addrlen = sizeof *sinp; } break; #endif @@ -244,23 +261,23 @@ getaddrinfo (const char *restrict nodename, #if HAVE_IPV4 case PF_INET: { - struct v4_pair *p = storage; - struct sockaddr_in *sinp = &p->sockaddr_in; - tmp = &p->addrinfo; + struct v4_pair *p = storage; + struct sockaddr_in *sinp = &p->sockaddr_in; + tmp = &p->addrinfo; - if (port) - sinp->sin_port = port; + if (port) + sinp->sin_port = port; - if (he->h_length != sizeof (sinp->sin_addr)) - { - free (storage); - return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ - } + if (he->h_length != sizeof (sinp->sin_addr)) + { + free (storage); + return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ + } - memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr); + memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr); - tmp->ai_addr = (struct sockaddr *) sinp; - tmp->ai_addrlen = sizeof *sinp; + tmp->ai_addr = (struct sockaddr *) sinp; + tmp->ai_addrlen = sizeof *sinp; } break; #endif @@ -274,16 +291,16 @@ getaddrinfo (const char *restrict nodename, { const char *cn; if (he->h_name) - cn = he->h_name; + cn = he->h_name; else - cn = nodename; + cn = nodename; tmp->ai_canonname = strdup (cn); if (!tmp->ai_canonname) - { - free (storage); - return EAI_MEMORY; - } + { + free (storage); + return EAI_MEMORY; + } } tmp->ai_protocol = (hints) ? hints->ai_protocol : 0; @@ -291,6 +308,22 @@ getaddrinfo (const char *restrict nodename, tmp->ai_addr->sa_family = he->h_addrtype; tmp->ai_family = he->h_addrtype; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + switch (he->h_addrtype) + { +#if HAVE_IPV4 + case AF_INET: + tmp->ai_addr->sa_len = sizeof (struct sockaddr_in); + break; +#endif +#if HAVE_IPV6 + case AF_INET6: + tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6); + break; +#endif + } +#endif + /* FIXME: If more than one address, create linked list of addrinfo's. */ *res = tmp; @@ -298,11 +331,11 @@ getaddrinfo (const char *restrict nodename, return 0; } -/* Free `addrinfo' structure AI including associated storage. */ +/* Free 'addrinfo' structure AI including associated storage. */ void freeaddrinfo (struct addrinfo *ai) { -#ifdef WIN32_NATIVE +#ifdef WINDOWS_NATIVE if (use_win32_p ()) { freeaddrinfo_ptr (ai); @@ -317,20 +350,21 @@ freeaddrinfo (struct addrinfo *ai) cur = ai; ai = ai->ai_next; - if (cur->ai_canonname) free (cur->ai_canonname); + free (cur->ai_canonname); free (cur); } } -int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, - char *restrict node, socklen_t nodelen, - char *restrict service, socklen_t servicelen, - int flags) +int +getnameinfo (const struct sockaddr *restrict sa, socklen_t salen, + char *restrict node, socklen_t nodelen, + char *restrict service, socklen_t servicelen, + int flags) { -#ifdef WIN32_NATIVE +#ifdef WINDOWS_NATIVE if (use_win32_p ()) return getnameinfo_ptr (sa, salen, node, nodelen, - service, servicelen, flags); + service, servicelen, flags); #endif /* FIXME: Support other flags. */ @@ -347,13 +381,13 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, #if HAVE_IPV4 case AF_INET: if (salen < sizeof (struct sockaddr_in)) - return EAI_FAMILY; + return EAI_FAMILY; break; #endif #if HAVE_IPV6 case AF_INET6: if (salen < sizeof (struct sockaddr_in6)) - return EAI_FAMILY; + return EAI_FAMILY; break; #endif default: @@ -363,28 +397,28 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, if (node && nodelen > 0 && flags & NI_NUMERICHOST) { switch (sa->sa_family) - { + { #if HAVE_IPV4 - case AF_INET: - if (!inet_ntop (AF_INET, - &(((const struct sockaddr_in *) sa)->sin_addr), - node, nodelen)) - return EAI_SYSTEM; - break; + case AF_INET: + if (!inet_ntop (AF_INET, + &(((const struct sockaddr_in *) sa)->sin_addr), + node, nodelen)) + return EAI_SYSTEM; + break; #endif #if HAVE_IPV6 - case AF_INET6: - if (!inet_ntop (AF_INET6, - &(((const struct sockaddr_in6 *) sa)->sin6_addr), - node, nodelen)) - return EAI_SYSTEM; - break; + case AF_INET6: + if (!inet_ntop (AF_INET6, + &(((const struct sockaddr_in6 *) sa)->sin6_addr), + node, nodelen)) + return EAI_SYSTEM; + break; #endif - default: - return EAI_FAMILY; - } + default: + return EAI_FAMILY; + } } if (service && servicelen > 0 && flags & NI_NUMERICSERV) @@ -396,11 +430,13 @@ 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; - break; + { + unsigned short int port + = ntohs (((const struct sockaddr_in *) sa)->sin_port); + if (servicelen <= snprintf (service, servicelen, "%u", port)) + return EAI_OVERFLOW; + } + break; } return 0;