1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains the hostmanager <--> server interaction routines.
4 * Created by: David C. Jedlinsky
6 * $Id: zhm_server.c,v 1.17 1999/10/14 18:37:35 ghudson Exp $
8 * Copyright (c) 1987 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, see the file
17 static char rcsid_hm_server_c[] = "$Id: zhm_server.c,v 1.17 1999/10/14 18:37:35 ghudson Exp $";
21 static void boot_timeout __P((void *));
23 static Timer *boot_timer = NULL;
26 extern u_short cli_port;
27 extern struct sockaddr_in serv_sin, from;
28 extern int timeout_type, hmdebug, nservchang, booting, nserv, no_server;
29 extern int deactivated, rebootflag;
31 extern char **serv_list;
32 extern char cur_serv[], prim_serv[];
33 extern void die_gracefully();
35 void hm_control(), send_back(), new_server();
37 /* Argument is whether we are actually booting, or just attaching
38 * after a server switch */
46 /* Set up server notice */
47 notice.z_kind = HMCTL;
48 notice.z_port = cli_port;
49 notice.z_class = ZEPHYR_CTL_CLASS;
50 notice.z_class_inst = ZEPHYR_CTL_HM;
52 notice.z_sender = "HM";
53 notice.z_recipient = "";
54 notice.z_default_format = "";
55 notice.z_num_other_fields = 0;
56 notice.z_message_len = 0;
58 /* Notify server that this host is here */
59 if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) {
61 com_err("hm", ret, "setting destination");
63 if ((ret = ZSendNotice(¬ice, ZNOAUTH)) != ZERR_NONE) {
65 com_err("hm", ret, "sending startup notice");
67 boot_timer = timer_set_rel(SERV_TIMEOUT, boot_timeout, NULL);
70 /* Argument is whether we are detaching or really going down */
78 /* Set up server notice */
79 notice.z_kind = HMCTL;
80 notice.z_port = cli_port;
81 notice.z_class = ZEPHYR_CTL_CLASS;
82 notice.z_class_inst = ZEPHYR_CTL_HM;
84 notice.z_sender = "HM";
85 notice.z_recipient = "";
86 notice.z_default_format = "";
87 notice.z_num_other_fields = 0;
88 notice.z_message_len = 0;
90 /* Tell server to lose us */
91 if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) {
93 com_err("hm", ret, "setting destination");
95 if ((ret = ZSendNotice(¬ice, ZNOAUTH)) != ZERR_NONE) {
97 com_err("hm", ret, "sending flush notice");
102 find_next_server(sugg_serv)
107 char **parse = serv_list;
112 if (!strcmp(*parse, sugg_serv))
114 } while ((done == 0) && (*++parse != NULL));
117 if ((hp = gethostbyname(sugg_serv)) != NULL) {
118 DPR2 ("Server = %s\n", sugg_serv);
119 (void)strncpy(cur_serv, sugg_serv, MAXHOSTNAMELEN);
120 cur_serv[MAXHOSTNAMELEN - 1] = '\0';
122 syslog(LOG_DEBUG, "Suggested server: %s\n", sugg_serv);
128 if ((++serv_loop > 3) && (strcmp(cur_serv, prim_serv))) {
130 if ((hp = gethostbyname(prim_serv)) != NULL) {
131 DPR2 ("Server = %s\n", prim_serv);
132 (void)strncpy(cur_serv, prim_serv, MAXHOSTNAMELEN);
133 cur_serv[MAXHOSTNAMELEN - 1] = '\0';
141 if ((hp = gethostbyname(*serv_list)) != NULL) {
142 DPR2 ("Server = %s\n", *serv_list);
143 (void)strncpy(cur_serv, *serv_list, MAXHOSTNAMELEN);
144 cur_serv[MAXHOSTNAMELEN - 1] = '\0';
157 new_serv = serv_list[random() % numserv];
158 } while (!strcmp(new_serv, cur_serv));
160 if ((hp = gethostbyname(new_serv)) != NULL) {
161 DPR2 ("Server = %s\n", new_serv);
162 (void)strncpy(cur_serv, new_serv, MAXHOSTNAMELEN);
163 cur_serv[MAXHOSTNAMELEN - 1] = '\0';
171 (void) memcpy((char *)&serv_sin.sin_addr, hp->h_addr, 4);
176 server_manager(notice)
179 if (memcmp((char *)&serv_sin.sin_addr, (char *)&from.sin_addr, 4) ||
180 (serv_sin.sin_port != from.sin_port)) {
181 syslog (LOG_INFO, "Bad notice from port %u.", notice->z_port);
183 /* This is our server, handle the notice */
186 timer_reset(boot_timer);
189 DPR ("A notice came in from the server.\n");
191 switch(notice->z_kind) {
200 syslog (LOG_INFO, "Bad notice kind!?");
212 char suggested_server[MAXHOSTNAMELEN];
215 DPR("Control message!\n");
216 if (!strcmp(notice->z_opcode, SERVER_SHUTDOWN)) {
217 if (notice->z_message_len) {
218 addr = inet_addr(notice->z_message);
219 hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
221 strncpy(suggested_server, hp->h_name, sizeof(suggested_server));
222 suggested_server[sizeof(suggested_server) - 1] = '\0';
223 new_server(suggested_server);
228 new_server((char *)NULL);
230 } else if (!strcmp(notice->z_opcode, SERVER_PING)) {
231 notice->z_kind = HMACK;
232 if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) {
234 com_err("hm", ret, "setting destination");
236 if ((ret = send_outgoing(notice)) != ZERR_NONE) {
238 com_err("hm", ret, "sending ACK");
242 retransmit_queue(&serv_sin);
245 syslog (LOG_INFO, "Bad control message.");
254 struct sockaddr_in repl;
257 if (!strcmp(notice->z_opcode, HM_BOOT) ||
258 !strcmp(notice->z_opcode, HM_ATTACH)) {
259 /* ignore message, just an ack from boot, but exit if we
265 if (remove_notice_from_queue(notice, &kind, &repl) != ZERR_NONE) {
266 syslog (LOG_INFO, "Hey! This packet isn't in my queue!");
268 /* check if client wants an ACK, and send it */
270 DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port));
271 if ((ret = ZSetDestAddr(&repl)) != ZERR_NONE) {
273 com_err("hm", ret, "setting destination");
275 if ((ret = send_outgoing(notice)) != ZERR_NONE) {
277 com_err("hm", ret, "sending ACK");
284 retransmit_queue(&serv_sin);
289 new_server(sugg_serv)
293 syslog (LOG_INFO, "Server went down, finding new server.");
294 send_flush_notice(HM_DETACH);
295 find_next_server(sugg_serv);
297 send_boot_notice(HM_BOOT);
300 send_boot_notice(HM_ATTACH);
302 disable_queue_retransmits();
305 static void boot_timeout(arg)