# 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. */
#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)
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
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
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;