[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [msmtp-users] msmtp: runtime fails with "Bad value for ai_flags"



Hi Lonnie!

On Wed, 31 Dec 2014 17:00:24 -0600, Lonnie Abelbeck wrote:
> msmtp: cannot locate host foo.example.com: Bad value for ai_flags
> msmtp: could not send mail...
> 
> [...]
>
> So the bottom line seems to be that checking the headers for AI_IDN
> (via autoconf) is not good enough.

This is not good. I asked on the glibc-help mailing list if this is
really intended, and how one is supposed to check if AI_IDN actually
works.

In my opinion, AI_IDN should only be defined if it is actually
supported. Otherwise, you need to build with a fall back code path that
uses libidn, and if you need that anyway, then why bother with an
unreliable AI_IDN? There's nothing to gain, you just make the code less
readable.

> The question is can autoconf determine if glibc was build with
> libidn ?

I did not find a way, except for AC_RUN_IFELSE, which does not work
when cross-compiling.

> Another solution would be a --with-idn configure switch which would
> add a USE_IDN config.h define.

I suggest --enable-gai-idn. The --with-* switches are typically
used to include external libraries.

See the attached patch.

This also allows for future systems that simply support IDN without
having to use AI_IDN (although we then need a way for configure to
detect this). For example, musl plans to support IDN by default
http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Name_Resolver_.2F_DNS).
I think they are right.

An unrelated question: why are you using glibc without IDN support?
Libidn is included in the glibc sources; I cannot see a reason to
disable it.

Regards,
Martin
diff --git a/configure.ac b/configure.ac
index 8205335..95fd2e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,33 +136,45 @@ if test "$libgsasl" != "no"; then
 fi
 AM_CONDITIONAL([HAVE_LIBGSASL], [test "$libgsasl" = "yes"])
 
-dnl Do we need libidn for IDN support? Modern systems don't.
-want_libidn=yes
-AC_CHECK_DECL([AI_IDN], [], [], [#include <netdb.h>])
-if test "$ac_cv_have_decl_AI_IDN" = "yes"; then
-    if test "$have_tls" = "no"; then
-        want_libidn=no
-    elif test "$tls_lib" = "GnuTLS"; then
-        gnutls_has_idn=no
-        AC_MSG_CHECKING([if GnuTLS has builtin IDN support])
-        CFLAGS_BAK="$CFLAGS"
-        CFLAGS="$CFLAGS $tls_CFLAGS"
-        AC_COMPILE_IFELSE(
-            [AC_LANG_PROGRAM([[
-             #include <gnutls/gnutls.h>
-             #if GNUTLS_VERSION_NUMBER < 0x030400
-              error: GnuTLS does not have builtin IDN support
-             #endif]],
-            [[int x = 0;]])],
-            [gnutls_has_idn="yes"], [])
-        CFLAGS="$CFLAGS_BAK"
-        AC_MSG_RESULT([$gnutls_has_idn])
-        if test "$gnutls_has_idn" = "yes"; then
-            want_libidn=no
-        fi
+dnl Check if getaddrinfo() has IDN support (and we want to use it)
+AC_ARG_ENABLE([gai-idn],
+    [AS_HELP_STRING([--enable-gai-idn], [Use IDN support from getaddrinfo if available. Enabled by default.])],
+    [if test "$enableval" = "yes"; then want_gai_idn="yes"; else want_gai_idn="no"; fi], [want_gai_idn="yes"])
+have_gai_idn=no
+if test "$want_gai_idn" = "yes"; then
+    AC_CHECK_DECL([AI_IDN], [], [], [#include <netdb.h>])
+    if test "$ac_cv_have_decl_AI_IDN" = "yes"; then
+        have_gai_idn=yes
+        AC_DEFINE([HAVE_GAI_IDN], [1], [Define to 1 if getaddrinfo supports IDN])
     fi
 fi
+
+dnl Check if TLS has IDN support
+have_tls_idn=no
+if test "$tls_lib" = "GnuTLS"; then
+    AC_MSG_CHECKING([if GnuTLS has builtin IDN support])
+    CFLAGS_BAK="$CFLAGS"
+    CFLAGS="$CFLAGS $tls_CFLAGS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[
+         #include <gnutls/gnutls.h>
+         #if GNUTLS_VERSION_NUMBER < 0x030400
+          error: GnuTLS does not have builtin IDN support
+         #endif]],
+        [[int x = 0;]])],
+        [have_tls_idn="yes"], [])
+    CFLAGS="$CFLAGS_BAK"
+    AC_MSG_RESULT([$have_tls_idn])
+fi
+
+dnl Do we need libidn for IDN support? Modern systems don't.
 AC_MSG_CHECKING([if libidn is needed for IDN support])
+want_libidn=no
+if test "$have_gai_idn" = "no"; then
+    want_libidn=yes
+elif test "$have_tls" = "yes" -a "$have_tls_idn" = "no"; then
+    want_libidn=yes
+fi
 AC_MSG_RESULT([$want_libidn])
 
 dnl GNU Libidn
diff --git a/src/net.c b/src/net.c
index eae0948..85644b9 100644
--- a/src/net.c
+++ b/src/net.c
@@ -620,8 +620,10 @@ int net_open_socket(
     hints.ai_addr = NULL;
     hints.ai_next = NULL;
     port_string = xasprintf("%d", port);
-#ifdef AI_IDN
+#ifdef HAVE_GAI_IDN
+# ifdef AI_IDN
     hints.ai_flags |= AI_IDN;
+# endif
 #elif defined(HAVE_LIBIDN)
     idna_to_ascii_lz(hostname, &idn_hostname, 0);
 #endif