Commit 54bc15c4 authored by Leigh Stoller's avatar Leigh Stoller

Middle part of the event system changes. The main part of this change

is to add HMACs to events to ensure they that events cannot be
injected into an experiment by an unauthorized client.

* The frontend now generates a secret key for each experiment and
  stores that into a file and in the DB.

* Each of the event clients, as well as the event producers
  (scheduler, tevc) have a new -k option to specify the name of the
  file. Two new event library functions were added for clients to give
  the key:

    event_handle_t
    event_register_withkeyfile(char *name, int threaded, char *keyfile);

    event_handle_t
    event_register_withkeydata(char *name, int threaded,
	   		       unsigned char *keydata, int keylen);

* When the library is in possesion of a key, it will generate an HMAC
  and attach it to outgoing notifications. A client receiving a
  notification will compute an HMAC and compare it against the HMAC in
  the notification. If they do not compare, the notification is
  dropped with a warning message printed (the client callback never
  gets the notification). If the client has not provided a key, then
  the HMAC in the incoming notification is ignored.

* The scheduler also takes a -k option, and will compute HMACs for all
  of the static events ahead of time. That keeps it off the critical
  path.

* The tevc client also takes a -k option. However, tevc will always
  try to find the keyfile (default path) so that it can attach the
  HMAC to dynamic events before sending them to the scheduler (which
  will check to make sure it matches). The scheduler will not accept
  dynamic events without unless the HMAC is present and matches.

* I have rebuilt the elvin librarys, removing all of the X goop and
  the SSL goop. Smaller binaries. So, I had to add -lcrypto to all of
  the client makefiles to that programs link.

* The program-agent got a few more changes. The command string is no
  longer passed inside the event; it comes in when the program agent
  is started, via a config file generated from tmcd data. This gets
  rid of our mostly insecure remote execution facility.
parent bf5b43d3
...@@ -13,9 +13,9 @@ include $(OBJDIR)/Makeconf ...@@ -13,9 +13,9 @@ include $(OBJDIR)/Makeconf
SYSTEM := $(shell uname -s) SYSTEM := $(shell uname -s)
SUBDIRS = lib tbgen trafgen program-agent SUBDIRS = lib tbgen trafgen program-agent proxy example
ifeq ($(SYSTEM),FreeBSD) ifeq ($(SYSTEM),FreeBSD)
SUBDIRS += sched example delay-agent nsetrafgen stated proxy SUBDIRS += sched delay-agent nsetrafgen stated
endif endif
all: $(SUBDIRS) all: $(SUBDIRS)
...@@ -60,21 +60,18 @@ install: ...@@ -60,21 +60,18 @@ install:
@$(MAKE) -C stated install @$(MAKE) -C stated install
client-install: client-install:
ifeq ($(SYSTEM),FreeBSD)
@$(MAKE) -C nsetrafgen client-install @$(MAKE) -C nsetrafgen client-install
@$(MAKE) -C delay-agent client-install @$(MAKE) -C delay-agent client-install
@$(MAKE) -C program-agent client-install endif
@$(MAKE) -C tbgen client-install @$(MAKE) -C tbgen client-install
@$(MAKE) -C program-agent client-install
@$(MAKE) -C trafgen client-install @$(MAKE) -C trafgen client-install
@$(MAKE) -C proxy client-install @$(MAKE) -C proxy client-install
control-install: control-install:
@$(MAKE) -C tbgen control-install @$(MAKE) -C tbgen control-install
linux-install:
@$(MAKE) -C program-agent client-install
@$(MAKE) -C tbgen client-install
@$(MAKE) -C trafgen client-install
clean: subdir-clean clean: subdir-clean
subdir-clean: subdir-clean:
......
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group. # Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
...@@ -22,7 +22,7 @@ CFLAGS += `elvin-config --cflags vin4c` ...@@ -22,7 +22,7 @@ CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static LDFLAGS += -static
LDFLAGS += -L../lib -L${OBJDIR}/lib/libtb LDFLAGS += -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c` LIBS += `elvin-config --libs vin4c`
OBJS = main.o callback.o OBJS = main.o callback.o
......
...@@ -75,6 +75,7 @@ int main(int argc, char **argv) ...@@ -75,6 +75,7 @@ int main(int argc, char **argv)
char *map_file = NULL; char *map_file = NULL;
char *log_file = "/tmp/agentlog"; char *log_file = "/tmp/agentlog";
char *pid_file = NULL; char *pid_file = NULL;
char *keyfile = NULL;
FILE *mp = NULL; FILE *mp = NULL;
//char *log = NULL; //char *log = NULL;
char buf[BUFSIZ]; char buf[BUFSIZ];
...@@ -86,7 +87,7 @@ int main(int argc, char **argv) ...@@ -86,7 +87,7 @@ int main(int argc, char **argv)
opterr = 0; opterr = 0;
/* get params from the optstring */ /* get params from the optstring */
while ((c = getopt(argc, argv, "s:p:f:dE:l:i:")) != -1) { while ((c = getopt(argc, argv, "s:p:f:dE:l:i:k:")) != -1) {
switch (c) { switch (c) {
case 'd': case 'd':
debug++; debug++;
...@@ -109,6 +110,9 @@ int main(int argc, char **argv) ...@@ -109,6 +110,9 @@ int main(int argc, char **argv)
case 'E': case 'E':
myexp = optarg; myexp = optarg;
break; break;
case 'k':
keyfile = optarg;
break;
case '?': case '?':
default: default:
usage(argv[0]); usage(argv[0]);
...@@ -274,7 +278,7 @@ int main(int argc, char **argv) ...@@ -274,7 +278,7 @@ int main(int argc, char **argv)
/* register with the event system*/ /* register with the event system*/
handle = event_register(server, 0); handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) { if (handle == NULL) {
error("could not register with event system\n"); error("could not register with event system\n");
return 1; return 1;
...@@ -319,7 +323,8 @@ void usage(char *progname) ...@@ -319,7 +323,8 @@ void usage(char *progname)
info("entering function usage\n"); info("entering function usage\n");
#endif #endif
fprintf(stderr, "Usage: %s -s server [-p port] -f link-map-file\n", fprintf(stderr, "Usage: %s -s server [-p port] [-k keyfile] "
"-f link-map-file\n",
progname); progname);
exit(-1); exit(-1);
} }
......
...@@ -3,6 +3,7 @@ TESTBED_SRCDIR = @top_srcdir@ ...@@ -3,6 +3,7 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../.. OBJDIR = ../..
SUBDIR = event/example SUBDIR = event/example
SYSTEM := $(shell uname -s)
PROGRAMS = tbrecv tbsend eventdebug.pl PROGRAMS = tbrecv tbsend eventdebug.pl
include $(OBJDIR)/Makeconf include $(OBJDIR)/Makeconf
...@@ -17,8 +18,11 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb ...@@ -17,8 +18,11 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c` CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c` LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux)
LIBS += -ldl
endif
tbrecv: tbrecv.o tbrecv: tbrecv.o
$(CC) $(LDFLAGS) -o $@ tbrecv.o $(LIBS) $(CC) $(LDFLAGS) -o $@ tbrecv.o $(LIBS)
......
...@@ -25,7 +25,7 @@ void ...@@ -25,7 +25,7 @@ void
usage() usage()
{ {
fprintf(stderr, fprintf(stderr,
"Usage: %s [-s server] [-p port]\n", progname); "Usage: %s [-s server] [-p port] [-k keyfile]\n", progname);
exit(-1); exit(-1);
} }
...@@ -35,6 +35,7 @@ main(int argc, char **argv) ...@@ -35,6 +35,7 @@ main(int argc, char **argv)
event_handle_t handle; event_handle_t handle;
address_tuple_t tuple; address_tuple_t tuple;
char *server = NULL; char *server = NULL;
char *keyfile = NULL;
char *port = NULL; char *port = NULL;
char *ipaddr = NULL; char *ipaddr = NULL;
char buf[BUFSIZ], ipbuf[BUFSIZ]; char buf[BUFSIZ], ipbuf[BUFSIZ];
...@@ -42,7 +43,7 @@ main(int argc, char **argv) ...@@ -42,7 +43,7 @@ main(int argc, char **argv)
progname = argv[0]; progname = argv[0];
while ((c = getopt(argc, argv, "s:p:i:")) != -1) { while ((c = getopt(argc, argv, "s:p:k:")) != -1) {
switch (c) { switch (c) {
case 's': case 's':
server = optarg; server = optarg;
...@@ -50,6 +51,9 @@ main(int argc, char **argv) ...@@ -50,6 +51,9 @@ main(int argc, char **argv)
case 'p': case 'p':
port = optarg; port = optarg;
break; break;
case 'k':
keyfile = optarg;
break;
default: default:
usage(); usage();
} }
...@@ -114,7 +118,7 @@ main(int argc, char **argv) ...@@ -114,7 +118,7 @@ main(int argc, char **argv)
/* /*
* Register with the event system. * Register with the event system.
*/ */
handle = event_register(server, 0); handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) { if (handle == NULL) {
fatal("could not register with event system"); fatal("could not register with event system");
} }
......
...@@ -22,7 +22,7 @@ void ...@@ -22,7 +22,7 @@ void
usage() usage()
{ {
fprintf(stderr, fprintf(stderr,
"Usage: %s [-s server] [-p port] <event>\n", "Usage: %s [-s server] [-p port] [-k keyfile] <event>\n",
progname); progname);
exit(-1); exit(-1);
} }
...@@ -35,13 +35,14 @@ main(int argc, char **argv) ...@@ -35,13 +35,14 @@ main(int argc, char **argv)
address_tuple_t tuple; address_tuple_t tuple;
char *server = NULL; char *server = NULL;
char *port = NULL; char *port = NULL;
char *keyfile = NULL;
char buf[BUFSIZ], *bp; char buf[BUFSIZ], *bp;
struct timeval now; struct timeval now;
int c; int c;
progname = argv[0]; progname = argv[0];
while ((c = getopt(argc, argv, "s:p:")) != -1) { while ((c = getopt(argc, argv, "s:p:k:")) != -1) {
switch (c) { switch (c) {
case 's': case 's':
server = optarg; server = optarg;
...@@ -49,6 +50,9 @@ main(int argc, char **argv) ...@@ -49,6 +50,9 @@ main(int argc, char **argv)
case 'p': case 'p':
port = optarg; port = optarg;
break; break;
case 'k':
keyfile = optarg;
break;
default: default:
usage(); usage();
} }
...@@ -95,7 +99,7 @@ main(int argc, char **argv) ...@@ -95,7 +99,7 @@ main(int argc, char **argv)
tuple->host = ADDRESSTUPLE_ALL; tuple->host = ADDRESSTUPLE_ALL;
/* Register with the event system: */ /* Register with the event system: */
handle = event_register(server, 0); handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) { if (handle == NULL) {
fatal("could not register with event system"); fatal("could not register with event system");
} }
......
...@@ -12,9 +12,9 @@ SUBDIR = event/lib ...@@ -12,9 +12,9 @@ SUBDIR = event/lib
include $(OBJDIR)/Makeconf include $(OBJDIR)/Makeconf
SYSTEM := $(shell uname -s) SYSTEM := $(shell uname -s)
PROGRAMS = libevent.a libevent_r.a PROGRAMS = libevent.a
ifneq ($(SYSTEM),Linux) ifneq ($(SYSTEM),Linux)
PROGRAMS += event.so PROGRAMS += libevent_r.a event.so
endif endif
all: $(PROGRAMS) all: $(PROGRAMS)
...@@ -22,10 +22,11 @@ all: $(PROGRAMS) ...@@ -22,10 +22,11 @@ all: $(PROGRAMS)
include $(TESTBED_SRCDIR)/GNUmakerules include $(TESTBED_SRCDIR)/GNUmakerules
#CFLAGS += -DDEBUG #CFLAGS += -DDEBUG
CFLAGS += -O -g -static -I. -Wall -I$(TESTBED_SRCDIR)/lib/libtb CFLAGS += -O2 -g -static -I. -Wall -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4mt` SCFLAGS = $(CFLAGS) `elvin-config --cflags vin4c`
TCFLAGS = $(CFLAGS) `elvin-config --cflags vin4mt`
# Special CFLAGS w/o warnings, for SWIG-generated code # Special CFLAGS w/o warnings, for SWIG-generated code
CFLAGS_NOWARN += -O -g -static -I. -I$(TESTBED_SRCDIR)/lib/libtb CFLAGS_NOWARN += -O2 -g -static -I. -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS_NOWARN += `elvin-config --cflags vin4mt` CFLAGS_NOWARN += `elvin-config --cflags vin4mt`
LDFLAGS += -L${OBJDIR}/lib/libtb LDFLAGS += -L${OBJDIR}/lib/libtb
...@@ -45,7 +46,12 @@ $(OBJS): event.h ...@@ -45,7 +46,12 @@ $(OBJS): event.h
$(POBJS): event.h $(POBJS): event.h
event_r.o: event.c event_r.o: event.c
$(CC) $(CFLAGS) -DTHREADED -c -o event_r.o $< $(CC) $(TCFLAGS) -DTHREADED -c -o event_r.o $<
event.o: event.c
$(CC) $(SCFLAGS) -c -o event.o $<
util.o: util.c
$(CC) $(SCFLAGS) -c -o util.o $<
# #
# These three targets are for the perl binding to the event system # These three targets are for the perl binding to the event system
...@@ -59,7 +65,7 @@ event_wrap.o: $(SRCDIR)/event_wrap.c ...@@ -59,7 +65,7 @@ event_wrap.o: $(SRCDIR)/event_wrap.c
event.so: event.o event_wrap.o util.o event.so: event.o event_wrap.o util.o
ld -shared $^ $(OBJDIR)/lib/libtb/libtb.a \ ld -shared $^ $(OBJDIR)/lib/libtb/libtb.a \
`elvin-config --libs vin4c` -o event.so `elvin-config --libs vin4c` -lcrypto -o event.so
LIB_STUFF = event.pm event.so LIB_STUFF = event.pm event.so
...@@ -67,4 +73,4 @@ install: $(addprefix $(INSTALL_LIBDIR)/, $(LIB_STUFF)) ...@@ -67,4 +73,4 @@ install: $(addprefix $(INSTALL_LIBDIR)/, $(LIB_STUFF))
clean: clean:
/bin/rm -f *.o libevent.a *.so *.pm /bin/rm -f *.o libevent.a libevent_r.a *.so *.pm
To isolate the pain of building threaded (and statically linked) event
system programs, we build two versions of the event library, one for
non threaded programs and another (libevent_r.a) for threaded
versions. Threaded clients require a bunch of extra link goo, but at
the moment the only threaded client is the event scheduler. If you
try and use the threaded API without the proper link, the library will
print an error message and quit.
This diff is collapsed.
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
struct event_handle { struct event_handle {
elvin_handle_t server; elvin_handle_t server;
elvin_error_t status; elvin_error_t status;
unsigned char *keydata;
int keylen;
/* API function pointers: */ /* API function pointers: */
elvin_error_t (*init)(void); elvin_error_t (*init)(void);
int (*connect)(elvin_handle_t handle, elvin_error_t error); int (*connect)(elvin_handle_t handle, elvin_error_t error);
...@@ -42,7 +44,12 @@ struct event_handle { ...@@ -42,7 +44,12 @@ struct event_handle {
typedef struct event_handle * event_handle_t; typedef struct event_handle * event_handle_t;
/* Event notification: */ /* Event notification: */
typedef elvin_notification_t event_notification_t; struct event_notification {
elvin_notification_t elvin_notification;
int has_hmac;
};
typedef struct event_notification *event_notification_t;
/* Event subscription: */ /* Event subscription: */
typedef elvin_subscription_t event_subscription_t; typedef elvin_subscription_t event_subscription_t;
...@@ -140,6 +147,10 @@ typedef void (*event_notify_callback_t)(event_handle_t handle, ...@@ -140,6 +147,10 @@ typedef void (*event_notify_callback_t)(event_handle_t handle,
/* event.c */ /* event.c */
event_handle_t event_register(char *name, int threaded); event_handle_t event_register(char *name, int threaded);
event_handle_t event_register_withkeyfile(char *name, int threaded,
char *keyfile);
event_handle_t event_register_withkeydata(char *name, int threaded,
unsigned char *keydata, int len);
int event_unregister(event_handle_t handle); int event_unregister(event_handle_t handle);
int event_poll(event_handle_t handle); int event_poll(event_handle_t handle);
int event_poll_blocking(event_handle_t handle, unsigned int timeout); int event_poll_blocking(event_handle_t handle, unsigned int timeout);
...@@ -188,6 +199,8 @@ int event_notification_remove(event_handle_t handle, ...@@ -188,6 +199,8 @@ int event_notification_remove(event_handle_t handle,
event_subscription_t event_subscribe(event_handle_t handle, event_subscription_t event_subscribe(event_handle_t handle,
event_notify_callback_t callback, event_notify_callback_t callback,
address_tuple_t tuple, void *data); address_tuple_t tuple, void *data);
int event_notification_insert_hmac(event_handle_t handle,
event_notification_t notification);
/* util.c */ /* util.c */
void *xmalloc(int size); void *xmalloc(int size);
......
...@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb ...@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c` CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c` LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux) ifeq ($(SYSTEM),Linux)
LIBS += -ldl LIBS += -ldl
......
...@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb ...@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c` CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c` LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux) ifeq ($(SYSTEM),Linux)
LIBS += -ldl LIBS += -ldl
......
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
#include "tbdefs.h" #include "tbdefs.h"
#include "log.h" #include "log.h"
#include "event.h" #include "event.h"
#define MAXAGENTS 100 #define MAXAGENTS 250
static char debug; static char debug;
static char *agentnames[MAXAGENTS];
static int numagents; static int numagents;
static char *user;
struct proginfo { struct proginfo {
char name[TBDB_FLEN_EVOBJNAME]; char name[TBDB_FLEN_EVOBJNAME];
...@@ -41,16 +41,17 @@ static struct proginfo *proginfos; ...@@ -41,16 +41,17 @@ static struct proginfo *proginfos;
static void callback(event_handle_t handle, static void callback(event_handle_t handle,
event_notification_t notification, void *data); event_notification_t notification, void *data);
static void start_program(char *objname, char *args); static void start_program(struct proginfo *pinfo, char *args);
static void stop_program(char *objname, char *args); static void stop_program(struct proginfo *pinfo, char *args);
static void signal_program(char *objname, char *args); static void signal_program(struct proginfo *pinfo, char *args);
static int parse_configfile(char *filename);
void void
usage(char *progname) usage(char *progname)
{ {
fprintf(stderr, fprintf(stderr,
"Usage: %s [-s server] [-p port] [-l logfile] " "Usage: %s [-s server] [-p port] [-l logfile] [-k keyfile] "
"[-u login] [-i pidfile] -e pid/eid -a agent [-a agent ...]\n", "[-u login] [-i pidfile] -e pid/eid -c configfile\n",
progname); progname);
exit(-1); exit(-1);
} }
...@@ -65,16 +66,18 @@ main(int argc, char **argv) ...@@ -65,16 +66,18 @@ main(int argc, char **argv)
char *server = NULL; char *server = NULL;
char *port = NULL; char *port = NULL;
char *logfile = NULL; char *logfile = NULL;
char *user = NULL;
char *pidfile = NULL; char *pidfile = NULL;
char *pideid = NULL; char *pideid = NULL;
char *keyfile = NULL;
char *configfile = NULL;
char buf[BUFSIZ], agentlist[BUFSIZ]; char buf[BUFSIZ], agentlist[BUFSIZ];
struct proginfo *pinfo;
int c; int c;
progname = argv[0]; progname = argv[0];
bzero(agentlist, sizeof(agentlist)); bzero(agentlist, sizeof(agentlist));
while ((c = getopt(argc, argv, "s:p:l:du:i:e:a:")) != -1) { while ((c = getopt(argc, argv, "s:p:l:du:i:e:c:k:")) != -1) {
switch (c) { switch (c) {
case 's': case 's':
server = optarg; server = optarg;
...@@ -85,6 +88,9 @@ main(int argc, char **argv) ...@@ -85,6 +88,9 @@ main(int argc, char **argv)
case 'l': case 'l':
logfile = optarg; logfile = optarg;
break; break;
case 'c':
configfile = optarg;
break;
case 'd': case 'd':
debug++; debug++;
break; break;
...@@ -97,14 +103,8 @@ main(int argc, char **argv) ...@@ -97,14 +103,8 @@ main(int argc, char **argv)
case 'e': case 'e':
pideid = optarg; pideid = optarg;
break; break;
case 'a': case 'k':
if (numagents >= MAXAGENTS) keyfile = optarg;
fatal("Too many agents listed");
agentnames[numagents] = optarg;
numagents++;
if (strlen(agentlist))
strcat(agentlist, ",");
strcat(agentlist, optarg);
break; break;
default: default:
usage(progname); usage(progname);
...@@ -113,8 +113,10 @@ main(int argc, char **argv) ...@@ -113,8 +113,10 @@ main(int argc, char **argv)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (!pideid || !numagents) if (!pideid || !configfile)
usage(progname); usage(progname);
if (parse_configfile(configfile) != 0)
exit(1);
if (!getuid() && !user) if (!getuid() && !user)
usage(progname); usage(progname);
...@@ -130,6 +132,26 @@ main(int argc, char **argv) ...@@ -130,6 +132,26 @@ main(int argc, char **argv)
loginit(1, "program-agent"); loginit(1, "program-agent");
} }
/*
* Cons up the agentlist for subscription below.
*/
pinfo = proginfos;
while (pinfo) {
info("AGENT: %s, CMD: %s\n", pinfo->name, pinfo->cmdline);
if (numagents >= MAXAGENTS)
fatal("Too many agents listed");
numagents++;
if (strlen(agentlist))
strcat(agentlist, ",");
strcat(agentlist, pinfo->name);
pinfo = pinfo->next;
}
info("agentlist: %s\n", agentlist);
info("user: %s\n", user);
/* /*
* Write out a pidfile if root. * Write out a pidfile if root.
*/ */
...@@ -199,7 +221,7 @@ main(int argc, char **argv) ...@@ -199,7 +221,7 @@ main(int argc, char **argv)
/* /*
* Register with the event system. * Register with the event system.
*/ */
handle = event_register(server, 0); handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) { if (handle == NULL) {
fatal("could not register with event system"); fatal("could not register with event system");
} }
...@@ -235,6 +257,7 @@ callback(event_handle_t handle, event_notification_t notification, void *data) ...@@ -235,6 +257,7 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
char objname[TBDB_FLEN_EVOBJTYPE]; char objname[TBDB_FLEN_EVOBJTYPE];
char event[TBDB_FLEN_EVEVENTTYPE]; char event[TBDB_FLEN_EVEVENTTYPE];
char args[BUFSIZ]; char args[BUFSIZ];
struct proginfo *pinfo;
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
...@@ -257,15 +280,26 @@ callback(event_handle_t handle, event_notification_t notification, void *data) ...@@ -257,15 +280,26 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
info("Event: %lu:%d %s %s %s\n", now.tv_sec, now.tv_usec, info("Event: %lu:%d %s %s %s\n", now.tv_sec, now.tv_usec,
objname, event, args); objname, event, args);
pinfo = proginfos;
while (pinfo) {
if (! strcmp(pinfo->name, objname))
break;
pinfo = pinfo->next;
}
if (!pinfo) {
error("Invalid program agent: %s\n", objname);
return;
}
/* /*
* Dispatch the event. * Dispatch the event.
*/ */
if (strcmp(event, TBDB_EVENTTYPE_START) == 0) if (strcmp(event, TBDB_EVENTTYPE_START) == 0)
start_program(objname, args); start_program(pinfo, args);
else if (strcmp(event, TBDB_EVENTTYPE_STOP) == 0) else if (strcmp(event, TBDB_EVENTTYPE_STOP) == 0)
stop_program(objname, args); stop_program(pinfo, args);
else if (strcmp(event, TBDB_EVENTTYPE_KILL) == 0) else if (strcmp(event, TBDB_EVENTTYPE_KILL) == 0)
signal_program(objname, args); signal_program(pinfo, args);
else { else {
error("Invalid event: %s\n", event); error("Invalid event: %s\n", event);
return; return;
...@@ -284,36 +318,11 @@ callback(event_handle_t handle, event_notification_t notification, void *data) ...@@ -284,36 +318,11 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
* Start a program. * Start a program.
*/ */
static void static void
start_program(char *objname, char *args) start_program(struct proginfo *pinfo, char *args)
{ {
struct proginfo *pinfo;
char buf[BUFSIZ]; char buf[BUFSIZ];
int pid, status; int pid, status;
/*
* Search for an existing proginfo. If we have one, and its
* running, then ignore the start request. The user has to
* be smarter than that. We do not release the proginfo when
* it stops; why bother.
*/
pinfo = proginfos;
while (pinfo) {
if (! strcmp(pinfo->name, objname))
break;
pinfo = pinfo->next;
}
if (!pinfo) {
pinfo = (struct proginfo *) calloc(1, sizeof(*pinfo));
if (!pinfo) {
error("start_program: out of memory\n");
return;
}
strcpy(pinfo->name, objname);
gettimeofday(&pinfo->started, NULL);