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 / aclc.c < prev    next >
C/C++ Source or Header  |  2011-09-23  |  15KB  |  735 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 copyright[] =
  24.     "@(#) Copyright (c) 2008, 2009, 2010, 2011\n\
  25. The Regents of the University of California.  All rights reserved.\n";
  26. static const char rcsid[] =
  27.     "@(#) $Id: aclc.c 763 2011-09-23 19:19:13Z leres $ (LBL)";
  28. #endif
  29.  
  30. /*
  31.  * aclc - broccoli acld client
  32.  */
  33.  
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <sys/time.h>
  37.  
  38. #include <arpa/inet.h>
  39.  
  40. #include <broccoli.h>
  41. #include <ctype.h>
  42. #include <errno.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <sysexits.h>
  46.  
  47. #include "broccoli.h"
  48. #include "gnuc.h"
  49. #include "version.h"
  50.  
  51. #define DEFAULT_SSL_PORT    "47776"
  52. #define DEFAULT_CLEAR_PORT    "47777"
  53.  
  54. /* Globals */
  55. int debug;
  56. int verbose;
  57. const char *prog;
  58. const char *addr = "127.0.0.1";
  59. const char *comment;
  60. struct sockaddr_in brosin;
  61. int s = -1;
  62. BroConn *bc;
  63. const char *port;
  64. const char *requestevstr = EV_REQUEST_STR;
  65. const char *replyevstr = EV_REPLY_STR;
  66. int usessl;
  67. uint32 cookie = 1;
  68. #define    MAXOUTSTANDING    5
  69. uint32 outstanding;
  70.  
  71. const char *file = NULL;
  72. static int timeout = 10;            /* select timeout */
  73. int success;
  74.  
  75. /* Externs */
  76. extern int optind;
  77. extern int opterr;
  78. extern char *optarg;
  79.  
  80. /* Forwards */
  81. BroEvent *acldevent(const char *, u_int32_t);
  82. void callback(BroConn *, void *, BroRecord *);
  83. int command(int, BroConn *, int, char **);
  84. int dofile(int, BroConn *, const char *, const char *);
  85. void connect2acld(void);
  86. int loop(int, BroConn *);
  87. int main(int, char **);
  88. __dead void usage(void) __attribute__((noreturn));
  89. int getresult(void);
  90.  
  91. /* XXX */
  92. int extractbool(BroRecord *, const char *, int *);
  93. char *extractstr(BroRecord *, const char *);
  94. int extracttime(BroRecord *, const char *, double *);
  95. int extractuint32(BroRecord *, const char *, uint32 *);
  96. void *new(size_t, size_t, const char *);
  97.  
  98. int
  99. main(int argc, char **argv)
  100. {
  101.     int op, ret;
  102.     long v;
  103.     char *cp, *ep;
  104.     struct timeval start, end, delta;
  105.  
  106.     if (argv[0] == NULL)
  107.         prog = "acld";
  108.     else if ((cp = strrchr(argv[0], '/')) != NULL)
  109.         prog = cp + 1;
  110.     else
  111.         prog = argv[0];
  112.  
  113.     opterr = 0;
  114.     while ((op = getopt(argc, argv, "dDva:c:C:e:f:P:")) != EOF)
  115.         switch (op) {
  116.  
  117.         case 'a':
  118.             addr = optarg;
  119.             break;
  120.  
  121.         case 'd':
  122.             ++debug;
  123.             break;
  124.  
  125.         case 'c':
  126.             comment = optarg;
  127.             break;
  128.  
  129.         case 'C':
  130.             /* Undocumented */
  131.             v = strtol(optarg, &ep, 10);
  132.             if (*ep != '\0' || v < 0)
  133.                 usage();
  134.             cookie = v;
  135.             break;
  136.  
  137.         case 'D':
  138.             ++bro_debug_messages;
  139.             break;
  140.  
  141.         case 'e':
  142.             requestevstr = optarg;
  143.             break;
  144.  
  145.         case 'E':
  146.             replyevstr = optarg;
  147.             break;
  148.  
  149.         case 'f':
  150.             file = optarg;
  151.             break;
  152.  
  153.         case 'P':
  154.             port = optarg;
  155.             break;
  156.  
  157.         case 'v':
  158.             ++verbose;
  159.             break;
  160.  
  161.         default:
  162.             usage();
  163.             /* NOTREACHED */
  164.         }
  165.  
  166.     memset(&brosin, 0, sizeof(brosin));
  167. #ifdef HAVE_SOCKADDR_SA_LEN
  168.     brosin.sin_len = sizeof(brosin);
  169. #endif
  170.     brosin.sin_family = AF_INET;
  171.  
  172.     /* Check this before we connect */
  173.     if (file != NULL && argc != optind + 1)
  174.         usage();
  175.  
  176. #ifdef HAVE_BRO_INIT
  177.     if (!bro_init(NULL)) {
  178.         fprintf(stderr, "%s: Failed to initialize broccoli; exiting\n",
  179.             prog);
  180.         exit(EX_CONFIG);
  181.     }
  182. #endif
  183.     usessl = 0;
  184.     if (!bro_conf_get_int("/broccoli/use_ssl", &usessl))
  185.         usessl = 0;
  186.  
  187.     if (port == NULL)
  188.         port = (usessl ? DEFAULT_SSL_PORT : DEFAULT_CLEAR_PORT);
  189.  
  190.     v = strtol(port, &ep, 10);
  191.     if (*ep != '\0' || v < 1 || v > 0xffff) {
  192.         fprintf(stderr, "%s: bad port value (%s)\n", prog, port);
  193.         exit(EX_USAGE);
  194.     }
  195.     brosin.sin_port = htons(v);
  196.  
  197.     /* "*" -> 0.0.0.0 else decode string address */
  198.     if (strcmp(addr, "*") != 0 &&
  199.         inet_pton(brosin.sin_family, addr, &brosin.sin_addr) < 0) {
  200.         fprintf(stderr, "%s: bad address value (%s): %s\n",
  201.             prog, addr, strerror(errno));
  202.         exit(EX_USAGE);
  203.     }
  204.  
  205.     gettimeofday(&start, NULL);
  206.     connect2acld();
  207.  
  208.     ret = 0;
  209.     if (file != NULL)
  210.         ret = dofile(s, bc, file, argv[optind]);
  211.     else if (argc != optind)
  212.         ret = command(s, bc, argc - optind, argv + optind);
  213.     else
  214.         ret = loop(s, bc);
  215.     bro_conn_delete(bc);
  216.  
  217.     gettimeofday(&end, NULL);
  218.     timersub(&end, &start, &delta);
  219.     printf("%s: (took %ld.%06ld seconds)\n",
  220.         prog, (long)delta.tv_sec, (long)delta.tv_usec);
  221.  
  222.     exit(ret);
  223. }
  224.  
  225. BroEvent *
  226. acldevent(const char *buf, uint32 reqcookie)
  227. {
  228.     BroEvent *ev;
  229.     BroRecord *rec;
  230.     BroString str;
  231.  
  232.     rec = bro_record_new();
  233.     if (rec == NULL) {
  234.         fprintf(stderr, "%s: bro_record_new() failed\n", prog);
  235.         return (NULL);
  236.     }
  237.  
  238.     /* "cmd" */
  239.     bro_string_init(&str);
  240.     bro_string_set(&str, buf);
  241.     if (!bro_record_add_val(rec, EV_CMD, BRO_TYPE_STRING, NULL, &str)) {
  242.         fprintf(stderr, "%s: bro_record_add_val(%s) failed\n",
  243.             prog, EV_CMD);
  244.         bro_record_free(rec);
  245.         return (NULL);
  246.     }
  247.     bro_string_cleanup(&str);
  248.  
  249.     if (!bro_record_add_val(rec, EV_COOKIE, BRO_TYPE_COUNT,
  250.         NULL, &reqcookie)) {
  251.         fprintf(stderr, "%s: bro_record_add_val(%s) failed\n",
  252.             prog, EV_CMD);
  253.         bro_record_free(rec);
  254.         return (NULL);
  255.     }
  256.  
  257.     /* Optional comment string */
  258.     if (comment != NULL) {
  259.         bro_string_init(&str);
  260.         bro_string_set(&str, comment);
  261.         if (!bro_record_add_val(rec, EV_COMMENT, BRO_TYPE_STRING,
  262.             NULL, &str)) {
  263.             fprintf(stderr, "%s: bro_record_add_val(%s) failed\n",
  264.                 prog, EV_COMMENT);
  265.             bro_record_free(rec);
  266.             return (NULL);
  267.         }
  268.         bro_string_cleanup(&str);
  269.     }
  270.  
  271.     ev = bro_event_new(requestevstr);
  272.  
  273.     bro_event_add_val(ev, BRO_TYPE_RECORD, NULL, rec);
  274.     bro_record_free(rec);
  275.     return (ev);
  276. }
  277.  
  278. void
  279. callback(BroConn *bc, void *data, BroRecord *rec)
  280. {
  281.     uint32 repcookie;
  282.     double time;
  283.     char *cmd;
  284.     char *payload;
  285.  
  286.     cmd = extractstr(rec, EV_CMD);
  287.     if (cmd == NULL) {
  288.         fprintf(stderr, "%s: missing %s\n", prog, EV_CMD);
  289.         return;
  290.     }
  291.     if (!extractuint32(rec, EV_COOKIE, &repcookie)) {
  292.         fprintf(stderr, "%s: missing %s\n", prog, EV_COOKIE);
  293.         free(cmd);
  294.         return;
  295.     }
  296.     if (!extractbool(rec, EV_SUCCESS, &success)) {
  297.         fprintf(stderr, "%s: missing %s\n", prog, EV_SUCCESS);
  298.         free(cmd);
  299.         return;
  300.     }
  301.     if (!extracttime(rec, EV_TIME, &time)) {
  302.         fprintf(stderr, "%s: missing %s\n", prog, EV_TIME);
  303.         free(cmd);
  304.         return;
  305.     }
  306.     if (debug)
  307.         fprintf(stderr, "%s: %.6f recv:%d \"%s\"\n",
  308.             prog, time, cookie, cmd);
  309.  
  310.     /* Payload goes to stdout */
  311.     payload = extractstr(rec, EV_PAYLOAD);
  312.     if (payload != NULL) {
  313.         fputs(payload, stdout);
  314.         fflush(stdout);
  315.         free(payload);
  316.     }
  317.  
  318.     /* Advance cookie */
  319.     if (repcookie != cookie) {
  320.         fprintf(stderr, "%s: %s cookie mismatch (%d != %d)\n",
  321.             prog, cmd, repcookie, cookie);
  322.         exit(1);
  323.     }
  324.     ++cookie;
  325.     --outstanding;
  326.  
  327.     free(cmd);
  328. }
  329.  
  330. /* Handle a single command */
  331. int
  332. command(int s, BroConn *bc, int an, char **av)
  333. {
  334.     int ret;
  335.     size_t size, len;
  336.     char *cp;
  337.     const char *cmd;
  338.     BroEvent *ev;
  339.     char buf[1024];
  340.  
  341.     size = sizeof(buf);
  342.     cp = buf;
  343.     cmd = av[0];
  344.     for (; an > 0; --an, ++av) {
  345.         len = strlen(*av);
  346.         /* room for blank and eos */
  347.         if (size < len + 2) {
  348.             fprintf(stderr, "%s: command: too big!\n", prog);
  349.             exit(1);
  350.         }
  351.         if (cp != buf) {
  352.             *cp++ = ' ';
  353.             --size;
  354.         }
  355.         strcpy(cp, *av);
  356.         cp += len;
  357.         size -= len;
  358.     }
  359.     ev = acldevent(buf, cookie);
  360.  
  361.     if (!bro_event_send(bc, ev)) {
  362.         fprintf(stderr, "%s: failed to send\n",
  363.             prog);
  364.         return (1);
  365.     }
  366.     bro_event_free(ev);
  367.  
  368.     ret = getresult();
  369.     if (ret)
  370.         fprintf(stderr, "%s: %s FAILED\n", prog, cmd);
  371.  
  372.     return (ret);
  373. }
  374.  
  375. void
  376. connect2acld(void)
  377. {
  378.     int n, secs;
  379.  
  380.     for (n = 0;; ++n) {
  381.         /* We need a new socket for each connect() failure */
  382.         s = socket(PF_INET, SOCK_STREAM, 0);
  383.         if (s < 0) {
  384.             fprintf(stderr, "%s: connect2acld: socket: %s\n",
  385.                 prog, strerror(errno));
  386.             exit(EX_OSERR);
  387.         }
  388.         if (connect(s,
  389.             (struct sockaddr *)&brosin, sizeof(brosin)) >= 0)
  390.             break;
  391.         fprintf(stderr, "%s: connect2acld: connect(%s.%d): %s\n",
  392.             prog, inet_ntoa(brosin.sin_addr), ntohs(brosin.sin_port),
  393.             strerror(errno));
  394.         close(s);
  395.         if (n > 60 * 10)
  396.             secs = 60 * 10;
  397.         else if (n > 60)
  398.             secs = 60;
  399.         else if (n > 10)
  400.             secs = 10;
  401.         else
  402.             secs = 1;
  403.         sleep(secs);
  404.     }
  405.  
  406.     bc = bro_conn_new_socket(s, BRO_CFLAG_RECONNECT);
  407.     if (bc == NULL) {
  408.         fprintf(stderr,
  409.             "%s: connect2acld: bro_conn_new_socket to %s:%d failed\n",
  410.             prog, inet_ntoa(brosin.sin_addr), ntohs(brosin.sin_port));
  411.         exit(EX_UNAVAILABLE);
  412.     }
  413.  
  414.     /* Set the connection class */
  415.     bro_conn_set_class(bc, "acld");
  416.  
  417.     /* Register handler */
  418.     bro_event_registry_add(bc, replyevstr, (BroEventFunc)callback, NULL);
  419.  
  420.     while (!bro_conn_connect(bc)) {
  421.         fprintf(stderr,
  422.             "%s: connect2acld: Failed to connect; retrying...\n", prog);
  423.         sleep(1);
  424.     }
  425.  
  426.     if (verbose)
  427.         fprintf(stderr, "%s: connected to %s:%s (%s)\n",
  428.             prog, addr, port, usessl ? "SSL" : "clear");
  429. }
  430.  
  431. int
  432. dofile(int s, BroConn *bc, const char *file, const char *cmd)
  433. {
  434.     int ret;
  435.     uint32 lastcookie;
  436.     char *cp;
  437.     BroEvent *ev;
  438.     char buf[1024];
  439.     char req[1024];
  440.     FILE *f;
  441.  
  442.     f = fopen(file, "r");
  443.     if (f == NULL) {
  444.         fprintf(stderr, "%s: fopen: %s\n",
  445.             prog, strerror(errno));
  446.         exit(1);
  447.     }
  448.  
  449.     lastcookie = cookie;
  450.     ret = 0;
  451.     while (fgets(buf, sizeof(buf), f) != NULL) {
  452.         cp = buf + strlen(buf) - 1;
  453.         if (cp >= buf && *cp == '\n')
  454.             *cp = '\0';
  455.         /* Skip empty lines */
  456.         for (cp = buf; *cp != '\0'; ++cp)
  457.             if (!isspace(*cp))
  458.                 break;
  459.         if (*cp == '\0')
  460.             continue;
  461.  
  462.         (void)snprintf(req, sizeof(req), "%s %s", cmd, buf);
  463.         ev = acldevent(req, lastcookie++);
  464.         ++outstanding;
  465.  
  466.         if (!bro_event_send(bc, ev)) {
  467.             fprintf(stderr, "%s: failed to send\n", prog);
  468.             ret = 1;
  469.         }
  470.         bro_event_free(ev);
  471.         if (outstanding >= MAXOUTSTANDING)
  472.             if (getresult())
  473.                 ret = 1;
  474.     }
  475.     fclose(f);
  476.     while (outstanding > 0)
  477.         if (getresult())
  478.             ret = 1;
  479.  
  480.     if (ret)
  481.         fprintf(stderr, "%s: %s failed\n", prog, cmd);
  482.     return (ret);
  483. }
  484.  
  485. int
  486. getresult()
  487. {
  488.     int n, nfds;
  489.     struct timeval tmo;
  490.     fd_set readfds;
  491.  
  492.     for (;;) {
  493.         /* Recalculate fdsets */
  494.         FD_ZERO(&readfds);
  495.         FD_SET(s, &readfds);
  496.         nfds = s;
  497.         ++nfds;
  498.  
  499.         /* Set timeout */
  500.         tmo.tv_sec = timeout;
  501.         tmo.tv_usec = 0;
  502.         n = select(nfds, &readfds, NULL, NULL, &tmo);
  503.  
  504.         if (n < 0) {
  505.             /* Don't choke if we get ptraced */
  506.             if (errno == EINTR)
  507.                 continue;
  508.             fprintf(stderr, "%s: select: %s\n",
  509.                 prog, strerror(errno));
  510.             exit(EX_OSERR);
  511.         }
  512.  
  513.         /* Timeout */
  514.         if (n == 0) {
  515.             // bro_event_queue_flush(bc);
  516.             fprintf(stderr, "%s: timeout\n", prog);
  517.             return (1);
  518.         }
  519.  
  520.         /* Data from server */
  521.         if (FD_ISSET(s, &readfds)) {
  522.             --n;
  523.             (void)bro_conn_process_input(bc);
  524.             if (!bro_conn_alive(bc)) {
  525.                 fprintf(stderr, "%s: server exited\n", prog);
  526.                 return (1);
  527.             }
  528.             /* Got our response; bail! */
  529.             return (!success);
  530.         }
  531.  
  532.         if (n != 0)
  533.             fprintf(stderr, "%s: select leakage: %d\n", prog, n);
  534.             continue;
  535.     }
  536. }
  537.  
  538. /* Interactive command loop */
  539. int
  540. loop(int s, BroConn *bc)
  541. {
  542.     int n, nfds, ret;
  543.     uint32 reqcookie;
  544.     ssize_t cc;
  545.     BroEvent *ev;
  546.     struct timeval tmo;
  547.     fd_set readfds;
  548.     char buf[1024];
  549.     const char *prompt = "> ";
  550.  
  551.     ret = 0;
  552.     reqcookie = cookie;
  553.     fputs(prompt, stdout);
  554.     fflush(stdout);
  555.     for (;;) {
  556.         /* Recalculate fdsets */
  557.         FD_ZERO(&readfds);
  558.         FD_SET(fileno(stdin), &readfds);
  559.         nfds = fileno(stdin);
  560.         FD_SET(s, &readfds);
  561.         if (nfds < s)
  562.             nfds = s;
  563.         ++nfds;
  564.  
  565.         /* Set timeout */
  566.         tmo.tv_sec = timeout;
  567.         tmo.tv_usec = 0;
  568.         n = select(nfds, &readfds, NULL, NULL, &tmo);
  569.  
  570.         if (n < 0) {
  571.             /* Don't choke if we get ptraced */
  572.             if (errno == EINTR)
  573.                 continue;
  574.             fprintf(stderr, "%s: select: %s\n",
  575.                 prog, strerror(errno));
  576.             exit(EX_OSERR);
  577.         }
  578.  
  579.         /* Timeout */
  580.         if (n == 0)
  581.             bro_event_queue_flush(bc);
  582.  
  583.         /* Data from server */
  584.         if (FD_ISSET(s, &readfds)) {
  585.             --n;
  586.             (void)bro_conn_process_input(bc);
  587.             if (!bro_conn_alive(bc)) {
  588.                 fprintf(stderr, "%s: server exited\n", prog);
  589.                 return (1);
  590.             }
  591.             fputs(prompt, stdout);
  592.             fflush(stdout);
  593.         }
  594.  
  595.         /* Input from stdin */
  596.         if (FD_ISSET(fileno(stdin), &readfds)) {
  597.             --n;
  598.             cc = read(fileno(stdin), buf, sizeof(buf));
  599.             if (cc < 0)
  600.                 fprintf(stderr, "%s: read stdin: %s\n",
  601.                     prog, strerror(errno));
  602.             else if (cc == 0) {
  603.                 /* EOF */
  604.                 putc('\n', stdout);
  605.                 return (ret);
  606.             } else {
  607.                 if (cc >= sizeof(buf))
  608.                     cc = sizeof(buf) - 1;
  609.                 if (cc > 0 && buf[cc - 1] == '\n')
  610.                     --cc;
  611.                 buf[cc] = '\0';
  612.                 ev = acldevent(buf, reqcookie++);
  613.  
  614.                 if (!bro_event_send(bc, ev)) {
  615.                     fprintf(stderr, "%s: failed to send\n",
  616.                         prog);
  617.                     ret = 1;
  618.                 }
  619.                 bro_event_free(ev);
  620.                 if (!success)
  621.                     ret = 1;
  622.             }
  623.         }
  624.  
  625.         if (n != 0)
  626.             fprintf(stderr, "%s: select leakage: %d\n", prog, n);
  627.             continue;
  628.     }
  629. }
  630.  
  631. __dead void
  632. usage(void)
  633. {
  634.     const char common[] = "[-dDv] [-a addr] [-P port]"
  635.         " [-e reqstr] [-E repstr] [-c comment] \\\n           ";
  636.  
  637.     fprintf(stderr, "%s version %s\n", prog, version);
  638.     fprintf(stderr, "Broccoli version %s\n", broccoli_version);
  639.     fprintf(stderr, "Usage: %s %s cmd [args ...]\n", prog, common);
  640.     fprintf(stderr, "       %s %s -f file cmd\n", prog, common);
  641.     exit(EX_USAGE);
  642. }
  643.  
  644. /*
  645.  * common - example broccoli common code
  646.  */
  647.  
  648. int
  649. extractbool(BroRecord *rec, const char *name, int *bp)
  650. {
  651.     int btype;
  652.     int *bbp;
  653.  
  654.     btype = BRO_TYPE_BOOL;
  655.     bbp = bro_record_get_named_val(rec, name, &btype);
  656.     if (bbp == NULL) {
  657.         *bp = 0;
  658.         return (0);
  659.     }
  660.     *bp = *bbp;
  661.     return (1);
  662. }
  663.  
  664. /* Note: Returns a malloc'ed buffer that the caller must free */
  665. char *
  666. extractstr(BroRecord *rec, const char *name)
  667. {
  668.     int btype;
  669.     size_t size;
  670.     char *cp;
  671.     BroString *bstr;
  672.  
  673.     btype = BRO_TYPE_STRING;
  674.     bstr = bro_record_get_named_val(rec, name, &btype);
  675.     if (bstr == NULL)
  676.         return (NULL);
  677.     size = bstr->str_len;
  678.     cp = malloc(size + 1);
  679.     if (cp == NULL) {
  680.         fprintf(stderr, "%s: extractstr: malloc: %s",
  681.             prog, strerror(errno));
  682.         exit(EX_OSERR);
  683.     }
  684.     strncpy(cp, (const char *)bstr->str_val, size);
  685.     cp[size] = '\0';
  686.     bro_string_cleanup(bstr);
  687.     return (cp);
  688. }
  689.  
  690. int
  691. extracttime(BroRecord *rec, const char *name, double *dp)
  692. {
  693.     int btype;
  694.     double *bdp;
  695.  
  696.     btype = BRO_TYPE_TIME;
  697.     bdp = bro_record_get_named_val(rec, name, &btype);
  698.     if (bdp == NULL) {
  699.         *dp = 0;
  700.         return (0);
  701.     }
  702.     *dp = *bdp;
  703.     return (1);
  704. }
  705.  
  706. int
  707. extractuint32(BroRecord *rec, const char *name, uint32 *up)
  708. {
  709.     int btype;
  710.     uint32 *bup;
  711.  
  712.     btype = BRO_TYPE_COUNT;
  713.     bup = bro_record_get_named_val(rec, name, &btype);
  714.     if (bup == NULL) {
  715.         *up = 0;
  716.         return (0);
  717.     }
  718.     *up = *bup;
  719.     return (1);
  720. }
  721.  
  722. void *
  723. new(size_t num, size_t size, const char *what)
  724. {
  725.     void *p;
  726.  
  727.     p = calloc(num, size);
  728.     if (p == NULL) {
  729.         fprintf(stderr, "%s: new: calloc %s: %s\n",
  730.             prog, what, strerror(errno));
  731.         exit(EX_OSERR);
  732.     }
  733.     return (p);
  734. }
  735.