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 >
C/C++ Source or Header  |  2011-04-13  |  7KB  |  265 lines

  1. /*
  2.  * Copyright (c) 2008, 2009, 2010, 2011
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static const char rcsid[] =
  24.     "@(#) $Id: broccoli.c 720 2011-04-14 00:35:07Z leres $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #include <sys/time.h>
  29.  
  30. #include <netinet/in.h>
  31.  
  32. #include <arpa/inet.h>
  33.  
  34. #include <ctype.h>
  35. #include <errno.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sysexits.h>
  40. #include <syslog.h>
  41. #include <unistd.h>
  42.  
  43. #include "acld.h"
  44. #include "broccoli.h"
  45.  
  46. /* Locals */
  47. const char *requestevstr = EV_REQUEST_STR;
  48. const char *replyevstr = EV_REPLY_STR;
  49.  
  50. /* Forwards */
  51. void brocallback(BroConn *, void *, BroRecord *);
  52. int broextractstr(BroRecord *, const char *, char **);
  53. int broextractuint32(BroRecord *, const char *, uint32 *);
  54.  
  55. /* Broccoli version of clientinput() */
  56. void
  57. brocallback(BroConn *bc, void *data, BroRecord *rec)
  58. {
  59.     int i;
  60.     struct client *cl;
  61.     char *cmd, *cmd2, *cp, *cp2;
  62.     struct req *rp;
  63.  
  64.     cl = data;
  65.     rp = cl->treq;
  66.     if (rp != NULL) {
  67.         lg(LOG_ERR, "brocallback: cl->treq not NULL");
  68.         exit(EX_SOFTWARE);
  69.     }
  70.  
  71.     rp = new(1, sizeof(*rp), "brocallback: req");
  72.     rp->state = RSTATE_PENDING;
  73.  
  74.     /* Arrival timestamp */
  75.     getts(&rp->ats);
  76.  
  77.     /* Command string */
  78.     if (!broextractstr(rec, EV_CMD, &cmd)) {
  79.         clientsenderr(cl, rp, "Missing \"cmd\"");
  80.         freereq(rp);
  81.         return;
  82.     }
  83.  
  84.     /* Cookie */
  85.     if (!broextractuint32(rec, EV_COOKIE, &rp->cookie)) {
  86.         clientsenderr(cl, rp, "Missing \"cookie\"");
  87.         freereq(rp);
  88.         return;
  89.     }
  90.  
  91.     /* Insert cookie as the 2nd argument as expected by clientfinishreq() */
  92.     cmd2 = new(strlen(cmd) + 16, sizeof(*cmd2), "brocallback");
  93.  
  94.     cp = cmd;
  95.     cp2 = cmd2;
  96.     while (!isspace(*cp) && *cp != '\0')
  97.         *cp2++ = *cp++;
  98.     cp2 += sprintf(cp2, " %u", rp->cookie);
  99.     strcpy(cp2, cp);
  100.  
  101.     rp->an = makeargv(cmd2, &rp->av);
  102.     free(cmd);
  103.     free(cmd2);
  104.  
  105.     /* Optional comment string */
  106.     if (broextractstr(rec, EV_COMMENT, &cp))
  107.         rp->comment = cp;
  108.  
  109.     if (debug) {
  110.         fprintf(lf, "%s brocallback: client #%d: \"%s",
  111.             tsstr(), cl->n, rp->an > 0 ? rp->av[0] : "");
  112.         for (i = 1; i < rp->an; ++i)
  113.             fprintf(lf, " %s", rp->av[i]);
  114.         fprintf(lf, "\"");
  115.         if (rp->comment != NULL)
  116.             fprintf(lf, " comment \"%s\"", rp->comment);
  117.         fprintf(lf, "\n");
  118.     }
  119.  
  120.     clientfinishreq(getstate(), cl, rp);
  121. }
  122.  
  123. int
  124. broextractstr(BroRecord *rec, const char *name, char **strp)
  125. {
  126.     int btype;
  127.     BroString *bstr;
  128.  
  129.     btype = BRO_TYPE_STRING;
  130.     bstr = bro_record_get_named_val(rec, name, &btype);
  131.     if (bstr == NULL)
  132.         return (0);
  133.     *strp = new(1, bstr->str_len + 1, "broextractstr");
  134.     strncpy(*strp, (const char *)bstr->str_val, bstr->str_len);
  135.     (*strp)[bstr->str_len] = '\0';
  136.     bro_string_cleanup(bstr);
  137.     return (1);
  138. }
  139.  
  140. int
  141. broextractuint32(BroRecord *rec, const char *name, uint32 *up)
  142. {
  143.     int btype;
  144.     uint32 *bup;
  145.  
  146.     btype = BRO_TYPE_COUNT;
  147.     bup = bro_record_get_named_val(rec, name, &btype);
  148.     if (bup == NULL) {
  149.         *up = 0;
  150.         return (0);
  151.     }
  152.     *up = *bup;
  153.     return (1);
  154. }
  155.  
  156. /* Returns true if successful else false */
  157. int
  158. broinit(struct state *sp, struct client *cl)
  159. {
  160.     cl->bc = bro_conn_new_socket(cl->c, BRO_CFLAG_NONE);
  161.     if (cl->bc == NULL) {
  162.         lg(LOG_DEBUG, "client #%d bro_conn_new_socket failed", cl->n);
  163.         return(0);
  164.     }
  165.  
  166.     /* Set the connection class */
  167.     bro_conn_set_class(cl->bc, "acld");
  168.  
  169.     bro_event_registry_add(cl->bc, requestevstr,
  170.         (BroEventFunc)brocallback, cl);
  171.     if (!bro_conn_connect(cl->bc)) {
  172.         lg(LOG_DEBUG, "client #%d bro_conn_connect failed", cl->n);
  173.         return(0);
  174.     }
  175.     return (1);
  176. }
  177.  
  178. /* Returns true if successful else false (callback side effect) */
  179. int
  180. broinput(struct client *cl)
  181. {
  182.  
  183.     (void)bro_conn_process_input(cl->bc);
  184.     return (bro_conn_alive(cl->bc));
  185. }
  186.  
  187. void
  188. brosend(struct client *cl, struct req *rp)
  189. {
  190.     int success;
  191.     double time;
  192.     BroEvent *ev;
  193.     BroRecord *rec;
  194.     BroString str;
  195.  
  196.     lg(LOG_DEBUG, "%s: #%d send", prog, cl->n);
  197.  
  198.     rec = bro_record_new();
  199.     if (rec == NULL) {
  200.         lg(LOG_ERR, "bro_record_new() failed");
  201.         return;
  202.     }
  203.  
  204.     /* "cmd" */
  205.     bro_string_init(&str);
  206.     bro_string_set(&str, rp->cmd);
  207.     if (!bro_record_add_val(rec, EV_CMD, BRO_TYPE_STRING, NULL, &str)) {
  208.         lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_CMD);
  209.         bro_record_free(rec);
  210.         return;
  211.     }
  212.     bro_string_cleanup(&str);
  213.  
  214.     /* cookie */
  215.     if (!bro_record_add_val(rec, EV_COOKIE, BRO_TYPE_COUNT,
  216.         NULL, &rp->cookie)) {
  217.         lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_COOKIE);
  218.         bro_record_free(rec);
  219.         return;
  220.     }
  221.  
  222.     /* timestamp */
  223.     time = bro_util_timeval_to_double(&rp->cts);
  224.     if (!bro_record_add_val(rec, EV_TIME, BRO_TYPE_TIME, NULL, &time)) {
  225.         lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_TIME);
  226.         bro_record_free(rec);
  227.         return;
  228.     }
  229.  
  230.     /* success */
  231.     success = ((rp->flags & RFLAG_FAILED) == 0);
  232.     if (!bro_record_add_val(rec, EV_SUCCESS, BRO_TYPE_BOOL,
  233.         NULL, &success)) {
  234.         lg(LOG_ERR, "bro_record_add_val(%s) failed", EV_SUCCESS);
  235.         bro_record_free(rec);
  236.         return;
  237.     }
  238.  
  239.     if (rp->payload.len > 0) {
  240.         bro_string_init(&str);
  241.         bro_string_set(&str, rp->payload.buf);
  242.         if (!bro_record_add_val(rec, EV_PAYLOAD, BRO_TYPE_STRING,
  243.             NULL, &str)) {
  244.             lg(LOG_ERR, "bro_record_add_val(%s) failed",
  245.                 EV_PAYLOAD);
  246.             bro_record_free(rec);
  247.             return;
  248.         }
  249.         bro_string_cleanup(&str);
  250.     }
  251.  
  252.     /* Build event */
  253.     ev = bro_event_new(replyevstr);
  254.  
  255.     bro_event_add_val(ev, BRO_TYPE_RECORD, NULL, rec);
  256.     bro_record_free(rec);
  257.  
  258.     if (!bro_event_send(cl->bc, ev))
  259.         lg(LOG_DEBUG, "%s: #%d failed to send", prog, cl->n);
  260.     else
  261.         lg(LOG_DEBUG, "%s: #%d sent", prog, cl->n);
  262.     bro_event_free(ev);
  263.     rp->state = RSTATE_DONE;
  264. }
  265.