Fix getaddrinfo under solaris (for multiprotocol case)
authorAzat Khuzhin <azat@solaris.azat>
Mon, 9 May 2016 22:34:28 +0000 (22:34 +0000)
committerAzat Khuzhin <a3at.mail@gmail.com>
Wed, 10 Aug 2016 08:15:15 +0000 (11:15 +0300)
During testing on solaris 11.3, util/getaddrinfo failed at:
  memset(&hints, 0, sizeof(hints));
  hints.ai_flags = EVUTIL_AI_NUMERICHOST;
  r = evutil_getaddrinfo("1.2.3.4", NULL, &hints, &ai);
  tt_assert(ai_find_by_protocol(ai, IPPROTO_TCP));

And this is because solaris's getaddrinfo() returns:
$6 = {
  ai_flags = 32,
  ai_family = 2,
  ai_socktype = 0,
  ai_protocol = 0, <-- no proto
  ai_addrlen = 16,
  ai_canonname = 0x0,
  ai_addr = 0x815d658,
  ai_next = 0x0 <-- nothing else
}

So we should emulate this too.

Plus introduce helper that will search through all results, not only first one.

Fixes: util/getaddrinfo
Fixes: #354
evutil.c

index 06b4e94882a6dbd21eb4d4d4c316a4613eceb105..7339d6105a54d8e1b77a0354cccdb917b1646b17 100644 (file)
--- a/evutil.c
+++ b/evutil.c
@@ -1238,11 +1238,20 @@ static int tested_for_getaddrinfo_hacks=0;
      field set to 0.  We test for this so we can apply an appropriate
      workaround.
 */
+struct evutil_addrinfo *ai_find_protocol(struct evutil_addrinfo *ai)
+{
+       while (ai) {
+               if (ai->ai_protocol)
+                       return ai;
+               ai = ai->ai_next;
+       }
+       return NULL;
+}
 static void
 test_for_getaddrinfo_hacks(void)
 {
        int r, r2;
-       struct evutil_addrinfo *ai=NULL, *ai2=NULL;
+       struct evutil_addrinfo *ai=NULL, *ai2=NULL, *ai3=NULL;
        struct evutil_addrinfo hints;
 
        memset(&hints,0,sizeof(hints));
@@ -1256,12 +1265,13 @@ test_for_getaddrinfo_hacks(void)
 #endif
            0;
        r = getaddrinfo("1.2.3.4", "80", &hints, &ai);
+       getaddrinfo("1.2.3.4", NULL, &hints, &ai3);
        hints.ai_socktype = SOCK_STREAM;
        r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2);
        if (r2 == 0 && r != 0) {
                need_numeric_port_hack_=1;
        }
-       if (ai2 && ai2->ai_protocol == 0) {
+       if (!ai_find_protocol(ai2) || !ai_find_protocol(ai3)) {
                need_socktype_protocol_hack_=1;
        }
 
@@ -1269,6 +1279,8 @@ test_for_getaddrinfo_hacks(void)
                freeaddrinfo(ai);
        if (ai2)
                freeaddrinfo(ai2);
+       if (ai3)
+               freeaddrinfo(ai3);
        tested_for_getaddrinfo_hacks=1;
 }