back out changes that shouldn't have been checked in yet
authorKen Raeburn <raeburn@mit.edu>
Thu, 26 Apr 2001 03:57:48 +0000 (03:57 +0000)
committerKen Raeburn <raeburn@mit.edu>
Thu, 26 Apr 2001 03:57:48 +0000 (03:57 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13198 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/accessor.c
src/lib/krb5/os/changepw.c
src/lib/krb5/os/locate_kdc.c
src/lib/krb5/os/os-proto.h
src/lib/krb5/os/sendto_kdc.c

index d3c842a86ec155c4551ffcd55cb6fbf99edbd7a3..d0d0dc21dda9d144a029fb4fc8c3dd217ef2b764 100644 (file)
@@ -37,7 +37,6 @@ krb5int_accessor(internals, version)
   if (version == KRB5INT_ACCESS_VERSION)
   {
     krb5int_access internals_temp;
-    internals_temp.krb5_locate_server = krb5int_locate_server;
     internals_temp.krb5_locate_kdc = krb5_locate_kdc;
     internals_temp.krb5_max_skdc_timeout = krb5_max_skdc_timeout;
     internals_temp.krb5_skdc_timeout_shift = krb5_skdc_timeout_shift;
index 1eefe6d98658b7a5c1c19037b256bab3ae141e31..61cfea01ff0976b05fd73f97b5762413fb3ee7e6 100644 (file)
@@ -8,7 +8,7 @@
  *   require a specific license from the United States Government.
  *   It is the responsibility of any person or organization contemplating
  *   export to obtain such a license before exporting.
- *
+ * 
  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  * distribute this software and its documentation for any purpose and
  * without fee is hereby granted, provided that the above copyright
@@ -22,7 +22,7 @@
  * M.I.T. makes no representations about the suitability of
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
- *
+ * 
  */
 
 #define NEED_SOCKETS
 #endif
 #endif /* _WIN32 && !__CYGWIN32__ */
 
-/* There's a lot of confusion between pointers to different sockaddr
-   types, and pointers with different degrees of indirection.  Use
-   this function in this file to ensure we don't do something silly
-   like cast a "sockaddr **" to a "sockaddr_in *".  */
-static struct sockaddr_in *sa2sin (struct sockaddr *sa)
-{
-    return (struct sockaddr_in *) sa;
-}
-#ifdef KRB5_USE_INET6xxNotUsed
-static struct sockaddr_in6 *sa2sin6 (struct sockaddr *sa)
-{
-    return (struct sockaddr_in6 *) sa;
-}
-#endif
-
 /*
  * Wrapper function for the two backends
  */
@@ -72,30 +57,54 @@ static krb5_error_code
 krb5_locate_kpasswd(context, realm, addr_pp, naddrs)
     krb5_context context;
     const krb5_data *realm;
-    struct sockaddr ***addr_pp;
+    struct sockaddr **addr_pp;
     int *naddrs;
 {
     krb5_error_code code;
+    int i;
 
-    code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0,
-                                 "kpasswd_server", "_kpasswd", 0,
-                                 DEFAULT_KPASSWD_PORT, 0);
+    /*
+     * We always try the local file first
+     */
+
+    code = krb5_locate_srv_conf(context, realm, "kpasswd_server",
+                                 addr_pp, naddrs, 0);
     if (code) {
-       code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0,
-                                     "admin_server", "_kerberos-adm", 1,
-                                     DEFAULT_KPASSWD_PORT, 0);
-       if (!code) {
-           /* Success with admin_server but now we need to change the
-              port number to use DEFAULT_KPASSWD_PORT.  */
-           int i;
-           for ( i=0;i<*naddrs;i++ ) {
-               struct sockaddr *a = (*addr_pp)[i];
-               if (a->sa_family == AF_INET)
-                   sa2sin (a)->sin_port = htons(DEFAULT_KPASSWD_PORT);
-           }
-       }
+        code = krb5_locate_srv_conf(context, realm, "admin_server", 
+                                     addr_pp, naddrs, 0);
+        if ( !code ) {
+            /* success with admin_server but now we need to change the port */
+            /* number to use DEFAULT_KPASSWD_PORT.                          */
+            for ( i=0;i<*naddrs;i++ ) {
+                struct sockaddr_in *sockin = (struct sockaddr_in *) addr_pp[i];
+                sockin->sin_port = htons(DEFAULT_KPASSWD_PORT);
+            }
+        }
     }
 
+#ifdef KRB5_DNS_LOOKUP
+    if (code) {
+        int use_dns = _krb5_use_dns_kdc(context);
+        if ( use_dns ) {
+            code = krb5_locate_srv_dns(realm, "_kpasswd", "_udp",
+                                        addr_pp, naddrs);
+            if ( code ) {
+                code = krb5_locate_srv_dns(realm, 
+                                            "_kerberos-adm", 
+                                            "_tcp",
+                                            addr_pp, naddrs);
+                if ( !code ) {
+                    /* success with admin_server but now we need to change the port */
+                    /* number to use DEFAULT_KPASSWD_PORT.                          */
+                    for ( i=0;i<*naddrs;i++ ) {
+                        struct sockaddr_in *sockin = (struct sockaddr_in *) addr_pp[i];
+                        sockin->sin_port = htons(DEFAULT_KPASSWD_PORT);
+                    }
+                }
+            }
+        }
+    }
+#endif /* KRB5_DNS_LOOKUP */
     return (code);
 }
 
@@ -116,7 +125,7 @@ krb5_change_password(context, creds, newpw, result_code,
     char *code_string;
     krb5_error_code code = 0;
     int i, addrlen;
-    struct sockaddr **addr_p, local_addr, remote_addr, tmp_addr;
+    struct sockaddr *addr_p, local_addr, remote_addr, tmp_addr;
     int naddr_p;
     int cc, local_result_code, tmp_len;
     SOCKET s1 = INVALID_SOCKET, s2 = INVALID_SOCKET;
@@ -128,18 +137,18 @@ krb5_change_password(context, creds, newpw, result_code,
     memset(&chpw_req, 0, sizeof(krb5_data));
     memset(&chpw_rep, 0, sizeof(krb5_data));
     memset(&ap_req, 0, sizeof(krb5_data));
-
+    
     /* initialize auth_context so that we know we have to free it */
     if ((code = krb5_auth_con_init(context, &auth_context)))
          goto cleanup;
-
-    if ((code = krb5_mk_req_extended(context, &auth_context,
+    
+    if ((code = krb5_mk_req_extended(context, &auth_context, 
                                     AP_OPTS_USE_SUBKEY,
                                     NULL, creds, &ap_req)))
          goto cleanup;
 
-    if ((code = krb5_locate_kpasswd(context,
-                                    krb5_princ_realm(context, creds->client),
+    if ((code = krb5_locate_kpasswd(context, 
+                                    krb5_princ_realm(context, creds->client), 
                                     &addr_p, &naddr_p)))
         goto cleanup;
 
@@ -147,7 +156,7 @@ krb5_change_password(context, creds, newpw, result_code,
        is left unconnected in case the server is multihomed and routes
        are asymmetric.  s2 is connected to resolve routes and get
        addresses.  this is the *only* way to get proper addresses for
-       multihomed hosts if routing is asymmetric.
+       multihomed hosts if routing is asymmetric.  
 
        A related problem in the server, but not the client, is that
        many os's have no way to disconnect a connected udp socket, so
@@ -159,207 +168,212 @@ krb5_change_password(context, creds, newpw, result_code,
        hostname resolution to get the local ip addr) will work and
        interoperate if the client is single-homed. */
 
-    if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
-       code = SOCKET_ERRNO;
-       goto cleanup;
-    }
-
-    if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
-       code = SOCKET_ERRNO;
-       goto cleanup;
-    }
-
-    for (i=0; i<naddr_p; i++) {
-       fd_set fdset;
-       struct timeval timeout;
-
-       /* XXX Now the locate_ functions can return IPv6 addresses.  */
-       if (addr_p[i]->sa_family != AF_INET)
-           continue;
-
-       if (connect(s2, addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR) {
-           if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
-               continue; /* try the next addr */
-
-           code = SOCKET_ERRNO;
-           goto cleanup;
-       }
-
-        addrlen = sizeof(local_addr);
-
-       if (getsockname(s2, &local_addr, &addrlen) < 0) {
-           if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
-               continue; /* try the next addr */
-
+    if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) 
+      {
            code = SOCKET_ERRNO;
            goto cleanup;
-       }
-
-       /* some brain-dead OS's don't return useful information from
-        * the getsockname call.  Namely, windows and solaris.  */
-
-       if (sa2sin(&local_addr)->sin_addr.s_addr != 0) {
-           local_kaddr.addrtype = ADDRTYPE_INET;
-           local_kaddr.length = sizeof(sa2sin(&local_addr)->sin_addr);
-           local_kaddr.contents = (krb5_octet *) &sa2sin(&local_addr)->sin_addr;
-       } else {
-           krb5_address **addrs;
-
-           krb5_os_localaddr(context, &addrs);
-
-           local_kaddr.magic = addrs[0]->magic;
-           local_kaddr.addrtype = addrs[0]->addrtype;
-           local_kaddr.length = addrs[0]->length;
-           local_kaddr.contents = malloc(addrs[0]->length);
-           memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
-
-           krb5_free_addresses(context, addrs);
-       }
-
-       addrlen = sizeof(remote_addr);
-       if (getpeername(s2, &remote_addr, &addrlen) < 0) {
-           if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
-               continue; /* try the next addr */
+      }
 
+    if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
+      {
            code = SOCKET_ERRNO;
            goto cleanup;
-       }
-
-       remote_kaddr.addrtype = ADDRTYPE_INET;
-       remote_kaddr.length = sizeof(sa2sin(&remote_addr)->sin_addr);
-       remote_kaddr.contents = (krb5_octet *) &sa2sin(&remote_addr)->sin_addr;
-
-       /* mk_priv requires that the local address be set.
-          getsockname is used for this.  rd_priv requires that the
-          remote address be set.  recvfrom is used for this.  If
-          rd_priv is given a local address, and the message has the
-          recipient addr in it, this will be checked.  However, there
-          is simply no way to know ahead of time what address the
-          message will be delivered *to*.  Therefore, it is important
-          that either no recipient address is in the messages when
-          mk_priv is called, or that no local address is passed to
-          rd_priv.  Both is a better idea, and I have done that.  In
-          summary, when mk_priv is called, *only* a local address is
-          specified.  when rd_priv is called, *only* a remote address
-          is specified.  Are we having fun yet?  */
-
-       if ((code = krb5_auth_con_setaddrs(context, auth_context,
-                                          &local_kaddr, NULL))) {
-           code = SOCKET_ERRNO;
-           goto cleanup;
-       }
-
-       if ((code = krb5_mk_chpw_req(context, auth_context, &ap_req,
-                                    newpw, &chpw_req)))
-       {
-           code = SOCKET_ERRNO;
-           goto cleanup;
-       }
-
-       if ((cc = sendto(s1, chpw_req.data, (int) chpw_req.length, 0,
-                        addr_p[i], sizeof(addr_p[i]))) != chpw_req.length)
-       {
-           if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
-                            (SOCKET_ERRNO == EHOSTUNREACH)))
-               continue; /* try the next addr */
-
-           code = (cc < 0) ? SOCKET_ERRNO : ECONNABORTED;
-           goto cleanup;
-       }
-
-       chpw_rep.length = 1500;
-       chpw_rep.data = (char *) malloc(chpw_rep.length);
-
-       /* XXX need a timeout/retry loop here */
-       FD_ZERO (&fdset);
-       FD_SET (s1, &fdset);
-       timeout.tv_sec = 120;
-       timeout.tv_usec = 0;
-       switch (select (s1 + 1, &fdset, 0, 0, &timeout)) {
-       case -1:
-           code = SOCKET_ERRNO;
-           goto cleanup;
-       case 0:
-           code = ETIMEDOUT;
-           goto cleanup;
-       default:
-           /* fall through */
-           ;
-       }
-
-       /* "recv" would be good enough here... except that Windows/NT
-          commits the atrocity of returning -1 to indicate failure,
-          but leaving errno set to 0.
-
-          "recvfrom(...,NULL,NULL)" would seem to be a good enough
-          alternative, and it works on NT, but it doesn't work on
-          SunOS 4.1.4 or Irix 5.3.  Thus we must actually accept the
-          value and discard it. */
-       tmp_len = sizeof(tmp_addr);
-       if ((cc = recvfrom(s1, chpw_rep.data, (int) chpw_rep.length,
-                          0, &tmp_addr, &tmp_len)) < 0)
-       {
-           code = SOCKET_ERRNO;
-           goto cleanup;
-       }
-
-       closesocket(s1);
-       s1 = INVALID_SOCKET;
-       closesocket(s2);
-       s2 = INVALID_SOCKET;
-
-       chpw_rep.length = cc;
-
-       if ((code = krb5_auth_con_setaddrs(context, auth_context,
-                                          NULL, &remote_kaddr)))
-           goto cleanup;
-
-       if ((code = krb5_rd_chpw_rep(context, auth_context, &chpw_rep,
-                                    &local_result_code,
-                                    result_string)))
-           goto cleanup;
-
-       if (result_code)
-           *result_code = local_result_code;
+      }
+
+    for (i=0; i<naddr_p; i++) 
+      {
+               fd_set fdset;
+               struct timeval timeout;
+
+               if (connect(s2, &addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR) 
+                 {
+                   if ((SOCKET_ERRNO == ECONNREFUSED) || (SOCKET_ERRNO == EHOSTUNREACH))
+                         continue; /* try the next addr */
+                   
+                   code = SOCKET_ERRNO;
+                   goto cleanup;
+                 }
+      
+        addrlen = sizeof(local_addr);
 
-       if (result_code_string) {
-           if ((code = krb5_chpw_result_code_string(context,
-                                                    local_result_code,
-                                                    &code_string)))
+               if (getsockname(s2, &local_addr, &addrlen) < 0) 
+                 {
+                   if ((SOCKET_ERRNO == ECONNREFUSED) || (SOCKET_ERRNO == EHOSTUNREACH))
+                         continue; /* try the next addr */
+                   
+                   code = SOCKET_ERRNO;
+                       goto cleanup;
+                 }
+
+               /* some brain-dead OS's don't return useful information from
+                * the getsockname call.  Namely, windows and solaris.  */
+
+               if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0) 
+                 {
+                   local_kaddr.addrtype = ADDRTYPE_INET;
+                   local_kaddr.length = sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
+                   local_kaddr.contents = (krb5_octet *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
+                 } 
+               else 
+                 {
+                   krb5_address **addrs;
+
+                   krb5_os_localaddr(context, &addrs);
+                   
+                   local_kaddr.magic = addrs[0]->magic;
+                   local_kaddr.addrtype = addrs[0]->addrtype;
+                   local_kaddr.length = addrs[0]->length;
+                   local_kaddr.contents = malloc(addrs[0]->length);
+                   memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
+
+                   krb5_free_addresses(context, addrs);
+                 }
+
+               addrlen = sizeof(remote_addr);
+               if (getpeername(s2, &remote_addr, &addrlen) < 0) 
+                 {
+                   if ((SOCKET_ERRNO == ECONNREFUSED) || (SOCKET_ERRNO == EHOSTUNREACH))
+                         continue; /* try the next addr */
+                   
+                   code = SOCKET_ERRNO;
+                       goto cleanup;
+                 }
+
+               remote_kaddr.addrtype = ADDRTYPE_INET;
+               remote_kaddr.length = sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
+               remote_kaddr.contents = (krb5_octet *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
+
+               /* mk_priv requires that the local address be set.
+                 getsockname is used for this.  rd_priv requires that the
+                 remote address be set.  recvfrom is used for this.  If
+                 rd_priv is given a local address, and the message has the
+                 recipient addr in it, this will be checked.  However, there
+                 is simply no way to know ahead of time what address the
+                 message will be delivered *to*.  Therefore, it is important
+                 that either no recipient address is in the messages when
+                 mk_priv is called, or that no local address is passed to
+                 rd_priv.  Both is a better idea, and I have done that.  In
+                 summary, when mk_priv is called, *only* a local address is
+                 specified.  when rd_priv is called, *only* a remote address
+                 is specified.  Are we having fun yet?  */
+
+               if ((code = krb5_auth_con_setaddrs(context, auth_context, 
+                                                  &local_kaddr, NULL)))
+                 {
+                   code = SOCKET_ERRNO;
+                       goto cleanup;
+                 }
+
+               if ((code = krb5_mk_chpw_req(context, auth_context, &ap_req, 
+                                            newpw, &chpw_req)))
+                 {
+                   code = SOCKET_ERRNO;
+                       goto cleanup;
+                 }
+
+               if ((cc = sendto(s1, chpw_req.data, (int) chpw_req.length, 0, 
+                                (struct sockaddr *) &addr_p[i], 
+                                sizeof(addr_p[i]))) != chpw_req.length) 
+                 {
+                   if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
+                                    (SOCKET_ERRNO == EHOSTUNREACH)))
+                         continue; /* try the next addr */
+                   
+                   code = (cc < 0) ? SOCKET_ERRNO : ECONNABORTED;
+                       goto cleanup;
+                 }
+
+               chpw_rep.length = 1500;
+               chpw_rep.data = (char *) malloc(chpw_rep.length);
+
+               /* XXX need a timeout/retry loop here */
+               FD_ZERO (&fdset);
+               FD_SET (s1, &fdset);
+               timeout.tv_sec = 120;
+               timeout.tv_usec = 0;
+               switch (select (s1 + 1, &fdset, 0, 0, &timeout)) {
+               case -1:
+                   code = SOCKET_ERRNO;
+                   goto cleanup;
+               case 0:
+                   code = ETIMEDOUT;
+                   goto cleanup;
+               default:
+                   /* fall through */
+                   ;
+               }
+
+               /* "recv" would be good enough here... except that Windows/NT
+                  commits the atrocity of returning -1 to indicate failure,
+                  but leaving errno set to 0.
+                  
+                  "recvfrom(...,NULL,NULL)" would seem to be a good enough
+                  alternative, and it works on NT, but it doesn't work on
+                  SunOS 4.1.4 or Irix 5.3.  Thus we must actually accept the
+                  value and discard it. */
+               tmp_len = sizeof(tmp_addr);
+               if ((cc = recvfrom(s1, chpw_rep.data, (int) chpw_rep.length, 
+                                  0, &tmp_addr, &tmp_len)) < 0) 
+                 {
+                   code = SOCKET_ERRNO;
+                   goto cleanup;
+                 }
+
+               closesocket(s1);
+               s1 = INVALID_SOCKET;
+               closesocket(s2);
+               s2 = INVALID_SOCKET;
+
+               chpw_rep.length = cc;
+
+               if ((code = krb5_auth_con_setaddrs(context, auth_context,
+                                                  NULL, &remote_kaddr)))
+                 goto cleanup;
+
+               if ((code = krb5_rd_chpw_rep(context, auth_context, &chpw_rep,
+                                            &local_result_code, 
+                                            result_string)))
+                 goto cleanup;
+
+               if (result_code)
+                 *result_code = local_result_code;
+
+               if (result_code_string) 
+                 {
+                   if ((code = krb5_chpw_result_code_string(context, 
+                                                            local_result_code,
+                                                            &code_string)))
+                         goto cleanup;
+
+                   result_code_string->length = strlen(code_string);
+                   if ((result_code_string->data =
+                           (char *) malloc(result_code_string->length)) == NULL)
+                         return(ENOMEM);
+                   strncpy(result_code_string->data, code_string, result_code_string->length);
+                 }
+
+               code = 0;
                goto cleanup;
-
-           result_code_string->length = strlen(code_string);
-           if ((result_code_string->data =
-                (char *) malloc(result_code_string->length)) == NULL)
-               return(ENOMEM);
-           strncpy(result_code_string->data, code_string, result_code_string->length);
-       }
-
-       code = 0;
-       goto cleanup;
-    }
+      }
 
     code = SOCKET_ERRNO;
-
+    
 cleanup:
-    if (auth_context != NULL)
-       krb5_auth_con_free(context, auth_context);
-
-    if (addr_p != NULL) {
-       for (i = 0; i < naddr_p; i++)
-           krb5_xfree (addr_p[i]);
-       krb5_xfree(addr_p);
-    }
-
-    if (s1 != INVALID_SOCKET)
-       closesocket(s1);
-
-    if (s2 != INVALID_SOCKET)
-       closesocket(s2);
-
+    if(auth_context != NULL)
+      krb5_auth_con_free(context, auth_context);
+    
+    if(addr_p != NULL)
+      krb5_xfree(addr_p);
+    
+    if(s1 != INVALID_SOCKET)
+      closesocket(s1);
+    
+    if(s2 != INVALID_SOCKET)
+      closesocket(s2);
+      
     krb5_free_data_contents(context, &chpw_req);
     krb5_free_data_contents(context, &chpw_rep);
-    krb5_free_data_contents(context, &ap_req);
-
+       krb5_free_data_contents(context, &ap_req);
+    
     return(code);
 }
index 808f868fc16bfb367da88728123fc005688d8efd..48a0147700d363d094285c5434f2d999e712a045 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lib/krb5/os/locate_kdc.c
  *
- * Copyright 1990,2000,2001 by the Massachusetts Institute of Technology.
+ * Copyright 1990 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -50,6 +50,9 @@
 #endif
 
 #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
+#ifndef KPASSWD_PORTNAME
+#define KPASSWD_PORTNAME "kpasswd"
+#endif
 
 #if KRB5_DNS_LOOKUP_KDC
 #define DEFAULT_LOOKUP_KDC 1
@@ -104,286 +107,32 @@ _krb5_use_dns_realm(context)
 
 #endif /* KRB5_DNS_LOOKUP */
 
-static int get_port (const char *service, int stream, int defalt)
-{
-#ifdef HAVE_GETADDRINFO
-    struct addrinfo hints = { 0 };
-    struct addrinfo *ai;
-    int err;
-
-    hints.ai_family = PF_INET;
-    hints.ai_socktype = stream ? SOCK_STREAM : SOCK_DGRAM;
-    err = getaddrinfo (NULL, service, &hints, &ai);
-    if (err == 0 && ai != 0) {
-       if (ai->ai_addr->sa_family == AF_INET) {
-           int port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
-           freeaddrinfo (ai);
-           return port;
-       }
-       freeaddrinfo (ai);
-    }
-    /* Any error - don't complain, just use default.  */
-    return htons (defalt);
-#else
-    struct servent *sp;
-    sp = getservbyname (service, stream ? "tcp" : "udp"); /* NOT THREAD SAFE */
-    if (sp)
-       return sp->s_port;
-    return htons (defalt);
-#endif
-}
-
-struct addrlist {
-    struct sockaddr **addrs;
-    int naddrs;
-    int space;
-};
-#define ADDRLIST_INIT { 0, 0, 0 }
-
-static int
-grow_list (struct addrlist *lp, int nmore)
-{
-    int i;
-    int newspace = lp->space + nmore;
-    size_t newsize = newspace * sizeof (struct addrlist);
-    struct sockaddr **newaddrs;
-
-    newaddrs = realloc (lp->addrs, newsize);
-
-    if (newaddrs == NULL)
-       return errno;
-    for (i = lp->space; i < newspace; i++)
-       newaddrs[i] = NULL;
-    lp->addrs = newaddrs;
-    lp->space = newspace;
-    return 0;
-}
-
-static void
-free_list (struct addrlist *lp)
-{
-    int i;
-    for (i = 0; i < lp->naddrs; i++)
-       free (lp->addrs[i]);
-    free (lp->addrs);
-    lp->addrs = NULL;
-    lp->naddrs = lp->space = 0;
-}
-
-static int
-add_sockaddr_to_list (struct addrlist *lp, const struct sockaddr *addr,
-                     size_t len)
-{
-    struct sockaddr *copy;
-
-#ifdef TEST
-    fprintf (stderr, "\tadding sockaddr family %2d", addr->sa_family);
-    if (addr->sa_family == AF_INET)
-       fprintf (stderr, "\t%s",
-                inet_ntoa (((const struct sockaddr_in *)addr)->sin_addr));
-    fprintf (stderr, "\n");
-#endif
-
-    if (lp->naddrs == lp->space) {
-       int err = grow_list (lp, 1);
-       if (err)
-           return err;
-    }
-    copy = malloc (len);
-    if (copy == NULL)
-       return errno;
-    memcpy (copy, addr, len);
-    lp->addrs[lp->naddrs++] = copy;
-    return 0;
-}
-
-#ifdef HAVE_GETADDRINFO
-static int translate_ai_error (int err)
-{
-    switch (err) {
-    case 0:
-       return 0;
-    case EAI_ADDRFAMILY:
-    case EAI_BADFLAGS:
-    case EAI_FAMILY:
-    case EAI_SOCKTYPE:
-    case EAI_SERVICE:
-       /* All of these indicate bad inputs to getaddrinfo.  */
-       return EINVAL;
-    case EAI_AGAIN:
-       /* Translate to standard errno code.  */
-       return EAGAIN;
-    case EAI_MEMORY:
-       /* Translate to standard errno code.  */
-       return ENOMEM;
-    case EAI_NODATA:
-    case EAI_NONAME:
-       /* Name not known or no address data, but no error.  Do
-          nothing more.  */
-       return 0;
-    case EAI_SYSTEM:
-       /* System error, duh.  */
-       return errno;
-    default:
-       /* An error code we haven't handled?  */
-       return EINVAL;
-    }
-}
-
-static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
-{
-    return add_sockaddr_to_list (lp, a->ai_addr, a->ai_addrlen);
-}
-
-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;
-    case AF_INET6:
-       ((struct sockaddr_in6 *)addr)->sin6_port = num;
-       break;
-    }
-}
-#endif
-
-/* There's also gethostbyname_r, which is IPv4-only but thread-safe;
-   it wants the caller to supply scratch space and a hostent
-   structure.  Let's go for IPv6 support before thread safety, though;
-   it's easier to accomplish, and will probably be finished first
-   anyways.  */
-#if !defined (HAVE_GETADDRINFO) && !defined (HAVE_GETIPNODEBYNAME)
-#undef getipnodebyname
-#define freehostent(X) ((void)(X))
-#ifdef HAVE_GETHOSTBYNAME2
-#define getipnodebyname(NAME,AF,FLAGS,ERRP) (gethostbyname2(NAME,AF))
-#else
-#define getipnodebyname(NAME,AF,FLAGS,ERRP) ((AF)==AF_INET?gethostbyname(NAME):(struct hostent *)0)
-#endif
-#endif
-
-static int
-add_host_to_list (struct addrlist *lp, const char *hostname,
-                 int port, int secport)
-{
-#ifdef HAVE_GETADDRINFO
-    int err;
-    struct addrinfo *addrs, *a;
-
-#ifdef TEST
-    fprintf (stderr, "adding hostname %s, ports %d,%d\n", hostname,
-            ntohs (port), ntohs (secport));
-#endif
-
-    err = getaddrinfo (hostname, NULL, NULL, &addrs);
-    if (err)
-       return translate_ai_error (err);
-    for (a = addrs; a; a = a->ai_next) {
-       set_port_num (a->ai_addr, port);
-       err = add_addrinfo_to_list (lp, a);
-       if (err)
-           break;
-
-       if (secport == 0)
-           continue;
-
-       set_port_num (a->ai_addr, secport);
-       err = add_addrinfo_to_list (lp, a);
-       if (err)
-           break;
-    }
-    freeaddrinfo (addrs);
-    return err;
-#else
-    int err;
-    struct hostent *hp;
-    int i;
-
-#ifdef TEST
-    fprintf (stderr, "adding hostname %s, ports %d,%d\n", hostname, port, secport);
-#endif
-
-    hp = getipnodebyname (hostname, AF_INET, 0, &err);
-    if (hp != NULL) {
-       for (i = 0; hp->h_addr_list[i] != 0; i++) {
-           struct sockaddr_in sin4;
-
-           memset (&sin4, 0, sizeof (sin4));
-           memcpy (&sin4.sin_addr, hp->h_addr_list[i],
-                   sizeof (sin4.sin_addr));
-           sin4.sin_family = AF_INET;
-           sin4.sin_port = port;
-           err = add_sockaddr_to_list (lp, (struct sockaddr *) &sin4,
-                                       sizeof (sin4));
-           if (err)
-               break;
-           if (secport != 0) {
-               sin4.sin_port = secport;
-               err = add_sockaddr_to_list (lp, (struct sockaddr *) &sin4,
-                                           sizeof (sin4));
-           }
-
-           if (err)
-               break;
-       }
-       freehostent (hp);
-    }
-#if defined (KRB5_USE_INET6)
-    hp = getipnodebyname (hostname, AF_INET6, 0, &err); /* NOT THREAD SAFE */
-    if (hp != NULL) {
-       for (i = 0; hp->h_addr_list[i] != 0; i++) {
-           struct sockaddr_in6 sin6;
-
-           memset (&sin6, 0, sizeof (sin6));
-           memcpy (&sin6.sin6_addr, hp->h_addr_list[i],
-                   sizeof (sin6.sin6_addr));
-           sin6.sin6_family = AF_INET6;
-           sin6.sin6_port = port;
-           err = add_sockaddr_to_list (lp, (struct sockaddr *) &sin6,
-                                       sizeof (sin6));
-           if (err)
-               break;
-           if (secport != 0) {
-               sin6.sin6_port = secport;
-               err = add_sockaddr_to_list (lp, (struct sockaddr *) &sin6,
-                                           sizeof (sin6));
-               if (err)
-                   break;
-           }
-       }
-       freehostent (hp);
-    }
-#endif
-    return 0;
-#endif
-}
-
 /*
  * returns count of number of addresses found
  * if master is non-NULL, it is filled in with the index of
  * the master kdc
  */
 
-static krb5_error_code
-krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
-                      udpport, sec_udpport)
+krb5_error_code
+krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters)
     krb5_context context;
     const krb5_data *realm;
     const char * name;
-    struct addrlist *addrlist;
+    struct sockaddr **addr_pp;
+    int *naddrs;
     int get_masters;
-    int udpport, sec_udpport;
 {
     const char *realm_srv_names[4];
     char **masterlist, **hostlist, *host, *port, *cp;
     krb5_error_code code;
-    int i, j, count, ismaster;
-
-#ifdef TEST
-    fprintf (stderr,
-            "looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
-            realm->data, name, ntohs (udpport), ntohs (sec_udpport));
+    int i, j, out, count, ismaster;
+    struct sockaddr *addr_p;
+    struct sockaddr_in *sin_p;
+    struct hostent *hp;
+    struct servent *sp;
+#ifdef HAVE_NETINET_IN_H
+    u_short udpport;
+    u_short sec_udpport;
 #endif
 
     if ((host = malloc(realm->length + 1)) == NULL) 
@@ -409,6 +158,27 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
        return code;
      }
 
+#ifdef HAVE_NETINET_IN_H
+    if ( !strcmp(name,"kpasswd_server") ) {
+        if ((sp = getservbyname(KPASSWD_PORTNAME, "udp")))
+            udpport = sp->s_port;
+        else
+            udpport = htons(DEFAULT_KPASSWD_PORT);
+        sec_udpport = 0;
+    } else {
+    if ((sp = getservbyname(KDC_PORTNAME, "udp")))
+       udpport = sp->s_port;
+        else 
+            udpport = htons(KRB5_DEFAULT_PORT);
+    if ((sp = getservbyname(KDC_SECONDARY_PORTNAME, "udp")))
+       sec_udpport = sp->s_port;
+        else
+            sec_udpport = htons(KRB5_DEFAULT_SEC_PORT);
+    }
+#endif
+    if (sec_udpport == udpport)
+       sec_udpport = 0;
+
     count = 0;
     while (hostlist && hostlist[count])
            count++;
@@ -416,7 +186,7 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
     if (count == 0) {
         profile_free_list(hostlist);
        krb5_xfree(host);
-       addrlist->naddrs = 0;
+       *naddrs = 0;
        return 0;
     }
     
@@ -462,9 +232,16 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
            count = count * 2;
 #endif
 
-    for (i=0; hostlist[i]; i++) {
-       int p1, p2;
+    addr_p = (struct sockaddr *)malloc (sizeof (struct sockaddr) * count);
+    if (addr_p == NULL) {
+        if (hostlist)
+            profile_free_list(hostlist);
+        if (masterlist)
+            profile_free_list(masterlist);
+       return ENOMEM;
+    }
 
+    for (i=0, out=0; hostlist[i]; i++) {
        host = hostlist[i];
        /*
         * Strip off excess whitespace
@@ -481,6 +258,10 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
            port++;
        }
 
+       if ((hp = gethostbyname(hostlist[i])) == 0) {
+           continue;
+       }
+
        ismaster = 0;
        if (masterlist) {
            for (j=0; masterlist[j]; j++) {
@@ -490,37 +271,44 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
            }
        }
 
-       if (get_masters && !ismaster)
-           continue;
+        if ( !get_masters || ismaster ) {
+            switch (hp->h_addrtype) {
 
-       if (port) {
-           unsigned long l;
-#ifdef HAVE_STROUL
-           char *endptr;
-           l = strtoul (port, &endptr, 10);
-           if (endptr == NULL || *endptr != 0)
-               return EINVAL;
-#else
-           l = atoi (port);
+#ifdef HAVE_NETINET_IN_H
+            case AF_INET:
+                for (j=0; hp->h_addr_list[j]; j++) {
+                    sin_p = (struct sockaddr_in *) &addr_p[out++];
+                    memset ((char *)sin_p, 0, sizeof(struct sockaddr));
+                    sin_p->sin_family = hp->h_addrtype;
+                    sin_p->sin_port = port ? htons(atoi(port)) : udpport;
+                    memcpy((char *)&sin_p->sin_addr,
+                            (char *)hp->h_addr_list[j],
+                            sizeof(struct in_addr));
+                    if (out+1 >= count) {
+                        count += 5;
+                        addr_p = (struct sockaddr *)
+                            realloc ((char *)addr_p,
+                                      sizeof(struct sockaddr) * count);
+                        if (addr_p == NULL) {
+                            if ( hostlist )
+                                profile_free_list(hostlist);
+                            if ( masterlist )
+                                profile_free_list(masterlist);
+                            return ENOMEM;
+                        }
+                    }
+                    if (sec_udpport && !port) {
+                        addr_p[out] = addr_p[out-1];
+                        sin_p = (struct sockaddr_in *) &addr_p[out++];
+                        sin_p->sin_port = sec_udpport;
+                    }
+                }
+                break;
 #endif
-           /* L is unsigned, don't need to check <0.  */
-           if (l > 65535)
-               return EINVAL;
-           p1 = htons (l);
-           p2 = 0;
-       } else {
-           p1 = udpport;
-           p2 = sec_udpport;
-       }
-
-       code = add_host_to_list (addrlist, hostlist[i], p1, p2);
-       if (code) {
-           if (hostlist)
-               profile_free_list (hostlist);
-           if (masterlist)
-               profile_free_list (masterlist);
-           return code;
-       }
+            default:
+                break;
+            }
+        }
     }
 
     if (hostlist)
@@ -528,56 +316,40 @@ krb5_locate_srv_conf_1(context, realm, name, addrlist, get_masters,
     if (masterlist)
         profile_free_list(masterlist);
 
-    return 0;
-}
-
-static krb5_error_code
-krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters,
-                    udpport, sec_udpport)
-    krb5_context context;
-    const krb5_data *realm;
-    const char * name;
-    struct sockaddr ***addr_pp;
-    int *naddrs;
-    int get_masters;
-    int udpport, sec_udpport;
-{
-    krb5_error_code ret;
-    struct addrlist al = ADDRLIST_INIT;
-
-    ret = krb5_locate_srv_conf_1 (context, realm, name, &al,
-                                 get_masters, udpport, sec_udpport);
-    if (ret) {
-       free_list (&al);
-       return ret;
+    if (out == 0) {     /* Couldn't resolve any KDC names */
+        free (addr_p);
+        return KRB5_REALM_CANT_RESOLVE;
     }
-    if (al.naddrs == 0)                /* Couldn't resolve any KDC names */
-       return KRB5_REALM_CANT_RESOLVE;
-    *addr_pp = al.addrs;
-    *naddrs = al.naddrs;
+
+    *addr_pp = addr_p;
+    *naddrs = out;
     return 0;
 }
 
-
 #ifdef KRB5_DNS_LOOKUP
 
 /*
  * Lookup a KDC via DNS SRV records
  */
 
-static krb5_error_code
-krb5_locate_srv_dns_1 (realm, service, protocol, addrlist)
+krb5_error_code
+krb5_locate_srv_dns(realm, service, protocol, addr_pp, naddrs)
     const krb5_data *realm;
     const char *service;
     const char *protocol;
-    struct addrlist *addrlist;
+    struct sockaddr **addr_pp;
+    int *naddrs;
 {
+    int out, j, count;
     union {
         unsigned char bytes[2048];
         HEADER hdr;
     } answer;
     unsigned char *p=NULL;
     char host[MAX_DNS_NAMELEN], *h;
+    struct sockaddr *addr = NULL;
+    struct sockaddr_in *sin_p = NULL;
+    struct hostent *hp = NULL;
     int type, class;
     int priority, weight, size, len, numanswers, numqueries, rdlen;
     unsigned short port;
@@ -592,7 +364,13 @@ krb5_locate_srv_dns_1 (realm, service, protocol, addrlist)
 
     struct srv_dns_entry *head = NULL;
     struct srv_dns_entry *srv = NULL, *entry = NULL;
-    krb5_error_code code = 0;
+
+    out = 0;
+    addr = (struct sockaddr *) malloc(sizeof(struct sockaddr));
+    if (addr == NULL)
+       return ENOMEM;
+
+    count = 1;
 
     /*
      * First off, build a query of the form:
@@ -612,22 +390,19 @@ krb5_locate_srv_dns_1 (realm, service, protocol, addrlist)
            realm->data);
 
     /* Realm names don't (normally) end with ".", but if the query
-       doesn't end with "." and doesn't get an answer as is, the
-       resolv code will try appending the local domain.  Since the
-       realm names are absolutes, let's stop that.  
+    doesn't end with "." and doesn't get an answer as is, the
+    resolv code will try appending the local domain.  Since the
+    realm names are absolutes, let's stop that.  
 
-       But only if a name has been specified.  If we are performing
-       a search on the prefix alone then the intention is to allow
-       the local domain or domain search lists to be expanded.  */
+    But only if a name has been specified.  If we are performing
+    a search on the prefix alone then the intention is to allow
+    the local domain or domain search lists to be expanded.
+    */
 
     h = host + strlen (host);
     if ((h > host) && (h[-1] != '.') && ((h - host + 1) < sizeof(host)))
         strcpy (h, ".");
 
-#ifdef TEST
-    fprintf (stderr, "sending DNS SRV query for %s\n", host);
-#endif
-
     size = res_search(host, C_IN, T_SRV, answer.bytes, sizeof(answer.bytes));
 
     if (size < hdrsize)
@@ -771,20 +546,36 @@ krb5_locate_srv_dns_1 (realm, service, protocol, addrlist)
     if (head == NULL)
        goto out;
 
-#ifdef TEST
-    fprintf (stderr, "walking answer list:\n");
-#endif
     for (entry = head; entry != NULL; entry = entry->next) {
-#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);
-       if (code)
-           break;
+       hp = gethostbyname(entry->host);
+       if (hp != 0) {
+           switch (hp->h_addrtype) {
+#ifdef HAVE_NETINET_IN_H
+            case AF_INET:
+               for (j=0; hp->h_addr_list[j]; j++) {
+                   sin_p = (struct sockaddr_in *) &addr[out++];
+                   memset ((char *) sin_p, 0, sizeof (struct sockaddr));
+                   sin_p->sin_family = hp->h_addrtype;
+                   sin_p->sin_port = htons(entry->port);
+                   memcpy((char *) &sin_p->sin_addr,
+                          (char *) hp->h_addr_list[j],
+                          sizeof(struct in_addr));
+                   if (out + 1 >= count) {
+                       count += 5;
+                       addr = (struct sockaddr *)
+                               realloc((char *) addr,
+                                       sizeof(struct sockaddr) * count);
+                       if (!addr)
+                           goto out;
+                   }
+               }
+               break;
+#endif /* HAVE_NETINET_IN_H */
+           default:
+               break;
+           }
+       }
     }
-#ifdef TEST
-    fprintf (stderr, "[end]\n");
-#endif
 
     for (entry = head; entry != NULL; ) {
        free(entry->host);
@@ -799,22 +590,15 @@ krb5_locate_srv_dns_1 (realm, service, protocol, addrlist)
     if (srv)
         free(srv);
 
-    return code;
-}
-
-static krb5_error_code
-krb5_locate_srv_dns(realm, service, protocol, addr_pp, naddrs)
-    const krb5_data *realm;
-    const char *service;
-    const char *protocol;
-    struct sockaddr ***addr_pp;
-    int *naddrs;
-{
-    struct addrlist al = ADDRLIST_INIT;
-    krb5_error_code code;
+    if (out == 0) {    /* No good servers */
+        if (addr)
+            free(addr);
+       return KRB5_REALM_CANT_RESOLVE;
+    }
 
-    code = krb5_locate_srv_dns_1 (realm, service, protocol, &al);
-    return code;
+    *addr_pp = addr;
+    *naddrs = out;
+    return 0;
 }
 #endif /* KRB5_DNS_LOOKUP */
 
@@ -823,63 +607,56 @@ krb5_locate_srv_dns(realm, service, protocol, addr_pp, naddrs)
  */
 
 krb5_error_code
-krb5int_locate_server (krb5_context context, const krb5_data *realm,
-                      struct sockaddr ***addr_pp, int *naddrs,
-                      int get_masters,
-                      const char *profname, const char *dnsname,
-                      int is_stream,
-                      /* network order port numbers! */
-                      int dflport1, int dflport2)
+krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters)
+    krb5_context context;
+    const krb5_data *realm;
+    struct sockaddr **addr_pp;
+    int *naddrs;
+    int get_masters;
 {
     krb5_error_code code;
-    struct addrlist al = ADDRLIST_INIT;
 
     /*
      * We always try the local file first
      */
 
-    code = krb5_locate_srv_conf(context, realm, profname, &al, get_masters);
+    code = krb5_locate_srv_conf(context, realm, "kdc", addr_pp, naddrs,
+                                 get_masters);
 
 #ifdef KRB5_DNS_LOOKUP
     if (code) {
-       int use_dns = _krb5_use_dns_kdc(context);
-       if (use_dns)
-           code = krb5_locate_srv_dns(realm, dnsname,
-                                      is_stream ? "_tcp" : "_udp", &al);
+        int use_dns = _krb5_use_dns_kdc(context);
+        if ( use_dns ) {
+            code = krb5_locate_srv_dns(realm, 
+                                        get_masters ? "_kerberos-master" : "_kerberos",
+                                        "_udp", addr_pp, naddrs);
+        }
     }
 #endif /* KRB5_DNS_LOOKUP */
-    if (al.naddrs == 0) {      /* No good servers */
-       return KRB5_REALM_CANT_RESOLVE;
-    }
-    if (code == 0) {
-       *addr_pp = al.addrs;
-       *naddrs = al.naddrs;
-    }
-    return code;
+    return (code);
 }
 
+#if 0 /* Why is this useful?  It's not used now, and it's certainly
+        not useful if you don't have the DNS code enabled.  -KR  */
+
+/*
+ * It turns out that it is really useful to be able to use these functions
+ * for other things (like admin servers), so create an abstract function
+ * for this
+ */
+
 krb5_error_code
-krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters)
-    krb5_context context;
+krb5_locate_server(realm, name, proto, addr_pp, naddrs)
     const krb5_data *realm;
-    struct sockaddr ***addr_pp;
+    const char *name, *proto;
+    struct sockaddr **addr_pp;
     int *naddrs;
-    int get_masters;
 {
-    int udpport, sec_udpport;
-
-    udpport = get_port (KDC_PORTNAME, 0, KRB5_DEFAULT_PORT);
-    sec_udpport = get_port (KDC_SECONDARY_PORTNAME, 0,
-                           (udpport == htons (KRB5_DEFAULT_PORT)
-                            ? KRB5_DEFAULT_SEC_PORT
-                            : KRB5_DEFAULT_PORT));
-    if (sec_udpport == udpport)
-       sec_udpport = 0;
-
-    return krb5int_locate_server (context, realm, addr_pp, naddrs, get_masters,
-                                 "kdc",
-                                 (get_masters
-                                  ? "_kerberos-master"
-                                  : "_kerberos"),
-                                 0, udpport, sec_udpport);
+    krb5_error_code code = KRB5_REALM_UNKNOWN;
+#ifdef KRB5_DNS_LOOKUP
+    code = krb5_locate_srv_dns(realm, name, proto,
+                                (struct sockaddr **) addr_pp, naddrs);
+#endif /* KRB5_DNS_LOOKUP */
+    return (code);
 }
+#endif
index ceba9b477f1258936fc4193fc39f493079b12d23..12e2afb4813adf7cf3de176f6c4e62d103ab5adc 100644 (file)
@@ -34,7 +34,7 @@
 krb5_error_code krb5_locate_kdc
     PROTOTYPE((krb5_context,
               const krb5_data *,
-              struct sockaddr ***,
+              struct sockaddr **,
               int *,
               int));
 #endif
index 86665b412bde540d8287565d1e0febf9961a7b82..58c97f837cc3fc4aba0ed23a3e439d6e95b8c9ac 100644 (file)
@@ -63,7 +63,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
     int use_master;
 {
     register int timeout, host, i;
-    struct sockaddr **addr;
+    struct sockaddr *addr;
     int naddr;
     int sent, nready;
     krb5_error_code retval;
@@ -90,8 +90,6 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
        socklist[i] = INVALID_SOCKET;
 
     if (!(reply->data = malloc(krb5_max_dgram_size))) {
-       for (i = 0; i < naddr; i++)
-           krb5_xfree (addr[i]);
        krb5_xfree(addr);
        krb5_xfree(socklist);
        return ENOMEM;
@@ -135,7 +133,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
                 * protocol exists to support a particular socket type
                 * within a given protocol family.
                 */
-               socklist[host] = socket(addr[host]->sa_family, SOCK_DGRAM, 0);
+               socklist[host] = socket(addr[host].sa_family, SOCK_DGRAM, 0);
                if (socklist[host] == INVALID_SOCKET)
                    continue;           /* try other hosts */
                /* have a socket to send/recv from */
@@ -145,7 +143,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],
-                           addr[host], sizeof(addr[host])) == SOCKET_ERROR)
+                           &addr[host], sizeof(addr[host])) == SOCKET_ERROR)
                  continue;
            }
            if (send(socklist[host],