Index: head/eBones/krb/send_to_kdc.c =================================================================== --- head/eBones/krb/send_to_kdc.c (revision 10573) +++ head/eBones/krb/send_to_kdc.c (revision 10574) @@ -1,307 +1,377 @@ /* * Copyright 1987, 1988 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . * * from: send_to_kdc.c,v 4.20 90/01/02 13:40:37 jtkohl Exp $ - * $Id: send_to_kdc.c,v 1.3 1995/07/18 16:39:42 mark Exp $ + * $Id: send_to_kdc.c,v 1.5 1995/08/25 22:52:05 markm Exp $ */ #if 0 #ifndef lint static char rcsid_send_to_kdc_c[] = "$Id: send_to_kdc.c,v 1.1 1994/03/21 17:35:39 piero Exp "; #endif /* lint */ #endif #include #include #include #include #include #include #include #include #ifdef lint #include /* struct iovec to make lint happy */ #endif /* lint */ #include #include #include #include #include #define S_AD_SZ sizeof(struct sockaddr_in) int krb_udp_port = 0; /* CLIENT_KRB_TIMEOUT indicates the time to wait before * retrying a server. It's defined in "krb.h". */ static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0}; static char *prog = "send_to_kdc"; /* * This file contains two routines, send_to_kdc() and send_recv(). * send_recv() is a static routine used by send_to_kdc(). */ /* * try to send out and receive message. * return 1 on success, 0 on failure */ static int send_recv(KTEXT pkt, KTEXT rpkt, int f, struct sockaddr_in *_to, struct hostent *addrs) { fd_set readfds; register struct hostent *hp; struct sockaddr_in from; int sin_size; int numsent; + int addr_count; if (krb_debug) { if (_to->sin_family == AF_INET) printf("Sending message to %s...", inet_ntoa(_to->sin_addr)); else printf("Sending message..."); (void) fflush(stdout); } if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0, (struct sockaddr *)_to, S_AD_SZ)) != pkt->length) { if (krb_debug) printf("sent only %d/%d\n",numsent, pkt->length); return 0; } if (krb_debug) { printf("Sent\nWaiting for reply..."); (void) fflush(stdout); } FD_ZERO(&readfds); FD_SET(f, &readfds); errno = 0; /* select - either recv is ready, or timeout */ /* see if timeout or error or wrong descriptor */ if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1 || !FD_ISSET(f, &readfds)) { if (krb_debug) { fprintf(stderr, "select failed: readfds=%lx", (unsigned long)&readfds); perror(""); } return 0; } sin_size = sizeof(from); if (recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0, (struct sockaddr *)&from, &sin_size) < 0) { if (krb_debug) perror("recvfrom"); return 0; } if (krb_debug) { printf("received packet from %s\n", inet_ntoa(from.sin_addr)); fflush(stdout); } +/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) for (hp = addrs; hp->h_name != (char *)NULL; hp++) { - if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr, - hp->h_length)) { - if (krb_debug) { - printf("Received it\n"); - (void) fflush(stdout); - } - return 1; - } - if (krb_debug) - fprintf(stderr, - "packet not from %lx\n", - (unsigned long)hp->h_addr); + if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr, + hp->h_length)) { + if (krb_debug) { + printf("Received it\n"); + (void) fflush(stdout); + } + return 1; + } + if (krb_debug) + fprintf(stderr, "packet not from %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr)); + } } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (hp = addrs; hp->h_name != (char *)NULL; hp++) { + for (addr_count = 0; hp->h_addr_list[addr_count]; addr_count++) { + if (!bcmp(hp->h_addr_list[addr_count], + (char *)&from.sin_addr.s_addr, hp->h_length)) { + if (krb_debug) { + printf("Received it\n"); + (void) fflush(stdout); + } + return 1; + } + if (krb_debug) + fprintf(stderr, "packet not from %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr_list[addr_count])); + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ if (krb_debug) - fprintf(stderr, "%s: received packet from wrong host! (%lx)\n", - "send_to_kdc(send_rcv)", (unsigned long)from.sin_addr.s_addr); + fprintf(stderr, "%s: received packet from wrong host! (%s)\n", + "send_to_kdc(send_rcv)", inet_ntoa(from.sin_addr)); return 0; } /* * send_to_kdc() sends a message to the Kerberos authentication * server(s) in the given realm and returns the reply message. * The "pkt" argument points to the message to be sent to Kerberos; * the "rpkt" argument will be filled in with Kerberos' reply. * The "realm" argument indicates the realm of the Kerberos server(s) * to transact with. If the realm is null, the local realm is used. * * If more than one Kerberos server is known for a given realm, * different servers will be queried until one of them replies. * Several attempts (retries) are made for each server before * giving up entirely. * * If an answer was received from a Kerberos host, KSUCCESS is * returned. The following errors can be returned: * * SKDC_CANT - can't get local realm * - can't find "kerberos" in /etc/services database * - can't open socket * - can't bind socket * - all ports in use * - couldn't find any Kerberos host * * SKDC_RETRY - couldn't get an answer from any Kerberos server, * after several retries */ int send_to_kdc(KTEXT pkt, KTEXT rpkt, char *realm) { int i, f; int no_host; /* was a kerberos host found? */ int retry; int n_hosts; int retval; + int addr_count; struct sockaddr_in to; struct hostent *host, *hostlist; - char *cp; char krbhst[MAX_HSTNM]; char lrealm[REALM_SZ]; /* * If "realm" is non-null, use that, otherwise get the * local realm. */ if (realm) (void) strcpy(lrealm, realm); else if (krb_get_lrealm(lrealm,1)) { if (krb_debug) fprintf(stderr, "%s: can't get local realm\n", prog); return(SKDC_CANT); } if (krb_debug) printf("lrealm is %s\n", lrealm); if (krb_udp_port == 0) { register struct servent *sp; if ((sp = getservbyname("kerberos","udp")) == 0) { if (krb_debug) fprintf(stderr, "%s: Can't get kerberos/udp service\n", prog); return(SKDC_CANT); } krb_udp_port = sp->s_port; if (krb_debug) printf("krb_udp_port is %d\n", krb_udp_port); } bzero((char *)&to, S_AD_SZ); hostlist = (struct hostent *) malloc(sizeof(struct hostent)); if (!hostlist) return (/*errno */SKDC_CANT); if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { if (krb_debug) fprintf(stderr,"%s: Can't open socket\n", prog); return(SKDC_CANT); } /* from now on, exit through rtn label for cleanup */ no_host = 1; /* get an initial allocation */ n_hosts = 0; for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) { if (krb_debug) { printf("Getting host entry for %s...",krbhst); (void) fflush(stdout); } host = gethostbyname(krbhst); if (krb_debug) { printf("%s.\n", host ? "Got it" : "Didn't get it"); (void) fflush(stdout); } if (!host) continue; no_host = 0; /* found at least one */ n_hosts++; - /* preserve host network address to check later - * (would be better to preserve *all* addresses, - * take care of that later) - */ + /* + * Preserve host network addresses to check against later + */ hostlist = (struct hostent *) realloc((char *)hostlist, (unsigned) sizeof(struct hostent)*(n_hosts+1)); - if (!hostlist) - return /*errno */SKDC_CANT; - bcopy((char *)host, (char *)&hostlist[n_hosts-1], - sizeof(struct hostent)); - host = &hostlist[n_hosts-1]; - cp = malloc((unsigned)host->h_length); - if (!cp) { - retval = /*errno */SKDC_CANT; - goto rtn; - } - bcopy((char *)host->h_addr, cp, host->h_length); + if (!hostlist) { + fprintf(stderr, "Could not grow hostlist\n"); + return /*errno */SKDC_CANT; + } + bcopy((char *)host, (char *)&hostlist[n_hosts-1], + sizeof(struct hostent)); + host = &hostlist[n_hosts-1]; /* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 - (or worse) only return one name ... */ -#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) - host->h_addr_list = (char **)malloc(sizeof(char *)); - if (!host->h_addr_list) { - retval = /*errno */SKDC_CANT; - goto rtn; - } -#endif /* ULTRIX022 || SunOS */ - host->h_addr = cp; + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + { + char *cp = malloc((unsigned)host->h_length); + if (!cp) { + retval = /*errno */SKDC_CANT; + goto rtn; + } + bcopy((char *)host->h_addr, cp, host->h_length); + host->h_addr = cp; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + /* + * Make a copy of the entire h_addr_list. + */ + { + char *addr; + char **old_addr_list; + addr_count = 0; + old_addr_list = host->h_addr_list; + while(old_addr_list[addr_count++]) + ; + host->h_addr_list = (char **)malloc(addr_count+1 * sizeof(char *)); + if (host->h_addr_list == NULL) { + fprintf(stderr, "Could not allocate host->h_addr_list\n"); + retval = SKDC_CANT; + goto rtn; + } + if (krb_debug) { + printf("h_length = %d\n", host->h_length); + printf("Number of addresses = %d\n", addr_count); + } + for (addr_count = 0; old_addr_list[addr_count]; addr_count++) { + if (krb_debug) + printf ("addr[%d] = %s\n", addr_count, + inet_ntoa(*(struct in_addr *)old_addr_list[addr_count])); + addr = (char *)malloc(host->h_length); + if (addr == NULL) { + fprintf(stderr, "Could not allocate address\n"); + retval = SKDC_CANT; + goto rtn; + } + bcopy(old_addr_list[addr_count], addr, host->h_length); + host->h_addr_list[addr_count] = addr; + } + host->h_addr_list[addr_count] = NULL; + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + bzero((char *)&hostlist[n_hosts], sizeof(struct hostent)); to.sin_family = host->h_addrtype; bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length); to.sin_port = krb_udp_port; if (send_recv(pkt, rpkt, f, &to, hostlist)) { retval = KSUCCESS; goto rtn; } if (krb_debug) { printf("Timeout, error, or wrong descriptor\n"); (void) fflush(stdout); } } if (no_host) { if (krb_debug) - fprintf(stderr, "%s: can't find any Kerberos host.\n", - prog); + fprintf(stderr, "%s: can't find any Kerberos host.\n", prog); retval = SKDC_CANT; goto rtn; } - /* retry each host in sequence */ + /* + * retry each host in sequence. Some addresses may be unreachable + * from where we are, so loop through them as well. + */ for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) { for (host = hostlist; host->h_name != (char *)NULL; host++) { - to.sin_family = host->h_addrtype; - bcopy(host->h_addr, (char *)&to.sin_addr, - host->h_length); - if (send_recv(pkt, rpkt, f, &to, hostlist)) { - retval = KSUCCESS; - goto rtn; - } - } +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (addr_count = 0; host->h_addr_list[addr_count]; addr_count++) { + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + } } retval = SKDC_RETRY; rtn: (void) close(f); if (hostlist) { if(!no_host) { register struct hostent *hp; for (hp = hostlist; hp->h_name; hp++) #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) if (hp->h_addr_list) { #endif /* ULTRIX022 || SunOS */ if (hp->h_addr) free(hp->h_addr); #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) free((char *)hp->h_addr_list); } #endif /* ULTRIX022 || SunOS */ } free((char *)hostlist); } return(retval); } Index: head/eBones/lib/libkrb/send_to_kdc.c =================================================================== --- head/eBones/lib/libkrb/send_to_kdc.c (revision 10573) +++ head/eBones/lib/libkrb/send_to_kdc.c (revision 10574) @@ -1,307 +1,377 @@ /* * Copyright 1987, 1988 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . * * from: send_to_kdc.c,v 4.20 90/01/02 13:40:37 jtkohl Exp $ - * $Id: send_to_kdc.c,v 1.3 1995/07/18 16:39:42 mark Exp $ + * $Id: send_to_kdc.c,v 1.5 1995/08/25 22:52:05 markm Exp $ */ #if 0 #ifndef lint static char rcsid_send_to_kdc_c[] = "$Id: send_to_kdc.c,v 1.1 1994/03/21 17:35:39 piero Exp "; #endif /* lint */ #endif #include #include #include #include #include #include #include #include #ifdef lint #include /* struct iovec to make lint happy */ #endif /* lint */ #include #include #include #include #include #define S_AD_SZ sizeof(struct sockaddr_in) int krb_udp_port = 0; /* CLIENT_KRB_TIMEOUT indicates the time to wait before * retrying a server. It's defined in "krb.h". */ static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0}; static char *prog = "send_to_kdc"; /* * This file contains two routines, send_to_kdc() and send_recv(). * send_recv() is a static routine used by send_to_kdc(). */ /* * try to send out and receive message. * return 1 on success, 0 on failure */ static int send_recv(KTEXT pkt, KTEXT rpkt, int f, struct sockaddr_in *_to, struct hostent *addrs) { fd_set readfds; register struct hostent *hp; struct sockaddr_in from; int sin_size; int numsent; + int addr_count; if (krb_debug) { if (_to->sin_family == AF_INET) printf("Sending message to %s...", inet_ntoa(_to->sin_addr)); else printf("Sending message..."); (void) fflush(stdout); } if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0, (struct sockaddr *)_to, S_AD_SZ)) != pkt->length) { if (krb_debug) printf("sent only %d/%d\n",numsent, pkt->length); return 0; } if (krb_debug) { printf("Sent\nWaiting for reply..."); (void) fflush(stdout); } FD_ZERO(&readfds); FD_SET(f, &readfds); errno = 0; /* select - either recv is ready, or timeout */ /* see if timeout or error or wrong descriptor */ if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1 || !FD_ISSET(f, &readfds)) { if (krb_debug) { fprintf(stderr, "select failed: readfds=%lx", (unsigned long)&readfds); perror(""); } return 0; } sin_size = sizeof(from); if (recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0, (struct sockaddr *)&from, &sin_size) < 0) { if (krb_debug) perror("recvfrom"); return 0; } if (krb_debug) { printf("received packet from %s\n", inet_ntoa(from.sin_addr)); fflush(stdout); } +/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) for (hp = addrs; hp->h_name != (char *)NULL; hp++) { - if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr, - hp->h_length)) { - if (krb_debug) { - printf("Received it\n"); - (void) fflush(stdout); - } - return 1; - } - if (krb_debug) - fprintf(stderr, - "packet not from %lx\n", - (unsigned long)hp->h_addr); + if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr, + hp->h_length)) { + if (krb_debug) { + printf("Received it\n"); + (void) fflush(stdout); + } + return 1; + } + if (krb_debug) + fprintf(stderr, "packet not from %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr)); + } } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (hp = addrs; hp->h_name != (char *)NULL; hp++) { + for (addr_count = 0; hp->h_addr_list[addr_count]; addr_count++) { + if (!bcmp(hp->h_addr_list[addr_count], + (char *)&from.sin_addr.s_addr, hp->h_length)) { + if (krb_debug) { + printf("Received it\n"); + (void) fflush(stdout); + } + return 1; + } + if (krb_debug) + fprintf(stderr, "packet not from %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr_list[addr_count])); + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ if (krb_debug) - fprintf(stderr, "%s: received packet from wrong host! (%lx)\n", - "send_to_kdc(send_rcv)", (unsigned long)from.sin_addr.s_addr); + fprintf(stderr, "%s: received packet from wrong host! (%s)\n", + "send_to_kdc(send_rcv)", inet_ntoa(from.sin_addr)); return 0; } /* * send_to_kdc() sends a message to the Kerberos authentication * server(s) in the given realm and returns the reply message. * The "pkt" argument points to the message to be sent to Kerberos; * the "rpkt" argument will be filled in with Kerberos' reply. * The "realm" argument indicates the realm of the Kerberos server(s) * to transact with. If the realm is null, the local realm is used. * * If more than one Kerberos server is known for a given realm, * different servers will be queried until one of them replies. * Several attempts (retries) are made for each server before * giving up entirely. * * If an answer was received from a Kerberos host, KSUCCESS is * returned. The following errors can be returned: * * SKDC_CANT - can't get local realm * - can't find "kerberos" in /etc/services database * - can't open socket * - can't bind socket * - all ports in use * - couldn't find any Kerberos host * * SKDC_RETRY - couldn't get an answer from any Kerberos server, * after several retries */ int send_to_kdc(KTEXT pkt, KTEXT rpkt, char *realm) { int i, f; int no_host; /* was a kerberos host found? */ int retry; int n_hosts; int retval; + int addr_count; struct sockaddr_in to; struct hostent *host, *hostlist; - char *cp; char krbhst[MAX_HSTNM]; char lrealm[REALM_SZ]; /* * If "realm" is non-null, use that, otherwise get the * local realm. */ if (realm) (void) strcpy(lrealm, realm); else if (krb_get_lrealm(lrealm,1)) { if (krb_debug) fprintf(stderr, "%s: can't get local realm\n", prog); return(SKDC_CANT); } if (krb_debug) printf("lrealm is %s\n", lrealm); if (krb_udp_port == 0) { register struct servent *sp; if ((sp = getservbyname("kerberos","udp")) == 0) { if (krb_debug) fprintf(stderr, "%s: Can't get kerberos/udp service\n", prog); return(SKDC_CANT); } krb_udp_port = sp->s_port; if (krb_debug) printf("krb_udp_port is %d\n", krb_udp_port); } bzero((char *)&to, S_AD_SZ); hostlist = (struct hostent *) malloc(sizeof(struct hostent)); if (!hostlist) return (/*errno */SKDC_CANT); if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { if (krb_debug) fprintf(stderr,"%s: Can't open socket\n", prog); return(SKDC_CANT); } /* from now on, exit through rtn label for cleanup */ no_host = 1; /* get an initial allocation */ n_hosts = 0; for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) { if (krb_debug) { printf("Getting host entry for %s...",krbhst); (void) fflush(stdout); } host = gethostbyname(krbhst); if (krb_debug) { printf("%s.\n", host ? "Got it" : "Didn't get it"); (void) fflush(stdout); } if (!host) continue; no_host = 0; /* found at least one */ n_hosts++; - /* preserve host network address to check later - * (would be better to preserve *all* addresses, - * take care of that later) - */ + /* + * Preserve host network addresses to check against later + */ hostlist = (struct hostent *) realloc((char *)hostlist, (unsigned) sizeof(struct hostent)*(n_hosts+1)); - if (!hostlist) - return /*errno */SKDC_CANT; - bcopy((char *)host, (char *)&hostlist[n_hosts-1], - sizeof(struct hostent)); - host = &hostlist[n_hosts-1]; - cp = malloc((unsigned)host->h_length); - if (!cp) { - retval = /*errno */SKDC_CANT; - goto rtn; - } - bcopy((char *)host->h_addr, cp, host->h_length); + if (!hostlist) { + fprintf(stderr, "Could not grow hostlist\n"); + return /*errno */SKDC_CANT; + } + bcopy((char *)host, (char *)&hostlist[n_hosts-1], + sizeof(struct hostent)); + host = &hostlist[n_hosts-1]; /* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 - (or worse) only return one name ... */ -#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) - host->h_addr_list = (char **)malloc(sizeof(char *)); - if (!host->h_addr_list) { - retval = /*errno */SKDC_CANT; - goto rtn; - } -#endif /* ULTRIX022 || SunOS */ - host->h_addr = cp; + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + { + char *cp = malloc((unsigned)host->h_length); + if (!cp) { + retval = /*errno */SKDC_CANT; + goto rtn; + } + bcopy((char *)host->h_addr, cp, host->h_length); + host->h_addr = cp; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + /* + * Make a copy of the entire h_addr_list. + */ + { + char *addr; + char **old_addr_list; + addr_count = 0; + old_addr_list = host->h_addr_list; + while(old_addr_list[addr_count++]) + ; + host->h_addr_list = (char **)malloc(addr_count+1 * sizeof(char *)); + if (host->h_addr_list == NULL) { + fprintf(stderr, "Could not allocate host->h_addr_list\n"); + retval = SKDC_CANT; + goto rtn; + } + if (krb_debug) { + printf("h_length = %d\n", host->h_length); + printf("Number of addresses = %d\n", addr_count); + } + for (addr_count = 0; old_addr_list[addr_count]; addr_count++) { + if (krb_debug) + printf ("addr[%d] = %s\n", addr_count, + inet_ntoa(*(struct in_addr *)old_addr_list[addr_count])); + addr = (char *)malloc(host->h_length); + if (addr == NULL) { + fprintf(stderr, "Could not allocate address\n"); + retval = SKDC_CANT; + goto rtn; + } + bcopy(old_addr_list[addr_count], addr, host->h_length); + host->h_addr_list[addr_count] = addr; + } + host->h_addr_list[addr_count] = NULL; + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + bzero((char *)&hostlist[n_hosts], sizeof(struct hostent)); to.sin_family = host->h_addrtype; bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length); to.sin_port = krb_udp_port; if (send_recv(pkt, rpkt, f, &to, hostlist)) { retval = KSUCCESS; goto rtn; } if (krb_debug) { printf("Timeout, error, or wrong descriptor\n"); (void) fflush(stdout); } } if (no_host) { if (krb_debug) - fprintf(stderr, "%s: can't find any Kerberos host.\n", - prog); + fprintf(stderr, "%s: can't find any Kerberos host.\n", prog); retval = SKDC_CANT; goto rtn; } - /* retry each host in sequence */ + /* + * retry each host in sequence. Some addresses may be unreachable + * from where we are, so loop through them as well. + */ for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) { for (host = hostlist; host->h_name != (char *)NULL; host++) { - to.sin_family = host->h_addrtype; - bcopy(host->h_addr, (char *)&to.sin_addr, - host->h_length); - if (send_recv(pkt, rpkt, f, &to, hostlist)) { - retval = KSUCCESS; - goto rtn; - } - } +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (addr_count = 0; host->h_addr_list[addr_count]; addr_count++) { + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + } } retval = SKDC_RETRY; rtn: (void) close(f); if (hostlist) { if(!no_host) { register struct hostent *hp; for (hp = hostlist; hp->h_name; hp++) #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) if (hp->h_addr_list) { #endif /* ULTRIX022 || SunOS */ if (hp->h_addr) free(hp->h_addr); #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) free((char *)hp->h_addr_list); } #endif /* ULTRIX022 || SunOS */ } free((char *)hostlist); } return(retval); }