diff options
author | Karl Ramm <kcr@mit.edu> | 2007-07-20 04:26:48 +0000 |
---|---|---|
committer | Karl Ramm <kcr@mit.edu> | 2007-07-20 04:26:48 +0000 |
commit | 82ea504def6eb144c2b13b315890b297e29345c5 (patch) | |
tree | b4623148e6feddde431fcb3b564342c5b0d64523 /zhm | |
parent | 0feeeb3f9ce439f7bca5b691c7c681319a107a8e (diff) | |
parent | e6df42eaf361b9878e79ab8964aa26e1ddb95cef (diff) |
unpack of new upstream
Diffstat (limited to 'zhm')
-rw-r--r-- | zhm/ChangeLog | 5 | ||||
-rw-r--r-- | zhm/Makefile.in | 24 | ||||
-rw-r--r-- | zhm/queue.c | 122 | ||||
-rw-r--r-- | zhm/zhm.c | 727 | ||||
-rw-r--r-- | zhm/zhm.h | 84 | ||||
-rw-r--r-- | zhm/zhm_client.c | 101 | ||||
-rw-r--r-- | zhm/zhm_server.c | 412 |
7 files changed, 691 insertions, 784 deletions
diff --git a/zhm/ChangeLog b/zhm/ChangeLog deleted file mode 100644 index 0b00623..0000000 --- a/zhm/ChangeLog +++ /dev/null @@ -1,5 +0,0 @@ -2002-01-05 Ken Raeburn <raeburn@mit.edu> - - * zhm.c (deactivate, terminate): Change function signatures to be - proper signal handler functions (one argument, signal number). - diff --git a/zhm/Makefile.in b/zhm/Makefile.in index 8cf18be..29d7217 100644 --- a/zhm/Makefile.in +++ b/zhm/Makefile.in @@ -8,30 +8,31 @@ sbindir=@sbindir@ lsbindir=@lsbindir@ includedir=${prefix}/include -mandir=@mandir@ +mandir=${prefix}/man libdir=${exec_prefix}/lib +top_builddir=.. srcdir=@srcdir@ top_srcdir=@top_srcdir@ -top_builddir=.. BUILDTOP=.. VPATH=@srcdir@ +LIBTOOL=@LIBTOOL@ CC=@CC@ INSTALL=@INSTALL@ -LIBTOOL=@LIBTOOL@ +LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la CPPFLAGS=@CPPFLAGS@ -CFLAGS=@CFLAGS@ -DSYSCONFDIR=\"@sysconfdir@\" +CFLAGS=@CFLAGS@ ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS} -LDFLAGS=-L${BUILDTOP}/lib @LDFLAGS@ -LIBS=${BUILDTOP}/lib/libzephyr.la @LIBS@ -lcom_err +LDFLAGS=@LDFLAGS@ +LIBS=${LIBZEPHYR} @LIBS@ -lcom_err OBJS= timer.o queue.o zhm.o zhm_client.o zhm_server.o all: zhm -zhm: ${OBJS} ${BUILDTOP}/lib/libzephyr.la - ${LIBTOOL} ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS} +zhm: ${OBJS} ${LIBZEPHYR} + ${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS} .c.o: ${CC} -c ${ALL_CFLAGS} $< @@ -39,11 +40,12 @@ zhm: ${OBJS} ${BUILDTOP}/lib/libzephyr.la check: install: zhm - ${LIBTOOL} ${INSTALL} -m 755 -s zhm ${DESTDIR}${lsbindir} - ${LIBTOOL} ${INSTALL} -m 644 ${srcdir}/zhm.8 ${DESTDIR}${mandir}/man8 + ${LIBTOOL} --mode=install ${INSTALL} -m 755 zhm ${DESTDIR}${lsbindir} + ${INSTALL} -m 644 ${srcdir}/zhm.8 ${DESTDIR}${mandir}/man8 clean: - ${LIBTOOL} rm -f ${OBJS} zhm + ${LIBTOOL} --mode=clean rm -f zhm + rm -f ${OBJS} ${OBJS}: zhm.h timer.h ${top_srcdir}/h/internal.h ${top_srcdir}/h/sysdep.h ${OBJS}: ${BUILDTOP}/h/config.h ${BUILDTOP}/h/zephyr/zephyr.h diff --git a/zhm/queue.c b/zhm/queue.c index ecffdbf..5a072aa 100644 --- a/zhm/queue.c +++ b/zhm/queue.c @@ -18,83 +18,78 @@ static char rcsid_queue_c[] = "$Id$"; #endif /* SABER */ #endif /* lint */ -static const int rexmit_times[] = { 2, 2, 4, 4, 8, -1 }; - -static Queue *find_notice_in_galaxy __P((galaxy_info *gi, ZNotice_t *notice)); +typedef struct _Queue { + Timer *timer; + int retries; + ZNotice_t notice; + caddr_t packet; + struct sockaddr_in reply; + struct _Queue *next, **prev_p; +} Queue; + +static Queue *hm_queue; +static int retransmits_enabled = 0; + +static Queue *find_notice_in_queue __P((ZNotice_t *notice)); +static Code_t dump_queue __P((void)); static void queue_timeout __P((void *arg)); +int rexmit_times[] = { 2, 2, 4, 4, 8, -1 }; + #ifdef DEBUG -Code_t dump_galaxy_queue(galaxy_info *); +Code_t dump_queue(); #endif -void init_galaxy_queue(galaxy_info *gi) +void init_queue() { Queue *q; - while (gi->queue) { - q = gi->queue; + while (hm_queue) { + q = hm_queue; if (q->timer) timer_reset(q->timer); free(q->packet); - gi->queue = q->next; + hm_queue = q->next; free(q); } DPR("Queue initialized and flushed.\n"); } -Code_t add_notice_to_galaxy(gi, notice, repl, len) - galaxy_info *gi; +Code_t add_notice_to_queue(notice, packet, repl, len) ZNotice_t *notice; + char * packet; struct sockaddr_in *repl; int len; { Queue *entry; - int length; - int retval; DPR("Adding notice to queue...\n"); - if (!find_notice_in_galaxy(gi, notice)) { + if (!find_notice_in_queue(notice)) { entry = (Queue *) malloc(sizeof(Queue)); if (entry == NULL) return(ZERR_NONOTICE); - entry->gi = gi; entry->retries = 0; - if (!(entry->packet = (char *) malloc((unsigned)sizeof(ZPacket_t)))) { + entry->packet = (char *) malloc(Z_MAXPKTLEN); + if (entry->packet == NULL) { free(entry); - return(ENOMEM); + return(ZERR_NONOTICE); } - - if ((retval = ZFormatSmallRawNotice(notice, entry->packet, &length)) - != ZERR_NONE) { + memcpy(entry->packet, packet, Z_MAXPKTLEN); + if (ZParseNotice(entry->packet, len, &entry->notice) != ZERR_NONE) { + syslog(LOG_ERR, "ZParseNotice failed, but succeeded before"); free(entry->packet); - free(entry); - return(retval); - } - - /* I dislike this, but I need a notice which represents the - packet. since the notice structure refers to the internals - of its packet, I can't use the notice which was passed in, - so I need to make a new one. */ - - if ((retval = ZParseNotice(entry->packet, length, &entry->notice)) - != ZERR_NONE) { - free(entry->packet); - free(entry); - return(retval); + } else { + entry->reply = *repl; + LIST_INSERT(&hm_queue, entry); } - - entry->reply = *repl; - LIST_INSERT(&gi->queue, entry); - - entry->timer = (gi->state == ATTACHED) ? - timer_set_rel(rexmit_times[0], queue_timeout, entry) : NULL; + entry->timer = (retransmits_enabled) ? + timer_set_rel(rexmit_times[0], queue_timeout, entry) : NULL; } return(ZERR_NONE); } -Code_t remove_notice_from_galaxy(gi, notice, kind, repl) - galaxy_info *gi; +Code_t remove_notice_from_queue(notice, kind, repl) ZNotice_t *notice; ZNotice_Kind_t *kind; struct sockaddr_in *repl; @@ -102,7 +97,7 @@ Code_t remove_notice_from_galaxy(gi, notice, kind, repl) Queue *entry; DPR("Removing notice from queue...\n"); - entry = find_notice_in_galaxy(gi, notice); + entry = find_notice_in_queue(notice); if (entry == NULL) return(ZERR_NONOTICE); @@ -120,14 +115,19 @@ Code_t remove_notice_from_galaxy(gi, notice, kind, repl) } /* We have a server; transmit all of our packets. */ -void retransmit_galaxy(gi) - galaxy_info *gi; +void retransmit_queue(sin) + struct sockaddr_in *sin; { Queue *entry; Code_t ret; DPR("Retransmitting queue to new server...\n"); - for (entry = gi->queue; entry; entry = entry->next) { + ret = ZSetDestAddr(sin); + if (ret != ZERR_NONE) { + Zperr (ret); + com_err("queue", ret, "setting destination"); + } + for (entry = hm_queue; entry; entry = entry->next) { DPR("notice:\n"); DPR2("\tz_kind: %d\n", entry->notice.z_kind); DPR2("\tz_port: %u\n", ntohs(entry->notice.z_port)); @@ -136,7 +136,7 @@ void retransmit_galaxy(gi) DPR2("\tz_opcode: %s\n", entry->notice.z_opcode); DPR2("\tz_sender: %s\n", entry->notice.z_sender); DPR2("\tz_recip: %s\n", entry->notice.z_recipient); - ret = send_outgoing(&gi->sin, &entry->notice); + ret = send_outgoing(&entry->notice); if (ret != ZERR_NONE) { Zperr(ret); com_err("queue", ret, "sending raw notice"); @@ -144,36 +144,36 @@ void retransmit_galaxy(gi) entry->timer = timer_set_rel(rexmit_times[0], queue_timeout, entry); entry->retries = 0; } + retransmits_enabled = 1; } /* We lost our server; nuke all of our timers. */ -void disable_galaxy_retransmits(gi) - galaxy_info *gi; +void disable_queue_retransmits() { Queue *entry; - for (entry = gi->queue; entry; entry = entry->next) { + for (entry = hm_queue; entry; entry = entry->next) { if (entry->timer) timer_reset(entry->timer); entry->timer = NULL; } + retransmits_enabled = 0; } #ifdef DEBUG -static Code_t dump_galaxy_queue(gi) - galaxy_info *gi; +static Code_t dump_queue() { Queue *entry; caddr_t mp; int ml; DPR("Dumping queue...\n"); - if (!gi->queue) { + if (!hm_queue) { printf("Queue is empty.\n"); return; } - for (entry = gi->queue; entry; entry = entry->next) { + for (entry = hm_queue; entry; entry = entry->next) { printf("notice:\n"); printf("\tz_kind: %d\n", entry->notice.z_kind); printf("\tz_port: %u\n", ntohs(entry->notice.z_port)); @@ -193,24 +193,22 @@ static Code_t dump_galaxy_queue(gi) } #endif /* DEBUG */ -int galaxy_queue_len(gi) - galaxy_info *gi; +int queue_len() { int length = 0; Queue *entry; - for (entry = gi->queue; entry; entry = entry->next) + for (entry = hm_queue; entry; entry = entry->next) length++; return length; } -static Queue *find_notice_in_galaxy(gi, notice) - galaxy_info *gi; +static Queue *find_notice_in_queue(notice) ZNotice_t *notice; { Queue *entry; - for (entry = gi->queue; entry; entry = entry->next) { + for (entry = hm_queue; entry; entry = entry->next) { if (ZCompareUID(&entry->notice.z_uid, ¬ice->z_uid)) return entry; } @@ -224,14 +222,14 @@ static void queue_timeout(arg) Code_t ret; entry->timer = NULL; - + ret = ZSetDestAddr(&serv_sin); if (ret != ZERR_NONE) { Zperr(ret); com_err("queue", ret, "setting destination"); } entry->retries++; if (rexmit_times[entry->retries] == -1) { - galaxy_new_server(entry->gi, NULL); + new_server(NULL); return; } DPR("Resending notice:\n"); @@ -242,7 +240,7 @@ static void queue_timeout(arg) DPR2("\tz_opcode: %s\n", entry->notice.z_opcode); DPR2("\tz_sender: %s\n", entry->notice.z_sender); DPR2("\tz_recip: %s\n", entry->notice.z_recipient); - ret = send_outgoing(&entry->gi->sin, &entry->notice); + ret = send_outgoing(&entry->notice); if (ret != ZERR_NONE) { Zperr(ret); com_err("queue", ret, "sending raw notice"); @@ -10,75 +10,55 @@ * "mit-copyright.h". */ -#include <stdio.h> -#include <errno.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> - #include "zhm.h" static const char rcsid_hm_c[] = "$Id$"; -#ifdef macII -#define srandom srand48 +#ifdef HAVE_HESIOD +int use_hesiod = 0; #endif -#ifdef _PATH_VARRUN -#define PIDDIR _PATH_VARRUN -#else -#define PIDDIR "/etc/" +#ifdef macII +#define srandom srand48 #endif +#define PIDDIR "/var/athena/" -int hmdebug = 0, noflushflag = 0; -time_t starttime; +int hmdebug, rebootflag, noflushflag, errflg, dieflag, inetd, oldpid, nofork; +int no_server = 1, nservchang, nserv, nclt; +int booting = 1, timeout_type, deactivated = 1; +long starttime; u_short cli_port; -struct sockaddr_in cli_sin; +struct sockaddr_in cli_sin, serv_sin, from; +int numserv; +char **serv_list = NULL; +char prim_serv[MAXHOSTNAMELEN], cur_serv[MAXHOSTNAMELEN]; +char *zcluster; +int deactivating = 0; +int terminating = 0; +struct hostent *hp; +char hostname[MAXHOSTNAMELEN], loopback[4]; char PidFile[128]; -char *conffile = NULL; -char *confline = NULL; -galaxy_info *galaxy_list = NULL; -int ngalaxies = 0; - -volatile int deactivating = 0; -volatile int terminating = 0; - -static RETSIGTYPE deactivate __P(()); -static RETSIGTYPE terminate __P(()); -static void init_hm __P((int, int)); -static void parse_conf __P((char *, char *)); +static RETSIGTYPE deactivate __P((void)); +static RETSIGTYPE terminate __P((void)); +static void choose_server __P((void)); +static void init_hm __P((void)); static void detach __P((void)); static void send_stats __P((ZNotice_t *, struct sockaddr_in *)); static char *strsave __P((const char *)); extern int optind; -extern char *optarg; -static RETSIGTYPE deactivate(int signo) +static RETSIGTYPE deactivate() { deactivating = 1; } -static RETSIGTYPE terminate(int signo) +static RETSIGTYPE terminate() { terminating = 1; } -static void die_gracefully() -{ - int i; - - syslog(LOG_INFO, "Terminate signal caught..."); - - for (i=0; i<ngalaxies; i++) - galaxy_flush(&galaxy_list[i]); - - unlink(PidFile); - closelog(); - exit(0); -} - main(argc, argv) char *argv[]; { @@ -86,15 +66,17 @@ char *argv[]; ZPacket_t packet; Code_t ret; int opt, pak_len, i, j = 0, fd, count; - int dieflag = 0, rebootflag = 0, inetd = 0, nofork = 0, errflg = 0; fd_set readers; struct timeval tv; - struct hostent *hp; - struct sockaddr_in from; sprintf(PidFile, "%szhm.pid", PIDDIR); - while ((opt = getopt(argc, argv, "drhinc:f")) != EOF) + if (gethostname(hostname, MAXHOSTNAMELEN) < 0) { + printf("Can't find my hostname?!\n"); + exit(-1); + } + prim_serv[0] = '\0'; + while ((opt = getopt(argc, argv, "drhinf")) != EOF) switch(opt) { case 'd': hmdebug = 1; @@ -116,9 +98,6 @@ char *argv[]; case 'n': nofork = 1; break; - case 'c': - conffile = optarg; - break; case 'f': noflushflag = 1; break; @@ -127,56 +106,61 @@ char *argv[]; errflg++; break; } + if (errflg) { + fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [-f] [server]\n", + argv[0]); + exit(2); + } + + numserv = 0; /* Override server argument? */ if (optind < argc) { - if (conffile) { - errflg++; + if ((hp = gethostbyname(argv[optind++])) == NULL) { + printf("Unknown server name: %s\n", argv[optind-1]); } else { - int len; - static const char lg[] = "local-galaxy hostlist"; - - len = sizeof(lg)+1; - for (i=optind; i < argc; i++) - len += strlen(argv[i])+1; + strncpy(prim_serv, hp->h_name, sizeof(prim_serv)); + prim_serv[sizeof(prim_serv) - 1] = '\0'; + } - if ((confline = (char *) malloc(len)) == NULL) { - fprintf(stderr, "Out of memory constructing default galaxy"); - exit(1); - } - strcpy(confline, lg); - for (i=optind; i < argc; i++) { - strcat(confline, " "); - strcat(confline, argv[i]); + /* argc-optind is the # of other servers on the command line */ + serv_list = (char **) malloc((argc - optind + 2) * sizeof(char *)); + if (serv_list == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + serv_list[numserv++] = prim_serv; + for (; optind < argc; optind++) { + if ((hp = gethostbyname(argv[optind])) == NULL) { + printf("Unknown server name '%s', ignoring\n", argv[optind]); + continue; } + serv_list[numserv++] = strsave(hp->h_name); } + serv_list[numserv] = NULL; } +#ifdef HAVE_HESIOD + else + use_hesiod = 1; +#endif - if (errflg) { - fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [-f] [server... | -c conffile ]\n", argv[0]); - exit(2); + choose_server(); + if (*prim_serv == '\0') { + printf("No valid primary server found, exiting.\n"); + exit(ZERR_SERVNAK); } + init_hm(); - ZSetServerState(1); /* Aargh!!! */ - if ((ret = ZInitialize()) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "initializing"); - closelog(); - exit(-1); - } - - parse_conf(conffile, confline); - - init_hm(inetd, nofork); - - for (;;) { + DPR2("zephyr server port: %u\n", ntohs(serv_sin.sin_port)); + DPR2("zephyr client port: %u\n", ntohs(cli_port)); + + /* Main loop */ + for ever { /* Wait for incoming packets or queue timeouts. */ DPR("Waiting for a packet..."); - fd = ZGetFD(); FD_ZERO(&readers); FD_SET(fd, &readers); - count = select(fd + 1, &readers, NULL, NULL, timer_timeout(&tv)); if (count == -1 && errno != EINTR) { syslog(LOG_CRIT, "select() failed: %m"); @@ -191,203 +175,177 @@ char *argv[]; if (dieflag) { die_gracefully(); } else { - for (i=0; i<ngalaxies; i++) - galaxy_reset(&galaxy_list[i]); + choose_server(); + send_flush_notice(HM_FLUSH); + deactivated = 1; } } timer_process(); - if (count == 0) - continue; - - if ((ret = ZReceivePacket(packet, &pak_len, &from)) != ZERR_NONE) { - if (ret != EINTR) { + if (count > 0) { + ret = ZReceivePacket(packet, &pak_len, &from); + if ((ret != ZERR_NONE) && (ret != EINTR)){ Zperr(ret); com_err("hm", ret, "receiving notice"); + } else if (ret != EINTR) { + /* Where did it come from? */ + if ((ret = ZParseNotice(packet, pak_len, ¬ice)) + != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "parsing notice"); + } else { + DPR("Got a packet.\n"); + 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); + DPR2("\tz_def_format: %s\n", notice.z_default_format); + DPR2("\tz_message: %s\n", notice.z_message); + if (memcmp(loopback, &from.sin_addr, 4) && + ((notice.z_kind == SERVACK) || + (notice.z_kind == SERVNAK) || + (notice.z_kind == HMCTL))) { + server_manager(¬ice); + } else { + if (!memcmp(loopback, &from.sin_addr, 4) && + ((notice.z_kind == UNSAFE) || + (notice.z_kind == UNACKED) || + (notice.z_kind == ACKED) || + (notice.z_kind == HMCTL))) { + /* Client program... */ + if (deactivated) { + send_boot_notice(HM_BOOT); + deactivated = 0; + } + transmission_tower(¬ice, packet, pak_len); + DPR2("Pending = %d\n", ZPending()); + } else { + if (notice.z_kind == STAT) { + send_stats(¬ice, &from); + } else { + syslog(LOG_INFO, + "Unknown notice type: %d", + notice.z_kind); + } + } + } + } } - continue; - } - - /* Where did it come from? */ - if ((ret = ZParseNotice(packet, pak_len, ¬ice)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "parsing notice"); - - continue; - } - - DPR("Got a packet.\n"); - 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); - DPR2("\tz_def_format: %s\n", notice.z_default_format); - DPR2("\tz_message: %s\n", notice.z_message); - - if ((from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) && - ((notice.z_kind == SERVACK) || - (notice.z_kind == SERVNAK) || - (notice.z_kind == HMCTL))) { - server_manager(¬ice, &from); - } else if ((from.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && - ((notice.z_kind == UNSAFE) || - (notice.z_kind == UNACKED) || - (notice.z_kind == ACKED) || - (notice.z_kind == HMCTL))) { - transmission_tower(¬ice, &from, packet, pak_len); - DPR2("Pending = %d\n", ZPending()); - } else if (notice.z_kind == STAT) { - send_stats(¬ice, &from); - } else { - syslog(LOG_INFO, "Unknown notice type: %d", - notice.z_kind); } } } -static void parse_conf(conffile, confline) - char *conffile; - char *confline; +static void choose_server() { - struct servent *sp; - int zsrvport; - char filename[MAXPATHLEN]; - FILE *file; - int lineno; - char buf[1024]; - Code_t code; - int i; - - /* this isn't a wonderful place to put this, but the alternatives - don't seem any better */ - - sp = getservbyname(SERVER_SVCNAME, "udp"); - zsrvport = (sp) ? sp->s_port : SERVER_SVC_FALLBACK; - - if (confline) { - if ((galaxy_list = (galaxy_info *) malloc(sizeof(galaxy_info))) == NULL) { - fprintf(stderr, "Out of memory parsing command line %s", - filename); - exit(1); - } - - if (code = Z_ParseGalaxyConfig(confline, - &galaxy_list[ngalaxies].galaxy_config)) { - fprintf(stderr, "Error in command line: %s", error_message(code)); - exit(1); - } - - if (galaxy_list[ngalaxies].galaxy_config.galaxy == NULL) { - fprintf(stderr, - "the command line did not contain any valid galaxies."); - exit(1); - } - - ngalaxies++; - } else { - if (conffile == NULL) - sprintf(filename, "%s/zephyr/zhm.conf", SYSCONFDIR); - else - strcpy(filename, conffile); - - if ((file = fopen(filename, "r")) == NULL) { -#ifdef ZEPHYR_USES_HESIOD - if ((galaxy_list = (galaxy_info *) malloc(sizeof(galaxy_info))) - == NULL) { - fprintf(stderr, "Out of memory parsing command line %s", - filename); - exit(1); - } - - if (code = Z_ParseGalaxyConfig("local-galaxy hesiod zephyr", - &galaxy_list[ngalaxies].galaxy_config)) { - fprintf(stderr, "Internal error parsing hesiod default"); - exit(1); - } - - if (galaxy_list[ngalaxies].galaxy_config.galaxy == NULL) { - fprintf(stderr, "Internal error using hesiod default"); - exit(1); - } - - ngalaxies++; -#else - fprintf(stderr, "Error opening configuration file %s: %s\n", - filename, strerror(errno)); - exit(1); -#endif + int i = 0; + char **clust_info, **cpp; + +#ifdef HAVE_HESIOD + if (use_hesiod) { + + /* Free up any previously used resources */ + if (prim_serv[0]) + i = 1; + while (i < numserv) + free(serv_list[i++]); + if (serv_list) + free(serv_list); + + numserv = 0; + prim_serv[0] = '\0'; + + if ((clust_info = hes_resolve(hostname, "CLUSTER")) == NULL) { + zcluster = NULL; } else { - for (lineno = 1; ; lineno++) { - if (fgets(buf, sizeof(buf), file) == NULL) { - if (ferror(file)) { - fprintf(stderr, - "Error reading configuration file %s: %s", - filename, strerror(errno)); - exit(1); + for (cpp = clust_info; *cpp; cpp++) { + /* Remove the following check once we have changed over to + * new Hesiod format (i.e. ZCLUSTER.sloc lookup, no primary + * server + */ + if (!strncasecmp("ZEPHYR", *cpp, 6)) { + register char *c; + + if ((c = strchr(*cpp, ' ')) == 0) { + printf("Hesiod error getting primary server info.\n"); + } else { + strncpy(prim_serv, c+1, sizeof(prim_serv)); + prim_serv[sizeof(prim_serv) - 1] = '\0'; } break; } - - if (galaxy_list) { - galaxy_list = (galaxy_info *) - realloc(galaxy_list, sizeof(galaxy_info)*(ngalaxies+1)); - } else { - galaxy_list = (galaxy_info *) - malloc(sizeof(galaxy_info)); - } - - if (galaxy_list == NULL) { - fprintf(stderr, - "Out of memory reading configuration file %s", - filename); - exit(1); - } - - if (code = Z_ParseGalaxyConfig(buf, - &galaxy_list[ngalaxies].galaxy_config)) { - fprintf(stderr, - "Error in configuration file %s, line %d: %s", - filename, lineno, error_message(code)); - exit(1); + if (!strncasecmp("ZCLUSTER", *cpp, 9)) { + register char *c; + + if ((c = strchr(*cpp, ' ')) == 0) { + printf("Hesiod error getting zcluster info.\n"); + } else { + if ((zcluster = malloc((unsigned)(strlen(c+1)+1))) + != NULL) { + strcpy(zcluster, c+1); + } else { + printf("Out of memory.\n"); + exit(-5); + } + } + break; } - - if (galaxy_list[ngalaxies].galaxy_config.galaxy) - ngalaxies++; } + for (cpp = clust_info; *cpp; cpp++) + free(*cpp); } - if (ngalaxies == 0) { - fprintf(stderr, - "Configuration file %s did not contain any valid galaxies."); - exit(1); + if (zcluster == NULL) { + if ((zcluster = malloc((unsigned)(strlen("zephyr")+1))) != NULL) + strcpy(zcluster, "zephyr"); + else { + printf("Out of memory.\n"); + exit(-5); + } } + while ((serv_list = hes_resolve(zcluster, "sloc")) == (char **)NULL) { + syslog(LOG_ERR, "No servers or no hesiod"); + /* wait a bit, and try again */ + sleep(30); + } + cpp = (char **) malloc(2 * sizeof(char *)); + if (cpp == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + if (prim_serv[0]) + cpp[numserv++] = prim_serv; + for (i = 0; serv_list[i]; i++) { + /* copy in non-duplicates */ + /* assume the names returned in the sloc are full domain names */ + if (!prim_serv[0] || strcasecmp(prim_serv, serv_list[i])) { + cpp = (char **) realloc(cpp, (numserv+2) * sizeof(char *)); + if (cpp == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + cpp[numserv++] = strsave(serv_list[i]); + } + } + for (i = 0; serv_list[i]; i++) + free(serv_list[i]); + cpp[numserv] = NULL; + serv_list = cpp; } - - for (i=0; i<ngalaxies; i++) { - galaxy_list[i].current_server = NO_SERVER; -#if 0 - galaxy_list[i].sin.sin_len = sizeof(struct in_addr); #endif - galaxy_list[i].sin.sin_family = AF_INET; - galaxy_list[i].sin.sin_port = zsrvport; - galaxy_list[i].state = NEED_SERVER; - galaxy_list[i].nchange = 0; - galaxy_list[i].nsrvpkts = 0; - galaxy_list[i].ncltpkts = 0; - galaxy_list[i].queue = NULL; - init_galaxy_queue(&galaxy_list[i]); - galaxy_list[i].boot_timer = NULL; + + if (!prim_serv[0] && numserv) { + srandom(time(NULL)); + strncpy(prim_serv, serv_list[random() % numserv], sizeof(prim_serv)); + prim_serv[sizeof(prim_serv) - 1] = '\0'; } } -static void init_hm(inetd, nofork) - int inetd; - int nofork; +static void init_hm() { struct servent *sp; Code_t ret; @@ -395,12 +353,29 @@ static void init_hm(inetd, nofork) #ifdef _POSIX_VERSION struct sigaction sa; #endif - struct hostent *hp; - int i; starttime = time((time_t *)0); OPENLOG("hm", LOG_PID, LOG_DAEMON); + ZSetServerState(1); /* Aargh!!! */ + if ((ret = ZInitialize()) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "initializing"); + closelog(); + exit(-1); + } + init_queue(); + + if (*prim_serv == '\0') { + strncpy(prim_serv, *serv_list, sizeof(prim_serv)); + prim_serv[sizeof(prim_serv) - 1] = '\0'; + } + + loopback[0] = 127; + loopback[1] = 0; + loopback[2] = 0; + loopback[3] = 1; + if (inetd) { ZSetFD(0); /* fd 0 is on the socket, thanks to inetd */ } else { @@ -414,9 +389,12 @@ static void init_hm(inetd, nofork) exit(ret); } } - cli_sin = ZGetDestAddr(); + sp = getservbyname(SERVER_SVCNAME, "udp"); + memset(&serv_sin, 0, sizeof(struct sockaddr_in)); + serv_sin.sin_port = (sp) ? sp->s_port : SERVER_SVC_FALLBACK; + #ifndef DEBUG if (!inetd && !nofork) detach(); @@ -433,10 +411,24 @@ static void init_hm(inetd, nofork) syslog(LOG_INFO, "Debugging on."); } - /* Initiate communication with each galaxy */ + /* Set up communications with server */ + /* target is SERVER_SVCNAME port on server machine */ + + serv_sin.sin_family = AF_INET; + + /* who to talk to */ + if ((hp = gethostbyname(prim_serv)) == NULL) { + DPR("gethostbyname failed\n"); + find_next_server(NULL); + } else { + DPR2("Server = %s\n", prim_serv); + strncpy(cur_serv, prim_serv, sizeof(cur_serv)); + cur_serv[sizeof(cur_serv) - 1] = '\0'; + memcpy(&serv_sin.sin_addr, hp->h_addr, 4); + } - for (i=0; i<ngalaxies; i++) - galaxy_new_server(&galaxy_list[i], NULL); + send_boot_notice(HM_BOOT); + deactivated = 0; #ifdef _POSIX_VERSION sigemptyset(&sa.sa_mask); @@ -498,8 +490,8 @@ static void send_stats(notice, sin) ZNotice_t newnotice; Code_t ret; char *bfr; - char **list; - int len, i, j, nitems; + char *list[20]; + int len, i, nitems = 10; unsigned long size; newnotice = *notice; @@ -510,149 +502,87 @@ static void send_stats(notice, sin) } newnotice.z_kind = HMACK; -#define NSTATS 12 - - nitems = NSTATS*ngalaxies; - - list = (char **) malloc(sizeof(char *)*nitems); - if (list == NULL) { - printf("Out of memory.\n"); - exit(5); + list[0] = (char *) malloc(MAXHOSTNAMELEN); + if (list[0] == NULL) { + printf("Out of memory.\n"); + exit(-5); } - - for (i=0; i<ngalaxies; i++) { - list[i*NSTATS] = (char *) malloc(MAXHOSTNAMELEN); - if (list[i*NSTATS] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - if (galaxy_list[i].current_server == NO_SERVER) - strcpy(list[i*NSTATS+0], "NO_SERVER"); - else if (galaxy_list[i].current_server == EXCEPTION_SERVER) - strcpy(list[i*NSTATS+0], inet_ntoa(galaxy_list[i].sin.sin_addr)); - else - strcpy(list[i*NSTATS+0], - galaxy_list[i].galaxy_config.server_list[galaxy_list[i].current_server].name); - list[i*NSTATS+1] = (char *) malloc(64); - if (list[i*NSTATS+1] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+1], "%d", galaxy_queue_len(&galaxy_list[i])); - list[i*NSTATS+2] = (char *) malloc(64); - if (list[i*NSTATS+2] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+2], "%d", galaxy_list[i].ncltpkts); - list[i*NSTATS+3] = (char *) malloc(64); - if (list[i*NSTATS+3] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+3], "%d", galaxy_list[i].nsrvpkts); - list[i*NSTATS+4] = (char *) malloc(64); - if (list[i*NSTATS+4] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+4], "%d", galaxy_list[i].nchange); - list[i*NSTATS+5] = (char *) malloc(64); - if (list[i*NSTATS+5] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - strcpy(list[i*NSTATS+5], rcsid_hm_c); - list[i*NSTATS+6] = (char *) malloc(64); - if (list[i*NSTATS+6] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - switch (galaxy_list[i].state) { - case NEED_SERVER: - sprintf(list[i*NSTATS+6], "yes (need server)"); - break; - case DEAD_SERVER: - sprintf(list[i*NSTATS+6], "yes (dead server)"); - break; - case BOOTING: - sprintf(list[i*NSTATS+6], "yes (booting)"); - break; - case ATTACHING: - sprintf(list[i*NSTATS+6], "yes (attaching)"); - break; - case ATTACHED: - sprintf(list[i*NSTATS+6], "no (attached)"); - break; - default: - sprintf(list[i*NSTATS+6], "weird value %x", galaxy_list[i].state); - break; - } - list[i*NSTATS+7] = (char *) malloc(64); - if (list[i*NSTATS+7] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+7], "%ld", (long) (time((time_t *)0) - starttime)); + strcpy(list[0], cur_serv); + list[1] = (char *) malloc(64); + if (list[1] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[1], "%d", queue_len()); + list[2] = (char *) malloc(64); + if (list[2] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[2], "%d", nclt); + list[3] = (char *) malloc(64); + if (list[3] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[3], "%d", nserv); + list[4] = (char *) malloc(64); + if (list[4] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[4], "%d", nservchang); + list[5] = (char *) malloc(64); + if (list[5] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + strncpy(list[5], rcsid_hm_c, 64); + list[5][63] = '\0'; + + list[6] = (char *) malloc(64); + if (list[6] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + if (no_server) + sprintf(list[6], "yes"); + else + sprintf(list[6], "no"); + list[7] = (char *) malloc(64); + if (list[7] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[7], "%ld", time((time_t *)0) - starttime); #ifdef adjust_size - size = (unsigned long)sbrk(0); - adjust_size (size); + size = (unsigned long)sbrk(0); + adjust_size (size); #else - size = -1; + size = -1; #endif - list[i*NSTATS+8] = (char *)malloc(64); - if (list[i*NSTATS+8] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - sprintf(list[i*NSTATS+8], "%ld", size); - list[i*NSTATS+9] = (char *)malloc(32); - if (list[i*NSTATS+9] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - strcpy(list[i*NSTATS+9], MACHINE_TYPE); - list[i*NSTATS+10] = (char *)malloc(64); - if (list[i*NSTATS+10] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - strcpy(list[i*NSTATS+10], galaxy_list[i].galaxy_config.galaxy); - - len = strlen(galaxy_list[i].galaxy_config.galaxy)+1; - len += strlen("hostlist "); - for (j=0; j<galaxy_list[i].galaxy_config.nservers; j++) - len += 1+strlen(galaxy_list[i].galaxy_config.server_list[j].name); - len++; - - list[i*NSTATS+11] = (char *) malloc(len); - if (list[i*NSTATS+11] == NULL) { - printf("Out of memory.\n"); - exit(5); - } - strcpy(list[i*NSTATS+11], galaxy_list[i].galaxy_config.galaxy); - strcat(list[i*NSTATS+11], " hostlist"); - for (j=0; j<galaxy_list[i].galaxy_config.nservers; j++) { - strcat(list[i*NSTATS+11], " "); - strcat(list[i*NSTATS+11], - galaxy_list[i].galaxy_config.server_list[j].name); - } + list[8] = (char *)malloc(64); + if (list[8] == NULL) { + printf("Out of memory.\n"); + exit(-5); + } + sprintf(list[8], "%ld", size); + list[9] = (char *)malloc(32); + if (list[9] == NULL) { + printf("Out of memory.\n"); + exit(-5); } + strncpy(list[9], MACHINE_TYPE, 32); + list[9][31] = '\0'; /* Since ZFormatRaw* won't change the version number on notices, we need to set the version number explicitly. This code is taken from Zinternal.c, function Z_FormatHeader */ if (!*version) sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR, - ZVERSIONMINOR_NOGALAXY); + ZVERSIONMINOR); newnotice.z_version = version; -#if 1 - if ((ret = ZSendRawList(&newnotice, list, nitems)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending stat notice"); - } -#else if ((ret = ZFormatRawNoticeList(&newnotice, list, nitems, &bfr, &len)) != ZERR_NONE) { syslog(LOG_INFO, "Couldn't format stats packet"); @@ -663,10 +593,17 @@ static void send_stats(notice, sin) } } free(bfr); -#endif for(i=0;i<nitems;i++) free(list[i]); - free(list); +} + +void die_gracefully() +{ + syslog(LOG_INFO, "Terminate signal caught..."); + send_flush_notice(HM_FLUSH); + unlink(PidFile); + closelog(); + exit(0); } static char *strsave(sp) @@ -42,78 +42,30 @@ #define Zperr(e) #endif -#define BOOT_TIMEOUT 10 -#define DEAD_TIMEOUT 5*60 - -typedef struct _Queue { - struct _galaxy_info *gi; - Timer *timer; - int retries; - ZNotice_t notice; - caddr_t packet; - struct sockaddr_in reply; - struct _Queue *next, **prev_p; -} Queue; - -typedef enum _galaxy_state { - NEED_SERVER, /* never had a server, HM_BOOT when we find one. This can - also be set if a flush was requested when the state - was != ATTACHED. */ - DEAD_SERVER, /* server timed out, no others around. This is - actually handled in the same way as BOOTING or - ATTACHING (although some of the timeouts are - different), but it's handy to know which of the two - states the zhm is in */ - BOOTING, /* waiting for HM_BOOT SERVACK */ - ATTACHING, /* waiting for HM_BOOT SERVACK */ - ATTACHED /* active and connected */ -} galaxy_state; - -typedef struct _galaxy_info { - Z_GalaxyConfig galaxy_config; - -#define NO_SERVER -1 -#define EXCEPTION_SERVER -2 - int current_server; - struct sockaddr_in sin; - galaxy_state state; - - int nchange; - int nsrvpkts; - int ncltpkts; - - Queue *queue; - Timer *boot_timer; -} galaxy_info; +#define ever (;;) + +#define BOOTING 1 +#define NOTICES 2 /* main.c */ +void die_gracefully __P((void)); /* zhm_client.c */ -void transmission_tower __P((ZNotice_t *, struct sockaddr_in *, char *, int)); -Code_t send_outgoing __P((struct sockaddr_in *, ZNotice_t *)); +void transmission_tower __P((ZNotice_t *, char *, int)); +Code_t send_outgoing __P((ZNotice_t *)); /* queue.c */ -void init_galaxy_queue __P((galaxy_info *)); -Code_t add_notice_to_galaxy __P((galaxy_info *, ZNotice_t *, - struct sockaddr_in *, int)); -Code_t remove_notice_from_galaxy __P((galaxy_info *, ZNotice_t *, - ZNotice_Kind_t *, struct sockaddr_in *)); -void retransmit_galaxy __P((galaxy_info *)); -void disable_galaxy_retransmits __P((galaxy_info *)); -int galaxy_queue_len __P((galaxy_info *)); - -/* zhm.c */ -extern galaxy_info *galaxy_list; -extern int ngalaxies; -extern int noflushflag; - -/* zhm_server.c */ -void server_manager __P((ZNotice_t *, struct sockaddr_in *)); -void hm_control __P((galaxy_info *, ZNotice_t *)); -void galaxy_new_server __P((galaxy_info *, struct in_addr *addr)); -void galaxy_flush __P((galaxy_info *)); -void galaxy_reset __P((galaxy_info *)); - +void init_queue __P((void)); +Code_t add_notice_to_queue __P((ZNotice_t *, char *, struct sockaddr_in *, + int)); +Code_t remove_notice_from_queue __P((ZNotice_t *, ZNotice_Kind_t *, + struct sockaddr_in *)); +void retransmit_queue __P((struct sockaddr_in *)); +void disable_queue_retransmits __P((void)); +int queue_len __P((void)); + +struct sockaddr_in serv_sin; +extern int rexmit_times[]; #ifdef vax #define use_etext diff --git a/zhm/zhm_client.c b/zhm/zhm_client.c index 87b7362..6ee448b 100644 --- a/zhm/zhm_client.c +++ b/zhm/zhm_client.c @@ -18,95 +18,79 @@ static char rcsid_hm_client_c[] = "$Id$"; #endif /* SABER */ #endif /* lint */ -extern int noflushflag; -extern struct sockaddr_in cli_sin; +extern int no_server, nclt, deactivated, noflushflag; +extern struct sockaddr_in cli_sin, serv_sin, from; -void transmission_tower(notice, from, packet, pak_len) +void transmission_tower(notice, packet, pak_len) ZNotice_t *notice; - struct sockaddr_in *from; char *packet; int pak_len; { - int i; - galaxy_info *gi; ZNotice_t gack; Code_t ret; struct sockaddr_in gsin; - if (notice->z_dest_galaxy) { - for (i=0; i<ngalaxies; i++) - if (strcasecmp(galaxy_list[i].galaxy_config.galaxy, - notice->z_dest_galaxy) == 0) { - gi = &galaxy_list[i]; - break; - } - if (i == ngalaxies) { - /* XXX I should generate some sort of error here. Fortunately, - only new clients can elicit this error, so I can use a new - error value (message body string, probably) here. For now, - just return and let the sender time out. */ - return; - } - } else { - gi = &galaxy_list[0]; - } - + nclt++; if (notice->z_kind == HMCTL) { if (!strcmp(notice->z_opcode, CLIENT_FLUSH)) { if (noflushflag) syslog(LOG_INFO, "Client requested hm flush (disabled)."); - else - galaxy_flush(gi); + else { + send_flush_notice(HM_FLUSH); + deactivated = 1; + } } else if (!strcmp(notice->z_opcode, CLIENT_NEW_SERVER)) { - galaxy_new_server(gi, NULL); + new_server((char *)NULL); } else { syslog (LOG_INFO, "Bad control notice from client."); } return; - } - - if (notice->z_kind != UNSAFE) { - gack = *notice; - gack.z_kind = HMACK; - gack.z_message_len = 0; - gack.z_multinotice = ""; - gsin = cli_sin; - gsin.sin_port = from->sin_port; - if (gack.z_port == 0) - gack.z_port = from->sin_port; - notice->z_port = gack.z_port; - /* Bounce ACK to library */ - if ((ret = send_outgoing(&gsin, &gack)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending raw notice"); + } else { + if (notice->z_kind != UNSAFE) { + gack = *notice; + gack.z_kind = HMACK; + gack.z_message_len = 0; + gack.z_multinotice = ""; + gsin = cli_sin; + 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"); + } + /* Bounce ACK to library */ + if ((ret = send_outgoing(&gack)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending raw notice"); + } } } - - /* remove the dest galaxy, since the servers aren't prepared for it */ - notice->z_dest_galaxy = NULL; - - if (gi->current_server != NO_SERVER) { - if ((ret = send_outgoing(&gi->sin, notice)) != ZERR_NONE) { + if (!no_server) { + 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"); + } + if ((ret = send_outgoing(notice)) != ZERR_NONE) { Zperr(ret); com_err("hm", ret, "while sending raw notice"); } } - - add_notice_to_galaxy(gi, notice, &gsin, pak_len); + if (add_notice_to_queue(notice, packet, &gsin, pak_len) != ZERR_NONE) + syslog(LOG_INFO, "Hey! Insufficient memory to add notice to queue!"); } Code_t -send_outgoing(sin, notice) - struct sockaddr_in *sin; - ZNotice_t *notice; +send_outgoing(notice) +ZNotice_t *notice; { Code_t retval; char *packet; int length; - if ((retval = ZSetDestAddr(sin)) != ZERR_NONE) - return(retval); - if (!(packet = (char *) malloc((unsigned)sizeof(ZPacket_t)))) return(ENOMEM); @@ -115,11 +99,8 @@ send_outgoing(sin, notice) free(packet); return(retval); } - retval = ZSendPacket(packet, length, 0); - free(packet); - return(retval); } diff --git a/zhm/zhm_server.c b/zhm/zhm_server.c index 9d515d5..50fa04f 100644 --- a/zhm/zhm_server.c +++ b/zhm/zhm_server.c @@ -18,15 +18,30 @@ static char rcsid_hm_server_c[] = "$Id$"; #endif /* SABER */ #endif /* lint */ -static void send_back __P((galaxy_info *, ZNotice_t *)); static void boot_timeout __P((void *)); +static int get_serv_timeout __P((void)); -extern int hmdebug; -extern u_short cli_port; +static Timer *boot_timer = NULL; +static int serv_rexmit_times[] = { 5, 10, 20, 40 }; +static int serv_timeouts = 0; -static void send_hmctl_notice(gi, op) - galaxy_info *gi; - char *op; +int serv_loop = 0; +extern u_short cli_port; +extern struct sockaddr_in serv_sin, from; +extern int timeout_type, hmdebug, nservchang, booting, nserv, no_server; +extern int deactivated, rebootflag; +extern int numserv; +extern char **serv_list; +extern char cur_serv[], prim_serv[]; +extern void die_gracefully(); + +void hm_control(), send_back(), new_server(); + +/* Argument is whether we are actually booting, or just attaching + * after a server switch */ +void +send_boot_notice(op) +char *op; { ZNotice_t notice; Code_t ret; @@ -40,244 +55,271 @@ static void send_hmctl_notice(gi, op) notice.z_sender = "HM"; notice.z_recipient = ""; notice.z_default_format = ""; - notice.z_dest_galaxy = ""; notice.z_num_other_fields = 0; notice.z_message_len = 0; - if ((ret = ZSetDestAddr(&gi->sin)) != ZERR_NONE) { + /* 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, ZNOAUTH)) != ZERR_NONE) { Zperr(ret); - com_err("hm", ret, "sending hmctl notice %s", op); + com_err("hm", ret, "sending startup notice"); } + boot_timer = timer_set_rel(get_serv_timeout(), boot_timeout, NULL); } -static int choose_next_server(gi) - galaxy_info *gi; +/* Argument is whether we are detaching or really going down */ +void +send_flush_notice(op) +char *op; { - int new_server; + ZNotice_t notice; + Code_t ret; + + /* Set up server notice */ + notice.z_kind = HMCTL; + notice.z_port = cli_port; + notice.z_class = ZEPHYR_CTL_CLASS; + notice.z_class_inst = ZEPHYR_CTL_HM; + notice.z_opcode = op; + notice.z_sender = "HM"; + notice.z_recipient = ""; + notice.z_default_format = ""; + notice.z_num_other_fields = 0; + notice.z_message_len = 0; - if (gi->current_server < 0) { - new_server = random() % gi->galaxy_config.nservers; - } else if (gi->galaxy_config.nservers == 1) { - new_server = NO_SERVER; - } else if ((new_server = (random() % (gi->galaxy_config.nservers - 1))) == - gi->current_server) { - new_server = gi->galaxy_config.nservers - 1; + /* Tell server to lose us */ + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = ZSendNotice(¬ice, ZNOAUTH)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending flush notice"); } - - return(new_server); } -void server_manager(notice, from) - ZNotice_t *notice; - struct sockaddr_in *from; +void +find_next_server(sugg_serv) +char *sugg_serv; { - int i; - galaxy_info *gi; + struct hostent *hp; + int done = 0; + char **parse = serv_list; + char *new_serv; + + if (sugg_serv) { + do { + if (!strcmp(*parse, sugg_serv)) + done = 1; + } while ((done == 0) && (*++parse != NULL)); + } + if (done) { + if ((hp = gethostbyname(sugg_serv)) != NULL) { + DPR2 ("Server = %s\n", sugg_serv); + (void)strncpy(cur_serv, sugg_serv, MAXHOSTNAMELEN); + cur_serv[MAXHOSTNAMELEN - 1] = '\0'; + if (hmdebug) + syslog(LOG_DEBUG, "Suggested server: %s\n", sugg_serv); + } else { + done = 0; + } + } + while (!done) { + if ((++serv_loop > 3) && (strcmp(cur_serv, prim_serv))) { + serv_loop = 0; + if ((hp = gethostbyname(prim_serv)) != NULL) { + DPR2 ("Server = %s\n", prim_serv); + (void)strncpy(cur_serv, prim_serv, MAXHOSTNAMELEN); + cur_serv[MAXHOSTNAMELEN - 1] = '\0'; + done = 1; + break; + } + } + + switch (numserv) { + case 1: + if ((hp = gethostbyname(*serv_list)) != NULL) { + DPR2 ("Server = %s\n", *serv_list); + (void)strncpy(cur_serv, *serv_list, MAXHOSTNAMELEN); + cur_serv[MAXHOSTNAMELEN - 1] = '\0'; + done = 1; + break; + } + /* fall through */ + case 0: + if (rebootflag) + die_gracefully(); + else + sleep(1); + break; + default: + do { + new_serv = serv_list[random() % numserv]; + } while (!strcmp(new_serv, cur_serv)); + + if ((hp = gethostbyname(new_serv)) != NULL) { + DPR2 ("Server = %s\n", new_serv); + (void)strncpy(cur_serv, new_serv, MAXHOSTNAMELEN); + cur_serv[MAXHOSTNAMELEN - 1] = '\0'; + done = 1; + } else + sleep(1); + + break; + } + } + (void) memcpy((char *)&serv_sin.sin_addr, hp->h_addr, 4); + nservchang++; +} - for (i=0; i<ngalaxies; i++) - if ((memcmp((char *)&galaxy_list[i].sin.sin_addr, - (char *)&from->sin_addr, 4) == 0) && - (galaxy_list[i].sin.sin_port == from->sin_port)) { - gi = &galaxy_list[i]; +void +server_manager(notice) +ZNotice_t *notice; +{ + if (memcmp((char *)&serv_sin.sin_addr, (char *)&from.sin_addr, 4) || + (serv_sin.sin_port != from.sin_port)) { + syslog (LOG_INFO, "Bad notice from port %u.", notice->z_port); + } else { + /* This is our server, handle the notice */ + booting = 0; + serv_timeouts = 0; + if (boot_timer) { + timer_reset(boot_timer); + boot_timer = NULL; + } + DPR ("A notice came in from the server.\n"); + nserv++; + switch(notice->z_kind) { + case HMCTL: + hm_control(notice); + break; + case SERVNAK: + case SERVACK: + send_back(notice); + break; + default: + syslog (LOG_INFO, "Bad notice kind!?"); break; } - - if (!gi) { - syslog(LOG_INFO, "Bad server notice from %s:%u.", - inet_ntoa(from->sin_addr), from->sin_port); - return; - } - - DPR ("A notice came in from the server.\n"); - - if (gi->boot_timer) { - timer_reset(gi->boot_timer); - gi->boot_timer = NULL; - } - - gi->nsrvpkts++; - - switch (gi->state) { - case NEED_SERVER: - /* there's a server which thinks it cares about us. it's - wrong. reboot the hm. */ - send_hmctl_notice(gi, HM_BOOT); - - gi->state = BOOTING; - gi->boot_timer = timer_set_rel(BOOT_TIMEOUT, boot_timeout, gi); - - return; - case DEAD_SERVER: - /* the server is back from the dead. reanimate the queue and - pretend it never went away */ - /* fall through */ - case BOOTING: - /* got the ack. */ - retransmit_galaxy(gi); - gi->state = ATTACHED; - break; - } - - switch(notice->z_kind) { - case HMCTL: - hm_control(gi, notice); - break; - case SERVNAK: - case SERVACK: - send_back(gi, notice); - break; - default: - syslog (LOG_INFO, "Bad notice kind %d", notice->z_kind); - break; } } -void hm_control(gi, notice) - galaxy_info *gi; - ZNotice_t *notice; +void +hm_control(notice) +ZNotice_t *notice; { Code_t ret; struct hostent *hp; - char suggested_server[64]; - struct in_addr addr; + char suggested_server[MAXHOSTNAMELEN]; + unsigned long addr; DPR("Control message!\n"); if (!strcmp(notice->z_opcode, SERVER_SHUTDOWN)) { if (notice->z_message_len) { - addr.s_addr = inet_addr(notice->z_message); - galaxy_new_server(gi, &addr); + addr = inet_addr(notice->z_message); + hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); + if (hp != NULL) { + strncpy(suggested_server, hp->h_name, sizeof(suggested_server)); + suggested_server[sizeof(suggested_server) - 1] = '\0'; + new_server(suggested_server); + } else { + new_server(NULL); + } } else { - galaxy_new_server(gi, NULL); + new_server((char *)NULL); } } else if (!strcmp(notice->z_opcode, SERVER_PING)) { notice->z_kind = HMACK; - if ((ret = send_outgoing(&gi->sin, notice)) != ZERR_NONE) { + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = send_outgoing(notice)) != ZERR_NONE) { Zperr(ret); com_err("hm", ret, "sending ACK"); } + if (no_server) { + no_server = 0; + retransmit_queue(&serv_sin); + } } else { syslog (LOG_INFO, "Bad control message."); } } -static void send_back(gi, notice) - galaxy_info *gi; - ZNotice_t *notice; +void +send_back(notice) +ZNotice_t *notice; { ZNotice_Kind_t kind; struct sockaddr_in repl; Code_t ret; - if ((strcmp(notice->z_opcode, HM_BOOT) == 0) || - (strcmp(notice->z_opcode, HM_ATTACH) == 0)) - return; - - if (remove_notice_from_galaxy(gi, notice, &kind, &repl) != ZERR_NONE) { - syslog (LOG_INFO, "Hey! This packet isn't in my queue!"); - return; - } - - /* check if client wants an ACK, and send it */ - if (kind == ACKED) { - DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port)); - if ((ret = send_outgoing(&repl, notice)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending ACK"); + if (!strcmp(notice->z_opcode, HM_BOOT) || + !strcmp(notice->z_opcode, HM_ATTACH)) { + /* ignore message, just an ack from boot, but exit if we + * are rebooting. + */ + if (rebootflag) + die_gracefully(); + } else { + if (remove_notice_from_queue(notice, &kind, &repl) != ZERR_NONE) { + syslog (LOG_INFO, "Hey! This packet isn't in my queue!"); + } else { + /* check if client wants an ACK, and send it */ + if (kind == ACKED) { + 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 = send_outgoing(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending ACK"); + } + } } } -} - -void galaxy_new_server(gi, addr) - galaxy_info *gi; - struct in_addr *addr; -{ - int i; - int new_server; - - if (gi->state == ATTACHED) { - disable_galaxy_retransmits(gi); - gi->nchange++; - syslog(LOG_INFO, "Server went down, finding new server."); - } - - if (gi->current_server != NO_SERVER) - send_hmctl_notice(gi, HM_DETACH); - - if (gi->boot_timer) { - timer_reset(gi->boot_timer); - gi->boot_timer = 0; + if (no_server) { + no_server = 0; + retransmit_queue(&serv_sin); } - - if (addr) { - gi->current_server = EXCEPTION_SERVER; - gi->sin.sin_addr = *addr; - - for (i=0; i<gi->galaxy_config.nservers; i++) - if (gi->galaxy_config.server_list[i].addr.s_addr == - gi->sin.sin_addr.s_addr) { - gi->current_server = i; - break; - } - - gi->state = ATTACHING; - } else if ((new_server = choose_next_server(gi)) == NO_SERVER) { - /* the only server went away. Set a boot timer, try again - later */ - - gi->current_server = NO_SERVER; - - gi->state = (gi->state == BOOTING)?NEED_SERVER:DEAD_SERVER; - gi->boot_timer = timer_set_rel(DEAD_TIMEOUT, boot_timeout, gi); - - return; - } else { - gi->current_server = new_server; - gi->sin.sin_addr = - gi->galaxy_config.server_list[gi->current_server].addr; - - gi->state = (gi->state == NEED_SERVER)?BOOTING:ATTACHING; - } - - send_hmctl_notice(gi, (gi->state == BOOTING)?HM_BOOT:HM_ATTACH); - gi->boot_timer = timer_set_rel(BOOT_TIMEOUT, boot_timeout, gi); } -void galaxy_flush(gi) - galaxy_info *gi; +void +new_server(sugg_serv) +char *sugg_serv; { - init_galaxy_queue(gi); - - /* to flush, actually do a boot, because this causes an ACK to - come back when it completes */ - - if (gi->state == ATTACHED) { - send_hmctl_notice(gi, HM_BOOT); - - gi->state = BOOTING; - gi->boot_timer = timer_set_rel(BOOT_TIMEOUT, boot_timeout, gi); + no_server = 1; + syslog (LOG_INFO, "Server went down, finding new server."); + send_flush_notice(HM_DETACH); + find_next_server(sugg_serv); + if (booting) { + send_boot_notice(HM_BOOT); + deactivated = 0; } else { - gi->state = NEED_SERVER; + send_boot_notice(HM_ATTACH); } -} - -void galaxy_reset(gi) - galaxy_info *gi; -{ - gi->current_server = NO_SERVER; - gi->nchange = 0; - gi->nsrvpkts = 0; - gi->ncltpkts = 0; - - galaxy_flush(gi); + disable_queue_retransmits(); } static void boot_timeout(arg) void *arg; { - galaxy_new_server((galaxy_info *) arg, NULL); + serv_timeouts++; + new_server(NULL); } +static int get_serv_timeout(void) +{ + int ind, ntimeouts; + + ind = (numserv == 0) ? serv_timeouts : serv_timeouts / numserv; + ntimeouts = sizeof(serv_rexmit_times) / sizeof(*serv_rexmit_times); + if (ind >= ntimeouts) + ind = ntimeouts - 1; + return serv_rexmit_times[ind]; +} |