| |
1 /* This file is part of the Project Athena Zephyr Notification System. |
| |
2 * It contains source for the ZInitialize function. |
| |
3 * |
| |
4 * Created by: Robert French |
| |
5 * |
| |
6 * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology. |
| |
7 * For copying and distribution information, see the file |
| |
8 * "mit-copyright.h". |
| |
9 */ |
| |
10 |
| |
11 #ifdef ZEPHYR_USES_KERBEROS |
| |
12 #ifdef WIN32 |
| |
13 |
| |
14 #else |
| |
15 #include <krb_err.h> |
| |
16 #endif |
| |
17 #endif |
| |
18 |
| |
19 #include "internal.h" |
| |
20 |
| |
21 #ifdef WIN32 |
| |
22 #include <winsock2.h> |
| |
23 #else |
| |
24 #include <sys/socket.h> |
| |
25 #endif |
| |
26 |
| |
27 |
| |
28 #ifndef INADDR_NONE |
| |
29 #define INADDR_NONE 0xffffffff |
| |
30 #endif |
| |
31 |
| |
32 Code_t ZInitialize() |
| |
33 { |
| |
34 struct servent *hmserv; |
| |
35 struct hostent *hostent; |
| |
36 char addr[4], hostname[MAXHOSTNAMELEN]; |
| |
37 struct in_addr servaddr; |
| |
38 struct sockaddr_in sin; |
| |
39 int s; |
| |
40 socklen_t sinsize = sizeof(sin); |
| |
41 Code_t code; |
| |
42 ZNotice_t notice; |
| |
43 #ifdef ZEPHYR_USES_KERBEROS |
| |
44 char *krealm = NULL; |
| |
45 int krbval; |
| |
46 char d1[ANAME_SZ], d2[INST_SZ]; |
| |
47 |
| |
48 /* initialize_krb_error_table(); */ |
| |
49 #endif |
| |
50 |
| |
51 initialize_zeph_error_table(); |
| |
52 |
| |
53 (void) memset((char *)&__HM_addr, 0, sizeof(__HM_addr)); |
| |
54 |
| |
55 __HM_addr.sin_family = AF_INET; |
| |
56 |
| |
57 /* Set up local loopback address for HostManager */ |
| |
58 addr[0] = 127; |
| |
59 addr[1] = 0; |
| |
60 addr[2] = 0; |
| |
61 addr[3] = 1; |
| |
62 |
| |
63 hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp"); |
| |
64 __HM_addr.sin_port = (hmserv) ? hmserv->s_port : HM_SVC_FALLBACK; |
| |
65 |
| |
66 (void) memcpy((char *)&__HM_addr.sin_addr, addr, 4); |
| |
67 |
| |
68 __HM_set = 0; |
| |
69 |
| |
70 /* Initialize the input queue */ |
| |
71 __Q_Tail = NULL; |
| |
72 __Q_Head = NULL; |
| |
73 |
| |
74 /* if the application is a server, there might not be a zhm. The |
| |
75 code will fall back to something which might not be "right", |
| |
76 but this is is ok, since none of the servers call krb_rd_req. */ |
| |
77 |
| |
78 servaddr.s_addr = INADDR_NONE; |
| |
79 if (! __Zephyr_server) { |
| |
80 if ((code = ZOpenPort(NULL)) != ZERR_NONE) |
| |
81 return(code); |
| |
82 |
| |
83 if ((code = ZhmStat(NULL, ¬ice)) != ZERR_NONE) |
| |
84 return(code); |
| |
85 |
| |
86 ZClosePort(); |
| |
87 |
| |
88 /* the first field, which is NUL-terminated, is the server name. |
| |
89 If this code ever support a multiplexing zhm, this will have to |
| |
90 be made smarter, and probably per-message */ |
| |
91 |
| |
92 #ifdef ZEPHYR_USES_KERBEROS |
| |
93 krealm = krb_realmofhost(notice.z_message); |
| |
94 #endif |
| |
95 hostent = gethostbyname(notice.z_message); |
| |
96 if (hostent && hostent->h_addrtype == AF_INET) |
| |
97 memcpy(&servaddr, hostent->h_addr, sizeof(servaddr)); |
| |
98 |
| |
99 ZFreeNotice(¬ice); |
| |
100 } |
| |
101 |
| |
102 #ifdef ZEPHYR_USES_KERBEROS |
| |
103 if (krealm) { |
| |
104 strcpy(__Zephyr_realm, krealm); |
| |
105 } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm) |
| |
106 != KSUCCESS) && |
| |
107 ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) { |
| |
108 return (krbval); |
| |
109 } |
| |
110 #else |
| |
111 strcpy(__Zephyr_realm, "local-realm"); |
| |
112 #endif |
| |
113 |
| |
114 __My_addr.s_addr = INADDR_NONE; |
| |
115 if (servaddr.s_addr != INADDR_NONE) { |
| |
116 /* Try to get the local interface address by connecting a UDP |
| |
117 * socket to the server address and getting the local address. |
| |
118 * Some broken operating systems (e.g. Solaris 2.0-2.5) yield |
| |
119 * INADDR_ANY (zero), so we have to check for that. */ |
| |
120 s = socket(AF_INET, SOCK_DGRAM, 0); |
| |
121 if (s != -1) { |
| |
122 memset(&sin, 0, sizeof(sin)); |
| |
123 sin.sin_family = AF_INET; |
| |
124 memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr)); |
| |
125 sin.sin_port = HM_SRV_SVC_FALLBACK; |
| |
126 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0 |
| |
127 && getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0 |
| |
128 && sin.sin_addr.s_addr != 0) |
| |
129 memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr)); |
| |
130 close(s); |
| |
131 } |
| |
132 } |
| |
133 if (__My_addr.s_addr == INADDR_NONE) { |
| |
134 /* We couldn't figure out the local interface address by the |
| |
135 * above method. Try by resolving the local hostname. (This |
| |
136 * is a pretty broken thing to do, and unfortunately what we |
| |
137 * always do on server machines.) */ |
| |
138 if (gethostname(hostname, sizeof(hostname)) == 0) { |
| |
139 hostent = gethostbyname(hostname); |
| |
140 if (hostent && hostent->h_addrtype == AF_INET) |
| |
141 memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr)); |
| |
142 } |
| |
143 } |
| |
144 /* If the above methods failed, zero out __My_addr so things will |
| |
145 * sort of kind of work. */ |
| |
146 if (__My_addr.s_addr == INADDR_NONE) |
| |
147 __My_addr.s_addr = 0; |
| |
148 |
| |
149 /* Get the sender so we can cache it */ |
| |
150 (void) ZGetSender(); |
| |
151 |
| |
152 return (ZERR_NONE); |
| |
153 } |
| |
154 |