* hostaddr.c: Include fake-addrinfo.h.
authorKen Raeburn <raeburn@mit.edu>
Thu, 19 Jul 2001 14:17:19 +0000 (14:17 +0000)
committerKen Raeburn <raeburn@mit.edu>
Thu, 19 Jul 2001 14:17:19 +0000 (14:17 +0000)
(FAI_PREFIX): Define macro.
(krb5_os_hostaddr): Use getaddrinfo, to get ipv6 support and thread safety.
Support numeric addresses as well.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13617 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/hostaddr.c

index 8688b92d4e4683142925a8081613ec6cea8a2308..5a4aeec93fe0903d835aa4f15f7e5fb3924782fb 100644 (file)
@@ -1,5 +1,10 @@
 2001-07-19  Ken Raeburn  <raeburn@mit.edu>
 
+       * hostaddr.c: Include fake-addrinfo.h.
+       (FAI_PREFIX): Define macro.
+       (krb5_os_hostaddr): Use getaddrinfo, to get ipv6 support and
+       thread safety.  Support numeric addresses as well.
+
        * t_locate_kdc.c: New file.
        * Makefile.in (t_locate_kdc.o, t_locate_kdc): New targets.
 
index 5380caf160ee8bd5f34b17b0215f86f972f8f3b6..f8d5806f53f5291677f428d2d584be11fa34e4a9 100644 (file)
@@ -30,6 +30,9 @@
 #define NEED_SOCKETS
 #include "k5-int.h"
 
+#define FAI_PREFIX krb5int
+#include "fake-addrinfo.h"
+
 krb5_error_code
 krb5_os_hostaddr(context, name, ret_addrs)
     krb5_context context;
@@ -37,47 +40,102 @@ krb5_os_hostaddr(context, name, ret_addrs)
     krb5_address ***ret_addrs;
 {
     krb5_error_code    retval;
-    struct hostent     *hp;
     krb5_address       **addrs;
-    int                        i;
+    int                        i, j, r;
+    struct addrinfo hints, *ai, *aip;
+
+    if (!name)
+       return KRB5_ERR_BAD_HOSTNAME;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_flags = AI_DEFAULT | AI_NUMERICHOST;
+    /* We don't care what kind at this point, really, but without
+       this, we can get back multiple sockaddrs per address, for
+       SOCK_DGRAM, SOCK_STREAM, and SOCK_RAW.  I haven't checked if
+       that's what the spec indicates.  */
+    hints.ai_socktype = SOCK_DGRAM;
 
-    if (!name || !(hp = gethostbyname(name)))
-      return KRB5_ERR_BAD_HOSTNAME;
+    r = getaddrinfo (name, 0, &hints, &ai);
+    if (r) {
+       hints.ai_flags &= ~AI_NUMERICHOST;
+       r = getaddrinfo (name, 0, &hints, &ai);
+    }
+    if (r)
+       return KRB5_ERR_BAD_HOSTNAME;
 
-    /* Count elements */
-    for(i=0; hp->h_addr_list[i]; i++);
+    for (i = 0, aip = ai; aip; aip = aip->ai_next) {
+       switch (aip->ai_addr->sa_family) {
+       case AF_INET:
+#ifdef KRB5_USE_INET6
+       case AF_INET6:
+#endif
+           i++;
+       default:
+           /* Ignore addresses of unknown families.  */
+           ;
+       }
+    }
 
-    addrs = (krb5_address **) malloc ((i+1)*sizeof(*addrs));
+    addrs = malloc ((i+1) * sizeof(*addrs));
     if (!addrs)
-       return ENOMEM;
+       return errno;
 
-    memset(addrs, 0, (i+1)*sizeof(*addrs));
-    
-    for(i=0; hp->h_addr_list[i]; i++) {
+    for (j = 0; j < i + 1; j++)
+       addrs[j] = 0;
+
+    for (i = 0, aip = ai; aip; aip = aip->ai_next) {
+       void *ptr;
+       size_t addrlen;
+       int atype;
+
+       switch (aip->ai_addr->sa_family) {
+       case AF_INET:
+           addrlen = sizeof (struct in_addr);
+           ptr = &((struct sockaddr_in *)aip->ai_addr)->sin_addr;
+           atype = ADDRTYPE_INET;
+           break;
+#ifdef KRB5_USE_INET6
+       case AF_INET6:
+           addrlen = sizeof (struct in6_addr);
+           ptr = &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr;
+           atype = ADDRTYPE_INET6;
+           break;
+#endif
+       default:
+           continue;
+       }
        addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
        if (!addrs[i]) {
            retval = ENOMEM;
            goto errout;
        }
        addrs[i]->magic = KV5M_ADDRESS;
-       addrs[i]->addrtype = hp->h_addrtype;
-       addrs[i]->length   = hp->h_length;
-       addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+       addrs[i]->addrtype = atype;
+       addrs[i]->length = addrlen;
+       addrs[i]->contents = malloc(addrs[i]->length);
        if (!addrs[i]->contents) {
            retval = ENOMEM;
            goto errout;
        }
-       memcpy ((char *)addrs[i]->contents, hp->h_addr_list[i],
-               addrs[i]->length);
+       memcpy (addrs[i]->contents, ptr, addrs[i]->length);
+       i++;
     }
-    addrs[i] = 0;
 
     *ret_addrs = addrs;
+    if (ai)
+       freeaddrinfo(ai);
     return 0;
 
 errout:
-    if (addrs)
+    if (addrs) {
+       for (i = 0; addrs[i]; i++) {
+           free (addrs[i]->contents);
+           free (addrs[i]);
+       }
        krb5_free_addresses(context, addrs);
+    }
+    if (ai)
+       freeaddrinfo(ai);
     return retval;
        
 }