split fake getaddrinfo implementation off into a separate file
authorKen Raeburn <raeburn@mit.edu>
Wed, 29 Aug 2001 20:48:07 +0000 (20:48 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 29 Aug 2001 20:48:07 +0000 (20:48 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13687 dc483132-0cff-0310-8789-dd5450dbe970

src/include/ChangeLog
src/include/fake-addrinfo.c [new file with mode: 0644]
src/include/fake-addrinfo.h

index f9b6872f9c6135b8bc92d0a0902a780bb28f085f..ffc8ed42426c16eef8f15b9ed874fff810f15c4b 100644 (file)
@@ -1,3 +1,10 @@
+2001-08-29  Ken Raeburn  <raeburn@mit.edu>
+
+       * fake-addrinfo.c: New file, split off from fake-addrinfo.h.
+       * fake-addrinfo.h: Don't define implementation functions.
+       (FAI_DEFINED): New macro, used to protect against multiple
+       inclusions.
+
 2001-08-03  Ken Raeburn  <raeburn@mit.edu>
 
        * k5-int.h (ss2sin6): New gcc-specific function and alternative
diff --git a/src/include/fake-addrinfo.c b/src/include/fake-addrinfo.c
new file mode 100644 (file)
index 0000000..74be2cf
--- /dev/null
@@ -0,0 +1,270 @@
+#include "fake-addrinfo.h"
+
+#if !defined (HAVE_GETADDRINFO) || defined (BROKEN_GETADDRINFO)
+
+static int translate_h_errno (int h);
+
+static int fai_add_entry (struct addrinfo **result, void *addr, int port,
+                         const struct addrinfo *template)
+{
+    struct addrinfo *n = malloc (sizeof (struct addrinfo));
+    struct sockaddr_in *sin4;
+    if (n == 0)
+       return EAI_MEMORY;
+    if (template->ai_family != AF_INET)
+       return EAI_FAMILY;
+    *n = *template;
+    sin4 = malloc (sizeof (struct sockaddr_in));
+    if (sin4 == 0)
+       return EAI_MEMORY;
+    n->ai_addr = (struct sockaddr *) sin4;
+    sin4->sin_family = AF_INET;
+    sin4->sin_addr = *(struct in_addr *)addr;
+    sin4->sin_port = port;
+#ifdef HAVE_SA_LEN
+    sin4->sin_len = sizeof (struct sockaddr_in);
+#endif
+    n->ai_next = *result;
+    *result = n;
+    return 0;
+}
+
+static int fai_add_hosts_by_name (const char *name, int af,
+                                 struct addrinfo *template,
+                                 int portnum, int flags,
+                                 struct addrinfo **result)
+{
+    struct hostent *hp;
+    int i, r;
+
+    if (af != AF_INET)
+       /* For now, real ipv6 support needs real getaddrinfo.  */
+       return EAI_FAMILY;
+    hp = gethostbyname (name);
+    if (hp == 0)
+       return translate_h_errno (h_errno);
+    for (i = 0; hp->h_addr_list[i]; i++) {
+       r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
+       if (r)
+           return r;
+    }
+    if (*result && (flags & AI_CANONNAME))
+       (*result)->ai_canonname = strdup (hp->h_name);
+    return 0;
+}
+
+int getaddrinfo (const char *name, const char *serv,
+                const struct addrinfo *hint, struct addrinfo **result)
+{
+    struct addrinfo *res = 0;
+    int ret;
+    int port = 0, socktype;
+    int flags;
+    struct addrinfo template;
+
+    if (hint != 0) {
+       if (hint->ai_family != 0 && hint->ai_family != AF_INET)
+           return EAI_NODATA;
+       socktype = hint->ai_socktype;
+       flags = hint->ai_flags;
+    } else {
+       socktype = 0;
+       flags = 0;
+    }
+
+    if (serv) {
+       size_t numlen = strspn (serv, "0123456789");
+       if (serv[numlen] == '\0') {
+           /* pure numeric */
+           unsigned long p = strtoul (serv, 0, 10);
+           if (p == 0 || p > 65535)
+               return EAI_NONAME;
+           port = htons (p);
+       } else {
+           struct servent *sp;
+           int try_dgram_too = 0;
+           if (socktype == 0) {
+               try_dgram_too = 1;
+               socktype = SOCK_STREAM;
+           }
+       try_service_lookup:
+           sp = getservbyname (serv, socktype == SOCK_STREAM ? "tcp" : "udp");
+           if (sp == 0) {
+               if (try_dgram_too) {
+                   socktype = SOCK_DGRAM;
+                   goto try_service_lookup;
+               }
+               return EAI_SERVICE;
+           }
+           port = sp->s_port;
+       }
+    }
+
+    if (name == 0) {
+       name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
+       flags |= AI_NUMERICHOST;
+    }
+
+    template.ai_family = AF_INET;
+    template.ai_addrlen = sizeof (struct sockaddr_in);
+    template.ai_socktype = socktype;
+    template.ai_protocol = 0;
+    template.ai_flags = 0;
+    template.ai_canonname = 0;
+    template.ai_next = 0;
+    template.ai_addr = 0;
+
+    /* If NUMERICHOST is set, parse a numeric address.
+       If it's not set, don't accept such names.  */
+    if (flags & AI_NUMERICHOST) {
+       struct in_addr addr4;
+#if 0
+       ret = inet_aton (name, &addr4);
+       if (ret)
+           return EAI_NONAME;
+#else
+       addr4.s_addr = inet_addr (name);
+       if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
+           /* 255.255.255.255 or parse error, both bad */
+           return EAI_NONAME;
+#endif
+       ret = fai_add_entry (&res, &addr4, port, &template);
+    } else {
+       ret = fai_add_hosts_by_name (name, AF_INET, &template, port, flags,
+                                    &res);
+    }
+
+    if (ret && ret != NO_ADDRESS) {
+       freeaddrinfo (res);
+       return ret;
+    }
+    if (res == 0)
+       return NO_ADDRESS;
+    *result = res;
+    return 0;
+}
+
+int getnameinfo (const struct sockaddr *sa, socklen_t len,
+                char *host, size_t hostlen,
+                char *service, size_t servicelen,
+                int flags)
+{
+    struct hostent *hp;
+    const struct sockaddr_in *sinp;
+    struct servent *sp;
+
+    if (sa->sa_family != AF_INET) {
+       return EAI_FAMILY;
+    }
+    sinp = (const struct sockaddr_in *) sa;
+
+    if (host) {
+       if (flags & NI_NUMERICHOST) {
+           char *p;
+       numeric_host:
+           p = inet_ntoa (sinp->sin_addr);
+           if (strlen (p) < hostlen)
+               strcpy (host, p);
+           else
+               return EAI_FAIL; /* ?? */
+       } else {
+           hp = gethostbyaddr (&sinp->sin_addr, sizeof (struct in_addr),
+                               sa->sa_family);
+           if (hp == 0) {
+               if (h_errno == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
+                   goto numeric_host;
+               return translate_h_errno (h_errno);
+           }
+           if (strlen (hp->h_name) < hostlen)
+               strcpy (host, hp->h_name);
+           else
+               return EAI_FAIL; /* ?? */
+       }
+    }
+
+    if (service) {
+       if (flags & NI_NUMERICSERV) {
+           char numbuf[10];
+           int port;
+       numeric_service:
+           port = ntohs (sinp->sin_port);
+           if (port < 0 || port > 65535)
+               return EAI_FAIL;
+           sprintf (numbuf, "%d", port);
+           if (strlen (numbuf) < servicelen)
+               strcpy (service, numbuf);
+           else
+               return EAI_FAIL;
+       } else {
+           sp = getservbyport (sinp->sin_port,
+                               (flags & NI_DGRAM) ? "udp" : "tcp");
+           if (sp == 0)
+               goto numeric_service;
+           if (strlen (sp->s_name) < servicelen)
+               strcpy (service, sp->s_name);
+           else
+               return EAI_FAIL;
+       }
+    }
+
+    return 0;
+}
+
+void freeaddrinfo (struct addrinfo *ai)
+{
+    struct addrinfo *next;
+    while (ai) {
+       next = ai->ai_next;
+       free (ai->ai_canonname);
+       free (ai->ai_addr);
+       free (ai);
+       ai = next;
+    }
+}
+
+char *gai_strerror (int code)
+{
+    switch (code) {
+    case EAI_ADDRFAMILY: return "address family for nodename not supported";
+    case EAI_AGAIN:    return "temporary failure in name resolution";
+    case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
+    case EAI_FAIL:     return "non-recoverable failure in name resolution";
+    case EAI_FAMILY:   return "ai_family not supported";
+    case EAI_MEMORY:   return "out of memory";
+    case EAI_NODATA:   return "no address associated with hostname";
+    case EAI_NONAME:   return "name does not exist";
+    case EAI_SERVICE:  return "service name not supported for specified socket type";
+    case EAI_SOCKTYPE: return "ai_socktype not supported";
+    case EAI_SYSTEM:   return strerror (errno);
+    default:           return "bogus getaddrinfo error?";
+    }
+}
+
+static int translate_h_errno (int h)
+{
+    switch (h) {
+    case 0:
+       return 0;
+#ifdef NETDB_INTERNAL
+    case NETDB_INTERNAL:
+       if (errno == ENOMEM)
+           return EAI_MEMORY;
+       return EAI_SYSTEM;
+#endif
+    case HOST_NOT_FOUND:
+       return EAI_NONAME;
+    case TRY_AGAIN:
+       return EAI_AGAIN;
+    case NO_RECOVERY:
+       return EAI_FAIL;
+    case NO_DATA:
+#if NO_DATA != NO_ADDRESS
+    case NO_ADDRESS:
+#endif
+       return EAI_NODATA;
+    default:
+       return EAI_SYSTEM;
+    }
+}
+
+#endif
index 08536e9a4a9ff3582a71fa946b7972895418990d..483230d758fa7eacd176de336f2eefdd2d5e6d95 100644 (file)
@@ -1,6 +1,8 @@
+#ifndef FAI_DEFINED
+#define FAI_DEFINED
 #include "port-sockets.h"
 
-#ifndef HAVE_GETADDRINFO
+#if !defined (HAVE_GETADDRINFO) || defined (BROKEN_GETADDRINFO)
 
 #ifndef FAI_PREFIX
 # error "FAI_PREFIX must be defined when fake-addrinfo.h is included"
@@ -100,275 +102,6 @@ void freeaddrinfo (struct addrinfo *ai);
 
 char *gai_strerror (int code);
 
-#ifdef FAI_IMPLEMENTATION
-
-static int translate_h_errno (int h);
-
-static int fai_add_entry (struct addrinfo **result, void *addr, int port,
-                         const struct addrinfo *template)
-{
-    struct addrinfo *n = malloc (sizeof (struct addrinfo));
-    struct sockaddr_in *sin4;
-    if (n == 0)
-       return EAI_MEMORY;
-    if (template->ai_family != AF_INET)
-       return EAI_FAMILY;
-    *n = *template;
-    sin4 = malloc (sizeof (struct sockaddr_in));
-    if (sin4 == 0)
-       return EAI_MEMORY;
-    n->ai_addr = (struct sockaddr *) sin4;
-    sin4->sin_family = AF_INET;
-    sin4->sin_addr = *(struct in_addr *)addr;
-    sin4->sin_port = port;
-#ifdef HAVE_SA_LEN
-    sin4->sin_len = sizeof (struct sockaddr_in);
-#endif
-    n->ai_next = *result;
-    *result = n;
-    return 0;
-}
-
-static int fai_add_hosts_by_name (const char *name, int af,
-                                 struct addrinfo *template,
-                                 int portnum, int flags,
-                                 struct addrinfo **result)
-{
-    struct hostent *hp;
-    int i, r;
-
-    if (af != AF_INET)
-       /* For now, real ipv6 support needs real getaddrinfo.  */
-       return EAI_FAMILY;
-    hp = gethostbyname (name);
-    if (hp == 0)
-       return translate_h_errno (h_errno);
-    for (i = 0; hp->h_addr_list[i]; i++) {
-       r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
-       if (r)
-           return r;
-    }
-    if (*result && (flags & AI_CANONNAME))
-       (*result)->ai_canonname = strdup (hp->h_name);
-    return 0;
-}
-
-int getaddrinfo (const char *name, const char *serv,
-                const struct addrinfo *hint, struct addrinfo **result)
-{
-    struct addrinfo *res = 0;
-    int ret;
-    int port = 0, socktype;
-    int flags;
-    struct addrinfo template;
-
-    if (hint != 0) {
-       if (hint->ai_family != 0 && hint->ai_family != AF_INET)
-           return EAI_NODATA;
-       socktype = hint->ai_socktype;
-       flags = hint->ai_flags;
-    } else {
-       socktype = 0;
-       flags = 0;
-    }
-
-    if (serv) {
-       size_t numlen = strspn (serv, "0123456789");
-       if (serv[numlen] == '\0') {
-           /* pure numeric */
-           unsigned long p = strtoul (serv, 0, 10);
-           if (p == 0 || p > 65535)
-               return EAI_NONAME;
-           port = htons (p);
-       } else {
-           struct servent *sp;
-           int try_dgram_too = 0;
-           if (socktype == 0) {
-               try_dgram_too = 1;
-               socktype = SOCK_STREAM;
-           }
-       try_service_lookup:
-           sp = getservbyname (serv, socktype == SOCK_STREAM ? "tcp" : "udp");
-           if (sp == 0) {
-               if (try_dgram_too) {
-                   socktype = SOCK_DGRAM;
-                   goto try_service_lookup;
-               }
-               return EAI_SERVICE;
-           }
-           port = sp->s_port;
-       }
-    }
-
-    if (name == 0) {
-       name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
-       flags |= AI_NUMERICHOST;
-    }
-
-    template.ai_family = AF_INET;
-    template.ai_addrlen = sizeof (struct sockaddr_in);
-    template.ai_socktype = socktype;
-    template.ai_protocol = 0;
-    template.ai_flags = 0;
-    template.ai_canonname = 0;
-    template.ai_next = 0;
-    template.ai_addr = 0;
-
-    /* If NUMERICHOST is set, parse a numeric address.
-       If it's not set, don't accept such names.  */
-    if (flags & AI_NUMERICHOST) {
-       struct in_addr addr4;
-#if 0
-       ret = inet_aton (name, &addr4);
-       if (ret)
-           return EAI_NONAME;
-#else
-       addr4.s_addr = inet_addr (name);
-       if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
-           /* 255.255.255.255 or parse error, both bad */
-           return EAI_NONAME;
-#endif
-       ret = fai_add_entry (&res, &addr4, port, &template);
-    } else {
-       ret = fai_add_hosts_by_name (name, AF_INET, &template, port, flags,
-                                    &res);
-    }
-
-    if (ret && ret != NO_ADDRESS) {
-       freeaddrinfo (res);
-       return ret;
-    }
-    if (res == 0)
-       return NO_ADDRESS;
-    *result = res;
-    return 0;
-}
-
-int getnameinfo (const struct sockaddr *sa, socklen_t len,
-                char *host, size_t hostlen,
-                char *service, size_t servicelen,
-                int flags)
-{
-    struct hostent *hp;
-    const struct sockaddr_in *sinp;
-    struct servent *sp;
-
-    if (sa->sa_family != AF_INET) {
-       return EAI_FAMILY;
-    }
-    sinp = (const struct sockaddr_in *) sa;
-
-    if (host) {
-       if (flags & NI_NUMERICHOST) {
-           char *p;
-       numeric_host:
-           p = inet_ntoa (sinp->sin_addr);
-           if (strlen (p) < hostlen)
-               strcpy (host, p);
-           else
-               return EAI_FAIL; /* ?? */
-       } else {
-           hp = gethostbyaddr (&sinp->sin_addr, sizeof (struct in_addr),
-                               AF_INET);
-           if (hp == 0) {
-               if (h_errno == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
-                   goto numeric_host;
-               return translate_h_errno (h_errno);
-           }
-           if (strlen (hp->h_name) < hostlen)
-               strcpy (host, hp->h_name);
-           else
-               return EAI_FAIL; /* ?? */
-       }
-    }
-
-    if (service) {
-       if (flags & NI_NUMERICSERV) {
-           char numbuf[10];
-           int port;
-       numeric_service:
-           port = ntohs (sinp->sin_port);
-           if (port < 0 || port > 65535)
-               return EAI_FAIL;
-           sprintf (numbuf, "%d", port);
-           if (strlen (numbuf) < servicelen)
-               strcpy (service, numbuf);
-           else
-               return EAI_FAIL;
-       } else {
-           sp = getservbyport (sinp->sin_port,
-                               (flags & NI_DGRAM) ? "udp" : "tcp");
-           if (sp == 0)
-               goto numeric_service;
-           if (strlen (sp->s_name) < servicelen)
-               strcpy (service, sp->s_name);
-           else
-               return EAI_FAIL;
-       }
-    }
-
-    return 0;
-}
-
-void freeaddrinfo (struct addrinfo *ai)
-{
-    struct addrinfo *next;
-    while (ai) {
-       next = ai->ai_next;
-       free (ai->ai_canonname);
-       free (ai->ai_addr);
-       free (ai);
-       ai = next;
-    }
-}
-
-char *gai_strerror (int code)
-{
-    switch (code) {
-    case EAI_ADDRFAMILY: return "address family for nodename not supported";
-    case EAI_AGAIN:    return "temporary failure in name resolution";
-    case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
-    case EAI_FAIL:     return "non-recoverable failure in name resolution";
-    case EAI_FAMILY:   return "ai_family not supported";
-    case EAI_MEMORY:   return "out of memory";
-    case EAI_NODATA:   return "no address associated with hostname";
-    case EAI_NONAME:   return "name does not exist";
-    case EAI_SERVICE:  return "service name not supported for specified socket type";
-    case EAI_SOCKTYPE: return "ai_socktype not supported";
-    case EAI_SYSTEM:   return strerror (errno);
-    default:           return "bogus getaddrinfo error?";
-    }
-}
-
-static int translate_h_errno (int h)
-{
-    switch (h) {
-    case 0:
-       return 0;
-#ifdef NETDB_INTERNAL
-    case NETDB_INTERNAL:
-       if (errno == ENOMEM)
-           return EAI_MEMORY;
-       return EAI_SYSTEM;
-#endif
-    case HOST_NOT_FOUND:
-       return EAI_NONAME;
-    case TRY_AGAIN:
-       return EAI_AGAIN;
-    case NO_RECOVERY:
-       return EAI_FAIL;
-    case NO_DATA:
-#if NO_DATA != NO_ADDRESS
-    case NO_ADDRESS:
-#endif
-       return EAI_NODATA;
-    default:
-       return EAI_SYSTEM;
-    }
-}
-
-#endif /* FAI_IMPLEMENTATION */
-
 #define HAVE_GETADDRINFO
 #undef  HAVE_GETNAMEINFO
 #define HAVE_GETNAMEINFO
@@ -383,3 +116,5 @@ static int translate_h_errno (int h)
 #ifndef AI_NUMERICHOST
 # define AI_NUMERICHOST 0
 #endif
+
+#endif /* FAI_DEFINED */