Use a "struct addrlist" instead of separate count and pointer-to-pointer values
authorKen Raeburn <raeburn@mit.edu>
Wed, 20 Jun 2001 00:00:05 +0000 (00:00 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 20 Jun 2001 00:00:05 +0000 (00:00 +0000)
for internal interfaces for looking up servers.  Add a new routine to free the
addrlist contents, so that memory management can be changed in one place.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13390 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/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 cb73197a184511b66bad212051c33ce62f10f6c2..8858905f8107aadfd80bf6a577fc581ee8ad65f7 100644 (file)
@@ -1,3 +1,13 @@
+2001-06-19  Ken Raeburn  <raeburn@mit.edu>
+
+       * k5-int.h (struct addrlist): New type.
+       (ADDRLIST_INIT): New macro.
+       (krb5int_free_addrlist): Declare.
+       (krb5int_locate_server): Update declaration.
+       (KRB5INT_ACCESS_STRUCT_VERSION): Update to 3.
+       (struct _krb5int_access): Change locale_server prototype.  Add
+       free_addrlist function pointer field.
+
 2001-06-11  Ezra Peisach  <epeisach@mit.edu>
 
        * k5-util.h: Add prototypes for krb5_compat_recvauth_version() and
index 0a6c9a8fb2b76436b4e0dc4a6e7129c6029345e2..a58d2821da94367300f3fece85cb1cc9737ddeb8 100644 (file)
@@ -544,14 +544,18 @@ void krb5_os_free_context (krb5_context);
 
 krb5_error_code krb5_find_config_files (void);
 
+struct addrlist {
+    struct sockaddr **addrs;
+    int naddrs;
+    int space;
+};
+#define ADDRLIST_INIT { 0, 0, 0 }
+extern void krb5int_free_addrlist (struct addrlist *);
+
 krb5_error_code
 krb5int_locate_server (krb5_context,
                       const krb5_data *realm,
-                      /* Thing pointed to will be filled in with a
-                         pointer to a block of sockaddr pointers,
-                         with each sockaddr allocated separately
-                         (wasteful, oh well).  */
-                      struct sockaddr ***addrs, int *naddrs,
+                      struct addrlist *,
                       /* Only meaningful for kdc, really...  */
                       int want_masters,
                       /* look up [realms]->$realm->$name in krb5.conf */
@@ -1566,16 +1570,16 @@ void krb5int_set_prompt_types
 /* To keep happy libraries which are (for now) accessing internal stuff */
 
 /* Make sure to increment by one when changing the struct */
-#define KRB5INT_ACCESS_STRUCT_VERSION 2
+#define KRB5INT_ACCESS_STRUCT_VERSION 3
 
 typedef struct _krb5int_access {
     krb5_error_code (*krb5_locate_kdc) (krb5_context, const krb5_data *,
-                                       struct sockaddr ***, int *, int);
+                                       struct addrlist *, int);
     krb5_error_code (*krb5_locate_server) (krb5_context, const krb5_data *,
-                                          struct sockaddr ***, int *,
-                                          int,
+                                          struct addrlist *, int,
                                           const char *, const char *,
                                           int, int, int);
+    void (*free_addrlist) (struct addrlist *);
     unsigned int krb5_max_skdc_timeout;
     unsigned int krb5_skdc_timeout_shift;
     unsigned int krb5_skdc_timeout_1;
index 9389020038f85ca77a61b910c41671d4f8db9a1a..ba597d54fc2476e9d48fead12bd4bfc78282e136 100644 (file)
@@ -1,3 +1,7 @@
+2001-06-19  Ken Raeburn  <raeburn@mit.edu>
+
+       * sendmsg.c (krb524_sendto_kdc): Use new locate_server interface.
+
 2001-06-06  Ezra Peisach  <epeisach@mit.edu>
 
        * test.c (print_key): Pass in des_cblock* instead of char *.
index 3d7b433a77719f6fb5a4fd17ece3cd5cc3b91749..00c55f0d2a57ac935d4059d5d47ba8eee6572458 100644 (file)
@@ -68,8 +68,7 @@ krb524_sendto_kdc (context, message, realm, reply)
     krb5_data * reply;
 {
     register int timeout, host, i;
-    struct sockaddr **addr;
-    int naddr;
+    struct addrlist al = ADDRLIST_INIT;
     struct servent *serv;
     int sent, nready;
     krb5_error_code retval;
@@ -90,37 +89,37 @@ krb524_sendto_kdc (context, message, realm, reply)
     serv = getservbyname(KRB524_SERVICE, "udp");
     port = serv ? serv->s_port : htons (KRB524_PORT);
 
-    retval = internals.krb5_locate_server(context, realm, &addr, &naddr, 0,
+    retval = internals.krb5_locate_server(context, realm, &al, 0,
                                          "krb524_server", "_krb524",
                                          0, port, 0);
     if (retval == KRB5_REALM_CANT_RESOLVE || retval == KRB5_REALM_UNKNOWN) {
        /* Fallback heuristic: Assume krb524 port on every KDC might
           work.  */
-       retval = internals.krb5_locate_kdc(context, realm, &addr, &naddr, 0);
+       retval = internals.krb5_locate_kdc(context, realm, &al, 0);
        /*
         * Bash the ports numbers.
         */
        if (retval == 0)
-           for (i = 0; i < naddr; i++) {
-               if (addr[i]->sa_family == AF_INET)
-                   sa2sin (addr[i])->sin_port = port;
+           for (i = 0; i < al.naddrs; i++) {
+               if (al.addrs[i]->sa_family == AF_INET)
+                   sa2sin (al.addrs[i])->sin_port = port;
            }
     }
     if (retval)
        return retval;
-    if (naddr == 0)
+    if (al.naddrs == 0)
        return KRB5_REALM_UNKNOWN;
 
-    socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET));
+    socklist = (SOCKET *)malloc(al.naddrs * sizeof(SOCKET));
     if (socklist == NULL) {
-       free(addr);
+       internals.free_addrlist (&al);
        return ENOMEM;
     }
-    for (i = 0; i < naddr; i++)
+    for (i = 0; i < al.naddrs; i++)
        socklist[i] = INVALID_SOCKET;
 
     if (!(reply->data = malloc(internals.krb5_max_dgram_size))) {
-       free(addr);
+       internals.free_addrlist (&al);
        free(socklist);
        return ENOMEM;
     }
@@ -145,10 +144,11 @@ krb524_sendto_kdc (context, message, realm, reply)
      * do exponential backoff.
      */
 
-    for (timeout = internals.krb5_skdc_timeout_1; timeout < internals.krb5_max_skdc_timeout;
+    for (timeout = internals.krb5_skdc_timeout_1;
+        timeout < internals.krb5_max_skdc_timeout;
         timeout <<= internals.krb5_skdc_timeout_shift) {
        sent = 0;
-       for (host = 0; host < naddr; host++) {
+       for (host = 0; host < al.naddrs; host++) {
            /* send to the host, wait timeout seconds for a response,
               then move on. */
            /* cache some sockets for each host */
@@ -163,7 +163,8 @@ krb524_sendto_kdc (context, message, realm, reply)
                 * 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(al.addrs[host]->sa_family, SOCK_DGRAM,
+                                       0);
                if (socklist[host] == INVALID_SOCKET)
                    continue;           /* try other hosts */
                /* have a socket to send/recv from */
@@ -172,12 +173,12 @@ 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],
-                           addr[host], socklen(addr[host])) == SOCKET_ERROR)
+               if (connect(socklist[host], al.addrs[host],
+                           socklen(al.addrs[host])) == SOCKET_ERROR)
                  continue;
            }
-           if (send(socklist[host],
-                      message->data, (int) message->length, 0) != message->length)
+           if (send(socklist[host], message->data, (int) message->length, 0)
+               != message->length)
              continue;
        retry:
            waitlen.tv_usec = 0;
@@ -238,13 +239,13 @@ krb524_sendto_kdc (context, message, realm, reply)
     }
     retval = KRB5_KDC_UNREACH;
  out:
-    for (i = 0; i < naddr; i++)
+    for (i = 0; i < al.naddrs; i++)
        if (socklist[i] != INVALID_SOCKET)
            (void) closesocket (socklist[i]);
 #if 0
     SOCKET_CLEANUP();                           /* Done with sockets for now */
 #endif
-    free(addr);
+    internals.free_addrlist (&al);
     free(socklist);
     if (retval) {
        free(reply->data);
index 2767311a5949bd06690ff2cf673a0b3aa69bd5d1..137ef7680804baefb026e362c66adf0795a5f087 100644 (file)
@@ -1,3 +1,26 @@
+2001-06-19  Ken Raeburn  <raeburn@mit.edu>
+
+       * locate_kdc.c (struct addrlist, ADDRLIST_INIT): Moved to
+       k5-int.h.
+       (krb5int_free_addrlist): Renamed from free_list; no longer
+       static.
+       (krb5_locate_srv_conf, krb5_locate_srv_dns, krb5int_locate_server,
+       krb5_locate_kdc): Use addrlist in interface.
+
+       * sendto_kdc.c (krb5_sendto_kdc): Use new struct addrlist
+       interface.
+
+       * changepw.c (krb5_locate_kpasswd): Use addrlist structure in
+       interface and implementation.
+       (krb5_change_password): Likewise.
+
+       * accessor.c (krb5int_accessor): Fill in free_addrlist function
+       pointer field.
+
+       * os-proto.h (krb5_locate_kdc): Update prototype.
+
+       * t_std_conf.c (test_locate_kdc): Update tests for new API.
+
 2001-06-12  Ezra Peisach  <epeisach@mit.edu>
 
        * sn2princ.c, hst_realm.c, an_to_ln.c: Cast argument to
index d3c842a86ec155c4551ffcd55cb6fbf99edbd7a3..bcf89a7b66467f4b00bf6f0261b7eaaa2c9f8829 100644 (file)
@@ -39,6 +39,7 @@ krb5int_accessor(internals, version)
     krb5int_access internals_temp;
     internals_temp.krb5_locate_server = krb5int_locate_server;
     internals_temp.krb5_locate_kdc = krb5_locate_kdc;
+    internals_temp.free_addrlist = krb5int_free_addrlist;
     internals_temp.krb5_max_skdc_timeout = krb5_max_skdc_timeout;
     internals_temp.krb5_skdc_timeout_shift = krb5_skdc_timeout_shift;
     internals_temp.krb5_skdc_timeout_1 = krb5_skdc_timeout_1;
index 0a6d0e5ee8c643c3955b86dd7db1f39902ed79f4..7153b75ec498e76da07f2d3175749263606061d6 100644 (file)
  */
 
 static krb5_error_code
-krb5_locate_kpasswd(context, realm, addr_pp, naddrs)
-    krb5_context context;
-    const krb5_data *realm;
-    struct sockaddr ***addr_pp;
-    int *naddrs;
+krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
+                   struct addrlist *addrlist)
 {
     krb5_error_code code;
 
-    code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0,
+    code = krb5int_locate_server (context, realm, addrlist, 0,
                                  "kpasswd_server", "_kpasswd", 0,
                                  DEFAULT_KPASSWD_PORT, 0);
     if (code) {
-       code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0,
+       code = krb5int_locate_server (context, realm, addrlist, 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];
+           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);
            }
@@ -100,17 +97,15 @@ krb5_change_password(context, creds, newpw, result_code,
     char *code_string;
     krb5_error_code code = 0;
     int i, addrlen;
-    struct sockaddr **addr_p;
     struct sockaddr_storage local_addr, remote_addr, tmp_addr;
-    int naddr_p;
     int cc, local_result_code, tmp_len;
     SOCKET s1 = INVALID_SOCKET, s2 = INVALID_SOCKET;
     int tried_one = 0;
+    struct addrlist al = ADDRLIST_INIT;
 
 
     /* Initialize values so that cleanup call can safely check for NULL */
     auth_context = NULL;
-    addr_p = NULL;
     memset(&chpw_req, 0, sizeof(krb5_data));
     memset(&chpw_rep, 0, sizeof(krb5_data));
     memset(&ap_req, 0, sizeof(krb5_data));
@@ -126,7 +121,7 @@ krb5_change_password(context, creds, newpw, result_code,
 
     if ((code = krb5_locate_kpasswd(context,
                                     krb5_princ_realm(context, creds->client),
-                                    &addr_p, &naddr_p)))
+                                   &al)))
         goto cleanup;
 
     /* this is really obscure.  s1 is used for all communications.  it
@@ -155,16 +150,23 @@ krb5_change_password(context, creds, newpw, result_code,
        goto cleanup;
     }
 
-    for (i=0; i<naddr_p; i++) {
+    /*
+     * This really should try fallback addresses in cases of timeouts.
+     * For now, where the MIT KDC implementation only supports one
+     * kpasswd server machine anyways, we'll only try the first IPv4
+     * address we can connect() to.  This isn't right for multi-homed
+     * servers; oh well.
+     */
+    for (i=0; i<al.naddrs; i++) {
        fd_set fdset;
        struct timeval timeout;
 
        /* XXX Now the locate_ functions can return IPv6 addresses.  */
-       if (addr_p[i]->sa_family != AF_INET)
+       if (al.addrs[i]->sa_family != AF_INET)
            continue;
 
        tried_one = 1;
-       if (connect(s2, addr_p[i], socklen(addr_p[i])) == SOCKET_ERROR) {
+       if (connect(s2, al.addrs[i], socklen(al.addrs[i])) == SOCKET_ERROR) {
            if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
                continue; /* try the next addr */
 
@@ -244,7 +246,7 @@ krb5_change_password(context, creds, newpw, result_code,
        }
 
        if ((cc = sendto(s1, chpw_req.data, (int) chpw_req.length, 0,
-                        addr_p[i], socklen(addr_p[i]))) != chpw_req.length)
+                        al.addrs[i], socklen(al.addrs[i]))) != chpw_req.length)
        {
            if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
                             (SOCKET_ERRNO == EHOSTUNREACH)))
@@ -316,9 +318,11 @@ krb5_change_password(context, creds, newpw, result_code,
                goto cleanup;
 
            result_code_string->length = strlen(code_string);
-           if ((result_code_string->data =
-                (char *) malloc(result_code_string->length)) == NULL)
-               return(ENOMEM);
+           result_code_string->data = malloc(result_code_string->length);
+           if (result_code_string->data == NULL) {
+               code = ENOMEM;
+               goto cleanup;
+           }
            strncpy(result_code_string->data, code_string, result_code_string->length);
        }
 
@@ -339,11 +343,7 @@ 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);
-    }
+    krb5int_free_addrlist (&al);
 
     if (s1 != INVALID_SOCKET)
        closesocket(s1);
index c518c1f1f6cdc4c20e654b847534f8b7f11a64c3..a4587e08959c141815c7fd103a4e69d567079c84 100644 (file)
@@ -133,13 +133,6 @@ static int get_port (const char *service, int stream, int 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)
 {
@@ -164,8 +157,10 @@ grow_list (struct addrlist *lp, int nmore)
     return 0;
 }
 
-static void
-free_list (struct addrlist *lp)
+/* Free up everything pointed to by the addrlist structure, but don't
+   free the structure itself.  */
+void
+krb5int_free_addrlist (struct addrlist *lp)
 {
     int i;
     for (i = 0; i < lp->naddrs; i++)
@@ -174,6 +169,7 @@ free_list (struct addrlist *lp)
     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,
@@ -516,29 +512,23 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
 
 #ifdef TEST
 static krb5_error_code
-krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters,
+krb5_locate_srv_conf(context, realm, name, al, get_masters,
                     udpport, sec_udpport)
     krb5_context context;
     const krb5_data *realm;
     const char * name;
-    struct sockaddr ***addr_pp;
-    int *naddrs;
+    struct addrlist *al;
     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,
+    ret = krb5_locate_srv_conf_1 (context, realm, name, al,
                                  get_masters, udpport, sec_udpport);
-    if (ret) {
-       free_list (&al);
+    if (ret)
        return ret;
-    }
-    if (al.naddrs == 0)                /* Couldn't resolve any KDC names */
+    if (al->naddrs == 0)       /* Couldn't resolve any KDC names */
        return KRB5_REALM_CANT_RESOLVE;
-    *addr_pp = al.addrs;
-    *naddrs = al.naddrs;
     return 0;
 }
 #endif
@@ -789,15 +779,9 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
 static krb5_error_code
 krb5_locate_srv_dns(const krb5_data *realm,
                    const char *service, const char *protocol,
-                   struct sockaddr ***addr_pp, int *naddrs)
+                   struct addrlist *al)
 {
-    struct addrlist al = ADDRLIST_INIT;
-    krb5_error_code code;
-
-    code = krb5_locate_srv_dns_1 (realm, service, protocol, &al);
-    *addr_pp = al.addrs;
-    *naddrs = al.naddrs;
-    return code;
+    return krb5_locate_srv_dns_1 (realm, service, protocol, al);
 }
 #endif
 #endif /* KRB5_DNS_LOOKUP */
@@ -808,7 +792,7 @@ krb5_locate_srv_dns(const krb5_data *realm,
 
 krb5_error_code
 krb5int_locate_server (krb5_context context, const krb5_data *realm,
-                      struct sockaddr ***addr_pp, int *naddrs,
+                      struct addrlist *addrlist,
                       int get_masters,
                       const char *profname, const char *dnsname,
                       int is_stream,
@@ -818,6 +802,8 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm,
     krb5_error_code code;
     struct addrlist al = ADDRLIST_INIT;
 
+    *addrlist = al;
+
     /*
      * We always try the local file first
      */
@@ -851,18 +837,14 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm,
            free_list (&al);
        return KRB5_REALM_CANT_RESOLVE;
     }
-    *addr_pp = al.addrs;
-    *naddrs = al.naddrs;
+    *addrlist = al;
     return 0;
 }
 
 krb5_error_code
-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_locate_kdc(krb5_context context, const krb5_data *realm,
+               struct addrlist *addrlist,
+               int get_masters)
 {
     int udpport, sec_udpport;
 
@@ -874,8 +856,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters)
     if (sec_udpport == udpport)
        sec_udpport = 0;
 
-    return krb5int_locate_server (context, realm, addr_pp, naddrs, get_masters,
-                                 "kdc",
+    return krb5int_locate_server (context, realm, addrlist, get_masters, "kdc",
                                  (get_masters
                                   ? "_kerberos-master"
                                   : "_kerberos"),
index ceba9b477f1258936fc4193fc39f493079b12d23..7be2c3fc6781e75ee101e25bed198b65758e7c5f 100644 (file)
 
 #ifdef SOCK_DGRAM                      /* XXX hack... */
 krb5_error_code krb5_locate_kdc
-    PROTOTYPE((krb5_context,
-              const krb5_data *,
-              struct sockaddr ***,
-              int *,
-              int));
+    PROTOTYPE((krb5_context, const krb5_data *, struct addrlist *, int));
 #endif
 
 #ifdef HAVE_NETINET_IN_H
index 486066b56cafda4e79771cb6d340a82a00e07f3d..45e6d00b3c4e914e98070e364cd1dee5795ba870 100644 (file)
@@ -62,37 +62,36 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
     krb5_data * reply;
     int use_master;
 {
-    register int timeout, host, i;
-    struct sockaddr **addr;
-    int naddr;
+    int timeout, host, i;
     int sent, nready;
     krb5_error_code retval;
     SOCKET *socklist;
     fd_set readable;
     struct timeval waitlen;
     int cc;
+    struct addrlist addrs;
 
     /*
      * find KDC location(s) for realm
      */
 
-    if ((retval = krb5_locate_kdc(context, realm, &addr, &naddr, use_master)))
+    if ((retval = krb5_locate_kdc(context, realm, &addrs, use_master)))
        return retval;
-    if (naddr == 0)
+    if (addrs.naddrs == 0)
        return (use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN);
 
-    socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET));
+    socklist = (SOCKET *)malloc(addrs.naddrs * sizeof(SOCKET));
     if (socklist == NULL) {
-       krb5_xfree(addr);
+       krb5int_free_addrlist (&addrs);
        return ENOMEM;
     }
-    for (i = 0; i < naddr; i++)
+    for (i = 0; i < addrs.naddrs; i++)
        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);
+       for (i = 0; i < addrs.naddrs; i++)
+           krb5_xfree (addrs.addrs[i]);
+       krb5int_free_addrlist (&addrs);
        krb5_xfree(socklist);
        return ENOMEM;
     }
@@ -106,7 +105,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
      * See below for commented out SOCKET_CLEANUP()
      */
     if (SOCKET_INITIALIZE()) {  /* PC needs this for some tcp/ip stacks */
-       krb5_xfree(addr);
+       krb5int_free_addrlist (&addrs);
        krb5_xfree(socklist);
        free(reply->data);
         return SOCKET_ERRNO;
@@ -120,7 +119,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
     for (timeout = krb5_skdc_timeout_1; timeout < krb5_max_skdc_timeout;
         timeout <<= krb5_skdc_timeout_shift) {
        sent = 0;
-       for (host = 0; host < naddr; host++) {
+       for (host = 0; host < addrs.naddrs; host++) {
            /* send to the host, wait timeout seconds for a response,
               then move on. */
            /* cache some sockets for each host */
@@ -135,7 +134,8 @@ 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(addrs.addrs[host]->sa_family,
+                                       SOCK_DGRAM, 0);
                if (socklist[host] == INVALID_SOCKET)
                    continue;           /* try other hosts */
                /* have a socket to send/recv from */
@@ -145,7 +145,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], socklen(addr[host])) == SOCKET_ERROR)
+                           addrs.addrs[host], socklen(addrs.addrs[host])) == SOCKET_ERROR)
                  continue;
            }
            if (send(socklist[host],
@@ -214,13 +214,13 @@ krb5_sendto_kdc (context, message, realm, reply, use_master)
     }
     retval = KRB5_KDC_UNREACH;
  out:
-    for (i = 0; i < naddr; i++)
+    for (i = 0; i < addrs.naddrs; i++)
        if (socklist[i] != INVALID_SOCKET)
            (void) closesocket (socklist[i]);
 #if 0
     SOCKET_CLEANUP();                           /* Done with sockets for now */
 #endif
-    krb5_xfree(addr);
+    krb5int_free_addrlist (&addrs);
     krb5_xfree(socklist);
     if (retval) {
        free(reply->data);