From: John Kohl Date: Thu, 29 Mar 1990 16:01:40 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: krb5-1.0-alpha2~959 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c14271c589cc546e1f2b5dffcfa7ad5e7cfadc2c;p=krb5.git *** empty log message *** git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@429 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c new file mode 100644 index 000000000..be74b8a39 --- /dev/null +++ b/src/lib/krb5/os/sendto_kdc.c @@ -0,0 +1,169 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Send packet to KDC for realm; wait for response, retransmitting + * as necessary. + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_sendto_kdc_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#define MAX_DGRAM_SIZE 4096 /* XXX! */ +#define MAX_TIMEOUT 30 /* XXX */ +#define TIMEOUT_SHIFT 2 /* XXX */ + +#include +#include + +/* + * send the formatted request 'message' to a KDC for realm 'realm' and + * return the response (if any) in 'reply'. + * + * If the message is sent and a response is received, 0 is returned, + * otherwise an error code is returned. + * + * The storage for 'reply' is allocated and should be freed by the caller + * when finished. + * + */ +krb5_error_code +krb5_sendto_kdc (DECLARG(krb5_data *, message), + DECLARG(krb5_data *, realm), + DECLARG(krb5_data *, reply)) +OLDDECLARG(krb5_data *, message) +OLDDECLARG(krb5_data *, realm) +OLDDECLARG(krb5_data *, reply) +{ + register int timeout, host, i; + struct sockaddr *addr; + int naddr; + int sent, nready; + krb5_error_code retval; + int socklist[AF_MAX]; /* one for each, if necessary! */ + fd_set readable; + struct timeval waitlen; + struct sockaddr fromaddr; + int fromlen, cc; + + /* + * find KDC location(s) for realm + */ + + if (retval = krb5_locate_kdc (realm, &addr, &naddr)) + return retval; + if (naddr == 0) + return KRB5_REALM_UNKNOWN; + + for (i = 0; i < AF_MAX; i++) + socklist[i] = -1; + + if (!(reply->data = malloc(MAX_DGRAM_SIZE))) { /* XXX size? */ + free((char *)addr); + return ENOMEM; + } + reply->length = MAX_DGRAM_SIZE; + + /* + * do exponential backoff. + */ + + for (timeout = 1; timeout < MAXTIMEOUT; timeout <<=TIMEOUT_SHIFT) { + sent = 0; + for (host = 0; host < naddr; host++) { + /* send to the host, wait timeout seconds for a response, + then move on. */ + /* cache some sockets for various address families in the + list */ + if (socklist[addr[host].sa_family] == -1) { + /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the socket + creation here will work properly... */ + socklist[addr[host].sa_family] = socket(addr[host].sa_family, + SOCK_DGRAM, + 0); /* XXX always zero? */ + if (socklist[addr[host].sa_family] == -1) + continue; /* try other hosts */ + } + /* have a socket to send/recv from */ + if (sendto(socklist[addr[host].sa_family], + message->data, + message->length, + 0, + &addr[host], + sizeof(addr[host])) != message->length) + continue; + else + sent = 1; + waitlen.tv_usec = 0; + waitlen.tv_sec = timeout; + FD_ZERO(&readable); + FD_SET(socklist[addr[host].sa_family], &readable); + if (nready = select(1<data, + reply->length, + 0, + &fromaddr, + &fromlen) == -1) + continue; /* XXX */ + if (bcmp((char *)&fromaddr, (char *)&addr[host], + fromlen)) { + /* not from this one, perhaps from an earlier + request? */ + for (i = host-1; i >= 0; i--) { + if (!bcmp((char *)&fromaddr, (char *)&addr[host], + fromlen)) + break; + } + if (i < 0) /* not from someone we asked */ + continue; /* XXX */ + } + /* reply came from where we sent a request, + so clean up and return. */ + reply->length = cc; + retval = 0; + goto out; + } + /* not ready, go on to next server */ + } + if (!sent) { + /* never were able to send to any servers; give up */ + retval = KRB5_KDC_UNREACH; + break; + } + } + retval = KRB5_KDC_UNREACH; + out: + for (i = 0; i < AF_MAX; i++) + (void) close(i); + free((char *)addr); + if (retval) { + free(reply->data); + reply->data = 0; + reply->length = 0; + } + return retval; +}