diff options
author | David C. Jedlinsky <opus@mit.edu> | 1987-06-25 23:09:44 +0000 |
---|---|---|
committer | David C. Jedlinsky <opus@mit.edu> | 1987-06-25 23:09:44 +0000 |
commit | 6241a2861863289827afd68018c67d01b98c3918 (patch) | |
tree | 4c9a35ceabc30ecfa49c183d3a035b84637170a1 /zhm/zhm.c | |
parent | aab45f135df128d6f09999849094366ced2559ba (diff) |
90% finished - needs timer routines, and a few control things here
and there.
Diffstat (limited to 'zhm/zhm.c')
-rw-r--r-- | zhm/zhm.c | 419 |
1 files changed, 303 insertions, 116 deletions
@@ -15,7 +15,9 @@ #include <zephyr/zephyr.h> #ifndef lint +#ifndef SABER static char rcsid_hm_c[] = "$Header$"; +#endif SABER #endif lint #include <syslog.h> @@ -23,10 +25,11 @@ static char rcsid_hm_c[] = "$Header$"; #include <netdb.h> #include <sys/socket.h> #include <sys/param.h> +#include <hesiod.h> #ifdef DEBUG -#define DPR(a) fprintf(stderr, a) -#define DPR2(a,b) fprintf(stderr, a, b) +#define DPR(a) fprintf(stderr, a); fflush(stderr) +#define DPR2(a,b) fprintf(stderr, a, b); fflush(stderr) #else #define DPR(a) #define DPR2(a,b) @@ -35,169 +38,353 @@ static char rcsid_hm_c[] = "$Header$"; #define ever (;;) #define Zperr(e) fprintf(stderr, "Error = %d\n", e) -int serv_sock; +int serv_sock, no_server = 1, exp_serv = 0; struct sockaddr_in cli_sin, serv_sin, from; +struct hostent *hp; +char **serv_list, **cur_serv; +u_short cli_port; +char hostname[MAXHOSTNAMELEN], loopback[4]; extern int errno; +extern char *malloc(); + +void init_hm(); main(argc, argv) char *argv[]; { - struct hostent *hp; - struct servent *sp; - int cli_port; - ZPacket_t packet; + caddr_t packet; ZNotice_t notice; - int auth, len; - Code_t repl; - char hostname[MAXHOSTNAMELEN]; - - if (argc < 2) { - printf("Usage: %s server_machine\n", argv[0]); - exit(-1); - } - - ZInitialize(); - gethostname(hostname, MAXHOSTNAMELEN); - - /* Open client socket, for receiving client and server notices */ - - sp = getservbyname("zephyr-hm", "udp"); - cli_port = ntohs(sp->s_port); - - if ((repl = ZOpenPort(&cli_port)) != ZERR_NONE) { - Zperr(repl); - com_err("hm", repl, "opening port"); + Code_t ret; + + /* Override server argument? */ + if (argc > 1) { + exp_serv = 1; + /* who to talk to */ + if ((hp = gethostbyname(argv[1])) == NULL) { + DPR("gethostbyname failed\n"); + exp_serv = 0; + } + DPR2 ("Server = %s\n", argv[1]); } - cli_sin = ZGetDestAddr(); - cli_sin.sin_port = sp->s_port; - - /* Open the server socket */ - sp = getservbyname("zephyr-clt", "udp"); - serv_sin.sin_port = sp->s_port; - - if ((serv_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - printf("server socket failed\n"); - exit(1); - } + init_hm(); DPR2 ("zephyr server port: %u\n", ntohs(serv_sin.sin_port)); - DPR2 ("zephyr client port: %u\n", cli_port); + DPR2 ("zephyr client port: %u\n", ntohs(cli_port)); - /* This is here until hesiod or something that can find NS is put in */ - - /* who to talk to */ - if ((hp = gethostbyname(argv[1])) == NULL) { - printf("gethostbyname failed\n"); - exit(1); - } - - /* Set up communications with server */ - /* target is "zephyr-clt" port on server machine */ - - serv_sin.sin_family = AF_INET; - bcopy(hp->h_addr, &serv_sin.sin_addr, hp->h_length); - - /* Set up server notice */ - notice.z_kind = ACK; - notice.z_checksum[0] = 0x100; - notice.z_checksum[1] = 0x200; - notice.z_port = (short) cli_port; - notice.z_class = "HMBOOT"; - notice.z_class_inst = hostname; - notice.z_opcode = "opcode"; - notice.z_sender = "sender"; - notice.z_recipient = "recip"; - notice.z_message_len = 0; - - /* send it off, using ZSendNotice */ - + /* Put in a fork here... */ /* Sleep with wakeup call set */ for ever { DPR ("Waiting for a packet..."); - if ((repl = ZReceivePacket(packet, sizeof packet, - &len, &from)) != ZERR_NONE) { - Zperr(repl); - com_err("hm", repl, "receiving packet"); + packet = (char *) malloc(Z_MAXPKTLEN); + if ((ret = ZReceiveNotice(packet, Z_MAXPKTLEN, ¬ice, + NULL, &from)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "receiving notice"); + free(packet); } else { - if ((repl = ZParseNotice(packet, len, - ¬ice, &auth)) != ZERR_NONE) { - Zperr(repl); - com_err("hm", repl, "parsing notice"); - } /* Where did it come from? */ DPR ("Got a packet.\n"); - - /* Client program... */ - transmission_tower(¬ice); + DPR ("notice:\n"); + DPR2("\tz_kind: %d\n", notice.z_kind); + DPR2("\tz_port: %u\n", ntohs(notice.z_port)); + DPR2("\tz_class: %s\n", notice.z_class); + DPR2("\tz_class_inst: %s\n", notice.z_class_inst); + DPR2("\tz_opcode: %s\n", notice.z_opcode); + DPR2("\tz_sender: %s\n", notice.z_sender); + DPR2("\tz_recip: %s\n", notice.z_recipient); + if ((notice.z_kind == SERVACK) || + (notice.z_kind == SERVNAK) || + (notice.z_kind == HMCTL)) { + server_manager(¬ice); + free(packet); + } else { + if (bcmp(loopback, &from.sin_addr, 4) == 0) { + /* Client program... */ + transmission_tower(¬ice, packet); + DPR2 ("Pending = %d\n", ZPending()); + } else { + fprintf(stderr, "Unknown notice type: %d\n", + notice.z_kind); + free(packet); + } + } } - } - } -/* This will eventually use Hesiod */ - -find_next_server(current_hostent) -struct hostent **current_hostent; +void init_hm() { - if ((*current_hostent = gethostbyname("hal")) == NULL) { - perror("gethostbyname failed\n"); + struct servent *sp; + Code_t ret; + + ZInitialize(); + ZSetServerState(1); /* Aargh!!! */ + gethostname(hostname, MAXHOSTNAMELEN); + init_queue(); + if ((serv_list = hes_resolve("*", "ZEPHYR-SERVER")) == (char **)NULL) { + syslog(LOG_ERR, "No servers?!?"); + exit(1); + } + cur_serv = serv_list; + --cur_serv; + + loopback[0] = 127; + loopback[1] = 0; + loopback[2] = 0; + loopback[3] = 1; + + /* Open client socket, for receiving client and server notices */ + + sp = getservbyname("zephyr-hm", "udp"); + cli_port = sp->s_port; + + if ((ret = ZOpenPort(&cli_port)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "opening port"); + } + cli_sin = ZGetDestAddr(); + cli_sin.sin_port = sp->s_port; + + /* Open the server socket */ + + sp = getservbyname("zephyr-clt", "udp"); + bzero(&serv_sin, sizeof(struct sockaddr_in)); + serv_sin.sin_port = sp->s_port; + + if ((serv_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + printf("server socket failed\n"); exit(1); } + + /* Set up communications with server */ + /* target is "zephyr-clt" port on server machine */ + + serv_sin.sin_family = AF_INET; + if (!exp_serv) + find_next_server(); + else + bcopy(hp->h_addr, &serv_sin.sin_addr, hp->h_length); + + send_boot_notice(); +} + +send_boot_notice() +{ + ZNotice_t notice; + Code_t ret; + + /* Set up server notice */ + notice.z_kind = ACKED; + notice.z_port = cli_port; + notice.z_class = ZEPHYR_CTL_CLASS; + notice.z_class_inst = ZEPHYR_CTL_HM; + notice.z_opcode = HM_BOOT; + notice.z_sender = "sender"; + notice.z_recipient = "recip"; + notice.z_message_len = 0; + + /* Notify server that this host is here */ + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendNotice(¬ice, 0)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending startup notice"); + } +} + +find_next_server() +{ + struct hostent *hp; + + if (*++cur_serv == NULL) + cur_serv = serv_list; + DPR2 ("Server = %s\n", *cur_serv); + hp = gethostbyname(*cur_serv); + bcopy(hp->h_addr, &serv_sin.sin_addr, hp->h_length); } server_manager(notice) -ZNotice_t notice; + ZNotice_t *notice; +{ + DPR ("A notice came in from the server.\n"); + if (bcmp(&serv_sin.sin_addr, &from.sin_addr, 4) != 0) { + DPR2 ("Bad notice from port %u\n", notice->z_port); + /* Sent a notice back saying this hostmanager isn't theirs */ + } else { + /* This is our server, handle the notice */ + no_server = 0; + switch(notice->z_kind) { + case HMCTL: + hm_control(notice); + break; + case SERVNAK: + send_nak(notice); + break; + case SERVACK: + send_ack(notice); + break; + default: + DPR ("Bad notice kind!?\n"); + break; + } + } +} + +hm_control(notice) + ZNotice_t *notice; { - printf("A notice came in from the server.\n"); + Code_t ret; + + DPR("Control message!\n"); + if (strcmp(notice->z_opcode, SERVER_SHUTDOWN)) + new_server(); + else if (strcmp(notice->z_opcode, SERVER_PING)) { + notice->z_kind = HMACK; + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendRawNotice(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending ACK"); + } + } else + fprintf(stderr, "Bad control message.\n"); } -transmission_tower(notice) -ZNotice_t *notice; +send_nak(notice) + ZNotice_t *notice; +{ + caddr_t packet; + struct sockaddr_in repl; + Code_t ret; + + if (!strcmp(notice->z_opcode, HM_BOOT)) { + /* ignore message, just a nak from boot */ + } else { + if (remove_notice_from_queue(notice, &packet, + &repl) != ZERR_NONE) { + DPR ("Hey! This packet isn't in my queue!\n"); + } else { + /* check if client wants an ACK, and send it */ + if (notice->z_kind == ACKED) { + notice->z_kind = SERVNAK; + DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port)); + if ((ret = ZSetDestAddr(&repl)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendRawNotice(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending NAK"); + } + } + free(packet); + } + } +} + +send_ack(notice) + ZNotice_t *notice; +{ + caddr_t packet; + struct sockaddr_in repl; + Code_t ret; + + if (!strcmp(notice->z_opcode, HM_BOOT)) { + /* ignore message, just an ack from boot */ + } else { + if (remove_notice_from_queue(notice, &packet, + &repl) != ZERR_NONE) { + DPR ("Hey! This packet isn't in my queue!\n"); + } else { + /* check if client wants an ACK, and send it */ + if (notice->z_kind == ACKED) { + notice->z_kind = SERVACK; + DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port)); + if ((ret = ZSetDestAddr(&repl)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendRawNotice(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending ACK"); + } + } + free(packet); + } + } +} + +transmission_tower(notice, packet) + ZNotice_t *notice; + caddr_t packet; { ZNotice_t gack; - Code_t repl; + Code_t ret; struct sockaddr_in gsin; gack = *notice; DPR2 ("Message = %s\n", gack.z_message); gack.z_kind = HMACK; gack.z_message_len = 0; - /* Make library think the client is the HM */ gsin = cli_sin; - gsin.sin_port = htons(gack.z_port); - if (gack.z_port == 0) { - gack.z_port = ntohs(from.sin_port); - gsin.sin_port = from.sin_port; + gsin.sin_port = from.sin_port; + if (gack.z_port == 0) + gack.z_port = from.sin_port; + DPR2 ("Client Port = %u\n", ntohs(gack.z_port)); + notice->z_port = gack.z_port; + if ((ret = ZSetDestAddr(&gsin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); } - DPR2 ("Client Port = %u\n", gack.z_port); - if ((repl = ZSetDestAddr(&gsin)) != ZERR_NONE) { - Zperr(repl); - com_err("hm", repl, "setting destination"); + /* Bounce ACK to library */ + if ((ret = ZSendRawNotice(&gack)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending raw notice"); } - if ((repl = ZSendRawNotice(&gack)) != ZERR_NONE) { - Zperr(repl); - com_err("hm", repl, "sending raw notice"); + DPR2 ("Server Port = %u\n", ntohs(serv_sin.sin_port)); + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); } - gsin = serv_sin; - DPR2 ("Server Port = %u\n", ntohs(gsin.sin_port)); - if ((repl = ZSetDestAddr(&gsin)) != ZERR_NONE) { - printf("Error = %d\n", repl); - com_err("hm", repl, "setting destination"); + if ((ret = ZSendRawNotice(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "while sending raw notice"); } - if ((repl = ZSendRawNotice(notice)) != ZERR_NONE) { - printf("Error = %d\n", repl); - com_err("hm", repl, "while sending raw notice"); - } - add_notice_to_queue(notice); + add_notice_to_queue(notice, packet, &gsin); } new_server() { - perror("server going down.\n"); - exit(1); + ZNotice_t notice; + Code_t ret; + + no_server = 1; + DPR ("server going down.\n"); + notice.z_kind = ACKED; + notice.z_port = cli_port; + notice.z_class = ZEPHYR_CTL_CLASS; + notice.z_class_inst = ZEPHYR_CTL_HM; + notice.z_opcode = HM_FLUSH; + notice.z_sender = "sender"; + notice.z_recipient = "recip"; + notice.z_message_len = 0; + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendNotice(¬ice, 0)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending flush notice"); + } + find_next_server(); + send_boot_notice(); + retransmit_queue(); } |