home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
acld-1.11.tar.gz
/
acld-1.11.tar
/
acld-1.11
/
broccoli.c
< prev
next >
Wrap
C/C++ Source or Header
|
2011-04-13
|
7KB
|
265 lines
/*
* Copyright (c) 2008, 2009, 2010, 2011
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Id: broccoli.c 720 2011-04-14 00:35:07Z leres $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <syslog.h>
#include <unistd.h>
#include "acld.h"
#include "broccoli.h"
/* Locals */
const char *requestevstr = EV_REQUEST_STR;
const char *replyevstr = EV_REPLY_STR;
/* Forwards */
void brocallback(BroConn *, void *, BroRecord *);
int broextractstr(BroRecord *, const char *, char **);
int broextractuint32(BroRecord *, const char *, uint32 *);
/* Broccoli version of clientinput() */
void
brocallback(BroConn *bc, void *data, BroRecord *rec)
{
int i;
struct client *cl;
char *cmd, *cmd2, *cp, *cp2;
struct req *rp;
cl = data;
rp = cl->treq;
if (rp != NULL) {
lg(LOG_ERR, "brocallback: cl->treq not NULL");
exit(EX_SOFTWARE);
}
rp = new(1, sizeof(*rp), "brocallback: req");
rp->state = RSTATE_PENDING;
/* Arrival timestamp */
getts(&rp->ats);
/* Command string */
if (!broextractstr(rec, EV_CMD, &cmd)) {
clientsenderr(cl, rp, "Missing \"cmd\"");
freereq(rp);
return;
}
/* Cookie */
if (!broextractuint32(rec, EV_COOKIE, &rp->cookie)) {
clientsenderr(cl, rp, "Missing \"cookie\"");
freereq(rp);
return;
}
/* Insert cookie as the 2nd argument as expected by clientfinishreq() */
cmd2 = new(strlen(cmd) + 16, sizeof(*cmd2), "brocallback");
cp = cmd;
cp2 = cmd2;
while (!isspace(*cp) && *cp != '\0')
*cp2++ = *cp++;
cp2 += sprintf(cp2, " %u", rp->cookie);
strcpy(cp2, cp);
rp->an = makeargv(cmd2, &rp->av);
free(cmd);
free(cmd2);
/* Optional comment string */
if (broextractstr(rec, EV_COMMENT, &cp))
rp->comment = cp;
if (debug) {
fprintf(lf, "%s brocallback: client #%d: \"%s",
tsstr(), cl->n, rp->an > 0 ? rp->av[0] : "");
for (i = 1; i < rp->an; ++i)
fprintf(lf, " %s", rp->av[i]);
fprintf(lf, "\"");
if (rp->comment != NULL)
fprintf(lf, " comment \"%s\"", rp->comment);
fprintf(lf, "\n");
}
clientfinishreq(getstate(), cl, rp);
}
int
broextractstr(BroRecord *rec, const char *name, char **strp)
{
int btype;
BroString *bstr;
btype = BRO_TYPE_STRING;
bstr = bro_record_get_named_val(rec, name, &btype);
if (bstr == NULL)
return (0);
*strp = new(1, bstr->str_len + 1, "broextractstr");
strncpy(*strp, (const char *)bstr->str_val, bstr->str_len);
(*strp)[bstr->str_len] = '\0';
bro_string_cleanup(bstr);
return (1);
}
int
broextractuint32(BroRecord *rec, const char *name, uint32 *up)
{
int btype;
uint32 *bup;
btype = BRO_TYPE_COUNT;
bup = bro_record_get_named_val(rec, name, &btype);
if (bup == NULL) {
*up = 0;
return (0);
}
*up = *bup;
return (1);
}
/* Returns true if successful else false */
int
broinit(struct state *sp, struct client *cl)
{
cl->bc = bro_conn_new_socket(cl->c, BRO_CFLAG_NONE);
if (cl->bc == NULL) {
lg(LOG_DEBUG, "client #%d bro_conn_new_socket failed", cl->n);
return(0);
}
/* Set the connection class */
bro_conn_set_class(cl->bc, "acld");
bro_event_registry_add(cl->bc, requestevstr,
(BroEventFunc)brocallback, cl);
if (!bro_conn_connect(cl->bc)) {
lg(LOG_DEBUG, "client #%d bro_conn_connect failed", cl->n);
return(0);
}
return (1);
}
/* Returns true if successful else false (callback side effect) */
int
broinput(struct client *cl)
{
(void)bro_conn_process_input(cl->bc);
return (bro_conn_alive(cl->bc));
}
void
brosend(struct client *cl, struct req *rp)
{
int success;
double time;
BroEvent *ev;
BroRecord *rec;
BroString str;
lg(LOG_DEBUG, "%s: #%d send", prog, cl->n);
rec = bro_record_new();
if (rec == NULL) {
lg(LOG_ERR, "bro_record_new() failed");
return;
}
/* "cmd" */
bro_string_init(&str);
bro_string_set(&str, rp->cmd);
if (!bro_record_add_val(rec, EV_CMD, BRO_TYPE_STRING, NULL, &str)) {
lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_CMD);
bro_record_free(rec);
return;
}
bro_string_cleanup(&str);
/* cookie */
if (!bro_record_add_val(rec, EV_COOKIE, BRO_TYPE_COUNT,
NULL, &rp->cookie)) {
lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_COOKIE);
bro_record_free(rec);
return;
}
/* timestamp */
time = bro_util_timeval_to_double(&rp->cts);
if (!bro_record_add_val(rec, EV_TIME, BRO_TYPE_TIME, NULL, &time)) {
lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_TIME);
bro_record_free(rec);
return;
}
/* success */
success = ((rp->flags & RFLAG_FAILED) == 0);
if (!bro_record_add_val(rec, EV_SUCCESS, BRO_TYPE_BOOL,
NULL, &success)) {
lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_SUCCESS);
bro_record_free(rec);
return;
}
if (rp->payload.len > 0) {
bro_string_init(&str);
bro_string_set(&str, rp->payload.buf);
if (!bro_record_add_val(rec, EV_PAYLOAD, BRO_TYPE_STRING,
NULL, &str)) {
lg(LOG_ERR, "bro_record_add_val(%s) failed",
EV_PAYLOAD);
bro_record_free(rec);
return;
}
bro_string_cleanup(&str);
}
/* Build event */
ev = bro_event_new(replyevstr);
bro_event_add_val(ev, BRO_TYPE_RECORD, NULL, rec);
bro_record_free(rec);
if (!bro_event_send(cl->bc, ev))
lg(LOG_DEBUG, "%s: #%d failed to send", prog, cl->n);
else
lg(LOG_DEBUG, "%s: #%d sent", prog, cl->n);
bro_event_free(ev);
rp->state = RSTATE_DONE;
}