diff options
Diffstat (limited to 'eBones/lib/libkrb/send_to_kdc.c')
-rw-r--r-- | eBones/lib/libkrb/send_to_kdc.c | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/eBones/lib/libkrb/send_to_kdc.c b/eBones/lib/libkrb/send_to_kdc.c index 521ba9a..c9f4355 100644 --- a/eBones/lib/libkrb/send_to_kdc.c +++ b/eBones/lib/libkrb/send_to_kdc.c @@ -4,7 +4,7 @@ * <Copyright.MIT>. * * from: send_to_kdc.c,v 4.20 90/01/02 13:40:37 jtkohl Exp $ - * $Id: send_to_kdc.c,v 1.8 1995/09/14 20:58:35 gibbs Exp $ + * $Id: send_to_kdc.c,v 1.9 1995/09/16 23:11:25 gibbs Exp $ */ #if 0 @@ -22,11 +22,15 @@ static char rcsid_send_to_kdc_c[] = #include <stdio.h> #include <errno.h> #include <sys/time.h> +#include <sys/param.h> #include <sys/types.h> #ifdef lint #include <sys/uio.h> /* struct iovec to make lint happy */ #endif /* lint */ +#include <sys/sysctl.h> #include <sys/socket.h> +#include <net/if.h> +#include <net/route.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> @@ -34,6 +38,11 @@ static char rcsid_send_to_kdc_c[] = #define S_AD_SZ sizeof(struct sockaddr_in) +/* Used for extracting addresses from routing messages */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sin_len)) + extern int errno; extern int krb_debug; @@ -41,6 +50,10 @@ extern char *malloc(), *calloc(), *realloc(); int krb_udp_port = 0; +static struct sockaddr_in local_addr = { S_AD_SZ, + AF_INET + }; + /* CLIENT_KRB_TIMEOUT indicates the time to wait before * retrying a server. It's defined in "krb.h". */ @@ -222,6 +235,11 @@ send_to_kdc(pkt,rpkt,realm) bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length); to.sin_port = krb_udp_port; + if ((retval = krb_bind_local_addr(f)) != KSUCCESS) { + fprintf(stderr, "krb_bind_local_addr: %s", krb_err_txt[retval]); + retval = SKDC_CANT; + goto rtn; + } if (send_recv(pkt, rpkt, f, &to, hostlist)) { retval = KSUCCESS; goto rtn; @@ -389,3 +407,123 @@ send_recv(pkt,rpkt,f,_to,addrs) "send_to_kdc(send_rcv)", inet_ntoa(from.sin_addr)); return 0; } + + +static int +setfixedaddr(s) + int s; +{ + struct ifa_msghdr *ifa, *ifa0, *ifa_end; + struct sockaddr_in *cur_addr; + int tries; + int i; + u_long loopback; + int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 }; + size_t len; + + /* Get information about our interfaces */ +#define NUMTRIES 10 + tries = 0; + +retry: + len = 0; + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { + perror("setfixedaddr: Can't get size of interface table: sysctl"); + return GT_LADDR_IFLIST; + } + ifa = (struct ifa_msghdr *)malloc(len); + if (!ifa) { + fprintf(stderr, "setfixedaddr: Cannot malloc\n"); + return (KFAILURE); + } + if (sysctl(mib, 6, ifa, &len, NULL, 0) < 0) { + free(ifa); + if (errno == ENOMEM && tries < NUMTRIES) { + /* Table grew between calls */ + tries++; + goto retry; + } + else { + perror("setfixedaddr: Can't get interface table: sysctl"); + return GT_LADDR_IFLIST; + } + } + loopback = inet_addr("127.0.0.1"); + + ifa0 = ifa; + for(ifa_end = (struct ifa_msghdr *)((caddr_t)ifa + len); + ifa < ifa_end; + (caddr_t)ifa += ifa->ifam_msglen) { + /* Ignore interface name messages and ensure we have an address */ + if (ifa->ifam_type == RTM_IFINFO || !(ifa->ifam_addrs & RTAX_IFA)) + continue; + cur_addr = (struct sockaddr_in *)(ifa + 1); + for (i = 0; i < RTAX_IFA; i++) { + if (ifa->ifam_addrs & (1 << i)) + ADVANCE((caddr_t)cur_addr, cur_addr); + } + if (cur_addr->sin_addr.s_addr != loopback) { + local_addr.sin_addr.s_addr = cur_addr->sin_addr.s_addr; + break; + } + } + free(ifa0); + if (ifa >= ifa_end) { + return GT_LADDR_NVI; + } + if (krb_debug) { + fprintf(stderr, "setfixedaddr: using local address %s\n", + inet_ntoa(local_addr.sin_addr)); + } + return (KSUCCESS); +} + +int +krb_bind_local_addr(s) + int s; +{ + int retval; + if (local_addr.sin_addr.s_addr == INADDR_ANY) { + /* + * We haven't determined the local interface to use + * for kerberos server interactions. Do so now. + */ + if ((retval = setfixedaddr(s)) != KSUCCESS) + return (retval); + } + if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) { + perror("krb_bind_local_addr: bind"); + return BND_LADDR_BIND; + } + if (krb_debug) + printf("local_addr = %s\n", inet_ntoa(local_addr.sin_addr)); + return(KSUCCESS); +} + +int +krb_get_local_addr(returned_addr) + struct sockaddr_in *returned_addr; +{ + int retval; + if (local_addr.sin_addr.s_addr == INADDR_ANY) { + /* + * We haven't determined the local interface to use + * for kerberos server interactions. Do so now. + */ + int s; + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return GT_LADDR_NOSOCK; + } + if ((retval = setfixedaddr(s)) != KSUCCESS) { + close(s); + return (retval); + } + close(s); + } + if (!returned_addr) + return(KFAILURE); + *returned_addr = local_addr; + if (krb_debug) + printf("local_addr = %s\n", inet_ntoa(local_addr.sin_addr)); + return (KSUCCESS); +} |