summaryrefslogtreecommitdiff
path: root/lib/ZInit.c
diff options
context:
space:
mode:
authorGravatar Greg Hudson <ghudson@mit.edu>1998-03-17 14:19:51 +0000
committerGravatar Greg Hudson <ghudson@mit.edu>1998-03-17 14:19:51 +0000
commitfaeb04a01f22bbb776a3300f771191ebcbdcad9b (patch)
treeb34848c794b2cc62ce33245e2007038edcf9b52f /lib/ZInit.c
parentf3932ba5242486adf6766db16c5554ff00f42a13 (diff)
Make __My_addr a struct in_addr and initialize it in ZInit() instead of
having a special function in Zinternal.c. More importantly, do a better job of finding the local address by using getsockname() on a connected UDP socket.
Diffstat (limited to 'lib/ZInit.c')
-rw-r--r--lib/ZInit.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/lib/ZInit.c b/lib/ZInit.c
index 8e875ba..1bfa7df 100644
--- a/lib/ZInit.c
+++ b/lib/ZInit.c
@@ -24,14 +24,22 @@ static char rcsid_ZInitialize_c[] =
#include <krb_err.h>
#endif
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
Code_t ZInitialize()
{
struct servent *hmserv;
- char addr[4];
+ struct hostent *hostent;
+ char addr[4], hostname[MAXHOSTNAMELEN];
+ struct in_addr servaddr;
+ struct sockaddr_in sin;
+ int s, sinsize = sizeof(sin);
#ifdef HAVE_KRB4
Code_t code;
ZNotice_t notice;
- char *krealm;
+ char *krealm = NULL;
int krbval;
char d1[ANAME_SZ], d2[INST_SZ];
@@ -61,12 +69,11 @@ Code_t ZInitialize()
__Q_Tail = NULL;
__Q_Head = NULL;
-#ifdef HAVE_KRB4
-
/* if the application is a server, there might not be a zhm. The
code will fall back to something which might not be "right",
but this is is ok, since none of the servers call krb_rd_req. */
+ servaddr.s_addr = INADDR_NONE;
if (! __Zephyr_server) {
if ((code = ZOpenPort(NULL)) != ZERR_NONE)
return(code);
@@ -80,13 +87,17 @@ Code_t ZInitialize()
If this code ever support a multiplexing zhm, this will have to
be made smarter, and probably per-message */
+#ifdef HAVE_KRB4
krealm = krb_realmofhost(notice.z_message);
+#endif
+ hostent = gethostbyname(notice.z_message);
+ if (hostent && hostent->h_addrtype == AF_INET)
+ memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
ZFreeNotice(&notice);
- } else {
- krealm = NULL;
}
+#ifdef HAVE_KRB4
if (krealm) {
strcpy(__Zephyr_realm, krealm);
} else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
@@ -98,6 +109,41 @@ Code_t ZInitialize()
strcpy(__Zephyr_realm, "local-realm");
#endif
+ __My_addr.s_addr = INADDR_NONE;
+ if (servaddr.s_addr != INADDR_NONE) {
+ /* Try to get the local interface address by connecting a UDP
+ * socket to the server address and getting the local address.
+ * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
+ * INADDR_ANY (zero), so we have to check for that. */
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s != -1) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
+ sin.sin_port = HM_SRV_SVC_FALLBACK;
+ if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
+ && getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
+ && sin.sin_addr.s_addr != 0)
+ memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
+ close(s);
+ }
+ }
+ if (__My_addr.s_addr == INADDR_NONE) {
+ /* We couldn't figure out the local interface address by the
+ * above method. Try by resolving the local hostname. (This
+ * is a pretty broken thing to do, and unfortunately what we
+ * always do on server machines.) */
+ if (gethostname(hostname, sizeof(hostname)) == 0) {
+ hostent = gethostbyname(hostname);
+ if (hostent && hostent->h_addrtype == AF_INET)
+ memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
+ }
+ }
+ /* If the above methods failed, zero out __My_addr so things will
+ * sort of kind of work. */
+ if (__My_addr.s_addr == INADDR_NONE)
+ __My_addr.s_addr = 0;
+
/* Get the sender so we can cache it */
(void) ZGetSender();