From ab0fcbfaaa5a6306ddb9a0abd2b945c160f99629 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 13 Mar 2004 08:47:19 +0000 Subject: Update. 2004-03-13 Ulrich Drepper * resolv/netdb.h (EAI_OVERFLOW): Define. (NI_IDN): Define. * inet/getnameinfo.c (getnameinfo): Return error in case argument buffers overflow. Implement NI_IDN. 2004-03-12 Ulrich Drepper * resolv/netdb.h: Define AI_CANONIDN. * sysdeps/posix/getaddrinfo.c: Implement AI_CANONIDN. --- inet/getnameinfo.c | 61 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 13 deletions(-) (limited to 'inet/getnameinfo.c') diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c index d735bbf9ea..447980d5d9 100644 --- a/inet/getnameinfo.c +++ b/inet/getnameinfo.c @@ -51,6 +51,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifdef HAVE_LIBIDN +# include +extern int __idna_to_unicode_lzlz (const char *input, char **output, + int flags); +#endif + #ifndef min # define min(x,y) (((x) > (y)) ? (y) : (x)) #endif /* min */ @@ -160,7 +166,11 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, struct hostent th; int ok = 0; - if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)) + if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM +#ifdef HAVE_LIBIDN + |NI_IDN +#endif + )) return EAI_BADFLAGS; if (sa == NULL || addrlen < sizeof (sa_family_t)) @@ -244,18 +254,39 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, && (c = nrl_domainname ()) && (c = strstr (h->h_name, c)) && (c != h->h_name) && (*(--c) == '.')) + /* Terminate the string after the prefix. */ + *c = '\0'; + +#ifdef HAVE_LIBIDN + /* If requested, convert from the IDN format. */ + if (flags & NI_IDN) { - strncpy (host, h->h_name, - min(hostlen, (size_t) (c - h->h_name))); - host[min(hostlen - 1, (size_t) (c - h->h_name))] - = '\0'; - ok = 1; - } - else - { - strncpy (host, h->h_name, hostlen); - ok = 1; + char *out; + int rc = __idna_to_unicode_lzlz (h->h_name, &out, 0); + if (rc != IDNA_SUCCESS) + { + if (rc == IDNA_MALLOC_ERROR) + return EAI_MEMORY; + if (rc == IDNA_DLOPEN_ERROR) + return EAI_SYSTEM; + return EAI_IDN_ENCODE; + } + + if (out != h->h_name) + { + h->h_name = strdupa (out); + free (out); + } } +#endif + + size_t len = strlen (h->h_name) + 1; + if (len > hostlen) + return EAI_OVERFLOW; + + memcpy (host, h->h_name, len); + + ok = 1; } } @@ -390,8 +421,12 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, break; } } - __snprintf (serv, servlen, "%d", - ntohs (((const struct sockaddr_in *) sa)->sin_port)); + + if (__snprintf (serv, servlen, "%d", + ntohs (((const struct sockaddr_in *) sa)->sin_port)) + + 1 > servlen) + return EAI_OVERFLOW; + break; case AF_LOCAL: -- cgit v1.2.3