This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 345643d5ae4 libs/libc/netdb: default ai_protocol and multi-transport 
in getaddrinfo
345643d5ae4 is described below

commit 345643d5ae409f288e311bc8f400820cf382a9b8
Author: Swatantra Yadav <[email protected]>
AuthorDate: Fri Oct 16 00:09:23 2026 +0530

    libs/libc/netdb: default ai_protocol and multi-transport in getaddrinfo
    
    When getaddrinfo() is called with hints->ai_socktype set to
    SOCK_STREAM or SOCK_DGRAM and hints->ai_protocol set to 0,
    standard networking implementations (KAME, BSD, glibc, musl)
    populate ai_protocol with IPPROTO_TCP or IPPROTO_UDP
    respectively.
    
    Previously, NuttX left ai_protocol as 0, which broke applications
    and runtimes (such as WAMR) that validate or rely on standard
    ai_protocol values.
    
    Furthermore, POSIX requires that when both ai_socktype and
    ai_protocol are unspecified (0), getaddrinfo() returns all
    supported transports (e.g., both SOCK_STREAM/IPPROTO_TCP and
    SOCK_DGRAM/IPPROTO_UDP) for each resolved address.
    
    This patch:
    1. Normalizes ai_protocol to IPPROTO_TCP for SOCK_STREAM and
       IPPROTO_UDP for SOCK_DGRAM when ai_protocol is 0 under Internet
       address families (AF_INET, AF_INET6, AF_UNSPEC).
    2. Validates compatibility between ai_socktype and ai_protocol,
       returning EAI_SOCKTYPE for incompatible combinations.
    3. Preserves explicit non-zero ai_protocol values without
       overwriting them during service resolution.
    4. Returns separate records for all supported transports (both TCP
       and UDP) when ai_socktype and ai_protocol are 0.
    5. Rejects SOCK_RAW with EAI_SERVICE when resolving named services.
    
    Resolves #16693
    Signed-off-by: Swatantra Yadav <[email protected]>
---
 libs/libc/netdb/lib_getaddrinfo.c | 503 ++++++++++++++++++++++----------------
 1 file changed, 288 insertions(+), 215 deletions(-)

diff --git a/libs/libc/netdb/lib_getaddrinfo.c 
b/libs/libc/netdb/lib_getaddrinfo.c
index fe1cb844a48..ceb8f8953f6 100644
--- a/libs/libc/netdb/lib_getaddrinfo.c
+++ b/libs/libc/netdb/lib_getaddrinfo.c
@@ -30,15 +30,24 @@
 #include <string.h>
 
 #include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
 #include <nuttx/net/loopback.h>
 #include <netpacket/rpmsg.h>
 #include <netpacket/vm_sockets.h>
-#include <netdb.h>
 #include <sys/un.h>
 
 #include "libc.h"
 #include "lib_netdb.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define AI_VALID_FLAGS (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | \
+                        AI_NUMERICSERV | AI_V4MAPPED | AI_ALL | \
+                        AI_ADDRCONFIG)
+
 /****************************************************************************
  * Private Data Types
  ****************************************************************************/
@@ -56,70 +65,100 @@ struct ai_s
   } sa;
 };
 
+struct transport_s
+{
+  int socktype;
+  int proto;
+  int port;
+};
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
-FAR static struct ai_s *alloc_ai(int family, int socktype, int protocol,
-                                 int port, FAR const void *addr)
+/****************************************************************************
+ * Name: add_transports
+ ****************************************************************************/
+
+static FAR struct addrinfo **
+add_transports(FAR struct addrinfo **prev_ai, int family,
+               FAR const struct transport_s *transports,
+               int ntransports, FAR const void *addr,
+               FAR const char *canonname)
 {
   FAR struct ai_s *ai;
+  int t;
 
-  ai = lib_zalloc(sizeof(struct ai_s));
-  if (ai == NULL)
+  for (t = 0; t < ntransports; t++)
     {
-      return ai;
-    }
+      ai = lib_zalloc(sizeof(struct ai_s));
+      if (ai == NULL)
+        {
+          return NULL;
+        }
 
-  ai->ai.ai_addr     = (FAR struct sockaddr *)&ai->sa;
-  ai->ai.ai_family   = family;
-  ai->ai.ai_socktype = socktype;
-  ai->ai.ai_protocol = protocol;
+      ai->ai.ai_addr      = (FAR struct sockaddr *)&ai->sa;
+      ai->ai.ai_family    = family;
+      ai->ai.ai_socktype  = transports[t].socktype;
+      ai->ai.ai_protocol  = transports[t].proto;
+      ai->ai.ai_canonname = (FAR char *)canonname;
 
-  switch (family)
-    {
+      switch (family)
+        {
 #ifdef CONFIG_NET_LOCAL
-      case AF_LOCAL:
-        ai->ai.ai_addrlen       = sizeof(struct sockaddr_un);
-        ai->sa.sun.sun_family   = AF_LOCAL;
-        strlcpy(ai->sa.sun.sun_path, addr, sizeof(ai->sa.sun.sun_path));
-        break;
+          case AF_LOCAL:
+            ai->ai.ai_addrlen     = sizeof(struct sockaddr_un);
+            ai->sa.sun.sun_family = AF_LOCAL;
+            strlcpy(ai->sa.sun.sun_path, addr, sizeof(ai->sa.sun.sun_path));
+            break;
 #endif
 #ifdef CONFIG_NET_IPv4
-      case AF_INET:
-        ai->ai.ai_addrlen       = sizeof(struct sockaddr_in);
-        ai->sa.sin.sin_family   = AF_INET;
-        ai->sa.sin.sin_port     = port;  /* Already network order */
-        memcpy(&ai->sa.sin.sin_addr, addr, sizeof(ai->sa.sin.sin_addr));
-        break;
+          case AF_INET:
+            ai->ai.ai_addrlen     = sizeof(struct sockaddr_in);
+            ai->sa.sin.sin_family = AF_INET;
+            ai->sa.sin.sin_port   = transports[t].port;
+            if (addr != NULL)
+              {
+                memcpy(&ai->sa.sin.sin_addr, addr, sizeof(struct in_addr));
+              }
+            break;
 #endif
 #ifdef CONFIG_NET_IPv6
-      case AF_INET6:
-        ai->ai.ai_addrlen       = sizeof(struct sockaddr_in6);
-        ai->sa.sin6.sin6_family = AF_INET6;
-        ai->sa.sin6.sin6_port   = port;  /* Already network order */
-        memcpy(&ai->sa.sin6.sin6_addr, addr, sizeof(ai->sa.sin6.sin6_addr));
-        break;
+          case AF_INET6:
+            ai->ai.ai_addrlen       = sizeof(struct sockaddr_in6);
+            ai->sa.sin6.sin6_family = AF_INET6;
+            ai->sa.sin6.sin6_port   = transports[t].port;
+            if (addr != NULL)
+              {
+                memcpy(&ai->sa.sin6.sin6_addr, addr,
+                       sizeof(struct in6_addr));
+              }
+            break;
 #endif
 #ifdef CONFIG_NET_RPMSG
-      case AF_RPMSG:
-        ai->ai.ai_addrlen       = sizeof(struct sockaddr_rpmsg);
-        ai->sa.srp.rp_family    = AF_RPMSG;
-        strlcpy(ai->sa.srp.rp_cpu, addr, sizeof(ai->sa.srp.rp_cpu));
-        snprintf(ai->sa.srp.rp_name, sizeof(ai->sa.srp.rp_name), "%d", port);
-        break;
+          case AF_RPMSG:
+            ai->ai.ai_addrlen     = sizeof(struct sockaddr_rpmsg);
+            ai->sa.srp.rp_family  = AF_RPMSG;
+            strlcpy(ai->sa.srp.rp_cpu, addr, sizeof(ai->sa.srp.rp_cpu));
+            snprintf(ai->sa.srp.rp_name, sizeof(ai->sa.srp.rp_name), "%d",
+                     transports[t].port);
+            break;
 #endif
 #ifdef CONFIG_NET_VSOCK
-      case AF_VSOCK:
-        ai->ai.ai_addrlen     = sizeof(struct sockaddr_vm);
-        ai->sa.svm.svm_family = AF_VSOCK;
-        ai->sa.svm.svm_cid    = strtoul(addr, NULL, 0);
-        ai->sa.svm.svm_port   = ntohl(port);
-        break;
+          case AF_VSOCK:
+            ai->ai.ai_addrlen     = sizeof(struct sockaddr_vm);
+            ai->sa.svm.svm_family = AF_VSOCK;
+            ai->sa.svm.svm_cid    = strtoul(addr, NULL, 0);
+            ai->sa.svm.svm_port   = ntohl(transports[t].port);
+            break;
 #endif
+        }
+
+      *prev_ai = (FAR struct addrinfo *)ai;
+      prev_ai  = &ai->ai.ai_next;
     }
 
-  return ai;
+  return prev_ai;
 }
 
 /****************************************************************************
@@ -133,18 +172,17 @@ FAR static struct ai_s *alloc_ai(int family, int 
socktype, int protocol,
 int getaddrinfo(FAR const char *hostname, FAR const char *servname,
                 FAR const struct addrinfo *hint, FAR struct addrinfo **res)
 {
+  FAR const char *canon = NULL;
+  FAR char *hostbuffer = NULL;
+  FAR struct addrinfo **prev_ai = res;
+  struct hostent_s host;
+  struct transport_s transports[2];
+  int ntransports = 0;
   int family = AF_UNSPEC;
-  int port = 0;
   int flags = 0;
   int proto = 0;
   int socktype = 0;
-  FAR char *hostbuffer;
-  struct hostent_s host;
-  FAR struct ai_s *ai;
-  FAR struct ai_s *prev_ai = NULL;
-  const int valid_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST |
-                          AI_NUMERICSERV | AI_V4MAPPED | AI_ALL |
-                          AI_ADDRCONFIG;
+  int port = 0;
   int ret = OK;
   int i;
 
@@ -153,33 +191,85 @@ int getaddrinfo(FAR const char *hostname, FAR const char 
*servname,
       return EAI_NONAME;
     }
 
-  if (hint)
+  if (hint != NULL)
     {
       family   = hint->ai_family;
       flags    = hint->ai_flags;
       proto    = hint->ai_protocol;
       socktype = hint->ai_socktype;
 
-      if ((flags & valid_flags) != flags)
+      if ((flags & AI_VALID_FLAGS) != flags)
         {
           return EAI_BADFLAGS;
         }
 
-      if (family != AF_INET &&
-          family != AF_INET6 &&
-          family != AF_LOCAL &&
-          family != AF_RPMSG &&
-          family != AF_VSOCK &&
-          family != AF_UNSPEC)
+      switch (family)
+        {
+#ifdef CONFIG_NET_IPv4
+          case AF_INET:
+#endif
+#ifdef CONFIG_NET_IPv6
+          case AF_INET6:
+#endif
+#ifdef CONFIG_NET_LOCAL
+          case AF_LOCAL:
+#endif
+#ifdef CONFIG_NET_RPMSG
+          case AF_RPMSG:
+#endif
+#ifdef CONFIG_NET_VSOCK
+          case AF_VSOCK:
+#endif
+          case AF_UNSPEC:
+            break;
+          default:
+            return EAI_FAMILY;
+        }
+
+      if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC)
         {
-          return EAI_FAMILY;
+          if (socktype == SOCK_STREAM)
+            {
+              if (proto == 0)
+                {
+                  proto = IPPROTO_TCP;
+                }
+              else if (proto != IPPROTO_TCP)
+                {
+                  return EAI_SOCKTYPE;
+                }
+            }
+          else if (socktype == SOCK_DGRAM)
+            {
+              if (proto == 0)
+                {
+                  proto = IPPROTO_UDP;
+                }
+              else if (proto != IPPROTO_UDP)
+                {
+                  return EAI_SOCKTYPE;
+                }
+            }
+          else if (socktype == 0)
+            {
+              if (proto == IPPROTO_TCP)
+                {
+                  socktype = SOCK_STREAM;
+                }
+              else if (proto == IPPROTO_UDP)
+                {
+                  socktype = SOCK_DGRAM;
+                }
+            }
+          else if (socktype != SOCK_RAW)
+            {
+              return EAI_SOCKTYPE;
+            }
         }
     }
 
   if (servname != NULL)
     {
-      struct servent ent;
-      FAR struct servent *sp;
       FAR char *endp;
 
       port = strtol(servname, &endp, 10);
@@ -193,186 +283,189 @@ int getaddrinfo(FAR const char *hostname, FAR const 
char *servname,
         {
           return EAI_NONAME;
         }
-      else if (getservbyname_r(servname, NULL, &ent, NULL, 0, &sp) == OK)
+      else
         {
-          /* The s_port field of struct servent is required to
-           * be in network byte order (per OpenGroup.org)
-           */
+          struct servent ent;
+          FAR struct servent *sp;
+
+          if (socktype == SOCK_RAW ||
+              (proto != 0 && proto != IPPROTO_TCP && proto != IPPROTO_UDP))
+            {
+              return EAI_SERVICE;
+            }
 
-          port = sp->s_port;
+          if (socktype != SOCK_DGRAM && proto != IPPROTO_UDP &&
+              getservbyname_r(servname, "tcp", &ent, NULL, 0, &sp) == OK)
+            {
+              transports[ntransports].socktype = SOCK_STREAM;
+              transports[ntransports].proto    = IPPROTO_TCP;
+              transports[ntransports++].port   = sp->s_port;
+            }
+
+          if (socktype != SOCK_STREAM && proto != IPPROTO_TCP &&
+              getservbyname_r(servname, "udp", &ent, NULL, 0, &sp) == OK)
+            {
+              transports[ntransports].socktype = SOCK_DGRAM;
+              transports[ntransports].proto    = IPPROTO_UDP;
+              transports[ntransports++].port   = sp->s_port;
+            }
+
+          if (ntransports == 0)
+            {
+              return EAI_SERVICE;
+            }
+
+          port = transports[0].port;
+          if (ntransports == 1)
+            {
+              socktype = transports[0].socktype;
+              proto    = transports[0].proto;
+            }
+        }
+    }
+
+  if (ntransports == 0)
+    {
+      if (socktype == 0 && proto == 0)
+        {
+          transports[0].socktype = SOCK_STREAM;
+          transports[0].proto    = IPPROTO_TCP;
+          transports[0].port     = port;
+          transports[1].socktype = SOCK_DGRAM;
+          transports[1].proto    = IPPROTO_UDP;
+          transports[1].port     = port;
+          ntransports            = 2;
         }
       else
         {
-          return EAI_SERVICE;
+          transports[0].socktype = (socktype != 0) ? socktype : SOCK_RAW;
+          transports[0].proto    = (proto != 0) ? proto :
+                                   (transports[0].socktype == SOCK_STREAM ?
+                                    IPPROTO_TCP : 0);
+          transports[0].port     = port;
+          ntransports            = 1;
         }
     }
 
-  *res = NULL;
+  /* Override transports for local socket families */
+
+#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_RPMSG) || \
+    defined(CONFIG_NET_VSOCK)
+  if (family == AF_LOCAL || family == AF_RPMSG || family == AF_VSOCK)
+    {
+      transports[0].socktype = socktype;
+      transports[0].proto    = proto;
+      transports[0].port     = port;
+      ntransports            = 1;
+    }
+#endif
 
-  /* If hostname is not NULL, then the AI_PASSIVE flag is ignored. */
+  *res = NULL;
 
-  if ((flags & AI_PASSIVE) != 0 && hostname == NULL)
+  if (hostname == NULL)
     {
-#ifdef CONFIG_NET_IPv4
-      if (family == AF_INET || family == AF_UNSPEC)
+#if !defined(CONFIG_NET_LOOPBACK) && !defined(CONFIG_NET_VSOCK)
+      if ((flags & AI_PASSIVE) == 0)
         {
-          struct in_addr addr;
-
-          memset(&addr, 0, sizeof(struct in_addr));
-          ai = alloc_ai(AF_INET, socktype, proto, port, &addr);
-          if (ai != NULL)
-            {
-              *res = (FAR struct addrinfo *)ai;
-            }
+          return EAI_FAIL;
         }
 #endif
 
-#ifdef CONFIG_NET_IPv6
-      if (family == AF_INET6 || family == AF_UNSPEC)
+#ifdef CONFIG_NET_IPv4
+      if (family == AF_INET || family == AF_UNSPEC)
         {
-          struct in6_addr addr;
+          FAR const void *addr = NULL;
 
-          memset(&addr, 0, sizeof(struct in6_addr));
-          ai = alloc_ai(AF_INET6, socktype, proto, port, &addr);
-          if (ai != NULL)
+#ifdef CONFIG_NET_LOOPBACK
+          if ((flags & AI_PASSIVE) == 0)
             {
-              /* Can return both IPv4 and IPv6 loopback. */
-
-              if (*res != NULL)
-                {
-                  (*res)->ai_next = (FAR struct addrinfo *)ai;
-                }
-              else
-                {
-                  *res = (FAR struct addrinfo *)ai;
-                }
+              addr = &g_lo_ipv4addr;
             }
-        }
 #endif
 
-#if defined(CONFIG_NET_RPMSG)
-      if (family == AF_RPMSG || family == AF_UNSPEC)
-        {
-          ai = alloc_ai(AF_RPMSG, socktype, proto, port, "");
-          if (ai != NULL)
+          if ((flags & AI_PASSIVE) != 0 || addr != NULL)
             {
-              if (*res != NULL)
-                {
-                  (*res)->ai_next = (FAR struct addrinfo *)ai;
-                }
-              else
+              prev_ai = add_transports(prev_ai, AF_INET, transports,
+                                       ntransports, addr, NULL);
+              if (prev_ai == NULL)
                 {
-                  *res = (FAR struct addrinfo *)ai;
+                  goto errout_nomem;
                 }
             }
         }
 #endif
 
-#if defined(CONFIG_NET_VSOCK)
-      if (family == AF_VSOCK || family == AF_UNSPEC)
+#ifdef CONFIG_NET_IPv6
+      if (family == AF_INET6 || family == AF_UNSPEC)
         {
-          /* "-1" <--> VMADDR_CID_ANY */
+          FAR const void *addr = NULL;
 
-          ai = alloc_ai(AF_VSOCK, socktype, proto, port, "-1");
-          if (ai != NULL)
+#ifdef CONFIG_NET_LOOPBACK
+          if ((flags & AI_PASSIVE) == 0)
             {
-              if (*res != NULL)
-                {
-                  (*res)->ai_next = (FAR struct addrinfo *)ai;
-                }
-              else
-                {
-                  *res = (FAR struct addrinfo *)ai;
-                }
+              addr = &g_lo_ipv6addr;
             }
-        }
 #endif
 
-      return (*res != NULL) ? OK : EAI_MEMORY;
-    }
-
-  if (hostname == NULL)
-    {
-#ifdef CONFIG_NET_LOOPBACK
-      /* Local service. */
-
-#ifdef CONFIG_NET_IPv4
-      if (family == AF_INET || family == AF_UNSPEC)
-        {
-          ai = alloc_ai(AF_INET, socktype, proto, port,
-                        &g_lo_ipv4addr);
-          if (ai != NULL)
+          if ((flags & AI_PASSIVE) != 0 || addr != NULL)
             {
-              *res = (FAR struct addrinfo *)ai;
+              prev_ai = add_transports(prev_ai, AF_INET6, transports,
+                                       ntransports, addr, NULL);
+              if (prev_ai == NULL)
+                {
+                  goto errout_nomem;
+                }
             }
         }
 #endif
 
-#ifdef CONFIG_NET_IPv6
-      if (family == AF_INET6 || family == AF_UNSPEC)
+#if defined(CONFIG_NET_RPMSG)
+      if (((flags & AI_PASSIVE) != 0) &&
+          (family == AF_RPMSG || family == AF_UNSPEC))
         {
-          ai = alloc_ai(AF_INET6, socktype, proto, port,
-                        &g_lo_ipv6addr);
-          if (ai != NULL)
+          prev_ai = add_transports(prev_ai, AF_RPMSG, transports,
+                                   ntransports, "", NULL);
+          if (prev_ai == NULL)
             {
-              /* Can return both IPv4 and IPv6 loopback. */
-
-              if (*res != NULL)
-                {
-                  (*res)->ai_next = (FAR struct addrinfo *)ai;
-                }
-              else
-                {
-                  *res = (FAR struct addrinfo *)ai;
-                }
+              goto errout_nomem;
             }
         }
 #endif
-#endif
 
 #if defined(CONFIG_NET_VSOCK)
       if (family == AF_VSOCK || family == AF_UNSPEC)
         {
-          /* "1" <--> VMADDR_CID_LOCAL */
+          FAR const char *cid = ((flags & AI_PASSIVE) != 0) ? "-1" : "1";
 
-          ai = alloc_ai(AF_VSOCK, socktype, proto, port, "1");
-          if (ai != NULL)
+          prev_ai = add_transports(prev_ai, AF_VSOCK, transports,
+                                   ntransports, cid, NULL);
+          if (prev_ai == NULL)
             {
-              if (*res != NULL)
-                {
-                  (*res)->ai_next = (FAR struct addrinfo *)ai;
-                }
-              else
-                {
-                  *res = (FAR struct addrinfo *)ai;
-                }
+              goto errout_nomem;
             }
         }
 #endif
 
-#if defined(CONFIG_NET_LOOPBACK) || defined(CONFIG_NET_VSOCK)
-      return (*res != NULL) ? OK : EAI_MEMORY;
-#else
-      /* Local service, but no loopback so cannot succeed. */
+      return (*res != NULL) ? OK : EAI_NONAME;
+    }
 
-      return EAI_FAIL;
-#endif
+  if ((flags & AI_CANONNAME) != 0)
+    {
+      canon = hostname;
     }
 
-#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_RPMSG) || 
defined(CONFIG_NET_VSOCK)
+#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_RPMSG) || \
+    defined(CONFIG_NET_VSOCK)
   if (family == AF_LOCAL || family == AF_RPMSG || family == AF_VSOCK)
     {
-      ai = alloc_ai(family, socktype, proto, port, hostname);
-      if (ai != NULL)
+      prev_ai = add_transports(prev_ai, family, transports,
+                               ntransports, hostname, canon);
+      if (prev_ai == NULL)
         {
-          *res = (FAR struct addrinfo *)ai;
-          if (flags & AI_CANONNAME)
-            {
-              ai->ai.ai_canonname = (FAR char *)hostname;
-            }
+          goto errout_nomem;
         }
 
-      return (*res != NULL) ? OK : EAI_MEMORY;
+      return OK;
     }
 #endif
 
@@ -399,46 +492,26 @@ int getaddrinfo(FAR const char *hostname, FAR const char 
*servname,
           continue;
         }
 
-      /* REVISIT: filter by socktype and protocol not implemented. */
-
-      ai = alloc_ai(host.h_addrtypes[i], socktype, proto, port,
-                    host.h_addr_list[i]);
-      if (ai == NULL)
+      prev_ai = add_transports(prev_ai, host.h_addrtypes[i],
+                               transports, ntransports,
+                               host.h_addr_list[i], canon);
+      if (prev_ai == NULL)
         {
-          if (*res)
-            {
-              freeaddrinfo(*res);
-            }
-
-          lib_free(hostbuffer);
-          return EAI_MEMORY;
+          goto errout_nomem;
         }
+    }
 
-      /* REVISIT: grok canonical name.
-       *
-       * OpenGroup: "if the canonical name is not available, then
-       * ai_canonname shall refer to the hostname argument or a string
-       * with the same contents."
-       */
-
-      ai->ai.ai_canonname = (FAR char *)hostname;
-
-      /* Add result to linked list.
-       * TODO: RFC 3484/6724 destination address sort not implemented.
-       */
-
-      if (prev_ai != NULL)
-        {
-          prev_ai->ai.ai_next = (FAR struct addrinfo *)ai;
-        }
-      else
-        {
-          *res = (FAR struct addrinfo *)ai;
-        }
+  lib_free(hostbuffer);
+  return (*res != NULL) ? OK : EAI_FAMILY;
 
-      prev_ai = ai;
+errout_nomem:
+  if (*res != NULL)
+    {
+      freeaddrinfo(*res);
+      *res = NULL;
     }
 
   lib_free(hostbuffer);
-  return (*res != NULL) ? OK : EAI_FAMILY;
+
+  return EAI_MEMORY;
 }

Reply via email to