]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZInit.c
r4254@bucket (orig r244): kcr | 2008-01-20 14:40:42 -0500
[1ts-debian.git] / zephyr / lib / ZInit.c
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  *      $Id$
7  *
8  *      Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #ifndef lint
14 static char rcsid_ZInitialize_c[] =
15     "$Zephyr: /afs/athena.mit.edu/astaff/project/zephyr/src/lib/RCS/ZInitialize.c,v 1.17 89/05/30 18:11:25 jtkohl Exp $";
16 #endif
17
18 #include <internal.h>
19
20 #include <sys/socket.h>
21 #ifdef HAVE_KRB4
22 #include <krb_err.h>
23 #endif
24 #ifdef HAVE_KRB5
25 #include <krb5.h>
26 #endif
27 #ifdef HAVE_KRB5_ERR_H
28 #include <krb5_err.h>
29 #endif
30
31 #ifndef INADDR_NONE
32 #define INADDR_NONE 0xffffffff
33 #endif
34
35 Code_t
36 ZInitialize(void)
37 {
38     struct servent *hmserv;
39     struct hostent *hostent;
40     char addr[4], hostname[MAXHOSTNAMELEN];
41     struct in_addr servaddr;
42     struct sockaddr_in sin;
43     int s, sinsize = sizeof(sin);
44     Code_t code;
45     ZNotice_t notice;
46 #ifdef HAVE_KRB5
47     char **krealms = NULL;
48 #else
49 #ifdef HAVE_KRB4
50     char *krealm = NULL;
51     int krbval;
52     char d1[ANAME_SZ], d2[INST_SZ];
53 #endif
54 #endif
55
56 #ifdef HAVE_KRB4
57     initialize_krb_error_table();
58 #endif
59 #ifdef HAVE_KRB5
60     initialize_krb5_error_table();
61 #endif
62
63     initialize_zeph_error_table();
64     
65     (void) memset((char *)&__HM_addr, 0, sizeof(__HM_addr));
66
67     __HM_addr.sin_family = AF_INET;
68
69     /* Set up local loopback address for HostManager */
70     addr[0] = 127;
71     addr[1] = 0;
72     addr[2] = 0;
73     addr[3] = 1;
74
75     hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp");
76     __HM_addr.sin_port = (hmserv) ? hmserv->s_port : HM_SVC_FALLBACK;
77
78     (void) memcpy((char *)&__HM_addr.sin_addr, addr, 4);
79
80     __HM_set = 0;
81
82     /* Initialize the input queue */
83     __Q_Tail = NULL;
84     __Q_Head = NULL;
85     
86 #ifdef HAVE_KRB5
87     if ((code = krb5_init_context(&Z_krb5_ctx)))
88         return(code);
89 #endif
90
91     /* if the application is a server, there might not be a zhm.  The
92        code will fall back to something which might not be "right",
93        but this is is ok, since none of the servers call krb_rd_req. */
94
95     servaddr.s_addr = INADDR_NONE;
96     if (! __Zephyr_server) {
97        if ((code = ZOpenPort(NULL)) != ZERR_NONE)
98           return(code);
99
100        if ((code = ZhmStat(NULL, &notice)) != ZERR_NONE)
101           return(code);
102
103        ZClosePort();
104
105        /* the first field, which is NUL-terminated, is the server name.
106           If this code ever support a multiplexing zhm, this will have to
107           be made smarter, and probably per-message */
108
109 #ifdef HAVE_KRB5
110        code = krb5_get_host_realm(Z_krb5_ctx, notice.z_message, &krealms);
111        if (code)
112          return(code);
113 #else
114 #ifdef HAVE_KRB4
115        krealm = krb_realmofhost(notice.z_message);
116 #endif
117 #endif
118        hostent = gethostbyname(notice.z_message);
119        if (hostent && hostent->h_addrtype == AF_INET)
120            memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
121
122        ZFreeNotice(&notice);
123     }
124
125 #ifdef HAVE_KRB5
126     if (krealms) {
127       strcpy(__Zephyr_realm, krealms[0]);
128       krb5_free_host_realm(Z_krb5_ctx, krealms);
129     } else {
130       char *p; /* XXX define this somewhere portable */
131       /* XXX check ticket file here */
132       code = krb5_get_default_realm(Z_krb5_ctx, &p);
133       strcpy(__Zephyr_realm, p);
134 #ifdef HAVE_KRB5_FREE_DEFAULT_REALM
135       krb5_free_default_realm(Z_krb5_ctx, p);
136 #else
137       free(p);
138 #endif
139       if (code)
140         return code;
141     }
142 #else
143 #ifdef HAVE_KRB4
144     if (krealm) {
145         strcpy(__Zephyr_realm, krealm);
146     } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
147                 != KSUCCESS) &&
148                ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
149         return (krbval);
150     }
151 #else
152     strcpy(__Zephyr_realm, "local-realm");
153 #endif
154 #endif
155
156     __My_addr.s_addr = INADDR_NONE;
157     if (servaddr.s_addr != INADDR_NONE) {
158         /* Try to get the local interface address by connecting a UDP
159          * socket to the server address and getting the local address.
160          * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
161          * INADDR_ANY (zero), so we have to check for that. */
162         s = socket(AF_INET, SOCK_DGRAM, 0);
163         if (s != -1) {
164             memset(&sin, 0, sizeof(sin));
165             sin.sin_family = AF_INET;
166             memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
167             sin.sin_port = HM_SRV_SVC_FALLBACK;
168             if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
169                 && getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
170                 && sin.sin_addr.s_addr != 0)
171                 memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
172             close(s);
173         }
174     }
175     if (__My_addr.s_addr == INADDR_NONE) {
176         /* We couldn't figure out the local interface address by the
177          * above method.  Try by resolving the local hostname.  (This
178          * is a pretty broken thing to do, and unfortunately what we
179          * always do on server machines.) */
180         if (gethostname(hostname, sizeof(hostname)) == 0) {
181             hostent = gethostbyname(hostname);
182             if (hostent && hostent->h_addrtype == AF_INET)
183                 memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
184         }
185     }
186     /* If the above methods failed, zero out __My_addr so things will
187      * sort of kind of work. */
188     if (__My_addr.s_addr == INADDR_NONE)
189         __My_addr.s_addr = 0;
190
191     /* Get the sender so we can cache it */
192     (void) ZGetSender();
193
194     return (ZERR_NONE);
195 }
196