X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=inline;f=src%2Fnetwork%2Fgetaddrinfo.c;h=236088e2dde1c8de8b8cd25ab975cccf90d91e65;hb=6d9fde80110542d213ed6236efc134931da58066;hp=aa275eba964958daf03db17d22157662cdddabf5;hpb=1ec75fc582a40a17867dd6c16005a3751661c52a;p=vlc diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index aa275eba96..236088e2dd 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -22,6 +22,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include /* size_t */ @@ -54,17 +58,13 @@ # define AF_UNSPEC 0 #endif -#define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\ - NI_DGRAM) -#define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) - #ifndef HAVE_GAI_STRERROR -static struct +static const struct { - int code; - const char *msg; -} const __gai_errlist[] = + int code; + const char msg[41]; +} gai_errlist[] = { { 0, "Error 0" }, { EAI_BADFLAGS, "Invalid flag used" }, @@ -79,21 +79,21 @@ static struct { EAI_MEMORY, "Memory allocation failure" }, { EAI_OVERFLOW, "Buffer overflow" }, { EAI_SYSTEM, "System error" }, - { 0, NULL } + { 0, "" }, }; -static const char *__gai_unknownerr = "Unrecognized error number"; +static const char gai_unknownerr[] = "Unrecognized error number"; /**************************************************************************** * Converts an EAI_* error code into human readable english text. ****************************************************************************/ const char *vlc_gai_strerror (int errnum) { - for (unsigned i = 0; __gai_errlist[i].msg != NULL; i++) - if (errnum == __gai_errlist[i].code) - return __gai_errlist[i].msg; + for (unsigned i = 0; *gai_errlist[i].msg; i++) + if (errnum == gai_errlist[i].code) + return gai_errlist[i].msg; - return __gai_unknownerr; + return gai_unknownerr; } #else /* ifndef HAVE_GAI_STRERROR */ const char *vlc_gai_strerror (int errnum) @@ -103,9 +103,11 @@ const char *vlc_gai_strerror (int errnum) #endif #ifndef HAVE_GETNAMEINFO +#define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\ + NI_DGRAM) /* * getnameinfo() non-thread-safe IPv4-only implementation, - * Address-family-independant address to hostname translation + * Address-family-independent address to hostname translation * (reverse DNS lookup in case of IPv4). * * This is meant for use on old IP-enabled systems that are not IPv6-aware, @@ -115,9 +117,15 @@ const char *vlc_gai_strerror (int errnum) * GNU C library 2.0.x is known to lack this function, even though it defines * getaddrinfo(). */ +#ifdef WIN32 +static int WSAAPI +getnameinfo (const struct sockaddr *sa, socklen_t salen, + char *host, DWORD hostlen, char *serv, DWORD servlen, int flags) +#else static int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, int hostlen, char *serv, int servlen, int flags) +#endif { if (((size_t)salen < sizeof (struct sockaddr_in)) || (sa->sa_family != AF_INET)) @@ -144,14 +152,14 @@ getnameinfo (const struct sockaddr *sa, socklen_t salen, if (snprintf (host, hostlen, "%u.%u.%u.%u", ipv4 >> 24, (ipv4 >> 16) & 0xff, (ipv4 >> 8) & 0xff, - ipv4 & 0xff) >= hostlen) + ipv4 & 0xff) >= (int)hostlen) return EAI_OVERFLOW; } if (serv != NULL) { if (snprintf (serv, servlen, "%u", - (unsigned int)ntohs (addr->sin_port)) >= servlen) + (unsigned int)ntohs (addr->sin_port)) >= (int)servlen) return EAI_OVERFLOW; } } @@ -161,6 +169,7 @@ getnameinfo (const struct sockaddr *sa, socklen_t salen, #endif /* if !HAVE_GETNAMEINFO */ #ifndef HAVE_GETADDRINFO +#define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) /* * Converts the current herrno error value into an EAI_* error code. * That error code is normally returned by getnameinfo() or getaddrinfo(). @@ -191,7 +200,11 @@ gai_error_from_herrno (void) /* * This functions must be used to free the memory allocated by getaddrinfo(). */ +#ifdef WIN32 +static void WSAAPI freeaddrinfo (struct addrinfo *res) +#else static void freeaddrinfo (struct addrinfo *res) +#endif { if (res != NULL) { @@ -268,16 +281,22 @@ makeipv4info (int type, int proto, u_long ip, u_short port, const char *name) /* * getaddrinfo() non-thread-safe IPv4-only implementation - * Address-family-independant hostname to address resolution. + * Address-family-independent hostname to address resolution. * * This is meant for IPv6-unaware systems that do probably not provide * getaddrinfo(), but still have old function gethostbyname(). * * Only UDP and TCP over IPv4 are supported here. */ +#ifdef WIN32 +static int WSAAPI +getaddrinfo (const char *node, const char *service, + const struct addrinfo *hints, struct addrinfo **res) +#else static int getaddrinfo (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) +#endif { struct addrinfo *info; u_long ip; @@ -383,38 +402,14 @@ getaddrinfo (const char *node, const char *service, port = 0; else { - long d; + unsigned long d; char *end; d = strtoul (service, &end, 0); - if (end[0] /* service is not a number */ - || (d > 65535)) - { - struct servent *entry; - const char *protoname; - - switch (protocol) - { - case IPPROTO_TCP: - protoname = "tcp"; - break; - - case IPPROTO_UDP: - protoname = "udp"; - break; - - default: - protoname = NULL; - } - - entry = getservbyname (service, protoname); - if (entry == NULL) - return EAI_SERVICE; + if (end[0] || (d > 65535u)) + return EAI_SERVICE; - port = entry->s_port; - } - else - port = htons ((u_short)d); + port = htons ((u_short)d); } /* building results... */ @@ -494,43 +489,43 @@ static WSAAPI int _ws2_getnameinfo_bind( const struct sockaddr FAR * sa, socklen char FAR *host, DWORD hostlen, char FAR *serv, DWORD servlen, int flags ) { GETNAMEINFO entry = (GETNAMEINFO)ws2_find_api (TEXT("getnameinfo")); - if (entry != NULL) + int result; + + if (entry == NULL) { - /* call API before replacing function pointer to avoid crash */ - int result = entry (sa, salen, host, hostlen, serv, servlen, flags); - ws2_getnameinfo = entry; - return result; + /* not found, use replacement API instead */ + entry = getnameinfo; + } - return getnameinfo (sa, salen, host, hostlen, serv, servlen, flags); + /* call API before replacing function pointer to avoid crash */ + result = entry (sa, salen, host, hostlen, serv, servlen, flags); + ws2_getnameinfo = entry; + return result; } #undef getnameinfo #define getnameinfo ws2_getnameinfo -/* So much for using different calling conventions */ -static WSAAPI void call_freeaddrinfo (struct addrinfo *infos) -{ - freeaddrinfo (infos); -} - static WSAAPI int _ws2_getaddrinfo_bind(const char FAR *node, const char FAR *service, const struct addrinfo FAR *hints, struct addrinfo FAR * FAR *res) { GETADDRINFO entry; FREEADDRINFO freentry; + int result; entry = (GETADDRINFO)ws2_find_api (TEXT("getaddrinfo")); freentry = (FREEADDRINFO)ws2_find_api (TEXT("freeaddrinfo")); - if ((entry != NULL) && (freentry != NULL)) + if ((entry == NULL) || (freentry == NULL)) { - /* call API before replacing function pointer to avoid crash */ - int result = entry (node, service, hints, res); - ws2_freeaddrinfo = freentry; - ws2_getaddrinfo = entry; - return result; + /* not found, use replacement API instead */ + entry = getaddrinfo; + freentry = freeaddrinfo; } - ws2_freeaddrinfo = call_freeaddrinfo; - return getaddrinfo (node, service, hints, res); + /* call API before replacing function pointer to avoid crash */ + result = entry (node, service, hints, res); + ws2_freeaddrinfo = freentry; + ws2_getaddrinfo = entry; + return result; } #undef getaddrinfo #undef freeaddrinfo @@ -592,29 +587,48 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node, memset (&hints, 0, sizeof (hints)); if (p_hints != NULL) { + const int safe_flags = + AI_PASSIVE | + AI_CANONNAME | + AI_NUMERICHOST | +#ifdef AI_NUMERICSERV + AI_NUMERICSERV | +#endif +#ifdef AI_ALL + AI_ALL | +#endif +#ifdef AI_ADDRCONFIG + AI_ADDRCONFIG | +#endif +#ifdef AI_V4MAPPED + AI_V4MAPPED | +#endif + 0; + hints.ai_family = p_hints->ai_family; hints.ai_socktype = p_hints->ai_socktype; hints.ai_protocol = p_hints->ai_protocol; - hints.ai_flags = p_hints->ai_flags & (AI_NUMERICHOST|AI_PASSIVE); + /* Unfortunately, some flags chang the layout of struct addrinfo, so + * they cannot be copied blindly from p_hints to &hints. Therefore, we + * only copy flags that we know for sure are "safe". + */ + hints.ai_flags = p_hints->ai_flags & safe_flags; } - /* we only ever use port *numbers* */ + +#ifdef AI_NUMERICSERV + /* We only ever use port *numbers* */ hints.ai_flags |= AI_NUMERICSERV; +#endif if( hints.ai_family == AF_UNSPEC ) { - vlc_value_t val; - - var_Create( p_this, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - var_Get( p_this, "ipv4", &val ); - if( val.b_bool ) - hints.ai_family = AF_INET; - #ifdef AF_INET6 - var_Create( p_this, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - var_Get( p_this, "ipv6", &val ); - if( val.b_bool ) + if (var_CreateGetBool (p_this, "ipv6")) hints.ai_family = AF_INET6; + else #endif + if (var_CreateGetBool (p_this, "ipv4")) + hints.ai_family = AF_INET; } /* @@ -660,38 +674,17 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node, hints.ai_flags &= ~AI_NUMERICHOST; } #endif -#if defined (HAVE_GETADDRINFO) -# ifdef AI_IDN +#ifdef AI_IDN /* Run-time I18n Domain Names support */ - static vlc_bool_t b_idn = VLC_TRUE; /* beware of thread-safety */ - - if (b_idn) - { - hints.ai_flags |= AI_IDN; - int ret = getaddrinfo (psz_node, psz_service, &hints, res); - - if (ret != EAI_BADFLAGS) - return ret; + hints.ai_flags |= AI_IDN; + int ret = getaddrinfo (psz_node, psz_service, &hints, res); + if (ret != EAI_BADFLAGS) + return ret; - /* IDN not available: disable and retry without it */ - hints.ai_flags &= ~AI_IDN; - b_idn = VLC_FALSE; - msg_Info (p_this, "International Domain Names not supported"); - } -# endif - return getaddrinfo (psz_node, psz_service, &hints, res); -#else - int ret; - vlc_value_t lock; - - var_Create (p_this->p_libvlc, "getaddrinfo_mutex", VLC_VAR_MUTEX); - var_Get (p_this->p_libvlc, "getaddrinfo_mutex", &lock); - vlc_mutex_lock (lock.p_address); - - ret = getaddrinfo (psz_node, psz_service, &hints, res); - vlc_mutex_unlock (lock.p_address); - return ret; + /* IDN not available: disable and retry without it */ + hints.ai_flags &= ~AI_IDN; #endif + return getaddrinfo (psz_node, psz_service, &hints, res); }