Add capability of looking up TCP addresses for KDC in DNS; not enabled yet.
authorKen Raeburn <raeburn@mit.edu>
Tue, 4 Jun 2002 06:59:28 +0000 (06:59 +0000)
committerKen Raeburn <raeburn@mit.edu>
Tue, 4 Jun 2002 06:59:28 +0000 (06:59 +0000)
Internal "addrlist" structure now includes socket type, by way of using
struct addrinfo where struct sockaddr was used before; updated uses.
No support for noting TCP/UDP vs UDP-only addresses in config files.

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

src/include/ChangeLog
src/include/k5-int.h
src/krb524/ChangeLog
src/krb524/sendmsg.c
src/lib/krb5/os/ChangeLog
src/lib/krb5/os/changepw.c
src/lib/krb5/os/locate_kdc.c
src/lib/krb5/os/sendto_kdc.c
src/lib/krb5/os/t_locate_kdc.c

index 2fdec2914535449bd32e70a0dcccc3205b9604a1..0872f7104de95fbb7acc41cd07c770d2336a35d1 100644 (file)
@@ -1,3 +1,8 @@
+2002-06-04  Ken Raeburn  <raeburn@mit.edu>
+
+       * k5-int.h (struct addrlist): Field "addrs" now points to
+       addrinfo instead of sockaddr.
+
 2002-05-31  Ken Raeburn  <raeburn@mit.edu>
 
        * socket-utils.h (socklen) [! HAVE_SA_LEN]: Return a socklen_t
index 1b90386f5b52b0c9252dfc8b560b694a9bfc0e02..e53585a15c953fce6b3ffba5b57211484ce120d7 100644 (file)
@@ -485,8 +485,10 @@ krb5_error_code krb5_find_config_files (void);
 krb5_error_code krb5_os_hostaddr
        (krb5_context, const char *, krb5_address ***);
 
+/* N.B.: You need to include fake-addrinfo.h *before* k5-int.h if you're
+   going to use this structure.  */
 struct addrlist {
-    struct sockaddr **addrs;
+    struct addrinfo **addrs;
     int naddrs;
     int space;
 };
index 68b0a832a108cb17ea1fd614a6293edc5d67e48c..6f35970eded62c8597fffd76b969ed4b129cc4bc 100644 (file)
@@ -1,3 +1,8 @@
+2002-06-04  Ken Raeburn  <raeburn@mit.edu>
+
+       * sendmsg.c: Include fake-addrinfo.h.
+       (krb524_sendto_kdc): Update for addrlist changes.
+
 2002-04-10  Danilo Almeida  <dalmeida@mit.edu>
 
        * encode.c, cnv_tkt_skey.c: Need port-sockets.h for Win32 (now
index 00c55f0d2a57ac935d4059d5d47ba8eee6572458..2335dad316b58d9d957840aa24c38e7e64dc9c4c 100644 (file)
@@ -28,6 +28,7 @@
 /* Grab socket stuff.  This might want to go away later. */
 #define NEED_SOCKETS
 #define NEED_LOWLEVEL_IO
+#include "fake-addrinfo.h" /* for custom addrinfo if needed */
 #include "k5-int.h"
 
 #ifndef _WIN32
@@ -101,8 +102,8 @@ krb524_sendto_kdc (context, message, realm, reply)
         */
        if (retval == 0)
            for (i = 0; i < al.naddrs; i++) {
-               if (al.addrs[i]->sa_family == AF_INET)
-                   sa2sin (al.addrs[i])->sin_port = port;
+               if (al.addrs[i]->ai_family == AF_INET)
+                   sa2sin (al.addrs[i]->ai_addr)->sin_port = port;
            }
     }
     if (retval)
@@ -163,7 +164,7 @@ krb524_sendto_kdc (context, message, realm, reply)
                 * protocol exists to support a particular socket type
                 * within a given protocol family.
                 */
-               socklist[host] = socket(al.addrs[host]->sa_family, SOCK_DGRAM,
+               socklist[host] = socket(al.addrs[host]->ai_family, SOCK_DGRAM,
                                        0);
                if (socklist[host] == INVALID_SOCKET)
                    continue;           /* try other hosts */
@@ -173,8 +174,8 @@ krb524_sendto_kdc (context, message, realm, reply)
                   socket will time out, so use connect, send, recv instead of
                   sendto, recvfrom.  The connect here may return an error if
                   the destination host is known to be unreachable. */
-               if (connect(socklist[host], al.addrs[host],
-                           socklen(al.addrs[host])) == SOCKET_ERROR)
+               if (connect(socklist[host], al.addrs[host]->ai_addr,
+                           al.addrs[host]->ai_addrlen) == SOCKET_ERROR)
                  continue;
            }
            if (send(socklist[host], message->data, (int) message->length, 0)
index 9f981c884abdd778f9b79ff5a6a8c7f2c9704921..9f75d40b93d3a9cf0089295cc2c948559970ee10 100644 (file)
@@ -1,3 +1,29 @@
+2002-06-04  Ken Raeburn  <raeburn@mit.edu>
+
+       * locate_kdc.c: Include fake-addrinfo.h before k5-int.h.
+       (grow_list, krb5int_free_addrlist)
+       (add_addrinfo_to_list): Incorporate list-updating code from
+       add_sockaddr_to_list.  Store an addrinfo pointer, and set the
+       ai_next field to null.
+       (add_host_to_list): New arg SOCKTYPE.  Write port numbers into
+       buffers and let getaddrinfo fill in the sin*_port fields.  Call
+       getaddrinfo twice, and use two loops to add entries to the
+       addrlist structure.
+       (add_sockaddr_to_list, set_port_num): Deleted.
+       (krb5_locate_srv_conf_1, krb5_locate_srv_dns_1): Pass extra arg
+       to add_host_to_list.
+       (krb5int_locate_server): New value 2 for is_stream arg means
+       accept both UDP and TCP.
+       * changepw.c: Include fake-addrinfo.h.
+       (krb5_locate_passwd, krb5_change_password): Update for addrlist
+       changes.
+       * sendto_kdc.c: Include fake-addrinfo.h.
+       (krb5_sendto_kdc): Update for addrlist changes.  Skip any
+       addresses that are not SOCK_DGRAM.
+       * t_locate_kdc.c (stypename): New function.
+       (print_addrs): Update for addrlist changes.  Print socket type
+       with address and port.
+
 2002-04-12  Ken Raeburn  <raeburn@mit.edu>
 
        * lock_file.c (krb5_lock_file) [POSIX_FILE_LOCKS]: Make static
index 88d50cc907e316485d14891f3a4e305b9801ab46..42b77286e2d4416ab1444431d23a7d019d2fd90a 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #define NEED_SOCKETS
+#include "fake-addrinfo.h"
 #include "k5-int.h"
 #include "os-proto.h"
 #include "adm_err.h"
@@ -75,9 +76,9 @@ krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
               port number to use DEFAULT_KPASSWD_PORT.  */
            int i;
            for ( i=0;i<addrlist->naddrs;i++ ) {
-               struct sockaddr *a = addrlist->addrs[i];
-               if (a->sa_family == AF_INET)
-                   sa2sin (a)->sin_port = htons(DEFAULT_KPASSWD_PORT);
+               struct addrinfo *a = addrlist->addrs[i];
+               if (a->ai_family == AF_INET)
+                   sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT);
            }
        }
     }
@@ -169,11 +170,11 @@ krb5_change_password(context, creds, newpw, result_code,
        struct timeval timeout;
 
        /* XXX Now the locate_ functions can return IPv6 addresses.  */
-       if (al.addrs[i]->sa_family != AF_INET)
+       if (al.addrs[i]->ai_family != AF_INET)
            continue;
 
        tried_one = 1;
-       if (connect(s2, al.addrs[i], socklen(al.addrs[i])) == SOCKET_ERROR) {
+       if (connect(s2, al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen) == SOCKET_ERROR) {
            if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
                continue; /* try the next addr */
 
@@ -254,7 +255,7 @@ krb5_change_password(context, creds, newpw, result_code,
 
        if ((cc = sendto(s1, chpw_req.data, 
                         (GETSOCKNAME_ARG3_TYPE) chpw_req.length, 0,
-                        al.addrs[i], socklen(al.addrs[i]))) != chpw_req.length)
+                        al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen)) != chpw_req.length)
        {
            if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
                             (SOCKET_ERRNO == EHOSTUNREACH)))
index cc6d9c56709352dd9a87ea9a31f10de0f3df3d89..d1819939d116b07169f0ba807509d5f3ff4e15ee 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #define NEED_SOCKETS
+#include "fake-addrinfo.h"
 #include "k5-int.h"
 #include "os-proto.h"
 #include <stdio.h>
@@ -44,8 +45,6 @@
 #define T_SRV 33
 #endif /* T_SRV */
 
-#include "fake-addrinfo.h"
-
 /* for old Unixes and friends ... */
 #ifndef MAXHOSTNAMELEN
 #define MAXHOSTNAMELEN 64
@@ -133,7 +132,7 @@ grow_list (struct addrlist *lp, int nmore)
     int i;
     int newspace = lp->space + nmore;
     size_t newsize = newspace * sizeof (struct addrlist);
-    struct sockaddr **newaddrs;
+    struct addrinfo **newaddrs;
 
     /* NULL check a concession to SunOS4 compatibility for now; not
        required for pure ANSI support.  */
@@ -158,57 +157,13 @@ krb5int_free_addrlist (struct addrlist *lp)
 {
     int i;
     for (i = 0; i < lp->naddrs; i++)
-       free (lp->addrs[i]);
+       freeaddrinfo (lp->addrs[i]);
     free (lp->addrs);
     lp->addrs = NULL;
     lp->naddrs = lp->space = 0;
 }
 #define free_list krb5int_free_addrlist
 
-static int
-add_sockaddr_to_list (struct addrlist *lp, const struct sockaddr *addr,
-                     size_t len)
-{
-    struct sockaddr *copy;
-    int err;
-
-#ifdef TEST
-    char name[NI_MAXHOST];
-
-    fprintf (stderr, "\tadding sockaddr family %2d, len %d", addr->sa_family,
-            len);
-
-    err = getnameinfo (addr, len, name, sizeof (name), NULL, 0,
-                      NI_NUMERICHOST | NI_NUMERICSERV);
-    if (err == 0)
-       fprintf (stderr, "\t%s", name);
-    fprintf (stderr, "\n");
-#endif
-
-    if (lp->naddrs == lp->space) {
-       err = grow_list (lp, 1);
-       if (err) {
-#ifdef TEST
-           fprintf (stderr, "grow_list failed %d\n", err);
-#endif
-           return err;
-       }
-    }
-    copy = malloc (len);
-    if (copy == NULL) {
-#ifdef TEST
-       perror ("malloc");
-#endif
-       return errno;
-    }
-    memcpy (copy, addr, len);
-    lp->addrs[lp->naddrs++] = copy;
-#ifdef TEST
-    fprintf (stderr, "count is now %d\n", lp->naddrs);
-#endif
-    return 0;
-}
-
 static int translate_ai_error (int err)
 {
     switch (err) {
@@ -249,8 +204,8 @@ static int translate_ai_error (int err)
 
 static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
 {
-    int r;
-    r = add_sockaddr_to_list (lp, a->ai_addr, a->ai_addrlen);
+    int err;
+
 #ifdef TEST
     switch (a->ai_socktype) {
     case SOCK_DGRAM:
@@ -269,29 +224,31 @@ static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
        break;
     }
 #endif
-    return r;
-}
 
-static void set_port_num (struct sockaddr *addr, int num)
-{
-    switch (addr->sa_family) {
-    case AF_INET:
-       ((struct sockaddr_in *)addr)->sin_port = num;
-       break;
-#ifdef KRB5_USE_INET6
-    case AF_INET6:
-       ((struct sockaddr_in6 *)addr)->sin6_port = num;
-       break;
+    if (lp->naddrs == lp->space) {
+       err = grow_list (lp, 1);
+       if (err) {
+#ifdef TEST
+           fprintf (stderr, "grow_list failed %d\n", err);
 #endif
+           return err;
+       }
     }
+    lp->addrs[lp->naddrs++] = a;
+    a->ai_next = 0;
+#ifdef TEST
+    fprintf (stderr, "count is now %d\n", lp->naddrs);
+#endif
+    return 0;
 }
 
 static int
 add_host_to_list (struct addrlist *lp, const char *hostname,
-                 int port, int secport)
+                 int port, int secport, int socktype)
 {
-    struct addrinfo *addrs, *a, hint;
+    struct addrinfo *addrs, *a, *anext, hint;
     int err;
+    char portbuf[10], secportbuf[10];
 
 #ifdef TEST
     fprintf (stderr, "adding hostname %s, ports %d,%d\n", hostname,
@@ -299,25 +256,29 @@ add_host_to_list (struct addrlist *lp, const char *hostname,
 #endif
 
     memset(&hint, 0, sizeof(hint));
-    hint.ai_socktype = SOCK_DGRAM;
-    err = getaddrinfo (hostname, NULL, &hint, &addrs);
+    hint.ai_socktype = socktype;
+    sprintf(portbuf, "%d", ntohs(port));
+    sprintf(secportbuf, "%d", ntohs(secport));
+    err = getaddrinfo (hostname, portbuf, &hint, &addrs);
     if (err)
        return translate_ai_error (err);
-    for (a = addrs; a; a = a->ai_next) {
-       set_port_num (a->ai_addr, port);
+    anext = 0;
+    for (a = addrs; a != 0 && err == 0; a = anext) {
+       anext = a->ai_next;
        err = add_addrinfo_to_list (lp, a);
-       if (err)
-           break;
-
-       if (secport == 0)
-           continue;
-
-       set_port_num (a->ai_addr, secport);
+    }
+    if (err || secport == 0)
+       goto egress;
+    err = getaddrinfo (hostname, secportbuf, &hint, &addrs);
+    if (err)
+       return translate_ai_error (err);
+    for (a = addrs; a != 0 && err == 0; a = anext) {
+       anext = a->ai_next;
        err = add_addrinfo_to_list (lp, a);
-       if (err)
-           break;
     }
-    freeaddrinfo (addrs);
+egress:
+    if (anext)
+       freeaddrinfo (anext);
     return err;
 }
 
@@ -470,7 +431,7 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
            p2 = sec_udpport;
        }
 
-       code = add_host_to_list (addrlist, hostlist[i], p1, p2);
+       code = add_host_to_list (addrlist, hostlist[i], p1, p2, SOCK_DGRAM);
        if (code) {
 #ifdef TEST
            fprintf (stderr, "error %d returned from add_host_to_list\n", code);
@@ -732,7 +693,10 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
 #ifdef TEST
        fprintf (stderr, "\tport=%d host=%s\n", entry->port, entry->host);
 #endif
-       code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0);
+       code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0,
+                                (strcmp("_tcp", protocol)
+                                 ? SOCK_DGRAM
+                                 : SOCK_STREAM));
        if (code)
            break;
     }
@@ -795,9 +759,31 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm,
 #ifdef KRB5_DNS_LOOKUP
     if (code && dnsname != 0) {
        int use_dns = _krb5_use_dns_kdc(context);
-       if (use_dns)
-           code = krb5_locate_srv_dns_1(realm, dnsname,
-                                        is_stream ? "_tcp" : "_udp", &al);
+       if (use_dns) {
+           /* Values of is_stream:
+              0: udp only
+              1: tcp only
+              2: udp or tcp
+              No other values currently allowed.  */
+           code = 0;
+#ifdef TEST
+           fprintf(stderr, "is_stream = %d\n", is_stream);
+#endif
+           if (is_stream != 1) {
+               code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", &al);
+#ifdef TEST
+               if (code)
+                   fprintf(stderr, "dns lookup returned error %d\n", code);
+#endif
+           }
+           if (is_stream != 0 && code == 0) {
+               code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", &al);
+#ifdef TEST
+               if (code)
+                   fprintf(stderr, "dns lookup returned error %d\n", code);
+#endif
+           }
+       }
     }
 #endif /* KRB5_DNS_LOOKUP */
 #ifdef TEST
index 7bb63522c3c8cb5199cb8f940ca96da49a625891..595e2c9d8c8e02b832544dbdf5b1d6f3728341c5 100644 (file)
@@ -30,6 +30,7 @@
 
 #define NEED_SOCKETS
 #define NEED_LOWLEVEL_IO
+#include "fake-addrinfo.h"
 #include "k5-int.h"
 
 #ifdef HAVE_SYS_TIME_H
@@ -120,9 +121,11 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
         timeout <<= krb5_skdc_timeout_shift) {
        sent = 0;
        for (host = 0; host < addrs.naddrs; host++) {
-           /* send to the host, wait timeout seconds for a response,
+           if (addrs.addrs[host]->ai_socktype != SOCK_DGRAM)
+               continue;
+           /* Send to the host, wait timeout seconds for a response,
               then move on. */
-           /* cache some sockets for each host */
+           /* Cache some sockets for each host.  */
            if (socklist[host] == INVALID_SOCKET) {
                /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the socket
                   creation here will work properly... */
@@ -136,22 +139,22 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
                 */
 #ifdef DEBUG
                fprintf (stderr, "getting dgram socket in family %d...",
-                        addrs.addrs[host]->sa_family);
+                        addrs.addrs[host]->ai_family);
 #endif
-               socklist[host] = socket(addrs.addrs[host]->sa_family,
+               socklist[host] = socket(addrs.addrs[host]->ai_family,
                                        SOCK_DGRAM, 0);
                if (socklist[host] == INVALID_SOCKET) {
 #ifdef DEBUG
                    perror ("socket");
-                   fprintf (stderr, "af was %d\n", addrs.addrs[host]->sa_family);
+                   fprintf (stderr, "af was %d\n", addrs.addrs[host]->ai_family);
 #endif
                    continue;           /* try other hosts */
                }
 #ifdef DEBUG
                {
                    char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
-                   if (0 != getnameinfo (addrs.addrs[host],
-                                         socklen (addrs.addrs[host]),
+                   if (0 != getnameinfo (addrs.addrs[host]->ai_addr,
+                                         addrs.addrs[host]->ai_addrlen,
                                          addrbuf, sizeof (addrbuf),
                                          portbuf, sizeof (portbuf),
                                          NI_NUMERICHOST | NI_NUMERICSERV))
@@ -167,7 +170,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
                   sendto, recvfrom.  The connect here may return an error if
                   the destination host is known to be unreachable. */
                if (connect(socklist[host],
-                           addrs.addrs[host], socklen(addrs.addrs[host])) == SOCKET_ERROR) {
+                           addrs.addrs[host]->ai_addr, addrs.addrs[host]->ai_addrlen) == SOCKET_ERROR) {
 #ifdef DEBUG
                    perror ("connect");
 #endif
index e93b6d8776e97deac66911f936bac36375771fb3..5bb334b6dfc81b2dc42c4cbd2dddc0d35bb622bb 100644 (file)
@@ -27,18 +27,34 @@ void kfatal (krb5_error_code err)
     exit (1);
 }
 
+const char *stypename (int stype)
+{
+    static char buf[20];
+    switch (stype) {
+    case SOCK_STREAM:
+       return "stream";
+    case SOCK_DGRAM:
+       return "dgram";
+    case SOCK_RAW:
+       return "raw";
+    default:
+       sprintf(buf, "?%d", stype);
+       return buf;
+    }
+}
+
 void print_addrs ()
 {
     int i;
 
-    struct sockaddr **addrs = al.addrs;
+    struct addrinfo **addrs = al.addrs;
     int naddrs = al.naddrs;
 
     printf ("%d addresses:\n", naddrs);
     for (i = 0; i < naddrs; i++) {
        int err;
        char hostbuf[NI_MAXHOST], srvbuf[NI_MAXSERV];
-       err = getnameinfo (addrs[i], socklen(addrs[i]),
+       err = getnameinfo (addrs[i]->ai_addr, addrs[i]->ai_addrlen,
                           hostbuf, sizeof (hostbuf),
                           srvbuf, sizeof (srvbuf),
                           NI_NUMERICHOST | NI_NUMERICSERV);
@@ -46,7 +62,8 @@ void print_addrs ()
            printf ("%2d: getnameinfo returns error %d=%s\n",
                    i, err, gai_strerror (err));
        else
-           printf ("%2d: address %s\tport %s\n", i, hostbuf, srvbuf);
+           printf ("%2d: address %s\t%s\tport %s\n", i, hostbuf,
+                   stypename (addrs[i]->ai_socktype), srvbuf);
     }
 }