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
SYSTEM := $(shell uname -s)
SUBDIRS = lib tbgen trafgen program-agent
SUBDIRS = lib tbgen trafgen program-agent proxy example
ifeq ($(SYSTEM),FreeBSD)
SUBDIRS += sched example delay-agent nsetrafgen stated proxy
SUBDIRS += sched delay-agent nsetrafgen stated
endif
all: $(SUBDIRS)
......@@ -60,21 +60,18 @@ install:
@$(MAKE) -C stated install
client-install:
ifeq ($(SYSTEM),FreeBSD)
@$(MAKE) -C nsetrafgen client-install
@$(MAKE) -C delay-agent client-install
@$(MAKE) -C program-agent client-install
endif
@$(MAKE) -C tbgen client-install
@$(MAKE) -C program-agent client-install
@$(MAKE) -C trafgen client-install
@$(MAKE) -C proxy client-install
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
subdir-clean:
......
#
# 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.
#
......@@ -22,7 +22,7 @@ CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static
LDFLAGS += -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb
LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c`
OBJS = main.o callback.o
......
......@@ -75,6 +75,7 @@ int main(int argc, char **argv)
char *map_file = NULL;
char *log_file = "/tmp/agentlog";
char *pid_file = NULL;
char *keyfile = NULL;
FILE *mp = NULL;
//char *log = NULL;
char buf[BUFSIZ];
......@@ -86,7 +87,7 @@ int main(int argc, char **argv)
opterr = 0;
/* 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) {
case 'd':
debug++;
......@@ -109,6 +110,9 @@ int main(int argc, char **argv)
case 'E':
myexp = optarg;
break;
case 'k':
keyfile = optarg;
break;
case '?':
default:
usage(argv[0]);
......@@ -274,7 +278,7 @@ int main(int argc, char **argv)
/* register with the event system*/
handle = event_register(server, 0);
handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) {
error("could not register with event system\n");
return 1;
......@@ -319,7 +323,8 @@ void usage(char *progname)
info("entering function usage\n");
#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);
exit(-1);
}
......
......@@ -3,6 +3,7 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = event/example
SYSTEM := $(shell uname -s)
PROGRAMS = tbrecv tbsend eventdebug.pl
include $(OBJDIR)/Makeconf
......@@ -17,8 +18,11 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb
LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux)
LIBS += -ldl
endif
tbrecv: tbrecv.o
$(CC) $(LDFLAGS) -o $@ tbrecv.o $(LIBS)
......
......@@ -25,7 +25,7 @@ void
usage()
{
fprintf(stderr,
"Usage: %s [-s server] [-p port]\n", progname);
"Usage: %s [-s server] [-p port] [-k keyfile]\n", progname);
exit(-1);
}
......@@ -35,6 +35,7 @@ main(int argc, char **argv)
event_handle_t handle;
address_tuple_t tuple;
char *server = NULL;
char *keyfile = NULL;
char *port = NULL;
char *ipaddr = NULL;
char buf[BUFSIZ], ipbuf[BUFSIZ];
......@@ -42,7 +43,7 @@ main(int argc, char **argv)
progname = argv[0];
while ((c = getopt(argc, argv, "s:p:i:")) != -1) {
while ((c = getopt(argc, argv, "s:p:k:")) != -1) {
switch (c) {
case 's':
server = optarg;
......@@ -50,6 +51,9 @@ main(int argc, char **argv)
case 'p':
port = optarg;
break;
case 'k':
keyfile = optarg;
break;
default:
usage();
}
......@@ -114,7 +118,7 @@ main(int argc, char **argv)
/*
* Register with the event system.
*/
handle = event_register(server, 0);
handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) {
fatal("could not register with event system");
}
......
......@@ -22,7 +22,7 @@ void
usage()
{
fprintf(stderr,
"Usage: %s [-s server] [-p port] <event>\n",
"Usage: %s [-s server] [-p port] [-k keyfile] <event>\n",
progname);
exit(-1);
}
......@@ -35,13 +35,14 @@ main(int argc, char **argv)
address_tuple_t tuple;
char *server = NULL;
char *port = NULL;
char *keyfile = NULL;
char buf[BUFSIZ], *bp;
struct timeval now;
int c;
progname = argv[0];
while ((c = getopt(argc, argv, "s:p:")) != -1) {
while ((c = getopt(argc, argv, "s:p:k:")) != -1) {
switch (c) {
case 's':
server = optarg;
......@@ -49,6 +50,9 @@ main(int argc, char **argv)
case 'p':
port = optarg;
break;
case 'k':
keyfile = optarg;
break;
default:
usage();
}
......@@ -95,7 +99,7 @@ main(int argc, char **argv)
tuple->host = ADDRESSTUPLE_ALL;
/* Register with the event system: */
handle = event_register(server, 0);
handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) {
fatal("could not register with event system");
}
......
......@@ -12,9 +12,9 @@ SUBDIR = event/lib
include $(OBJDIR)/Makeconf
SYSTEM := $(shell uname -s)
PROGRAMS = libevent.a libevent_r.a
PROGRAMS = libevent.a
ifneq ($(SYSTEM),Linux)
PROGRAMS += event.so
PROGRAMS += libevent_r.a event.so
endif
all: $(PROGRAMS)
......@@ -22,10 +22,11 @@ all: $(PROGRAMS)
include $(TESTBED_SRCDIR)/GNUmakerules
#CFLAGS += -DDEBUG
CFLAGS += -O -g -static -I. -Wall -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4mt`
CFLAGS += -O2 -g -static -I. -Wall -I$(TESTBED_SRCDIR)/lib/libtb
SCFLAGS = $(CFLAGS) `elvin-config --cflags vin4c`
TCFLAGS = $(CFLAGS) `elvin-config --cflags vin4mt`
# 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`
LDFLAGS += -L${OBJDIR}/lib/libtb
......@@ -45,7 +46,12 @@ $(OBJS): event.h
$(POBJS): event.h
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
......@@ -59,7 +65,7 @@ event_wrap.o: $(SRCDIR)/event_wrap.c
event.so: event.o event_wrap.o util.o
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
......@@ -67,4 +73,4 @@ install: $(addprefix $(INSTALL_LIBDIR)/, $(LIB_STUFF))
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 @@
struct event_handle {
elvin_handle_t server;
elvin_error_t status;
unsigned char *keydata;
int keylen;
/* API function pointers: */
elvin_error_t (*init)(void);
int (*connect)(elvin_handle_t handle, elvin_error_t error);
......@@ -42,7 +44,12 @@ struct event_handle {
typedef struct event_handle * event_handle_t;
/* 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: */
typedef elvin_subscription_t event_subscription_t;
......@@ -140,6 +147,10 @@ typedef void (*event_notify_callback_t)(event_handle_t handle,
/* event.c */
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_poll(event_handle_t handle);
int event_poll_blocking(event_handle_t handle, unsigned int timeout);
......@@ -188,6 +199,8 @@ int event_notification_remove(event_handle_t handle,
event_subscription_t event_subscribe(event_handle_t handle,
event_notify_callback_t callback,
address_tuple_t tuple, void *data);
int event_notification_insert_hmac(event_handle_t handle,
event_notification_t notification);
/* util.c */
void *xmalloc(int size);
......
......@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb
LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux)
LIBS += -ldl
......
......@@ -24,7 +24,7 @@ CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c`
LDFLAGS += -static -L../lib -L${OBJDIR}/lib/libtb
LIBS += -levent -ltb
LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux)
LIBS += -ldl
......
......@@ -24,11 +24,11 @@
#include "tbdefs.h"
#include "log.h"
#include "event.h"
#define MAXAGENTS 100
#define MAXAGENTS 250
static char debug;
static char *agentnames[MAXAGENTS];
static int numagents;
static char *user;
struct proginfo {
char name[TBDB_FLEN_EVOBJNAME];
......@@ -41,16 +41,17 @@ static struct proginfo *proginfos;
static void callback(event_handle_t handle,
event_notification_t notification, void *data);
static void start_program(char *objname, char *args);
static void stop_program(char *objname, char *args);
static void signal_program(char *objname, char *args);
static void start_program(struct proginfo *pinfo, char *args);
static void stop_program(struct proginfo *pinfo, char *args);
static void signal_program(struct proginfo *pinfo, char *args);
static int parse_configfile(char *filename);
void
usage(char *progname)
{
fprintf(stderr,
"Usage: %s [-s server] [-p port] [-l logfile] "
"[-u login] [-i pidfile] -e pid/eid -a agent [-a agent ...]\n",
"Usage: %s [-s server] [-p port] [-l logfile] [-k keyfile] "
"[-u login] [-i pidfile] -e pid/eid -c configfile\n",
progname);
exit(-1);
}
......@@ -65,16 +66,18 @@ main(int argc, char **argv)
char *server = NULL;
char *port = NULL;
char *logfile = NULL;
char *user = NULL;
char *pidfile = NULL;
char *pideid = NULL;
char *keyfile = NULL;
char *configfile = NULL;
char buf[BUFSIZ], agentlist[BUFSIZ];
struct proginfo *pinfo;
int c;
progname = argv[0];
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) {
case 's':
server = optarg;
......@@ -85,6 +88,9 @@ main(int argc, char **argv)
case 'l':
logfile = optarg;
break;
case 'c':
configfile = optarg;
break;
case 'd':
debug++;
break;
......@@ -97,14 +103,8 @@ main(int argc, char **argv)
case 'e':
pideid = optarg;
break;
case 'a':
if (numagents >= MAXAGENTS)
fatal("Too many agents listed");
agentnames[numagents] = optarg;
numagents++;
if (strlen(agentlist))
strcat(agentlist, ",");
strcat(agentlist, optarg);
case 'k':
keyfile = optarg;
break;
default:
usage(progname);
......@@ -113,8 +113,10 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (!pideid || !numagents)
if (!pideid || !configfile)
usage(progname);
if (parse_configfile(configfile) != 0)
exit(1);
if (!getuid() && !user)
usage(progname);
......@@ -130,6 +132,26 @@ main(int argc, char **argv)
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.
*/
......@@ -199,7 +221,7 @@ main(int argc, char **argv)
/*
* Register with the event system.
*/
handle = event_register(server, 0);
handle = event_register_withkeyfile(server, 0, keyfile);
if (handle == NULL) {
fatal("could not register with event system");
}
......@@ -235,6 +257,7 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
char objname[TBDB_FLEN_EVOBJTYPE];
char event[TBDB_FLEN_EVEVENTTYPE];
char args[BUFSIZ];
struct proginfo *pinfo;
struct timeval now;
gettimeofday(&now, NULL);
......@@ -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,
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.
*/
if (strcmp(event, TBDB_EVENTTYPE_START) == 0)
start_program(objname, args);
start_program(pinfo, args);
else if (strcmp(event, TBDB_EVENTTYPE_STOP) == 0)
stop_program(objname, args);
stop_program(pinfo, args);
else if (strcmp(event, TBDB_EVENTTYPE_KILL) == 0)
signal_program(objname, args);
signal_program(pinfo, args);
else {
error("Invalid event: %s\n", event);
return;
......@@ -284,36 +318,11 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
* Start a program.
*/
static void
start_program(char *objname, char *args)
start_program(struct proginfo *pinfo, char *args)
{
struct proginfo *pinfo;
char buf[BUFSIZ];
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);
pinfo->next = proginfos;
proginfos = pinfo;
}
if (pinfo->pid) {
/*
* We reap children here, rather than using SIGCHLD.
......@@ -322,29 +331,18 @@ start_program(char *objname, char *args)
if ((pid = waitpid(pinfo->pid, &status, WNOHANG) <= 0)) {
if (pid < 0)
error("start_program: %s waitpid: %s\n",
objname, strerror(errno));
pinfo->name, strerror(errno));
warning("start_program: %s is still running: %d\n",
objname, pinfo->pid);
pinfo->name, pinfo->pid);
return;
}
info("start_program: "
"%s (pid:%d) has exited with status: 0x%x\n",
objname, pinfo->pid, status);
pinfo->name, pinfo->pid, status);
pinfo->pid = 0;
}
/*
* The args string holds the command line to execute. We allow
* this to be reset in dynamic events, which may seem a little
* odd, but its easy to support, so why not.
*/
if (strncmp("COMMAND=", args, strlen("COMMAND="))) {
error("start_program: malformed arguments: %s\n", args);
return;
}
pinfo->cmdline = strdup(&args[strlen("COMMAND=")]);
/*
* Fork a child to run the command in and return to get
* more events.
......@@ -354,7 +352,7 @@ start_program(char *objname, char *args)
return;
}
if (pid) {
info("start_program: %s (pid:%d) starting\n", objname, pid);
info("start_program: %s (pid:%d) starting\n", pinfo->name,pid);
pinfo->pid = pid;
return;
}
......@@ -391,22 +389,10 @@ start_program(char *objname, char *args)
* Stop a program.
*/
static void
stop_program(char *objname, char *args)
stop_program(struct proginfo *pinfo, char *args)
{
struct proginfo *pinfo;
/*
* Search for an existing proginfo. If there is none, or if
* the pid is zero (stopped), then ignore request.
*/
pinfo = proginfos;
while (pinfo) {
if (! strcmp(pinfo->name, objname))
break;
pinfo = pinfo->next;
}
if (!pinfo || !pinfo->pid) {
warning("stop_program: %s is not running!\n", objname);
if (!pinfo->pid) {
warning("stop_program: %s is not running!\n", pinfo->name);
return;
}
if (killpg(pinfo->pid, SIGTERM) < 0 &&
......@@ -424,24 +410,13 @@ extern const char * const sys_siglist[];
#endif
static void
signal_program(char *objname, char *args)
signal_program(struct proginfo *pinfo, char *args)
{
char buf[BUFSIZ], *bp;
struct proginfo *pinfo;
int i;
/*
* Search for an existing proginfo. If there is none, or if
* the pid is zero (stopped), then ignore request.
*/
pinfo = proginfos;
while (pinfo) {
if (! strcmp(pinfo->name, objname))
break;
pinfo = pinfo->next;
}
if (!pinfo || !pinfo->pid) {
warning("signal_program: %s is not running!\n", objname);
if (!pinfo->pid) {
warning("signal_program: %s is not running!\n", pinfo->name);
return;
}
......@@ -471,3 +446,77 @@ signal_program(char *objname, char *args)
strerror(errno));
}
}
static int
parse_configfile(char *filename)
{
FILE *fp;
char buf[BUFSIZ], *bp, *cp;
struct proginfo *pinfo;
if ((fp = fopen(filename, "r")) == NULL) {
errorc("could not open configfile %s", filename);
return -1;
}
while (fgets(buf, sizeof(buf), fp)) {
int cc = strlen(buf);
if (buf[cc-1] == '\n')
buf[cc-1] = (char) NULL;
if (!strncmp(buf, "UID=", 4)) {
if (user) {
info("User already set; skipping config\n");
continue;
}
user = strdup(&buf[4]);
if (!user) {
error("parse_configfile: out of memory\n");
goto bad;
}
continue;
}
if (!strncmp(buf, "AGENT=", 6)) {
pinfo = (struct proginfo *) calloc(1, sizeof(*pinfo));
if (!pinfo) {
error("parse_configfile: out of memory\n");
goto bad;
}
bp = cp = buf + 6;
while (*cp && !isspace(*bp))
bp++;
*bp++ = (char) NULL;
strncpy(pinfo->name, cp, sizeof(pinfo->name));
if (strncmp(bp, "COMMAND='", 9)) {
error("parse_configfile: malformed: %s\n", bp);
goto bad;
}
bp += 9;
cc = strlen(bp);
if (bp[cc-1] != '\'') {
error("parse_configfile: malformed: %s\n", bp);
goto bad;
}
bp[cc-1] = (char) NULL;
pinfo->cmdline = strdup(bp);
if (!pinfo->cmdline) {
error("parse_configfile: out of memory\n");
goto bad;
}
pinfo->next = proginfos;
proginfos = pinfo;
continue;
}
error("parse_configfile: malformed: %s\n", buf);
goto bad;
}
fclose(fp);
return 0;
bad:
fclose(fp);
return -1;
}
......@@ -30,28 +30,49 @@ $(LIBEVENTDIR)/%.a:
@$(MAKE) -C $(LIBEVENTDIR) $(@F)
CFLAGS += -DDEBUG
CFLAGS += -O -g -static -Wall
CFLAGS += -O2 -g -static -Wall
CFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += `elvin-config --cflags vin4c`
PFLAGS = -pthread
PFLAGS += -DDEBUG
PFLAGS += -O2 -g -Wall
PFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
PFLAGS += `elvin-config --cflags vin4mt`
LDFLAGS += -L$(OBJDIR)/lib -L$(OBJDIR)/lib/libtb -L../lib
LIBS += -levent
LIBS += -levent -ltb -lcrypto
LIBS += `elvin-config --libs vin4c`
ifeq ($(SYSTEM),Linux)
LIBS += -ldl
endif
PLDFLAGS = -pthread -static
PLDFLAGS += -L../lib -L${OBJDIR}/lib/libtb
PLIBS = -levent_r -ltb
PLIBS += -L/usr/local/lib -lvin4mt -lvin4c -lvin4 -lcrypto -lm
evproxy: evproxy.o $(LIBTBDIR)/log.o
# Link against some of the object files from libtb, instead of the
# whole library, since the latter cannot be built on ops
$(CC) $(LDFLAGS) -static -o $@ evproxy.o $(LIBTBDIR)/log.o $(LIBS)
$(CC) $(LDFLAGS) -static -o $@ evproxy.o $(LIBS)
evproxyclient: proxyclient.o $(LIBTBDIR)/log.o
$(CC) $(LDFLAGS) -static -o $@ proxyclient.o $(LIBS)
evproxyserver: proxyserver.o $(LIBTBDIR)/log.o
$(CC) $(PLDFLAGS) -static -o $@ proxyserver.o $(PLIBS)