summaryrefslogtreecommitdiff
path: root/zhm
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@mit.edu>2007-07-20 04:26:48 +0000
committerGravatar Karl Ramm <kcr@mit.edu>2007-07-20 04:26:48 +0000
commit82ea504def6eb144c2b13b315890b297e29345c5 (patch)
treeb4623148e6feddde431fcb3b564342c5b0d64523 /zhm
parent0feeeb3f9ce439f7bca5b691c7c681319a107a8e (diff)
parente6df42eaf361b9878e79ab8964aa26e1ddb95cef (diff)
unpack of new upstream
Diffstat (limited to 'zhm')
-rw-r--r--zhm/ChangeLog5
-rw-r--r--zhm/Makefile.in24
-rw-r--r--zhm/queue.c122
-rw-r--r--zhm/zhm.c727
-rw-r--r--zhm/zhm.h84
-rw-r--r--zhm/zhm_client.c101
-rw-r--r--zhm/zhm_server.c412
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, &notice->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");
diff --git a/zhm/zhm.c b/zhm/zhm.c
index b8476a5..1354c9e 100644
--- a/zhm/zhm.c
+++ b/zhm/zhm.c
@@ -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, &notice))
+ != 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(&notice);
+ } 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(&notice, packet, pak_len);
+ DPR2("Pending = %d\n", ZPending());
+ } else {
+ if (notice.z_kind == STAT) {
+ send_stats(&notice, &from);
+ } else {
+ syslog(LOG_INFO,
+ "Unknown notice type: %d",
+ notice.z_kind);
+ }
+ }
+ }
+ }
}
- continue;
- }
-
- /* Where did it come from? */
- if ((ret = ZParseNotice(packet, pak_len, &notice)) != 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(&notice, &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(&notice, &from, packet, pak_len);
- DPR2("Pending = %d\n", ZPending());
- } else if (notice.z_kind == STAT) {
- send_stats(&notice, &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)
diff --git a/zhm/zhm.h b/zhm/zhm.h
index 1d4ef2b..3d6f153 100644
--- a/zhm/zhm.h
+++ b/zhm/zhm.h
@@ -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(&notice, 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(&notice, 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];
+}