diff options
-rw-r--r-- | resolv/netdb.h | 1 | ||||
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 48 |
2 files changed, 44 insertions, 5 deletions
diff --git a/resolv/netdb.h b/resolv/netdb.h index 5aaa387166..238510f0e4 100644 --- a/resolv/netdb.h +++ b/resolv/netdb.h @@ -577,6 +577,7 @@ struct gaicb # define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded in the current locale's character set) before looking it up. */ +# define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */ # endif /* Error values for `getaddrinfo' function. */ diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 2b6f0ba0ac..4597feac79 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -55,8 +55,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <nsswitch.h> #include <not-cancel.h> +#ifdef HAVE_LIBIDN extern int __idna_to_ascii_lz (const char *input, char **output, int flags); -#define IDNA_SUCCESS 0 +extern int __idna_to_unicode_lzlz (const char *input, char **output, + int flags); +# include <libidn/idna.h> +#endif #define GAIH_OKIFUNSPEC 0x0100 #define GAIH_EAI ~(GAIH_OKIFUNSPEC) @@ -548,9 +552,20 @@ gaih_inet (const char *name, const struct gaih_service *service, char *p = NULL; rc = __idna_to_ascii_lz (name, &p, 0); if (rc != IDNA_SUCCESS) - return -EAI_IDN_ENCODE; - name = strdupa (p); - free (p); + { + if (rc == IDNA_MALLOC_ERROR) + return -EAI_MEMORY; + if (rc == IDNA_DLOPEN_ERROR) + return -EAI_SYSTEM; + return -EAI_IDN_ENCODE; + } + /* In case the output string is the same as the input string + no new string has been allocated. */ + if (p != name) + { + name = strdupa (p); + free (p); + } } #endif @@ -820,6 +835,29 @@ gaih_inet (const char *name, const struct gaih_service *service, if (c == NULL) return GAIH_OKIFUNSPEC | -EAI_NONAME; +#ifdef HAVE_LIBIDN + if (req->ai_flags & AI_CANONIDN) + { + char *out; + int rc = __idna_to_unicode_lzlz (c, &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; + } + /* In case the output string is the same as the input + string no new string has been allocated. */ + if (out != c) + { + c = strdupa (out); + free (out); + } + } +#endif + namelen = strlen (c) + 1; } else @@ -1268,7 +1306,7 @@ getaddrinfo (const char *name, const char *service, if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED #ifdef HAVE_LIBIDN - |AI_IDN + |AI_IDN|AI_CANONIDN #endif |AI_ALL)) return EAI_BADFLAGS; |