Commit facd1c7e authored by Leigh Stoller's avatar Leigh Stoller

Almost ready for primetime ...

parent 7e572dde
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -15,8 +15,8 @@ include $(OBJDIR)/Makeconf
all: boss-all tipserv-all
boss-all: capserver
tipserv-all: capture capture-tty capquery
client: capture capquery
tipserv-all: capture capture-tty capquery caplogserver caplog caplog.bin
client: capture capquery caplog caplog.bin
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -46,6 +46,12 @@ capture: capture.c capdecls.h
capquery: capquery.c capdecls.h
$(CC) $(CFLAGS) -DPREFIX=\"$(TBROOT)\" -o $@ $< $(LDFLAGS) $(LIBS)
caplog.bin: caplog.c capdecls.h
$(CC) $(CFLAGS) -DPREFIX=\"$(TBROOT)\" -o $@ $< $(LDFLAGS) $(LIBS)
caplogserver: caplogserver.c capdecls.h
$(CC) $(CFLAGS) -DPREFIX=\"$(TBROOT)\" -o $@ $< $(LDFLAGS) $(LIBS)
capture-nossl: capture.c capdecls.h
$(CC) $(CFLAGS) -DUSESOCKETS -DPREFIX=\"$(TBROOT)\" -o capture-nossl $<
......@@ -69,7 +75,10 @@ client-install: client
real-install: all $(INSTALL_SBINDIR)/capserver $(INSTALL_SBINDIR)/capture
tipserv-install: tipserv-all $(INSTALL_SBINDIR)/capture
tipserv-install: tipserv-all $(INSTALL_SBINDIR)/capture \
$(INSTALL_SBINDIR)/caplogserver
clean:
rm -f *.o capture capture-tty capserver capquery core errs Errs
rm -f caplog caplog.bin caplogserver
......@@ -25,15 +25,6 @@ typedef struct {
} secretkey_t;
#define DEFAULTKEYLEN 32
/*
* This is for the cap logger handshake, which passes additional stuff.
*/
typedef struct {
secretkey_t secretkey;
char node_id[128];
int offset;
} logger_t;
/*
* The capserver then returns this structure as part of the handshake.
*/
......@@ -51,6 +42,18 @@ typedef struct {
secretkey_t key;
} whoami_t;
/*
* This is for the cap logger handshake, which passes additional stuff.
*/
typedef struct {
secretkey_t secretkey;
char node_id[128];
int offset;
unsigned int flags;
} logger_t;
#define CAPLOGFLAG_NOFLAGS 0x0
#define CAPLOGFLAG_TAIL 0x1
/*
* Return Status. Define a constant size return to ensure that the
* status is read as an independent block, distinct from any output
......
......@@ -49,6 +49,8 @@ char *Aclname;
char *nodeid;
char *server;
int debug = 0;
int tailmode = 0;
int offset;
int sockfd, portnum = LOGGERPORT;
logger_t logreq;
......@@ -99,7 +101,19 @@ main(int argc, char **argv)
else
Progname = *argv;
while ((op = getopt(argc, argv, "da:p:")) != EOF) {
/*
* The first argument has to be the +/- line option. Leave it
* someone else to generalize.
*/
if (argc > 1) {
if ((argv[1][0] == '+' || argv[1][0] == '-') &&
isdigit(argv[1][1])) {
offset = atoi(argv[1]);
optind++;
}
}
while ((op = getopt(argc, argv, "da:p:f")) != EOF) {
switch (op) {
case 'd':
debug++;
......@@ -107,6 +121,9 @@ main(int argc, char **argv)
case 'a':
Aclname = optarg;
break;
case 'f':
tailmode++;
break;
case 'p':
portnum = atoi(optarg);
break;
......@@ -121,8 +138,10 @@ main(int argc, char **argv)
if (!Aclname) {
(void) snprintf(strbuf, sizeof(strbuf), ACLNAME, ACLPATH, argv[0]);
Aclname = strdup(strbuf);
nodeid = argv[0];
}
if (argc)
nodeid = argv[0];
loadAcl(Aclname);
ConnectToServer();
wfd = fileno(stdout);
......@@ -132,11 +151,11 @@ main(int argc, char **argv)
*/
while (1) {
if ((cc = Read(strbuf, sizeof(strbuf))) <= 0) {
if (cc < 0)
if (cc < 0) {
perror("reading data from server");
else
fprintf(stderr, "Error reading date from server!\n");
exit(-1);
exit(-1);
}
exit(0);
}
if (write(wfd, strbuf, cc) != cc) {
exit(-1);
......@@ -166,6 +185,12 @@ ConnectToServer(void)
exit(-1);
}
/* Additonal options to pass to the server */
if (tailmode)
logreq.flags |= CAPLOGFLAG_TAIL;
if (offset)
logreq.offset = offset;
#ifdef WITHSSL
if (usingSSL)
initSSL();
......@@ -301,7 +326,8 @@ Read(void * data, int size)
void
usage(void)
{
fprintf(stderr, "usage: %s [-d] [-p port] [-a aclfile] machine\n",
fprintf(stderr, "usage: %s "
"[-/+line] [-f] [-p port] [-a aclfile] machine\n",
Progname);
exit(1);
}
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use English;
use Getopt::Std;
use POSIX qw(setsid);
#
# Wrapper for caplog program; grab tipacl from XMLRPC server, and feed it
# to the caplog binary.
#
sub usage()
{
print(STDOUT "Usage: caplog [-/+line] [-f] [-p port] pcXXX\n");
exit(-1);
}
my @opts = ();
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $WRAPPER = "$TB/bin/script_wrapper.py";
my $CAPLOGBIN = "$TB/bin/caplog.bin";
my $aclfile;
#
# Turn off line buffering on output. Very important for this script!
#
$| = 1;
#
# All args pass right through except the last one.
#
usage()
if (@ARGV < 1);
my $node = $ARGV[scalar(@ARGV)-1];
@ARGV = @ARGV[0..(scalar(@ARGV)-2)];
#
# Make a temp file for the acl.
#
$ENV{'TMPDIR'} = "/tmp";
my $tempfile = `mktemp -t tipacl`;
if ($?) {
die("*** $0:\n".
" Could not create a temporary file!\n");
}
if ($tempfile =~ /^([-\w\/\.]*)$/) {
$tempfile = $1;
}
else {
die("*** $0:\n".
" Bad data in tag: $tempfile\n");
}
#
# Ask the XMLRPC server for the tipacl. The current user has to have proper
# permission of course.
#
if (system("$WRAPPER tipacl $node >> $tempfile")) {
unlink($tempfile);
die("*** $0:\n".
" $WRAPPER failed\n");
}
#
# Do not want to leave the acl file around, and do not want to wait for
# the user to quit the program, so fork a child to wait a moment and remove
# the file. We have the child do it so as to avoid messing with the session
# and tty goo.
#
my $syspid = fork();
# Child delays a moment and exits.
if (!$syspid) {
sleep(1);
unlink($tempfile);
exit(0);
}
my @cmdargs = ($CAPLOGBIN, "-a", "$tempfile", @ARGV, "$node");
exec(@cmdargs);
die("*** $0:\n".
" Exec failure: '@cmdargs'\n");
......@@ -52,6 +52,7 @@ void dolog(int level, char *format, ...);
int clientconnect(void);
int Write(void *thing, void *data, int size);
int Read(void *thing, void *data, int size);
int checkAcl(const char * filename, logger_t *logreq);
#ifndef LOG_TESTBED
#define LOG_TESTBED LOG_USER
......@@ -334,14 +335,15 @@ clientconnect(void)
{
struct sockaddr_in client;
struct timeval timeout;
int i, cc, length = sizeof(client);
int i, cc, lines, count, length = sizeof(client);
int clientfd = -1, logfd = -1, pid;
logger_t logreq;
capret_t capret = CAPOK;
char strbuf[BUFSIZ];
char *bp, strbuf[BUFSIZ];
static fd_set sfds;
static int fdcount;
fd_set fds;
FILE *fp;
#ifdef WITHSSL
int ret;
SSL *ssl = NULL;
......@@ -354,8 +356,11 @@ clientconnect(void)
return 1;
}
pid = fork();
if (pid)
if (pid) {
close(clientfd);
return pid;
}
close(sockfd);
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
......@@ -426,6 +431,10 @@ clientconnect(void)
Aclname = strdup(strbuf);
(void) snprintf(strbuf, sizeof(strbuf), RUNNAME, LOGPATH, Machine);
Runname = strdup(strbuf);
if (! checkAcl(Aclname, &logreq)) {
capret = CAPNOPERM;
}
}
else {
capret = CAPERROR;
......@@ -450,6 +459,61 @@ clientconnect(void)
if (capret != CAPOK)
goto done;
/*
* Handle the offset. This is in lines, so its not as simple as
* seeking.
*/
lines = logreq.offset;
fp = fdopen(logfd, "r");
count = 0;
/*
* If a negative line count, have to read to the end first
* to get total line count, and then start over from the
* beginning. I am sure there are clever ways to avoid this
* but why bother.
*/
if (lines < 0) {
while ((bp = fgets(strbuf, sizeof(strbuf), fp)) != NULL) {
int cc = strlen(strbuf);
if (strbuf[cc-1] == '\n' || strbuf[cc-1] == '\r') {
count++;
}
}
lines = count - lines;
if (lines < 0)
lines = 0;
count = 0;
rewind(fp);
}
/*
* Now spit out whatever we have, starting at the offset.
*/
while ((bp = fgets(strbuf, sizeof(strbuf), fp)) != NULL) {
int cc = strlen(strbuf);
if (strbuf[cc-1] == '\r')
strbuf[cc-1] = '\n';
if (strbuf[cc-1] == '\n')
count++;
if (count >= lines) {
while (cc) {
int wc = Write(output, bp, cc);
if (wc < 0) {
warning("%s: write: ", geterr(errno));
goto done;
}
cc -= wc;
bp += wc;
}
}
}
if (!(logreq.flags & CAPLOGFLAG_TAIL))
goto done;
/*
* Now just loop reading from file and sending it back.
* Need to use select since we are waiting for stuff to
......@@ -459,6 +523,8 @@ clientconnect(void)
FD_SET(logfd, &sfds);
FD_SET(clientfd, &sfds);
fdcount = logfd + 1;
if (clientfd > logfd)
fdcount = clientfd + 1;
for (;;) {
fds = sfds;
......@@ -506,11 +572,47 @@ clientconnect(void)
}
}
}
dolog(LOG_NOTICE, "%s disconnected", inet_ntoa(client.sin_addr));
exit(0);
done:
dolog(LOG_NOTICE, "%s disconnected", inet_ntoa(client.sin_addr));
exit(1);
}
/*
* Check aclfile against provided key.
*/
int
checkAcl(const char * filename, logger_t *logreq)
{
FILE *aclFile = fopen(filename, "r");
char b1[256];
char b2[256];
int valid = 0;
if (!aclFile) {
warning("Error opening ACL file '%s' - %s\n",
filename, strerror(errno));
return 0;
}
while (fscanf(aclFile, "%256s %256s\n", b1, b2) != EOF) {
if (strncmp(b1, "key:", 4) == 0 || strncmp(b1, "keydata:", 8) == 0) {
if (strncmp(logreq->secretkey.key, b2,
sizeof(logreq->secretkey.key))) {
warning("Key mismatch in ACL file '%s'\n", filename);
valid = 0;
}
else
valid = 1;
break;
}
}
fclose(aclFile);
return valid;
}
/*
* SIGTERM
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment