broccoli-1.97-minimal/0000775002342100234210000000000012523041064014505 5ustar johannajohannabroccoli-1.97-minimal/compat/0000775002342100234210000000000012523041064015770 5ustar johannajohannabroccoli-1.97-minimal/compat/sys/0000775002342100234210000000000012523041064016606 5ustar johannajohannabroccoli-1.97-minimal/compat/sys/queue.h0000664002342100234210000002027712523041064020113 0ustar johannajohanna/* * Copyright (c) 1991, 1993 * 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)queue.h 8.3 (Berkeley) 12/13/93 */ #ifndef _SYS_QUEUE_H #define _SYS_QUEUE_H 1 /* * This file defines three types of data structures: lists, tail queues, * and circular queues. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list after * an existing element or at the head of the list. A list may only be * traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list after * an existing element, at the head of the list, or at the end of the * list. A tail queue may only be traversed in the forward direction. * * A circle queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the list. * A circle queue may be traversed in either direction, but has a more * complex end of list detection. * * For details on the use of these macros, see the queue(3) manual page. */ /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #define LIST_INIT(head) { \ (head)->lh_first = NULL; \ } #define LIST_INSERT_AFTER(listelm, elm, field) { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } #define LIST_INSERT_HEAD(head, elm, field) { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } #define LIST_REMOVE(elm, field) { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ } /* * Tail queue definitions. */ #define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ } /* * Tail queue functions. */ #define TAILQ_INIT(head) { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } #define TAILQ_INSERT_HEAD(head, elm, field) { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } #define TAILQ_INSERT_TAIL(head, elm, field) { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } #define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } #define TAILQ_REMOVE(head, elm, field) { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ } /* * Circular queue definitions. */ #define CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } #define CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ } /* * Circular queue functions. */ #define CIRCLEQ_INIT(head) { \ (head)->cqh_first = (void *)(head); \ (head)->cqh_last = (void *)(head); \ } #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ if ((listelm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ if ((listelm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } #define CIRCLEQ_INSERT_HEAD(head, elm, field) { \ (elm)->field.cqe_next = (head)->cqh_first; \ (elm)->field.cqe_prev = (void *)(head); \ if ((head)->cqh_last == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } #define CIRCLEQ_INSERT_TAIL(head, elm, field) { \ (elm)->field.cqe_next = (void *)(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ if ((head)->cqh_first == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } #define CIRCLEQ_REMOVE(head, elm, field) { \ if ((elm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ if ((elm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ } #endif /* sys/queue.h */ broccoli-1.97-minimal/TODO0000664002342100234210000000230612523041064015176 0ustar johannajohanna- Separate method pointers (i.e., the vtable) in the various classes into separate "class" structs (think klass in Gtk). Right now these waste space because they're allocated with every instance, but since they're not used extensively it hasn't really been worth it so far. - The init methods must be allowed to fail. Currently allocations in that method can fail but this failure can not be signaled to the caller. - Add an error variable so the user has a way to figure out what happened when things go wrong. - Add support for at least a small number of expressions -- needed in bro_attr.[ch]. - Add support for tables/sets. - Add a server-suitable API, i.e., how can one write an application that listens on a given port, using Broccoli. - When configure determined that lex+yacc exist, make clean doesn't clean up the generated lexer/parser C files. I presume this is because I keep them all in EXTRA_DIST. Ensure make clean removes the generated files when we know we can regenerate them. - There's a segfault lurking in __bro_record_get_nth_val() with records that don't have all members assigned to. Investigate whether dummy val approach really works or whether it's a design flaw. broccoli-1.97-minimal/test/0000775002342100234210000000000012523041064015464 5ustar johannajohannabroccoli-1.97-minimal/test/brotable.c0000664002342100234210000002041112523041064017420 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif void print_val(void *val, int type) { char br_open = '['; char br_close = ']'; if (! val) { printf("NULL"); return; } switch (type) { case BRO_TYPE_BOOL: printf("%s", *((int*) val) == 0 ? "false" : "true"); break; case BRO_TYPE_INT: printf("%i", *((int*) val)); break; case BRO_TYPE_DOUBLE: printf("%f", *((double*) val)); break; case BRO_TYPE_STRING: printf("'%s'", bro_string_get_data((BroString*) val)); break; case BRO_TYPE_LIST: /* This means that we're dealing with a composite indexing type. * Except for this differing type code, treatment is exactly as * with a record: */ br_open = '{'; br_close = '}'; /* Fall through */ case BRO_TYPE_RECORD: { void *item; int i, type; BroRecord *rec = (BroRecord*) val; printf("%c", br_open); for (i = 0; i < bro_record_get_length(rec); i++) { /* We don't want to enforce typechecking of the * queried value, so we use BRO_TYPE_UNKNOWN. */ type = BRO_TYPE_UNKNOWN; item = bro_record_get_nth_val(rec, i, &type); print_val(item, type); if (i + 1 < bro_record_get_length(rec)) printf(", "); } printf("%c", br_close); } break; default: printf("", type); } } int table_it_cb(void *key, void *val, BroTable *table) { int key_type, val_type; bro_table_get_types(table, &key_type, &val_type); print_val(key, key_type); printf(" -> "); print_val(val, val_type); printf("\n"); return TRUE; } int main(int argc, char **argv) { int opt, debugging = 0; /* A few tables with different atomic indexing/yield types: */ BroTable *int_to_str; BroTable *str_to_double; /* A table with a composite indexing type: */ BroTable *int_str_double_to_int; /* Placeholders for the stuff we insert/retrieve: */ BroString str, *str_ptr; BroRecord *rec; int i, i2, *i_ptr; double d, *d_ptr; while ( (opt = getopt(argc, argv, "c:p:dh?r")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; default: break; } } /* ---- Mandatory initialization ------------------------------------- */ bro_init(NULL); /* ---- int -> string ------------------------------------------------ */ printf("int_to_str table dump:\n"); printf("----------------------\n"); int_to_str = bro_table_new(); i = 10; bro_string_set(&str, "foo"); bro_table_insert(int_to_str, BRO_TYPE_INT, &i, BRO_TYPE_STRING, &str); bro_string_cleanup(&str); i = 20; bro_string_set(&str, "bar"); bro_table_insert(int_to_str, BRO_TYPE_INT, &i, BRO_TYPE_STRING, &str); bro_string_cleanup(&str); i = 30; bro_string_set(&str, "baz"); bro_table_insert(int_to_str, BRO_TYPE_INT, &i, BRO_TYPE_STRING, &str); bro_string_cleanup(&str); bro_table_foreach(int_to_str, (BroTableCallback) table_it_cb, int_to_str); printf("\ntest lookup: "); i = 20; str_ptr = (BroString*) bro_table_find(int_to_str, &i); print_val(&i, BRO_TYPE_INT); printf(" -> "); print_val(str_ptr, BRO_TYPE_STRING); printf("\n\n"); bro_table_free(int_to_str); /* ---- string -> double --------------------------------------------- */ printf("str_to_double table dump:\n"); printf("-------------------------\n"); str_to_double = bro_table_new(); d = 1.1; bro_string_set(&str, "foo"); bro_table_insert(str_to_double, BRO_TYPE_STRING, &str, BRO_TYPE_DOUBLE, &d); bro_string_cleanup(&str); d = 2.2; bro_string_set(&str, "bar"); bro_table_insert(str_to_double, BRO_TYPE_STRING, &str, BRO_TYPE_DOUBLE, &d); bro_string_cleanup(&str); d = 3.3; bro_string_set(&str, "baz"); bro_table_insert(str_to_double, BRO_TYPE_STRING, &str, BRO_TYPE_DOUBLE, &d); bro_string_cleanup(&str); bro_table_foreach(str_to_double, (BroTableCallback) table_it_cb, str_to_double); printf("\ntest lookup: "); bro_string_set(&str, "bar"); d_ptr = (double*) bro_table_find(str_to_double, &str); print_val(&str, BRO_TYPE_STRING); printf(" -> "); print_val(d_ptr, BRO_TYPE_DOUBLE); printf("\n\n"); bro_string_cleanup(&str); bro_table_free(str_to_double); /* ---- {int, string, double} -> int --------------------------------- */ printf("int_str_double_to_int table dump:\n"); printf("---------------------------------\n"); int_str_double_to_int = bro_table_new(); /* -- first element -- */ i = 1; d = 1.1; bro_string_set(&str, "foo"); i2 = 10; /* You may pass NULL as the field name, but then of course looking * up elements by field name will not work in case you need it. */ rec = bro_record_new(); bro_record_add_val(rec, NULL, BRO_TYPE_INT, NULL, &i); bro_record_add_val(rec, NULL, BRO_TYPE_STRING, NULL, &str); bro_record_add_val(rec, NULL, BRO_TYPE_DOUBLE, NULL, &d); bro_table_insert(int_str_double_to_int, BRO_TYPE_LIST, rec, BRO_TYPE_INT, &i2); bro_string_cleanup(&str); bro_record_free(rec); /* -- second element -- */ i = 2; d = 2.2; bro_string_set(&str, "bar"); i2 = 20; /* You may pass NULL as the field name, but then of course looking * up elements by field name will not work in case you need it. */ rec = bro_record_new(); bro_record_add_val(rec, NULL, BRO_TYPE_INT, NULL, &i); bro_record_add_val(rec, NULL, BRO_TYPE_STRING, NULL, &str); bro_record_add_val(rec, NULL, BRO_TYPE_DOUBLE, NULL, &d); bro_table_insert(int_str_double_to_int, BRO_TYPE_LIST, rec, BRO_TYPE_INT, &i2); bro_string_cleanup(&str); bro_record_free(rec); /* -- third element -- */ i = 3; d = 3.3; bro_string_set(&str, "baz"); i2 = 30; /* You may pass NULL as the field name, but then of course looking * up elements by field name will not work in case you need it. */ rec = bro_record_new(); bro_record_add_val(rec, NULL, BRO_TYPE_INT, NULL, &i); bro_record_add_val(rec, NULL, BRO_TYPE_STRING, NULL, &str); bro_record_add_val(rec, NULL, BRO_TYPE_DOUBLE, NULL, &d); bro_table_insert(int_str_double_to_int, BRO_TYPE_LIST, rec, BRO_TYPE_INT, &i2); bro_string_cleanup(&str); bro_record_free(rec); bro_table_foreach(int_str_double_to_int, (BroTableCallback) table_it_cb, int_str_double_to_int); printf("\ntest lookup: "); i = 2; d = 2.2; bro_string_set(&str, "bar"); rec = bro_record_new(); bro_record_add_val(rec, NULL, BRO_TYPE_INT, NULL, &i); bro_record_add_val(rec, NULL, BRO_TYPE_STRING, NULL, &str); bro_record_add_val(rec, NULL, BRO_TYPE_DOUBLE, NULL, &d); i_ptr = (int*) bro_table_find(int_str_double_to_int, rec); print_val(rec, BRO_TYPE_LIST); printf(" -> "); print_val(i_ptr, BRO_TYPE_INT); printf("\n\n"); bro_string_cleanup(&str); bro_record_free(rec); bro_table_free(int_str_double_to_int); return 0; } broccoli-1.97-minimal/test/brosendpackets.c0000664002342100234210000000426012523041064020641 0ustar johannajohanna#include #include #include void usage() { fprintf(stderr, "usage: brosendpackets [-r file] [-b host:port ] [-t tag]\n"); exit(1); } int main(int argc, char** argv) { bro_init(NULL); char* filename=NULL; char* bro_connection=NULL; const char* tag=""; int opt; while ((opt=getopt(argc, argv, "r:b:t:h?")) != -1) { switch(opt) { case 'r': filename=strdup(optarg); break; case 'b': bro_connection=strdup(optarg); break; case 't': tag=strdup(optarg); break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if (filename==NULL || bro_connection==NULL) usage(); BroConn *broccoli_p=bro_conn_new_str(bro_connection, BRO_CFLAG_NONE); if (!broccoli_p) { fprintf(stderr, "can't instantiate connection object\n"); exit(1); } if (! bro_conn_connect(broccoli_p)) { fprintf(stderr, "Bro connection to %s failed\n", bro_connection); exit(1); } printf("connected to Bro %s\n", bro_connection); char pcap_errbuf[PCAP_ERRBUF_SIZE]=""; pcap_t* pcap_p=pcap_open_offline(filename, pcap_errbuf); if (!pcap_p) { fprintf(stderr, "pcap eror: %s\n", pcap_errbuf); exit(1); } bro_conn_set_packet_ctxt(broccoli_p, pcap_datalink(pcap_p)); const uchar* packet_p=NULL; struct pcap_pkthdr pkthdr; int pkt_cnt=0; while ((packet_p=pcap_next(pcap_p, &pkthdr))) { pkt_cnt++; BroPacket* broccoli_packet_p=bro_packet_new(&pkthdr, packet_p, tag); bro_packet_send(broccoli_p, broccoli_packet_p); bro_packet_free(broccoli_packet_p); } printf("sent %d packets\n",pkt_cnt); /* fd_set rfds; int broccoli_fd=bro_conn_get_fd(broccoli_p); // printf("bro_connect_str=%s broccoli_fd=%d\n", conf_main_bro_connect_str, broccoli_fd); bro_event_registry_add(broccoli_p, "tm_query", (BroEventFunc)tm_query_cb); bro_event_registry_request(broccoli_p); // loop FD_ZERO(&rfds); FD_SET(broccoli_fd, &rfds); while (1) { select(broccoli_fd+1, &rfds, NULL, NULL, NULL); /// error handling! printf("select()ed on Bro connection file descriptor\n"); bro_conn_process_input(broccoli_p); } */ bro_conn_delete(broccoli_p); printf("connection to Bro %s closed\n", bro_connection); return 0; } broccoli-1.97-minimal/test/broping-record.bro0000664002342100234210000000235512523041064021111 0ustar johannajohanna@load frameworks/communication/listen # Let's make sure we use the same port no matter whether we use encryption or not: redef Communication::listen_port = 47758/tcp; # Redef this to T if you want to use SSL. redef Communication::listen_ssl = F; # Set the SSL certificates being used to something real if you are using encryption. #redef ssl_ca_certificate = "/ca_cert.pem"; #redef ssl_private_key = "/bro.pem"; redef Communication::nodes += { ["broping"] = [$host = 127.0.0.1, $events = /ping/, $connect=F, $ssl=F] }; global ping_log = open_log_file("ping"); type ping_data: record { seq: count; src_time: time; }; type pong_data: record { seq: count; src_time: time; dst_time: time; }; # global pdata: pong_data; global ping: event(data: ping_data); global pong: event(data: pong_data); event ping(data: ping_data) { local pdata: pong_data; pdata$seq = data$seq; pdata$src_time = data$src_time; pdata$dst_time = current_time(); event pong(pdata); } event pong(data: pong_data) { print ping_log, fmt("ping received, seq %d, %f at src, %f at dest, one-way: %f", data$seq, data$src_time, data$dst_time, data$dst_time - data$src_time); } broccoli-1.97-minimal/test/broconn.c0000664002342100234210000002033012523041064017266 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif char *host_default = "127.0.0.1"; char *port_default = "47758"; char *host_str; char *port_str; int count = -1; int seq; static void usage(void) { printf("broconn - dumps arriving connection events to console.\n" "USAGE: broconn [-h|-?] [-d] [-p port] host\n"); exit(0); } /* Snippet from Bro policies containing relevant record types: type connection: record { id: conn_id; orig: endpoint; resp: endpoint; start_time: time; duration: interval; service: string; addl: string; hot: count; }; type conn_id: record { orig_h: addr; orig_p: port; resp_h: addr; resp_p: port; }; type endpoint: record { size: count; state: count; }; */ static int services_print_cb(BroString *service, void *user_data) { printf("'%s' ", service->str_val); return TRUE; user_data = NULL; } static void conn_generic(BroConn *bc, BroRecord *conn) { BroRecord *id, *orig, *resp; BroSet *services; BroString *addl; BroPort *port; BroAddr *addr; uint32 *size, *state; double *start_time, *duration; int type = BRO_TYPE_RECORD; char addr_str[INET6_ADDRSTRLEN]; if (! (id = bro_record_get_named_val(conn, "id", &type))) { printf("[Error obtaining 'id' member from connection record.]\n"); return; } if (! (orig = bro_record_get_named_val(conn, "orig", &type))) { printf("[Error obtaining 'orig' member from connection record.]\n"); return; } if (! (resp = bro_record_get_named_val(conn, "resp", &type))) { printf("[Error obtaining 'orig' member from connection record.]\n"); return; } type = BRO_TYPE_IPADDR; if (! (addr = bro_record_get_named_val(id, "orig_h", &type))) { printf("[Error obtaining 'orig_h' member from connection ID record.]\n"); return; } type = BRO_TYPE_PORT; if (! (port = bro_record_get_named_val(id, "orig_p", &type))) { printf("[Error obtaining 'orig_p' member from connection ID record.]\n"); return; } type = BRO_TYPE_COUNT; if (! (size = bro_record_get_named_val(orig, "size", &type))) { printf("[Error obtaining 'size' member from orig endpoint record.]\n"); return; } if (! (state = bro_record_get_named_val(orig, "state", &type))) { printf("[Error obtaining 'state' member from orig endpoint record.]\n"); return; } inet_ntop(AF_INET6, addr->addr, addr_str, INET6_ADDRSTRLEN); printf("%s/%"PRIu64" [%"PRIu32"/%"PRIu32"] -> ", addr_str, port->port_num, *size, *state); type = BRO_TYPE_IPADDR; if (! (addr = bro_record_get_named_val(id, "resp_h", &type))) { printf("[Error obtaining 'resp_h' member from connection ID record.]\n"); return; } type = BRO_TYPE_PORT; if (! (port = bro_record_get_named_val(id, "resp_p", &type))) { printf("[Error obtaining 'resp_p' member from connection ID record.]\n"); return; } type = BRO_TYPE_COUNT; if (! (size = bro_record_get_named_val(resp, "size", &type))) { printf("[Error obtaining 'size' member from orig endpoint record.]\n"); return; } if (! (state = bro_record_get_named_val(resp, "state", &type))) { printf("[Error obtaining 'state' member from orig endpoint record.]\n"); return; } inet_ntop(AF_INET6, addr->addr, addr_str, INET6_ADDRSTRLEN); printf("%s/%"PRIu64" [%"PRIu32"/%"PRIu32"] -> ", addr_str, port->port_num, *size, *state); type = BRO_TYPE_TIME; if (! (start_time = bro_record_get_named_val(conn, "start_time", &type))) { printf("[Error obtaining 'start_time' member from connection record.]\n"); return; } type = BRO_TYPE_INTERVAL; if (! (duration = bro_record_get_named_val(conn, "duration", &type))) { printf("[Error obtaining 'duration' member from connection record.]\n"); return; } type = BRO_TYPE_SET; services = bro_record_get_named_val(conn, "service", &type); type = BRO_TYPE_STRING; if (! (addl = bro_record_get_named_val(conn, "addl", &type))) { printf("[Error obtaining 'addl' member from connection record.]\n"); return; } printf("start: %f, duration: %f, addl: '%s', ", *start_time, *duration, addl->str_val); if (services) { int type; bro_set_get_type(services, &type); printf("%i services (type check: %d) ", bro_set_get_size(services), type); if (bro_set_get_size(services) > 0) bro_set_foreach(services, (BroSetCallback) services_print_cb, NULL); } else printf("no services listed"); printf("\n"); } static void conn_new(BroConn *bc, void *data, BroRecord *conn) { printf("new_connection: "); conn_generic(bc, conn); data = NULL; } static void conn_fin(BroConn *bc, void *data, BroRecord *conn) { printf("connection_finished: "); conn_generic(bc, conn); data = NULL; } int main(int argc, char **argv) { int opt, port, fd, debugging = 0; BroConn *bc; extern char *optarg; extern int optind; char hostname[512]; fd_set fd_read; bro_init(NULL); host_str = host_default; port_str = port_default; bro_debug_calltrace = 0; bro_debug_messages = 0; while ( (opt = getopt(argc, argv, "c:p:dh?r")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; case 'h': case '?': usage(); case 'p': port_str = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) host_str = argv[0]; port = strtol(port_str, NULL, 0); if (errno == ERANGE) { printf("Please provide a port number with -p.\n"); exit(-1); } snprintf(hostname, 512, "%s:%s", host_str, port_str); /* Connect to Bro */ if (! (bc = bro_conn_new_str(hostname, BRO_CFLAG_RECONNECT | BRO_CFLAG_ALWAYS_QUEUE))) { printf("Couldn't get Bro connection handle.\n"); exit(-1); } /* Request a few event types and have the corresponding callbacks * called when they arrive. The callback mechanism automatically figures out * the number of arguments and invokes the callback accordingly. */ bro_event_registry_add(bc, "new_connection", (BroEventFunc) conn_new, NULL); bro_event_registry_add(bc, "connection_finished", (BroEventFunc) conn_fin, NULL); if (! bro_conn_connect(bc)) { printf("Could not connect to Bro at %s:%s.\n", host_str, port_str); exit(-1); } /* Sit and wait for events */ fd = bro_conn_get_fd(bc); for ( ; ; ) { FD_ZERO(&fd_read); FD_SET(fd, &fd_read); if (select(fd + 1, &fd_read, NULL, NULL, NULL) <= 0) break; bro_conn_process_input(bc); } /* Disconnect from Bro and release state. */ bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/test/broconn.bro0000664002342100234210000000172312523041064017633 0ustar johannajohanna@load frameworks/communication/listen # Let's make sure we use the same port no matter whether we use encryption or not: redef Communication::listen_port = 47758/tcp; # Redef this to T if you want to use SSL. redef Communication::listen_ssl = F; # Set the SSL certificates being used to something real if you are using encryption. #redef ssl_ca_certificate = "/ca_cert.pem"; #redef ssl_private_key = "/bro.pem"; redef Communication::nodes += { ["broconn"] = [$host = 127.0.0.1, $connect=F, $ssl=F] }; function services_to_string(ss: string_set): string { local result = ""; for (s in ss) result = fmt("%s %s", result, s); return result; } event new_connection(c: connection) { print fmt("new_connection: %s, services:%s", id_string(c$id), services_to_string(c$service)); } event connection_finished(c: connection) { print fmt("connection_finished: %s, services:%s", id_string(c$id), services_to_string(c$service)); } broccoli-1.97-minimal/test/brohose.c0000664002342100234210000001256512523041064017302 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif char *host_default = "127.0.0.1"; char *port_default = "47758"; char *host_str; char *port_str; int num_procs = 10; int num_events = 1000; int seq; static void usage(void) { printf("brohose - sends events to a Bro node from multiple processes in parallel.\n" "USAGE: brohose [-h|-?] [-n <# processes>] [-e <# events>] [-p port] host\n" " -h|? this message\n" " -n <# processes> number of processes to use (10)\n" " -e <# events> number of events per process (1000)\n" " -p port to contact\n" " host host to contanct\n\n"); exit(0); } static void hose_away(BroConn *bc) { BroEvent *ev; BroString str; int i; pid_t pid = getpid(); char msg[1024]; printf("++ child %u\n", pid); for (i = 0; i < num_events; i++) { /* Create empty "ping" event */ if (! (ev = bro_event_new("brohose"))) { printf("**** EEEEK\n"); bro_conn_delete(bc); return; } snprintf(msg, 1024, "%u-%i-%i", pid, i, bro_event_queue_length(bc)); bro_string_set(&str, msg); bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &str); /* Ship it -- sends it if possible, queues it otherwise */ bro_event_send(bc, ev); bro_event_free(ev); bro_string_cleanup(&str); if (bro_event_queue_length(bc) > bro_event_queue_length_max(bc) / 2) { while (bro_event_queue_length(bc) > 0) bro_event_queue_flush(bc); } } while (bro_event_queue_length(bc) > 0) bro_event_queue_flush(bc); printf("-- child %u, %i queued\n", pid, bro_event_queue_length(bc)); bro_conn_delete(bc); } int main(int argc, char **argv) { int i, opt, port, debugging = 0; BroConn *bc; extern char *optarg; extern int optind; char hostname[512]; bro_init(NULL); host_str = host_default; port_str = port_default; bro_debug_calltrace = 0; bro_debug_messages = 0; while ( (opt = getopt(argc, argv, "n:e:p:dh?")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; case 'h': case '?': usage(); case 'n': num_procs = strtol(optarg, NULL, 0); if (errno == ERANGE || num_procs < 1 || num_procs > 100) { printf("Please restrict the number of processes to 1-100.\n"); exit(-1); } break; case 'e': num_events = strtol(optarg, NULL, 0); if (errno == ERANGE || num_events < 1 || num_events > 10000) { printf("Please restrict the number of events to 1-10,000..\n"); exit(-1); } break; case 'p': port_str = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) host_str = argv[0]; port = strtol(port_str, NULL, 0); if (errno == ERANGE) { printf("Please provide a port number with -p.\n"); exit(-1); } snprintf(hostname, 512, "%s:%s", host_str, port_str); printf("Will attempt to send %i events from %i processes, to %s\n", num_events, num_procs, hostname); /* Connect to Bro */ if (! (bc = bro_conn_new_str(hostname, BRO_CFLAG_SHAREABLE))) { printf("Couldn't get Bro connection handle.\n"); exit(-1); } if (! bro_conn_connect(bc)) { printf("Could not connect to Bro at %s:%s.\n", host_str, port_str); exit(-1); } for (i = 0; i < num_procs; i++) { int pid = fork(); if (pid < 0) { printf("Couldn't fork children, aborting.\n"); exit(-1); } if (pid == 0) { hose_away(bc); exit(0); } } while (i > 0) { int status; wait(&status); // Ignore errors. i--; } /* Disconnect from Bro -- this will keep the copies in the children * working but reduce the reference count of the underlying socket so * that eventually it is really closed. */ bro_conn_delete(bc); printf("Exiting ...\n"); return 0; } broccoli-1.97-minimal/test/broconftest.c0000664002342100234210000000311012523041064020153 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef HAVE_CONFIG_H #include #endif int main(int argc, char **argv) { int i; const char *s; bro_init(NULL); if ( (s = bro_conf_get_str("PeerName"))) printf("PeerName: %s\n", s); if (bro_conf_get_int("PeerPort", &i)) printf("PeerPort: %i\n", i); return 0; } broccoli-1.97-minimal/test/broping.c0000664002342100234210000002447112523041064017300 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif char *host_default = "127.0.0.1"; char *port_default = "47758"; char *host_str; char *port_str; int count = -1; uint64 seq; static void usage(void) { printf("broping - sends ping events to a Bro agent, expecting pong events.\n" "USAGE: broping [-h|-?] [-d] [-l] [-r] [-c num] [-p port] host\n" " -h|-? This message.\n" " -d Enable debugging (only useful if configured with --enable-debug).\n" " -r Use record types to transfer data.\n" " -C Use compact callback argument passing.\n" " -c Number of events to send.\n" " -p Port on to contact.\n"); exit(0); } static void bro_pong(BroConn *conn, void *data, double *src_time, double *dst_time, uint64 *seq) { double now = bro_util_current_time(); printf("pong event from %s: seq=%"PRIu64", time=%f/%f s\n", host_str, *seq, *dst_time - *src_time, now - *src_time); conn = NULL; data = NULL; } static void bro_pong_record(BroConn *conn, void *data, BroRecord *rec) { double now = bro_util_current_time(); double *src_time, *dst_time; uint64 *seq; int type = BRO_TYPE_COUNT; if (! (seq = bro_record_get_nth_val(rec, 0, &type))) { printf("Error getting sequence count from event, got type %i\n", type); return; } type = BRO_TYPE_TIME; if (! (src_time = bro_record_get_nth_val(rec, 1, &type))) { printf("Error getting src time from event, got type %i.\n", type); return; } type = BRO_TYPE_TIME; if (! (dst_time = bro_record_get_nth_val(rec, 2, &type))) { printf("Error getting dst time from event, got type %i\n", type); return; } printf("pong event from %s: seq=%"PRIu64", time=%f/%f s\n", host_str, *seq, *dst_time - *src_time, now - *src_time); conn = NULL; data = NULL; } static void bro_pong_compact(BroConn *conn, void *data, BroEvMeta *meta) { double *src_time; double *dst_time; uint64 *seq; /* Sanity-check arguments: */ if (strcmp(meta->ev_name, "pong") != 0) { printf("Event should be 'pong', is '%s', error.\n", meta->ev_name); return; } if (meta->ev_numargs != 3) { printf("Pong event should have 3 arguments, has %d, error.\n", meta->ev_numargs); return; } if (meta->ev_args[0].arg_type != BRO_TYPE_TIME) { printf("Type of first argument should be %i, is %i, error.\n", BRO_TYPE_TIME, meta->ev_args[0].arg_type); return; } if (meta->ev_args[1].arg_type != BRO_TYPE_TIME) { printf("Type of second argument should be %i, is %i, error.\n", BRO_TYPE_TIME, meta->ev_args[1].arg_type); return; } if (meta->ev_args[2].arg_type != BRO_TYPE_COUNT) { printf("Type of third argument should be %i, is %i, error.\n", BRO_TYPE_COUNT, meta->ev_args[2].arg_type); return; } src_time = (double *) meta->ev_args[0].arg_data; dst_time = (double *) meta->ev_args[1].arg_data; seq = (uint64 *) meta->ev_args[2].arg_data; bro_pong(conn, data, src_time, dst_time, seq); } static void bro_pong_compact_record(BroConn *conn, void *data, BroEvMeta *meta) { BroRecord *rec; /* Sanity-check argument type: */ if (strcmp(meta->ev_name, "pong") != 0) { printf("Event should be 'pong', is '%s', error.\n", meta->ev_name); return; } if (meta->ev_numargs != 1) { printf("Pong event should have 1 argument, has %d, error.\n", meta->ev_numargs); return; } if (meta->ev_args[0].arg_type != BRO_TYPE_RECORD) { printf("Type of argument should be %i, is %i, error.\n", BRO_TYPE_RECORD, meta->ev_args[0].arg_type); return; } rec = (BroRecord *) meta->ev_args[0].arg_data; bro_pong_record(conn, data, rec); } BroConn* start_listen(int port) { int fd = 0; struct sockaddr_in server; struct sockaddr_in client; socklen_t len = sizeof(client); fd_set fds; const int turn_on = 1; BroConn *bc = 0; fd = socket(PF_INET, SOCK_STREAM, 0); if ( fd < 0 ) { printf("can't create listen socket: %s\n", strerror(errno)); exit(-1); } // Set SO_REUSEADDR. if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &turn_on, sizeof(turn_on)) < 0 ) { printf("can't set SO_REUSEADDR: %s\n", strerror(errno)); exit(-1); } bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = 0; if ( bind(fd, (struct sockaddr*) &server, sizeof(server)) < 0 ) { printf("can't bind to port %d: %s\n", port, strerror(errno)); exit(-1); } if ( listen(fd, 50) < 0 ) { printf("can't listen: %s\n", strerror(errno)); exit(-1); } FD_ZERO(&fds); FD_SET(fd, &fds); if ( select(fd + 1, &fds, &fds, &fds, 0) < 0 ) { printf("can't select: %s\n", strerror(errno)); exit(-1); } fd = accept(fd, (struct sockaddr*) &client, &len); if ( fd < 0 ) { printf("can't accept: %s\n", strerror(errno)); exit(-1); } bc = bro_conn_new_socket(fd, BRO_CFLAG_ALWAYS_QUEUE); if ( ! bc ) { printf("can't create connection form fd\n"); exit(-1); } return bc; } int main(int argc, char **argv) { int opt, port, use_record = 0, use_compact = 0, debugging = 0, listen = 0; BroConn *bc; extern char *optarg; extern int optind; char hostname[512]; int fd = -1; bro_init(NULL); host_str = host_default; port_str = port_default; bro_debug_calltrace = 0; bro_debug_messages = 0; while ( (opt = getopt(argc, argv, "Cc:p:dh?lr")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; case 'l': listen = 1; break; case 'h': case '?': usage(); case 'c': count = strtol(optarg, NULL, 0); if (errno == ERANGE || count < 1) { printf("Please provide an integer to -c.\n"); exit(-1); } break; case 'p': port_str = optarg; break; case 'r': use_record = 1; break; case 'C': use_compact = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) host_str = argv[0]; /* if (! (host = gethostbyname(host_str)) || ! (host->h_addr_list[0])) { printf("Could not resolve host %s\n", host_str); exit(-1); } */ port = strtol(port_str, NULL, 0); if (errno == ERANGE) { printf("Please provide a port number with -p.\n"); exit(-1); } snprintf(hostname, 512, "%s:%s", host_str, port_str); if ( listen ) bc = start_listen(port); /* Connect to Bro */ else if (! (bc = bro_conn_new_str(hostname, BRO_CFLAG_RECONNECT | BRO_CFLAG_ALWAYS_QUEUE))) { printf("Could not get Bro connection handle.\n"); exit(-1); } /* Request "pong" events, and have bro_pong called when they * arrive. The callback mechanism automatically figures out * the number of arguments and invokes the callback accordingly. * Use record-based callback if -r option was given, and compact * argument passing if -C was provided. */ if (use_compact) { if (use_record) bro_event_registry_add_compact(bc, "pong", (BroCompactEventFunc) bro_pong_compact_record, NULL); else bro_event_registry_add_compact(bc, "pong", (BroCompactEventFunc) bro_pong_compact, NULL); } else { if (use_record) bro_event_registry_add(bc, "pong", (BroEventFunc) bro_pong_record, NULL); else bro_event_registry_add(bc, "pong", (BroEventFunc) bro_pong, NULL); } if (! bro_conn_connect(bc)) { printf("Could not connect to Bro at %s:%s.\n", host_str, port_str); exit(-1); } /* Enter pinging loop */ for ( ; ; ) { BroEvent *ev; bro_conn_process_input(bc); if (count > 0 && seq == count) break; /* Create empty "ping" event */ if ( (ev = bro_event_new("ping"))) { double timestamp = bro_util_current_time(); if (use_record) { /* Create a record with the sequence number as first * element of type counter, and the second element the * current time: */ BroRecord *rec = bro_record_new(); bro_record_add_val(rec, "seq", BRO_TYPE_COUNT, NULL, &seq); bro_record_add_val(rec, "src_time", BRO_TYPE_TIME, NULL, ×tamp); bro_event_add_val(ev, BRO_TYPE_RECORD, NULL, rec); bro_record_free(rec); } else { /* Add a timestamp to it: */ bro_event_add_val(ev, BRO_TYPE_TIME, NULL, ×tamp); /* Add the sequence counter: */ bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, &seq); } seq++; /* Ship it -- sends it if possible, queues it otherwise */ bro_event_send(bc, ev); bro_event_free(ev); } #ifdef __MINGW32__ sleep(1000); #else sleep(1); #endif } /* Disconnect from Bro and release state. */ bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/test/broccoli-vectors.bro0000664002342100234210000000162512523041064021453 0ustar johannajohanna@load frameworks/communication/listen redef Communication::nodes += { ["vectors"] = [$host=127.0.0.1, $connect=F, $ssl=F, $events=/broccoli_.*/] }; event bro_vector(v: vector of string) { print fmt("bro_vector(%s)", v); } global cnt = 0; event broccoli_vector(v: vector of string) { # TODO: broccoli can't produce events w/ vector arguments print fmt("broccoli_vector(%s)", v); } event broccoli_vector_element(idx: count, ele: string) { print fmt("broccoli_vector_element(%s, %s)", idx, ele); cnt = cnt + 1; if ( cnt == 10 ) terminate(); } event broccoli_string(s: string) { print fmt("broccoli_string(%s)", s); } event remote_connection_handshake_done(p: event_peer) { print "handshake done with peer"; local v1: vector of string = ["a", "b", "c", "d", "e"]; local v2: vector of string = ["one", "two", "three"]; event bro_vector(v1); event bro_vector(v2); } broccoli-1.97-minimal/test/CMakeLists.txt0000664002342100234210000000172512523041064020231 0ustar johannajohannainclude_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/../src) add_executable(broping broping.c) target_link_libraries(broping ${Broccoli_LIBRARY}) add_executable(broconn broconn.c) target_link_libraries(broconn ${Broccoli_LIBRARY}) add_executable(brohose brohose.c) target_link_libraries(brohose ${Broccoli_LIBRARY}) add_executable(broconftest broconftest.c) target_link_libraries(broconftest ${Broccoli_LIBRARY}) add_executable(broenum broenum.c) target_link_libraries(broenum ${Broccoli_LIBRARY}) if (BRO_PCAP_SUPPORT) add_executable(brosendpackets brosendpackets.c) target_link_libraries(brosendpackets ${Broccoli_LIBRARY} ${PCAP_LIBRARY}) endif() add_executable(brotable brotable.c) target_link_libraries(brotable ${Broccoli_LIBRARY}) add_executable(broccoli-v6addrs broccoli-v6addrs.c) target_link_libraries(broccoli-v6addrs ${Broccoli_LIBRARY}) add_executable(broccoli-vectors broccoli-vectors.c) target_link_libraries(broccoli-vectors ${Broccoli_LIBRARY}) broccoli-1.97-minimal/test/broccoli-v6addrs.c0000664002342100234210000000671512523041064021004 0ustar johannajohanna#include #include #include #include #include #include #include #include #include #include void bro_addr_cb(BroConn* bc, void* user_data, BroAddr* a) { char addr[INET6_ADDRSTRLEN]; if ( bro_util_is_v4_addr(a) ) inet_ntop(AF_INET, a->addr + 3, addr, INET6_ADDRSTRLEN); else inet_ntop(AF_INET6, a->addr, addr, INET6_ADDRSTRLEN); printf("Received bro_addr(%s)\n", addr); BroEvent* event; event = bro_event_new("broccoli_addr"); bro_event_add_val(event, BRO_TYPE_IPADDR, 0, a); bro_event_send(bc, event); bro_event_free(event); } void bro_subnet_cb(BroConn* bc, void* user_data, BroSubnet* s) { char addr[INET6_ADDRSTRLEN]; if ( bro_util_is_v4_addr(&s->sn_net) ) inet_ntop(AF_INET, s->sn_net.addr + 3, addr, INET6_ADDRSTRLEN); else inet_ntop(AF_INET6, s->sn_net.addr, addr, INET6_ADDRSTRLEN); printf("Received bro_subnet(%s/%"PRIu32")\n", addr, s->sn_width); BroEvent* event; event = bro_event_new("broccoli_subnet"); bro_event_add_val(event, BRO_TYPE_SUBNET, 0, s); bro_event_send(bc, event); bro_event_free(event); } static void usage() { printf("broccoli-v6addrs - send/recv events w/ IPv6 address args to Bro.\n" "USAGE: broccoli-v6addrs [-h|-?] [-4|-6] [-p port] host\n"); exit(0); } int main(int argc, char** argv) { int opt, port, ipv4_host = 0, ipv6_host = 0; extern char* optarg; extern int optind; BroConn* bc; const char* host_str = "localhost"; const char* port_str = "47757"; char hostname[512]; struct in_addr in4; struct in6_addr in6; while ( (opt = getopt(argc, argv, "?h46p:")) != -1 ) { switch ( opt ) { case '4': ipv4_host = 1; break; case '6': ipv6_host = 1; break; case 'p': port_str = optarg; break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if ( argc > 0 ) host_str = argv[0]; snprintf(hostname, 512, "%s:%s", host_str, port_str); port = strtol(port_str, 0, 0); if ( errno == ERANGE ) { fprintf(stderr, "invalid port string: %s\n", port_str); return 1; } bro_init(0); if ( ipv4_host ) { if ( inet_pton(AF_INET, host_str, &in4) <= 0 ) { fprintf(stderr, "invalid IPv4 address: %s\n", host_str); return 1; } if ( ! (bc = bro_conn_new(&in4, htons(port), BRO_CFLAG_NONE)) ) { fprintf(stderr, "bro_conn_new IPv4 failed for %s\n", hostname); return 1; } } else if ( ipv6_host ) { if ( inet_pton(AF_INET6, host_str, &in6) <= 0 ) { fprintf(stderr, "invalid IPv6 address: %s\n", host_str); return 1; } if ( ! (bc = bro_conn_new6(&in6, htons(port), BRO_CFLAG_NONE)) ) { fprintf(stderr, "bro_conn_new IPv6 failed for %s\n", hostname); return 1; } } else if ( ! (bc = bro_conn_new_str(hostname, BRO_CFLAG_NONE)) ) { fprintf(stderr, "bro_conn_new_str failed for %s\n", hostname); return 1; } bro_event_registry_add(bc, "bro_addr", (BroEventFunc)bro_addr_cb, 0); bro_event_registry_add(bc, "bro_subnet", (BroEventFunc)bro_subnet_cb, 0); if ( ! bro_conn_connect(bc) ) { fprintf(stderr, "failed to connect to %s\n", hostname); return 1; } printf("Connected to Bro instance at: %s\n", hostname); int fd = bro_conn_get_fd(bc); fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); struct timeval to; to.tv_sec = 3; to.tv_usec = 0; while ( select(fd+1, &fds, 0, 0, &to) > 0 ) bro_conn_process_input(bc); printf("Terminating\n"); bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/test/broping.bro0000664002342100234210000000202712523041064017631 0ustar johannajohanna@load frameworks/communication/listen # Let's make sure we use the same port no matter whether we use encryption or not: redef Communication::listen_port = 47758/tcp; # Redef this to T if you want to use SSL. redef Communication::listen_ssl = F; # Set the SSL certificates being used to something real if you are using encryption. #redef ssl_ca_certificate = "/ca_cert.pem"; #redef ssl_private_key = "/bro.pem"; global ping_log = open_log_file("ping"); global ping: event(src_time: time, seq: count); global pong: event(src_time: time, dst_time: time, seq: count); redef Communication::nodes += { ["broping"] = [$host = 127.0.0.1, $events = /ping/, $connect=F, $ssl=F] }; event ping(src_time: time, seq: count) { event pong(src_time, current_time(), seq); } event pong(src_time: time, dst_time: time, seq: count) { print ping_log, fmt("ping received, seq %d, %f at src, %f at dest, one-way: %f", seq, src_time, dst_time, dst_time-src_time); } broccoli-1.97-minimal/test/broenum.bro0000664002342100234210000000127212523041064017641 0ustar johannajohanna@load frameworks/communication/listen # Let's make sure we use the same port no matter whether we use encryption or not: redef Communication::listen_port = 47758/tcp; # Redef this to T if you want to use SSL. redef Communication::listen_ssl = F; # Set the SSL certificates being used to something real if you are using encryption. #redef ssl_ca_certificate = "/ca_cert.pem"; #redef ssl_private_key = "/bro.pem"; module enumtest; type enumtype: enum { ENUM1, ENUM2, ENUM3, ENUM4 }; redef Communication::nodes += { ["broenum"] = [$host = 127.0.0.1, $events = /enumtest/, $connect=F, $ssl=F] }; event enumtest(e: enumtype) { print fmt("Received enum val %d/%s", e, e); } broccoli-1.97-minimal/test/broccoli-v6addrs.bro0000664002342100234210000000150712523041064021336 0ustar johannajohanna@load frameworks/communication/listen redef Communication::nodes += { ["v6addrs-over-v6"] = [$host=[::1], $connect=F, $ssl=F, $events=/broccoli_.*/], ["v6addrs-over-v4"] = [$host=127.0.0.1, $connect=F, $ssl=F, $events=/broccoli_.*/] }; event bro_addr(a: addr) { print fmt("bro_addr(%s)", a); } event bro_subnet(s: subnet) { print fmt("bro_subnet(%s)", s); } event broccoli_addr(a: addr) { print fmt("broccoli_addr(%s)", a); } global cnt = 0; event broccoli_subnet(s: subnet) { print fmt("broccoli_subnet(%s)", s); cnt = cnt + 1; if ( cnt == 2 ) terminate(); } event remote_connection_handshake_done(p: event_peer) { print "handshake done with peer"; event bro_addr(1.2.3.4); event bro_subnet(10.0.0.0/16); event bro_addr([2607:f8b0:4009:802::1014]); event bro_subnet([2607:f8b0:4009:802::1014]/32); } broccoli-1.97-minimal/test/broenum.c0000664002342100234210000000761312523041064017306 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif char *host_default = "127.0.0.1"; char *port_default = "47758"; char *host_str; char *port_str; char *type = "enumtest::enumtype"; static void usage(void) { printf("broenum - sends enum vals to a Bro node, printing the corresponding\n" "string value on the Bro side.\n" "USAGE: broping [-h|-?] [-d] [-p port] [-t type] [-n num] host\n"); exit(0); } int main(int argc, char **argv) { int opt, port, debugging = 0; BroConn *bc; BroEvent *ev; extern char *optarg; extern int optind; char hostname[512]; int enumval; bro_init(NULL); host_str = host_default; port_str = port_default; bro_debug_calltrace = 0; bro_debug_messages = 0; while ( (opt = getopt(argc, argv, "t:n:p:dh?")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; case 'h': case '?': usage(); case 't': type = optarg; break; case 'n': enumval = strtol(optarg, NULL, 0); if (errno == ERANGE) { printf("Please provide an integer to -n.\n"); exit(-1); } break; case 'p': port_str = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) host_str = argv[0]; port = strtol(port_str, NULL, 0); if (errno == ERANGE) { printf("Please provide a port number with -p.\n"); exit(-1); } if (!type) usage(); printf("Sending enum val %i to remote peer.\n", enumval); snprintf(hostname, 512, "%s:%s", host_str, port_str); /* Connect to Bro */ if (! (bc = bro_conn_new_str(hostname, BRO_CFLAG_NONE))) { printf("Could not get Bro connection handle.\n"); exit(-1); } if (! bro_conn_connect(bc)) { printf("Could not connect to Bro at %s:%s.\n", host_str, port_str); exit(-1); } /* Create empty "ping" event */ if (! (ev = bro_event_new("enumtest"))) { printf("Couldn't create event structure.\n"); exit(-1); } /* We send the given number as an instance of an enum type defined * in the remote Bro's policy: */ bro_event_add_val(ev, BRO_TYPE_ENUM, type, &enumval); /* Ship it -- sends it if possible, queues it otherwise */ bro_event_send(bc, ev); bro_event_free(ev); /* Make sure we sent the thing. */ while (bro_event_queue_length(bc) > 0) bro_event_queue_flush(bc); /* Disconnect from Bro and release state. */ bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/test/broccoli-vectors.c0000664002342100234210000000605212523041064021112 0ustar johannajohanna#include #include #include #include #include #include #include #include #include #include static char* bro_string_to_c_str(const BroString* str) { uint32 len = bro_string_get_length(str); char* cstr = (char*) calloc(len + 1, sizeof(char)); if ( ! cstr ) return 0; strncpy(cstr, (const char*) bro_string_get_data(str), len); return cstr; } static void bro_vector_cb(BroConn* bc, void* user_data, BroVector* v) { BroString str; int i; printf("Received bro_vector\n"); for ( i = 0; i < bro_vector_get_length(v); ++i ) { char* e = bro_string_to_c_str(bro_vector_get_nth_val(v, i, 0)); printf(" %d: %s\n", i, e); free(e); } bro_string_set(&str, "additional element"); bro_vector_add_val(v, BRO_TYPE_STRING, 0, &str); BroEvent* event; /* // Broccoli can't currently produce events w/ vector args, // see __bro_val_assign in bro_val.c event = bro_event_new("broccoli_vector"); bro_event_add_val(event, BRO_TYPE_VECTOR, 0, v); bro_event_send(bc, event); bro_event_free(event); */ for ( i = 0; i < bro_vector_get_length(v); ++i ) { event = bro_event_new("broccoli_vector_element"); uint64 idx = i; bro_event_add_val(event, BRO_TYPE_COUNT, 0, &idx); bro_event_add_val(event, BRO_TYPE_STRING, 0, bro_vector_get_nth_val(v, i, 0)); bro_event_send(bc, event); bro_event_free(event); } bro_string_cleanup(&str); } static void usage() { printf("broccoli-vectors - send/recv events w/ vector args to Bro.\n" "USAGE: broccoli-vectors [-h|-?] [-d] [-p port] host\n"); exit(0); } int main(int argc, char** argv) { int opt, port; extern char* optarg; extern int optind; BroConn* bc; const char* host_str = "localhost"; const char* port_str = "47757"; char hostname[512]; struct in_addr in4; struct in6_addr in6; bro_debug_messages = 0; while ( (opt = getopt(argc, argv, "?hdp:")) != -1 ) { switch ( opt ) { case 'p': port_str = optarg; break; case 'd': bro_debug_messages = 1; break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if ( argc > 0 ) host_str = argv[0]; snprintf(hostname, 512, "%s:%s", host_str, port_str); port = strtol(port_str, 0, 0); if ( errno == ERANGE ) { fprintf(stderr, "invalid port string: %s\n", port_str); return 1; } bro_init(0); if ( ! (bc = bro_conn_new_str(hostname, BRO_CFLAG_NONE)) ) { fprintf(stderr, "bro_conn_new_str failed for %s\n", hostname); return 1; } bro_event_registry_add(bc, "bro_vector", (BroEventFunc)&bro_vector_cb, 0); if ( ! bro_conn_connect(bc) ) { fprintf(stderr, "failed to connect to %s\n", hostname); return 1; } printf("Connected to Bro instance at: %s\n", hostname); int fd = bro_conn_get_fd(bc); fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); struct timeval to; to.tv_sec = 3; to.tv_usec = 0; while ( select(fd+1, &fds, 0, 0, &to) > 0 ) bro_conn_process_input(bc); printf("Terminating\n"); bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/test/dummysensor.c0000664002342100234210000000322312523041064020215 0ustar johannajohanna#include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif char *ip_default = "127.0.0.1"; char *port_default = "47756"; int main(int argc, char **argv) { char *ip_str = ip_default; char *port_str = port_default; int port; struct in_addr ipaddr; BroConn *bc; BroEvent *ev; int i; if (argc >= 2) ip_str = argv[1]; if (argc >= 3) port_str = argv[2]; if (inet_pton(AF_INET, ip_str, &ipaddr) <= 0) { printf("Please provide an IP address to contact as first argument.\n"); exit(-1); } port = strtol(port_str, NULL, 0); if (errno == ERANGE) { printf("Please provide a port number as second argument.\n"); exit(-1); } bro_init(NULL); printf("Opening connection.\n"); if (! (bc = bro_connect_remote(0x0000, &ipaddr, port))) { printf("Couldn't connect.\n"); exit(-1); } sleep(1); bro_conn_process_input(bc); sleep(5); bro_conn_process_input(bc); /* if ( (ev = bro_event_new("bar"))) { bro_event_add_string(ev, "hello world"); if (bro_event_send(bc, ev)) printf("Bro test event sent.\n"); else printf("Bro test event queued.\n"); } if ( (ev = bro_event_new("foo"))) { bro_event_add_string(ev, "hello world"); if (bro_event_send(bc, ev)) printf("Bro test event sent.\n"); else printf("Bro test event queued.\n"); } */ sleep(2); printf("Disconnecting.\n"); bro_disconnect(bc); return 0; } broccoli-1.97-minimal/test/brohose.bro0000664002342100234210000000116712523041064017636 0ustar johannajohanna@load frameworks/communication/listen # Let's make sure we use the same port no matter whether we use encryption or not: redef Communication::listen_port = 47758/tcp; # Redef this to T if you want to use SSL. redef Communication::listen_ssl = F; # Set the SSL certificates being used to something real if you are using encryption. #redef ssl_ca_certificate = "/ca_cert.pem"; #redef ssl_private_key = "/bro.pem"; redef Communication::nodes += { ["brohose"] = [$host = 127.0.0.1, $events = /brohose/, $connect=F, $ssl=F] }; event brohose(id: string) { print brohose_log, fmt("%s %s", id, current_time()); } broccoli-1.97-minimal/broccoli.conf0000664002342100234210000000434012523041064017151 0ustar johannajohanna# This is the Broccoli system-wide configuration file. # # The config file is structured into sections. The settings in each # section are called a domain. Each domain is identified as follows: # # [ name ] # # where "name" is a single word consisting of alphanumeric letters # without whitespace. The beginning of the document can contain # additional settings, these comprise the default domain. It will be # used when bro_conf_set_domain() is never used. # # Entries are of the form , where the identifier # is a sequence of letters, and value can be a string (including # whitespace), and floating point or integer numbers. Comments start # with a "#" and go to the end of the line. For boolean values, you # may also use "yes", "on", "true", "no", "off", or "false". # Strings may contain whitespace, but need to be surrounded by # double quotes '"'. # # You can name identifiers any way you like, but to keep things # organized we recommend a hierarchical structure. Case matters. # # Examples: # # Foo/PeerName mybro.securesite.com # Foo/PortNum 123 # Bar/SomeFloat 1.23443543 # Bar/SomeLongStr "Hello World" # # Debugging output # ---------------- #/broccoli/debug_messages yes #/broccoli/debug_calltrace yes # Encryption setup # ---------------- # # In order to configure encrypted communications, you have to point # these two entries to this agent's certificate + private key and # the trusted CA's certificate, respectively. You can optionally # store the passphrase for this agent's private key in the config # file as well, but you should obviously only do so when the config # file has appropriate access restrictions. Check the manual for # details. # # use_ssl is the main switch to control whether the SSL settings # are used (yes/on/1) or not (no/false/0). When use_ssl is not # present, SSL is attempted if certificates are configured, other- # wise cleartext connections are used. When it is present and enabled, # then setup is aborted if certificates are not found. In no case # does an SSL setup ever fall back to a cleartext one. # #/broccoli/use_ssl yes #/broccoli/ca_cert /ca_cert.pem #/broccoli/host_cert /bro_cert.pem #/broccoli/host_pass foo # Your settings below # ------------------- broccoli-1.97-minimal/broccoli-config.in0000775002342100234210000000234012523041064020076 0ustar johannajohanna#!/bin/sh buildinfo="@BUILDINFO@" prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} exec_prefix_set=no usage="\ Usage: broccoli-config [--build] [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags] [--config]" if test $# -eq 0; then echo "${usage}" 1>&2 exit 1 fi while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --build) echo $buildinfo ;; --prefix=*) prefix=$optarg if test $exec_prefix_set = no ; then exec_prefix=$optarg fi ;; --prefix) echo $prefix ;; --exec-prefix=*) exec_prefix=$optarg exec_prefix_set=yes ;; --exec-prefix) echo $exec_prefix ;; --version) echo @VERSION@ ;; --cflags) if test $prefix/include != /usr/include ; then includes=-I$prefix/include fi echo $includes -I$prefix/include @BRO_CFLAGSADD@ -DBROCCOLI ;; --libs) libdirs=-L@INSTALL_LIB_DIR@ echo $libdirs -lbroccoli @BRO_LIBADD@ ;; --config) echo @BRO_SYSCONF_FILE@ ;; *) echo "${usage}" 1>&2 exit 1 ;; esac shift done exit 0 broccoli-1.97-minimal/config-file.h.in0000664002342100234210000000011512523041064017442 0ustar johannajohanna/* Location of config file */ #define BRO_SYSCONF_FILE "@BRO_SYSCONF_FILE@" broccoli-1.97-minimal/README0000664002342100234210000001151712523041064015372 0ustar johannajohanna.. -*- mode: rst-mode -*- .. .. Version number is filled in automatically. .. |version| replace:: 1.97 =============================================== Broccoli: The Bro Client Communications Library =============================================== .. rst-class:: opening Broccoli is the "Bro client communications library". It allows you to create client sensors for the Bro intrusion detection system. Broccoli can speak a good subset of the Bro communication protocol, in particular, it can receive Bro IDs, send and receive Bro events, and send and receive event requests to/from peering Bros. You can currently create and receive values of pure types like integers, counters, timestamps, IP addresses, port numbers, booleans, and strings. Download -------- You can find the latest Broccoli release for download at http://www.bro.org/download. Broccoli's git repository is located at `git://git.bro.org/broccoli `_. You can browse the repository `here `_. This document describes Broccoli |version|. See the ``CHANGES`` file for version history. Installation ------------ The Broccoli library has been tested on Linux, the BSDs, and Solaris. A Windows build has not currently been tried but is part of our future plans. If you succeed in building Broccoli on other platforms, let us know! Prerequisites ------------- Broccoli relies on the following libraries and tools, which need to be installed before you begin: Flex (Fast Lexical Analyzer) Flex is already installed on most systems, so with luck you can skip having to install it yourself. Bison (GNU Parser Generator) This comes with many systems, but if you get errors compiling parse.y, you will need to install it. OpenSSL headers and libraries For encrypted communication. These are likely installed, though some platforms may require installation of a 'devel' package for the headers. CMake 2.6.3 or greater CMake is a cross-platform, open-source build system, typically not installed by default. See http://www.cmake.org for more information regarding CMake and the installation steps below for how to use it to build this distribution. CMake generates native Makefiles that depend on GNU Make by default. Broccoli can also make use of some optional libraries if they are found at installation time: Libpcap headers and libraries Network traffic capture library Installation ------------ To build and install into ``/usr/local``:: ./configure make make install This will perform an out-of-source build into the build directory using the default build options and then install libraries into ``/usr/local/lib``. You can specify a different installation directory with:: ./configure --prefix= Or control the python bindings install destination more precisely with:: ./configure --python-install-dir= Run ``./configure --help`` for more options. Further notable configure options: ``--enable-debug`` This one enables lots of debugging output. Be sure to disable this when using the library in a production environment! The output could easily end up in undersired places when the stdout of the program you've instrumented is used in other ways. ``--with-configfile=FILE`` Broccoli can read key/value pairs from a config file. By default it is located in the etc directory of the installation root (exception: when using ``--prefix=/usr``, ``/etc`` is used instead of /usr/etc). The default config file name is broccoli.conf. Using ``--with-configfile``, you can override the location and name of the config file. To use the library in other programs & configure scripts, use the ``broccoli-config`` script. It gives you the necessary configuration flags and linker flags for your system, see ``--cflags`` and ``--libs``. The API is contained in broccoli.h and pretty well documented. A few usage examples can be found in the test directory, in particular, the ``broping`` tool can be used to test event transmission and reception. Have a look at the policy file ``broping.bro`` for the events that need to be defined at the peering Bro. Try ``broping -h`` for a look at the available options. Broccoli knows two kinds of version numbers: the release version number (as in "broccoli-x.y.tar.gz", or as shipped with Bro) and the shared library API version number (as in libbroccoli.so.3.0.0). The former relates to changes in the tree, the latter to compatibility changes in the API. Comments, feedback and patches are appreciated; please check the `Bro website `_. Documentation ------------- Please see the `Broccoli User Manual <./broccoli-manual.html>`_ and the `Broccoli API Reference <../../broccoli-api/index.html>`_. broccoli-1.97-minimal/btest0000664002342100234210000000000012523041064015537 0ustar johannajohannabroccoli-1.97-minimal/configure0000775002342100234210000002032212523041064016413 0ustar johannajohanna#!/bin/sh # Convenience wrapper for easily viewing/setting options that # the project's CMake scripts will recognize set -e command="$0 $*" # check for `cmake` command type cmake > /dev/null 2>&1 || { echo "\ This package requires CMake, please install it first, then you may use this configure script to access CMake equivalent functionality.\ " >&2; exit 1; } usage="\ Usage: $0 [OPTION]... [VAR=VALUE]... Build Directory: --builddir=DIR place build files in directory [build] Installation Directories: --prefix=PREFIX installation directory [/usr/local] --conf-files-dir=DIR config files installation directory [PREFIX/etc] --python-install-dir the desired installation directory for broccoli python bindings (if present) [PREFIX/lib/python] --libdir=DIR installation directory for static and dynamic libraries [PREFIX/lib] Optional Features: --enable-debug compile in debugging mode --enable-ruby build ruby bindings for broccoli --disable-shared don't build shared libraries [default=no] (no effect on broccoli bindings) --disable-static don't build static libraries [default=no] --disable-python don't try to build python bindings for broccoli --disable-packets Do not support tx/rx of pcap packets --with-configfile=FILE use config file at location instead of the default broccoli.conf Required Packages in Non-Standard Locations: --with-openssl=PATH path to OpenSSL install root --with-flex=PATH path to flex executable --with-bison=PATH path to bison executable Optional Packages in Non-Standard Locations: --with-pcap=PATH path to libpcap install root --with-python=PATH path to Python interpreter --with-python-lib=PATH path to Python library --with-python-inc=PATH path to Python headers --with-ruby=PATH path to Ruby interpreter --with-ruby-lib=PATH path to Ruby library --with-ruby-inc=PATH path to Ruby headers --with-swig=PATH path to SWIG executable Packaging Options (for developers): --binary-package toggle special logic for binary packaging --ignore-dirs=PATHS paths to ignore when creating source package (semicolon delimited and quoted when multiple) --pkg-name-prefix=NAME use the given name as the package prefix instead of the default CMake project name --osx-sysroot=PATH path to the OS X SDK to compile against --osx-min-version=VER minimum OS X version (the deployment target) Influential Environment Variables (only on first invocation per build directory): CC C compiler command CFLAGS C compiler flags CXX C++ compiler command CXXFLAGS C++ compiler flags " sourcedir="$( cd "$( dirname "$0" )" && pwd )" # Function to append a CMake cache entry definition to the # CMakeCacheEntries variable # $1 is the cache entry variable name # $2 is the cache entry variable type # $3 is the cache entry variable value append_cache_entry () { CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3" } # set defaults builddir=build prefix=/usr/local CMakeCacheEntries="" append_cache_entry CMAKE_INSTALL_PREFIX PATH $prefix append_cache_entry PY_MOD_INSTALL_DIR PATH $prefix/lib/python append_cache_entry INSTALL_LIB_DIR PATH $prefix/lib append_cache_entry ENABLE_DEBUG BOOL false append_cache_entry BRO_PCAP_SUPPORT BOOL true append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING append_cache_entry DISABLE_RUBY_BINDINGS BOOL true # parse arguments while [ $# -ne 0 ]; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case "$1" in --help|-h) echo "${usage}" 1>&2 exit 1 ;; --builddir=*) builddir=$optarg ;; --prefix=*) prefix=$optarg append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg append_cache_entry PY_MOD_INSTALL_DIR PATH $optarg/lib/python append_cache_entry INSTALL_LIB_DIR PATH $optarg/lib ;; --libdir=*) libdir=$optarg append_cache_entry INSTALL_LIB_DIR PATH $optarg ;; --conf-files-dir=*) append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg user_set_conffilesdir="true" ;; --enable-debug) append_cache_entry ENABLE_DEBUG BOOL true ;; --disable-shared) append_cache_entry ENABLE_SHARED BOOL false ;; --disable-static) append_cache_entry ENABLE_STATIC BOOL false ;; --disable-python) append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true CMakeCacheEntries=`echo $CMakeCacheEntries | sed 's/-D PY_MOD_INSTALL_DIR:PATH=[^ ]* //g'` ;; --enable-ruby) append_cache_entry DISABLE_RUBY_BINDINGS BOOL false ;; --disable-packets) append_cache_entry BRO_PCAP_SUPPORT BOOL false ;; --with-configfile=*) append_cache_entry BRO_SYSCONF_FILE FILEPATH $optarg ;; --python-install-dir=*) append_cache_entry PY_MOD_INSTALL_DIR PATH $optarg ;; --with-openssl=*) append_cache_entry OpenSSL_ROOT_DIR PATH $optarg ;; --with-flex=*) append_cache_entry FLEX_EXECUTABLE PATH $optarg ;; --with-bison=*) append_cache_entry BISON_EXECUTABLE PATH $optarg ;; --with-pcap=*) append_cache_entry PCAP_ROOT_DIR PATH $optarg ;; --with-python=*) append_cache_entry PYTHON_EXECUTABLE PATH $optarg ;; --with-python-lib=*) append_cache_entry PYTHON_LIBRARY PATH $optarg ;; --with-python-inc=*) append_cache_entry PYTHON_INCLUDE_DIR PATH $optarg append_cache_entry PYTHON_INCLUDE_PATH PATH $optarg ;; --with-ruby=*) append_cache_entry RUBY_EXECUTABLE PATH $optarg ;; --with-ruby-lib=*) append_cache_entry RUBY_LIBRARY PATH $optarg ;; --with-ruby-inc=*) append_cache_entry RUBY_INCLUDE_DIR PATH $optarg append_cache_entry RUBY_INCLUDE_PATH PATH $optarg ;; --with-swig=*) append_cache_entry SWIG_EXECUTABLE PATH $optarg ;; --binary-package) append_cache_entry BINARY_PACKAGING_MODE BOOL true ;; --ignore-dirs=*) append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING $optarg ;; --pkg-name-prefix=*) append_cache_entry PACKAGE_NAME_PREFIX STRING $optarg ;; --osx-sysroot=*) append_cache_entry CMAKE_OSX_SYSROOT PATH $optarg ;; --osx-min-version=*) append_cache_entry CMAKE_OSX_DEPLOYMENT_TARGET STRING $optarg ;; *) echo "Invalid option '$1'. Try $0 --help to see available options." exit 1 ;; esac shift done if [ "$user_set_conffilesdir" != "true" ]; then append_cache_entry BRO_ETC_INSTALL_DIR PATH $prefix/etc fi if [ -d $builddir ]; then # If build directory exists, check if it has a CMake cache if [ -f $builddir/CMakeCache.txt ]; then # If the CMake cache exists, delete it so that this configuration # is not tainted by a previous one rm -f $builddir/CMakeCache.txt fi else # Create build directory mkdir -p $builddir fi echo "Build Directory : $builddir" echo "Source Directory: $sourcedir" cd $builddir cmake $CMakeCacheEntries $sourcedir echo "# This is the command used to configure this build" > config.status echo $command >> config.status chmod u+x config.status broccoli-1.97-minimal/AUTHORS0000664002342100234210000000014112523041064015551 0ustar johannajohannaChristian Kreibich and various contributors, see ChangeLog for details. broccoli-1.97-minimal/setup.py0000664002342100234210000000000012523041064016205 0ustar johannajohannabroccoli-1.97-minimal/contrib/0000775002342100234210000000000012523041064016145 5ustar johannajohannabroccoli-1.97-minimal/contrib/brosendpkts.c0000664002342100234210000000403712523041064020653 0ustar johannajohanna/* NOTE: This file needs to be cleaned up to build with all * C compilers -- no variable definitions in the middle of * functions, etc. Conditional compilation depending on * whether we're using a Broccoli with or without pcap support * can be done with #ifdef BRO_PCAP_SUPPORT. --ck. */ #include #include #include void usage() { fprintf(stderr, "usage: brosendpkts -r file -b host:port [-t tag]\n"); exit(1); } int main(int argc, char** argv) { char* filename=NULL; char* bro_connection=NULL; char* tag=""; bro_init(NULL); int opt; while ((opt=getopt(argc, argv, "r:b:t:h?")) != -1) { switch(opt) { case 'r': filename=strdup(optarg); break; case 'b': bro_connection=strdup(optarg); break; case 't': tag=strdup(optarg); break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if (filename==NULL || bro_connection==NULL) usage(); BroConn *broccoli_p=bro_conn_new_str(bro_connection, BRO_CFLAG_NONE); if (!broccoli_p) { fprintf(stderr, "can't instantiate connection object\n"); exit(1); } if (! bro_conn_connect(broccoli_p)) { fprintf(stderr, "Bro connection to %s failed\n", bro_connection); exit(1); } printf("connected to Bro %s\n", bro_connection); char pcap_errbuf[PCAP_ERRBUF_SIZE]=""; pcap_t* pcap_p=pcap_open_offline(filename, pcap_errbuf); if (!pcap_p) { fprintf(stderr, "pcap eror: %s\n", pcap_errbuf); exit(1); } bro_conn_set_packet_ctxt(broccoli_p, pcap_datalink(pcap_p)); const uchar* packet_p=NULL; struct pcap_pkthdr pkthdr; int pkt_cnt=0; while ((packet_p=pcap_next(pcap_p, &pkthdr))) { pkt_cnt++; BroPacket* broccoli_packet_p=bro_packet_new(&pkthdr, packet_p, tag); bro_packet_send(broccoli_p, broccoli_packet_p); bro_packet_free(broccoli_packet_p); } printf("sent %d packets\n",pkt_cnt); bro_conn_delete(broccoli_p); printf("connection to Bro %s closed\n", bro_connection); return 0; } broccoli-1.97-minimal/contrib/broclient.cc0000664002342100234210000001542312523041064020442 0ustar johannajohanna#include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif using std::string; using std::vector; using std::cout; using std::cin; using std::cerr; string default_host = "127.0.0.1"; string default_port = "47757"; string host; string port; int count = -1; int seq; void usage(void) { cout << "broclient - sends events with string arguments from stdin to a running Bro\n" "USAGE: broclient [-p port=47757] [host=127.0.0.1]\n" "Input format (each line): event_name type=arg1 type=arg2...\n"; exit(0); } void showtypes(void) { cout << "Legitimate event types are:\n" "string, int, count, double, bool, time, \n" "interval, port, addr, subnet\n\n" "eamples: string=foo, port=23/tcp, addr=10.10.10.10, \n" "and subnet=10.0.0.0/8\n"; exit(0); } void tokenize(const string& str, vector& tokens) { int num_tokens = 0; char delim = '\0'; for ( unsigned int i = 0; i < str.length(); ++i ) { while ( isspace(str[i]) ) ++i; string next_arg; if (str[i] == '"' || str[i] == '\'') { delim = str[i]; ++i; } else delim = '\0'; for ( ; str[i]; ++i ) { if ( delim && str[i] == '\\' && i < str.length() && str[i+1] == delim ) { ++i; next_arg.push_back(str[i]); } else if ( delim && str[i] == delim ) { ++i; break; } else if ( ! delim && isspace(str[i]) ) break; else next_arg.push_back(str[i]); } tokens.push_back(next_arg); } } int main(int argc, char **argv) { int opt, use_record = 0, debugging = 0; BroConn *bc; extern char *optarg; extern int optind; bro_init(NULL); bro_debug_calltrace = 0; bro_debug_messages = 0; host = default_host; port = default_port; while ( (opt = getopt(argc, argv, "p:dh?")) != -1) { switch (opt) { case 'd': debugging++; if (debugging == 1) bro_debug_messages = 1; if (debugging > 1) bro_debug_calltrace = 1; break; case 'h': case '?': usage(); case 'p': port = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) host = argv[0]; /* Connect to Bro */ if (! (bc = bro_conn_new_str( (host + ":" + port).c_str(), BRO_CFLAG_NONE ))) { cerr << "Could not obtain connection handle for Bro at " << host.c_str() << ":" << port.c_str() << "\n"; exit(-1); } cout << "Connecting... \n"; if (! bro_conn_connect(bc)) { cout << "Could not connect to Bro.\n"; exit(-1); } cout << "Handshake Complete \n"; /* Enter pinging loop */ while ( ! cin.eof() ) { string inp; vector tokens; cout << "Calling getline .. \n"; std::getline(cin, inp); tokenize(inp, tokens); if ( tokens.size() == 0 ) continue; BroEvent *ev; cout << "Calling bro_conn_process_input .. \n"; bro_conn_process_input(bc); cout << "Generating Bro event \n"; if ( (ev = bro_event_new(tokens[0].c_str())) ) { for ( unsigned int i = 1; i < tokens.size(); ++i ) { // this is something of a nasty hack, but it does work string tkn,tkn_type,tkn_data; char delim = '='; tkn=tokens[i].c_str(); string::size_type position = tkn.find_first_of("=",0); tkn_type = tkn.substr(0,position); tkn_data = tkn.substr(position+1,tkn.length()); if ( tkn_type == "string" ) { BroString arg; bro_string_init(&arg); bro_string_set(&arg, tkn_data.c_str()); bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &arg); bro_string_cleanup(&arg); } else if ( tkn_type == "int" ) { int bint; bint = atoi(tkn_data.c_str()); bro_event_add_val(ev, BRO_TYPE_INT, NULL, (int*)bint); } else if ( tkn_type == "count" ) { uint32 buint; buint = atoi(tkn_data.c_str()); bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, (uint32*)buint); } else if ( tkn_type == "double" ) { double bdouble; char* end_s; bdouble = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_DOUBLE, NULL, &bdouble); } else if ( tkn_type == "bool" ) { int bbool=0; if ( tkn_data == "T" || tkn_data == "TRUE" || tkn_data == "1" ) bbool = 1; bro_event_add_val(ev, BRO_TYPE_BOOL, NULL, &bbool); } else if ( tkn_type == "time" ) { double btime; char* end_s; btime = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_TIME, NULL, &btime); } else if ( tkn_type == "interval" ) { double binterval; char* end_s; binterval = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_INTERVAL, NULL, &binterval); } else if ( tkn_type == "port" ) { BroPort BP; string port_value; string::size_type port_offset; int broport; //determine protocol type, start with tcp/udp do icmp // later since the 'ports' are not as simple... if ( tkn_data.find("tcp",0) < tkn_data.length() ) BP.port_proto = IPPROTO_TCP; else BP.port_proto = IPPROTO_UDP; // parse out the numeric values port_offset = tkn_data.find_first_of("/",0); port_value = tkn_data.substr(0,port_offset); broport = atoi(port_value.c_str()); BP.port_num = broport; bro_event_add_val(ev, BRO_TYPE_PORT, NULL, &BP); } else if ( tkn_type == "addr" ) { uint32 badd; // badd=htonl((uint32)inet_addr(tkn_data.c_str())); badd=(uint32)inet_addr(tkn_data.c_str()); bro_event_add_val(ev, BRO_TYPE_IPADDR, NULL, &badd); } else if ( tkn_type == "subnet" ) { // this is assuming a string that looks like // "subnet=10.0.0.0/8" BroSubnet BS; string subnet_value; string subnet_width; string::size_type mask_offset; uint32 sn_net, sn_width; //parse out numeric values mask_offset = tkn_data.find_first_of("/",0); subnet_value = tkn_data.substr(0,mask_offset); subnet_width = tkn_data.substr(mask_offset+1,tkn_data.length()); sn_net = (uint32)inet_addr(subnet_value.c_str()); sn_width = (uint32)atol(subnet_width.c_str()); BS.sn_net = sn_net; BS.sn_width = sn_width; bro_event_add_val(ev, BRO_TYPE_SUBNET, NULL, &BS); } else { // there is something wrong here cerr << "unknown data type: " << tkn_type << "\n\n"; bro_event_free(ev); showtypes(); } } /* Ship it -- sends it if possible, queues it otherwise */ cout << "Sending event to Bro \n"; if ( ! bro_event_send(bc, ev) ) cerr << "event could not be sent right away\n"; bro_event_free(ev); } } /* Disconnect from Bro */ bro_conn_delete(bc); return 0; } broccoli-1.97-minimal/contrib/README0000664002342100234210000000060212523041064017023 0ustar johannajohannaThis directory contains code contributed by others, until it's clear where's the best place to put it. Note: given broccoli-config, the generic build command for a Broccoli application is $ -o output `broccoli-config --cflags` \ `broccoli-config --libs` --Christian. ________________________________________________________________________ broccoli-1.97-minimal/contrib/bropipe.cc0000664002342100234210000004037512523041064020125 0ustar johannajohanna// bropipe.cc: pipe version of generic client // 02/04/05 // // to compile: g++ `broccoli-config --cflags` `broccoli-config --libs` -o bropipe bropipe.cc // #include #include #include #include #include #include #include #include #include #include #include #include #include #include "broccoli.h" using std::string; using std::vector; using std::cout; using std::cin; using std::cerr; string default_host = "127.0.0.1"; string default_port = "47757"; string default_input_file = "brocsock"; string default_log_file = "/tmp/bropipe.log"; string conn_str; string host; string port; string input_file; string log_file; int debug; BroConn *bc; // The following are declarations needed for the modp_burl string decoding // functions. They were cribbed from the stringencoders-v3.7.0 source tree. // syc 1/20/09 /** * \file *
 * BFASTURL.c High performance URL encoder/decoder
 * http://code.google.com/p/stringencoders/
 *
 * Copyright © 2006,2007  Nick Galbreath -- nickg [at] modp [dot] com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 *   Neither the name of the modp.com 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This is the standard "new" BSD license:
 * http://www.opensource.org/licenses/bsd-license.php
 * 
*/ static const uint32_t gsHexDecodeMap[256] = { 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 256, 256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256 }; int modp_burl_decode(char* dest, const char* s, int len) { uint32_t d = 0; // used for decoding %XX const uint8_t* src = (const uint8_t*) s; const char* deststart = dest; const uint8_t* srcend = (const uint8_t*)(src + len); const uint8_t* srcendloop = (const uint8_t*)(srcend - 2); while (src < srcendloop) { switch (*src) { case '+': *dest++ = ' '; src++; break; case '%': d = (gsHexDecodeMap[(uint32_t)(*(src + 1))] << 4) | gsHexDecodeMap[(uint32_t)(*(src + 2))]; if (d < 256) { // if one of the hex chars is bad, d >= 256 *dest = (char) d; dest++; src += 3; } else { *dest++ = '%'; src++; } break; default: *dest++ = *src++; } } // handle last two chars // dont decode "%XX" while (src < srcend) { switch (*src) { case '+': *dest++ = ' '; src++; break; default: *dest++ = *src++; } } *dest = '\0'; return dest - deststart; // compute "strlen" of dest. } void usage(void) { cout << "bropipe - sends events with string arguments from file to a\n" " running Bro\n" "USAGE: bropipe [-p port=47757] [-f input] [host=127.0.0.1[:port]] [-d]\n" "Input format (each line): event_name type=arg1 type=arg2...\n"; exit(0); } void showtypes(void) { cout << "Legitimate event types are:\n" " string, urlstring, int, count, double, bool, time, \n" " interval, port, addr, subnet\n\n" " examples: string=foo, port=23/tcp, addr=10.10.10.10, \n" " subnet=10.0.0.0/8\n" " urlstring is a url encoded string type - use this when\n" " whitespace can be found in the strings\n"; exit(0); } void tokenize(const string& str, vector& tokens) { int num_tokens = 0; char delim = '\0'; for ( unsigned int i = 0; i < str.length(); ++i ) { while ( isspace(str[i]) ) ++i; string next_arg; if (str[i] == '"' || str[i] == '\'') { delim = str[i]; ++i; } else delim = '\0'; for ( ; str[i]; ++i ) { if ( delim && str[i] == '\\' && i < str.length() && str[i+1] == delim ) { ++i; next_arg.push_back(str[i]); } else if ( delim && str[i] == delim ) { ++i; break; } else if ( ! delim && isspace(str[i]) ) break; else next_arg.push_back(str[i]); } tokens.push_back(next_arg); } } void ntokenize(const string& str, vector& inText) { int num_tokens = 0; char delim = '\n'; for ( unsigned int i = 0; i < str.length(); ++i ) { while ( isspace(str[i]) ) ++i; string next_arg; if (str[i] == '"' || str[i] == '\'') { delim = str[i]; ++i; } else delim = '\n'; for ( ; str[i]; ++i ) { if ( delim && str[i] == '\\' && i < str.length() && str[i+1] == delim ) { next_arg.push_back(str[i]); ++i; } else if ( delim && str[i] == delim ) { break; } else if ( ! delim && isspace(str[i]) ) break; else next_arg.push_back(str[i]); } inText.push_back(next_arg); } } FILE * open_input_stream() { FILE *fp; if (input_file == "-") { fp = stdin; if (debug) fprintf(stderr, "DEBUG: input is STDIN.\n"); } else { if (debug) fprintf(stderr, "DEBUG: try opening `%s' as input\n", input_file.c_str()); fp = fopen(input_file.c_str(),"r"); if (fp == NULL) { if (debug) fprintf(stderr, "DEBUG: can't open, so creating pipe %s\n", input_file.c_str()); mkfifo(input_file.c_str(), S_IRUSR | S_IRGRP | S_IROTH ); fp = fopen(input_file.c_str(),"r"); if (fp==NULL) fprintf(stderr, "Failed to create pipe %s\n", input_file.c_str()); else if (debug) fprintf(stderr, "DEBUG: created and opened pipe `%s'\n", input_file.c_str()); } } return(fp); } int make_connection() { // now connect to the bro host - on failure, try again three times // the flags here are telling us to block on connect, reconnect in the // event of a connection failure, and queue up events in the event of a // failure to the bro host // // the flags have been modified to allow for connect back and event queuing if ((bc = bro_conn_new_str(conn_str.c_str(), BRO_CFLAG_RECONNECT | BRO_CFLAG_ALWAYS_QUEUE))) { if (debug) fprintf(stderr, "DEBUG: got BroConn handle\n"); } else { fprintf(stderr, "fatal: could not get BroConn handle.\n"); exit(-1); } if (debug) fprintf(stderr, "DEBUG: attempt to connect to %s...", conn_str.c_str()); bro_conn_set_class(bc, "bropipe"); while (!bro_conn_connect (bc)) { fprintf (stderr, "could not connect to Bro at %s:%s.\n", host.c_str (), port.c_str ()); fprintf (stderr, "Will try again in 5 seconds \n"); sleep (5); } if (debug) fprintf(stderr, "DEBUG: connected\n"); return(0); } int main(int argc, char **argv) { int fd,rc,n; int j; int ecount=0; fd_set readfds; char buf[1024]; char *urlstr = NULL; int urlstrsz = 0; struct timeval tv; FILE *fp; int opt, use_record = 0; extern char *optarg; extern int optind; bro_init(NULL); host = default_host + ":" + default_port; input_file = default_input_file; while ( (opt = getopt(argc, argv, "l:f:p:dDh?")) != -1) { switch (opt) { case 'l': log_file = optarg; break; case 'f': input_file = optarg; break; case 'd': debug++; break; case 'D': debug++; debug++; break; case 'h': case '?': usage(); break; case 'p': port = optarg; break; default: usage(); break; } } argc -= optind; argv += optind; if (argc == 1) { host = argv[0]; if (host.find(':') == string::npos) host += ":" + default_port; } if (argc > 1) usage(); // config destination connection string conn_str = host; if (port != "") { conn_str += ":"; conn_str += port; } // open input fp = open_input_stream(); if (fp == NULL) { fprintf(stderr, "fatal: failed to get input stream\n"); return(1); } if (!debug || debug < 2) make_connection(); else if (debug) fprintf(stderr, "DEBUG: not connecting to Bro (debug level >1)\n"); // socket and pipe are set up, now start processing if(debug) fprintf(stderr, "DEBUG: waiting for data on input stream...\n"); while(fgets(buf, sizeof(buf), fp)) { ecount++; string inp; vector inText; //text inputts within the pipe vector tokens; if (debug) fprintf(stderr, "DEBUG: read event #%d: %s", ecount, buf); if(debug >1) continue; inp = buf; ntokenize(inp, inText); BroEvent *ev; bro_conn_process_input(bc); for(j=0;j urlstrsz) { if (urlstr) free( urlstr); urlstr = (char *)malloc( sz); if (urlstr == NULL) { fprintf( stderr,"Could not allocate %d bytes for url conversion buffer\n",sz); return(1); } urlstrsz = sz; } modp_burl_decode(urlstr,tkn_data.c_str(),strlen(tkn_data.c_str())); bro_string_set(&arg,urlstr); bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &arg); bro_string_cleanup(&arg); } else if ( tkn_type == "int" ) { long long bint; char* end_s; bint = strtoll(tkn_data.c_str(), &end_s, 0); bro_event_add_val(ev, BRO_TYPE_INT, NULL, &bint); } else if ( tkn_type == "count" ) { uint64_t buint; char* end_s; buint = strtoull(tkn_data.c_str(), &end_s, 0); bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, &buint); } else if ( tkn_type == "double" ) { double bdouble; char* end_s; bdouble = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_DOUBLE, NULL, &bdouble); } else if ( tkn_type == "bool" ) { int bbool=0; if ( tkn_data == "T" || tkn_data == "TRUE" || tkn_data == "1" ) bbool = 1; bro_event_add_val(ev, BRO_TYPE_BOOL, NULL, &bbool); } else if ( tkn_type == "time" ) { double btime; char* end_s; btime = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_TIME, NULL, &btime); } else if ( tkn_type == "interval" ) { double binterval; char* end_s; binterval = strtod(tkn_data.c_str(),&end_s); bro_event_add_val(ev, BRO_TYPE_INTERVAL, NULL, &binterval); } else if ( tkn_type == "port" ) { BroPort BP; string port_value; string::size_type port_offset; int broport; //determine protocol type, start with tcp/udp do icmp // later since the 'ports' are not as simple... if ( tkn_data.find("tcp",0) Requires: openssl >= 0.9.7a, python-libs, libpcap BuildRequires: cmake >= 2.6.3, openssl-devel >= 0.9.7a, flex, bison, python-devel, swig, libpcap-devel %description Broccoli enables your applications to speak the Bro communication protocol, allowing you to compose, send, request, and receive events. You can register your own event handlers. You can talk to other Broccoli applications or Bro agents -- Bro agents cannot tell whether they are talking to another Bro or a Broccoli application. Communications can be SSL-encrypted. Broccoli turns Bro into a distributed policy-controlled event management system. %prep %setup -q %build ./configure --prefix=%{_prefix} --libdir=%{_libdir} --conf-files-dir=%{_sysconfdir}/bro --python-install-dir=%{python_sitearch} make %{?_smp_mflags} %install rm -rf %{buildroot} make DESTDIR=%{buildroot} install install -m 755 -d %{buildroot}/%{_bindir} %clean rm -rf %{buildroot} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root,-) %doc AUTHORS COPYING README TODO %{_libdir}/lib*.so.* %{_libdir}/libbroccoli.so %{_libdir}/lib*a %{python_sitearch}/_broccoli_intern.so %{python_sitearch}/broccoli.py* %{_prefix}/include/broccoli.h %{_prefix}/bin/bro* /etc/bro/broccoli.conf %changelog * Sun Aug 11 2013 Derek Ditch - Updated severely outdated spec file * Mon Dec 06 2004 Christian Kreibich - Added spec file to tree. broccoli-1.97-minimal/cmake/0000775002342100234210000000000012523041064015565 5ustar johannajohannabroccoli-1.97-minimal/cmake/FindGooglePerftools.cmake0000664002342100234210000000334312523041064022505 0ustar johannajohanna# - Try to find GooglePerftools headers and libraries # # Usage of this module as follows: # # find_package(GooglePerftools) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # GooglePerftools_ROOT_DIR Set this variable to the root installation of # GooglePerftools if the module has problems finding # the proper installation path. # # Variables defined by this module: # # GOOGLEPERFTOOLS_FOUND System has GooglePerftools libs/headers # TCMALLOC_FOUND System has GooglePerftools tcmalloc library # GooglePerftools_LIBRARIES The GooglePerftools libraries # GooglePerftools_LIBRARIES_DEBUG The GooglePerftools libraries for heap checking. # GooglePerftools_INCLUDE_DIR The location of GooglePerftools headers find_path(GooglePerftools_ROOT_DIR NAMES include/google/heap-profiler.h ) find_library(GooglePerftools_LIBRARIES_DEBUG NAMES tcmalloc_and_profiler HINTS ${GooglePerftools_ROOT_DIR}/lib ) find_library(GooglePerftools_LIBRARIES NAMES tcmalloc HINTS ${GooglePerftools_ROOT_DIR}/lib ) find_path(GooglePerftools_INCLUDE_DIR NAMES google/heap-profiler.h HINTS ${GooglePerftools_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GooglePerftools DEFAULT_MSG GooglePerftools_LIBRARIES GooglePerftools_LIBRARIES_DEBUG GooglePerftools_INCLUDE_DIR ) find_package_handle_standard_args(tcmalloc DEFAULT_MSG GooglePerftools_LIBRARIES ) mark_as_advanced( GooglePerftools_ROOT_DIR GooglePerftools_LIBRARIES GooglePerftools_LIBRARIES_DEBUG GooglePerftools_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/MiscTests.cmake0000664002342100234210000000201012523041064020476 0ustar johannajohannainclude(CheckCXXSourceCompiles) include(CheckCSourceCompiles) # This autoconf variable is obsolete; it's portable to assume C89 and signal # handlers returning void set(RETSIGTYPE "void") set(RETSIGVAL "") check_c_source_compiles(" #include #include extern int socket(int, int, int); extern int connect(int, const struct sockaddr *, int); extern int send(int, const void *, int, int); extern int recvfrom(int, void *, int, int, struct sockaddr *, int *); int main() { return 0; } " DO_SOCK_DECL) if (DO_SOCK_DECL) message(STATUS "socket() and friends need explicit declaration") endif () check_cxx_source_compiles(" #include #include extern \"C\" { int openlog(const char* ident, int logopt, int facility); int syslog(int priority, const char* message_fmt, ...); int closelog(); } int main() { return 0; } " SYSLOG_INT) if (SYSLOG_INT) message(STATUS "syslog prototypes need declaration") endif () broccoli-1.97-minimal/cmake/ChangeMacInstallNames.cmake0000664002342100234210000000660212523041064022714 0ustar johannajohanna# Calling this macro with the name of a list variable will modify that # list such that any third party libraries that do not come with a # vanilla Mac OS X system will be replaced by an adjusted library that # has an install_name relative to the location of any executable that # links to it. # # Also, it will schedule the modified libraries for installation in a # 'support_libs' subdirectory of the CMAKE_INSTALL_PREFIX. # # The case of third party libraries depending on other third party # libraries is currently not handled by this macro. # # Ex. # # set(libs /usr/lib/libz.dylib # /usr/lib/libssl.dylib # /usr/local/lib/libmagic.dylib # /usr/local/lib/libGeoIP.dylib # /usr/local/lib/somestaticlib.a) # # include(ChangeMacInstallNames) # ChangeMacInstallNames(libs) # # Should result in ${libs} containing: # /usr/lib/libz.dylib # /usr/lib/libssl.dylib # ${CMAKE_BINARY_DIR}/darwin_support_libs/libmagic.dylib # ${CMAKE_BINARY_DIR}/darwin_support_libs/libGeoIP.dylib # /usr/local/lib/somestaticlib.a # # such that we can now do: # # add_executable(some_exe ${srcs}) # target_link_libraries(some_exe ${libs}) # # Any binary packages created from such a build should be self-contained # and provide working installs on vanilla OS X systems. macro(ChangeMacInstallNames libListVar) if (APPLE) find_program(INSTALL_NAME_TOOL install_name_tool) set(MAC_INSTALL_NAME_DEPS) set(SUPPORT_BIN_DIR ${CMAKE_BINARY_DIR}/darwin_support_libs) set(SUPPORT_INSTALL_DIR support_libs) file(MAKE_DIRECTORY ${SUPPORT_BIN_DIR}) foreach (_lib ${${libListVar}}) # only care about install_name for shared libraries that are # not shipped in Apple's vanilla OS X installs string(REGEX MATCH ^/usr/lib/* apple_provided_lib ${_lib}) string(REGEX MATCH dylib$ is_shared_lib ${_lib}) if (NOT apple_provided_lib AND is_shared_lib) get_filename_component(_libname ${_lib} NAME) set(_adjustedLib ${SUPPORT_BIN_DIR}/${_libname}) set(_tmpLib ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_libname}) # make a tempory copy so we can adjust permissions configure_file(${_lib} ${_tmpLib} COPYONLY) # copy to build directory with correct write permissions file(COPY ${_tmpLib} DESTINATION ${SUPPORT_BIN_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) # remove the old library from the list provided as macro # argument and add the new library with modified install_name list(REMOVE_ITEM ${libListVar} ${_lib}) list(APPEND ${libListVar} ${_adjustedLib}) # update the install target to install the third party libs # with modified install_name install(FILES ${_adjustedLib} DESTINATION ${SUPPORT_INSTALL_DIR}) # perform the install_name change execute_process(COMMAND install_name_tool -id @executable_path/../${SUPPORT_INSTALL_DIR}/${_libname} ${_adjustedLib}) endif () endforeach () endif () endmacro() broccoli-1.97-minimal/cmake/InstallShellScript.cmake0000664002342100234210000000465212523041064022361 0ustar johannajohanna# Schedules a file to be installed by the 'install' target, but first # transformed by configure_file(... @ONLY) as well as by changing the # shell script's hashbang (#!) line to use the absolute path to the # interpreter in the path of the user running ./configure (or CMake equiv.). # # Hashbangs are not transformed when in binary packaging mode because, # if NMI systems are to be used in creating binary packages, that could # result in picking up a python interpreter in a non-standard location for # a given distro. (NMI tends to install non-essential prerequisite packages # in atypical locations). # # _dstdir: absolute path to the directory in which to install the transformed # source file # _srcfile: path relevant to CMAKE_CURRENT_SOURCE_DIR pointing to the shell # script to install # [_dstfilename]: an optional argument for how to (re)name the file as # it's installed inside _dstdir macro(InstallShellScript _dstdir _srcfile) if (NOT "${ARGN}" STREQUAL "") set(_dstfilename ${ARGN}) else () get_filename_component(_dstfilename ${_srcfile} NAME) endif () set(orig_file ${CMAKE_CURRENT_SOURCE_DIR}/${_srcfile}) set(configed_file ${CMAKE_CURRENT_BINARY_DIR}/${_srcfile}) set(dehashbanged_file ${CMAKE_CURRENT_BINARY_DIR}/${_srcfile}.dehashbanged) configure_file(${orig_file} ${configed_file} @ONLY) file(READ ${configed_file} _srclines) file(WRITE ${dehashbanged_file} "") if (NOT BINARY_PACKAGING_MODE) set(_regex "^#![ ]*/usr/bin/env[ ]+([^\n ]*)") string(REGEX MATCH ${_regex} _match ${_srclines}) if (_match) set(_shell ${CMAKE_MATCH_1}) if (${_shell} STREQUAL "python" AND PYTHON_EXECUTABLE) set(${_shell}_interp ${PYTHON_EXECUTABLE}) else () find_program(${_shell}_interp ${_shell}) endif () if (NOT ${_shell}_interp) message(FATAL_ERROR "Absolute path to interpreter '${_shell}' not found, " "failed to configure shell script: ${orig_file}") endif () string(REGEX REPLACE ${_regex} "#!${${_shell}_interp}" _srclines "${_srclines}") endif () endif () file(WRITE ${dehashbanged_file} "${_srclines}") install(PROGRAMS ${dehashbanged_file} DESTINATION ${_dstdir} RENAME ${_dstfilename}) endmacro(InstallShellScript) broccoli-1.97-minimal/cmake/package_preinstall.sh.in0000775002342100234210000000167212523041064022367 0ustar johannajohanna#!/bin/sh # This script is meant to be used by binary packages pre-installation. # Variables between @ symbols are replaced by CMake at configure time. configFiles="@INSTALLED_CONFIG_FILES@" backupNamesFile=/tmp/bro_install_backups # Checks if a config file exists in a default location and makes a backup # so that a modified version is not clobbered backupFile () { origFile="$1" if [ -e ${origFile} ]; then # choose a file suffix that doesn't already exist ver=1 while [ -e ${origFile}.${ver} ]; do ver=$(( ver + 1 )) done backupFile=${origFile}.${ver} cp -p ${origFile} ${backupFile} # the post upgrade script will check whether the installed # config file actually differs from existing version # and delete unnecessary backups echo "${backupFile}" >> ${backupNamesFile} fi } for file in ${configFiles}; do backupFile "${file}" done broccoli-1.97-minimal/cmake/CheckTypes.cmake0000664002342100234210000000223012523041064020626 0ustar johannajohannainclude(CheckTypeSize) check_type_size("long int" SIZEOF_LONG_INT) check_type_size("long long" SIZEOF_LONG_LONG) check_type_size("void *" SIZEOF_VOID_P) # checks existence of ${_type}, and if it does not, sets CMake variable ${_var} # to alternative type, ${_alt_type} macro(CheckType _type _alt_type _var) # don't perform check if we have a result from a previous CMake run if (NOT HAVE_${_var}) check_type_size(${_type} ${_var}) if (NOT ${_var}) set(${_var} ${_alt_type}) else () unset(${_var}) unset(${_var} CACHE) endif () endif () endmacro(CheckType _type _alt_type _var) set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h) CheckType(int32_t int int32_t) CheckType(u_int32_t u_int u_int32_t) CheckType(u_int16_t u_short u_int16_t) CheckType(u_int8_t u_char u_int8_t) set(CMAKE_EXTRA_INCLUDE_FILES) set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) CheckType(socklen_t int socklen_t) set(CMAKE_EXTRA_INCLUDE_FILES) set(CMAKE_EXTRA_INCLUDE_FILES netinet/in.h netinet/ip6.h) check_type_size("struct ip6_opt" IP6_OPT) check_type_size("struct ip6_ext" IP6_EXT) set(CMAKE_EXTRA_INCLUDE_FILES) broccoli-1.97-minimal/cmake/PCAPTests.cmake0000664002342100234210000000353712523041064020345 0ustar johannajohannainclude(CheckFunctionExists) include(CheckSymbolExists) include(CheckCSourceCompiles) include(CheckIncludeFiles) set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) check_include_files(pcap-int.h HAVE_PCAP_INT_H) check_function_exists(pcap_freecode HAVE_LIBPCAP_PCAP_FREECODE) if (NOT HAVE_LIBPCAP_PCAP_FREECODE) set(DONT_HAVE_LIBPCAP_PCAP_FREECODE true) message(STATUS "No implementation for pcap_freecode()") endif () check_c_source_compiles(" #include int main () { int snaplen; int linktype; struct bpf_program fp; int optimize; bpf_u_int32 netmask; char str[10]; char error[1024]; snaplen = 50; linktype = DLT_EN10MB; optimize = 1; netmask = 0L; str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; (void)pcap_compile_nopcap( snaplen, linktype, &fp, str, optimize, netmask, &error); return 0; } " LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) # double check check_c_source_compiles(" #include int main () { int snaplen; int linktype; struct bpf_program fp; int optimize; bpf_u_int32 netmask; char str[10]; snaplen = 50; linktype = DLT_EN10MB; optimize = 1; netmask = 0L; str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; (void)pcap_compile_nopcap(snaplen, linktype, &fp, str, optimize, netmask); return 0; } " LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) message(FATAL_ERROR "Can't determine if pcap_compile_nopcap takes an error parameter") endif () endif () check_symbol_exists(DLT_PPP_SERIAL pcap.h HAVE_DLT_PPP_SERIAL) if (NOT HAVE_DLT_PPP_SERIAL) set(DLT_PPP_SERIAL 50) endif () set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) broccoli-1.97-minimal/cmake/FindFLEX.cmake0000664002342100234210000001633012523041064020131 0ustar johannajohanna# - Find flex executable and provides a macro to generate custom build rules # # The module defines the following variables: # FLEX_FOUND - true is flex executable is found # FLEX_EXECUTABLE - the path to the flex executable # FLEX_VERSION - the version of flex # FLEX_LIBRARIES - The flex libraries # # The minimum required version of flex can be specified using the # standard syntax, e.g. FIND_PACKAGE(FLEX 2.5.13) # # # If flex is found on the system, the module provides the macro: # FLEX_TARGET(Name FlexInput FlexOutput [COMPILE_FLAGS ]) # which creates a custom command to generate the file from # the file. If COMPILE_FLAGS option is specified, the next # parameter is added to the flex command line. Name is an alias used to # get details of this custom command. Indeed the macro defines the # following variables: # FLEX_${Name}_DEFINED - true is the macro ran successfully # FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an # alias for FlexOutput # FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput} # # Flex scanners oftenly use tokens defined by Bison: the code generated # by Flex depends of the header generated by Bison. This module also # defines a macro: # ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget) # which adds the required dependency between a scanner and a parser # where and are the first parameters of # respectively FLEX_TARGET and BISON_TARGET macros. # # ==================================================================== # Example: # # find_package(BISON) # find_package(FLEX) # # BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) # FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BIANRY_DIR}/lexer.cpp) # ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser) # # include_directories(${CMAKE_CURRENT_BINARY_DIR}) # add_executable(Foo # Foo.cc # ${BISON_MyParser_OUTPUTS} # ${FLEX_MyScanner_OUTPUTS} # ) # ==================================================================== #============================================================================= # Copyright 2009 Kitware, Inc. # Copyright 2006 Tristan Carel # Modified 2010 by Jon Siwek, backporting for CMake 2.6 compat # # Distributed under the OSI-approved BSD License (the "License"): # CMake - Cross Platform Makefile Generator # Copyright 2000-2009 Kitware, Inc., Insight Software Consortium # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the names of Kitware, Inc., the Insight Software Consortium, # nor the names of their contributors may be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable") MARK_AS_ADVANCED(FLEX_EXECUTABLE) FIND_LIBRARY(FL_LIBRARY NAMES fl DOC "path to the fl library") MARK_AS_ADVANCED(FL_LIBRARY) SET(FLEX_LIBRARIES ${FL_LIBRARY}) IF(FLEX_EXECUTABLE) EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version OUTPUT_VARIABLE FLEX_version_output ERROR_VARIABLE FLEX_version_error RESULT_VARIABLE FLEX_version_result OUTPUT_STRIP_TRAILING_WHITESPACE) IF(NOT ${FLEX_version_result} EQUAL 0) IF(FLEX_FIND_REQUIRED) MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}") ELSE() MESSAGE("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available") ENDIF() ELSE() STRING(REGEX REPLACE "^flex (.*)$" "\\1" FLEX_VERSION "${FLEX_version_output}") ENDIF() #============================================================ # FLEX_TARGET (public macro) #============================================================ # MACRO(FLEX_TARGET Name Input Output) SET(FLEX_TARGET_usage "FLEX_TARGET( [COMPILE_FLAGS ]") IF(${ARGC} GREATER 3) IF(${ARGC} EQUAL 5) IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") SET(FLEX_EXECUTABLE_opts "${ARGV4}") SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts) ELSE() MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) ENDIF() ELSE() MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) ENDIF() ENDIF() ADD_CUSTOM_COMMAND(OUTPUT ${Output} COMMAND ${FLEX_EXECUTABLE} ARGS ${FLEX_EXECUTABLE_opts} -o${Output} ${Input} DEPENDS ${Input} COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) SET(FLEX_${Name}_DEFINED TRUE) SET(FLEX_${Name}_OUTPUTS ${Output}) SET(FLEX_${Name}_INPUT ${Input}) SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) ENDMACRO(FLEX_TARGET) #============================================================ #============================================================ # ADD_FLEX_BISON_DEPENDENCY (public macro) #============================================================ # MACRO(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget) IF(NOT FLEX_${FlexTarget}_OUTPUTS) MESSAGE(SEND_ERROR "Flex target `${FlexTarget}' does not exists.") ENDIF() IF(NOT BISON_${BisonTarget}_OUTPUT_HEADER) MESSAGE(SEND_ERROR "Bison target `${BisonTarget}' does not exists.") ENDIF() SET_SOURCE_FILES_PROPERTIES(${FLEX_${FlexTarget}_OUTPUTS} PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER}) ENDMACRO(ADD_FLEX_BISON_DEPENDENCY) #============================================================ ENDIF(FLEX_EXECUTABLE) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX FLEX_EXECUTABLE FLEX_VERSION) # FindFLEX.cmake ends here broccoli-1.97-minimal/cmake/OSSpecific.cmake0000664002342100234210000000344112523041064020560 0ustar johannajohannaif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(bro_LINKER_FLAGS "${bro_LINKER_FLAGS} -rdynamic") elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(HAVE_LINUX true) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Solaris") set(SOCKET_LIBS nsl socket) elseif (${CMAKE_SYSTEM_NAME} MATCHES "osf") # Workaround ip_hl vs. ip_vhl problem in netinet/ip.h add_definitions(-D__STDC__=2) elseif (${CMAKE_SYSTEM_NAME} MATCHES "irix") list(APPEND CMAKE_C_FLAGS -xansi -signed -g3) list(APPEND CMAKE_CXX_FLAGS -xansi -signed -g3) elseif (${CMAKE_SYSTEM_NAME} MATCHES "ultrix") list(APPEND CMAKE_C_FLAGS -std1 -g3) list(APPEND CMAKE_CXX_FLAGS -std1 -g3) include(CheckCSourceCompiles) check_c_source_compiles(" #include int main() { void c(const struct a *); return 0; } " have_ultrix_const) if (NOT have_ultrix_const) set(NEED_ULTRIX_CONST_HACK true) endif () elseif (${CMAKE_SYSTEM_NAME} MATCHES "hpux" OR ${CMAKE_SYSTEM_NAME} MATCHES "HP-UX") include(CheckCSourceCompiles) set(CMAKE_REQUIRED_FLAGS -Aa) set(CMAKE_REQUIRED_DEFINITIONS -D_HPUX_SOURCE) check_c_source_compiles(" #include int main() { int frob(int, char *); return 0; } " have_ansi_prototypes) set(CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_DEFINITIONS) if (have_ansi_prototypes) add_definitions(-D_HPUX_SOURCE) list(APPEND CMAKE_C_FLAGS -Aa) list(APPEND CMAKE_CXX_FLAGS -Aa) endif () if (NOT have_ansi_prototypes) message(FATAL_ERROR "Can't get HPUX compiler to handle ANSI prototypes") endif () endif () broccoli-1.97-minimal/cmake/FindBinPAC.cmake0000664002342100234210000000244012523041064020424 0ustar johannajohanna# - Try to find BinPAC binary and library # # Usage of this module as follows: # # find_package(BinPAC) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # BinPAC_ROOT_DIR Set this variable to the root installation of # BinPAC if the module has problems finding the # proper installation path. # # Variables defined by this module: # # BINPAC_FOUND System has BinPAC binary and library # BinPAC_EXE The binpac executable # BinPAC_LIBRARY The libbinpac.a library # BinPAC_INCLUDE_DIR The binpac headers # look for BinPAC in standard locations or user-provided root find_path(BinPAC_ROOT_DIR NAMES include/binpac.h ) find_file(BinPAC_EXE NAMES binpac HINTS ${BinPAC_ROOT_DIR}/bin ) find_library(BinPAC_LIBRARY NAMES libbinpac.a HINTS ${BinPAC_ROOT_DIR}/lib ) find_path(BinPAC_INCLUDE_DIR NAMES binpac.h HINTS ${BinPAC_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(BinPAC DEFAULT_MSG BinPAC_EXE BinPAC_LIBRARY BinPAC_INCLUDE_DIR ) mark_as_advanced( BinPAC_ROOT_DIR BinPAC_EXE BinPAC_LIBRARY BinPAC_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/BroPluginDynamic.cmake0000664002342100234210000002317112523041064022001 0ustar johannajohanna## A set of functions for defining Bro plugins. ## ## This set is for plugins compiled dynamically for loading at run-time. ## See BroPluginsStatic.cmake for the static version. ## ## Note: This is meant to run as a standalone CMakeLists.txt. It sets ## up all the basic infrastructure to compile a dynamic Bro plugin when ## included from its top-level CMake file. if ( NOT BRO_PLUGIN_INTERNAL_BUILD ) include(${BRO_DIST}/cmake/CommonCMakeConfig.cmake) if ( NOT BRO_DIST ) message(FATAL_ERROR "BRO_DIST not set") endif () if ( NOT EXISTS "${BRO_DIST}/build/CMakeCache.txt" ) message(FATAL_ERROR "${BRO_DIST}/build/CMakeCache.txt; has Bro been built?") endif () load_cache("${BRO_DIST}/build" READ_WITH_PREFIX bro_cache_ CMAKE_INSTALL_PREFIX Bro_BINARY_DIR Bro_SOURCE_DIR ENABLE_DEBUG BRO_PLUGIN_INSTALL_PATH BRO_EXE_PATH CMAKE_CXX_FLAGS CMAKE_C_FLAGS) if ( NOT BRO_PLUGIN_BASE ) set(BRO_PLUGIN_BASE "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "" FORCE) endif () set(BRO_PLUGIN_SCRIPTS "${CMAKE_CURRENT_BINARY_DIR}/scripts" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_SCRIPTS_SRC "${BRO_PLUGIN_BASE}/scripts" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BUILD "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_LIB "${BRO_PLUGIN_BUILD}/lib" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BIF "${BRO_PLUGIN_LIB}/bif" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_MAGIC "${BRO_PLUGIN_BUILD}/__bro_plugin__" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_README "${BRO_PLUGIN_BASE}/README" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH "${BRO_PLUGIN_INSTALL_ROOT}" CACHE INTERNAL "" FORCE) if ( NOT BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH ) set(BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH "${bro_cache_BRO_PLUGIN_INSTALL_PATH}" CACHE INTERNAL "" FORCE) endif () set(BRO_PLUGIN_BRO_INSTALL_PREFIX "${bro_cache_CMAKE_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_SRC "${bro_cache_Bro_SOURCE_DIR}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_BUILD "${bro_cache_Bro_BINARY_DIR}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_EXE_PATH "${bro_cache_BRO_EXE_PATH}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_CXX_FLAGS "${bro_cache_CMAKE_CXX_FLAGS}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BRO_C_FLAGS "${bro_cache_CMAKE_C_FLAGS}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_ENABLE_DEBUG "${bro_cache_ENABLE_DEBUG}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_INTERNAL_BUILD false CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BUILD_DYNAMIC true CACHE INTERNAL "" FORCE) message(STATUS "Bro executable : ${BRO_PLUGIN_BRO_EXE_PATH}") message(STATUS "Bro source : ${BRO_PLUGIN_BRO_SRC}") message(STATUS "Bro build : ${BRO_PLUGIN_BRO_BUILD}") message(STATUS "Bro install prefix : ${BRO_PLUGIN_BRO_INSTALL_PREFIX}") message(STATUS "Bro plugin directory: ${BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH}") message(STATUS "Bro debug mode : ${BRO_PLUGIN_ENABLE_DEBUG}") set(CMAKE_MODULE_PATH ${BRO_PLUGIN_BASE}/cmake ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH ${BRO_PLUGIN_BRO_SRC}/cmake ${CMAKE_MODULE_PATH}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${BRO_PLUGIN_BRO_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BRO_PLUGIN_BRO_CXX_FLAGS}") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # By default Darwin's linker requires all symbols to be present at link time. set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -undefined dynamic_lookup -Wl,-bind_at_load") endif () include_directories(BEFORE ${BRO_PLUGIN_BRO_SRC}/src ${BRO_PLUGIN_BRO_SRC}/aux/binpac/lib ${BRO_PLUGIN_BRO_BUILD} ${BRO_PLUGIN_BRO_BUILD}/src ${BRO_PLUGIN_BRO_BUILD}/aux/binpac/lib ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ) set(ENV{PATH} "${BRO_PLUGIN_BRO_BUILD}/build/src:$ENV{PATH}") set(bro_PLUGIN_LIBS CACHE INTERNAL "plugin libraries" FORCE) set(bro_PLUGIN_BIF_SCRIPTS CACHE INTERNAL "Bro script stubs for BIFs in Bro plugins" FORCE) add_definitions(-DBRO_PLUGIN_INTERNAL_BUILD=false) add_custom_target(generate_outputs) if ( BRO_PLUGIN_ENABLE_DEBUG ) set(ENABLE_DEBUG true) set(CMAKE_BUILD_TYPE Debug) endif () include(SetDefaultCompileFlags) else () set(BRO_PLUGIN_BASE "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_LIB "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_BIF "${BRO_PLUGIN_LIB}/bif" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_MAGIC "${BRO_PLUGIN_BASE}/__bro_plugin__" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_README "${BRO_PLUGIN_BASE}/README" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_SCRIPTS "${BRO_PLUGIN_BASE}/scripts" CACHE INTERNAL "" FORCE) set(BRO_PLUGIN_SCRIPTS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/scripts" CACHE INTERNAL "" FORCE) endif () include(GetArchitecture) function(bro_plugin_bif_dynamic) foreach ( bif ${ARGV} ) bif_target(${bif} "plugin" ${_plugin_name} ${_plugin_name_canon} FALSE) list(APPEND _plugin_objs ${BIF_OUTPUT_CC}) list(APPEND _plugin_deps ${BIF_BUILD_TARGET}) set(_plugin_objs "${_plugin_objs}" PARENT_SCOPE) set(_plugin_deps "${_plugin_deps}" PARENT_SCOPE) endforeach () endfunction() function(bro_plugin_link_library_dynamic) foreach ( lib ${ARGV} ) set(_plugin_libs ${_plugin_libs} ${lib} CACHE INTERNAL "dynamic plugin libraries") endforeach () endfunction() function(bro_plugin_end_dynamic) # Create the dynamic library/bundle. add_library(${_plugin_lib} MODULE ${_plugin_objs}) set_target_properties(${_plugin_lib} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${BRO_PLUGIN_LIB}") set_target_properties(${_plugin_lib} PROPERTIES PREFIX "") # set_target_properties(${_plugin_lib} PROPERTIES ENABLE_EXPORTS TRUE) add_dependencies(${_plugin_lib} generate_outputs) if ( _plugin_deps ) add_dependencies(${_plugin_lib} ${_plugin_deps}) endif() target_link_libraries(${_plugin_lib} ${_plugin_libs}) # Copy bif/*.bro. string(REPLACE "${BRO_PLUGIN_BASE}/" "" msg "Creating ${BRO_PLUGIN_BIF} for ${_plugin_name}") add_custom_target(copy-bif-${_plugin_name_canon} COMMAND "${CMAKE_COMMAND}" -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/bif ${BRO_PLUGIN_BIF} COMMENT "${msg}") # Create bif/__init__.bro. bro_bif_create_loader(bif-init-${_plugin_name_canon} "${bro_PLUGIN_BIF_SCRIPTS}") # Copy scripts/ if it's not already at the right place inside the # plugin directory. (Actually, we create a symbolic link rather # than copy so that edits to the scripts show up immediately.) if ( NOT "${BRO_PLUGIN_SCRIPTS_SRC}" STREQUAL "${BRO_PLUGIN_SCRIPTS}" ) add_custom_target(copy-scripts-${_plugin_name_canon} # COMMAND "${CMAKE_COMMAND}" -E remove_directory ${BRO_PLUGIN_SCRIPTS} # COMMAND "${CMAKE_COMMAND}" -E copy_directory ${BRO_PLUGIN_SCRIPTS_SRC} ${BRO_PLUGIN_SCRIPTS}) COMMAND test -d ${BRO_PLUGIN_SCRIPTS_SRC} && rm -f ${BRO_PLUGIN_SCRIPTS} && ln -s ${BRO_PLUGIN_SCRIPTS_SRC} ${BRO_PLUGIN_SCRIPTS} || true) add_dependencies(${_plugin_lib} copy-scripts-${_plugin_name_canon}) endif() if ( _plugin_deps ) add_dependencies(bif-init-${_plugin_name_canon} ${_plugin_deps}) add_dependencies(copy-bif-${_plugin_name_canon} ${_plugin_deps}) add_dependencies(bif-init-${_plugin_name_canon} copy-bif-${_plugin_name_canon}) add_dependencies(${_plugin_lib} bif-init-${_plugin_name_canon} copy-bif-${_plugin_name_canon}) endif() # Create __bro_plugin__ # string(REPLACE "${BRO_PLUGIN_BASE}/" "" msg "Creating ${BRO_PLUGIN_MAGIC} for ${_plugin_name}") add_custom_target(bro-plugin-${_plugin_name_canon} COMMAND echo "${_plugin_name}" ">${BRO_PLUGIN_MAGIC}" COMMENT "${msg}") if ( _plugin_deps ) add_dependencies(bro-plugin-${_plugin_name_canon} ${_plugin_deps}) endif() add_dependencies(${_plugin_lib} bro-plugin-${_plugin_name_canon}) # Create binary install package. add_custom_command(TARGET ${_plugin_lib} POST_BUILD COMMAND ${BRO_PLUGIN_BRO_SRC}/cmake/bro-plugin-create-package.sh ${_plugin_name_canon} ${_plugin_dist} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${_plugin_lib} COMMENT "Building binary plugin package") set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${BRO_PLUGIN_BIF}) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${BRO_PLUGIN_LIB}) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${BRO_PLUGIN_MAGIC}) ### Plugin installation. set(plugin_install "${BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH}/${_plugin_name_canon}") INSTALL(CODE "execute_process( COMMAND ${BRO_PLUGIN_BRO_SRC}/cmake/bro-plugin-install-package.sh ${_plugin_name_canon} ${BRO_PLUGIN_BRO_PLUGIN_INSTALL_PATH} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") endfunction() macro(_plugin_target_name_dynamic target ns name) set(${target} "${ns}-${name}.${HOST_ARCHITECTURE}") endmacro() broccoli-1.97-minimal/cmake/cmake_uninstall.cmake.in0000664002342100234210000000221112523041064022341 0ustar johannajohannafunction(uninstall_manifest manifestPath) file(READ "${manifestPath}" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach (file ${files}) set(fileName $ENV{DESTDIR}${file}) if (EXISTS "${fileName}" OR IS_SYMLINK "${fileName}") message(STATUS "Uninstalling: ${fileName}") execute_process( COMMAND "@CMAKE_COMMAND@" -E remove "${fileName}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) if (NOT ${rm_retval} EQUAL 0) message(FATAL_ERROR "Problem when removing: ${fileName}") endif () else () message(STATUS "Does not exist: ${fileName}") endif () endforeach () endfunction(uninstall_manifest) file(GLOB install_manifests @CMAKE_CURRENT_BINARY_DIR@/install_manifest*.txt) if (install_manifests) foreach (manifest ${install_manifests}) uninstall_manifest(${manifest}) endforeach () else () message(FATAL_ERROR "Cannot find any install manifests in: " "\"@CMAKE_CURRENT_BINARY_DIR@/install_manifest*.txt\"") endif () broccoli-1.97-minimal/cmake/BroPluginCommon.cmake0000664002342100234210000000555412523041064021652 0ustar johannajohanna## A set of functions for defining Bro plugins. ## ## This set is used by both static and dynamic plugins via ## BroPluginsStatic and BroPluginsDynamic, respectively. include(BifCl) include(BinPAC) # Begins a plugin definition, giving its namespace and name as the arguments. function(bro_plugin_begin ns name) _plugin_target_name(target "${ns}" "${name}") set(_plugin_lib "${target}" PARENT_SCOPE) set(_plugin_name "${ns}::${name}" PARENT_SCOPE) set(_plugin_name_canon "${ns}_${name}" PARENT_SCOPE) set(_plugin_ns "${ns}" PARENT_SCOPE) set(_plugin_objs "" PARENT_SCOPE) set(_plugin_deps "" PARENT_SCOPE) set(_plugin_dist "" PARENT_SCOPE) endfunction() # Adds *.cc files to a plugin. function(bro_plugin_cc) list(APPEND _plugin_objs ${ARGV}) set(_plugin_objs "${_plugin_objs}" PARENT_SCOPE) endfunction() # Adds a *.pac file to a plugin. Further *.pac files may given that # it depends on. function(bro_plugin_pac) binpac_target(${ARGV}) list(APPEND _plugin_objs ${BINPAC_OUTPUT_CC}) list(APPEND _plugin_deps ${BINPAC_BUILD_TARGET}) set(_plugin_objs "${_plugin_objs}" PARENT_SCOPE) set(_plugin_deps "${_plugin_deps}" PARENT_SCOPE) endfunction() # Add an additional object file to the plugin's library. function(bro_plugin_obj) foreach ( bif ${ARGV} ) list(APPEND _plugin_objs ${bif}) set(_plugin_objs "${_plugin_objs}" PARENT_SCOPE) endforeach () endfunction() # Add additional files that should be included into the binary plugin distribution. # Ignored for static plugins. macro(bro_plugin_dist_files) foreach ( file ${ARGV} ) list(APPEND _plugin_dist ${file}) # Don't need this here, and generates an error that # there is not parent scope. Not sure why it does that # here but not for other macros doing something similar. # set(_plugin_dist "${_plugin_dist}" PARENT_SCOPE) endforeach () endmacro() # Link an additional library to the plugin's library. function(bro_plugin_link_library) if ( BRO_PLUGIN_BUILD_DYNAMIC ) bro_plugin_link_library_dynamic(${ARGV}) else () bro_plugin_link_library_static(${ARGV}) endif () endfunction() # Adds *.bif files to a plugin. macro(bro_plugin_bif) if ( BRO_PLUGIN_BUILD_DYNAMIC ) bro_plugin_bif_dynamic(${ARGV}) else () bro_plugin_bif_static(${ARGV}) endif () endmacro() # Ends a plugin definition. macro(bro_plugin_end) if ( BRO_PLUGIN_BUILD_DYNAMIC ) bro_plugin_end_dynamic(${ARGV}) else () bro_plugin_end_static(${ARGV}) endif () endmacro() # Internal macro to create a unique target name for a plugin. macro(_plugin_target_name target ns name) if ( BRO_PLUGIN_BUILD_DYNAMIC ) _plugin_target_name_dynamic(${ARGV}) else () _plugin_target_name_static(${ARGV}) endif () endmacro() broccoli-1.97-minimal/cmake/OpenSSLTests.cmake0000664002342100234210000000401112523041064021071 0ustar johannajohannainclude(CheckCSourceCompiles) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_LIBRARIES ${OpenSSL_LIBRARIES}) set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR}) check_c_source_compiles(" #include int main() { return 0; } " including_ssl_h_works) if (NOT including_ssl_h_works) # On Red Hat we may need to include Kerberos header. set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR} /usr/kerberos/include) check_c_source_compiles(" #include #include int main() { return 0; } " NEED_KRB5_H) set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR}) if (NOT NEED_KRB5_H) message(FATAL_ERROR "OpenSSL test failure. See CmakeError.log for details.") else () message(STATUS "OpenSSL requires Kerberos header") include_directories("/usr/kerberos/include") endif () endif () # check for OPENSSL_add_all_algorithms_conf function # and thus OpenSSL >= v0.9.7 check_c_source_compiles(" #include int main() { OPENSSL_add_all_algorithms_conf(); return 0; } " openssl_greater_than_0_9_7) if (NOT openssl_greater_than_0_9_7) message(FATAL_ERROR "OpenSSL >= v0.9.7 required") endif () check_cxx_source_compiles(" #include int main() { const unsigned char** cpp = 0; X509** x =0; d2i_X509(x, cpp, 0); return 0; } " OPENSSL_D2I_X509_USES_CONST_CHAR) if (NOT OPENSSL_D2I_X509_USES_CONST_CHAR) # double check that it compiles without const check_cxx_source_compiles(" #include int main() { unsigned char** cpp = 0; X509** x =0; d2i_X509(x, cpp, 0); return 0; } " OPENSSL_D2I_X509_USES_CHAR) if (NOT OPENSSL_D2I_X509_USES_CHAR) message(FATAL_ERROR "Can't determine if openssl_d2i_x509() takes const char parameter") endif () endif () set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) broccoli-1.97-minimal/cmake/MAC_PACKAGE_INTRO0000664002342100234210000000124712523041064020202 0ustar johannajohannaThis package will install @CMAKE_PROJECT_NAME@ into the following location: @CMAKE_INSTALL_PREFIX@ You may choose to update your PATH environment variable: # For Bash export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH # For CSH setenv PATH @CMAKE_INSTALL_PREFIX@/bin:$PATH If you have more than one volume, please choose the install destination as the one that contains the root filesystem. If you have existing configuration files that are modified or otherwise different from the version included in the package, this installer will attempt to prevent overwirting them, but its also advisable to make your own backups of important files before proceeding. broccoli-1.97-minimal/cmake/README0000664002342100234210000000021112523041064016437 0ustar johannajohannaThis is a collection of CMake scripts intended to be included as a git submodule in other repositories related to Bro (www.bro-ids.org). broccoli-1.97-minimal/cmake/FindCapstats.cmake0000664002342100234210000000062512523041064021155 0ustar johannajohanna# - Try to find capstats program # # Usage of this module as follows: # # find_package(Capstats) # # Variables defined by this module: # # CAPSTATS_FOUND capstats binary found # Capstats_EXE path to the capstats executable binary find_program(CAPSTATS_EXE capstats) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Capstats DEFAULT_MSG CAPSTATS_EXE) broccoli-1.97-minimal/cmake/FindJeMalloc.cmake0000664002342100234210000000217412523041064021062 0ustar johannajohanna# - Try to find jemalloc headers and libraries. # # Usage of this module as follows: # # find_package(JeMalloc) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # JEMALLOC_ROOT_DIR Set this variable to the root installation of # jemalloc if the module has problems finding # the proper installation path. # # Variables defined by this module: # # JEMALLOC_FOUND System has jemalloc libs/headers # JEMALLOC_LIBRARIES The jemalloc library/libraries # JEMALLOC_INCLUDE_DIR The location of jemalloc headers find_path(JEMALLOC_ROOT_DIR NAMES include/jemalloc/jemalloc.h ) find_library(JEMALLOC_LIBRARIES NAMES jemalloc HINTS ${JEMALLOC_ROOT_DIR}/lib ) find_path(JEMALLOC_INCLUDE_DIR NAMES jemalloc/jemalloc.h HINTS ${JEMALLOC_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(JeMalloc DEFAULT_MSG JEMALLOC_LIBRARIES JEMALLOC_INCLUDE_DIR ) mark_as_advanced( JEMALLOC_ROOT_DIR JEMALLOC_LIBRARIES JEMALLOC_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/bro-plugin-install-package.sh0000775002342100234210000000075512523041064023246 0ustar johannajohanna#! /bin/sh # # Helper script to install the tarball with a plugin's binary distribution. # # Called from BroPluginDynamic.cmake. Current directory is the plugin # build directory. if [ $# != 2 ]; then echo "usage: `basename $0` " exit 1 fi dst=$2 if [ ! -d "${dst}" ]; then echo "Error: ${dst} does not exist; has Bro been installed?" exit 1 fi name=$1 tgz=`pwd`/$name.tgz ( cd ${dst} && rm -rf "${name}" && tar xzf ${tgz} ) broccoli-1.97-minimal/cmake/CheckFunctions.cmake0000664002342100234210000000067512523041064021505 0ustar johannajohannainclude(CheckFunctionExists) check_function_exists(getopt_long HAVE_GETOPT_LONG) check_function_exists(mallinfo HAVE_MALLINFO) check_function_exists(strcasestr HAVE_STRCASESTR) check_function_exists(strerror HAVE_STRERROR) check_function_exists(strsep HAVE_STRSEP) check_function_exists(sigset HAVE_SIGSET) if (HAVE_SIGSET) set(SIG_FUNC sigset) else () set(SIG_FUNC signal) check_function_exists(sigaction HAVE_SIGACTION) endif () broccoli-1.97-minimal/cmake/FindPCAP.cmake0000664002342100234210000000443612523041064020122 0ustar johannajohanna# - Try to find libpcap include dirs and libraries # # Usage of this module as follows: # # find_package(PCAP) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # PCAP_ROOT_DIR Set this variable to the root installation of # libpcap if the module has problems finding the # proper installation path. # # Variables defined by this module: # # PCAP_FOUND System has libpcap, include and library dirs found # PCAP_INCLUDE_DIR The libpcap include directories. # PCAP_LIBRARY The libpcap library (possibly includes a thread # library e.g. required by pf_ring's libpcap) # HAVE_PF_RING If a found version of libpcap supports PF_RING find_path(PCAP_ROOT_DIR NAMES include/pcap.h ) find_path(PCAP_INCLUDE_DIR NAMES pcap.h HINTS ${PCAP_ROOT_DIR}/include ) find_library(PCAP_LIBRARY NAMES pcap HINTS ${PCAP_ROOT_DIR}/lib ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PCAP DEFAULT_MSG PCAP_LIBRARY PCAP_INCLUDE_DIR ) include(CheckCSourceCompiles) set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) check_c_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO) set(CMAKE_REQUIRED_LIBRARIES) # check if linking against libpcap also needs to link against a thread library if (NOT PCAP_LINKS_SOLO) find_package(Threads) if (THREADS_FOUND) set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) check_c_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS) set(CMAKE_REQUIRED_LIBRARIES) endif () if (THREADS_FOUND AND PCAP_NEEDS_THREADS) set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) list(REMOVE_DUPLICATES _tmp) set(PCAP_LIBRARY ${_tmp} CACHE STRING "Libraries needed to link against libpcap" FORCE) else () message(FATAL_ERROR "Couldn't determine how to link against libpcap") endif () endif () include(CheckFunctionExists) set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) check_function_exists(pcap_get_pfring_id HAVE_PF_RING) set(CMAKE_REQUIRED_LIBRARIES) mark_as_advanced( PCAP_ROOT_DIR PCAP_INCLUDE_DIR PCAP_LIBRARY ) broccoli-1.97-minimal/cmake/FindBISON.cmake0000664002342100234210000002221512523041064020244 0ustar johannajohanna# - Find bison executable and provides macros to generate custom build rules # The module defines the following variables: # # BISON_EXECUTABLE - path to the bison program # BISON_VERSION - version of bison # BISON_FOUND - true if the program was found # # If bison is found, the module defines the macros: # BISON_TARGET( [VERBOSE ] # [COMPILE_FLAGS ] [HEADER ]) # which will create a custom rule to generate a parser. is # the path to a yacc file. is the name of the source file # generated by bison. A header file containing the token list is also # generated according to bison's -d option by default or if the HEADER # option is used, the argument is passed to bison's --defines option to # specify output file. If COMPILE_FLAGS option is specified, the next # parameter is added in the bison command line. if VERBOSE option is # specified, is created and contains verbose descriptions of the # grammar and parser. The macro defines a set of variables: # BISON_${Name}_DEFINED - true is the macro ran successfully # BISON_${Name}_INPUT - The input source file, an alias for # BISON_${Name}_OUTPUT_SOURCE - The source file generated by bison # BISON_${Name}_OUTPUT_HEADER - The header file generated by bison # BISON_${Name}_OUTPUTS - The sources files generated by bison # BISON_${Name}_COMPILE_FLAGS - Options used in the bison command line # # ==================================================================== # Example: # # find_package(BISON) # BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) # add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS}) # ==================================================================== #============================================================================= # Copyright 2009 Kitware, Inc. # Copyright 2006 Tristan Carel # Modified 2010 by Jon Siwek, adding HEADER option # # Distributed under the OSI-approved BSD License (the "License"): # CMake - Cross Platform Makefile Generator # Copyright 2000-2009 Kitware, Inc., Insight Software Consortium # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the names of Kitware, Inc., the Insight Software Consortium, # nor the names of their contributors may be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= FIND_PROGRAM(BISON_EXECUTABLE bison DOC "path to the bison executable") MARK_AS_ADVANCED(BISON_EXECUTABLE) IF(BISON_EXECUTABLE) EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version OUTPUT_VARIABLE BISON_version_output ERROR_VARIABLE BISON_version_error RESULT_VARIABLE BISON_version_result OUTPUT_STRIP_TRAILING_WHITESPACE) IF(NOT ${BISON_version_result} EQUAL 0) MESSAGE(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}") ELSE() STRING(REGEX REPLACE "^bison \\(GNU Bison\\) ([^\n]+)\n.*" "\\1" BISON_VERSION "${BISON_version_output}") ENDIF() # internal macro MACRO(BISON_TARGET_option_verbose Name BisonOutput filename) LIST(APPEND BISON_TARGET_cmdopt "--verbose") GET_FILENAME_COMPONENT(BISON_TARGET_output_path "${BisonOutput}" PATH) GET_FILENAME_COMPONENT(BISON_TARGET_output_name "${BisonOutput}" NAME_WE) ADD_CUSTOM_COMMAND(OUTPUT ${filename} COMMAND ${CMAKE_COMMAND} ARGS -E copy "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" "${filename}" DEPENDS "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) SET(BISON_${Name}_VERBOSE_FILE ${filename}) LIST(APPEND BISON_TARGET_extraoutputs "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output") ENDMACRO(BISON_TARGET_option_verbose) # internal macro MACRO(BISON_TARGET_option_extraopts Options) SET(BISON_TARGET_extraopts "${Options}") SEPARATE_ARGUMENTS(BISON_TARGET_extraopts) LIST(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts}) ENDMACRO(BISON_TARGET_option_extraopts) #============================================================ # BISON_TARGET (public macro) #============================================================ # MACRO(BISON_TARGET Name BisonInput BisonOutput) SET(BISON_TARGET_output_header "") #SET(BISON_TARGET_command_opt "") SET(BISON_TARGET_cmdopt "") SET(BISON_TARGET_outputs "${BisonOutput}") IF(NOT ${ARGC} EQUAL 3 AND NOT ${ARGC} EQUAL 5 AND NOT ${ARGC} EQUAL 7 AND NOT ${ARGC} EQUAL 9) MESSAGE(SEND_ERROR "Usage") ELSE() # Parsing parameters IF(${ARGC} GREATER 5 OR ${ARGC} EQUAL 5) IF("${ARGV3}" STREQUAL "VERBOSE") BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV4}") ENDIF() IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") BISON_TARGET_option_extraopts("${ARGV4}") ENDIF() IF("${ARGV3}" STREQUAL "HEADER") set(BISON_TARGET_output_header "${ARGV4}") ENDIF() ENDIF() IF(${ARGC} GREATER 7 OR ${ARGC} EQUAL 7) IF("${ARGV5}" STREQUAL "VERBOSE") BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV6}") ENDIF() IF("${ARGV5}" STREQUAL "COMPILE_FLAGS") BISON_TARGET_option_extraopts("${ARGV6}") ENDIF() IF("${ARGV5}" STREQUAL "HEADER") set(BISON_TARGET_output_header "${ARGV6}") ENDIF() ENDIF() IF(${ARGC} EQUAL 9) IF("${ARGV7}" STREQUAL "VERBOSE") BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV8}") ENDIF() IF("${ARGV7}" STREQUAL "COMPILE_FLAGS") BISON_TARGET_option_extraopts("${ARGV8}") ENDIF() IF("${ARGV7}" STREQUAL "HEADER") set(BISON_TARGET_output_header "${ARGV8}") ENDIF() ENDIF() IF(BISON_TARGET_output_header) # Header's name passed in as argument to be used in --defines option LIST(APPEND BISON_TARGET_cmdopt "--defines=${BISON_TARGET_output_header}") set(BISON_${Name}_OUTPUT_HEADER ${BISON_TARGET_output_header}) ELSE() # Header's name generated by bison (see option -d) LIST(APPEND BISON_TARGET_cmdopt "-d") STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${ARGV2}") STRING(REPLACE "c" "h" _fileext ${_fileext}) STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}" BISON_${Name}_OUTPUT_HEADER "${ARGV2}") ENDIF() LIST(APPEND BISON_TARGET_outputs "${BISON_${Name}_OUTPUT_HEADER}") ADD_CUSTOM_COMMAND(OUTPUT ${BISON_TARGET_outputs} ${BISON_TARGET_extraoutputs} COMMAND ${BISON_EXECUTABLE} ARGS ${BISON_TARGET_cmdopt} -o ${ARGV2} ${ARGV1} DEPENDS ${ARGV1} COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # define target variables SET(BISON_${Name}_DEFINED TRUE) SET(BISON_${Name}_INPUT ${ARGV1}) SET(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs}) SET(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt}) SET(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}") ENDIF(NOT ${ARGC} EQUAL 3 AND NOT ${ARGC} EQUAL 5 AND NOT ${ARGC} EQUAL 7 AND NOT ${ARGC} EQUAL 9) ENDMACRO(BISON_TARGET) # #============================================================ ENDIF(BISON_EXECUTABLE) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON DEFAULT_MSG BISON_EXECUTABLE) # FindBISON.cmake ends here broccoli-1.97-minimal/cmake/FindPyBroccoli.cmake0000664002342100234210000000137512523041064021443 0ustar johannajohanna# - Determine if the Broccoli Python bindings are available # # Usage of this module as follows: # # find_package(PythonInterp REQUIRED) # find_package(PyBroccoli) # # Variables defined by this module: # # PYBROCCOLI_FOUND Python successfully imports broccoli bindings if (NOT PYBROCCOLI_FOUND) execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import broccoli" RESULT_VARIABLE PYBROCCOLI_IMPORT_RESULT) if (PYBROCCOLI_IMPORT_RESULT) # python returned non-zero exit status set(BROCCOLI_PYTHON_MODULE false) else () set(BROCCOLI_PYTHON_MODULE true) endif () endif () include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PyBroccoli DEFAULT_MSG BROCCOLI_PYTHON_MODULE) broccoli-1.97-minimal/cmake/BroPlugin.cmake0000664002342100234210000000073312523041064020473 0ustar johannajohanna # Wrapper include file that loads the macros for building a Bro # plugin either statically or dynamically, depending on whether # we're building as part of the main Bro source tree, or externally. if ( BRO_PLUGIN_INTERNAL_BUILD ) if ( "${BRO_PLUGIN_BUILD_DYNAMIC}" STREQUAL "" ) set(BRO_PLUGIN_BUILD_DYNAMIC FALSE) endif() else () set(BRO_PLUGIN_BUILD_DYNAMIC TRUE) endif () include(BroPluginCommon) include(BroPluginStatic) include(BroPluginDynamic) broccoli-1.97-minimal/cmake/FindLibGeoIP.cmake0000664002342100234210000000400412523041064020760 0ustar johannajohanna# - Try to find GeoIP headers and libraries # # Usage of this module as follows: # # find_package(LibGeoIP) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # LibGeoIP_ROOT_DIR Set this variable to the root installation of # libGeoIP if the module has problems finding the # proper installation path. # # Variables defined by this module: # # LIBGEOIP_FOUND System has GeoIP libraries and headers # LibGeoIP_LIBRARY The GeoIP library # LibGeoIP_INCLUDE_DIR The location of GeoIP headers # HAVE_GEOIP_COUNTRY_EDITION_V6 Whether the API support IPv6 country edition # HAVE_GEOIP_CITY_EDITION_REV0_V6 Whether the API supports IPv6 city edition find_path(LibGeoIP_ROOT_DIR NAMES include/GeoIPCity.h ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # the static version of the library is preferred on OS X for the # purposes of making packages (libGeoIP doesn't ship w/ OS X) set(libgeoip_names libGeoIp.a GeoIP) else () set(libgeoip_names GeoIP) endif () find_library(LibGeoIP_LIBRARY NAMES ${libgeoip_names} HINTS ${LibGeoIP_ROOT_DIR}/lib ) find_path(LibGeoIP_INCLUDE_DIR NAMES GeoIPCity.h HINTS ${LibGeoIP_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LibGeoIP DEFAULT_MSG LibGeoIP_LIBRARY LibGeoIP_INCLUDE_DIR ) if (LIBGEOIP_FOUND) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${LibGeoIP_INCLUDE_DIR}) check_cxx_source_compiles(" #include int main() { GEOIP_COUNTRY_EDITION_V6; return 0; } " HAVE_GEOIP_COUNTRY_EDITION_V6) check_cxx_source_compiles(" #include int main() { GEOIP_CITY_EDITION_REV0_V6; return 0; } " HAVE_GEOIP_CITY_EDITION_REV0_V6) set(CMAKE_REQUIRED_INCLUDES) endif () mark_as_advanced( LibGeoIP_ROOT_DIR LibGeoIP_LIBRARY LibGeoIP_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/FindOpenSSL.cmake0000664002342100234210000000302712523041064020655 0ustar johannajohanna# - Try to find openssl include dirs and libraries # # Usage of this module as follows: # # find_package(OpenSSL) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # OpenSSL_ROOT_DIR Set this variable to the root installation of # openssl if the module has problems finding the # proper installation path. # # Variables defined by this module: # # OPENSSL_FOUND System has openssl, include and library dirs found # OpenSSL_INCLUDE_DIR The openssl include directories. # OpenSSL_LIBRARIES The openssl libraries. # OpenSSL_CYRPTO_LIBRARY The openssl crypto library. # OpenSSL_SSL_LIBRARY The openssl ssl library. find_path(OpenSSL_ROOT_DIR NAMES include/openssl/ssl.h ) find_path(OpenSSL_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${OpenSSL_ROOT_DIR}/include ) find_library(OpenSSL_SSL_LIBRARY NAMES ssl ssleay32 ssleay32MD HINTS ${OpenSSL_ROOT_DIR}/lib ) find_library(OpenSSL_CRYPTO_LIBRARY NAMES crypto HINTS ${OpenSSL_ROOT_DIR}/lib ) set(OpenSSL_LIBRARIES ${OpenSSL_SSL_LIBRARY} ${OpenSSL_CRYPTO_LIBRARY} CACHE STRING "OpenSSL SSL and crypto libraries" FORCE) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OpenSSL DEFAULT_MSG OpenSSL_LIBRARIES OpenSSL_INCLUDE_DIR ) mark_as_advanced( OpenSSL_ROOT_DIR OpenSSL_INCLUDE_DIR OpenSSL_LIBRARIES OpenSSL_CRYPTO_LIBRARY OpenSSL_SSL_LIBRARY ) broccoli-1.97-minimal/cmake/BinPAC.cmake0000664002342100234210000000414612523041064017630 0ustar johannajohanna # A macro to define a command that uses the BinPac compiler to # produce C++ code that implements a protocol parser/analyzer. # The outputs are returned in BINPAC_OUTPUT_{CC,H}. # Additional dependencies are pulled from BINPAC_AUXSRC. # # The macro also creates a target that can be used to define depencencies on # the generated files. The name of the target includes a normalized path to # the input pac to make it unique. The target is added automatically to # bro_ALL_GENERATED_OUTPUTS. macro(BINPAC_TARGET pacFile) if ( BRO_PLUGIN_INTERNAL_BUILD ) set(binpacDep "${BinPAC_EXE}") else () set(BinPAC_EXE "${BRO_PLUGIN_BRO_BUILD}/aux/binpac/src/binpac") set(BinPAC_addl_args "-I;${BRO_PLUGIN_BRO_SRC}/src") endif () get_filename_component(basename ${pacFile} NAME_WE) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc COMMAND ${BinPAC_EXE} ARGS -q -d ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} -I ${CMAKE_SOURCE_DIR}/src ${BinPAC_addl_args} ${CMAKE_CURRENT_SOURCE_DIR}/${pacFile} DEPENDS ${binpacDep} ${pacFile} ${BINPAC_AUXSRC} ${ARGN} COMMENT "[BINPAC] Processing ${pacFile}" ) set(BINPAC_OUTPUT_H ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h) set(BINPAC_OUTPUT_CC ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc) set(pacOutputs ${BINPAC_OUTPUT_H} ${BINPAC_OUTPUT_CC}) set(target "pac-${CMAKE_CURRENT_BINARY_DIR}/${pacFile}") string(REGEX REPLACE "${CMAKE_BINARY_DIR}/src/" "" target "${target}") string(REGEX REPLACE "/" "-" target "${target}") add_custom_target(${target} DEPENDS ${pacOutputs}) set(BINPAC_BUILD_TARGET ${target}) set(bro_ALL_GENERATED_OUTPUTS ${bro_ALL_GENERATED_OUTPUTS} ${target} CACHE INTERNAL "automatically generated files" FORCE) # Propagate to top-level. endmacro(BINPAC_TARGET) broccoli-1.97-minimal/cmake/AddUninstallTarget.cmake0000664002342100234210000000067412523041064022327 0ustar johannajohannaif (NOT TARGET uninstall) if ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" ) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) endif () endif () broccoli-1.97-minimal/cmake/FindBroccoli.cmake0000664002342100234210000000222512523041064021125 0ustar johannajohanna# - Try to find libbroccoli include dirs and libraries # # Usage of this module as follows: # # find_package(Broccoli) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # Broccoli_ROOT_DIR Set this variable to the root installation of # libbroccoli if the module has problems finding the # proper installation path. # # Variables defined by this module: # # BROCCOLI_FOUND System has libbroccoli, include and lib dirs found # Broccoli_INCLUDE_DIR The libbroccoli include directories. # Broccoli_LIBRARY The libbroccoli library. find_path(Broccoli_ROOT_DIR NAMES include/broccoli.h ) find_path(Broccoli_INCLUDE_DIR NAMES broccoli.h HINTS ${Broccoli_ROOT_DIR}/include ) find_library(Broccoli_LIBRARY NAMES broccoli HINTS ${Broccoli_ROOT_DIR}/lib ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Broccoli DEFAULT_MSG Broccoli_LIBRARY Broccoli_INCLUDE_DIR ) mark_as_advanced( Broccoli_ROOT_DIR Broccoli_INCLUDE_DIR Broccoli_LIBRARY ) broccoli-1.97-minimal/cmake/CheckCompilers.cmake0000664002342100234210000000067012523041064021465 0ustar johannajohanna# Aborts the configuration if no C or C++ compiler is found, depending # on whether a previous call to the project() macro was supplied either # language as a requirement. if (NOT CMAKE_C_COMPILER AND DEFINED CMAKE_C_COMPILER) message(FATAL_ERROR "Could not find prerequisite C compiler") endif () if (NOT CMAKE_CXX_COMPILER AND DEFINED CMAKE_CXX_COMPILER) message(FATAL_ERROR "Could not find prerequisite C++ compiler") endif () broccoli-1.97-minimal/cmake/InstallPackageConfigFile.cmake0000664002342100234210000000527312523041064023406 0ustar johannajohannainclude(InstallClobberImmune) # This macro can be used to install configuration files which # users are expected to modify after installation. It will: # # - If binary packaging is enabled: # Install the file in the typical CMake fashion, but append to the # INSTALLED_CONFIG_FILES cache variable for use with the Mac package's # pre/post install scripts # # - If binary packaging is not enabled: # Install the script in a way such that it will check at `make install` # time whether the file does not exist. See InstallClobberImmune.cmake # # - Always create a target "install-example-configs" which installs an # example version of the config file. # # _srcfile: the absolute path to the file to install # _dstdir: absolute path to the directory in which to install the file # _dstfilename: how to (re)name the file inside _dstdir macro(InstallPackageConfigFile _srcfile _dstdir _dstfilename) set(_dstfile ${_dstdir}/${_dstfilename}) if (BINARY_PACKAGING_MODE) # If packaging mode is enabled, always install the distribution's # version of the file. The Mac package's pre/post install scripts # or native functionality of RPMs will take care of not clobbering it. install(FILES ${_srcfile} DESTINATION ${_dstdir} RENAME ${_dstfilename}) # This cache variable is what the Mac package pre/post install scripts # use to avoid clobbering user-modified config files set(INSTALLED_CONFIG_FILES "${INSTALLED_CONFIG_FILES} ${_dstfile}" CACHE STRING "" FORCE) # Additionally, the Mac PackageMaker packages don't have any automatic # handling of configuration file conflicts so install an example file # that the post install script will cleanup in the case it's extraneous if (APPLE) install(FILES ${_srcfile} DESTINATION ${_dstdir} RENAME ${_dstfilename}.example) endif () else () # Have `make install` check at run time whether the file does not exist InstallClobberImmune(${_srcfile} ${_dstfile}) endif () if (NOT TARGET install-example-configs) add_custom_target(install-example-configs COMMENT "Installed example configuration files") endif () # '/' is invalid in target names, so replace w/ '.' string(REGEX REPLACE "/" "." _flatsrc ${_srcfile}) set(_example ${_dstfile}.example) add_custom_target(install-example-config-${_flatsrc} COMMAND "${CMAKE_COMMAND}" -E copy ${_srcfile} \${DESTDIR}${_example} COMMENT "Installing ${_example}") add_dependencies(install-example-configs install-example-config-${_flatsrc}) endmacro(InstallPackageConfigFile) broccoli-1.97-minimal/cmake/BifCl.cmake0000664002342100234210000002221012523041064017543 0ustar johannajohanna # A macro to define a command that uses the BIF compiler to produce C++ # segments and Bro language declarations from a .bif file. The outputs # are returned in BIF_OUTPUT_{CC,H,BRO}. By default, it runs bifcl in # alternative mode (-a; suitable for standalone compilation). If # an additional parameter "standard" is given, it runs it in standard mode # for inclusion in NetVar.*. If an additional parameter "plugin" is given, # it runs it in plugin mode (-p). In the latter case, one more argument # is required with the plugin's name. # # The macro also creates a target that can be used to define depencencies on # the generated files. The name of the target depends on the mode and includes # a normalized path to the input bif to make it unique. The target is added # automatically to bro_ALL_GENERATED_OUTPUTS. macro(bif_target bifInput) set(target "") get_filename_component(bifInputBasename "${bifInput}" NAME) if ( "${ARGV1}" STREQUAL "standard" ) set(bifcl_args "") set(target "bif-std-${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}") set(bifOutputs ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.func_def ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.func_h ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.func_init ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.netvar_def ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.netvar_h ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}.netvar_init) set(BIF_OUTPUT_CC ${bifInputBasename}.func_def ${bifInputBasename}.func_init ${bifInputBasename}.netvar_def ${bifInputBasename}.netvar_init) set(BIF_OUTPUT_H ${bifInputBasename}.func_h ${bifInputBasename}.netvar_h) set(BIF_OUTPUT_BRO ${CMAKE_BINARY_DIR}/scripts/base/bif/${bifInputBasename}.bro) set(bro_BASE_BIF_SCRIPTS ${bro_BASE_BIF_SCRIPTS} ${BIF_OUTPUT_BRO} CACHE INTERNAL "Bro script stubs for BIFs in base distribution of Bro" FORCE) # Propogate to top-level elseif ( "${ARGV1}" STREQUAL "plugin" ) set(plugin_name ${ARGV2}) set(plugin_name_canon ${ARGV3}) set(plugin_is_static ${ARGV4}) set(target "bif-plugin-${plugin_name_canon}-${bifInputBasename}") set(bifcl_args "-p;${plugin_name}") set(bifOutputs ${bifInputBasename}.h ${bifInputBasename}.cc ${bifInputBasename}.init.cc ${bifInputBasename}.register.cc) if ( plugin_is_static ) set(BIF_OUTPUT_CC ${bifInputBasename}.cc ${bifInputBasename}.init.cc) set(bro_REGISTER_BIFS ${bro_REGISTER_BIFS} ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename} CACHE INTERNAL "BIFs for automatic registering" FORCE) # Propagate to top-level. else () set(BIF_OUTPUT_CC ${bifInputBasename}.cc ${bifInputBasename}.init.cc ${bifInputBasename}.register.cc) endif() set(BIF_OUTPUT_H ${bifInputBasename}.h) if ( NOT BRO_PLUGIN_BUILD_DYNAMIC ) set(BIF_OUTPUT_BRO ${CMAKE_BINARY_DIR}/scripts/base/bif/plugins/${plugin_name_canon}.${bifInputBasename}.bro) else () set(BIF_OUTPUT_BRO ${BRO_PLUGIN_BIF}/${bifInputBasename}.bro) endif() set(bro_PLUGIN_BIF_SCRIPTS ${bro_PLUGIN_BIF_SCRIPTS} ${BIF_OUTPUT_BRO} CACHE INTERNAL "Bro script stubs for BIFs in Bro plugins" FORCE) # Propogate to top-level else () # Alternative mode. These will get compiled in automatically. set(bifcl_args "-s") set(target "bif-alt-${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename}") set(bifOutputs ${bifInputBasename}.h ${bifInputBasename}.cc ${bifInputBasename}.init.cc) set(BIF_OUTPUT_CC ${bifInputBasename}.cc) set(BIF_OUTPUT_H ${bifInputBasename}.h) # In order be able to run bro from the build directory, the # generated bro script needs to be inside a directory tree # named the same way it will be referenced from an @load. set(BIF_OUTPUT_BRO ${CMAKE_BINARY_DIR}/scripts/base/bif/${bifInputBasename}.bro) set(bro_AUTO_BIFS ${bro_AUTO_BIFS} ${CMAKE_CURRENT_BINARY_DIR}/${bifInputBasename} CACHE INTERNAL "BIFs for automatic inclusion" FORCE) # Propagate to top-level. set(bro_BASE_BIF_SCRIPTS ${bro_BASE_BIF_SCRIPTS} ${BIF_OUTPUT_BRO} CACHE INTERNAL "Bro script stubs for BIFs in base distribution of Bro" FORCE) # Propogate to top-level endif () if ( BRO_PLUGIN_INTERNAL_BUILD ) set(bifclDep "bifcl") endif () if ( BRO_PLUGIN_INTERNAL_BUILD ) set(BifCl_EXE "bifcl") else () set(BifCl_EXE "${BRO_PLUGIN_BRO_BUILD}/src/bifcl") endif () add_custom_command(OUTPUT ${bifOutputs} ${BIF_OUTPUT_BRO} COMMAND ${BifCl_EXE} ARGS ${bifcl_args} ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} || (rm -f ${bifOutputs} && exit 1) COMMAND "${CMAKE_COMMAND}" ARGS -E copy ${bifInputBasename}.bro ${BIF_OUTPUT_BRO} COMMAND "${CMAKE_COMMAND}" ARGS -E remove -f ${bifInputBasename}.bro DEPENDS ${bifInput} DEPENDS ${bifclDep} COMMENT "[BIFCL] Processing ${bifInput}" ) string(REGEX REPLACE "${CMAKE_BINARY_DIR}/src/" "" target "${target}") string(REGEX REPLACE "/" "-" target "${target}") add_custom_target(${target} DEPENDS ${BIF_OUTPUT_H} ${BIF_OUTPUT_CC}) set_source_files_properties(${bifOutputs} PROPERTIES GENERATED 1) set(BIF_BUILD_TARGET ${target}) set(bro_ALL_GENERATED_OUTPUTS ${bro_ALL_GENERATED_OUTPUTS} ${target} CACHE INTERNAL "automatically generated files" FORCE) # Propagate to top-level. endmacro(bif_target) # A macro to create a __load__.bro file for all *.bif.bro files in # a given collection (which should all be in the same directory). # It creates a corresponding target to trigger the generation. function(bro_bif_create_loader target bifinputs) set(_bif_loader_dir "") foreach ( _bro_file ${bifinputs} ) get_filename_component(_bif_loader_dir_tmp ${_bro_file} PATH) get_filename_component(_bro_file_name ${_bro_file} NAME) if ( _bif_loader_dir ) if ( NOT _bif_loader_dir_tmp STREQUAL _bif_loader_dir ) message(FATAL_ERROR "Directory of Bro script BIF stub ${_bro_file} differs from expected: ${_bif_loader_dir}") endif () else () set(_bif_loader_dir ${_bif_loader_dir_tmp}) endif () set(_bif_loader_content "${_bif_loader_content} ${_bro_file_name}") endforeach () if ( NOT _bif_loader_dir ) return () endif () file(MAKE_DIRECTORY ${_bif_loader_dir}) set(_bif_loader_file ${_bif_loader_dir}/__load__.bro) add_custom_target(${target} COMMAND "sh" "-c" "rm -f ${_bif_loader_file}" COMMAND "sh" "-c" "for i in ${_bif_loader_content}; do echo @load ./$i >> ${_bif_loader_file}; done" WORKING_DIRECTORY ${_bif_loader_dir} VERBATIM ) add_dependencies(${target} generate_outputs) endfunction() # A macro to create joint include files for compiling in all the # autogenerated bif code. function(bro_bif_create_includes target dstdir bifinputs) file(MAKE_DIRECTORY ${dstdir}) add_custom_target(${target} COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.cc.tmp" COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.init.cc.tmp" COMMAND for i in ${bifinputs}\; do echo \\\#include \\"\$\$i.cc\\"\; done >> ${dstdir}/__all__.bif.cc.tmp COMMAND for i in ${bifinputs}\; do echo \\\#include \\"\$\$i.init.cc\\"\; done >> ${dstdir}/__all__.bif.init.cc.tmp COMMAND ${CMAKE_COMMAND} -E copy_if_different "${dstdir}/__all__.bif.cc.tmp" "${dstdir}/__all__.bif.cc" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${dstdir}/__all__.bif.init.cc.tmp" "${dstdir}/__all__.bif.init.cc" COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.cc.tmp" COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.init.cc.tmp" WORKING_DIRECTORY ${dstdir} ) set(clean_files ${dstdir}/__all__.bif.cc ${dstdir}/__all__.bif.init.cc) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean_files}") endfunction() function(bro_bif_create_register target dstdir bifinputs) file(MAKE_DIRECTORY ${dstdir}) add_custom_target(${target} COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.register.cc.tmp" COMMAND for i in ${bifinputs}\; do echo \\\#include \\"\$\$i.register.cc\\"\; done >> ${dstdir}/__all__.bif.register.cc.tmp COMMAND ${CMAKE_COMMAND} -E copy_if_different "${dstdir}/__all__.bif.register.cc.tmp" "${dstdir}/__all__.bif.register.cc" COMMAND "sh" "-c" "rm -f ${dstdir}/__all__.bif.register.cc.tmp" WORKING_DIRECTORY ${dstdir} ) set(clean_files ${dstdir}/__all__.bif.cc ${dstdir}/__all__.bif.register.cc) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean_files}") endfunction() broccoli-1.97-minimal/cmake/SetupRPATH.cmake0000664002342100234210000000053012523041064020464 0ustar johannajohanna# Keep RPATH upon installing so that user doesn't have to ensure the linker # can find internal/private libraries or libraries external to the build # directory that were explicitly linked against if (NOT BINARY_PACKAGING_MODE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif () broccoli-1.97-minimal/cmake/CommonCMakeConfig.cmake0000664002342100234210000000036212523041064022047 0ustar johannajohannaset(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) include(CheckCompilers) include(ProhibitInSourceBuild) include(AddUninstallTarget) include(SetupRPATH) include(SetDefaultCompileFlags) include(MacDependencyPaths) broccoli-1.97-minimal/cmake/FindRequiredPackage.cmake0000664002342100234210000000303712523041064022427 0ustar johannajohanna# A wrapper macro around the standard CMake find_package macro that # facilitates displaying better error messages by default, or even # accepting custom error messages on a per package basis. # # If a package is not found, then the MISSING_PREREQS variable gets # set to true and either a default or custom error message appended # to MISSING_PREREQ_DESCS. # # The caller can use these variables to display a list of any missing # packages and abort the build/configuration if there were any. # # Use as follows: # # include(FindRequiredPackage) # FindRequiredPackage(Perl) # FindRequiredPackage(FLEX "You need to install flex (Fast Lexical Analyzer)") # # if (MISSING_PREREQS) # foreach (prereq ${MISSING_PREREQ_DESCS}) # message(SEND_ERROR ${prereq}) # endforeach () # message(FATAL_ERROR "Configuration aborted due to missing prerequisites") # endif () macro(FindRequiredPackage packageName) find_package(${packageName}) string(TOUPPER ${packageName} canonPackageName) if (NOT ${canonPackageName}_FOUND) set(MISSING_PREREQS true) set(customDesc) foreach (descArg ${ARGN}) set(customDesc "${customDesc} ${descArg}") endforeach () if (customDesc) # append the custom error message that was provided as an argument list(APPEND MISSING_PREREQ_DESCS ${customDesc}) else () list(APPEND MISSING_PREREQ_DESCS " Could not find prerequisite package '${packageName}'") endif () endif () endmacro(FindRequiredPackage) broccoli-1.97-minimal/cmake/CheckOptionalBuildSources.cmake0000664002342100234210000000165012523041064023640 0ustar johannajohanna# A macro that checks whether optional sources exist and if they do, they # are added to the build/install process, else a warning is issued # # _dir: the subdir of the current source dir in which the optional # sources are located # _packageName: a string that identifies the package # _varName: name of the variable indicating whether package is scheduled # to be installed macro(CheckOptionalBuildSources _dir _packageName _varName) if (${_varName}) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}/CMakeLists.txt) add_subdirectory(${_dir}) else () message(WARNING "${_packageName} source code does not exist in " "${CMAKE_CURRENT_SOURCE_DIR}/${_dir} " "so it will not be built or installed") set(${_varName} false) endif () endif () endmacro(CheckOptionalBuildSources) broccoli-1.97-minimal/cmake/GetArchitecture.cmake0000664002342100234210000000052712523041064021655 0ustar johannajohanna # Determine a tag for the host architecture (e.g., "linux-x86_64"). # We run uname ourselves here as CMAKE by default uses -p rather than # -m. execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE) set(HOST_ARCHITECTURE "${CMAKE_SYSTEM_NAME}-${arch}") string(TOLOWER ${HOST_ARCHITECTURE} HOST_ARCHITECTURE) broccoli-1.97-minimal/cmake/FindLibcaf.cmake0000664002342100234210000000701212523041064020550 0ustar johannajohanna# Try to find libcaf headers and library. # # Use this module as follows: # # find_package(Libcaf) # # Variables used by this module (they can change the default behaviour and need # to be set before calling find_package): # # LIBCAF_ROOT_DIR Set this variable to the root installation of # libcaf if the module has problems finding # the proper installation path. # # Variables defined by this module: # # LIBCAF_FOUND System has libcaf headers and library # LIBCAF_LIBRARIES List of library files for all components # LIBCAF_INCLUDE_DIRS List of include paths for all components # LIBCAF_LIBRARY_$C Library file for component $C # LIBCAF_INCLUDE_DIR_$C Include path for component $C # iterate over user-defined components foreach (comp ${Libcaf_FIND_COMPONENTS}) # we use uppercase letters only for variable names string(TOUPPER "${comp}" UPPERCOMP) if ("${comp}" STREQUAL "core") set(HDRNAME "caf/all.hpp") else () set(HDRNAME "caf/${comp}/all.hpp") endif () # look for headers: give CMake hints where to find non-installed CAF versions # note that we look for the headers of each component individually: this is # necessary to support non-installed versions of CAF, i.e., accessing the # checked out "actor-framework" directory structure directly set(HDRHINT "actor-framework/libcaf_${comp}") find_path(LIBCAF_INCLUDE_DIR_${UPPERCOMP} NAMES ${HDRNAME} HINTS ${LIBCAF_ROOT_DIR}/include /usr/include /usr/local/include /opt/local/include /sw/include ${CMAKE_INSTALL_PREFIX}/include ../${HDRHINT} ../../${HDRHINT} ../../../${HDRHINT}) mark_as_advanced(LIBCAF_INCLUDE_DIR_${UPPERCOMP}) if ("${LIBCAF_INCLUDE_DIR_${UPPERCOMP}}" STREQUAL "LIBCAF_INCLUDE_DIR_${UPPERCOMP}-NOTFOUND") # exit on first error break () else () # add to LIBCAF_INCLUDE_DIRS only if path isn't already set set(duplicate false) foreach (p ${LIBCAF_INCLUDE_DIRS}) if (${p} STREQUAL ${LIBCAF_INCLUDE_DIR_${UPPERCOMP}}) set(duplicate true) endif () endforeach () if (NOT duplicate) set(LIBCAF_INCLUDE_DIRS ${LIBCAF_INCLUDE_DIRS} ${LIBCAF_INCLUDE_DIR_${UPPERCOMP}}) endif() endif () # look for (.dll|.so|.dylib) file, again giving hints for non-installed CAFs find_library(LIBCAF_LIBRARY_${UPPERCOMP} NAMES "caf_${comp}" HINTS ${LIBCAF_ROOT_DIR}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib ${CMAKE_INSTALL_PREFIX}/lib ../actor-framework/build/lib ../../actor-framework/build/lib ../../../actor-framework/build/lib) mark_as_advanced(LIBCAF_LIBRARY_${UPPERCOMP}) if ("${LIBCAF_LIBRARY_${UPPERCOMP}}" STREQUAL "LIBCAF_LIBRARY-NOTFOUND") # exit on first error break () else () set(LIBCAF_LIBRARIES ${LIBCAF_LIBRARIES} ${LIBCAF_LIBRARY_${UPPERCOMP}}) endif () endforeach () # final steps to tell CMake we're done include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Libcaf DEFAULT_MSG LIBCAF_LIBRARIES LIBCAF_INCLUDE_DIRS) mark_as_advanced(LIBCAF_ROOT_DIR LIBCAF_LIBRARIES LIBCAF_INCLUDE_DIRS) broccoli-1.97-minimal/cmake/CheckNameserCompat.cmake0000664002342100234210000000136012523041064022263 0ustar johannajohannainclude(CheckCSourceCompiles) # Check whether the namser compatibility header is required # This can be the case on the Darwin platform set(CMAKE_REQUIRED_INCLUDES ${BIND_INCLUDE_DIR}) check_c_source_compiles(" #include int main() { HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; }" have_nameser_header) if (NOT have_nameser_header) check_c_source_compiles(" #include #include int main() { HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; }" NEED_NAMESER_COMPAT_H) if (NOT NEED_NAMESER_COMPAT_H) message(FATAL_ERROR "Asynchronous DNS support compatibility check failed.") endif () endif () set(CMAKE_REQUIRED_INCLUDES) broccoli-1.97-minimal/cmake/RequireCXX11.cmake0000664002342100234210000000412612523041064020733 0ustar johannajohanna# Detect if compiler version is sufficient for supporting C++11. # If it is, CMAKE_CXX_FLAGS are modified appropriately and HAVE_CXX11 # is set to a true value. Else, CMake exits with a fatal error message. # This currently only works for GCC and Clang compilers. # In Cmake 3.1+, CMAKE_CXX_STANDARD_REQUIRED should be able to replace # all the logic below. if ( DEFINED HAVE_CXX11 ) return() endif () set(required_gcc_version 4.8) set(required_clang_version 3.3) # CMAKE_CXX_COMPILER_VERSION may not always be available (e.g. particularly # for CMakes older than 2.8.10, but use it if it exists. if ( DEFINED CMAKE_CXX_COMPILER_VERSION ) if ( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if ( CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${required_gcc_version} ) message(FATAL_ERROR "GCC version must be at least " "${required_gcc_version} for C++11 support, detected: " "${CMAKE_CXX_COMPILER_VERSION}") endif () elseif ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) if ( CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${required_clang_version} ) message(FATAL_ERROR "Clang version must be at least " "${required_clang_version} for C++11 support, detected: " "${CMAKE_CXX_COMPILER_VERSION}") endif () endif () set(HAVE_CXX11 true) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") return() endif () # Need to manually retrieve compiler version. if ( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE gcc_version) if ( ${gcc_version} VERSION_LESS ${required_gcc_version} ) message(FATAL_ERROR "GCC version must be at least " "${required_gcc_version} for C++11 support, manually detected: " "${CMAKE_CXX_COMPILER_VERSION}") endif () elseif ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) # TODO: don't seem to be any great/easy ways to get a clang version string. endif () set(HAVE_CXX11 true) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") broccoli-1.97-minimal/cmake/bro-plugin-create-package.sh0000775002342100234210000000172012523041064023034 0ustar johannajohanna#! /bin/sh # # Helper script creating a tarball with a plugin's binary distribution. We'll # also leave a MANIFEST in place with all files part of the tar ball. # # Called from BroPluginDynamic.cmake. Current directory is the plugin # build directory. if [ $# = 0 ]; then echo "usage: `basename $0` []" exit 1 fi name=$1 shift addl=$@ # Copy additional distribution files into build directory. for i in ${addl}; do if [ -e ../$i ]; then dir=`dirname $i` mkdir -p ${dir} cp -p ../$i ${dir} fi done tgz=${name}-`(test -e ../VERSION && cat ../VERSION | head -1) || echo 0.0`.tar.gz rm -f MANIFEST ${name} ${name}.tgz ${tgz} for i in __bro_plugin__ lib scripts ${addl}; do test -e $i && find -L $i -type f | sed "s%^%${name}/%g" >>MANIFEST done ln -s . ${name} mkdir -p dist tar czf dist/${tgz} -T MANIFEST ln -s dist/${tgz} ${name}.tgz rm -f ${name} broccoli-1.97-minimal/cmake/InstallSymlink.cmake0000664002342100234210000000347512523041064021555 0ustar johannajohanna# This macro can be used to install symlinks, which turns out to be # non-trivial due to CMake version differences and limitations on how # files can be installed when building binary packages. # # The rule for binary packaging is that files (including symlinks) must # be installed with the standard CMake install() macro. # # The rule for non-binary packaging is that CMake 2.6 cannot install() # symlinks, but can create the symlink at install-time via scripting. # Though, we assume that CMake 2.6 isn't going to be used to generate # packages because versions later than 2.8.3 are superior for that purpose. # # _filepath: the absolute path to the file to symlink # _sympath: absolute path of the installed symlink macro(InstallSymlink _filepath _sympath) get_filename_component(_symname ${_sympath} NAME) get_filename_component(_installdir ${_sympath} PATH) if (BINARY_PACKAGING_MODE) execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink ${_filepath} ${CMAKE_CURRENT_BINARY_DIR}/${_symname}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_symname} DESTINATION ${_installdir}) else () # scripting the symlink installation at install time should work # for CMake 2.6.x and 2.8.x install(CODE " if (\"\$ENV{DESTDIR}\" STREQUAL \"\") execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ${_filepath} ${_installdir}/${_symname}) else () execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ${_filepath} \$ENV{DESTDIR}/${_installdir}/${_symname}) endif () ") endif () endmacro(InstallSymlink) broccoli-1.97-minimal/cmake/FindRocksDB.cmake0000664002342100234210000000216212523041064020660 0ustar johannajohanna# Try to find RocksDB headers and library. # # Usage of this module as follows: # # find_package(RocksDB) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # ROCKSDB_ROOT_DIR Set this variable to the root installation of # RocksDB if the module has problems finding the # proper installation path. # # Variables defined by this module: # # ROCKSDB_FOUND System has RocksDB library/headers. # ROCKSDB_LIBRARIES The RocksDB library. # ROCKSDB_INCLUDE_DIRS The location of RocksDB headers. find_path(ROCKSDB_ROOT_DIR NAMES include/rocksdb/db.h ) find_library(ROCKSDB_LIBRARIES NAMES rocksdb HINTS ${ROCKSDB_ROOT_DIR}/lib ) find_path(ROCKSDB_INCLUDE_DIRS NAMES rocksdb/db.h HINTS ${ROCKSDB_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(RocksDB DEFAULT_MSG ROCKSDB_LIBRARIES ROCKSDB_INCLUDE_DIRS ) mark_as_advanced( ROCKSDB_ROOT_DIR ROCKSDB_LIBRARIES ROCKSDB_INCLUDE_DIRS ) broccoli-1.97-minimal/cmake/FindBIND.cmake0000664002342100234210000000550012523041064020104 0ustar johannajohanna# - Try to find libpcap include dirs and libraries # # Usage of this module as follows: # # find_package(BIND) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # BIND_ROOT_DIR Set this variable to the root installation of BIND # if the module has problems finding the proper # installation path. # # Variables defined by this module: # # BIND_FOUND System has BIND, include and library dirs found # BIND_INCLUDE_DIR The BIND include directories. # BIND_LIBRARY The BIND library (if any) required for # ns_inittab and res_mkquery symbols find_path(BIND_ROOT_DIR NAMES include/bind/resolv.h include/resolv.h ) find_path(BIND_INCLUDE_DIR NAMES resolv.h HINTS ${BIND_ROOT_DIR}/include/bind ${BIND_ROOT_DIR}/include ) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # the static resolv library is preferred because # on some systems, the ns_initparse symbol is not # exported in the shared library (strangely) # see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=291609 set(bind_libs none libresolv.a resolv bind) else () set(bind_libs none resolv bind) endif () include(CheckCSourceCompiles) # Find which library has the res_mkquery and ns_initparse symbols set(CMAKE_REQUIRED_INCLUDES ${BIND_INCLUDE_DIR}) foreach (bindlib ${bind_libs}) if (NOT ${bindlib} MATCHES "none") find_library(BIND_LIBRARY NAMES ${bindlib} HINTS ${BIND_ROOT_DIR}/lib ) endif () set(CMAKE_REQUIRED_LIBRARIES ${BIND_LIBRARY}) check_c_source_compiles(" #include int main() { ns_initparse(0, 0, 0); return 0; } " ns_initparse_works_${bindlib}) check_c_source_compiles(" #include #include #include #include #include int main() { int (*p)() = res_mkquery; return 0; } " res_mkquery_works_${bindlib}) set(CMAKE_REQUIRED_LIBRARIES) if (ns_initparse_works_${bindlib} AND res_mkquery_works_${bindlib}) break () else () set(BIND_LIBRARY BIND_LIBRARY-NOTFOUND) endif () endforeach () set(CMAKE_REQUIRED_INCLUDES) include(FindPackageHandleStandardArgs) if (ns_initparse_works_none AND res_mkquery_works_none) # system does not require linking to a BIND library find_package_handle_standard_args(BIND DEFAULT_MSG BIND_INCLUDE_DIR ) else () find_package_handle_standard_args(BIND DEFAULT_MSG BIND_LIBRARY BIND_INCLUDE_DIR ) endif () mark_as_advanced( BIND_ROOT_DIR BIND_LIBRARY BIND_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/MacDependencyPaths.cmake0000664002342100234210000000062212523041064022266 0ustar johannajohanna# As of CMake 2.8.3, Fink and MacPorts search paths are appended to the # default search prefix paths, but the nicer thing would be if they are # prepended to the default, so that is fixed here. if (APPLE AND "${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") list(INSERT CMAKE_SYSTEM_PREFIX_PATH 0 /opt/local) # MacPorts list(INSERT CMAKE_SYSTEM_PREFIX_PATH 0 /sw) # Fink endif () broccoli-1.97-minimal/cmake/FindBro.cmake0000664002342100234210000000206012523041064020110 0ustar johannajohanna# - Try to find Bro installation # # Usage of this module as follows: # # find_package(Bro) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # BRO_ROOT_DIR Set this variable to the root installation of # Bro if the module has problems finding the # proper installation path. # # Variables defined by this module: # # BRO_FOUND Bro NIDS is installed # BRO_EXE path to the 'bro' binary if (BRO_EXE AND BRO_ROOT_DIR) # this implies that we're building from the Bro source tree set(BRO_FOUND true) return() endif () find_program(BRO_EXE bro HINTS ${BRO_ROOT_DIR}/bin /usr/local/bro/bin) if (BRO_EXE) get_filename_component(BRO_ROOT_DIR ${BRO_EXE} PATH) get_filename_component(BRO_ROOT_DIR ${BRO_ROOT_DIR} PATH) endif () include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Bro DEFAULT_MSG BRO_EXE) mark_as_advanced(BRO_ROOT_DIR) broccoli-1.97-minimal/cmake/FindLibMagic.cmake0000664002342100234210000000404712523041064021044 0ustar johannajohanna# - Try to find libmagic header and library # # Usage of this module as follows: # # find_package(LibMagic) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # LibMagic_ROOT_DIR Set this variable to the root installation of # libmagic if the module has problems finding the # proper installation path. # # Variables defined by this module: # # LIBMAGIC_FOUND System has libmagic, magic.h, and file # LibMagic_FILE_EXE Path to the 'file' command # LibMagic_VERSION Version of libmagic # LibMagic_LIBRARY The libmagic library # LibMagic_INCLUDE_DIR The location of magic.h find_path(LibMagic_ROOT_DIR NAMES include/magic.h ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # the static version of the library is preferred on OS X for the # purposes of making packages (libmagic doesn't ship w/ OS X) set(libmagic_names libmagic.a magic) else () set(libmagic_names magic) endif () find_file(LibMagic_FILE_EXE NAMES file HINTS ${LibMagic_ROOT_DIR}/bin ) find_library(LibMagic_LIBRARY NAMES ${libmagic_names} HINTS ${LibMagic_ROOT_DIR}/lib ) find_path(LibMagic_INCLUDE_DIR NAMES magic.h HINTS ${LibMagic_ROOT_DIR}/include ) if (LibMagic_FILE_EXE) execute_process(COMMAND "${LibMagic_FILE_EXE}" --version ERROR_VARIABLE LibMagic_VERSION OUTPUT_VARIABLE LibMagic_VERSION) string(REGEX REPLACE "^file-([0-9.]+).*$" "\\1" LibMagic_VERSION "${LibMagic_VERSION}") message(STATUS "libmagic version: ${LibMagic_VERSION}") else () set(LibMagic_VERSION NOTFOUND) endif () include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LibMagic DEFAULT_MSG LibMagic_LIBRARY LibMagic_INCLUDE_DIR LibMagic_FILE_EXE LibMagic_VERSION ) mark_as_advanced( LibMagic_ROOT_DIR LibMagic_FILE_EXE LibMagic_VERSION LibMagic_LIBRARY LibMagic_INCLUDE_DIR ) broccoli-1.97-minimal/cmake/UserChangedWarning.cmake0000664002342100234210000000137012523041064022306 0ustar johannajohanna# Show warning when installing user is different from the one that configured, # except when the install is root. if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") install(CODE " if (NOT \"$ENV{USER}\" STREQUAL \"\$ENV{USER}\" AND NOT \"\$ENV{USER}\" STREQUAL root) message(STATUS \"WARNING: Install is being performed by user \" \"'\$ENV{USER}', but the build directory was configured by \" \"user '$ENV{USER}'. This may result in a permissions error \" \"when writing the install manifest, but you can ignore it \" \"and consider the installation as successful if you don't \" \"care about the install manifest.\") endif () ") endif () broccoli-1.97-minimal/cmake/BroPluginStatic.cmake0000664002342100234210000000262612523041064021646 0ustar johannajohanna## A set of functions for defining Bro plugins. ## ## This set is for plugins compiled in statically. ## See BroPluginsDynamic.cmake for the dynamic version. function(bro_plugin_bif_static) foreach ( bif ${ARGV} ) bif_target(${bif} "plugin" ${_plugin_name} ${_plugin_name_canon} TRUE) list(APPEND _plugin_objs ${BIF_OUTPUT_CC}) list(APPEND _plugin_deps ${BIF_BUILD_TARGET}) set(_plugin_objs "${_plugin_objs}" PARENT_SCOPE) set(_plugin_deps "${_plugin_deps}" PARENT_SCOPE) endforeach () endfunction() function(bro_plugin_link_library_static) foreach ( lib ${ARGV} ) set(bro_SUBDIR_LIBS ${bro_SUBDIR_LIBS} "${lib}" CACHE INTERNAL "plugin libraries") endforeach () endfunction() function(bro_plugin_end_static) if ( bro_HAVE_OBJECT_LIBRARIES ) add_library(${_plugin_lib} OBJECT ${_plugin_objs}) set(_target "$") else () add_library(${_plugin_lib} STATIC ${_plugin_objs}) set(_target "${_plugin_lib}") endif () if ( NOT "${_plugin_deps}" STREQUAL "" ) add_dependencies(${_plugin_lib} ${_plugin_deps}) endif () add_dependencies(${_plugin_lib} generate_outputs) set(bro_PLUGIN_LIBS ${bro_PLUGIN_LIBS} "${_target}" CACHE INTERNAL "plugin libraries") endfunction() macro(_plugin_target_name_static target ns name) set(${target} "plugin-${ns}-${name}") endmacro() broccoli-1.97-minimal/cmake/FindPythonDev.cmake0000664002342100234210000000462112523041064021313 0ustar johannajohanna# - Try to find Python include dirs and libraries # # Usage of this module as follows: # # find_package(PythonDev) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # PYTHON_EXECUTABLE If this is set to a path to a Python interpreter # then this module attempts to infer the path to # python-config from it # PYTHON_CONFIG Set this variable to the location of python-config # if the module has problems finding the proper # installation path. # # Variables defined by this module: # # PYTHONDEV_FOUND System has Python dev headers/libraries # PYTHON_INCLUDE_DIR The Python include directories. # PYTHON_LIBRARIES The Python libraries and linker flags. include(FindPackageHandleStandardArgs) if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}-config) set(PYTHON_CONFIG ${PYTHON_EXECUTABLE}-config CACHE PATH "" FORCE) else () find_program(PYTHON_CONFIG NAMES python-config python-config2.7 python-config2.6 python-config2.6 python-config2.4 python-config2.3) endif () # The OpenBSD python packages have python-config's that don't reliably # report linking flags that will work. if (PYTHON_CONFIG AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") execute_process(COMMAND "${PYTHON_CONFIG}" --ldflags OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) execute_process(COMMAND "${PYTHON_CONFIG}" --includes OUTPUT_VARIABLE PYTHON_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) string(REGEX REPLACE "^[-I]" "" PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}") string(REGEX REPLACE "[ ]-I" " " PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}") separate_arguments(PYTHON_INCLUDE_DIR) find_package_handle_standard_args(PythonDev DEFAULT_MSG PYTHON_CONFIG PYTHON_INCLUDE_DIR PYTHON_LIBRARIES ) else () find_package(PythonLibs) if (PYTHON_INCLUDE_PATH AND NOT PYTHON_INCLUDE_DIR) set(PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_PATH}") endif () find_package_handle_standard_args(PythonDev DEFAULT_MSG PYTHON_INCLUDE_DIR PYTHON_LIBRARIES ) endif () broccoli-1.97-minimal/cmake/InstallClobberImmune.cmake0000664002342100234210000000255612523041064022651 0ustar johannajohanna# Determines at `make install` time if a file, typically a configuration # file placed in $PREFIX/etc, shouldn't be installed to prevent overwrite # of an existing file. # # _srcfile: the file to install # _dstfile: the absolute file name after installation macro(InstallClobberImmune _srcfile _dstfile) install(CODE " set(_destfile \"${_dstfile}\") if (NOT \"\$ENV{DESTDIR}\" STREQUAL \"\") # prepend install root prefix with install-time DESTDIR set(_destfile \"\$ENV{DESTDIR}/${_dstfile}\") endif () if (EXISTS \${_destfile}) message(STATUS \"Skipping: \${_destfile} (already exists)\") execute_process(COMMAND \"${CMAKE_COMMAND}\" -E compare_files ${_srcfile} \${_destfile} RESULT_VARIABLE _diff) if (NOT \"\${_diff}\" STREQUAL \"0\") message(STATUS \"Installing: \${_destfile}.example\") configure_file(${_srcfile} \${_destfile}.example COPYONLY) endif () else () message(STATUS \"Installing: \${_destfile}\") # install() is not scriptable within install(), and # configure_file() is the next best thing configure_file(${_srcfile} \${_destfile} COPYONLY) # TODO: create additional install_manifest files? endif () ") endmacro(InstallClobberImmune) broccoli-1.97-minimal/cmake/ProhibitInSourceBuild.cmake0000664002342100234210000000045612523041064023004 0ustar johannajohanna# Prohibit in-source builds. if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "In-source builds are not allowed. Please use " "./configure to choose a build directory and " "initialize the build configuration.") endif () broccoli-1.97-minimal/cmake/FindTraceSummary.cmake0000664002342100234210000000070412523041064022005 0ustar johannajohanna# - Try to find the trace-summary Python program # # Usage of this module as follows: # # find_package(TraceSummary) # # Variables defined by this module: # # TRACESUMMARY_FOUND capstats binary found # TraceSummary_EXE path to the capstats executable binary find_program(TRACE_SUMMARY_EXE trace-summary) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(TraceSummary DEFAULT_MSG TRACE_SUMMARY_EXE) broccoli-1.97-minimal/cmake/BroSubdir.cmake0000664002342100234210000000077112523041064020467 0ustar johannajohanna # Creates a target for a library of objects file in a subdirectory, # and adds to the global bro_SUBDIR_LIBS. function(bro_add_subdir_library name) if ( bro_HAVE_OBJECT_LIBRARIES ) add_library("bro_${name}" OBJECT ${ARGN}) set(_target "$") else () add_library("bro_${name}" STATIC ${ARGN}) set(_target "bro_${name}") endif () set(bro_SUBDIR_LIBS "${_target}" ${bro_SUBDIR_LIBS} CACHE INTERNAL "subdir libraries") endfunction() broccoli-1.97-minimal/cmake/package_postupgrade.sh.in0000775002342100234210000000435712523041064022552 0ustar johannajohanna#!/bin/sh # This script is meant to be used by binary packages post-installation. # Variables between @ symbols are replaced by CMake at configure time. backupNamesFile=/tmp/bro_install_backups version=@VERSION@ sampleFiles="" # check whether it's safe to remove backup configuration files that # the most recent package install created if [ -e ${backupNamesFile} ]; then backupFileList=`cat ${backupNamesFile}` for backupFile in ${backupFileList}; do origFileName=`echo ${backupFile} | sed 's/\(.*\)\..*/\1/'` diff ${origFileName} ${backupFile} > /dev/null 2>&1 if [ $? -eq 0 ]; then # if the installed version and the backup version don't differ # then we can remove the backup version and the example file rm ${backupFile} rm ${origFileName}.example else # The backup file differs from the newly installed version, # since we can't tell if the backup version has been modified # by the user, we should restore it to its original location # and rename the new version appropriately. sampleFiles="${sampleFiles}\n${origFileName}.example" mv ${backupFile} ${origFileName} fi done rm ${backupNamesFile} fi if [ -n "${sampleFiles}" ]; then # Use some apple script to display a message to user /usr/bin/osascript << EOF tell application "System Events" activate display alert "Existing configuration files differ from the ones that would be installed by this package. To avoid overwriting configuration which you may have modified, the following new config files have been installed:\n${sampleFiles}\n\nIf you have previously modified configuration files, please make sure that they are still compatible, else you should update your config files to the new versions." end tell EOF fi # Set up world writeable spool and logs directory for broctl, making sure # to set the sticky bit so that unprivileged users can't rename/remove files. # (CMake/CPack is supposed to install them, but has problems with empty dirs) if [ -n "@EMPTY_WORLD_DIRS@" ]; then for dir in "@EMPTY_WORLD_DIRS@"; do mkdir -p ${dir} chmod 777 ${dir} chmod +t ${dir} done fi broccoli-1.97-minimal/cmake/CheckHeaders.cmake0000664002342100234210000000306712523041064021106 0ustar johannajohannainclude(CheckIncludeFiles) include(CheckStructHasMember) include(CheckSymbolExists) check_include_files(getopt.h HAVE_GETOPT_H) check_include_files(memory.h HAVE_MEMORY_H) check_include_files("sys/socket.h;netinet/in.h;net/if.h;netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H) check_include_files("sys/socket.h;netinet/in.h;net/if.h;netinet/ip6.h" HAVE_NETINET_IP6_H) check_include_files("sys/socket.h;net/if.h;net/ethernet.h" HAVE_NET_ETHERNET_H) check_include_files(sys/ethernet.h HAVE_SYS_ETHERNET_H) check_include_files(net/ethertypes.h HAVE_NET_ETHERTYPES_H) check_include_files(sys/time.h HAVE_SYS_TIME_H) check_include_files("time.h;sys/time.h" TIME_WITH_SYS_TIME) check_include_files(os-proto.h HAVE_OS_PROTO_H) check_struct_has_member(HISTORY_STATE entries "stdio.h;readline/readline.h" HAVE_READLINE_HISTORY_ENTRIES) check_include_files("stdio.h;readline/readline.h" HAVE_READLINE_READLINE_H) check_include_files("stdio.h;readline/history.h" HAVE_READLINE_HISTORY_H) if (HAVE_READLINE_READLINE_H AND HAVE_READLINE_HISTORY_H AND HAVE_READLINE_HISTORY_ENTRIES) set(HAVE_READLINE true) endif () check_struct_has_member("struct sockaddr_in" sin_len "netinet/in.h" SIN_LEN) macro(CheckIPProto _proto) check_symbol_exists(IPPROTO_${_proto} netinet/in.h HAVE_IPPROTO_${_proto}) endmacro(CheckIPProto _proto) CheckIPProto(HOPOPTS) CheckIPProto(IPV6) CheckIPProto(IPV4) CheckIPProto(ROUTING) CheckIPProto(FRAGMENT) CheckIPProto(ESP) CheckIPProto(AH) CheckIPProto(ICMPV6) CheckIPProto(NONE) CheckIPProto(DSTOPTS) broccoli-1.97-minimal/cmake/ConfigurePackaging.cmake0000664002342100234210000002311312523041064022315 0ustar johannajohanna# A collection of macros to assist in configuring CMake/Cpack # source and binary packaging # Sets CPack version variables by splitting the first macro argument # using "." or "-" as a delimiter. If the length of the split list is # greater than 2, all remaining elements are tacked on to the patch # level version. Not that the version set by the macro is internal # to binary packaging, the file name of our package will reflect the # exact version number. macro(SetPackageVersion _version) string(REGEX REPLACE "[.-]" " " version_numbers ${_version}) separate_arguments(version_numbers) list(GET version_numbers 0 CPACK_PACKAGE_VERSION_MAJOR) list(REMOVE_AT version_numbers 0) list(GET version_numbers 0 CPACK_PACKAGE_VERSION_MINOR) list(REMOVE_AT version_numbers 0) list(LENGTH version_numbers version_length) while (version_length GREATER 0) list(GET version_numbers 0 patch_level) if (CPACK_PACKAGE_VERSION_PATCH) set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}.${patch_level}") else () set(CPACK_PACKAGE_VERSION_PATCH ${patch_level}) endif () list(REMOVE_AT version_numbers 0) list(LENGTH version_numbers version_length) endwhile () if (APPLE) # Mac PackageMaker package requires only numbers in the versioning string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) if (CPACK_PACKAGE_VERSION_PATCH) string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) endif () endif () if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # RPM version accepts letters, but not dashes. string(REGEX REPLACE "[-]" "." CPACK_PACKAGE_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) string(REGEX REPLACE "[-]" "." CPACK_PACKAGE_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) if (CPACK_PACKAGE_VERSION_PATCH) string(REGEX REPLACE "[-]" "." CPACK_PACKAGE_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) endif () endif () # Minimum supported OS X version set(CPACK_OSX_PACKAGE_VERSION 10.5) endmacro(SetPackageVersion) # Sets the list of desired package types to be created by the make # package target. A .tar.gz is only made for source packages, and # binary pacakage format depends on the operating system: # # Darwin - PackageMaker # Linux - RPM if the platform has rpmbuild installed # DEB if the platform has dpkg-shlibdeps installed # # CPACK_GENERATOR is set by this macro # CPACK_SOURCE_GENERATOR is set by this macro macro(SetPackageGenerators) set(CPACK_SOURCE_GENERATOR TGZ) #set(CPACK_GENERATOR TGZ) if (APPLE) list(APPEND CPACK_GENERATOR PackageMaker) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_program(RPMBUILD_EXE rpmbuild) find_program(DPKGSHLIB_EXE dpkg-shlibdeps) if (RPMBUILD_EXE) set(CPACK_GENERATOR ${CPACK_GENERATOR} RPM) endif () if (DPKGSHLIB_EXE) set(CPACK_GENERATOR ${CPACK_GENERATOR} DEB) set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS true) endif () endif () endmacro(SetPackageGenerators) # Sets CPACK_PACKAGE_FILE_NAME in the following format: # # --- # # and CPACK_SOURCE_PACKAGE_FILE_NAME as: # # - macro(SetPackageFileName _version) if (PACKAGE_NAME_PREFIX) set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME_PREFIX}-${_version}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PACKAGE_NAME_PREFIX}-${_version}") else () set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${_version}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${_version}") endif () set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CMAKE_SYSTEM_NAME}") if (APPLE) # Only Intel-based Macs are supported. CMAKE_SYSTEM_PROCESSOR may # return the confusing 'i386' if running a 32-bit kernel, but chances # are the binary is x86_64 (or more generally 'Intel') compatible. set(arch "Intel") else () set (arch ${CMAKE_SYSTEM_PROCESSOR}) endif () set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${arch}") endmacro(SetPackageFileName) # Sets up binary package metadata macro(SetPackageMetadata) set(CPACK_PACKAGE_VENDOR "International Computer Science Institute") set(CPACK_PACKAGE_CONTACT "info@bro.org") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Bro Network Intrusion Detection System") # CPack may enforce file name extensions for certain package generators configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/README.txt COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/COPYING ${CMAKE_CURRENT_BINARY_DIR}/COPYING.txt COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/MAC_PACKAGE_INTRO ${CMAKE_CURRENT_BINARY_DIR}/MAC_PACKAGE_INTRO.txt) set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_BINARY_DIR}/README.txt) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_BINARY_DIR}/COPYING.txt) set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_BINARY_DIR}/README.txt) set(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_BINARY_DIR}/MAC_PACKAGE_INTRO.txt) set(CPACK_RPM_PACKAGE_LICENSE "BSD") set(CPACK_RPM_PACKAGE_GROUP "Applications/System") set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /opt /var /var/opt) endmacro(SetPackageMetadata) # Sets pre and post install scripts for PackageMaker packages. # The main functionality that such scripts offer is a way to make backups # of "configuration" files that a user may have modified. # Note that RPMs already have a robust mechanism for dealing with # user-modified files, so we do not need this additional functionality macro(SetPackageInstallScripts VERSION) if (INSTALLED_CONFIG_FILES) # Remove duplicates from the list of installed config files separate_arguments(INSTALLED_CONFIG_FILES) list(REMOVE_DUPLICATES INSTALLED_CONFIG_FILES) # Space delimit the list again foreach (_file ${INSTALLED_CONFIG_FILES}) set(_tmp "${_tmp} ${_file}") endforeach () set(INSTALLED_CONFIG_FILES "${_tmp}" CACHE STRING "" FORCE) endif () if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # DEB packages can automatically handle configuration files # if provided in a "conffiles" file in the packaging set(conffiles_file ${CMAKE_CURRENT_BINARY_DIR}/conffiles) if (INSTALLED_CONFIG_FILES) string(REPLACE " " ";" conffiles ${INSTALLED_CONFIG_FILES}) endif () file(WRITE ${conffiles_file} "") foreach (_file ${conffiles}) file(APPEND ${conffiles_file} "${_file}\n") endforeach () list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CMAKE_CURRENT_BINARY_DIR}/conffiles) # RPMs don't need any explicit direction regarding config files. # Leaving the set of installed config files empty will just # bypass the logic in the default pre/post install scripts and let # the RPMs/DEBs do their own thing (regarding backups, etc.) # when upgrading packages. set(INSTALLED_CONFIG_FILES "") endif () if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh @ONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in ${CMAKE_CURRENT_BINARY_DIR}/preinst @ONLY) set(CPACK_PREFLIGHT_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh) set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh) list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CMAKE_CURRENT_BINARY_DIR}/preinst) endif () if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh @ONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in ${CMAKE_CURRENT_BINARY_DIR}/postinst @ONLY) set(CPACK_POSTUPGRADE_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh) set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh) list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CMAKE_CURRENT_BINARY_DIR}/postinst) endif () endmacro(SetPackageInstallScripts) # Main macro to configure all the packaging options macro(ConfigurePackaging _version) SetPackageVersion(${_version}) SetPackageGenerators() SetPackageFileName(${_version}) SetPackageMetadata() SetPackageInstallScripts(${_version}) set(CPACK_SET_DESTDIR true) set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) # add default files/directories to ignore for source package # user may specify others via configure script list(APPEND CPACK_SOURCE_IGNORE_FILES ${CMAKE_BINARY_DIR} ".git") include(CPack) endmacro(ConfigurePackaging) broccoli-1.97-minimal/cmake/SetDefaultCompileFlags.cmake0000664002342100234210000000174612523041064023125 0ustar johannajohanna# Set up the default flags and CMake build type once during the configuration # of the top-level CMake project. if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused") if ( NOT CMAKE_BUILD_TYPE ) if ( ENABLE_DEBUG ) set(CMAKE_BUILD_TYPE Debug) else () set(CMAKE_BUILD_TYPE RelWithDebInfo) endif () endif () string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type_upper) if ( "${_build_type_upper}" STREQUAL "DEBUG" ) # manual add of -g works around its omission in FreeBSD's CMake port set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -g -DDEBUG -DBRO_DEBUG") endif () # Compiler flags may already exist in CMake cache (e.g. when specifying # CFLAGS environment variable before running cmake for the the first time) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") endif () broccoli-1.97-minimal/cmake/FindReadline.cmake0000664002342100234210000000274412523041064021122 0ustar johannajohanna# - Try to find readline include dirs and libraries # # Usage of this module as follows: # # find_package(Readline) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # Readline_ROOT_DIR Set this variable to the root installation of # readline if the module has problems finding the # proper installation path. # # Variables defined by this module: # # READLINE_FOUND System has readline, include and lib dirs found # Readline_INCLUDE_DIR The readline include directories. # Readline_LIBRARY The readline library. find_path(Readline_ROOT_DIR NAMES include/readline/readline.h ) find_path(Readline_INCLUDE_DIR NAMES readline/readline.h HINTS ${Readline_ROOT_DIR}/include ) find_library(Readline_LIBRARY NAMES readline HINTS ${Readline_ROOT_DIR}/lib ) if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) set(READLINE_FOUND TRUE) else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) FIND_LIBRARY(Readline_LIBRARY NAMES readline) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY ) MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY) endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) mark_as_advanced( Readline_ROOT_DIR Readline_INCLUDE_DIR Readline_LIBRARY ) broccoli-1.97-minimal/cmake/FindSubnetTree.cmake0000664002342100234210000000144612523041064021455 0ustar johannajohanna# - Determine if the SubnetTree Python module is available # # Usage of this module as follows: # # find_package(PythonInterp REQUIRED) # find_package(SubnetTree) # # Variables defined by this module: # # SUBNETTREE_FOUND Python successfully imports SubnetTree module if (NOT SUBNETTREE_FOUND) execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import SubnetTree" RESULT_VARIABLE SUBNETTREE_IMPORT_RESULT) if (SUBNETTREE_IMPORT_RESULT) # python returned non-zero exit status set(SUBNETTREE_PYTHON_MODULE false) else () set(SUBNETTREE_PYTHON_MODULE true) endif () endif () include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SubnetTree DEFAULT_MSG SUBNETTREE_PYTHON_MODULE) broccoli-1.97-minimal/doc/0000775002342100234210000000000012523041064015252 5ustar johannajohannabroccoli-1.97-minimal/doc/images/0000775002342100234210000000000012523041064016517 5ustar johannajohannabroccoli-1.97-minimal/doc/images/caution.gif0000664002342100234210000000517312523041064020656 0ustar johannajohanna‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ ¢lÿ IDATxœíš[l\ÅÇsÎz½»^{ã½8¶×ıKRÖµ‹±Æ$ª£4G¡JÀD`SµÔЏ(BB<ä(RJ„„*RH•ª}EEŠ¢@D…(‚@ˆHjcš¤'¾ÅŽ/{±×»}˜9ëãõÚÞ]¢ö¥#ÎÙ9çÌüÿßmf¾Yøùßq›û2úÓRôb꿃ގ>İ̭~ªÃvãa®MÙ¼{þ LÓÜ&2?„€øóصØ· ÿ&üåü¢H2Y“È–€ôx>G‚I«Ä„>èøŽ`Š,µ¡gú =åà¨7?˜ÂH± ¤#˜‹r äY¡µ» Ó>c™j@k‡åøT€ßü ‡×‹¿© _U›[§OsñèQ„¦ÅïG€ @ƒã‡àQ`L5gdR™H >®€L»ÝTïØÁÝ>ŠÛíÆét"„ì~¬·—óo½E÷‘#Œ÷÷3 Í"­ÁLJà—H¿0”˜‰t ¤?©F,ߺ•-/¼@qq16›mÞN‚ýý|ºw/×¾ø‚±¾>â±X‚„€‚Ç€‘LH¤ãó‚¹Ýlܳ‡MO>III V«!ļÕêt²¢¥…ÑžÂÃÃLNL Çb‰¶âN°tÂW ¼fX6›:4˜ÁOz<´¼ú*[¶àr¹Ð4mAðæZ±i…\;}šÈØ5åÐÿ|ÇLˆÍš€*÷çHûÕë”×Ë–W^!°v-ùùùi7׊ ¦#ú/\ cQ‚É…µqø¤†ICóÈp¹Á¿7ãÈP±ª£ƒú{ïÅívgÞ¨e„‡†è;žX4Šˆ€½ ÎÂdd6HdD@r6Â' ŒÆ1à'O=ņÇcéÒ¥ó;pào¼ñï¼óW¯^¥±±1å{š¦á è;{–Ñ7±:o%è]Ò¦X ´¦" ý×°;Ç´¦ Í/¾Hii)‹%%¨ýû÷3<xÖÜ8T=ø ¥+VàõzvÎÂB.]ºÄÈÈÈì‰RMÏ=‡oåJ4‹Ä™+Á­¼6ùªI'iîJ& í€Š\øÑì>Í»wSTT´ ˆ„„Ãá9’º~ýú‚ßlÞ»WY iJå°X¢´° èKáó a vçNÇ‚¦#„ ¤¤„P(D0œCÀï÷/•JV­¢¸ºš<4% ühl0iaÖfÉL@ÛËÍÒ¹^/«ÛÚðx<‹°Z­sÀi‡ÖõÏ<ƒ5/Oö¥D^)MÚÅŒ/Ì! Í ™U­­,*}ÃÆN§søúúú´ øëêð×Õ¡çæÂ âÊuÐ8¯„Ìrlð´YúºÏÇÚ¶¶79²x<*++É”€‚õ»váôz¹Ð2¹p6Láß`¢µÃz J! ¢¹™üüü”‹´ùBbMM ‡ƒâââíÛ·gD tÍ–­[—Ђȃ»<ÅK„¡Ý N#§¿U;wαýù€› LLL«÷ûý444dD@AMk+ùEE -hÀø…"`˜QB«| |YM E³ké¬8¶nÝŠÝnÇjµÒÑÑ‘1x!wµ´`±ÙmŠfæÃŒ„h-P®A‰A ”oÚ”pÜŤž\ÛÚÚ¨­­eÛ¶mìÚµ++B–¯_Ožò«D¾F°+Å  ù`½Ù|b@Õ}÷áñxдT«ÅËÁƒ³úHhòÎÍ›ùשSM#Gí§ïmŸÁ§°蹦ÍJÈóùp•–&öµÿ­š¬éÚ c/,…8GÃt ÐtÓV1 øjj²Þ¨twwóÒK/qÿý÷ÓÞÞNgggÆÀÍuÅæÍ‰õ‘ȇ•ÈÀdt  Ç“ÖD¾ª*\.WB•™”×_ÞÞ^:;;¥¿¿ŸãÇ/h* §Ï—0c ˆÉ‹ÍL@‹›¦æ(Pè÷c·Û³"pêÔ)¹~ý:ŸþyÊ~ÒíÛ_WÇ7o¿ Ȱã„2äšÈ h@Ä“Vx×ÎËÚyËÊÊèííMünjjš6S¡@ÓõĽ]î5‘>' n®œ;G4ÍÊöíÛG H€íµ×² ÅF½úÕWÄã3»ÉQèE*CG…Ñx¾qÀµœ<|˜Ÿ?òHÆ«®®æÄ‰3Ì ÍåògŸT. Æ‘–(¿„¯Í nà?λ/¿|ÛBb¦õÊ—_òç‡fèÒ%‚CC€Ü›ŒÃ¿1/ä̶ôWðž#Qè÷³ªµ•Ï>Káw,*±*ñoæËC‡º|™[×®%òQàìí“ÙŠn ×Øø¸WBýfxÓ*²”76²ê¡‡¨hj¢¼¡aÖ³l÷ôÐsæ >ø€î>"Çfc*fb``Vx8£À?K@¿ ±Ì t9ÜÝ¿³ÊL@Ê"t<‡Üü|ü«WSPZJIu5%%Äãqc‰ß?ç»oß{/qáý÷šÆ÷ǃÄc1&ƒAâÓÓoÞ$‹GÚÉ8roü-üíkø;pEï†UJRò~`Ùxzü, êV+9v;9v;±éES™RšFljŠÉ`h$¦(E.&'‘þ8ýçàÃïápCè€ ãdÑ‚2%䪴´~\ MwBS®);w;‹!e#k5ÅÌÉÎ0\<§»á"p D†Ð^~ ˜4‹æ £h!à|êê @`%¬)„eKL»¶tKÌTÍIÿIYi¢017®À?ÎÀyfL¸©@÷«ûq¤¢bfÏÓš°!7ÏKLÕ¥Úòû]Pé÷R(àžÝE6ù<%c^”ö‹ñè²@ô iQÅ)‚LŽ+ð·™ê¤Ôƒê½D5C VEDmGÉW5OµÙ™YØHœÝ%fÈäÞP€a5†åD‘–3Ibž"¤$?®+Ð!EÎPbœ¤AÌ$ "9 d®jWW›j3HX£¦:©7ˆà§’ÀGfV`ûIf2Ôs²Ô oƒˆ¦È˜ÄŒûdð 0\!™ˆQ£¦ë´é’Á/F ùƒŒ™”fªfÓ™¯_CõfsŠ1¨ù/‹žg3}𠉤ßéôOq§hO«ü‰öÿDðB8IEND®B`‚broccoli-1.97-minimal/doc/images/warning.gif0000664002342100234210000000443512523041064020661 0ustar johannajohanna‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ "~ïªIDATxœí™[lWÇsÙÙ»/ëk×Nb;‰ÛÜhJHÒ¦êS“•€Z(¢ÚHÜ‘ŠWT^*DûO @Š jàÔ¤\” IHÓ4Á¹P¹IlÇØ±7öÞo³gx˜{vf×Þ5 íCÿÒÑÌžÛüÿçûÎw¾™…ð>识£ŒYuŸûà¨-~àªI×+c˜"?48LcÄk Ùùð]@?p†•‘w–{âVR“ýmò«j5vj>>³a˜Oô÷aÈ¿»x™?ŽO-5ßQàóMr¨B3ê’ïð©|c×¾³ªTéT ¤²9NfJ›âèäzóþO"P—üÁ­›ùᎭPH!Æ'©YÈ@†Áµp3>?$^ú×(#éÜ=¡¬”|§æãÏ<Å—z¨Ü¸Ž¸z#7zdI’è*‰ËÌúýìïjc¢XæV®à~Æ& œ½~ ìrVôœþÒgL'©\¼™äéZRau!KQQéŽÅØp*1ïb•{&àà7ùSÏ ëÎ bt¨8f  !uõ!µD12)0­ÓKhªJJÑ*W½î´ÓR÷BÀNàgîÊ_>ó)6§ˆסâ /ËÈ›¶ Çû‘üA¤`J:F6Y5>¦‘ü~Z¢Q2Å2·òUîÔŠimÏsW"àŒ5á^ÞÿÏútÄÍQ(«:Ë«Q‡7󵿞å¹c'øþÅÆìׄgâîrD0LG(ÀÛ‰$yQå~«hb?ÈuêãÚ´Ûã½|«3€¿ y—éeyÍ_ÿÛ[¼öÎå…ê_MòÍ´Ä5­Åó€=É;¬ ùöð@­ç¿Š£~ ,fùê`ÍqI+8xÒÛƒ»·#&o.5ÞD:eÁ¦vo´ÙØF“E}É)†r)6†Ô¦­àPå>½¡ Cx|D&è|¬£ÍÓ¶¹5B›¤£ÖÞ $‰°¨ðÂÐêZÍ/Öª„E;qÅý§·nA$fAñD”2P.±oÀºww¶©,½úIæÁìƒ!_-+Ô}ù‘ëu8´6Ž›XöÁ¸3ŧƒ2ÝÚâRwj>:UÕÅ̲S ´WÊ<ï©Õ¥¦ˆš¶ÆÚé.š/% #9Èdø¢ãd}²§¡@T¯œ0 ƒ®Ržµ­áZÍ5¨˜Ñ§Ê}<¼ æN1=ÉwKÝí”…ÁÞ¾.É&¤ÆÞ›$I¢·\`‡¬°§³S³Uû¯®€]îÊgcAÄÆ› ªò‹°Á¨â§?5G Ëû¿ñB†Ý10EuV¨¸BT—_£/èGÏ4ih òÈ­m´†lKfЯ^€&¼Ð†"Iìk ðo“'JȸÜgG¼‘NÞÜÊÉ=«¹ xìØIZr„=oœà¨eNñQYâ«­¤³§Ó–=ÞâIæ¶õÇ¡äΗª"wÅ8ü—·xwö.—’i~tí&g1&‚‘æædº5­_Ç{ŒŒëËĪX«ifP‘s).Í$ªª¯¤³ä¥F^½½ØõD£Ob’·…H œ›„ž*%Œä »R‰M­JBЗÉ67pWÕÈ:_YMôAL x,ð[+ðYcfš—·m`kÌ| }¨%ÌÞ.:4aÅCdI¤•‘B™ëiðw?°D 瀧íïÎñšo˜'Õ<1½‰½ ëìšçøÚNF†û˜F¡ÓÐùøì,“91¡…8Ÿ‚®sÖ›‡Í`Z bq æô_qözsì6…P ½­Qr†JH”ú€„$PË%(æX_ÌÒWÊ#7èþ·å §£œË æŠe~36Åxѳ€oïb~€€0pØáîS/ÞÍ€$ʧhÓK Ÿ¬Ë¡lŒú[™†H”Ê\žKsb*Á¿sùzC¾\Ãüj‘ò¶€5ÀŸx½‘E‚<Öc(âÑ€™ß´-ãbB‚œ¬’R5DtU&§¨$‰÷ÒYÎ'Rüs~ÙÈ÷cà’VÉÙ|À€Õ¡®ˆ*Aá íšu‘±€†Á`(L<¬¡XA ‚„fT8ÈP‘ ò• ç)4EæL"¹ÌªðsL/™±Ì[ ²ø0w÷÷€ç›™ý>â6ð{àp“ü]LJ…ŃA²ÊßßZ×aZèÿ÷€ãÀŸ€I‹l ÈX¥äŠ„ùN­`†%Ÿõ[ôF3ÿxóøð}"œ¦ë˜_§óVÉ`nÖy`κÚB @I²ˆË–;¬*˜†½?¢Ö}Ø‚™®Ú­±kp}G­ƒkŽûë˜ápĺ”-bºE¯Ü}AþÕàk5ù%'N—±R›à^¶’(vÜ¢,Í’¸Rxã¹®&ë;öŠYdTRp"°9Î9ìi:æÚæöÞ7Áp» pJÁŒòÁKŽ@õÍsÞé^¾ºÝ‰cAáC=ß,I<^Iù? H²æ’§‘þEõ¿c˜ë‹†V9Ô`«HÙÞI$Û?–+±:Þì8ھіÛžüÛõª¿YYâ¶·º‘îC‚ÑFÙP¸ädpŽFG®kŽ ß´mœø°,‹  mÎs…ó<&òª1÷ªÔÙŽ¹{>ˆÒu˜u (åfD”¬›»7—ë]ÒÝÛÂ@–UR|‰ªIÖ'±’)X\<£˜f˜!2pKd•Àôõ⥮z˜ÞlK•–I˜‰C–ÞG×5j×N1¦­ƒÔô¯—½íµØco2Hí%Npk}QÇ©^ÆKxẂÎyÝÅ":°ÈçâËsŽFMXZ[Zj%­Éð¦bR£wlÜîù|êœ:µ*SÙ±˜ó©löè¯3EXP{I}­5­‚XZ\"\OÀJöå<óùbÖõXô&âíÚ0é4i#Àí_?õ«.¯q=ľ q³ø¦7eÀ>¾ 9·nx¯;]™×j<ù17[2ë›."¿ ¤ðÚ?áõrØàäá€Èô=ê=ïo`ºðobð-bfE•€Â£ábHÜ1#Ï—òYÙ &’u²Rí”1bx,xÉäã¸âµXÇÕb³Òæ3N Ê]°÷ÎH/òžø¯6t—-l3}¥%…£$(­"¢XÎACŒeA*ã9ïšÐý@¾ò#¸ÜªÎJçiaÁÚ£r¼÷ãÓ½DÄ‹¤É"H|6ZBx’Æ{Àç<óÀ¦;ƶŒÝ7» 6$»²*»ã#±†ä`gšd0'ÁŠLsµ¸‰¡’1¶%‘0!•¤¡[¶8hw2É¡ݙ߮5¡UX~}àx^á#9ÀùvÇ9®}>m8[‰màýê ѳ·ÎàB¨8ôÏ5î¨þ$Æ.Õncøiˆƒ¹;mI<ÒÄÚ”sø‚á%Ùp\¸ÇáãéNŸÑÈÆÑ3uÔ÷> êšvŸ’7úðEðã=ñžå½xÅc¨Jˆ×>óžŒÆ$-i’È?tyÏz]7SŠ Y#p*ž³M2õm–¯Ò§J×lÁ½´‹~¡n€:‘Ùqðœc#ôªã‚+ÆÆûk‚:tµ»hVò;›97#2©Võ Èàöó=ª|Y\ÚE¤<»$¶bÛpÜw#׿4l¨È±T—^Æ|Ç÷¦=V–Êáô}QY"ݵ•Ç1°ì§ÔFUq{ò+,]Z-)®.´­nÉYvLy¡#?˜Ís{G…î`ÓÆr¡œƒèxÿ©];bOä¨ñÓ#ž> W½I¹Ò,¤Ï :‚}R?¾+Í׊rOÊ¿Ýyþ…ÆWý«ÿL:1 6÷¹dñ”1õ ²4˧¸¤m‚Kµb¤¹I2?§â›4|‰O¥W¤jZxÈ£Á”QEP8ù£YÔšk‹ÈîX—YYeœ«4g¸ÜNO—Áò¤Ö½–ÔÊ,åðí ø[QOÞ“ÜœŽüwãŽ)¯ì¯tvâÎöÐãï÷¦Œ”“8o»cØ9ô¥ ·´‹"¨Ü6‚qÏΤŅEn-DîÓÒ¹™n$ž%Úï2Ày G9õ#=ê‘“†ž{Ô–‹£ÞkÚ¬}™ŒÜ\’ÈûG““ô™µdWd…ã†ÚùWþÚl·þ¬ªcvm![GÓu^ôÙéV¯w8C'„¸ÉQÜóß½ö³Ú\”Ôìg´˜÷Dcý°+Q‹RÑõÞ—V‘Ÿ‡phO˱§}/Ú_QGµÕ-­5›La’î1¸êÌr HŒ@’ÞPJùv5Õqª5ì­â“wÄsù•þVõúÓ´Ðô'RƒîÆ^—ÕOáÿ¶vô'°óø~”¹wÓóÛß B1 Î3ªwG2ù20áõ©¤¿T·®L?lmèmtËkî1hÜÎy÷«/S´VéÉ£BX&$Sô Õ`.ô MLŠ@ÌUïÓº„zž–«ÊéŒgõãf—Ûer[ÆI¯É]k†g¢³Iwc—BŸ˜ä~Ù§m:ØÄ 7zP„ŧjJîÁHubp¨ý)ö6WEd ©yÕIÉÕ…ÁðÇé¾=/ƒ*(¢½R’¸ö¯ÓÃWÓmî"²žâê&ئ bXáˆCŸ*«4_g·E†¨±H¶ vd¸"9%‡»J¸ÆÉr|ëèëðLcЉ#šêW¹Æ*ôßAèý5{q{m{©ds„c¿FqÇlùÓFÚÈ+-µ 9nì­oá0Þ[Csî“F~†’õŸdÚ¡ºM<Í¥Î{èÿ4?àŠ~Û^í®5~@ùã_èͦ՚úÔ_Xú˜àþCºÿo.„!c–ÒáŒQÂ2Çjg¾•}SН:»Ù}¦¦$¾ÐÄvWç,ÐöŠcôþóR¥‹˜™kз§Å¥õF–aW : +ä×OKO7Oêm§]–6Z74•dnôIŸÁx. m·íÁ«&Ý­:‚Ö)•Ô8•‰ÇÔWƒªÆñ§ñþ&HÖÆÎ¡êµ £‚6SÒ;AýêÏ阮!é½>;¬øÂ¸ãÓöªº.P))&ì0È8«Æñ!GÆ7(8ª~™¥&3OÛfÊ(¢½‚£H…OEÏjbo\ÔµxÊ`ŒÐ'†kÝ•#% '+úVÛJ°çÈ×l†½Ù]OnUˆ±ðÏ¥€µ¹aVO,ÖA{Vèã5Ë#­º=~Ø\Ûì‹S‰~êl`H?‘þ^‡Êª]*I4íJKØä·Ãí’6àÄÿü5ôÑEeÚFE!u×C¦µ½³UMF%·a2ÿ#ƒåô©õVXµÈ¹Ã© “ëºÕ¥ˆòHïWpvª÷Ù†žb‡Qºš&ID¢r»y#õ#ô« ±£ÇÑ åœÅVQEV4(¢Š(¢Š+ŠG"Š(£°¬¨¢€ ñ”2àŒŠ(¡„Q$jB(9?:ÙEQEÿÙbroccoli-1.97-minimal/doc/images/note.gif0000664002342100234210000000575512523041064020167 0ustar johannajohanna‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs  d_‘tIMEÓ  „¼  zIDATxœíš{lÅÇ?³»÷²}vÎ>'±ã$@ÇÆ&OC\"^ „h^¤ ”¶iDKZ E¨¥UªV-¢ª*‚øƒ"$„D¨¢­šðŠBªVäÅ+BZœ†(qœøì»óÝùövúÇìîížÏŽ"õŸŽ4ºÝÙy|¿¿×üf÷àÿå[Ğ˙O+3·,ûW^ÈE/Ä‚ÆEDÄ:àJ V¹O%Ç)°ŸŒÜÎÓæ_€ À"óexßÁ=ç‘} Ègy±ð;`0QdΛÄù€Îfã~âw%¬„4§9)À…]@ÈsžÚÐ';ÐØh´p•¾]|Û÷$/!ƒ’©Ê¼E* ˆuÌý|*?ñ€Ÿ4Éj@ãvc&uâmM¾'Y>‰ÓÝt%­õ­„+ÂìÜËÎÏv¡¡aaêàuž1¿ $QÚ˜”IM†@yðHKb…«Û¿ÆKî ¶¶–ªª*„PÓ:Á?z¿D_ê4™|¦”Ä›G%—˹ý¼&WŽ„#ë/¹–€DCSfЭÝT8f¤:aÏaÅ”Ä+â4Mitϵc…ÏRi†ánZÞ’Ïç ƒcjr,]Û¹š\>Ë”Š)E-¢‘¢èJÞ£¢ —Mm/{P/9dÜÃKI‰ÅbnÿRÓ+ç[N½~ÎuÅüÈj˜ãÑ€nØÎà[±­¾•šššQ1~¬â,–Ïç9uê™LÆ÷<‰¸9T¹êÌQ®Ä«âÅP(H åÄ HO†gBS¬‰H$rN x8ÒO$®;¥¡¡ÊI}O"‘`ÕªU.`o™ÈB€.la L5ÅœH÷%F šßÿüCLÓ$L¼”’P(ÄO<Á–-[èííEAWW[¶lq5Uº Ÿ«ìÿâ]ߦHRž@éB„HÒ¼O„T <Ä »ÿÄí+6Lʤ”Äb1üqߦå\OV³ÿ8òOsCê&/!K ìÕ|€E¿|·ˆˆÁwžþ.¿þëCöÇ–½„¼¡v¼HS®î=ºol»ƒÞþ^ΟU“f¤<Šçû‚@ílÓ¸Ëx‘ˆhuØZkšÒȺεܷüšk›GIÈ’–%œtÙÂÎõumâ/Á_xïÏ<³oGÎü‡ãƒ'Ô‹/l™'%ì,<Äiy8 œ¨˜ZË¥b _ÕŸ" jÇš¼«e)ë:×Ð=k]3‹{Ÿ´´8ïÆ+ÇÎcß±¼Òó*¯~ƒP L.Ÿåtºßÿ8|d½ÄÖNàß@/Ð'Pá( 4Ò"s³þkA]èÔUÖ EélꤱºËÚ™^=)%‹š2#Ö4jÜK¾ €…䥞—Ñ…Îë‡ß@õ&/Ʋ œP/}%ÊPRR]´^æ=ëïÀç6øcÀ€:«¡h.bµ~7ÍÚÕãŠÎ.A-H8¦ÂˆPç|• €¦e2<2L.ŸC öL”Äó(LÉ>Þ·^ã3Ùœ´ Nig0pL €F¦‰¹´kÝ\"º ‹ê !›lq¤lJ÷ (‘&äg´Þá_ò3`èNØõ4êƒÈˆ÷³hµAÄ€8PoÿÖ0W´2W[@L\ÄQ<µM¨”þwlŽ”uÀ$MJžä¨ü˜ÖG¨˜“F}ô8kƒî³¯S¨ƒ¦åõ0 ¥‰0êð<ÅSkì¶J Â\1›jQKƒ˜Ôb¢S S9&g¥~Ù €Žä˜<„É>«EmÄ6lƒBIõá#IñLì†Qoqä´‰TØ £v­´Û"ó‘0J{Nbè$‡Þ¹-Š/¤ vuŒ&oA}«ÉØ’OÙ€S6èŒMÎùr#¡4(’pˆl!hÄþ Ûm‰ MÀ©å¾Ô;Dðùð9”Ùdm°ÎõˆÝÏ!î‹×ãi‡ˆf“ñtˆ9×¥àÇ#`Qô/§šžß‚g ¥àÏE ´CÆKJóT¯éŒ5¯£z¯9Yøzÿ‚pÎoÇçó¥ÞKH”ÜOdNYæW–iŸPù/ňû#°æIEND®B`‚broccoli-1.97-minimal/doc/README0000664002342100234210000000051312523041064016131 0ustar johannajohannaBroccoli API documentation is currently generated with the help of Doxygen. The Doxygen input file is configured by CMake from ``Doxyfile.in`` after running ``./configure`` from the source root, and then (if Doxygen is installed), running ``make doc`` will generate the API docs, using ``build/doc/html`` as the output directory. broccoli-1.97-minimal/doc/broccoli-manual.rst0000664002342100234210000015534412523041064021067 0ustar johannajohanna=============================================== Broccoli: The Bro Client Communications Library =============================================== This page documents Broccoli, the Bro client communications library. It allows you to create client sensors for the Bro intrusion detection system. Broccoli can speak a good subset of the Bro communication protocol, in particular, it can receive Bro IDs, send and receive Bro events, and send and receive event requests to/from peering Bros. .. contents:: Introduction ############ What is Broccoli? ================= Broccoli is the BRO Client COmmunications LIbrary. It allows you to write applications that speak the communication protocol of the `Bro intrusion detection system `_. Broccoli is free software under terms of the BSD license as given in the COPYING file distributed with its source code. In this document, we assume that you are familiar with the basic concepts of Bro, so please first review the documentation/publications available from the Bro website if necessary. Feedback, patches and bug reports are all welcome, please see http://www.bro.org/community for instructions on how to participate in the Bro community. Why do I care? ============== Having a single IDS on your network is good, but things become a lot more interesting when you can communicate information among multiple vantage points in your network. Bro agents can communicate with other Bro agents, sending and receiving events and other state information. In the Bro context this is particularly interesting because it means that you can build sophisticated policy-controlled distributed event management systems. Broccoli enters the picture when it comes to integrating components that are not Bro agents themselves. Broccoli lets you create applications that can speak the Bro communication protocol. You can compose, send, request, and receive events. You can register your own event handlers. You can talk to other Broccoli applications or Bro agents -- Bro agents cannot tell whether they are talking to another Bro or a Broccoli application. Broccoli allows you to integrate applications of your choosing into a distributed policy-controlled event management system. Broccoli is intended to be portable: it should build on Linux, the BSDs, Solaris, and Windows (in the `MinGW `_ environment). Unlike other distributed IDSs, Bro does not assume a strict sensor-manager hierarchy in the information flow. Instead, Bro agents can request delivery of arbitrary *events* from other instances. When an event is triggered in a Bro agent, it checks whether any connected agents have requested notification of this event, and sends a *copy* of the event, including the *event arguments*. Recall that in Bro, an event handler is essentially a function defined in the Bro language, and an event materializes through invocation of an event handler. Each remote agent can define its own event handlers. Broccoli applications will typically do one or more of the following: - *Configuration/Management Tasks:* the Broccoli application is used to configure remotely running Bros without the need for a restart. - *Interfacing with other Systems:* the Broccoli application is used to convert Bro events to other alert/notice formats, or into syslogd entries. - *Host-based Sensor Feeds into Bro:* the Broccoli application reports events based on host-based activity generated in kernel space or user space applications. Installing Broccoli ################### The installation process will hopefully be painless: Broccoli is installed from source using the usual ``./configure && make && make install`` routine after extraction of the tarball. Some relevant configuration options to pass to configure are: - ``--prefix=``: sets the installation root to DIR. The default is to install below ``/usr/local``. - ``--enable-debug``: enables debugging output. Please refer to the `Configuring Debugging Output`_ section for details on configuring and using debugging output. - ``--with-configfile=``: use FILE as location of configuration file. See the section on `Configuration Files`_ for more on this. - ``--with-openssl=``: use the OpenSSL installation below DIR. After installation, you'll find the library in shared and static versions in ``/lib``, the header file for compilation in ``/include``. Using Broccoli ############## Obtaining information about your build using ``broccoli-config`` ================================================================ Similarly to many other software packages, the Broccoli distribution provides a script that you can use to obtain details about your Broccoli setup. The script currently provides the following flags: - ``--build`` prints the name of the machine the build was made on, when, and whether debugging support was enabled or not. - ``--prefix`` prints the directory in the filesystem below which Broccoli was installed. - ``--version`` prints the version of the distribution you have installed. - ``--libs`` prints the flags to pass to the linker in order to link in the Broccoli library. - ``--cflags`` prints the flags to pass to the compiler in order to properly include Broccoli's header file. - ``--config`` prints the location of the system-wide config file your installation will use. The ``--cflags`` and ``--libs`` flags are the suggested way of obtaining the necessary information for integrating Broccoli into your build environment. It is generally recommended to use ``broccoli-config`` for this purpose, rather than, say, develop new **autoconf** tests. If you use the **autoconf/automake** tools, we recommend something along the following lines for your ``configure`` script:: dnl ################################################## dnl # Check for Broccoli dnl ################################################## AC_ARG_WITH(broccoli-config, AC_HELP_STRING(\[--with-broccoli-config=FILE], \[Use given broccoli-config]), [ brocfg="$withval" ], [ AC_PATH_GENERIC(broccoli,, brocfg="broccoli-config", AC_MSG_ERROR(Cannot find Broccoli: Is broccoli-config in path? Use more fertilizer?)) ]) broccoli_libs=`$brocfg --libs` broccoli_cflags=`$brocfg --cflags` AC_SUBST(broccoli_libs) AC_SUBST(broccoli_cflags)`` You can then use the compiler/linker flags in your Makefile.in/ams by substituting in the values accordingly, which might look as follows:: CFLAGS = -W -Wall -g -DFOOBAR @broccoli_cflags@ LDFLAGS = -L/usr/lib/foobar @broccoli_libs@ Suggestions for instrumenting applications ========================================== Often you will want to make existing applications Bro-aware, that is, *instrument* them so that they can send and receive Bro events at appropriate moments in the execution flow. This will involve modifying an existing code tree, so care needs to be taken to avoid unwanted side effects. By protecting the instrumented code with ``#ifdef``/``#endif`` statements you can still build the original application, using the instrumented source tree. The ``broccoli-config`` script helps you in doing so because it already adds ``-DBROCCOLI`` to the compiler flags reported when run with the ``--cflags`` option: .. console:: > broccoli-config --cflags -I/usr/local/include -I/usr/local/include -DBROCCOLI So simply surround all inserted code with a preprocessor check for ``BROCCOLI`` and you will be able to build the original application as soon as ``BROCCOLI`` is not defined. The Broccoli API ================ Time for some code. In the code snippets below we will introduce variables whenever context requires them and not necessarily when C requires them. The library does not require calling a global initialization function. In order to make the API known, include ``broccoli.h``: .. code:: c #ifdef BROCCOLI #include #endif .. note:: *Broccoli's memory management philosophy:* Broccoli generally does not release objects you allocate. The approach taken is "you clean up what you allocate." Initialization -------------- Broccoli requires global initialization before most of its other functions can be used. Generally, the way to initialize Broccoli is as follows: .. code:: c bro_init(NULL); The argument to ``bro_init()`` provides optional initialization context, and may be kept ``NULL`` for normal use. If required, you may allocate a ``BroCtx`` structure locally, initialize it using ``bro_ctx_init()``, fill in additional values as required and subsequently pass it to ``bro_init()``: .. code:: c BroCtx ctx; bro_ctx_init(&ctx); /* Make adjustments to the context structure as required...*/ bro_init(&ctx); .. note:: The ``BroCtx`` structure currently contains a set of five different callback function pointers. These are *required* for thread-safe operation of OpenSSL (Broccoli itself is thread-safe). If you intend to use Broccoli in a multithreaded environment, you need to implement functions and register them via the ``BroCtx`` structure. The O'Reilly book "Network Security with OpenSSL" by Viega et al. shows how to implement these callbacks. .. warning:: You *must* call ``bro_init()`` at the start of your application. Undefined behavior may result if you don't. Data types in Broccoli ---------------------- Broccoli declares a number of data types in ``broccoli.h`` that you should know about. The more complex ones are kept opaque, while you do get access to the fields in the simpler ones. The full list is as follows: - Simple signed and unsigned types: int, uint, uint16, uint32, uint64 and uchar. - Connection handles: BroConn, kept opaque. - Bro events: BroEvent, kept opaque. - Buffer objects: BroBuf, kept opaque. See also `Using Dynamic Buffers`_. - Ports: BroPort for network ports, defined as follows: .. code:: c typedef struct bro_port { uint16 port_num; /* port number in host byte order */ int port_proto; /* IPPROTO_xxx */ } BroPort; - Records: BroRecord, kept opaque. See also `Handling Records`_. - Strings (character and binary): BroString, defined as follows: .. code:: c typedef struct bro_string { int str_len; char str_val; } BroString; - BroStrings are mostly kept transparent for convenience; please have a look at the `Broccoli API Reference`_. - Tables: BroTable, kept opaque. See also `Handling Tables`_. - Sets: BroSet, kept opaque. See also `Handling Sets`_. - IP Address: BroAddr, defined as follows: .. code:: c typedef struct bro_addr { uint32 addr[4]; /* IP address in network byte order */ int size; /* Number of 4-byte words occupied in addr */ } BroAddr; Both IPv4 and IPv6 addresses are supported, with the former occupying only the first 4 bytes of the ``addr`` array. - Subnets: BroSubnet, defined as follows: .. code:: c typedef struct bro_subnet { BroAddr sn_net; /* IP address in network byte order */ uint32 sn_width; /* Length of prefix to consider. */ } BroSubnet; Managing Connections -------------------- You can use Broccoli to establish a connection to a remote Bro, or to create a Broccoli-enabled server application that other Bros will connect to (this means that in principle, you can also use Broccoli purely as middleware and have multiple Broccoli applications communicate directly). In order to establish a connection to a remote Bro, you first obtain a connection handle. You then use this connection handle to request events, connect to the remote Bro, send events, etc. Connection handles are pointers to ``BroConn`` structures, which are kept opaque. Use ``bro_conn_new()`` or ``bro_conn_new_str()`` to obtain a handle, depending on what parameters are more convenient for you: the former accepts the IP address and port number as separate numerical arguments, the latter uses a single string to encode both, in "hostname:port" format. To write a Broccoli-enabled server, you first need to implement the usual ``socket()`` / ``bind()`` / ``listen()`` / ``accept()`` routine. Once you have obtained a file descriptor for the new connection from ``accept()``, you pass it to the third function that returns a ``BroConn`` handle, ``bro_conn_new_socket()``. The rest of the connection handling then proceeds as in the client scenario. All three calls accept additional flags for fine-tuning connection behaviour. These flags are: - ``BRO_CFLAG_NONE``: no functionality. Use when no flags are desired. - ``BRO_CFLAG_RECONNECT``: When using this option, Broccoli will attempt to reconnect to the peer transparently after losing connectivity. Essentially whenever you try to read from or write to the peer and its connection has broke down, a full reconnect including complete handshaking is attempted. You can check whether the connection to a peer is alive at any time using ``bro_conn_alive()``. - ``BRO_CFLAG_ALWAYS_QUEUE``: When using this option, Broccoli will queue any events you send for later transmission when a connection is currently down. Without using this flag, any events you attempt to send while a connection is down get dropped on the floor. Note that Broccoli maintains a maximum queue size per connection so if you attempt to send lots of events while the connection is down, the oldest events may start to get dropped nonetheless. Again, you can check whether the connection is currently okay by using ``bro_conn_alive()``. - ``BRO_CFLAG_DONTCACHE``: When using this option, Broccoli will ask the peer not to use caching on the objects it sends to us. This is the default, and the flag need not normally be used. It is kept to maintain backward compatibility. - ``BRO_CFLAG_CACHE``: When using this option, Broccoli will ask the peer to use caching on the objects it sends to us. Caching is normally disabled. - ``BRO_CFLAG_YIELD``: When using this option, ``bro_conn_process_input()`` processes at most one event at a time and then returns. By obtaining a connection handle, you do not also establish a connection right away. This is done using ``bro_conn_connect()``. The main reason for this is to allow you to subscribe to events (using ``bro_event_registry_add()``, see `Receiving Events`_) before establishing the connection. Upon returning from ``bro_conn_connect()`` you are guaranteed to receive all instances of the event types you have requested, while later on during the connection some time may elapse between the issuing of a request for events and the processing of that request at the remote end. Connections are established via TCP, optionally using SSL encryption. See "`Configuring Encrypted Communication`_", for more information on setting up encryption. The port numbers Bro agents and Broccoli applications listen on can vary from peer to peer. Finally, ``bro_conn_delete()`` terminates a connection and releases all resources associated with it. You can create as many connections as you like, to one or more peers. You can obtain the file descriptor of a connection using ``bro_conn_get_fd()``: .. code:: c char host_str = "bro.yourorganization.com"; int port = 1234; struct hostent *host; BroConn *bc; if (! (host = gethostbyname(host_str)) || ! (host->h_addr_list[0])) { /* Error handling -- could not resolve host */ } /* In this example, we obtain a connection handle, then register event handlers, and finally connect to the remote Bro. */ /* First obtain a connection handle: */ if (! (bc = bro_conn_new((struct in_addr*) host->h_addr_list[0], htons(port), BRO_CFLAG_NONE))) { /* Error handling - could not get connection handle */ } /* Register event handlers: */ bro_event_registry_add(bc, "foo", bro_foo_handler, NULL); /* ... */ /* Now connect to the peer: */ if (! bro_conn_connect(bc)) { /* Error handling - could not connect to remote Bro. */ } /* Send and receive events ... */ /* Disconnect from Bro and clean up connection */ bro_conn_delete(bc); Or simply use the string-based version: .. code:: c char host_str = "bro.yourcompany.com:1234"; BroConn bc; /* In this example we don't request any events from the peer, but we ask it not to use the serialization cache. */ /* Again, first obtain a connection handle: */ if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) { /* Error handling - could not get connection handle */ } /* Now connect to the peer: */ if (! bro_conn_connect(bc)) { /* Error handling - could not connect to remote Bro. */ } /* ... */ Connection Classes ------------------ When you want to establish connections from multiple Broccoli applications with different purposes, the peer needs a means to understand what kind of application each connection belongs to. The real meaning of "kind of application" here is "sets of event types to request", because depending on the class of an application, the peer will likely want to receive different types of events. Broccoli lets you set the class of a connection using ``bro_conn_set_class()``. When using this feature, you need to call that function before issuing a ``bro_conn_connect()`` since the class of a connection is determined at connection startup: .. code:: c if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) { /* Error handling - could not get connection handle */ } /* Set class of this connection: */ bro_conn_set_class(bc, "syslog"); if (! bro_conn_connect(bc)) { /* Error handling - could not connect to remote Bro. */ } If your peer is a Bro node, you need to match the chosen connection class in the remote Bro's ``Communication::nodes`` configuration. See `Configuring event reception in Bro scripts`_, for how to do this. Finally, in order to obtain the class of a connection as indicated by the remote side, use ``bro_conn_get_peer_class()``. Composing and sending events ---------------------------- In order to send an event to the remote Bro agent, you first create an empty event structure with the name of the event, then add parameters to pass to the event handler at the remote agent, and then send off the event. .. note: *Bro peers ignore unrequested events.* You need to make sure that the remote Bro agent is interested in receiving the events you send. This interest is expressed in policy configuration. We'll explain this in more detail in `Configuring event reception in Bro scripts`_, and for now assume that our remote peer is configured to receive the events we send. Let's assume we want to request a report of all connections a remote Bro currently keeps state for that match a given destination port and host name and that have amassed more than a certain number of bytes. The idea is to send an event to the remote Bro that contains the query, identifiable through a request ID, and have the remote Bro answer us with ``remote_conn`` events containing the information we asked for. The definition of our requesting event could look as follows in the Bro policy: .. code:: bro event report_conns(req_id: int, dest_host: string, dest_port: port, min_size: count); First, create a new event: .. code:: c BroEvent *ev; if (! (ev = bro_event_new("report_conns"))) { /* Error handling - could not allocate new event. */ } Now we need to add parameters to the event. The sequence and types must match the event handler declaration -- check the Bro policy to make sure they match. The function to use for adding parameter values is ``bro_event_add_val()``. All values are passed as *pointer arguments* and are copied internally, so the object you're pointing to stays unmodified at all times. You clean up what you allocate. In order to indicate the type of the value passed into the function, you need to pass a numerical type identifier along as well. Table-1_ lists the value types that Broccoli supports along with the type identifier and data structures to point to. .. _Table-1: Types, type tags, and data structures for event parameters in Broccoli ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================== ===================== ==================== Type Type tag Data type pointed to ============================== ===================== ==================== Boolean ``BRO_TYPE_BOOL`` ``int`` Integer value ``BRO_TYPE_INT`` ``uint64`` Counter (nonnegative integers) ``BRO_TYPE_COUNT`` ``uint64`` Enums (enumerated values) ``BRO_TYPE_ENUM`` ``uint64`` (see also description of ``bro_event_add_val()``'s ``type_name`` argument) Floating-point number ``BRO_TYPE_DOUBLE`` ``double`` Timestamp ``BRO_TYPE_TIME`` ``double`` (see also ``bro_util_timeval_to_double()`` and ``bro_util_current_time()``) Time interval ``BRO_TYPE_INTERVAL`` ``double`` Strings (text and binary) ``BRO_TYPE_STRING`` ``BroString`` (see also family of ``bro_string_xxx()`` functions) Network ports ``BRO_TYPE_PORT`` ``BroPort``, with the port number in host byte order IPv4/IPv6 address ``BRO_TYPE_IPADDR`` ``BroAddr``, with the ``addr`` member in network byte order and ``size`` member indicating the address family and number of 4-byte words of ``addr`` that are occupied (1 for IPv4 and 4 for IPv6) IPv4/IPv6 subnet ``BRO_TYPE_SUBNET`` ``BroSubnet``, with the ``sn_net`` member in network byte order Record ``BRO_TYPE_RECORD`` ``BroRecord`` (see also the family of ``bro_record_xxx()`` functions and their explanation below) Table ``BRO_TYPE_TABLE`` ``BroTable`` (see also the family of ``bro_table_xxx()`` functions and their explanation below) Set ``BRO_TYPE_SET`` ``BroSet`` (see also the family of ``bro_set_xxx()`` functions and their explanation below) ============================== ===================== ==================== Knowing these, we can now compose a ``request_connections`` event: .. code:: c BroString dest_host; BroPort dest_port; uint32 min_size; int req_id = 0; bro_event_add_val(ev, BRO_TYPE_INT, NULL, &req_id); req_id++; bro_string_set(&dest_host, "desthost.destdomain.com"); bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &dest_host); bro_string_cleanup(&dest_host); dest_port.dst_port = 80; dest_port.dst_proto = IPPROTO_TCP; bro_event_add_val(ev, BRO_TYPE_PORT, NULL, &dest_port); min_size = 1000; bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, &min_size); The third argument to ``bro_event_add_val()`` lets you specify a specialization of the types listed in Table-1_. This is generally not necessary except for one situation: when using ``BRO_TYPE_ENUM``. You currently cannot define a Bro-level enum type in Broccoli, and thus when sending an enum value, you have to specify the type of the enum along with the value. For example, in order to add an instance of enum ``transport_type`` defined in Bro's ``bro.init``, you would use: .. code:: c int transport_proto = 2; /* ... */ bro_event_add_val(ev, BRO_TYPE_ENUM, "transport_proto", &transport_proto); to get the equivalent of "udp" on the remote side. The same system is used to point out type names when calling ``bro_event_set_val()``, ``bro_record_add_val()``, ``bro_record_set_nth_val()``, and ``bro_record_set_named_val()``. All that's left to do now is to send off the event. For this, use ``bro_event_send()`` and pass it the connection handle and the event. The function returns ``TRUE`` when the event could be sent right away or if it was queued for later delivery. ``FALSE`` is returned on error. If the event gets queued, this does not indicate an error -- likely the connection was just not ready to send the event at this point. Whenever you call ``bro_event_send()``, Broccoli attempts to send as much of an existing event queue as possible. Again, the event is copied internally to make it easier for you to send the same event repeatedly. You clean up what you allocate: .. code:: c bro_event_send(bc, ev); bro_event_free(ev); Two other functions may be useful to you: ``bro_event_queue_length()`` tells you how many events are currently queued, and ``bro_event_queue_flush()`` attempts to flush the current event queue and returns the number of events that do remain in the queue after the flush. .. note:: you do not normally need to call this function, queue flushing is attempted every time you send an event. Receiving Events ---------------- Receiving events is a little more work because you need to 1. tell Broccoli what to do when requested events arrive, #. let the remote Bro agent know that you would like to receive those events, #. find a spot in the code path suitable for extracting and processing arriving events. Each of these steps is explained in the following sections. Implementing event callbacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When Broccoli receives an event, it tries to dispatch the event to callbacks registered for that event type. The place where callbacks get registered is called the callback registry. Any callbacks registered for the arriving event's name are invoked with the parameters shipped with the event. There are two styles of argument passing to the event callbacks. Which one is better suited depends on your application. Expanded Argument Passing ^^^^^^^^^^^^^^^^^^^^^^^^^ Each event argument is passed via a pointer to the callback. This makes best sense when you know the type of the event and of its arguments, because it provides you immediate access to arguments as when using a normal C function. In order to register a callback with expanded argument passing, use ``bro_event_registry_add()`` and pass it the connection handle, the name of the event for which you register the callback, the callback itself that matches the signature of the ``BroEventFunc`` type, and any user data (or ``NULL``) you want to see passed to the callback on each invocation. The callback's type is defined rather generically as follows: .. code:: c typedef void (*BroEventFunc) (BroConn *bc, void *user_data, ...); It requires a connection handle as its first argument and a pointer to user-provided callback data as the second argument. Broccoli will pass the connection handle of the connection on which the event arrived through to the callback. ``BroEventFunc``'s are variadic, because each callback you provide is directly invoked with pointers to the parameters of the event, in a format directly usable in C. All you need to know is what type to point to in order to receive the parameters in the right layout. Refer to Table-1_ again for a summary of those types. Record types are more involved and are addressed in more detail in `Handling Records`_. .. note:: Note that *all* parameters are passed to the callback as pointers, even elementary types such as ``int`` that would normally be passed directly. Also note that Broccoli manages the lifecycle of event parameters and therefore you do *not* have to clean them up inside the event handler. Continuing our example, we will want to process the connection reports that contain the responses to our ``report_conns`` event. Let's assume those look as follows: .. code:: bro event remote_conn(req_id: int, conn: connection); The reply events contain the request ID so we can associate requests with replies, and a connection record (defined in ``bro.init`` in Bro). (It'd be nicer to report all replies in a single event but we'll ignore that for now.) For this event, our callback would look like this: .. code:: c void remote_conn_cb(BroConn *bc, void *user_data, int *req_id, BroRecord *conn); Once more, you clean up what you allocate, and since you never allocated the space these arguments point to, you also don't clean them up. Finally, we register the callback using ``bro_event_registry_add()``: .. code:: c bro_event_registry_add(bc, "remote_conn", remote_conn_cb, NULL); In this case we have no additional data to be passed into the callback, so we use ``NULL`` for the last argument. If you have multiple events you are interested in, register each one in this fashion. Compact Argument Passing ^^^^^^^^^^^^^^^^^^^^^^^^ This is designed for situations when you have to determine how to handle different types of events at runtime, for example when writing language bindings or when implementing generic event handlers for multiple event types. The callback is passed a connection handle and the user data as above but is only passed one additional pointer, to a BroEvMeta structure. This structure contains all metadata about the event, including its name, timestamp (in UTC) of creation, number of arguments, the arguments' types (via type tags as listed in Table-1_), and the arguments themselves. In order to register a callback with compact argument passing, use ``bro_event_registry_add_compact()`` and pass it similar arguments as you'd use with ``bro_event_registry_add()``. The callback's type is defined as follows: .. code:: c typedef void (*BroCompactEventFunc) (BroConn *bc, void *user_data, BroEvMeta *meta); .. note:: As before, Broccoli manages the lifecycle of event parameters. You do not have to clean up the BroEvMeta structure or any of its contents. Below is sample code for extracting the arguments from the BroEvMeta structure, using our running example. This is still written with the assumption that we know the types of the arguments, but note that this is not a requirement for this style of callback: .. code:: c void remote_conn_cb(BroConn *bc, void *user_data, BroEvMeta *meta) { int *req_id; BroRecord *rec; /* For demonstration, print out the event's name: */ printf("Handling a %s event.\n", meta->ev_name); /* Sanity-check the number of arguments: */ if (meta->ev_numargs != 2) { /* error */ } /* Sanity-check the argument types: */ if (meta->ev_args[0].arg_type != BRO_TYPE_INT) { /* error */ } if (meta->ev_args[1].arg_type != BRO_TYPE_RECORD) { /* error */ } req_id = (int *) meta->ev_args[0].arg_data; rec = (BroRecord *) meta->ev_args[1].arg_data; /* ... */ } Finally, register the callback using ``bro_event_registry_add_compact()``: .. code:: c bro_event_registry_add_compact(bc, "remote_conn", remote_conn_cb, NULL); Requesting event delivery ~~~~~~~~~~~~~~~~~~~~~~~~~ At this point, Broccoli knows what to do with the requested events upon arrival. What's left to do is to let the remote Bro know that you would like to receive the events for which you registered. If you haven't yet called ``bro_conn_connect()``, then there is nothing to do, since that function will request the registered events anyway. Once connected, you can still request events. To do so, call ``bro_event_registry_request()``: .. code:: c bro_event_registry_request(bc); This mechanism also implies that no unrequested events will be delivered to us (and if that happened for whatever reason, the event would simply be dropped on the floor). .. note:: At the moment you cannot unrequest events, nor can you request events based on predicates on the values of the events' arguments. Reading events from the connection handle ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ At this point the remote Bro will start sending you the requested events once they are triggered. What is left to do is to read the arriving events from the connection and trigger dispatching them to the registered callbacks. If you are writing a new Bro-enabled application, this is easy, and you can choose among two approaches: polling explicitly via Broccoli's API, or using ``select()`` on the file handle associated with a BroConn. The former case is particularly straightforward; all you need to do is call ``bro_conn_process_input()``, which will go off and check if any events have arrived and if so, dispatch them accordingly. This function does not block -- if no events have arrived, then the call will return immediately. For more fine-grained control over your I/O handling, you will probably want to use ``bro_conn_get_fd()`` to obtain the file descriptor of your connection and then incorporate that in your standard ``FD_SET``/``select()`` code. Once you have determined that data in fact are ready to be read from the obtained file descriptor, you can then try another ``bro_conn_process_input()`` this time knowing that it'll find something to dispatch. As a side note, if you don't process arriving events frequently enough, then TCP's flow control will start to slow down the sender until eventually events will queue up and be dropped at the sending end. Handling Records ---------------- Broccoli supports record structures, i.e., types that pack a set of values together, placing each value into its own field. In Broccoli, the way you handle records is somewhat similar to events: after creating an empty record (of opaque type ``BroRecord``), you can iteratively add fields and values to it. The main difference is that you must specify a field name with the value; each value in a record can be identified both by position (a numerical index starting from zero), and by field name. You can retrieve vals in a record by field index or field name. You can also reassign values. There is no explicit, IDL-style definition of record types. You define the type of a record implicitly by the sequence of field names and the sequence of the types of the values you put into the record. Note that all fields in a record must be assigned before it can be shipped. The API for record composition consists of ``bro_record_new()``, ``bro_record_free()``, ``bro_record_add_val()``, ``bro_record_set_nth_val()``, and ``bro_record_set_named_val()``. On records that use field names, the names of individual fields can be extracted using ``bro_record_get_nth_name()``. Extracting values from a record is done using ``bro_record_get_nth_val()`` and ``bro_record_get_named_val()``. The former allows numerical indexing of the fields in the record, the latter provides name-based lookups. Both need to be passed the record you want to extract a value from, the index or name of the field, and either a pointer to an int holding a BRO_TYPE_xxx value (see again Table-1_ for a summary of those types) or ``NULL``. The pointer, if not ``NULL``, serves two purposes: type checking and type retrieval. Type checking is performed if the value of the int upon calling the functions is not BRO_TYPE_UNKNOWN. The type tag of the requested record field then has to match the type tag stored in the int, otherwise ``NULL`` is returned. If the int stores BRO_TYPE_UNKNOWN upon calling, no type-checking is performed. In *both* cases, the *actual* type of the requested record field is returned in the int pointed to upon return from the function. Since you have no guarantees of the type of the value upon return if you pass ``NULL`` as the int pointer, this is a bad idea and either BRO_TYPE_UNKNOWN or another type value should always be used. For example, you could extract the value of the record field "label", which we assume should be a string, in the following ways: .. code:: c BroRecord *rec = /* obtained somehow */ BroString *string; int type; /* --- Example 1 --- */ type = BRO_TYPE_STRING; /* Use type-checking, will not accept other types */ if (! (string = bro_record_get_named_val(rec, "label", &type))) { /* Error handling, either there's no field of that value or the value is not of BRO_TYPE_STRING. The actual type is now stored in "type". */ } /* --- Example 2 --- */ type = BRO_TYPE_UNKNOWN; /* No type checking, just report the existent type */ if (! (string = bro_record_get_named_val(rec, "label", &type))) { /* Error handling, no field of that name exists. */ } printf("The type of the value in field 'label' is %i\n", type); /* --- Example 3 --- */ if (! (string = bro_record_get_named_val(rec, "label", NULL))) { /* Error handling, no field of that name exists. */ } /* We now have a value, but we can't really be sure of its type */ Record fields can be records, for example in the case of Bro's standard connection record type. In this case, in order to get to a nested record, you use ``BRO_TYPE_RECORD``: .. code:: c void remote_conn_cb(BroConn *bc, int *req_id, BroRecord *conn) { BroRecord *conn_id; int type = BRO_TYPE_RECORD; if ( ! (conn_id = bro_record_get_named_val(conn, "id", &type))) { /* Error handling */ } } Handling Tables --------------- Broccoli supports Bro-style tables, i.e., associative containers that map instances of a key type to an instance of a value type. A given key can only ever point to a single value. The key type can be *composite*, i.e., it may consist of an ordered sequence of different types, or it can be *direct*, i.e., consisting of a single type (such as an integer, a string, or a record). The API for table manipulation consists of ``bro_table_new()`` ``bro_table_free()``, ``bro_table_insert()``, ``bro_table_find()``, ``bro_table_get_size()``, ``bro_table_get_types()``, and ``bro_table_foreach()``. Tables are handled similarly to records in that typing is determined dynamically by the initial key/value pair inserted. The resulting types can be obtained via ``bro_table_get_types()``. Should the types not have been determined yet, ``BRO_TYPE_UNKNOWN`` will result. Also, as with records, values inserted into the table are copied internally, and the ones passed to the insertion functions remain unaffected. In contrast to records, table entries can be iterated. By passing a function of signature ``BroTableCallback()`` and a pointer to data of your choosing, ``bro_table_foreach()`` will invoke the given function for each key/value pair stored in the table. Return ``TRUE`` to keep the iteration going, or ``FALSE`` to stop it. .. note:: The main thing to know about Broccoli's tables is how to use composite key types. To avoid additional API calls, you may treat composite key types exactly as records, though you do not need to use field names when assigning elements to individual fields. So in order to insert a key/value pair, you create a record with the needed items assigned to its slots, and use this record as the key object. In order to differentiate composite index types from direct ones consisting of a single record, use ``BRO_TYPE_LIST`` as the type of the record, as opposed to ``BRO_TYPE_RECORD``. Broccoli will then know to interpret the record as an ordered sequence of items making up a composite element, not a regular record. ``brotable.c`` in the ``test/`` subdirectory of the Broccoli tree contains an extensive example of using tables with composite as well as direct indexing types. Handling Sets ------------- Sets are essentially tables with void value types. The API for set manipulation consists of ``bro_set_new()``, ``bro_set_free()``, ``bro_set_insert()``, ``bro_set_find()``, ``bro_set_get_size()``, ``bro_set_get_type()``, and ``bro_set_foreach()``. Associating data with connections --------------------------------- You will often find that you would like to connect data with a ``BroConn``. Broccoli provides an API that lets you associate data items with a connection handle through a string-based key-value registry. The functions of interest are ``bro_conn_data_set()``, ``bro_conn_data_get()``, and ``bro_conn_data_del()``. You need to provide a string identifier for a data item and can then use that string to register, look up, and remove the associated data item. Note that there is currently no mechanism to trigger a destructor function for registered data items when the Bro connection is terminated. You therefore need to make sure that all data items that you do not have pointers to via some other means are properly released before calling ``bro_disconnect()``. Configuration Files ------------------- Imagine you have instrumented the mother of all server applications. Building it takes forever, and every now and then you need to change some of the parameters that your Broccoli code uses, such as the host names of the Bro agents to talk to. To allow you to do this quickly, Broccoli comes with support for configuration files. All you need to do is change the settings in the file and restart the application (we're considering adding support for volatile configuration items that are read from the file every time they are requested). A configuration is read from a single configuration file. This file can be read from different locations. Broccoli searches in this order for the config file: - The location specified by the ``BROCCOLI_CONFIG_FILE`` environment variable. - A per-user configuration file stored in ``~/.broccoli.conf``. - The system-wide configuration file. You can obtain the location of this config file by running ``broccoli-config --config``. .. note:: ``BROCCOLI_CONFIG_FILE`` or ``~/.broccoli.conf`` will only be used if it is a regular file, not executable, and neither group nor others have any permissions on the file. That is, the file's permissions must look like ``-rw-------`` *or* ``-r--------``. In the configuration file, a ``#`` anywhere starts a comment that runs to the end of the line. Configuration items are specified as key-value pairs:: # This is the Broccoli system-wide configuration file. # # Entries are of the form , where the # identifier is a sequence of letters, and value can be a string # (including whitespace), and floating point or integer numbers. # Comments start with a "#" and go to the end of the line. For # boolean values, you may also use "yes", "on", "true", "no", # "off", or "false". Strings may contain whitespace, but need # to be surrounded by double quotes '"'. # # Examples: # Foo/PeerName mybro.securesite.com Foo/PortNum 123 Bar/SomeFloat 1.23443543 Bar/SomeLongStr "Hello World" You can also have multiple sections in your configuration. Your application can select a section as the current one, and queries for configuration settings will then only be answered with values specified in that section. A section is started by putting its name (no whitespace please) between square brackets. Configuration items positioned before the first section title are in the default domain and will be used by default:: # This section contains all settings for myapp. [ myapp ] You can name identifiers any way you like, but to keep things organized it is recommended to keep a namespace hierarchy similar to the file system. In the code, you can query configuration items using ``bro_conf_get_str()``, ``bro_conf_get_int()``, and ``bro_conf_get_dbl()``. You can switch between sections using ``bro_conf_set_domain()``. Using Dynamic Buffers --------------------- Broccoli provides an API for dynamically allocatable, growable, shrinkable, and consumable buffers with ``BroBuf``. You may or may not find this useful -- Broccoli mainly provides this feature in ``broccoli.h`` because these buffers are used internally anyway and because they are a typical case of something that people implement themselves over and over again, for example to collect a set of data before sending it through a file descriptor, etc. The buffers work as follows. The structure implementing a buffer is called ``BroBuf``, and is initialized to a default size when created via ``bro_buf_new()`` and released using ``bro_buf_free()``. Each ``BroBuf`` has a content pointer that points to an arbitrary location between the start of the buffer and the first byte after the last byte currently used in the buffer (see ``buf_off`` in the illustration below). The content pointer can seek to arbitrary locations, and data can be copied from and into the buffer, adjusting the content pointer accordingly. You can repeatedly append data to the end of the buffer's used contents using ``bro_buf_append()``. :: <---------------- allocated buffer space ------------> <======== used buffer space ========> ^ ^ ^ ^ | | | | | buf buf_ptr buf_off buf_len Have a look at the following functions for the details: ``bro_buf_new()``, ``bro_buf_free()``, ``bro_buf_append()``, ``bro_buf_consume()``, ``bro_buf_reset()``, ``bro_buf_get()``, ``bro_buf_get_end()``, ``bro_buf_get_size()``, ``bro_buf_get_used_size()``, ``bro_buf_ptr_get()``, ``bro_buf_ptr_tell()``, ``bro_buf_ptr_seek()``, ``bro_buf_ptr_check()``, and ``bro_buf_ptr_read()``. Configuring Encrypted Communication =================================== Encrypted communication between Bro peers takes place over an SSL connection in which both endpoints of the connection are authenticated. This requires at least some PKI in the form of a certificate authority (CA) which you use to issue and sign certificates for your Bro peers. To facilitate the SSL setup, each peer requires three documents: a certificate signed by the CA and containing the public key, the corresponding private key, and a copy of the CA's certificate. The OpenSSL command line tool ``openssl`` can be used to create all files necessary, but its unstructured arguments and poor documentation make it a pain to use and waste lots of people a lot of time [#]_. For an alternative tool to create SSL certificates for secure Bro/Broccoli communication, see the ``create-cert`` tool available at ftp://ee.lbl.gov/create-cert.tar.gz. In order to enable encrypted communication for your Broccoli application, you need to put the CA certificate and the peer certificate in the ``/broccoli/ca_cert`` and ``/broccoli/host_cert`` keys, respectively, in the configuration file. Optionally, you can store the private key in a separate file specified by ``/broccoli/host_key``. To quickly enable/disable a certificate configuration, the ``/broccoli/use_ssl`` key can be used. .. note:: *This is where you configure whether to use encrypted or unencrypted connections.* If the ``/broccoli/use_ssl`` key is present and set to one of "yes", "true", "on", or 1, then SSL will be used and an incorrect or missing certificate configuration will cause connection attempts to fail. If the key's value is one of "no", "false", "off", or 0, then in no case will SSL be used and connections will always be cleartext. If the ``/broccoli/use_ssl`` key is *not* present, then SSL will be used if a certificate configuration is found, and invalid certificates will cause the connection to fail. If no certificates are configured, cleartext connections will be used. In no case does an SSL-enabled setup ever fall back to a cleartext one. :: /broccoli/use_ssl yes /broccoli/ca_cert /ca_cert.pem /broccoli/host_cert /bro_cert.pem /broccoli/host_key /bro_cert.key In a Bro policy, you need to load the ``frameworks/communication/listen.bro`` script and redef ``Communication::listen_ssl=T``, ``ssl_ca_certificate``, and ``ssl_private_key``, defined in ``bro.init``: .. code:: bro @load frameworks/communication/listen redef Communication::listen_ssl=T; redef ssl_ca_certificate = "/ca_cert.pem"; redef ssl_private_key = "/bro.pem"; By default, you will be prompted for the passphrase for the private key matching the public key in your agent's certificate. Depending on your application's user interface and deployment, this may be inappropriate. You can store the passphrase in the config file as well, using the following identifier:: /broccoli/host_pass foobar .. warning:: *Make sure that access to your configuration is restricted.* If you provide the passphrase this way, it is obviously essential to have restrictive permissions on the configuration file. Broccoli partially enforces this. Please refer to the section on `Configuration Files`_ for details. Configuring event reception in Bro scripts ========================================== Before a remote Bro will accept your connection and your events, it needs to have its policy configured accordingly: 1. Load ``frameworks/communication/listen``, and redef the boolean variable ``Communication::listen_ssl`` depending on whether you want to have encrypted or cleartext communication. Obviously, encrypting the event exchange is recommended and cleartext should only be used for early experimental setups. See below for details on how to set up encrypted communication via SSL. #. You need to find a port to use for the Bros and Broccoli applications that will listen for connections. Every such agent can use a different port, though default ports are provided in the Bro policies. To change the port the Bro agent will be listening on from its default, redefine the ``Communication::listen_port``. Have a look at these policies as well as ``base/frameworks/communication/main.bro`` for the default values. Here is the policy for the unencrypted case: .. code:: bro @load frameworks/communication/listen redef Communication::listen_port = 12345/tcp; .. Including the settings for the cryptographic files introduced in the previous section, here is the encrypted one: .. code:: bro @load frameworks/communication/listen redef Communication::listen_ssl = T; redef Communication::listen_port = 12345/tcp; redef ssl_ca_certificate = "/ca_cert.pem"; redef ssl_private_key = "/bro.pem"; .. #. The policy controlling which peers a Bro agent will communicate with and how this communication will happen are defined in the ``Communication::nodes`` table defined in ``base/frameworks/communication/main.bro``. This table contains entries of type ``Node``, whose members mostly provide default values so you do not need to define everything. You need to come up with a tag for the connection under which it can be found in the table (a creative one would be "broccoli"), the IP address of the peer, the pattern of names of the events the Bro will accept from you, whether you want Bro to connect to your machine on startup or not, if so, a port to connect to (default is ``Communication::default_port`` also defined in ``base/frameworks/communication/main.bro``), a retry timeout, whether to use SSL, and the class of a connection as set on the Broccoli side via ``bro_conn_set_class()``. An example could look as follows: .. code:: bro redef Communication::nodes += { ["broping"] = [$host = 127.0.0.1, $class="broping", $events = /ping/, $connect=F, $ssl=F] }; .. This example is taken from ``broping.bro``, the policy the remote Bro must run when you want to use the ``broping`` tool explained in the section on `test programs`_ below. It will allow an agent on the local host to connect and send "ping" events. Our Bro will not attempt to connect, and incoming connections will be expected in cleartext. Configuring Debugging Output ============================ If your Broccoli installation was configured with ``--enable-debug``, Broccoli will report two kinds of debugging information: 1. function call traces and #. individual debugging messages. Both are enabled by default, but can be adjusted in two ways. - In the configuration file: in the appropriate section of the configuration file, you can set the keys ``/broccoli/debug_messages`` and ``/broccoli/debug_calltrace`` to ``on``/``off`` to enable/disable the corresponding output. - In code: you can set the variables ``bro_debug_calltrace`` and ``bro_debug_messages`` to 1/0 at any time to enable/disable the corresponding output. By default, debugging output is inactive (even with debug support compiled in). You need to enable it explicitly either in your code by assigning 1 to ``bro_debug_calltrace`` and ``bro_debug_messages`` or by enabling it in the configuration file. Test programs ============= The Broccoli distribution comes with a few small test programs, located in the ``test/`` directory of the tree. The most notable one is ``broping`` [#]_, a mini-version of ping. It sends "ping" events to a remote Bro agent, expecting "pong" events in return. It operates in two flavours: one uses atomic types for sending information across, and the other one uses records. The Bro agent you want to ping needs to run either the ``broping.bro`` or ``broping-record.bro`` policies. You can find these in the ``test/`` directory of the source tree, and in ``/share/broccoli`` in the installed version. ``broping.bro`` is shown below. By default, pinging a Bro on the same machine is configured. If you want your Bro to be pinged from another machine, you need to update the ``Communication::nodes`` variable accordingly: .. code:: bro @load frameworks/communication/listen; global ping_log = open_log_file("ping"); redef Communication::nodes += { ["broping"] = [$host = 127.0.0.1, $events = /ping/, $connect=F, $retry = 60 secs, $ssl=F] }; event ping(src_time: time, seq: count) { event pong(src_time, current_time(), seq); } event pong(src_time: time, dst_time: time, seq: count) { print ping_log, fmt("ping received, seq %d, %f at src, %f at dest, one-way: %f", seq, src_time, dst_time, dst_time-src_time); } ``broping`` sends ping events to Bro. Bro accepts those because they are configured accordingly in the nodes table. As shown in the policy, ping events trigger pong events, and ``broccoli`` requests delivery of all pong events back to it. When running ``broping``, you'll see something like this: .. console:: > ./test/broping pong event from 127.0.0.1: seq=1, time=0.004700/1.010303 s pong event from 127.0.0.1: seq=2, time=0.053777/1.010266 s pong event from 127.0.0.1: seq=3, time=0.006435/1.010284 s pong event from 127.0.0.1: seq=4, time=0.020278/1.010319 s pong event from 127.0.0.1: seq=5, time=0.004563/1.010187 s pong event from 127.0.0.1: seq=6, time=0.005685/1.010393 s Notes ===== .. [#] In other documents and books on OpenSSL you will find this expressed more politely, using terms such as "daunting to the uninitiated", "challenging", "complex", "intimidating". .. [#] Pronunciation is said to be somewhere on the continuum between "brooping" and "burping". Broccoli API Reference ###################### The `API documentation <../../broccoli-api/index.html>`_ describes Broccoli's public C interface. broccoli-1.97-minimal/doc/CMakeLists.txt0000664002342100234210000000114112523041064020007 0ustar johannajohannaconfigure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(broccolidoc COMMAND doxygen ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile COMMENT "[Doxygen] Generating HTML Broccoli API docs") add_custom_target(broccolidocclean COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/html) if (NOT TARGET doc) add_custom_target(doc) endif () add_dependencies(doc broccolidoc) if (NOT TARGET docclean) add_custom_target(docclean) endif () add_dependencies(docclean broccolidocclean) broccoli-1.97-minimal/doc/stylesheet.css0000664002342100234210000000117712523041064020163 0ustar johannajohannabody { margin-left:10px; margin-right:10px; margin-top:10px; margin-bottom:10px; color:#101010; background-repeat:no-repeat; } h1.title { text-align:center; } .abstract { text-align:center; margin-left:100px; margin-right:100px; } .caption { margin-left:100px; margin-right:100px; font-style:italic; } .programlisting { font-size:12px; font-family:courier; } .type { font-size:12px; font-family:courier; } .mediaobject { text-align:center; } span, h1, h2, h3, h4, p, div, table { font-family:arial,helvetica; } li { margin-bottom:10px } broccoli-1.97-minimal/doc/stylesheet.dsl0000664002342100234210000001757312523041064020164 0ustar johannajohanna ]> ;; These are some customizations to the standard HTML output produced by the ;; Modular DocBook Stylesheets. ;; I've copied parts of a few functions from the stylesheets so these should ;; be checked occasionally to ensure they are up to date. ;; ;; The last check was with version 1.40 of the stylesheets. ;; It will not work with versions < 1.19 since the $shade-verbatim-attr$ ;; function was added then. Versions 1.19 to 1.39 may be OK, if you're lucky! ;;(define %generate-book-toc% #f) ;; The email content should not line wrap in HTML, that looks ugly. ;; (okay there shouldn't be whitespace in there but when people want ;; to avoid an @ they can fill in all kinds of things). (element email ($mono-seq$ (make sequence (make element gi: "NOBR" (literal "<") (make element gi: "A" attributes: (list (list "HREF" (string-append "mailto:" (data (current-node))))) (process-children)) (literal ">"))))) ;; We want to have some control over how sections are split up into ;; separate pages. (define (chunk-element-list) (list (normalize "preface") (normalize "chapter") (normalize "appendix") (normalize "article") (normalize "glossary") (normalize "bibliography") (normalize "index") (normalize "colophon") (normalize "setindex") (normalize "reference") (normalize "refentry") (normalize "part") ;; Commented out to prevent splitting up every section into its own document ;; (normalize "sect1") ;; (normalize "section") (normalize "book") ;; just in case nothing else matches... (normalize "set") ;; sets are definitely chunks... )) ;; If a Chapter has role="no-toc" we don't generate a table of contents. ;; This is useful if a better contents page has been added manually, e.g. for ;; the GTK+ Widgets & Objects page. (But it is a bit of a hack.) (define ($generate-chapter-toc$) (not (equal? (attribute-string (normalize "role") (current-node)) "no-toc"))) (define %chapter-autolabel% ;; Are chapters enumerated? #t) (define %section-autolabel% ;; Are sections enumerated? #t) (define %use-id-as-filename% #t) (define %html-ext% ".html") (define %shade-verbatim% #t) (define (book-titlepage-separator side) (empty-sosofo)) (define ($shade-verbatim-attr$) ;; Attributes used to create a shaded verbatim environment. (list (list "WIDTH" "100%") (list "BORDER" "0") (list "BGCOLOR" "#eaeaf0"))) ;; This overrides the refsect2 definition (copied from 1.20, dbrfntry.dsl). ;; It puts a horizontal rule before each function/struct/... description, ;; except the first one in the refsect1. (element refsect2 (make sequence (if (first-sibling?) (empty-sosofo) (make empty-element gi: "HR")) ($block-container$))) ;; Override the book declaration, so that we generate a crossreference ;; for the book (element book (let* ((bookinfo (select-elements (children (current-node)) (normalize "bookinfo"))) (ititle (select-elements (children bookinfo) (normalize "title"))) (title (if (node-list-empty? ititle) (select-elements (children (current-node)) (normalize "title")) (node-list-first ititle))) (nl (titlepage-info-elements (current-node) bookinfo)) (tsosofo (with-mode head-title-mode (process-node-list title))) (dedication (select-elements (children (current-node)) (normalize "dedication")))) (make sequence (html-document tsosofo (make element gi: "DIV" attributes: '(("CLASS" "BOOK")) (if %generate-book-titlepage% (make sequence (book-titlepage nl 'recto) (book-titlepage nl 'verso)) (empty-sosofo)) (if (node-list-empty? dedication) (empty-sosofo) (with-mode dedication-page-mode (process-node-list dedication))) (if (not (generate-toc-in-front)) (process-children) (empty-sosofo)) (if %generate-book-toc% (build-toc (current-node) (toc-depth (current-node))) (empty-sosofo)) ;; (let loop ((gilist %generate-book-lot-list%)) ;; (if (null? gilist) ;; (empty-sosofo) ;; (if (not (node-list-empty? ;; (select-elements (descendants (current-node)) ;; (car gilist)))) ;; (make sequence ;; (build-lot (current-node) (car gilist)) ;; (loop (cdr gilist))) ;; (loop (cdr gilist))))) (if (generate-toc-in-front) (process-children) (empty-sosofo)))) (make entity system-id: "index.sgml" (with-mode generate-index-mode (process-children)))))) ;; Mode for generating cross references (define (process-child-elements) (process-node-list (node-list-map (lambda (snl) (if (equal? (node-property 'class-name snl) 'element) snl (empty-node-list))) (children (current-node))))) (mode generate-index-mode (element anchor (if (attribute-string "href" (current-node)) (empty-sosofo) (make formatting-instruction data: (string-append "\less-than-sign;ANCHOR id =\"" (attribute-string "id" (current-node)) "\" href=\"" (href-to (current-node)) "\"\greater-than-sign; ")))) ;; We also want to be able to link to complete RefEntry. (element refentry (make sequence (make formatting-instruction data: (string-append "\less-than-sign;ANCHOR id =\"" (attribute-string "id" (current-node)) "\" href=\"" (href-to (current-node)) "\"\greater-than-sign; ")) (process-child-elements))) (default (process-child-elements))) ;; For hypertext links for which no target is found in the document, we output ;; our own special tag which we use later to resolve cross-document links. (element link (let* ((target (element-with-id (attribute-string (normalize "linkend"))))) (if (node-list-empty? target) (make element gi: "GTKDOCLINK" attributes: (list (list "HREF" (attribute-string (normalize "linkend")))) (process-children)) (make element gi: "A" attributes: (list (list "HREF" (href-to target))) (process-children))))) (define ($section-body$) (make sequence (make empty-element gi: "BR" attributes: (list (list "CLEAR" "all"))) (make element gi: "DIV" attributes: (list (list "CLASS" (gi))) ($section-separator$) ($section-title$) (process-children)))) ;; We want to use a stylesheet! (define %css-decoration% ;; Enable CSS decoration of elements #t) (define %stylesheet% ;; Name of the stylesheet to use "stylesheet.css") ;; I want my own graphics with admonitions. (define %admon-graphics% ;; Use graphics in admonitions? #t) (define %admon-graphics-path% ;; Path to admonition graphics "images/") ;; Some stuff I really didn't like -- italics are ;; pretty hard to read most of the time. Don't use ;; them for parameter names and structure fields. (element parameter ($mono-seq$)) (element structfield ($mono-seq$)) ;; And don't use italics for emphasis either, just ;; use bold text. (element emphasis (let* ((class (if (and (attribute-string (normalize "role")) %emphasis-propagates-style%) (attribute-string (normalize "role")) "emphasis"))) (make element gi: "SPAN" attributes: (list (list "CLASS" class)) (if (and (attribute-string (normalize "role")) (or (equal? (attribute-string (normalize "role")) "strong") (equal? (attribute-string (normalize "role")) "bold"))) ($bold-seq$) ($bold-seq$))))) broccoli-1.97-minimal/doc/Doxyfile.in0000664002342100234210000022127512523041064017376 0ustar johannajohanna# Doxyfile 1.7.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "Broccoli API Documentation" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Broccoli API Documentation" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = @CMAKE_CURRENT_SOURCE_DIR@/images/logo.jpg # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_CURRENT_BINARY_DIR@/../src/broccoli.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to directory from which doxygen is run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is adviced to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES broccoli-1.97-minimal/VERSION0000664002342100234210000000000512523041064015550 0ustar johannajohanna1.97 broccoli-1.97-minimal/.update-changes.cfg0000664002342100234210000000020212523041064020126 0ustar johannajohanna # Automatically adapt version in files. function new_version_hook { version=$1 replace_version_in_rst README $version } broccoli-1.97-minimal/ylwrap0000775002342100234210000001406112523041064015753 0ustar johannajohanna#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2005-05-14.22 # Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case "$1" in '') echo "$0: No files given. Try \`$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input="$1" shift case "$input" in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input="`pwd`/$input" ;; esac pairlist= while test "$#" -ne 0; do if test "$1" = "--"; then shift break fi pairlist="$pairlist $1" shift done # The program to run. prog="$1" shift # Make any relative path in $prog absolute. case "$prog" in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog="`pwd`/$prog" ;; esac # FIXME: add hostname here for parallel makes that run commands on # other machines. But that might take us over the 14-char limit. dirname=ylwrap$$ trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 mkdir $dirname || exit 1 cd $dirname case $# in 0) $prog "$input" ;; *) $prog "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then set X $pairlist shift first=yes # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot="no" if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot="yes" fi # The directory holding the input. input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` # Quote $INPUT_DIR so we can use it in a regexp. # FIXME: really we should care about more than `.' and `\'. input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'` while test "$#" -ne 0; do from="$1" # Handle y_tab.c and y_tab.h output by DOS if test $y_tab_nodot = "yes"; then if test $from = "y.tab.c"; then from="y_tab.c" else if test $from = "y.tab.h"; then from="y_tab.h" fi fi fi if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend `../'. case "$2" in [\\/]* | ?:[\\/]*) target="$2";; *) target="../$2";; esac # We do not want to overwrite a header file if it hasn't # changed. This avoid useless recompilations. However the # parser itself (the first file) should always be updated, # because it is the destination of the .y.c rule in the # Makefile. Divert the output of all other files to a temporary # file so we can compare them to existing versions. if test $first = no; then realtarget="$target" target="tmp-`echo $target | sed s/.*[\\/]//g`" fi # Edit out `#line' or `#' directives. # # We don't want the resulting debug information to point at # an absolute srcdir; it is better for it to just mention the # .y file with no path. # # We want to use the real output file name, not yy.lex.c for # instance. # # We want the include guards to be adjusted too. FROM=`echo "$from" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` TARGET=`echo "$2" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \ -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$? # Check whether header files must be updated. if test $first = no; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$2" is unchanged rm -f "$target" else echo updating "$2" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the first file. This # is a blatant hack to let us support using "yacc -d". If -d # is not specified, we don't want an error when the header # file is "missing". if test $first = yes; then ret=1 fi fi shift shift first=no done else ret=$? fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: broccoli-1.97-minimal/CHANGES0000664002342100234210000020657012523041064015512 0ustar johannajohanna 1.97 | 2015-05-07 11:48:17 -0700 * Use @rpath in broccoli.dylib's install_name on OS X. * Fix a memory leak: table attributes weren't freed. (Jon Siwek) 1.96 | 2014-05-19 16:17:14 -0500 * Remove code corresponding w/ Bro's unused Val::attribs. (Jon Siwek) 1.95-13 | 2013-12-09 13:23:48 -0800 * Remove unused code in bro_vector_set_nth_val(). (Jon Siwek) * Fix memory leaks in relation to freeing BroVectors. (Jon Siwek) 1.95-10 | 2013-12-04 09:34:59 -0800 * Update type serialization format/process to align with Bro's changes to preserve type name info and remove old compatibility stuff. (Jon Siwek) 1.95-3 | 2013-12-03 10:53:34 -0800 * Add support for consuming events w/ vector args. (Jon Siwek) Producing events w/ vector args is still unsupported, and bindings are still missing support as well. 1.95 | 2013-11-06 00:23:50 -0800 * Don't build ruby bindings by default, use --enable-ruby to do so. (Jon Siwek) 1.94 | 2013-10-24 16:49:30 -0700 * Release. 1.93-17 | 2013-10-15 11:19:19 -0700 * Fix a minor memory leak recently introduced. (Jon Siwek) 1.93-15 | 2013-10-14 14:20:20 -0700 * Fix misc. issues reported by Coverity (Return value checks, time-of-check-time-of-use, null ptr checking, and a use-after-free). (Jon Siwek) * Fixed __bro_list_val_pop_front() to not erase the entire list but remove only the first element. (Jon Siwek) * Updating copyright notice. (Robin Sommer) 1.93-10 | 2013-10-02 10:38:27 -0700 * Remove dead code. (Jon Siwek) * Fix mem leaks. (Jon Siwek) * Updated specfile and configure script for libdir. (Derek Ditch) Package maintainers and those that would otherwise compile from source were unable to specify the installation directory of architecture dependent libraries. Namely, many distributions use lib64/ versus lib/ for the installation of architecture dependent library archives. * Add new 'configure' option, --libdir * Defaults to old behavior of "$prefix/lib" * Follows Kitware example for ProjectConfig.cmake on wiki See https://github.com/bro/broccoli/pull/1 * Added back config-file bits to CMakeLists.txt (Derek Ditch) * Fix for setting REPO in Makefile. (Robin Sommer) 1.93 | 2013-09-23 20:21:20 -0700 * Update 'make dist' target. (Jon Siwek) * Change submodules to fixed URL. (Jon Siwek) * Fix a compiler warning. (Daniel Thayer) * Fix a broken link in documentation. (Daniel Thayer) * Switching to relative submodule paths. (Robin Sommer) * s/bro-ids.org/bro.org/g. (Robin Sommer) 1.92-9 | 2013-01-31 12:17:39 -0800 * A test program for sending packets through Broccoli, moved over from the Time Machine repository. (Seth Hall) 1.92-7 | 2012-12-20 12:13:39 -0800 * Sync up with attribute definitions in Bro. (Daniel Thayer) * Rebuild only necessary files for new prefix. (Daniel Thayer) 1.92-4 | 2012-12-05 15:37:54 -0800 * Improved error checking/reporting in case of out of memory situations. (Bill Parker) 1.92-3 | 2012-11-23 19:51:14 -0800 * Bump data serialization format version for Bro's new "hook" function. (Jon Siwek) 1.92 | 2012-08-22 16:15:18 -0700 * Fix configure script to exit with non-zero status on error (Jon Siwek) 1.91 | 2012-07-10 16:08:50 -0700 * Add --conf-files-dir option to configure wrapper script. (Jon Siwek) 1.9 | 2012-07-05 12:59:54 -0700 * Fix a warning, and fix other typos in documentation. (Daniel Thayer) 1.8-28 | 2012-05-24 17:37:35 -0700 * Tweak a test script to register events with both IPv4 & IPv6 loopback. (Jon Siwek) * BROCCOLI_CONFIG_FILE env. variable can now specify config file path. (Jon Siwek) * Add ability to connect to Bro peers over IPv6. (Jon Siwek) 1.8-23 | 2012-05-03 11:33:03 -0700 * Fix typos and a few reST formatting problems. (Daniel Thayer) 1.8-21 | 2012-04-24 14:48:44 -0700 * Add option to set 'etc' directory. Addresses #801. (Daniel Thayer) * Change BroAddr to use standard IPv4 in IPv6 mapping. (Jon Siwek) The size field is now removed and the bro_util_is_v4_addr() function can be used instead to check whether the BroAddr is IPv4 or not. Addresses #800. * Add timeout to broccoli-v6addrs.c test. Addresses #793. (Jon Siwek) * Update IPv6 literal syntax in test scripts. (Jon Siwek) 1.8-8 | 2012-03-09 15:13:14 -0800 * Bump data format version corresponding to Bro's removal of match expression. (Jon Siwek) * Adding missing include needed on FreeBSD. (Robin Sommer) * Update Broccoli library to handle IPv6 addrs/subnets. Addresses #448. Addresses now use a new BroAddr struct to hold the address data and BroSubnet changed to use a BroAddr member instead of a single uint32 to represent the address. (Jon Siwek) * Raise minimum required CMake version to 2.6.3. (Jon Siwek) 1.8 | 2012-01-10 19:33:08 -0800 * Tweaks for OpenBSD support. (Jon Siwek) 1.71-26 | 2012-01-03 15:41:37 -0800 * Remove record base type list since it's been removed from Bro. (Jon Siwek) 1.71-22 | 2011-12-03 15:58:34 -0800 * Support for more types (not exposed at the API-level yet) to allow exchanging more complex record types. Adresses #606. (Christian Kreibich) * Broccoli now identifies itself as such when connecting to a peer. This allows Bro to adapt its serialization format based on what's supported by Broccoli. Adresses #606. (Christian Kreibich) 1.71-11 | 2011-11-07 05:44:16 -0800 * Fixing compiler warnings. Addresses #388. (Jon Siwek) * Update broccoli-ruby submodule. (Jon Siwek) * Fix CMake warning when python bindings are disabled. Fixes #605. (Jon Siwek) 1.71 | 2011-10-27 17:42:45 -0700 * Update submodules. (Jon Siwek) 1.7 | 2011-10-25 20:18:58 -0700 * Make dist now cleans the copied source. (Jon Siwek) * Distribution cleanup. (John Siwek and Robin Sommer) * Changed communications protocol option to listen_ssl from listen_encrypted. (Seth Hall) * Bug fix for a Bro test. (Seth Hall) * Updates to make broccoli work with communication API updates. 1.6-35 | 2011-09-15 16:48:01 -0700 * Adding Ruby bindings for Broccoli. (Seth Hall) * Broccoli API docs are now generated via Doxygen. Addresses #563. (Jon Siwek) * Converting manual to reST-format. (Don Appleman and Jon Siwek) 1.6-26 | 2011-09-04 09:26:47 -0700 * FindPCAP now links against thread library when necessary (e.g. PF_RING's libpcap). (Jon Siwek) * Install binaries with an RPATH. (Jon Siwek) * Remove the 'net' type from Broccoli. Addresses #535. (Jon Siwek) * Workaround for FreeBSD CMake port missing debug flags. (Jon Siwek) 1.6-13 | 2011-08-08 16:18:24 -0700 * Update broping.c test to use 64-bit int width for Bro counts (Jon Siwek) * Install example config files dynamically when the distribution version differs from existing version on disk. (Jon Siwek) 1.6-6 | 2011-07-19 17:54:57 -0700 * Update broccoli tests scripts to use new Bro policy organization (Jon Siwek and Robin Sommer) 1.6 | 2011-05-05 20:32:42 -0700 * Moving ChangeLog to CHANGES for consistency. (Robin Sommer) * Fixing write/read functionality for Bro's values that are now 64-bit. (Jon Siwek) * Converting build process to CMake (Jon Siwek). * Import of Bro's aux/broccoli subdir from SVN r7107 (Jon Siwek) ===== Old Subversion ChangeLog starts here. Wed Mar 2 15:38:02 PST 2011 Christian - Accept empty strings ("") as values in the configuration file (Craig Leres). - Support for specifying a separate host key for SSL-enabled operation, with documentation update (Craig Leres). - Version bump to 1.5.3. ------------------------------------------------------------------------ Fri Oct 9 18:42:05 PDT 2009 Christian - Version bump to 1.5. ------------------------------------------------------------------------ Fri Sep 25 10:09:03 PDT 2009 Christian - Bropipe fixes: set a connection class for robustness reasons; removes some C/C++ confusion (Seth Hall). ------------------------------------------------------------------------ Mon Jun 29 17:56:00 PDT 2009 Christian - SWIG bindings update. ------------------------------------------------------------------------ Mon Jun 29 15:29:35 PDT 2009 Christian - Support for sending raw serialized events via the new API function bro_event_send_raw(), with much help from Matthias Vallentin. ------------------------------------------------------------------------ Mon Jun 29 15:20:58 PDT 2009 Christian - Fix for buffered data remaining in transmit buffer when calling for_event_queue_flush(). - Added bro_conn_get_connstats() which reports statistical information about a connection in a new dedicated structure BroConnStats. For now this is only the amount of data buffered in the rx/tx buffers. ------------------------------------------------------------------------ Mon Jun 29 15:18:10 PDT 2009 Christian - All multiprocess/-threading synchronization code has been removed. ------------------------------------------------------------------------ Mon Jun 29 15:10:59 PDT 2009 Christian - Broccoli now requires initialization before any connections may be created. The reason is twofold: (i) it provides a clean method for initializing relevant parts of Broccoli in multithreaded environments, and (ii) it allows configuration of parts of Broccoli where the normal approach via configuration files is insufficient. For details on the initialization process, refer to the manual, but generally speaking, a call to bro_init(NULL); at the beginning of your application is all that is required. For the time being, a number of high-level API calls double-check whether you have called bro_init() previously. - Broccoli now supports the callback functions OpenSSL requires for thread-safe operation. Implement those callbacks as required by your threading library, hook them into a BroCtx structure previously initialized using bro_ctx_init(), and pass the structure to bro_init(). This will hook the callbacks into OpenSSL for you. O'Reilly's book "Network Security with OpenSSL" provides an example of how to implement the callbacks. ------------------------------------------------------------------------ Thu Jun 25 16:46:37 PDT 2009 Christian - Fix to Python bindings: added required bro_init() call (Matthias Vallentin). ------------------------------------------------------------------------ Thu May 28 10:27:30 PDT 2009 Christian - The BroEvMeta structure used in compact event callbacks now allows access to the timestamp of event creation. ------------------------------------------------------------------------ Fri Mar 27 23:39:10 CET 2009 Christian - Fixed a memory leak triggered by bro_event_send() but actually caused by lack of cleanup after an underlying string duplication. Thanks to Steve Chan and Matthias Vallentin for helpful feedback. ------------------------------------------------------------------------ Wed Mar 25 11:26:16 CET 2009 Christian Formatting robustness fixes to bropipe (Steve Chan). ------------------------------------------------------------------------ Thu Feb 12 19:28:24 PST 2009 Christian - Updates to contributed bropipe command (Steve Chan): - Proper parsing of default host/port. - Support for "urlstring" type, which urlencodes spaces in strings and other special characters. ------------------------------------------------------------------------ Thu Dec 11 09:37:12 PST 2008 Christian - Optimization: the internal slots vector of hashtables is now lazily allocated when the first actual insertion happens. Since hashtables are used in various places in the BroVal structures but frequently remain empty, the savings are substantial. Thanks to Matthias Vallentin for pointing this out. ------------------------------------------------------------------------ Mon Nov 3 11:07:49 PST 2008 Christian - Fixes for I/O deadlocking problems: - A bug in the implementation of BRO_CFLAG_YIELD has been fixed. Input processing now only yields after the handshake is complete on *both* endpoints. - When events arrive during bro_conn_connect(), it could happen that deadlock ensues if no additional data are sent and __bro_io_process_input() can not read new input data. It no longer returns immediately in that case, and instead attempts to process any available input data. ------------------------------------------------------------------------ Sat Oct 4 15:05:07 CEST 2008 Christian - Added bro_record_get_nth_name() to the API (Seth Hall). - make install no longer worked for documentation, apparently as part of Bro's make install cleanup. This isn't quite right since gtk-doc documentation is normally installed in a well-known place and Broccoli will normally need to be installed via "make install", but for now I'm leaving it uninstalled and instead provide a specific "install-docs" target for people who want documentation installed. - Documentation updated where missing, and rebuilt. - Copyright years updated. ------------------------------------------------------------------------ Mon Sep 22 21:34:13 CEST 2008 Christian - Updated broping.bro (and broping-record.bro, slightly) to explicitly declare the used event types ahead of their use. ------------------------------------------------------------------------ Mon Sep 8 11:30:35 CEST 2008 Christian - Use of caching on received objects is now disabled by default, but can be enabled using the new connection flag BRO_CFLAG_CACHE. The old BRO_CFLAG_DONTCACHE is kept for backward compatibility but no longer does anything. Keeping the caches between Bro instances and Broccoli synchronized still needs to be implemented completely, and in the meantime no caching is the safer default. Thanks to Stephen Chan for helping track this down. ------------------------------------------------------------------------ Wed Jul 16 01:47:16 PDT 2008 Christian - Python bindings for Broccoli are now provided in the bindings/python subdirectory (Robin Sommer). They are not built automatically. See the instructions in bindings/python/README for details. - Minor documentation setup tweaks. ------------------------------------------------------------------------ Thu May 15 14:05:10 PDT 2008 Christian Event callbacks of the "compact" type are now able to obtain start- and end pointers of the currently processed event in serialized form, from the receive buffer stored with the connection handle. ------------------------------------------------------------------------ Wed Feb 20 13:53:51 PST 2008 Christian - Fix to __bro_openssl_read(), which handled some error cases reported by BIO_read() incorrectly. (Robin Sommer) - Clarifications to documentation of bro_conn_active() and bro_conn_process_input(). - Version bump to 1.4.0. ------------------------------------------------------------------------ Thu Sep 13 13:56:58 PDT 2007 Christian - autogen.sh now uses --force when running libtoolize, which at least in some setups seems to be necessary to avoid bizarre build issues. (In the particular case encountered, these looked like run-together ar and runlib invocations). Thanks to Po-Ching Lin for helping nail this down. ------------------------------------------------------------------------ Mon Sep 10 18:17:29 PDT 2007 Christian - Broccoli now supports table and set container types. Have a look at the bro_table_...() and bro_set_...() families of functions in broccoli.h, the updated manual, and the updated broconn and brotable examples in the test/ directory. ------------------------------------------------------------------------ Tue Sep 4 15:53:27 PDT 2007 Christian - Major bugfix for capabilities exchange during handshake: Broccoli did not convert into NBO, causing successful event exchange to fail. :( Amazingly, this means disabling cache usage per Broccoli's request never worked... ------------------------------------------------------------------------ Tue Sep 4 12:36:53 PDT 2007 Christian - Changed the way compact argument passing to event callbacks works. All event metadata is now represented by a single argument, a pointer to a BroEvMeta structure. It contains the name of the event, the number of arguments, and the arguments along with their types. Updated documentation and broping demo accordingly. NOTE: This introduces an API incompatibility. If you were previously using the compact callback API, you will need to update your code! I bumped up the library version info to 2:0:0 to signal this. - Fixed a bug in the implementation of BRO_CFLAG_YIELD and some SGML- violating documentation of same. ------------------------------------------------------------------------ Thu Aug 16 15:24:51 CEST 2007 Christian - Include autogen.sh in the distribution. ------------------------------------------------------------------------ Sat Aug 11 04:59:35 PDT 2007 Robin - New flag for Broccoli's connections: with BRO_CFLAG_YIELD, bro_conn_process_input() processes at most one event at a time and then returns (Robin Sommer). - The new Broccoli function bro_conn_new_socket() creates a connection from an existing socket, which can then be used with listen()/accept() to have Broccoli listen for incoming connections (Robin Sommer). ------------------------------------------------------------------------ Fri Jul 6 18:18:05 PDT 2007 Christian - Bumped up the version number to 1.3. Now that Broccoli is bundled with Bro, it makes sense to keep Broccoli's release version number in synch with Bro's. - Added the automake-provided ylwrap wrapper script to the distribution. This is for compatibility reasons: some automakes believe that Broccoli requires ylwrap, others don't. The distcheck target however needs ylwrap when it *is* required, so it's easiest to just provide one. It can always be overwritten locally, should the need arise. ------------------------------------------------------------------------ Wed Mar 7 10:49:25 PST 2007 Christian - Data format version number bumped up, in sync with Bro again. ------------------------------------------------------------------------ Mon Dec 4 12:07:12 PST 2006 Christian - Updated broconn.c to new bro_record_get_named_val(). ------------------------------------------------------------------------ Tue Nov 28 11:16:04 PST 2006 Christian - Run-time type information is now also available for the values stored in records (previously there was only type-checking, but no way to obtain the type of the vals). See the manual and API documentation of the functions bro_record_get_nth_val() and bro_record_get_named_val() for details. ------------------------------------------------------------------------ Mon Nov 27 18:38:06 PST 2006 Christian - Compact argument passing for event callbacks: as an alternative to the argument passing style used so far for event callbacks (dubbed "expan- ded"), one can now request "compressed" passing by using the bro_event_registry_add_compact() variant. Instead of passing every event argument as a separate pointer, compact passing provides only the number of arguments, and a pointer to an array of BroEvArgs. The elements of this array then provide pointers to the actual argu- ments as well as pointers to the new BroValMeta metadata structure, which currently contains type information about the argument. This style is better suited for applications that don't know the type of events they will have to handle at compile time, for example when writing language bindings. broping.c features example code, also see the manual for detailed explanation. ------------------------------------------------------------------------ Mon Nov 27 16:32:52 PST 2006 Christian - Bumped up version to 0.9 - I'm starting to use shared library version numbers to indicate API changes. Their correspondence to the release version number will be listed in VERSION. - Fixed a warning in bro_packet.c ------------------------------------------------------------------------ Mon Nov 27 16:23:46 PST 2006 Christian - Renamed cvs.pl to svn.pl - Bumped up BRO_DATA_FORMAT_VERSION to 13, to match that of Bro trunk. ------------------------------------------------------------------------ Mon Nov 27 16:21:28 PST 2006 Christian - Updating my commit script to SVN -- let's see if this works... ------------------------------------------------------------------------ Mon May 15 19:21:30 BST 2006 Christian - Correction to the explanation of bro_event_registry_add(), pointed out by Robin Sommer. ------------------------------------------------------------------------ Mon May 8 08:14:31 PDT 2006 Christian - Added config.sub and config.guess versions that seem to work well with MacOS X to the tree, to remove the dependency on the libtool/automake versions installed on the machine where tarballs are built. - Removed -f from libtoolize invocation in autogen.sh, so we don't overwrite the above. - Fixed COPYING, which wasn't actually referring to Broccoli. :) ------------------------------------------------------------------------ Sat May 6 20:17:32 BST 2006 Christian - Last-minute tweaks bring last-minute brokenness, especially when configuring without --enable-debug... :( ------------------------------------------------------------------------ Tue May 2 13:25:31 BST 2006 Christian - Added generated HTML documentation to CVS, so it is guaranteed to be included in tarballs generated via dist/distcheck, regardless of whether GtkDoc support exists on the build system or not. ------------------------------------------------------------------------ Tue May 2 02:31:39 BST 2006 Christian - Changed connection setup debugging output to state more clearly whether an SSL or cleartext connection is attempted, as suggested by Brian Tierney. - New configuration item /broccoli/use_ssl to enable/disable SSL connections, as suggested by Jason Lee. Documentation and sample configuration in broccoli.conf updated accordingly, look at the latter for a quick explanation. - A bunch of small tweaks to get distcheck to work properly when invoked from the Bro tree. - Other doc/Makefile.am cleanups. ------------------------------------------------------------------------ Sat Apr 29 19:12:07 PDT 2006 Christian - Fixed bogusness in docs/Makefile.am's dist-hook target. Should now work much better in general, and in particular not bomb out with non-GNU make. ------------------------------------------------------------------------ Fri Apr 7 23:52:20 BST 2006 Christian - Bumped up BRO_DATA_FORMAT_VERSION to 12, to match the one in Bro's CVS HEAD again. ------------------------------------------------------------------------ Mon Mar 27 22:59:04 BST 2006 Christian - This should fix a memleak detected by Jim Mellander and reported with a test case by Mark Dedlow. ------------------------------------------------------------------------ Fri Mar 3 16:40:56 GMT 2006 Christian - Warning for invalid permissions on ~/.broccoli.conf has been upgraded from debugging output to stderr, per request from Mark Dedlow. - Only check validity of config file name assembled via getenv("HOME") if it yields a filename different from the one assembled via the passwd entry. ------------------------------------------------------------------------ Thu Mar 2 17:57:49 GMT 2006 Christian - Reintroducing file needed for distcheck. ------------------------------------------------------------------------ Thu Mar 2 16:27:55 GMT 2006 Christian - Debugging fixlet. ------------------------------------------------------------------------ Fri Feb 3 20:31:08 GMT 2006 Christian - Embarrassing debugging output fixes. ------------------------------------------------------------------------ Fri Jan 27 23:40:23 GMT 2006 Christian - Only do lock operations when there's any need for them. ------------------------------------------------------------------------ Fri Jan 27 18:30:06 GMT 2006 Christian I am *so* fired. Overlooked a very clear warning that bro_io.c:lock() wasn't returning a value. ------------------------------------------------------------------------ Wed Jan 18 10:45:33 GMT 2006 Christian - Fixed call trace debugging inconsistencies, this will hopefully fix a case of runaway call trace indentation depth that Robin + Stefan have bumped into. ------------------------------------------------------------------------ Wed Jan 4 16:21:07 GMT 2006 Christian - Documentation fixlet, pointed out by Stefan Kornexl. ------------------------------------------------------------------------ Thu Dec 22 00:48:20 GMT 2005 Christian - Attempt at a more portable detecting of [g]libtoolize. Let me know if this works any better. ------------------------------------------------------------------------ Mon Dec 19 17:48:19 PST 2005 Christian - Moved brosendpkts.c and rcvpackets.bro from test/ to contrib/, i.e., out of the default build process. brosendpkts.c defines variables in the middle of main(), which some compilers tolerate while others don't. This should fix build issues reported by Brian Tierney. ------------------------------------------------------------------------ Thu Dec 15 18:38:18 GMT 2005 Christian Configuration tweaks to run smoothly when invoked from a Bro build. - Added AC_CONFIG_AUX_DIR(.) to make sure things are exclusively run out of our tree. - Added flags to autogen.sh and configure.in to indicate that we're part of a Bro build. ------------------------------------------------------------------------ Fri Dec 2 14:04:05 GMT 2005 Christian - Removed EXTRA_DIST for the test app policies, since they are included in the tarball and installed anyway via pkgdata_DATA. ------------------------------------------------------------------------ Fri Dec 2 13:59:27 GMT 2005 Christian - Added "brosendpkts", a test program for sending pcap packets to a Bro, plus the accompanying Bro policy. Contributed by Stefan Kornexl and Robin Sommer, with a tiny tweak to build only when pcap support is available. ------------------------------------------------------------------------ Wed Nov 23 11:59:03 PST 2005 Christian - Avoided the keyword "class" to prevent problems with using broccoli.h in a C++ context. Pointed out by Stefan Kornexl. ------------------------------------------------------------------------ Tue Nov 8 14:10:23 PST 2005 Christian - Added support for connection classes, updated documentation. ------------------------------------------------------------------------ Mon Oct 31 19:37:55 PST 2005 Christian - Support for specifying type names along with values. This is done through a new and optional argument to bro_event_add_val(), bro_ record_add_val(), and friends. See manual for details. - Added a test program "broenum" for demonstrating this. When running Bro with the provided broenum.bro policy, it sends a single event with an enum val to the remote Bro, which will print both numerical and string representations of the value. For example, broenum.bro defines an enum type type enumtype: enum { ENUM1, ENUM2, ENUM3, ENUM4 }; Given this, $ broenum -n 0 yields Received enum val 0/ENUM1 $ broenum -n 1 yields Received enum val 1/ENUM2 $ broenum -n 4 yields Received enum val 4/ You can also test predefined enums: $ broenum -t transport_proto -n 1 yields Received enum val 1/tcp ------------------------------------------------------------------------ Mon Oct 31 17:07:15 PST 2005 Christian Changed commit script to pass the commit message through the generated file via -F, instead of via -m and the command line. D'oh. ------------------------------------------------------------------------ Mon Oct 31 17:03:47 PST 2005 Christian - Support for the new abbreviated serialization format for types. Need to come up with a decent API for actually using this feature now. ------------------------------------------------------------------------ Mon Oct 31 11:25:22 PST 2005 Christian Several changes to handshake implementation and API(!). - Refactored the handshake code to make the multiple phases of the connection's initialization phase more explicit. Our own and the peer's handshake state are now tracked separately. conn_init_configure() takes care of our state machine with a separate function per phase, and __bro_io_process_input() handles the peer's state. - Added support for capabilities. The only capability Broccoli currently supports is a non-capability: it can ask the remote Bro not to use the serialization cache. In order to do so, pass BRO_CONN_DONTCACHE as a connection flag when obtaining the connection handle. Needs more testing. - Several API changes. Given the more complex handshake procedure that is in place now, the old approach of only completing the handshake half- way in bro_connect() so the user can requests before calling bro_conn_await_handshake() (or alternatively, passing BRO_CONN_COMPLETE_HANDSHAKE as a connection flag) is just too messy now. The two steps of obtaining a connection handle and establishing a connection have been split into separate functions, so the user can register event handlers in between. What was BroConn *bc = bro_connect(..., BRO_CFLAGS_NONE); bro_event_registry_add(bc,...); bro_event_registry_add(bc,...); bro_event_registry_request(bc); bro_conn_await_handshake(bc); /* ... */ bro_disconnect(bc); is now BroConn *bc = bro_conn_new(..., BRO_CFLAGS_NONE); bro_event_registry_add(bc,...); bro_event_registry_add(bc,...); bro_conn_connect(bc); /* ... */ bro_conn_delete(bc); Note that the explicit call to bro_event_registry_request() is gone as bro_conn_connect() will automatically request event types for which handlers have been installed via bro_event_registry_add(). What was BroConn *bc = bro_connect(..., BRO_CFLAGS_COMPLETE_HANDSHAKE); bro_disconnect(bc); is now BroConn *bc = bro_conn_new(..., BRO_CFLAGS_NONE); bro_conn_connect(bc); /* ... */ bro_conn_delete(bc); I might add bro_conn_disconnect() in the near future. It'd allow us to keep a completely configured connection handle around and use it repeatedly for establishing connections. Sorry for the inconvenience but I really think this is a lot nicer than the old API. The examples and documentation have been updated accor- dingly. ------------------------------------------------------------------------ Sat Oct 29 15:43:18 PDT 2005 Christian Added an optional age list to the hash table implementation. We'll need this to duplicate Bro's object serialization caching strategy. ------------------------------------------------------------------------ Fri Oct 28 15:26:55 PDT 2005 Christian Brothers and sisters, hallelujah! On the 27th day Christian looked at record vals in the Broccoli, and he saw that it was leaking like a sieve. So Christian ran the valgrind. On the 28th day Christian still looked at Broccoli, with tired eyes, ground the vals[1] a bit more, and he saw that it was plugged[2]. Amen. :) [1] Really really bad pun. Sorry. [2] I get zero memleaks on broping -r -c 100 now. :) ------------------------------------------------------------------------ Thu Oct 27 20:02:39 PDT 2005 Christian First crack at reference-counted sobjects. I need reference counting in order to get rid of objects in the serialization cache (since they can contain nested objects etc -- it's nasty), which I had ignored so far. There are still leaks in the event transmission code, dammit. :( ------------------------------------------------------------------------ Thu Oct 27 15:06:10 PDT 2005 Christian Added my own list implementation due to suckiness of the TAILQ_xxx macro stuff which I never liked anyway. The problem is that elements of lists built using these macros can only have each member exactly once as the prev/next pointers are part of the structs. A few uses of TAILQ_xxx remain, these will go in the near future. ------------------------------------------------------------------------ Tue Oct 25 19:57:42 PDT 2005 Christian Partial support for enum vals, per request from Weidong. Sending enum vals should work, though the underlying enum types aren't fully handled yet. ------------------------------------------------------------------------ Mon Oct 24 16:31:56 PDT 2005 Christian TODO item: clean up generated parser/lexer files when we know we can regenerate them. make clean currently does not erase them, which caused Weidong some trouble. ------------------------------------------------------------------------ Fri Oct 21 17:48:51 PDT 2005 Christian Clarification to the manual, after a question from Weidong. ------------------------------------------------------------------------ Fri Oct 14 18:05:39 PDT 2005 Christian Transparent reconnects should work again (took all *day*, argh -- I totally broke it with the connection sharing stuff). Try broping while occasionally stopping and restarting the Bro side. Fixed a number of memleaks -- broping is now leak-free according to valgrind. Clarifications in the debugging output. ------------------------------------------------------------------------ Fri Oct 14 12:07:10 PDT 2005 Christian Added documentation for the new user data argument to bro_event_registry_add(). ------------------------------------------------------------------------ Fri Oct 14 11:48:00 PDT 2005 Christian Added user data to event handler callbacks. This is necessary for example when using class members in C++ as callbacks since the object needs to be provided at the time of dereferencing. It's also easier to use than the existing bro_conn_{set,get}_data() mechanism. Updated documentation with more details on the broccoli-config script. ------------------------------------------------------------------------ Thu Oct 13 15:08:56 PDT 2005 Christian When supporting packets (the default), check whether pcap.h actually exists. This has thus far just been assumed. We don't actually use the library, so there's no need to test for it. ------------------------------------------------------------------------ Mon Oct 10 20:37:15 PDT 2005 Christian Changed bro_record_get_named_val() and bro_record_get_nth_val() to return a pointer to the queried value directly, instead of through a pointer argument. These arguments' type used to be void* though it should really be void**, but switching to void** causes lots of warnings with current GCCs ('dereferencing type-punned pointer will break strict-aliasing rules'). NULL is perfectly usable as an error indicator here, and thus used from now on. Updated manual, broping, and broconn accordingly. ------------------------------------------------------------------------ Tue Sep 20 17:19:58 PDT 2005 Christian Fixed a varargs buglet that is tolerated on Linux but not BSD. Pointed out by Scott Campbell. ------------------------------------------------------------------------ Fri Sep 9 18:48:54 PDT 2005 Christian Support for textual tags on packets, also an upgrade to more complex handshake procedure that allows for synchronization of state (Robin Sommer). Note: as of this change, at least Bro 1.0a2 is required. ------------------------------------------------------------------------ Wed Aug 10 01:36:47 BST 2005 Christian Fixed my insecure usage of snprintf. ------------------------------------------------------------------------ Tue Jul 19 10:11:49 PDT 2005 Christian Forgot to include broconn's policy file in the distribution. ------------------------------------------------------------------------ Mon Jul 18 16:34:22 PDT 2005 Christian Fixed a bug that caused the lookup of record fields by name to fail. ------------------------------------------------------------------------ Fri Jul 1 00:44:49 BST 2005 Christian The sequence of tests determining which config file to read from failed to fall back properly to the global config file in case of incorrect user permissions. Fixed. ------------------------------------------------------------------------ Mon Jun 27 19:34:56 PDT 2005 Christian Added bro_buf_reset() to the user-visible API. ------------------------------------------------------------------------ Mon Jun 27 17:58:53 PDT 2005 Christian When a configuration item cannot be found in the current config file section, a lookup is also attempted in the default section (the one at the top of the file, before any sections are defined). This allows the sections to override the default section, which is what one would expect. ------------------------------------------------------------------------ Mon Jun 27 14:43:56 PDT 2005 Christian Debugging output tweak. When providing the SSL cert passphrase via the config file, do no longer report it in the debugging output. ------------------------------------------------------------------------ Mon Jun 27 12:33:52 PDT 2005 Christian Cosmetics in the debugging output of __bro_openssl_write(). ------------------------------------------------------------------------ Fri Jun 24 18:13:49 PDT 2005 Christian Added --build flag to broccoli-config. It reports various details about the build, for example whether debugging support was compiled in. ------------------------------------------------------------------------ Fri Jun 24 10:37:23 PDT 2005 Christian I'm adding a little test app that subscribes to a few connection events and prints out the fields of the received connection records, both for testing and code demonstration purposes. So far it has highlighted a bug in Bro that occurs when a remote app is a pure requester of events and not sending anything. Fix pending. ------------------------------------------------------------------------ Mon Jun 20 18:21:24 PDT 2005 Christian Show the names of requested events in the debugging output -- it had to be deciphered from the hex string which isn't that much fun. ------------------------------------------------------------------------ Thu Jun 16 14:02:59 PDT 2005 Christian Better documentation of how to extract record fields. ------------------------------------------------------------------------ Thu Jun 16 11:51:02 PDT 2005 Christian - Added bro_string_get_data() and bro_string_get_length() to avoid making people access BroString's internal fields directly. - Moved BroString's internal storage format to uchar*. ------------------------------------------------------------------------ Sun Jun 12 19:17:31 PDT 2005 Christian Debugging output now shows the correct function and line numbers again. I had accidentially moved __FUNCTION__ and __LINE__ into bro_debug.c :( ------------------------------------------------------------------------ Fri Jun 3 15:00:48 PDT 2005 Christian I broke the sanity checks for semaphore initialization when I moved the semaphore structures to shared memory. Fixed. ------------------------------------------------------------------------ Mon May 16 22:25:41 PDT 2005 Christian - Debugging output now goes to stderr instead of stdout. That keeps it out of the way if an instrumented app dups() stdout to another file descriptor. - Debugging output is now disabled by default (even when compiled in), so it needs to be enabled explicitly in the code or in the config file. ------------------------------------------------------------------------ Fri May 13 18:24:23 PDT 2005 Christian Synchronization fixes and minor cleanups. - Unsuccessful connection attempts to remote Bros in combination with connection sharing caused the caller to hang indefinitely. This should now be fixed, but required some fairly intricate tweaks to the locking constructs. Still needs more testing. - Bumped version to 0.8. ------------------------------------------------------------------------ Fri May 6 23:09:29 BST 2005 Christian This is the 0.7.1 release. ------------------------------------------------------------------------ Fri May 6 14:44:53 PDT 2005 Christian Documentation for shareable connection handles. ------------------------------------------------------------------------ Fri May 6 12:11:17 PDT 2005 Christian Build fixlets. - Don't only test for the first of the documentation extraction tools, but also for those used later on. - Few more signedness warnings fixed. ------------------------------------------------------------------------ Wed May 4 18:33:40 PDT 2005 Christian Fixed a whole bunch of signedness warnings reported by gcc 4 on MacOS 10.4. Thanks to Roger for the quick reply. ------------------------------------------------------------------------ Wed May 4 17:41:40 PDT 2005 Christian Fix for a little-endian bug that I managed to introduce when testing on Solaris ... *sigh* :( ------------------------------------------------------------------------ Wed May 4 17:30:07 PDT 2005 Christian A number of portability fixes after testing the build on Linux, FreeBSD and Solaris. ------------------------------------------------------------------------ Mon May 2 20:17:04 PDT 2005 Christian Fixed an obvious bug the config file parser. I'm baffled as to how it could go unnoticed for so long. ------------------------------------------------------------------------ Mon May 2 20:11:25 PDT 2005 Christian Portability fixes. - Use -pthread (not -lpthread) in both the --cflags and --libs options to broccoli-config, if required. -lpthread does not work on BSDs, where -pthread has different effects on the linker. - s/System V/SYSV/ in configure script output for consistency. - Bumped version to 0.7.1. It should build correctly on BSDs and Linux now. Still need to check whether synchronization actually works on the BSDs. ------------------------------------------------------------------------ Fri Apr 29 23:12:01 BST 2005 Christian If the configure script determines we need -lpthread, it's a good idea to actually reflect that in broccoli-config. ------------------------------------------------------------------------ Fri Apr 29 22:36:26 BST 2005 Christian Fix for SYSV semaphores pointed out by Craig Leres -- I completely forgot to test the SYSV stuff before the release. *sigh*. ------------------------------------------------------------------------ Thu Apr 28 13:46:57 BST 2005 Christian - This is the 0.7 release. ------------------------------------------------------------------------ Thu Apr 28 13:43:44 BST 2005 Christian RPM spec file fixlet. ------------------------------------------------------------------------ Wed Apr 27 18:04:57 BST 2005 Christian Preparations for the 0.7 release. ------------------------------------------------------------------------ Wed Mar 16 18:34:27 GMT 2005 Christian I think shared connections w/ SSL work. :) They key aspects are - We want to be able to use a single connection handle in arbitrary process/thread scenarios: in sshd, a single handle created in the listening process should work in all forked children (right now I'm created separate ones in each child, yuck), in Apache it should work in all servicing threads (creating a separate connection in each servicing thread would be far too costly), etc. - However, all SSL I/O on a single BIO must happen in the same *thread* according to openssl-users -- same process seems intuitive because of cipher streams etc; why it's per thread I don't know. The approach is now as follows: when a connection handle is marked as shareable, an I/O handler process is forked off during handle setup that processes all I/O for a single connection handle exclusively. Data are processed through separate tx/rx buffers that live in shared memory and are protected by semaphores. Additionally, a number of fields in the connection handle also live in shared memory so can be used to send back and forth messages etc. By using global semaphores as condition variables, rx/tx requests are dispatched to the I/O handler process. Therefore this should work for all multi-process/thread scenarios in which processes/threads are created after the connection handle is set up. This all is transparent when a connection is not marked shareable. The main optimization left to do now is to make the locking more fine- grained -- a throughput comparison is going to be interesting... I haven't tried transparent reconnects again; I'd presume I managed to break them in the process. ------------------------------------------------------------------------ Mon Mar 14 17:31:17 GMT 2005 Christian - Lots of work on shared connection handles. This is going to take a while to work robustly. For now steer clear of BRO_CFLAG_SHAREABLE. - Fixed wrong ordering of semaphore locks in __bro_io_msg_queue_flush(). - The connection hack to work around OpenSSL's 'temporary unavailable' beliefs is now only used when the problem occurs, namely during reconnects. - Fixed a bug in the Posix version of __bro_sem_new() that prevented processes from creating more than one different semaphores. Doh. - Bumped BRO_DATA_FORMAT_VERSION to 9, to sync up with Bro tree. - Added __bro_sem_get(), returning the current value of a sempahore, with implementations for Posix + SYSV. - Lots of calltracing added. ------------------------------------------------------------------------ Mon Mar 14 10:24:54 GMT 2005 Christian Code for shared connection handles with SSL enabled. Pretty much done, but needs a lot of testing now. ------------------------------------------------------------------------ Sat Mar 12 18:13:58 GMT 2005 Christian Beginning of support for sharing connection handles for SSL-enabled connections. Since supporting this is complex, it will be optional, and enabled by using the new BRO_CFLAG_SHAREABLE connection flag. ------------------------------------------------------------------------ Fri Mar 11 14:50:23 GMT 2005 Christian Move to AC_PROG_LIBTOOL. ------------------------------------------------------------------------ Fri Mar 11 14:33:57 GMT 2005 Christian Portability and robustness fixes. - auto* calls in autgen.sh are now checked for success and cause the script to abort on error. - Instead of trying to figure out what libraries the various OSs need in order to be able to use Posix semaphors, I'm now attempting to use the -pthread flag directly. If that fails, we just fall back to SYSV semaphores. - All semaphore + shmem implementations are now included in the tarball, the point is to include them selectively in the *build*. - Stevens' ifdef magic for union semun doesn't work on at least OpenBSD so I'm using the BSD_HOST macro from config.h now. - Apparently AM_PROG_LIBTOOL causes some people trouble so we need to check how to get that working realiably :( ------------------------------------------------------------------------ Mon Feb 21 14:45:51 GMT 2005 Christian - Partial-write bugfix. When we succeed only partially in writing out a message, report success, not failure. Failure is handled by queuing the message for later transmission, but we have already sent it partially and the rest is still stuck in the output buffer, so if we queue it again, it'll get sent at least twice. I had noticed that out of 100000 events sent by 100 processes in parallel, typically around 100020 arrived :) ------------------------------------------------------------------------ Sat Feb 19 21:04:46 GMT 2005 Christian - Lots of synchronization work. This generally seems to work now! :) It required one major addition: support for shared memory. The problem is that if multiple threads/processes attempt to write at the same time and one write succeeds only partially, then *whichever* thread/process gets to write next needs to write out the rest before writing any new messages. The only alternative is to have write operations block until entire messages are sent, which seems dangerous from an instrumentation point of view. To share the remaining message data, shared memory is required: both the tx and rx buffers now operate in shared memory and are protected by semaphores. The current implementation uses SYSV shared memory. I think shared memory is a good idea in general; for example it could be used during instrumentation to get information from one corner of an app to another without changing the application's structure. I don't think we'll need this right away, but it's nice to have a possible technique for it. - bro_disconnect() is now more tricky to use than before: if you use it in a parallel setting, you *must* call it from the same process that called bro_connect() and you must do so *after* all the other processes have finished using the connection (typically this is not hard to do, so I think we can live with that). The reason is that semaphores + shared memory need to be uninstalled specifically and I haven't yet figured out a way to automate reference counting so that the last thread/process using a connection could do this automatically. It would be very cool if the functions that are used for deinstallation could be asked to fail while the IPC objects are still in use, but that's not the case. - You can still build the whole thing without semaphores or shared mem and it'll work for single-threaded apps. The configure script now issues a warning if not all tools required for stable parallel operation can be found. - Added bro_event_queue_length_max() to allow applications to find out the maximum queue length before messages will get dropped. brohose uses this to wait until the queue gets half full before insisting on a flush. ------------------------------------------------------------------------ Fri Feb 18 17:14:40 GMT 2005 Christian - SYSV semaphore implementation. Configure checks are included and work as follows: if both Posix + SYSV semaphores are found, Posix are preferred, however the user can override this by passing --disable-posix-semaphores. Semaphores are still not actually used. ------------------------------------------------------------------------ Thu Feb 17 22:24:12 GMT 2005 Christian - First shot at semaphore support. Checking for Posix named semaphores and making sure they actually work at configure time was the hardest part; actual semaphore code untested and still unused. No ifdefs anywhere :) ------------------------------------------------------------------------ Thu Feb 17 20:06:00 GMT 2005 Christian - Incompletely sent chunks are now recognized and remaining parts are shipped as soon as possible: repeated brohose -n 1 -e 1000 runs do not take out Bro any more. :) ------------------------------------------------------------------------ Thu Feb 17 19:21:15 GMT 2005 Christian - Added "brohose", which lets you hose a Bro with events by forking a configurable number of processes, and having each process pump out an event a configurable number of times as fast as possible. This is meant as both a stress-testing tool for the protocol as well as obviously for the synchronization stuff that'll go into Broccoli soon. ------------------------------------------------------------------------ Wed Feb 16 17:40:47 GMT 2005 Christian - Documentation for the configuration options for debugging output. ------------------------------------------------------------------------ Thu Feb 10 11:39:57 GMT 2005 Christian - Changed bro_event_queue_empty() to bro_event_queue_length(), which is more useful in general and can be used to find out whether the queue is empty, too. ------------------------------------------------------------------------ Tue Feb 8 14:45:58 GMT 2005 Christian - This is release 0.6. ------------------------------------------------------------------------ Mon Feb 7 14:54:15 GMT 2005 Christian - Additional byte swaps for IP addresses + subnets for compatibility with Bro. ------------------------------------------------------------------------ Sun Feb 6 23:55:07 GMT 2005 Christian - Debugging output can now be configured from the config file, using the /broccoli/debug_messages and /broccoli/debug_calltrace config items. ------------------------------------------------------------------------ Tue Feb 1 21:34:17 GMT 2005 Christian - During handshake, data format compatibility is now confirmed as well as matching protocol version. ------------------------------------------------------------------------ Tue Feb 1 21:04:43 GMT 2005 Christian - Initial commit of support for sending/receiving libpcap packets. Totally untested, and not documented yet. More on this once support for packets is committed into the Bro tree. ------------------------------------------------------------------------ Tue Feb 1 18:39:02 GMT 2005 Christian - Transparent reconnects now also work for non-SSL connections. I was just lucky that the SSL handshake prevented the same problem from occurring in the SSL-enabled case. Two fixes were necessary: 1) a separate attempt to connect to the peer that I have full control over, and 2) a fixlet in queue management that caused the event that triggers the reconnect to be sent before any handshake information for the new connection, thus causing a connection teardown by the Bro end because the version number was not seen at the right time. ------------------------------------------------------------------------ Mon Jan 31 19:38:36 GMT 2005 Christian - Fixed a few spots where D_ENTER was not balanced with D_RETURN - Added an int-to-string table for message types, for debugging - Added a flag to the connection structure that prevents reconnect attempts while one is already in progress - Made io_msg_queue() private to bro_io.c because it was only called from there. ------------------------------------------------------------------------ Fri Jan 28 12:35:03 GMT 2005 Christian - Changed the error semantics of in __bro_io_msg_queue() so that queuing a message after failure to send is not a failure. This fixes an issue with handshake completion that I have observed with broping across different machines, where events could still get lost despite explicit request to complete the handshake. ------------------------------------------------------------------------ Sun Jan 16 20:45:42 GMT 2005 Christian - Serialization/Unserialization for ports fixed, support for ICMP ports. ------------------------------------------------------------------------ Sat Jan 15 13:58:16 GMT 2005 Christian - Sending and receiving IP addresses and subnets was broken, fixed now. - Fixed a small memleak when first-time connection setup fails. ------------------------------------------------------------------------ Thu Jan 13 21:03:45 GMT 2005 Christian - When using reconnects, Broccoli will now not attempt to reconnect more than once every 5s. ------------------------------------------------------------------------ Thu Jan 13 20:43:13 GMT 2005 Christian - Added connection flag BRO_CFLAG_ALWAYS_QUEUE that causes events always to be queued in the connection's event queue regardless of whether the peer is currently dead or not. - Moved the test of whether the peer requested an event that is about to be sent or not to the point where the event actually is about to be sent, from the point where it is requested to be sent. The difference is that now an event will get silently dropped on the floor if after a connection outage and a reconnect, a change in the events requested from the peer will prevent the old queued events to be sent anyway, even if they are no longer requested. ------------------------------------------------------------------------ Wed Jan 12 20:46:10 GMT 2005 Christian - Added support for transparent reconnects for broken connections. When using BRO_CFLAG_RECONNECT, Broccoli now attempts to reconnect whenever a peer died and the user tries to read from or write to the peer. This can aways be triggered manually using bro_reconnect(). - Added bro_conn_alive() to determine if a connection is currently alive or not. ------------------------------------------------------------------------ Tue Jan 11 17:33:51 GMT 2005 Christian - Added connection flags parameter to bro_connect() and bro_connect_str(): BRO_CFLAG_COMPLETE_HANDSHAKE completes the handshake right away before returning from bro_connect()/ bro_connect_str(), and BRO_CFLAG_RECONNECT still needs to be implemented. Documentation updated accordingly. ------------------------------------------------------------------------ Sat Jan 8 21:07:30 CET 2005 Christian - Allow empty (or comments-only) configuration files. ------------------------------------------------------------------------ Sat Jan 8 20:52:56 CET 2005 Christian - Fixed the home directory lookup via getpwent() -- now correctly looks up the entry of the current effective user. Doh. - Beginning of code for connection flags to use when creating a connection, for example for handshake behaviour, automatic reconnection attempts, etc. ------------------------------------------------------------------------ Tue Jan 4 23:28:59 CET 2005 Christian - constness fixes for functions that accept values for events and record fields. ------------------------------------------------------------------------ Tue Jan 4 22:07:35 CET 2005 Christian - Encrpyted connections now extract as much data as possible from the underlying buffer by calling BIO_read() optimistically. - For encrypted connections, the passphrase for the certificate's private key can now be specified in the configuration file using key "/broccoli/host_pass". - Added support for the handshake message in the Bro protocol. - If the ca_cert or host_cert keys are found in the config file, but there is a problem loading the crypto files, don't attempt to connect. - Completed documentation on encrypted communication, explaining the use of ca-create and ca-issue. - Fixed several bugs in the handling of sections in config files. Matching of domain names is now case-insensitive. - The ~/.broccoli.conf file is now only used when it is readable only by the user owning it. - More robustness for corner cases of buffer sizes. - Fixed a bug in sending messages that consist of only a single chunk (like the handshake message). - The library now attempts to initialize the random number generator in OpenSSL from /dev/random if possible. ------------------------------------------------------------------------ Fri Dec 24 11:58:08 CET 2004 Christian - If the ca_cert or host_cert keys are found in the config file, but there is a problem loading the crypto files, don't attempt to connect. - Completed documentation on encrypted communication, explaining the use of ca-create and ca-issue. - Fixed several bugs in the handling of sections in config files. ------------------------------------------------------------------------ Thu Dec 23 14:33:56 GMT 2004 Christian - Added sections support for configuration files. Sections can be declared at arbitrary points in the config file, using the same syntax as in OpenSSL config files. There can be a global section at the beginning of the file, before the first declared sections. Sections are selected using bro_conf_set_domain(). - Support for a per-user config file in ~/.broccoli.conf. This does not override settings in the global config file but completely replaces it, i.e., when the user-specific file is found, the global one is ignored. - Added bro_conn_await_handshake() that blocks for limitable amount of time, waiting for the handshake of a new Bro connection to complete. This still needs some fixing, but is definitely necessary to prevent weird races from occurring when a client tries to use a new connection that has not yet been established completely. - Test applications are now linked to static libraries. This will hopefully keep the build more portable. - Use of LFLAGS and YFLAGS moved to AM_LFLAGS and AM_YFLAGS, given the warnings issued when using automake 1.9. - First shot at fixing the buffer flushing issues I see when using encrypted connections. ------------------------------------------------------------------------ Fri Dec 10 16:31:26 GMT 2004 Christian - Added + fixed OpenSSL code to support encrypted communication. - Added OpenSSL as requirement to spec file. - Changed broping policies to always use the same port - Updated broccoli.conf: added keys for the CA's and the host's cert. ------------------------------------------------------------------------ Thu Dec 9 14:59:24 GMT 2004 Christian - Build fixes in case documentation tools are not found - Documentation polishing -- only SSL setup section todo still. ------------------------------------------------------------------------ Thu Dec 9 00:48:05 GMT 2004 Christian - Final documentation passes for the 0.6 release. ------------------------------------------------------------------------ Mon Dec 6 17:18:55 GMT 2004 Christian - More documentation, explaining the data types, records, Bro policy configuration, started section on SSL setup (copied from Robin right now), and minor fixes. ------------------------------------------------------------------------ Mon Dec 6 15:17:05 GMT 2004 Christian - Added spec file for building RPMs -- seems to work - Aest policies are now installed in $prefix/share/broccoli ------------------------------------------------------------------------ Mon Dec 6 00:22:02 GMT 2004 Christian - Dropped the ..._raw() functions for records. These won't be used internally ever. Their implementation moved to bro.c, and only the high- level code remained in bro_record.c. - Added bro_event_set_val() to replace a val in an existing event. There's not much use in resending an existing event unless it is identical, which is not that useful. High-level code is in __bro_event_set_val(). - Made it more clear in the comments explaining the bro_record_get_..._val() functions that the "result" argument must actually be the address of a pointer. (void * as argument type means that the compiler does not issue a warning when passing in, say, a double * -- but it would do so if we would use void **.) ------------------------------------------------------------------------ Sun Dec 5 22:05:53 GMT 2004 Christian - Updates to the cvs wrapper script: surround with date and name only in the ChangeLog, not in the commit message itself. ------------------------------------------------------------------------ Sun Dec 5 02:15:29 GMT 2004 Christian - Fixed a bug in __bro_val_clone(): forgot to handle BRO_INTTYPE_OTHER. - Changed --enable-debugging flag to --enable-debug, for consistency with the Bro tree. - Fixed bugs in several cloning implementations that didn't call the parent's implementation. ------------------------------------------------------------------------ Sun Dec 5 01:40:52 GMT 2004 Christian - Added __bro_event_copy() to clone events internally. - Events are now duplicated in __bro_io_event_queue() before they're sent so the user's event remains unaffected (and thus could be sent repeatedly etc). - Extensive pass over the documentation; still a good deal to do. ------------------------------------------------------------------------ Sat Dec 4 03:09:05 GMT 2004 Christian More work on documentation, much is outdated now. ------------------------------------------------------------------------ Sat Dec 4 02:05:30 GMT 2004 Christian - Started a ChangeLog. No detailed ChangeLog information was kept previous to this commit. ------------------------------------------------------------------------ broccoli-1.97-minimal/svn.pl0000775002342100234210000000715012523041064015656 0ustar johannajohanna#!/usr/bin/perl -w # CVS/SVN wrapper script that maintains a nice ChangeLog for us. # Heavily hacked & cleaned up, originally based upon a script # that was once used in the Enlightenment project. use strict; use FileHandle; # Prototypes #_______________________________________________________________________ sub create_changelog; sub validate_commit_message; sub create_commit_message; sub setup_username_translation; sub update_changelog; sub check_parameters; # Globals #_______________________________________________________________________ my %names; my ($date, $author); # Formats #_______________________________________________________________________ format ENTRY = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $date, $author . # Subroutines #_______________________________________________________________________ sub setup_username_translation { $names{"kreibich"} = "Christian "; $names{"cpk25"} = "Christian "; $names{"christian"} = "Christian "; } sub create_changelog { my $cl = "ChangeLog"; my $num_lines; my $wc; my @lines; my @commitlines; my $line; print "Updating the ChangeLog with your entry.\n"; if (open CHANGELOG, $cl) { @lines = ; close CHANGELOG; shift (@lines); shift (@lines); } open CHANGELOG, ">$cl"; print CHANGELOG <; close COMMITLOG; } CHANGELOG->format_name("ENTRY"); $date = `date`; $author = $names{$ENV{USER}}; write CHANGELOG; CHANGELOG->format_name(); print CHANGELOG "\n"; print CHANGELOG @commitlines; print CHANGELOG "\n------------------------------------------------------------------------\n"; print CHANGELOG @lines; close CHANGELOG; } sub create_commit_message { print "Please create a log message for the ChangeLog.\n"; if (open COMMITLOG, ">CommitLog") { print COMMITLOG "-" x 72; print COMMITLOG "\n"; close COMMITLOG; } if($ENV{EDITOR}) { system("$ENV{EDITOR} CommitLog"); } else { system("vi CommitLog"); } } sub update_changelog { my @ARGV2; @ARGV2 = @ARGV; $ARGV2[0] = "update"; print "Force updating ChangeLog\n"; unlink "ChangeLog"; system("svn update ChangeLog"); } sub check_parameters { if (scalar(@ARGV) < 1) { print "USAGE: cvs.pl \n"; exit (0); } } # Main Program #_______________________________________________________________________ check_parameters(); setup_username_translation(); if (($ARGV[0] =~ /com/) || ($ARGV[0] =~ /ci/)) { my @ARGV2; create_commit_message(); update_changelog(); $ARGV[0] .= " -F CommitLog"; @ARGV2 = @ARGV; $ARGV2[0] = "update"; print "Updating the files you are committing.\n"; system("svn @ARGV2 2>&1 |tee errors"); if (open ERRORS, "errors") { while() { if (/conflicts during merge/) { print "There are one or more conflicts,\n" . "Please resolve and try again.\n"; unlink "errors" if(-f "errors"); exit(0); } } close ERRORS; } unlink "errors" if(-f "errors"); create_changelog(); if($#ARGV >= 1) { my $found; $found = 0; foreach(@ARGV) { $found = 1 if(/ChangeLog$/); } push @ARGV, "ChangeLog" if(! $found); } } print "svn @ARGV\n"; system("svn @ARGV"); print "Finished.\n" broccoli-1.97-minimal/src/0000775002342100234210000000000012523041064015274 5ustar johannajohannabroccoli-1.97-minimal/src/bro_record.h0000664002342100234210000000476112523041064017575 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_record_h #define broccoli_record_h #include #include /* Typedef is in broccoli.h because the users need to know it -- we keep * it opaque for them though by defining it here. */ struct bro_record { BroList *val_list; int val_len; }; BroRecord *__bro_record_new(void); void __bro_record_free(BroRecord *rec); BroRecord *__bro_record_copy(BroRecord *rec); int __bro_record_get_length(BroRecord *rec); /* Adds the given val as a new field and adopts ownership, * i.e, the value is not duplicated internally. */ void __bro_record_add_val(BroRecord *rec, BroVal *val); BroVal *__bro_record_get_nth_val(BroRecord *rec, int num); const char *__bro_record_get_nth_name(BroRecord *rec, int num); BroVal *__bro_record_get_named_val(BroRecord *rec, const char *name); int __bro_record_set_nth_val(BroRecord *rec, int num, BroVal *val); int __bro_record_set_nth_name(BroRecord *rec, int num, const char *name); int __bro_record_set_named_val(BroRecord *rec, const char *name, BroVal *val); uint32 __bro_record_hash(BroRecord *rec); int __bro_record_cmp(BroRecord *rec1, BroRecord *rec2); #endif broccoli-1.97-minimal/src/bro_openssl.c0000664002342100234210000004060312523041064017770 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef __MINGW32__ #include #else #include #include #include #include #include #endif #ifdef __EMX__ #include #endif #include #include #include #include #include #include #include #include #include #include /* PLEASE NOTE: this file deals with handling I/O through OpenSSL in * an unencrypted and an encrypted fashion. There are no ifdefs for one * mode or the other, because using OpenSSL connection abstraction helps * portability so we always use OpenSSL, even when not encryting traffic. * * Encryption is automatically attempted if the certificate files can be * read from configuration items "/broccoli/host_cert" and "/broccoli/ca_cert". * (Note that when Bro peers communicate over an encrypted channel, they * both need to certify themselves). * * Much of the code here is from the O'Reilly book on OpenSSL, by Viega, * Messier, and Chandra. However the problem with their example application * is that they use SSL_read/SSL_write, thus losing the transparency of * the generic BIO_... functions regarding the use of encryption (we do * allow for plaintext communication as well). Since I don't want to write * duplicate code for the encrypted and unencrypted traffic, a socket * BIO is always used and, in the case of encryption, that is simply * appended to an SSL BIO. * * We currently do not support the following: * - ephemeral keying. * - session caching. * * I haven't specifically looked at whether this code supports session * renegotiation. */ /* Broccoli initialization context; defined in bro.c. */ extern const BroCtx *global_ctx; /* The connection creation context. If this context is NULL, * it means we are not using encryption. */ static SSL_CTX *ctx = NULL; #ifdef BRO_DEBUG static void print_errors(void) { if (bro_debug_messages) { D(("OpenSSL error dump:\n")); if (ERR_peek_error() == 0) fprintf(stdout, "--> %s\n", strerror(errno)); else ERR_print_errors_fp(stdout); } } #else #define print_errors() #endif static int verify_cb(int ok, X509_STORE_CTX *store) { char data[256]; int depth, err; X509 *cert; if (ok) return ok; cert = X509_STORE_CTX_get_current_cert(store); depth = X509_STORE_CTX_get_error_depth(store); err = X509_STORE_CTX_get_error(store); D(("Handshake failure: verification problem at depth %i:\n", depth)); X509_NAME_oneline(X509_get_issuer_name(cert), data, 256); D((" issuer = %s\n", data)); X509_NAME_oneline(X509_get_subject_name(cert), data, 256); D((" subject = %s\n", data)); D((" error code %i: %s\n", err, X509_verify_cert_error_string(err))); return ok; } static int prng_init_file(char *file) { int fd, flags, i; uchar buf[1024]; /* Try to seed the PRNG from a file. If things fail, do nothing and rely on * OpenSSL to initialize from /dev/urandom. */ if ( (fd = open(file, O_RDONLY)) < 0) { D(("Could not read from %s, not seeding from it.\n", file)); return FALSE; } if ( (flags = fcntl(fd, F_GETFL, 0)) < 0) { D(("can't obtain socket flags: %s", strerror(errno))); close(fd); return FALSE; } if ( fcntl(fd, F_SETFL, flags|O_NONBLOCK) < 0 ) { D(("can't set fd to non-blocking: %s.", strerror(errno))); close(fd); return FALSE; } /* Now we need to figure out how much entropy the device * can provide. We try to read 1K, and accept if it can * read at least 256 bytes. */ if ( (i = read(fd, buf, 1024)) < 256) { D(("Could only read %i bytes from %s, not enough.\n", i, file)); close(fd); return FALSE; } D(("Seeding PRNG from %s, using %i bytes.\n", file, i)); close(fd); RAND_seed(buf, i); return TRUE; } static void prng_init(void) { static int deja_vu = FALSE; if (deja_vu) return; if (prng_init_file("/dev/random")) { deja_vu = TRUE; return; } if (prng_init_file("/dev/urandom")) { deja_vu = TRUE; return; } D(("*** CAUTION: Unable to initialize random number generator ***\n")); } static int pem_passwd_cb(char *buf, int size, int rwflag, void *pass) { /* Note that if |pass| < size, the remainder in buf will be * zero-padded by strncpy(). */ strncpy(buf, (char *) pass, size); buf[size - 1] = '\0'; return strlen(buf); rwflag = 0; } int __bro_openssl_init(void) { static int deja_vu = FALSE; int use_ssl = FALSE; const char *our_cert, *our_key, *our_pass, *ca_cert; D_ENTER; if (deja_vu) D_RETURN_(TRUE); deja_vu = TRUE; /* I hope these should go before SSL_library_init() -- not even the * O'Reilly book is clear on that. :( --cpk */ if (global_ctx) { if (global_ctx->id_func) CRYPTO_set_id_callback(global_ctx->id_func); if (global_ctx->lock_func) CRYPTO_set_locking_callback(global_ctx->lock_func); if (global_ctx->dl_create_func) CRYPTO_set_dynlock_create_callback(global_ctx->dl_create_func); if (global_ctx->dl_lock_func) CRYPTO_set_dynlock_lock_callback(global_ctx->dl_lock_func); if (global_ctx->dl_free_func) CRYPTO_set_dynlock_destroy_callback(global_ctx->dl_free_func); } SSL_library_init(); prng_init(); #ifdef BRO_DEBUG D(("Loading OpenSSL error strings for debugging\n")); SSL_load_error_strings(); #endif if (__bro_conf_get_int("/broccoli/use_ssl", &use_ssl) && ! use_ssl) { D(("SSL disabled in configuration, not using SSL.\n")); D_RETURN_(TRUE); } our_cert = __bro_conf_get_str("/broccoli/host_cert"); our_key = __bro_conf_get_str("/broccoli/host_key"); if (our_key == NULL) { /* No private key configured; get it from the certificate file */ our_key = our_cert; } if (our_cert == NULL) { if (use_ssl) { D(("SSL requested but host certificate not given -- aborting.\n")); D_RETURN_(FALSE); } else { D(("use_ssl not used and host certificate not given -- not using SSL.\n")); D_RETURN_(TRUE); } } /* At this point we either haven't seen use_ssl but a host_cert, or * we have seen use_ssl and it is set to true. Either way, we attempt * to set up an SSL connection now and abort if this fails in any way. */ if (! (ctx = SSL_CTX_new(SSLv3_method()))) D_RETURN_(FALSE); /* We expect things to be stored in PEM format, which means that we * can store multiple entities in one file. In this case, our own * certificate is expected to be stored along with the private key * in the file pointed to by preference setting /broccoli/certificate. * * See page 121 in O'Reilly's OpenSSL book for details. */ if (SSL_CTX_use_certificate_chain_file(ctx, our_cert) != 1) { D(("Error loading certificate from '%s'.\n", our_cert)); goto error_return; } if ( (our_pass = __bro_conf_get_str("/broccoli/host_pass"))) { D(("Host passphrase given in config file, not prompting for input.\n")); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) our_pass); } if (SSL_CTX_use_PrivateKey_file(ctx, our_key, SSL_FILETYPE_PEM) != 1) { D(("SSL used but error loading private key from '%s' -- aborting.\n", our_key)); goto error_return; } /* We should not need the passphrase, if existant, ever again. * Therefore we erase it from memory now. */ if (our_pass) { our_pass = NULL; __bro_conf_forget_item("/broccoli/host_pass"); } /* For validation purposes, our trusted CA's certificate will * be needed as well: */ if (! (ca_cert = __bro_conf_get_str("/broccoli/ca_cert"))) { D(("SSL used but CA certificate not given -- aborting.")); goto error_return; } if (! SSL_CTX_load_verify_locations(ctx, ca_cert, 0)) { D(("SSL used but CA certificate could not be loaded -- aborting\n")); goto error_return; } /* Check the consistency of the certificate vs. the private key */ if (SSL_CTX_check_private_key(ctx) != 1) { D(("SSL used but private key does not match the certificate -- aborting\n")); goto error_return; } /* Only use real ciphers. */ if (! SSL_CTX_set_cipher_list(ctx, "HIGH")) { D(("SSL used but can't set cipher list -- aborting\n")); goto error_return; } /* We require certificates from all communication peers, regardless of * whether we're the "server" or "client" (these concepts are blurred in our * case anyway). In order to be able to give better error feedback, we * add our own verification filter callback, "verify_cb". */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb); D(("SSL setup successful.\n")); D_RETURN_(TRUE); error_return: SSL_CTX_free(ctx); ctx = NULL; D_RETURN_(FALSE); } int __bro_openssl_rand_bytes(u_char *buf, int num) { if (! buf || num <= 0) return FALSE; /* Make sure PRNG is initialized; has effect only once. */ prng_init(); if (RAND_bytes(buf, num) > 0) return TRUE; RAND_pseudo_bytes(buf, num); return TRUE; } int __bro_openssl_encrypted(void) { return ctx != NULL; } static int try_connect(const char* host_and_port) { int status, sockfd = -1; char* colon; char* tmp; char host[512]; char port[16]; struct addrinfo hints, *res, *res0; D_ENTER; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; if ( ! (tmp = strdup(host_and_port)) ) { D(("Out of memory.\n")); D_RETURN_(-1); } if ( ! (colon = strrchr(tmp, ':')) ) { D(("Invalid host:port string: %s\n", host_and_port)); free(tmp); D_RETURN_(-1); } if ( ! colon[1] ) { D(("Invalid port in host:port string: %s\n", host_and_port)); free(tmp); D_RETURN_(-1); } *colon = '\0'; __bro_util_snprintf(host, sizeof(host), "%s", tmp); __bro_util_snprintf(port, sizeof(port), "%s", colon + 1); free(tmp); D(("Trying to connect to [%s]:%s\n", host, port)); status = getaddrinfo(host, port, &hints, &res0); if ( status != 0 ) { D(("Error in getaddrinfo: %s\n", gai_strerror(status))); D_RETURN_(-1); } for ( res = res0; res; res = res->ai_next ) { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if ( sockfd < 0 ) { D(("socket() failed: %s\n", strerror(errno))); continue; } if ( connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 ) { D(("connect() to %s failed: %s\n", host_and_port, strerror(errno))); close(sockfd); sockfd = -1; continue; } break; } freeaddrinfo(res0); D_RETURN_(sockfd); } static int openssl_connect(BroConn *bc) { int flags, sockfd = -1; BIO *bio = NULL; BIO *ssl_bio = NULL; D_ENTER; if (! bc || ! bc->peer || ! *(bc->peer)) D_RETURN_(FALSE); /* Make sure OpenSSL is initialised -- this has effect only once */ if (! __bro_openssl_init()) D_RETURN_(FALSE); /* Use socket provided by user if BroConn came via bro_conn_new_socket */ if ( bc->socket >= 0 ) { D(("Connection created from externally provided socket.\n")); sockfd = bc->socket; } else sockfd = try_connect(bc->peer); if ( sockfd == -1 ) { D(("Error connecting to %s.\n", bc->peer)); goto err_return; } if ( ! (bio = BIO_new_socket(sockfd, BIO_CLOSE)) ) { D(("Error creating connection BIO from socket.\n")); goto err_return; } if ( (flags = fcntl(sockfd, F_GETFL, 0)) < 0 ) { D(("Error getting socket flags.\n")); goto err_return; } if ( fcntl(sockfd, F_SETFL, flags|O_NONBLOCK) < 0 ) { D(("Error setting socket to non-blocking.\n")); goto err_return; } /* Don't know whether this is needed but it does not hurt either. * It is however not sufficient to just call this; we manually need to * set the socket to non-blocking as done above. */ BIO_set_nbio(bio, 1); /* Add SSL if available */ if ( ctx ) { if ( ! (ssl_bio = BIO_new_ssl(ctx, 1)) ) { D(("Error creating ssl BIO.\n")); goto err_return; } BIO_set_close(ssl_bio, BIO_CLOSE); BIO_push(ssl_bio, bio); bio = ssl_bio; } bc->bio = bio; D(("Connection established successfully.\n")); D_RETURN_(TRUE); err_return: print_errors(); #ifdef BRO_DEBUG if (ctx) D(("--- SSL CONNECTION SETUP FAILED. ---")); else D(("--- CLEARTEXT CONNECTION SETUP FAILED. ---")); #endif if (bio) BIO_free_all(bio); bc->state->rx_dead = bc->state->tx_dead = TRUE; bc->bio = NULL; D_RETURN_(FALSE); } int __bro_openssl_connect(BroConn *bc) { return openssl_connect(bc); } int __bro_openssl_reconnect(BroConn *bc) { return openssl_connect(bc); } void __bro_openssl_shutdown(BroConn *bc) { if (!bc || !bc->bio) return; if (getpid() != bc->id_pid) return; if (bc->state->rx_dead) return; bc->state->rx_dead = bc->state->tx_dead = TRUE; BIO_flush(bc->bio); BIO_free_all(bc->bio); bc->bio = NULL; } int __bro_openssl_read(BroConn *bc, uchar *buf, uint buf_size) { int n; D_ENTER; /* It's important here to use <= for comparison, since, as the * invaluable O'Reilly OpenSSL book reports, "for each of the four * reading and writing functions, a 0 or -1 return value may or may * not necessarily indicate that an error has occurred." This may or * may not necessarily be indicative of the incredible PITA that * OpenSSL is. --cpk */ if ( (n = BIO_read(bc->bio, buf, buf_size)) <= 0) { if (BIO_should_retry(bc->bio)) D_RETURN_(0); __bro_openssl_shutdown(bc); D(("Connection closed, BIO_read() returned %i.\n", n)); print_errors(); D_RETURN_(-1); } D_RETURN_(n); } int __bro_openssl_write(BroConn *bc, uchar *buf, uint buf_size) { int n; void *old_sig; D_ENTER; #ifdef BRO_DEBUG if (bro_debug_messages) { unsigned int i = 0; int last_hex = 0; D(("Sending %u bytes: ", buf_size)); for (i = 0; i < buf_size; i++) { if (buf[i] >= 32 && buf[i] <= 126) { printf("%s%c", last_hex ? " " : "", buf[i]); last_hex = 0; } else { printf(" 0x%.2x", buf[i]); last_hex = 1; } } printf("\n"); } #endif /* We may get a SIGPIPE if we write to a connection whose peer * died. Since we don't know the application context in which * we're running, we temporarily set the SIGPIPE handler to our * own and then set it back to the old one after we wrote. */ old_sig = signal(SIGPIPE, SIG_IGN); n = BIO_write(bc->bio, buf, buf_size); if (n <= 0) { if (BIO_should_retry(bc->bio)) { n = 0; goto error_return; } print_errors(); __bro_openssl_shutdown(bc); D(("Connection closed.\n")); n = -1; } BIO_flush(bc->bio); error_return: if (old_sig != SIG_ERR) signal(SIGPIPE, old_sig); D_RETURN_(n); } broccoli-1.97-minimal/src/bro_id.h0000664002342100234210000000442012523041064016703 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_id_h #define broccoli_id_h #include #include #include #include struct bro_id { BroObject object; BroString name; char scope; char is_export; uint32 is_const; uint32 is_enum_const; uint32 is_type; uint32 offset; char infer_return_type; char weak_ref; BroType *type; BroVal *val; BroAttrs *attrs; }; BroID *__bro_id_new(void); void __bro_id_init(BroID *id); void __bro_id_free(BroID *id); int __bro_id_write(BroID *id, BroConn *bc); int __bro_id_read(BroID *id, BroConn *bc); int __bro_id_clone(BroID *dst, BroID *src); uint32 __bro_id_hash(BroID *obj); int __bro_id_cmp(BroID *obj1, BroID *obj2); #endif broccoli-1.97-minimal/src/bro_attr.h0000664002342100234210000000556012523041064017267 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_attr_h #define broccoli_attr_h #include /* Definitions of attribute type identifiers. * They must match the values of attr_tag in Bro's Attr.h. */ #define BRO_ATTR_OPTIONAL 0 #define BRO_ATTR_DEFAULT 1 #define BRO_ATTR_REDEF 2 #define BRO_ATTR_ROTATE_INTERVAL 3 #define BRO_ATTR_ROTATE_SIZE 4 #define BRO_ATTR_ADD_FUNC 5 #define BRO_ATTR_DEL_FUNC 6 #define BRO_ATTR_EXPIRE_FUNC 7 #define BRO_ATTR_EXPIRE_READ 8 #define BRO_ATTR_EXPIRE_WRITE 9 #define BRO_ATTR_EXPIRE_CREATE 10 #define BRO_ATTR_PERSISTENT 11 #define BRO_ATTR_SYNCHRONIZED 12 #define BRO_ATTR_ENCRYPT 13 #define BRO_ATTR_RAW_OUTPUT 14 #define BRO_ATTR_MERGEABLE 15 #define BRO_ATTR_PRIORITY 16 #define BRO_ATTR_GROUP 17 #define BRO_ATTR_LOG 18 #define BRO_ATTR_ERROR_HANDLER 19 #define BRO_ATTR_TYPE_COLUMN 20 typedef struct bro_expr { } BroExpr; /* NOTE: these attributes do *not* follow the inheritance approach, * unlike the attributes in Bro. This is because they're not currently * using the serialization framework like the rest of the Bro objects, * and all we need for Broccoli purposes is a (non-inherited) simple * way to read and write an attribute. */ typedef struct bro_attr { char tag; BroExpr *expr; } BroAttr; BroAttr *__bro_attr_new(void); BroAttr *__bro_attr_copy(BroAttr *attr); void __bro_attr_free(BroAttr *attr); int __bro_attr_read(BroAttr *attr, BroConn *bc); int __bro_attr_write(BroAttr *attr, BroConn *bc); #endif broccoli-1.97-minimal/src/bro_type.c0000664002342100234210000011230612523041064017266 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include #include /* The virtual implementations of BroSObject's functions are * kept static in this module, and so are the ..._init() methods * not currently needed by other, derived classes. */ static void __bro_type_init(BroType *type); static void __bro_type_free(BroType *type); static int __bro_type_read(BroType *type, BroConn *bc); static int __bro_type_write(BroType *type, BroConn *bc); static int __bro_type_clone(BroType *dst, BroType *src); static uint32 __bro_type_hash(BroType *type); static int __bro_type_cmp(BroType *type1, BroType *type2); static void __bro_type_list_init(BroTypeList *tl); static void __bro_type_list_free(BroTypeList *tl); static int __bro_type_list_read(BroTypeList *tl, BroConn *bc); static int __bro_type_list_write(BroTypeList *tl, BroConn *bc); static int __bro_type_list_clone(BroTypeList *dst, BroTypeList *src); static uint32 __bro_type_list_hash(BroTypeList *tl); static int __bro_type_list_cmp(BroTypeList *tl1, BroTypeList *tl2); static void __bro_record_type_init(BroRecordType *rt); static void __bro_record_type_free(BroRecordType *rt); static int __bro_record_type_read(BroRecordType *rt, BroConn *bc); static int __bro_record_type_write(BroRecordType *rt, BroConn *bc); static int __bro_record_type_clone(BroRecordType *dst, BroRecordType *src); static uint32 __bro_record_type_hash(BroRecordType *rt); static int __bro_record_type_cmp(BroRecordType *rt1, BroRecordType *rt2); static void __bro_index_type_init(BroIndexType *it); static void __bro_index_type_free(BroIndexType *it); static int __bro_index_type_read(BroIndexType *it, BroConn *bc); static int __bro_index_type_write(BroIndexType *it, BroConn *bc); static int __bro_index_type_clone(BroIndexType *dst, BroIndexType *src); static uint32 __bro_index_type_hash(BroIndexType *it); static int __bro_index_type_cmp(BroIndexType *it1, BroIndexType *it2); static void __bro_table_type_init(BroTableType *tt); static void __bro_table_type_free(BroTableType *tt); static int __bro_table_type_read(BroTableType *tt, BroConn *bc); static int __bro_table_type_write(BroTableType *tt, BroConn *bc); static int __bro_table_type_clone(BroTableType *dst, BroTableType *src); static uint32 __bro_table_type_hash(BroTableType *tt); static int __bro_table_type_cmp(BroTableType *tt1, BroTableType *tt2); static void __bro_set_type_init(BroSetType *st); static void __bro_set_type_free(BroSetType *st); static int __bro_set_type_read(BroSetType *st, BroConn *bc); static int __bro_set_type_write(BroSetType *st, BroConn *bc); static int __bro_set_type_clone(BroSetType *dst, BroSetType *src); static uint32 __bro_set_type_hash(BroSetType *st); static int __bro_set_type_cmp(BroSetType *st1, BroSetType *st2); static void __bro_file_type_init(BroFileType *st); static void __bro_file_type_free(BroFileType *ft); static int __bro_file_type_read(BroFileType *ft, BroConn *bc); static int __bro_file_type_write(BroFileType *ft, BroConn *bc); static int __bro_file_type_clone(BroFileType *dst, BroFileType *src); static uint32 __bro_file_type_hash(BroFileType *ft); static int __bro_file_type_cmp(BroFileType *ft1, BroFileType *ft2); static void __bro_enum_type_init(BroEnumType *et); static void __bro_enum_type_free(BroEnumType *et); static int __bro_enum_type_read(BroEnumType *et, BroConn *bc); static int __bro_enum_type_write(BroEnumType *et, BroConn *bc); static int __bro_enum_type_clone(BroEnumType *dst, BroEnumType *src); static uint32 __bro_enum_type_hash(BroEnumType *et); static int __bro_enum_type_cmp(BroEnumType *et1, BroEnumType *et2); static void __bro_vector_type_init(BroVectorType *et); static void __bro_vector_type_free(BroVectorType *et); static int __bro_vector_type_read(BroVectorType *et, BroConn *bc); static int __bro_vector_type_write(BroVectorType *et, BroConn *bc); static int __bro_vector_type_clone(BroVectorType *dst, BroVectorType *src); static uint32 __bro_vector_type_hash(BroVectorType *et); static int __bro_vector_type_cmp(BroVectorType *et1, BroVectorType *et2); BroType * __bro_type_new(void) { BroType *type; D_ENTER; if (! (type = calloc(1, sizeof(BroType)))) D_RETURN_(NULL); __bro_type_init(type); D_RETURN_(type); } BroType * __bro_type_new_of_type(int type_tag, const char *type_name) { BroType *type = NULL; int internal_tag; char is_nbo = 0; D_ENTER; switch (type_tag) { case BRO_TYPE_BOOL: case BRO_TYPE_INT: case BRO_TYPE_ENUM: internal_tag = BRO_INTTYPE_INT; break; case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: internal_tag = BRO_INTTYPE_UNSIGNED; break; case BRO_TYPE_PORT: internal_tag = BRO_INTTYPE_UNSIGNED; is_nbo = 1; break; case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: case BRO_TYPE_INTERVAL: internal_tag = BRO_INTTYPE_DOUBLE; break; case BRO_TYPE_STRING: internal_tag = BRO_INTTYPE_STRING; break; case BRO_TYPE_IPADDR: internal_tag = BRO_INTTYPE_IPADDR; break; case BRO_TYPE_SUBNET: internal_tag = BRO_INTTYPE_SUBNET; break; case BRO_TYPE_PATTERN: case BRO_TYPE_TIMER: case BRO_TYPE_ANY: case BRO_TYPE_UNION: case BRO_TYPE_LIST: case BRO_TYPE_FUNC: case BRO_TYPE_FILE: internal_tag = BRO_INTTYPE_OTHER; break; case BRO_TYPE_TABLE: if (! (type = (BroType *) __bro_table_type_new())) D_RETURN_(NULL); internal_tag = BRO_INTTYPE_OTHER; break; case BRO_TYPE_RECORD: if (! (type = (BroType *) __bro_record_type_new())) D_RETURN_(NULL); internal_tag = BRO_INTTYPE_OTHER; break; case BRO_TYPE_SET: if (! (type = (BroType *) __bro_set_type_new())) D_RETURN_(NULL); internal_tag = BRO_INTTYPE_OTHER; break; case BRO_TYPE_VECTOR: if (! (type = (BroType *) __bro_vector_type_new())) D_RETURN_(NULL); internal_tag = BRO_INTTYPE_OTHER; break; case BRO_TYPE_ERROR: default: internal_tag = BRO_INTTYPE_ERROR; } if (! type) { if (! (type = __bro_type_new())) D_RETURN_(NULL); } type->tag = type_tag; type->internal_tag = internal_tag; type->is_nbo = is_nbo; type->is_complete = TRUE; if (type_name) { type->is_complete = FALSE; bro_string_set(&type->type_name, type_name); } D_RETURN_(type); } static void __bro_type_init(BroType *type) { BroSObject *sobj = (BroSObject *) type; D_ENTER; __bro_object_init((BroObject *) type); sobj->read = (BroSObjectRead) __bro_type_read; sobj->write = (BroSObjectWrite) __bro_type_write; sobj->free = (BroSObjectFree) __bro_type_free; sobj->clone = (BroSObjectClone) __bro_type_clone; sobj->hash = (BroSObjectHash) __bro_type_hash; sobj->cmp = (BroSObjectCmp) __bro_type_cmp; sobj->type_id = SER_TYPE; bro_string_init(&type->type_name); type->is_complete = TRUE; D_RETURN; } static void __bro_type_free(BroType *type) { D_ENTER; bro_string_cleanup(&type->type_name); __bro_object_free((BroObject *) type); D_RETURN; } static int __bro_type_read(BroType *type, BroConn *bc) { D_ENTER; if (! __bro_object_read((BroObject *) type, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &type->tag)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &type->internal_tag)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &type->is_nbo)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &type->is_base_type)) D_RETURN_(FALSE); bro_string_cleanup(&type->type_name); if (! __bro_buf_read_string(bc->rx_buf, &type->type_name)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_type_write(BroType *type, BroConn *bc) { D_ENTER; if (! __bro_object_write((BroObject *) type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, type->tag)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, type->internal_tag)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, type->is_nbo)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, type->is_base_type)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &type->type_name)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_type_clone(BroType *dst, BroType *src) { D_ENTER; if (! __bro_object_clone((BroObject *) dst, (BroObject *) src)) D_RETURN_(FALSE); dst->tag = src->tag; dst->internal_tag = src->internal_tag; dst->is_nbo = src->is_nbo; dst->is_base_type = src->is_base_type; dst->is_complete = src->is_complete; bro_string_set(&dst->type_name, (const char *) bro_string_get_data(&src->type_name)); D_RETURN_(TRUE); } static uint32 __bro_type_hash(BroType *type) { uint32 result; D_ENTER; if (! type) D_RETURN_(0); result = __bro_ht_str_hash(type->type_name.str_val); result ^= (uint32) type->tag; result ^= ((uint32) type->internal_tag) << 8; result ^= ((uint32) type->is_nbo) << 8; result ^= ((uint32) type->is_base_type) << 8; result ^= ((uint32) type->is_complete) << 8; D_RETURN_(result); } static int __bro_type_cmp(BroType *type1, BroType *type2) { int result; D_ENTER; if (! type1 || ! type2) D_RETURN_(FALSE); if (type1->type_name.str_val && type2->type_name.str_val && ! __bro_ht_str_cmp(type1->type_name.str_val, type2->type_name.str_val)) D_RETURN_(FALSE); if (type1->tag != type2->tag || type1->internal_tag != type2->internal_tag || type1->is_nbo != type2->is_nbo || type1->is_base_type != type2->is_base_type || type1->is_complete != type2->is_complete) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroTypeList * __bro_type_list_new(void) { BroTypeList *tl; D_ENTER; if (! (tl = calloc(1, sizeof(BroTypeList)))) D_RETURN_(NULL); __bro_type_list_init(tl); D_RETURN_(tl); } static void __bro_type_list_init(BroTypeList *tl) { BroSObject *sobj = (BroSObject *) tl; D_ENTER; __bro_type_init((BroType *) tl); sobj->read = (BroSObjectRead) __bro_type_list_read; sobj->write = (BroSObjectWrite) __bro_type_list_write; sobj->free = (BroSObjectFree) __bro_type_list_free; sobj->clone = (BroSObjectClone) __bro_type_list_clone; sobj->hash = (BroSObjectHash) __bro_type_list_hash; sobj->cmp = (BroSObjectCmp) __bro_type_list_cmp; sobj->type_id = SER_TYPE_LIST; tl->types = NULL; D_RETURN; } static void __bro_type_list_free(BroTypeList *tl) { D_ENTER; __bro_list_free(tl->types, (BroFunc) __bro_sobject_release); __bro_sobject_release((BroSObject *) tl->pure_type); __bro_type_free((BroType *) tl); D_RETURN; } static int __bro_type_list_read(BroTypeList *tl, BroConn *bc) { char opt; uint32 i; D_ENTER; if (! __bro_type_read((BroType *) tl, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); /* Clean out old optional pure type */ if (tl->pure_type) __bro_sobject_release((BroSObject *) tl->pure_type); if (opt) { if (! (tl->pure_type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); } if (! __bro_buf_read_int(bc->rx_buf, &tl->num_types)) D_RETURN_(FALSE); if (tl->num_types > 0) { for (i = 0; i < tl->num_types; i++) { BroType *type; if (! (type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); tl->types = __bro_list_append(tl->types, type); } } D_RETURN_(TRUE); } static int __bro_type_list_write(BroTypeList *tl, BroConn *bc) { BroList *l; D_ENTER; if (! __bro_type_write((BroType *) tl, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, tl->pure_type ? 1 : 0)) D_RETURN_(FALSE); if (tl->pure_type && ! __bro_sobject_serialize((BroSObject *) tl->pure_type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, tl->num_types)) D_RETURN_(FALSE); for (l = tl->types; l; l = __bro_list_next(l)) { if (! __bro_sobject_serialize((BroSObject *) __bro_list_data(l), bc)) D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_type_list_clone(BroTypeList *dst, BroTypeList *src) { BroList *l; BroType *type; D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); dst->num_types = src->num_types; if (dst->types) __bro_list_free(dst->types, (BroFunc) __bro_sobject_release); dst->types = NULL; for (l = src->types; l; l = __bro_list_next(l)) { BroType *type_copy; type = __bro_list_data(l); if (! (type_copy = (BroType *) __bro_sobject_copy((BroSObject *) type))) D_RETURN_(FALSE); dst->types = __bro_list_append(dst->types, type_copy); } if (src->pure_type && ! (dst->pure_type = (BroType *) __bro_sobject_copy((BroSObject *) src->pure_type))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_type_list_hash(BroTypeList *tl) { uint32 result; BroList *l; D_ENTER; if (! tl) D_RETURN_(0); result = tl->num_types; result ^= __bro_sobject_hash((BroSObject*) tl->pure_type); for (l = tl->types; l; l = __bro_list_next(l)) result ^= __bro_sobject_hash((BroSObject*) __bro_list_data(l)); D_RETURN_(result); } static int __bro_type_list_cmp(BroTypeList *tl1, BroTypeList *tl2) { BroList *l1, *l2; D_ENTER; if (! tl1 || ! tl2) D_RETURN_(FALSE); if (tl1->num_types != tl2->num_types || ! __bro_sobject_cmp((BroSObject*) tl1->pure_type, (BroSObject*) tl2->pure_type)) D_RETURN_(FALSE); for (l1 = tl1->types, l2 = tl2->types; l1 && l2; l1 = __bro_list_next(l1), l2 = __bro_list_next(l2)) { if (! __bro_sobject_cmp((BroSObject*) __bro_list_data(l1), (BroSObject*) __bro_list_data(l2))) D_RETURN_(FALSE); } if (l1 || l2) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroRecordType * __bro_record_type_new(void) { BroRecordType *rt; D_ENTER; if (! (rt = calloc(1, sizeof(BroRecordType)))) D_RETURN_(NULL); __bro_record_type_init(rt); D_RETURN_(rt); } static void __bro_record_type_init(BroRecordType *rt) { BroSObject *sobj = (BroSObject *) rt; D_ENTER; __bro_type_init((BroType *) rt); sobj->read = (BroSObjectRead) __bro_record_type_read; sobj->write = (BroSObjectWrite) __bro_record_type_write; sobj->free = (BroSObjectFree) __bro_record_type_free; sobj->clone = (BroSObjectClone) __bro_record_type_clone; sobj->hash = (BroSObjectHash) __bro_record_type_hash; sobj->cmp = (BroSObjectCmp) __bro_record_type_cmp; sobj->type_id = SER_RECORD_TYPE; D_RETURN; } static void __bro_record_type_free(BroRecordType *rt) { D_ENTER; __bro_list_free(rt->type_decls, (BroFunc) __bro_type_decl_free); __bro_type_free((BroType *) rt); D_RETURN; } void __bro_record_type_add_type(BroRecordType *rt, const char *field, BroType *type) { BroTypeDecl *td; D_ENTER; if (! rt || ! type) D_RETURN; if (! (td = __bro_type_decl_new())) D_RETURN; if (! (td->type = (BroType *) __bro_sobject_copy((BroSObject *) type))) { D(("Cloning of type failed.\n")); __bro_type_decl_free(td); D_RETURN; } if (! bro_string_set(&td->id, field)) { __bro_type_decl_free(td); D_RETURN; } rt->type_decls = __bro_list_append(rt->type_decls, td); rt->num_fields++; rt->num_types++; D_RETURN; } const char * __bro_record_type_get_nth_field(BroRecordType *rt, int num) { BroList *l; if (! rt || num < 0 || (uint) num >= rt->num_fields) return NULL; if( (l = __bro_list_nth(rt->type_decls, num))) { BroTypeDecl *td = __bro_list_data(l); return (const char *) td->id.str_val; } return NULL; } static int __bro_record_type_read(BroRecordType *rt, BroConn *bc) { uint32 i; char opt; D_ENTER; if (! __bro_type_read((BroType *) rt, bc)) D_RETURN_(FALSE); /* Read type declarations */ rt->type_decls = NULL; rt->num_fields = 0; rt->num_types = 0; if (! __bro_buf_read_int(bc->rx_buf, &rt->num_fields)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (! __bro_buf_read_int(bc->rx_buf, &rt->num_types)) D_RETURN_(FALSE); if (rt->num_types > 0) { for (i = 0; i < rt->num_types; i++) { BroTypeDecl *td; if (! (td = __bro_type_decl_new())) D_RETURN_(FALSE); if (! __bro_type_decl_read(td, bc)) { __bro_type_decl_free(td); D_RETURN_(FALSE); } rt->type_decls = __bro_list_append(rt->type_decls, td); } } } D_RETURN_(TRUE); } static int __bro_record_type_write(BroRecordType *rt, BroConn *bc) { BroList *l; D_ENTER; if (! __bro_type_write((BroType *) rt, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, rt->num_fields)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, rt->type_decls ? 1 : 0)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, rt->num_types)) D_RETURN_(FALSE); for (l = rt->type_decls; l; l = __bro_list_next(l)) { BroTypeDecl *td = __bro_list_data(l); if (! __bro_type_decl_write(td, bc)) D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_record_type_clone(BroRecordType *dst, BroRecordType *src) { BroList *l; D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); dst->num_fields = src->num_fields; dst->num_types = src->num_types; for (l = src->type_decls; l; l = __bro_list_next(l)) { BroTypeDecl *td = __bro_list_data(l); BroTypeDecl *td_copy = __bro_type_decl_copy(td); if (! td_copy) D_RETURN_(FALSE); dst->type_decls = __bro_list_append(dst->type_decls, td_copy); } D_RETURN_(TRUE); } static uint32 __bro_record_type_hash(BroRecordType *rt) { uint32 result; BroList *l; D_ENTER; if (! rt) D_RETURN_(0); result = rt->num_fields; result ^= rt->num_types << 16; for (l = rt->type_decls; l; l = __bro_list_next(l)) result ^= __bro_type_decl_hash((BroTypeDecl*) __bro_list_data(l)); D_RETURN_(result); } static int __bro_record_type_cmp(BroRecordType *rt1, BroRecordType *rt2) { BroList *l1, *l2; D_ENTER; if (! rt1 || ! rt2) D_RETURN_(FALSE); if (rt1->num_fields != rt2->num_fields || rt1->num_types != rt2->num_types) D_RETURN_(FALSE); for (l1 = rt1->type_decls, l2 = rt2->type_decls; l1 && l2; l1 = __bro_list_next(l1), l2 = __bro_list_next(l2)) { if (! __bro_type_decl_cmp((BroTypeDecl*) __bro_list_data(l1), (BroTypeDecl*) __bro_list_data(l2))) D_RETURN_(FALSE); } if (l1 || l2) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroIndexType * __bro_index_type_new(void) { BroIndexType *it; D_ENTER; if (! (it = calloc(1, sizeof(BroIndexType)))) D_RETURN_(NULL); __bro_index_type_init(it); D_RETURN_(it); } static void __bro_index_type_init(BroIndexType *it) { BroSObject *sobj = (BroSObject *) it; D_ENTER; __bro_type_init((BroType *) it); sobj->read = (BroSObjectRead) __bro_index_type_read; sobj->write = (BroSObjectWrite) __bro_index_type_write; sobj->free = (BroSObjectFree) __bro_index_type_free; sobj->clone = (BroSObjectClone) __bro_index_type_clone; sobj->hash = (BroSObjectHash) __bro_index_type_hash; sobj->cmp = (BroSObjectCmp) __bro_index_type_cmp; sobj->type_id = SER_INDEX_TYPE; D_RETURN; } static void __bro_index_type_free(BroIndexType *it) { D_ENTER; __bro_sobject_release((BroSObject *) it->indices); __bro_sobject_release((BroSObject *) it->yield_type); __bro_type_free((BroType *) it); D_RETURN; } void __bro_index_type_set_indices(BroIndexType *it, BroTypeList *indices) { BroTypeList *tl; D_ENTER; if (! it || ! indices) D_RETURN; if (! (tl = __bro_type_list_new())) D_RETURN; if (! __bro_type_list_clone(tl, indices)) { __bro_type_list_free(tl); D_RETURN; } it->indices = tl; D_RETURN; } void __bro_index_type_set_yield_type(BroIndexType *it, BroType *yield_type) { D_ENTER; if (! it || ! yield_type) D_RETURN; if (! (it->yield_type = (BroType *) __bro_sobject_copy((BroSObject *) yield_type))) D_RETURN; D_RETURN; } static int __bro_index_type_read(BroIndexType *it, BroConn *bc) { char opt; D_ENTER; if (! __bro_type_read((BroType *) it, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (! (it->yield_type = (BroType *) __bro_sobject_unserialize(SER_TYPE, bc))) D_RETURN_(FALSE); } if (! (it->indices = (BroTypeList *) __bro_sobject_unserialize(SER_TYPE_LIST, bc))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_index_type_write(BroIndexType *it, BroConn *bc) { D_ENTER; if (! __bro_type_write((BroType *) it, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, it->yield_type ? 1 : 0)) D_RETURN_(FALSE); if (it->yield_type && ! __bro_sobject_serialize((BroSObject *) it->yield_type, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) it->indices, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_index_type_clone(BroIndexType *dst, BroIndexType *src) { D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); if (src->yield_type && ! (dst->yield_type = (BroType *) __bro_sobject_copy((BroSObject *) src->yield_type))) D_RETURN_(FALSE); if (! (dst->indices = (BroTypeList *) __bro_sobject_copy((BroSObject *) src->indices))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_index_type_hash(BroIndexType *it) { uint32 result; D_ENTER; if (! it) D_RETURN_(0); result = __bro_type_list_hash(it->indices); result ^= __bro_sobject_hash((BroSObject*) it->yield_type); D_RETURN_(result); } static int __bro_index_type_cmp(BroIndexType *it1, BroIndexType *it2) { D_ENTER; if (! it1 || ! it2) D_RETURN_(FALSE); if (! __bro_type_list_cmp(it1->indices, it2->indices) || ! __bro_sobject_cmp((BroSObject*) it1->yield_type, (BroSObject*) it2->yield_type)) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroTableType * __bro_table_type_new(void) { BroTableType *tt; D_ENTER; if (! (tt = calloc(1, sizeof(BroTableType)))) D_RETURN_(NULL); __bro_table_type_init(tt); D_RETURN_(tt); } static void __bro_table_type_init(BroTableType *tt) { BroSObject *sobj = (BroSObject *) tt; D_ENTER; __bro_index_type_init((BroIndexType *) tt); sobj->read = (BroSObjectRead) __bro_table_type_read; sobj->write = (BroSObjectWrite) __bro_table_type_write; sobj->free = (BroSObjectFree) __bro_table_type_free; sobj->clone = (BroSObjectClone) __bro_table_type_clone; sobj->hash = (BroSObjectHash) __bro_table_type_hash; sobj->cmp = (BroSObjectCmp) __bro_table_type_cmp; sobj->type_id = SER_TABLE_TYPE; D_RETURN; } static void __bro_table_type_free(BroTableType *tt) { D_ENTER; __bro_index_type_free((BroIndexType *) tt); D_RETURN; } static int __bro_table_type_read(BroTableType *tt, BroConn *bc) { D_ENTER; if (! __bro_index_type_read((BroIndexType *) tt, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_table_type_write(BroTableType *tt, BroConn *bc) { D_ENTER; if (! __bro_index_type_write((BroIndexType *) tt, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_table_type_clone(BroTableType *dst, BroTableType *src) { D_ENTER; if (! __bro_index_type_clone((BroIndexType *) dst, (BroIndexType *) src)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_table_type_hash(BroTableType *tt) { uint32 result; D_ENTER; result = __bro_index_type_hash((BroIndexType*) tt); D_RETURN_(result); } static int __bro_table_type_cmp(BroTableType *tt1, BroTableType *tt2) { D_ENTER; if (! tt1 || ! tt2) D_RETURN_(FALSE); D_RETURN_(__bro_index_type_cmp((BroIndexType*) tt1, (BroIndexType*) tt2)); } BroSetType * __bro_set_type_new(void) { BroSetType *st; D_ENTER; if (! (st = calloc(1, sizeof(BroSetType)))) D_RETURN_(NULL); __bro_set_type_init(st); D_RETURN_(st); } static void __bro_set_type_init(BroSetType *st) { BroSObject *sobj = (BroSObject *) st; D_ENTER; __bro_table_type_init((BroTableType *) st); sobj->read = (BroSObjectRead) __bro_set_type_read; sobj->write = (BroSObjectWrite) __bro_set_type_write; sobj->free = (BroSObjectFree) __bro_set_type_free; sobj->clone = (BroSObjectClone) __bro_set_type_clone; sobj->hash = (BroSObjectHash) __bro_set_type_hash; sobj->cmp = (BroSObjectCmp) __bro_set_type_cmp; sobj->type_id = SER_SET_TYPE; D_RETURN; } static void __bro_set_type_free(BroSetType *st) { D_ENTER; __bro_table_type_free((BroTableType *) st); D_RETURN; } static int __bro_set_type_read(BroSetType *st, BroConn *bc) { char opt; D_ENTER; if (! __bro_table_type_read((BroTableType *) st, bc)) D_RETURN_(FALSE); /* To allow unambiguous differentiation between tables and sets, * we set the type tag to set here, in divergence of Bro's * internal procedure. */ ((BroType*) st)->tag = BRO_TYPE_SET; if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { D(("Error: expressions are not yet supported. Sorry.\n")); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_set_type_write(BroSetType *st, BroConn *bc) { int ret; D_ENTER; /* Compatibility hack for Bro: its type tags don't differentiate * between sets and tables (they always indicate table types), so * we must ensure here that we do appear as a table type. */ ((BroType*) st)->tag = BRO_TYPE_TABLE; ret = __bro_table_type_write((BroTableType *) st, bc); ((BroType*) st)->tag = BRO_TYPE_SET; if (! ret) D_RETURN_(FALSE); /* We never send expressions. */ if (! __bro_buf_write_char(bc->tx_buf, FALSE)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_set_type_clone(BroSetType *dst, BroSetType *src) { D_ENTER; if (! __bro_table_type_clone((BroTableType *) dst, (BroTableType *) src)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_set_type_hash(BroSetType *st) { uint32 result; D_ENTER; result = __bro_table_type_hash((BroTableType*) st); D_RETURN_(result); } static int __bro_set_type_cmp(BroSetType *st1, BroSetType *st2) { int result; D_ENTER; if (! st1 || ! st2) D_RETURN_(FALSE); result = __bro_table_type_cmp((BroTableType*) st1, (BroTableType*) st2);; D_RETURN_(result); } BroFileType* __bro_file_type_new(void) { BroFileType *ft; D_ENTER; if (! (ft = calloc(1, sizeof(BroFileType)))) D_RETURN_(NULL); __bro_file_type_init(ft); D_RETURN_(ft); } static void __bro_file_type_init(BroFileType *ft) { BroSObject *sobj = (BroSObject *) ft; D_ENTER; __bro_type_init((BroType *) ft); sobj->read = (BroSObjectRead) __bro_file_type_read; sobj->write = (BroSObjectWrite) __bro_file_type_write; sobj->free = (BroSObjectFree) __bro_file_type_free; sobj->clone = (BroSObjectClone) __bro_file_type_clone; sobj->hash = (BroSObjectHash) __bro_file_type_hash; sobj->cmp = (BroSObjectCmp) __bro_file_type_cmp; sobj->type_id = SER_FILE_TYPE; D_RETURN; } static void __bro_file_type_free(BroFileType *ft) { D_ENTER; __bro_sobject_release((BroSObject *) ft->yield); __bro_type_free((BroType *) ft); D_RETURN; } static int __bro_file_type_read(BroFileType *ft, BroConn *bc) { int result; D_ENTER; if (! __bro_type_read((BroType *) ft, bc)) D_RETURN_(FALSE); ft->yield = (BroType*) __bro_sobject_unserialize(SER_TYPE, bc); result = ft->yield != 0; D_RETURN_(result); } static int __bro_file_type_write(BroFileType *ft, BroConn *bc) { D_ENTER; if (! __bro_type_write((BroType *) ft, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject*) ft->yield, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_file_type_clone(BroFileType *dst, BroFileType *src) { D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); dst->yield = __bro_type_new(); if (! __bro_type_clone(dst->yield, src->yield)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_file_type_hash(BroFileType *ft) { uint32 result; D_ENTER; result = __bro_type_hash((BroType*) ft); result ^= __bro_type_hash(ft->yield); D_RETURN_(result); } static int __bro_file_type_cmp(BroFileType *ft1, BroFileType *ft2) { int result; D_ENTER; if (! __bro_type_cmp((BroType*) ft1, (BroType*) ft2)) D_RETURN_(FALSE); result = __bro_type_cmp(ft1->yield, ft2->yield); D_RETURN_(result); } BroEnumType* __bro_enum_type_new(void) { BroEnumType *et; D_ENTER; if (! (et = calloc(1, sizeof(BroEnumType)))) D_RETURN_(NULL); __bro_enum_type_init(et); D_RETURN_(et); } static void __bro_enum_type_init(BroEnumType *et) { BroSObject *sobj = (BroSObject *) et; D_ENTER; __bro_type_init((BroType *) et); sobj->read = (BroSObjectRead) __bro_enum_type_read; sobj->write = (BroSObjectWrite) __bro_enum_type_write; sobj->free = (BroSObjectFree) __bro_enum_type_free; sobj->clone = (BroSObjectClone) __bro_enum_type_clone; sobj->hash = (BroSObjectHash) __bro_enum_type_hash; sobj->cmp = (BroSObjectCmp) __bro_enum_type_cmp; sobj->type_id = SER_ENUM_TYPE; /* A hashtable mapping enum entry name strings to their numeric * value. */ et->names = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, __bro_ht_mem_free, FALSE); D_RETURN; } static void __bro_enum_type_free(BroEnumType *st) { D_ENTER; __bro_ht_free(st->names); __bro_type_free((BroType *) st); D_RETURN; } static int __bro_enum_type_read(BroEnumType *st, BroConn *bc) { uint32 len; char dummy; D_ENTER; if (! __bro_type_read((BroType *) st, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_int64(bc->rx_buf, &st->counter)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &len)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &dummy)) D_RETURN_(FALSE); while (len--) { BroString name; uint64 *val = (uint64*) calloc(1, sizeof(uint64)); if (! __bro_buf_read_string(bc->rx_buf, &name) || ! __bro_buf_read_int64(bc->rx_buf, val)) { free(val); D_RETURN_(FALSE); } __bro_ht_add(st->names, (void*) name.str_val, (void*) val); } D_RETURN_(TRUE); } static int __bro_enum_type_write_item(void *key, void *data, void *user_data) { BroEnumType *st; BroConn *bc; BroString name; uint64 val = *((uint64*) data); D_ENTER; st = (BroEnumType*) user_data; bc = (BroConn*) __bro_sobject_data_get((BroSObject*) st, "__bro_enum_type_write"); bro_string_set(&name, (char*) key); if (! __bro_buf_write_string(bc->tx_buf, &name)) { bro_string_cleanup(&name); D_RETURN_(FALSE); } bro_string_cleanup(&name); if (! __bro_buf_write_int64(bc->tx_buf, val)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_enum_type_write(BroEnumType *st, BroConn *bc) { D_ENTER; if (! __bro_type_write((BroType *) st, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int64(bc->tx_buf, st->counter)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, __bro_ht_get_size(st->names))) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, 0)) D_RETURN_(FALSE); /* We need both this object instance and the connection for context in the iteration callback, so we temporarily add the conn handle to the object's data store. */ __bro_sobject_data_set((BroSObject*) st, "__bro_enum_type_write", bc); __bro_ht_foreach(st->names, __bro_enum_type_write_item, (void*) st); __bro_sobject_data_del((BroSObject*) st, "__bro_enum_type_write"); D_RETURN_(TRUE); } static int __bro_enum_type_clone_item(void *key, void *data, void *user_data) { BroEnumType *dst; D_ENTER; dst = (BroEnumType*) user_data; __bro_ht_add(dst->names, key, data); D_RETURN_(TRUE); } static int __bro_enum_type_clone(BroEnumType *dst, BroEnumType *src) { D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); dst->counter = src->counter; __bro_ht_foreach(src->names, __bro_enum_type_clone_item, (void*) dst); D_RETURN_(TRUE); } static int __bro_enum_type_hash_item(void *key, void *data, void *user_data) { BroEnumType *et; BroString name; uint64 val = *((uint64*) data); uint32 result; D_ENTER; et = (BroEnumType*) user_data; result = (uint32)(uintptr_t) __bro_sobject_data_get((BroSObject*) et, "__bro_enum_type_hash"); bro_string_set(&name, (char*) key); result ^= __bro_ht_str_hash(name.str_val); result ^= (uint32) (val >> 32); result ^= (uint32) (val); __bro_sobject_data_set((BroSObject*) et, "__bro_enum_type_hash", (void*)(uintptr_t) result); bro_string_cleanup(&name); D_RETURN_(TRUE); } static uint32 __bro_enum_type_hash(BroEnumType *et) { uint32 result; D_ENTER; if (! et) D_RETURN_(0); __bro_sobject_data_set((BroSObject*) et, "__bro_enum_type_hash", (void*)(uintptr_t) et->counter); __bro_ht_foreach(et->names, __bro_enum_type_hash_item, (void*) et); result = (uint32)(uintptr_t) __bro_sobject_data_del((BroSObject*) et, "__bro_enum_type_hash"); D_RETURN_(result); } static int __bro_enum_type_cmp(BroEnumType *et1, BroEnumType *et2) { int result; D_ENTER; if (! et1 || ! et2) D_RETURN_(FALSE); if (et1->counter != et2->counter) D_RETURN_(FALSE); result = __bro_enum_type_hash(et1) == __bro_enum_type_hash(et2); D_RETURN_(result); } BroVectorType* __bro_vector_type_new(void) { BroVectorType *vt; D_ENTER; if (! (vt = calloc(1, sizeof(BroVectorType)))) D_RETURN_(NULL); __bro_vector_type_init(vt); D_RETURN_(vt); } static void __bro_vector_type_init(BroVectorType *vt) { BroSObject *sobj = (BroSObject *) vt; D_ENTER; __bro_type_init((BroType *) vt); sobj->read = (BroSObjectRead) __bro_vector_type_read; sobj->write = (BroSObjectWrite) __bro_vector_type_write; sobj->free = (BroSObjectFree) __bro_vector_type_free; sobj->clone = (BroSObjectClone) __bro_vector_type_clone; sobj->hash = (BroSObjectHash) __bro_vector_type_hash; sobj->cmp = (BroSObjectCmp) __bro_vector_type_cmp; sobj->type_id = SER_VECTOR_TYPE; D_RETURN; } static void __bro_vector_type_free(BroVectorType *vt) { D_ENTER; __bro_sobject_release((BroSObject *) vt->yield); __bro_type_free((BroType *) vt); D_RETURN; } static int __bro_vector_type_read(BroVectorType *vt, BroConn *bc) { int result; D_ENTER; if (! __bro_type_read((BroType *) vt, bc)) D_RETURN_(FALSE); vt->yield = (BroType*) __bro_sobject_unserialize(SER_TYPE, bc); result = vt->yield != 0; D_RETURN_(result); } static int __bro_vector_type_write(BroVectorType *vt, BroConn *bc) { D_ENTER; if (! __bro_type_write((BroType *) vt, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject*) vt->yield, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_vector_type_clone(BroVectorType *dst, BroVectorType *src) { D_ENTER; if (! __bro_type_clone((BroType *) dst, (BroType *) src)) D_RETURN_(FALSE); dst->yield = __bro_type_new(); if (! __bro_type_clone(dst->yield, src->yield)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_vector_type_hash(BroVectorType *vt) { uint32 result; D_ENTER; result = __bro_type_hash((BroType*) vt); result ^= __bro_type_hash(vt->yield); D_RETURN_(result); } static int __bro_vector_type_cmp(BroVectorType *vt1, BroVectorType *vt2) { int result; D_ENTER; if (! __bro_type_cmp((BroType*) vt1, (BroType*) vt2)) D_RETURN_(FALSE); result = __bro_type_cmp(vt1->yield, vt2->yield); D_RETURN_(result); } broccoli-1.97-minimal/src/bro_buf.c0000664002342100234210000002536012523041064017064 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #define BRO_BUF_DEFAULT 4096 #ifdef BRO_DEBUG /* Use this to get detailed output of what is read -- * useful for debugging serialization format bugs. */ #define DEBUG_READS #endif #ifndef DEBUG_READS # define D(x) #endif BroBuf * __bro_buf_new(void) { BroBuf *buf; if (! (buf = calloc(1, sizeof(BroBuf)))) { D(("Unable to allocate memory in bro_buf_new.\n")); return NULL; } __bro_buf_init(buf); buf->may_grow = TRUE; return buf; } BroBuf * __bro_buf_new_mem(u_char *mem, int mem_size) { BroBuf *buf; if (! mem) { D(("Input error.\n")); return NULL; } if ((size_t) mem_size < sizeof(BroBuf) + BRO_BUF_DEFAULT) { D(("Given memory chunk of size %i is not big enough, need at least %i\n", mem_size, sizeof(BroBuf) + BRO_BUF_DEFAULT)); return NULL; } buf = (BroBuf *) mem; memset(buf, 0, sizeof(BroBuf)); buf->buf = mem + sizeof(BroBuf); buf->buf_len = mem_size - sizeof(BroBuf); buf->may_grow = FALSE; return buf; } void __bro_buf_free(BroBuf *buf) { if (! buf) return; __bro_buf_cleanup(buf); free(buf); } void __bro_buf_init(BroBuf *buf) { D_ENTER; if (!buf) D_RETURN; memset(buf, 0, sizeof(BroBuf)); buf->buf = calloc(1, BRO_BUF_DEFAULT); if (buf->buf == NULL) { D(("Unable to allocate memory in bro_buf_init.\n")); D_RETURN; } buf->buf_len = BRO_BUF_DEFAULT; D_RETURN; } void __bro_buf_cleanup(BroBuf *buf) { D_ENTER; if (!buf) D_RETURN; if (buf->buf) free(buf->buf); memset(buf, 0, sizeof(BroBuf)); D_RETURN; } int __bro_buf_append(BroBuf *buf, void *data, int data_len) { if (!buf) return FALSE; if (data_len == 0) return TRUE; if (buf->buf_off + data_len >= buf->buf_len) { uchar *new_buf; if (! buf->may_grow) { D(("Cannot expand this buffer, sorry.\n")); return FALSE; } buf->buf_len += MAX(BRO_BUF_DEFAULT, data_len); D(("Reallocating buffer\n")); if (! (new_buf = realloc(buf->buf, sizeof(uchar) * buf->buf_len))) { D(("Realloc'ing buffer failed.\n")); return FALSE; } buf->buf = new_buf; } memcpy(buf->buf + buf->buf_off, data, data_len); buf->buf_off += data_len; return TRUE; } void __bro_buf_consume(BroBuf *buf) { if (!buf || buf->buf_ptr == 0) return; D(("Consuming %i bytes in buffer.\n", buf->buf_ptr)); memmove(buf->buf, buf->buf + buf->buf_ptr, buf->buf_len - buf->buf_ptr); buf->buf_off -= buf->buf_ptr; buf->buf_ptr = 0; } void __bro_buf_reset(BroBuf *buf) { if (! buf) return; buf->buf_off = buf->buf_ptr = 0; } uchar * __bro_buf_get(BroBuf *buf) { if (!buf) return NULL; return buf->buf; } uchar * __bro_buf_get_end(BroBuf *buf) { if (!buf) return NULL; return (buf->buf + buf->buf_off); } uint __bro_buf_get_size(BroBuf *buf) { if (!buf) return 0; return buf->buf_len; } uint __bro_buf_get_used_size(BroBuf *buf) { if (!buf) return 0; return buf->buf_off; } uchar * __bro_buf_ptr_get(BroBuf *buf) { if (!buf) return NULL; return (buf->buf + buf->buf_ptr); } uint32 __bro_buf_ptr_tell(BroBuf *buf) { if (!buf) return 0; return buf->buf_ptr; } int __bro_buf_ptr_seek(BroBuf *buf, int offset, int whence) { if (!buf) return FALSE; switch (whence) { case SEEK_SET: if (offset >= 0 && (uint32) offset <= buf->buf_off) { buf->buf_ptr = offset; return TRUE; } break; case SEEK_CUR: if ((int) buf->buf_ptr + offset >= 0 && buf->buf_ptr + offset <= buf->buf_off) { buf->buf_ptr += offset; return TRUE; } break; case SEEK_END: if ((int) buf->buf_off + offset >= 0 && buf->buf_off + offset <= buf->buf_off) { buf->buf_ptr = buf->buf_off + offset; return TRUE; } break; default: break; } return FALSE; } int __bro_buf_ptr_check(BroBuf *buf, int size) { if (!buf || size < 0) return FALSE; if (buf->buf_ptr + size > buf->buf_off) { D(("Checking for %i bytes available, but have only %i\n", size, buf->buf_off - buf->buf_ptr)); return FALSE; } return TRUE; } int __bro_buf_ptr_read(BroBuf *buf, void *data, int size) { if (size == 0) return TRUE; if (!buf || !data) return FALSE; if (! __bro_buf_ptr_check(buf, size)) return FALSE; memcpy(data, buf->buf + buf->buf_ptr, size); buf->buf_ptr += size; return TRUE; } int __bro_buf_ptr_write(BroBuf *buf, const void *data, int size) { if (! buf || size < 0) return FALSE; if (size == 0) return TRUE; if (! data) { D(("Input error -- data length is %i but no data given.\n", size)); return FALSE; } if (buf->buf_ptr + size >= buf->buf_len) { /* Check how much the requested amount is bigger than * what we have, and add some extra buffering on top of it. */ uchar *new_buf; int inc = size - (buf->buf_off - buf->buf_ptr); if (! buf->may_grow) { D(("Cannot expand this buffer, sorry.\n")); return FALSE; } D(("Reallocating buffer\n")); if (! (new_buf = realloc(buf->buf, buf->buf_len + inc + BRO_BUF_DEFAULT))) { D(("Realloc'ing buffer failed.\n")); return FALSE; } buf->buf_len += inc + BRO_BUF_DEFAULT; buf->buf = new_buf; } memcpy(buf->buf + buf->buf_ptr, data, size); buf->buf_ptr += size; if (buf->buf_off < buf->buf_ptr) buf->buf_off = buf->buf_ptr; return TRUE; } /* I/O API below ---------------------------------------------------- */ int __bro_buf_read_data(BroBuf *buf, void *dest, int size) { return __bro_buf_ptr_read(buf, dest, size); } int __bro_buf_read_char(BroBuf *buf, char *val) { int result; result = __bro_buf_ptr_read(buf, val, sizeof(char)); D(("Read char: %i/0x%02x\n", *val, *val)); return result; } int __bro_buf_read_string(BroBuf *buf, BroString *val) { if (!buf || !val) return FALSE; bro_string_init(val); if (! __bro_buf_read_int(buf, &val->str_len)) return FALSE; /* We create space for the string's length plus one extra byte that * we use as the string terminator so things work with normal C strings. */ if (! (val->str_val = malloc(val->str_len + 1))) { D(("Unable to allocate memory in bro_buf_read_string.\n")); return FALSE; } if (val->str_len > 0) { if (! (__bro_buf_ptr_read(buf, val->str_val, val->str_len))) { free(val->str_val); return FALSE; } } /* Terminate the string. */ val->str_val[val->str_len] = '\0'; D(("Read string: '%s'\n", val->str_val)); return TRUE; } int __bro_buf_read_double(BroBuf *buf, double *d) { if (! buf || ! d) return FALSE; if (! __bro_buf_ptr_read(buf, d, sizeof(double))) return FALSE; *d = __bro_util_ntohd(*d); D(("Read double: %f\n", *d)); return TRUE; } int __bro_buf_read_int(BroBuf *buf, uint32 *i) { if (! __bro_buf_ptr_read(buf, i, sizeof(uint32))) return FALSE; *i = ntohl(*i); D(("Read int: %i/0x%08x\n", *i, *i)); return TRUE; } int __bro_buf_read_int64(BroBuf *buf, uint64 *i) { if (! __bro_buf_ptr_read(buf, i, sizeof(uint64))) return FALSE; *i = __bro_util_ntohll(*i); D(("Read int: %llu/0x%016llx\n", *i, *i)); return TRUE; } int __bro_buf_read_short(BroBuf *buf, uint16 *i) { if (! __bro_buf_ptr_read(buf, i, sizeof(uint16))) return FALSE; *i = ntohs(*i); D(("Read short: %i/0x%04x\n", *i, *i)); return TRUE; } int __bro_buf_write_data(BroBuf *buf, const void *data, int size) { return __bro_buf_ptr_write(buf, data, size); } int __bro_buf_write_char(BroBuf *buf, char val) { int result; result = __bro_buf_ptr_write(buf, &val, sizeof(char)); D(("Wrote char: %i/0x%02x\n", val, val)); return result; } int __bro_buf_write_string(BroBuf *buf, BroString *val) { int result; BroString tmp_val; if (! buf) return FALSE; if (! val) { tmp_val.str_val = (uchar*) ""; tmp_val.str_len = 0; val = &tmp_val; } if (! (__bro_buf_write_int(buf, val->str_len))) return FALSE; result = __bro_buf_write_data(buf, val->str_val, val->str_len); D(("Wrote string: '%s'\n", val->str_val)); return result; } int __bro_buf_write_double(BroBuf *buf, double d) { int result; double d_tmp; if (! buf) return FALSE; d_tmp = __bro_util_htond(d); result = __bro_buf_ptr_write(buf, &d_tmp, sizeof(double)); D(("Wrote double: %f\n", d)); return result; } int __bro_buf_write_int(BroBuf *buf, uint32 i) { int result; uint32 i_tmp; if (! buf) return FALSE; i_tmp = htonl(i); result = __bro_buf_write_data(buf, &i_tmp, sizeof(uint32)); D(("Wrote int: %i/0x%08x\n", i, i)); return result; } int __bro_buf_write_int64(BroBuf *buf, uint64 i) { int result; uint64 i_tmp; if (! buf) return FALSE; i_tmp = __bro_util_htonll(i); result = __bro_buf_write_data(buf, &i_tmp, sizeof(uint64)); D(("Wrote int64: %llu/0x%016llx\n", i, i)); return result; } int __bro_buf_write_short(BroBuf *buf, uint16 i) { int result; uint16 i_tmp; if (! buf) return FALSE; i_tmp = htons(i); result =__bro_buf_write_data(buf, &i_tmp, sizeof(uint16)); D(("Wrote short: %i/0x%04x\n", i, i)); return result; } broccoli-1.97-minimal/src/bro_packet.c0000664002342100234210000001170712523041064017557 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include static int packet_get_link_header_size(int dl) { switch (dl) { case DLT_NULL: return 4; case DLT_EN10MB: return 14; case DLT_FDDI: return 13 + 8; #ifdef LINUX_HOST case DLT_LINUX_SLL: return 16; #endif case DLT_RAW: return 0; } D(("WARNING: unknown DLT type %i encountered.\n", dl)); return -1; } BroPacket * __bro_packet_unserialize(BroConn *bc) { BroPacket *packet; if (! (packet = calloc(1, sizeof(BroPacket)))) return NULL; if (! __bro_packet_read(packet, bc)) { bro_packet_free(packet); return NULL; } return packet; } int __bro_packet_serialize(BroPacket *packet, BroConn *bc) { D_ENTER; /* Prepare the beginning of a serialized packet. */ if (! __bro_buf_write_char(bc->tx_buf, 'p')) D_RETURN_(FALSE); if (! __bro_packet_write(packet, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_packet_read(BroPacket *packet, BroConn *bc) { BroString packet_data; BroString packet_tag; uint32 tv_sec, tv_usec, len, pcap_link_type; D_ENTER; if (! packet || ! bc) D_RETURN_(FALSE); packet->pkt_link_type = bc->pcap_link_type; packet->pkt_hdr_size = packet_get_link_header_size(bc->pcap_link_type); if (! __bro_buf_read_int(bc->rx_buf, &tv_sec)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &tv_usec)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &len)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &pcap_link_type)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &packet_tag)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &packet_data)) D_RETURN_(FALSE); packet->pkt_pcap_hdr.ts.tv_sec = tv_sec; packet->pkt_pcap_hdr.ts.tv_usec = tv_usec; packet->pkt_pcap_hdr.len = len; packet->pkt_pcap_hdr.caplen = packet_data.str_len; packet->pkt_link_type = pcap_link_type; packet->pkt_data = (const u_char *) packet_data.str_val; packet->pkt_tag = (const char *) packet_tag.str_val; packet->pkt_time = bro_util_current_time(); D_RETURN_(TRUE); } int __bro_packet_write(BroPacket *packet, BroConn *bc) { BroString packet_data; BroString packet_tag; D_ENTER; if (! packet || ! bc) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, (uint32)packet->pkt_pcap_hdr.ts.tv_sec)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, (uint32)packet->pkt_pcap_hdr.ts.tv_usec)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, (uint32)packet->pkt_pcap_hdr.len)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, (uint32)bc->pcap_link_type)) D_RETURN_(FALSE); bro_string_init(&packet_tag); packet_tag.str_len = strlen(packet->pkt_tag); packet_tag.str_val = (u_char *) packet->pkt_tag; if (! __bro_buf_write_string(bc->tx_buf, &packet_tag)) D_RETURN_(FALSE); bro_string_init(&packet_data); packet_data.str_len = packet->pkt_pcap_hdr.caplen; packet_data.str_val = (u_char *) packet->pkt_data; if (! __bro_buf_write_string(bc->tx_buf, &packet_data)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_packet_clone(BroPacket *dst, const BroPacket *src) { D_ENTER; *dst = *src; if (! (dst->pkt_tag = strdup(src->pkt_tag))) D_RETURN_(FALSE); if (! (dst->pkt_data = malloc(src->pkt_pcap_hdr.caplen))) D_RETURN_(FALSE); memcpy((u_char *) dst->pkt_data, src->pkt_data, src->pkt_pcap_hdr.caplen); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_val.h0000664002342100234210000001122712523041064017074 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_val_h #define broccoli_val_h #include #include #include #include #include typedef void *(* BroValAccessor) (BroVal *val); struct bro_val { BroObject object; /* A class method for accessing the data contained by * a val: */ BroValAccessor get_data; /* The full type object of this val -- this also yields * what member of the union is used below (unless we're * inside a derived type and store our data elsewhere). * If val_type is NULL, it means we're dealing with an * unassigned val. */ BroType *val_type; union { char char_val; uint32 int_val; uint64 int64_val; double double_val; BroPort port_val; BroString str_val; BroAddr addr_val; BroSubnet subnet_val; } val; #define val_char val.char_val #define val_int val.int_val #define val_int64 val.int64_val #define val_double val.double_val #define val_port val.port_val #define val_str val.str_val #define val_strlen val.str_val.str_len #define val_addr val.addr_val #define val_subnet val.subnet_val }; struct bro_list_val { BroVal val; char type_tag; int len; BroList *list; }; struct bro_mutable_val { BroVal val; BroID *id; char props; }; #define BRO_VAL_PROP_PERS 0x01 #define BRO_VAL_PROP_SYNC 0x02 struct bro_record_val { BroMutableVal mutable; /* We don't use the full record val when interacting * with the user, but only what's really necessary. */ BroRecord *rec; }; struct bro_table_val { BroMutableVal mutable; BroTableType *table_type; BroAttrs *attrs; BroTable *table; }; struct bro_vector_val { BroMutableVal mutable; BroVector *vec; }; BroVal *__bro_val_new(void); BroVal *__bro_val_new_of_type(int type, const char *type_name); int __bro_val_assign(BroVal *val, const void *data); /* Returns a pointer to the val's data depending on its type. * Type is returned through *type if provided. */ int __bro_val_get_data(BroVal *val, int *type, void **data); int __bro_val_get_type_num(const BroVal *val); BroListVal *__bro_list_val_new(void); /* Append a val to the list. This does not duplicate, so adopts the * given val. */ void __bro_list_val_append(BroListVal *lv, BroVal *val); /* Removes the first value from the list and returns it. */ BroVal *__bro_list_val_pop_front(BroListVal *lv); /* Only returns the first value from the list. */ BroVal *__bro_list_val_get_front(BroListVal *lv); int __bro_list_val_get_length(BroListVal *lv); BroMutableVal *__bro_mutable_val_new(void); BroRecordVal *__bro_record_val_new(void); BroTableVal *__bro_table_val_new(void); int __bro_table_val_has_atomic_key(BroTableVal *tv); BroVectorVal *__bro_vector_val_new(void); #endif broccoli-1.97-minimal/src/bro_vector.h0000664002342100234210000000427412523041064017620 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_vector_h #define broccoli_vector_h #include #include /* Typedef is in broccoli.h because the users need to know it -- we keep * it opaque for them though by defining it here. */ struct bro_vector { BroVal **vector; int length; }; BroVector *__bro_vector_new(void); void __bro_vector_free(BroVector *rec); BroVector *__bro_vector_copy(BroVector *rec); int __bro_vector_get_length(BroVector *rec); /* Appends the given val at the end of the vector and adopts ownership, * i.e, the value is not duplicated internally. */ int __bro_vector_add_val(BroVector *vec, BroVal *val); BroVal *__bro_vector_get_nth_val(BroVector *rec, int num); int __bro_vector_set_nth_val(BroVector *rec, int num, BroVal *val); uint32 __bro_vector_hash(BroVector *rec); int __bro_vector_cmp(BroVector *rec1, BroVector *rec2); #endif broccoli-1.97-minimal/src/bro_hashtable.c0000664002342100234210000001772212523041064020246 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #define BRO_HT_NUM_SLOTS 127 #ifdef BRO_DEBUG #define DEBUG_HTS #endif #ifdef DEBUG_HTS # define DEBUG_HT(x) do { printf("%s/%i: ", __FILE__, __LINE__); printf x ; } while (0); #else # define DEBUG_HT(x) #endif typedef struct bro_hash_item { /* For the age list in the hashtable. We know every node will * occur only once in the hashtable, and we want the items * themselves to be the nodes, so the macros are okay. */ TAILQ_ENTRY(bro_hash_item) age_list; void *it_key; void *it_data; } BroHTIt; typedef TAILQ_HEAD(hi_list, bro_hash_item) BroHIList; struct bro_ht { BroList **ht_slots; int ht_numslots; int ht_size; /* Age list for elements in hash table, only used if * requested in __bro_ht_new(). The youngest element * of the age list sits at the *tail* of the list, * the oldest is at the *front*. */ int use_age_list; BroHIList age_list; BroHTHashFunc ht_hash_func; BroHTCmpFunc ht_cmp_func; BroHTFreeFunc ht_key_free_func; BroHTFreeFunc ht_val_free_func; }; BroHT * __bro_ht_new(BroHTHashFunc hash_func, BroHTCmpFunc cmp_func, BroHTFreeFunc key_free_func, BroHTFreeFunc val_free_func, int use_age_list) { BroHT *ht; int i; D_ENTER; /* It may be okay if we get no free_funcs ... */ if (!hash_func || !cmp_func) D_RETURN_(NULL); if (! (ht = calloc(1, sizeof(BroHT)))) { D(("Out of memory in bro_ht_new.\n")); D_RETURN_(NULL); } ht->ht_numslots = BRO_HT_NUM_SLOTS; ht->ht_size = 0; ht->use_age_list = use_age_list; ht->ht_hash_func = hash_func; ht->ht_cmp_func = cmp_func; ht->ht_key_free_func = key_free_func; ht->ht_val_free_func = val_free_func; /* ht_slots is kept NULL here to avoid work on tables that are never * inserted into. */ /* Initialize the age list no matter whether it'll be * used or not. */ TAILQ_INIT(&ht->age_list); D_RETURN_(ht); } void __bro_ht_free(BroHT *ht) { BroList *l; BroHTIt *it; int i; D_ENTER; if (! ht) D_RETURN; /* Age list doesn't need cleaning up as its nodes are * entries in the regular hashtable, which are cleaned * up now: */ if (ht->ht_slots == NULL) { free(ht); D_RETURN; } for (i = 0; i < ht->ht_numslots; i++) { for (l = ht->ht_slots[i]; l; l = __bro_list_next(l)) { it = __bro_list_data(l); if (ht->ht_key_free_func) ht->ht_key_free_func(it->it_key); if (ht->ht_val_free_func) ht->ht_val_free_func(it->it_data); free(it); } __bro_list_free(ht->ht_slots[i], NULL); } free(ht->ht_slots); free(ht); D_RETURN; } int __bro_ht_add(BroHT *ht, void *key, void *data) { uint32 slot; BroHTIt *it; D_ENTER; if (!ht || !key) { D(("Input error: (%p, %p, %p)\n", ht, key, data)); D_RETURN_(FALSE); } if (! (it = calloc(1, sizeof(BroHTIt)))) { D(("Out of memory in bro_ht_add.\n")); D_RETURN_(FALSE); } it->it_key = key; it->it_data = data; if (ht->ht_slots == NULL) { if (! (ht->ht_slots = calloc(ht->ht_numslots, sizeof(BroList*)))) { D(("Out of memory in bro_ht_add for ht_slots.\n")); free(it); D_RETURN_(FALSE); } } slot = ht->ht_hash_func(key) % ht->ht_numslots; ht->ht_slots[slot] = __bro_list_append(ht->ht_slots[slot], it); ht->ht_size++; if (ht->use_age_list) TAILQ_INSERT_TAIL(&ht->age_list, it, age_list); D_RETURN_(TRUE); } void * __bro_ht_get(BroHT *ht, const void *key) { BroList *l; BroHTIt *it; uint32 slot; if (!ht || !key) { D(("Input error: (%p, %p)\n", ht, key)); return NULL; } if (!ht->ht_slots) return NULL; slot = ht->ht_hash_func(key) % ht->ht_numslots; for (l = ht->ht_slots[slot]; l; l = __bro_list_next(l)) { it = __bro_list_data(l); if (ht->ht_cmp_func(it->it_key, key)) { if (ht->use_age_list) { TAILQ_REMOVE(&ht->age_list, it, age_list); TAILQ_INSERT_TAIL(&ht->age_list, it, age_list); } return it->it_data; } } return NULL; } void * __bro_ht_del(BroHT *ht, void *key) { void *result; BroHTIt *it; BroList *l; uint32 slot; D_ENTER; if (!ht || !key) D_RETURN_(NULL); if (!ht->ht_slots) D_RETURN_(NULL); slot = ht->ht_hash_func(key) % ht->ht_numslots; for (l = ht->ht_slots[slot]; l; l = __bro_list_next(l)) { it = __bro_list_data(l); if (ht->ht_cmp_func(it->it_key, key)) { result = it->it_data; ht->ht_slots[slot] = __bro_list_remove(ht->ht_slots[slot], l); ht->ht_size--; /* Free the key if possible -- don't free the * value, as we just return that. */ if (ht->ht_key_free_func) ht->ht_key_free_func(it->it_key); if (ht->use_age_list) TAILQ_REMOVE(&ht->age_list, it, age_list); free(it); D_RETURN_(result); } } D_RETURN_(NULL); } int __bro_ht_get_size(BroHT *ht) { if (! ht) return -1; return ht->ht_size; } void __bro_ht_get_oldest(BroHT *ht, void **key, void **data) { if (! ht || !ht->use_age_list) { if (key) *key = NULL; if (data) *data = NULL; return; } if (key) *key = ht->age_list.tqh_first->it_key; if (data) *data = ht->age_list.tqh_first->it_data; } int __bro_ht_evict_oldest(BroHT *ht) { if (! ht) return 0; if (ht->use_age_list && ht->age_list.tqh_first) __bro_ht_del(ht, ht->age_list.tqh_first->it_key); return ht->ht_size; } void __bro_ht_foreach(BroHT *ht, BroHTCallback callback, void *user_data) { BroList *l; BroHTIt *it; int i; if (!ht || !callback) return; if (!ht->ht_slots) return; for (i = 0; i < ht->ht_numslots; i++) { for (l = ht->ht_slots[i]; l; l = __bro_list_next(l)) { it = __bro_list_data(l); if (! callback(it->it_key, it->it_data, user_data)) return; } } } uint32 __bro_ht_str_hash(const void *val) { char *val_ptr; uint32 hash; if (!val) return 0; val_ptr = (char *) val; for (hash = 0; *val_ptr != '\0'; val_ptr++) hash = (64 * hash + *val_ptr); return hash; } int __bro_ht_str_cmp(const void *val1, const void *val2) { if (! val1 || ! val2) return FALSE; return strcmp((char*) val1, (char*) val2) == 0; } void __bro_ht_mem_free(void *data) { if (data) free(data); } uint32 __bro_ht_int_hash(const void *val) { return (uint32)(uintptr_t) val; } int __bro_ht_int_cmp(const void *val1, const void *val2) { return val1 == val2; } broccoli-1.97-minimal/src/bro_table.h0000664002342100234210000000520612523041064017401 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_table_h #define broccoli_table_h #include #include #include /* BroTable is the table type we export to the user. It relies * on BroHTs for the implementation. * * Related typedefs are in broccoli.h because the users need * to know them -- we keep the definition opaque here. */ struct bro_table { /* The underlying hashtable */ BroHT *tbl_impl; int tbl_key_type, tbl_val_type; }; BroTable *__bro_table_new(void); void __bro_table_free(BroTable *tbl); BroTable *__bro_table_copy(BroTable *tbl); /* Inserts the given key-val pair and adopts ownership, * i.e., the values are not duplicated internally. */ void __bro_table_insert(BroTable *tbl, BroVal *key, BroVal *val); BroVal *__bro_table_find(BroTable *tbl, const BroVal *key); int __bro_table_get_size(BroTable *tbl); void __bro_table_foreach(BroTable *tbl, BroTableCallback cb, void *user_data); /* Sets are just tables that have no meaningful values associated * with the keys. As long as a table's tbl_val_type remains unknown, * a table is in fact a set. */ int __bro_table_is_set(BroTable *tbl); uint32 __bro_table_hash_key(BroVal *key); int __bro_table_cmp_key(BroVal *val1, BroVal *val2); uint32 __bro_table_hash(BroTable *tbl); int __bro_table_cmp(BroTable *tbl1, BroTable *tbl2); #endif broccoli-1.97-minimal/src/bro_list.h0000664002342100234210000000572712523041064017275 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_list_h #define broccoli_list_h typedef struct bro_list BroList; typedef void(*BroFunc) (void *data); /* Create new list with data item. */ BroList *__bro_list_new(void *data); /* Erase entire list, applying free_func to each item * in order to free it. Pass %NULL for free_func if no-op * is desired. */ void __bro_list_free(BroList *l, BroFunc free_func); /* Given list element, returns the head of list by * walking back to it. */ BroList *__bro_list_head(BroList *l); /* Next/prev items. */ BroList *__bro_list_next(BroList *l); BroList *__bro_list_prev(BroList *l); /* Returns nth list member, starting at 0, or NULL if not found. */ BroList *__bro_list_nth(BroList *l, int n); /* Returns length of list, or 0 on error. */ int __bro_list_length(BroList *l); /* Appends item to end of list and returns pointer to * the list. NOTE: O(N) runtime. Try to use * __bro_list_prepend() or track last list * element in case lists contain more than a handful * of elements. */ BroList *__bro_list_append(BroList *l, void *data); /* Prepends item and returns pointer to it. */ BroList *__bro_list_prepend(BroList *l, void *data); /* Inserts new node for @data after @l. * Returns pointer to new item. */ BroList *__bro_list_insert(BroList *l, void *data); /* Removes a node and returns a pointer to the first * element of the resulting list. */ BroList *__bro_list_remove(BroList *l, BroList *ll); /* List node data element accessor. */ void *__bro_list_data(BroList *l); /* Set data of list node, return old ones. */ void *__bro_list_set_data(BroList *l, void *data); /* Moves an item to the front of the list. For implementing * MRU/LRU schemes. */ BroList *__bro_list_move_to_front(BroList *l, BroList *item); #endif broccoli-1.97-minimal/src/bro_event_reg.c0000664002342100234210000003334512523041064020270 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include typedef void (*BroEvDispatcher)(BroConn *bc, BroEventCB *cb, BroEvent *ev); #define DISPATCH_TABLE_SIZE 15 /* Goes through all vals in the given event ev and extracts * from each val a pointer to its actual value, storing it * into the vals array. */ static int event_reg_init_vals(BroEvent *ev, void **vals) { int i; BroList *l; BroVal *val; for (i = 0, l = ev->val_list; l; i++, l = __bro_list_next(l)) { val = __bro_list_data(l); if (! __bro_val_get_data(val, NULL, &(vals[i]))) { D(("Error during callback parameter marshaling of parameter %i\n", i)); return FALSE; } } return TRUE; } /* Goes through all vals in the given event ev and extracts * from each val a pointer to its actual value and the type * of the val, storing it into the given BroEvArg and BroValMeta * structures. */ static int event_reg_init_args(BroEvent *ev, BroEvArg *args) { int i; BroList *l; BroVal *val; for (i = 0, l = ev->val_list; l; l = __bro_list_next(l), args++, i++) { val = __bro_list_data(l); if (! __bro_val_get_data(val, &args->arg_type, &args->arg_data)) { D(("Error during callback parameter marshaling of parameter %i\n", i)); return FALSE; } } return TRUE; } static void dispatcher_compact(BroConn *bc, BroEventCB *cb, BroEvent *ev) { BroEvMeta meta; BroEvArg *args = NULL; memset(&meta, 0, sizeof(meta)); if (! (args = calloc(ev->val_len, sizeof(BroEvArg)))) { D(("Out of memory when allocating %d BroEvArgs\n", ev->val_len)); return; } meta.ev_name = (const char*) bro_string_get_data(&ev->name); meta.ev_ts = ev->ts; meta.ev_numargs = ev->val_len; meta.ev_args = args; meta.ev_start = (const uchar*) bc->rx_ev_start; meta.ev_end = (const uchar*) bc->rx_ev_end; if (! event_reg_init_args(ev, args)) { free(args); return; } cb->cb_compact_func(bc, cb->cb_user_data, &meta); free(args); } static void dispatcher0(BroConn *bc, BroEventCB *cb, BroEvent *ev) { cb->cb_expanded_func(bc, cb->cb_user_data); return; ev = 0; } static void dispatcher1(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[1]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0]); } static void dispatcher2(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[2]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1]); } static void dispatcher3(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[3]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2]); } static void dispatcher4(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[4]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3]); } static void dispatcher5(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[5]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4]); } static void dispatcher6(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[6]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]); } static void dispatcher7(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[7]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6]); } static void dispatcher8(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[8]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7]); } static void dispatcher9(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[9]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8]); } static void dispatcher10(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[10]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9]); } static void dispatcher11(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[11]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10]); } static void dispatcher12(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[12]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11]); } static void dispatcher13(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[13]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11], vals[12]); } static void dispatcher14(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[14]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11], vals[12], vals[13]); } static void dispatcher15(BroConn *bc, BroEventCB *cb, BroEvent *ev) { void *vals[15]; if (! event_reg_init_vals(ev, vals)) return; cb->cb_expanded_func(bc, cb->cb_user_data, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11], vals[12], vals[13], vals[14]); } static BroEvDispatcher disp_table[] = { dispatcher0, dispatcher1, dispatcher2, dispatcher3, dispatcher4, dispatcher5, dispatcher6, dispatcher7, dispatcher8, dispatcher9, dispatcher10, dispatcher11, dispatcher12, dispatcher13, dispatcher14, dispatcher15, }; static BroEventHandler* event_reg_handler_new(const char *ev_name) { BroEventHandler *beh; if (!ev_name || !*ev_name) return NULL; if (! (beh = calloc(1, sizeof(BroEventHandler)))) return NULL; beh->ev_name = strdup(ev_name); TAILQ_INIT(&beh->cb_list); return beh; } static void event_reg_handler_free(BroEventHandler *beh) { BroEventCB *cb; if (!beh) return; if (beh->ev_name) free(beh->ev_name); while ( (cb = beh->cb_list.tqh_first)) { TAILQ_REMOVE(&beh->cb_list, cb, cb_list); free(cb); } free(beh); } static void event_reg_handler_dispatch(BroConn *bc, BroEventHandler *beh, BroEvent *ev) { BroEventCB *cb; if (!beh || !ev) return; if (ev->val_len > DISPATCH_TABLE_SIZE) return; for (cb = beh->cb_list.tqh_first; cb; cb = cb->cb_list.tqe_next) { switch (cb->cb_style) { case BRO_CALLBACK_EXPANDED: disp_table[ev->val_len](bc, cb, ev); break; case BRO_CALLBACK_COMPACT: dispatcher_compact(bc, cb, ev); break; default: ; }; } } BroEventReg * __bro_event_reg_new(void) { BroEventReg *reg; if (! (reg = calloc(1, sizeof(BroEventReg)))) return NULL; TAILQ_INIT(®->handler_list); return reg; } void __bro_event_reg_free(BroEventReg *reg) { BroEventHandler *beh; if (!reg) return; while ( (beh = reg->handler_list.tqh_first)) { TAILQ_REMOVE(®->handler_list, beh, handler_list); event_reg_handler_free(beh); } free(reg); } static void event_reg_add(BroEventCB *cb, BroEventReg *reg, const char *ev_name) { BroEventHandler *beh; for (beh = reg->handler_list.tqh_first; beh; beh = beh->handler_list.tqe_next) { if (strcmp(beh->ev_name, ev_name)) continue; /* We have found a handler for this event. * Add the new callback and return. */ TAILQ_INSERT_TAIL(&beh->cb_list, cb, cb_list); reg->num_handlers++; return; } /* We don't have a handler for this event yet. * Create it, add a callback for the given func, * and register it. */ if (! (beh = event_reg_handler_new(ev_name))) { free(cb); return; } TAILQ_INSERT_TAIL(&beh->cb_list, cb, cb_list); TAILQ_INSERT_TAIL(®->handler_list, beh, handler_list); reg->num_handlers++; } void __bro_event_reg_add(BroConn *bc, const char *ev_name, BroEventFunc func, void *user_data) { BroEventHandler *beh; BroEventCB *cb; BroEventReg *reg; if (!bc || !ev_name || !*ev_name) return; if (! (reg = bc->ev_reg)) return; /* Create a new callback data structure */ if (! (cb = calloc(1, sizeof(BroEventCB)))) return; cb->cb_expanded_func = func; cb->cb_user_data = user_data; cb->cb_style = BRO_CALLBACK_EXPANDED; event_reg_add(cb, reg, ev_name); } void __bro_event_reg_add_compact(BroConn *bc, const char *ev_name, BroCompactEventFunc func, void *user_data) { BroEventHandler *beh; BroEventCB *cb; BroEventReg *reg; if (!bc || !ev_name || !*ev_name) return; if (! (reg = bc->ev_reg)) return; /* Create a new callback data structure */ if (! (cb = calloc(1, sizeof(BroEventCB)))) return; cb->cb_compact_func = func; cb->cb_user_data = user_data; cb->cb_style = BRO_CALLBACK_COMPACT; event_reg_add(cb, reg, ev_name); } int __bro_event_reg_remove(BroConn *bc, const char *ev_name) { BroEventHandler *beh; BroEventReg *reg; if (!bc || !ev_name || !*ev_name) return FALSE; if (! (reg = bc->ev_reg)) return FALSE; for (beh = reg->handler_list.tqh_first; beh; beh = beh->handler_list.tqe_next) { if (strcmp(beh->ev_name, ev_name)) continue; TAILQ_REMOVE(®->handler_list, beh, handler_list); event_reg_handler_free(beh); reg->num_handlers--; return TRUE; } return FALSE; } int __bro_event_reg_request(BroConn *bc) { BroEventReg *reg; BroEventHandler *beh; BroRequest *req; int len = 0; int result; char *ptr; D_ENTER; if (!bc) D_RETURN_(FALSE); if (! (reg = bc->ev_reg)) D_RETURN_(FALSE); /* Go over all handlers once, and collect the total length of * all event names including terminating 0s. */ for (beh = reg->handler_list.tqh_first; beh; beh = beh->handler_list.tqe_next) len += strlen(beh->ev_name) + 1; /* Allocate a request structure for that length */ if (! (req = __bro_event_request_new(len))) D_RETURN_(FALSE); /* Go through again and copy all event names into the * request structure. */ ptr = req->req_dat; for (beh = reg->handler_list.tqh_first; beh; beh = beh->handler_list.tqe_next) { D(("Requesting event '%s'\n", beh->ev_name)); memcpy(ptr, beh->ev_name, strlen(beh->ev_name)); ptr += strlen(ptr) + 1; } if (! __bro_io_request_queue(bc, req)) D_RETURN_(FALSE); D_RETURN_(TRUE); } void __bro_event_reg_dispatch(BroConn *bc, BroEvent *ev) { BroEventReg *reg; BroEventHandler *beh; D_ENTER; if (!bc || !ev || ! (reg = bc->ev_reg)) { D(("Input error\n")); D_RETURN; } D(("Dispatching event '%s' with %i paramaters.\n", ev->name.str_val, ev->val_len)); for (beh = reg->handler_list.tqh_first; beh; beh = beh->handler_list.tqe_next) { if (strcmp(__bro_event_get_name(ev), beh->ev_name) == 0) event_reg_handler_dispatch(bc, beh, ev); } D_RETURN; } BroRequest * __bro_event_request_new(int len) { BroRequest *req; if (len <= 0) return NULL; if (! (req = calloc(1, sizeof(BroRequest)))) return NULL; if (! (req->req_dat = calloc(len + 1, sizeof(char)))) { free(req); return NULL; } req->req_len = len; return req; } void __bro_event_request_free(BroRequest *req) { if (! req) return; if (req->req_dat) free(req->req_dat); free(req); } broccoli-1.97-minimal/src/bro_type_decl.h0000664002342100234210000000406412523041064020263 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_type_decl_h #define broccoli_type_decl_h #include #include /* BroTypeDecls live outside the inheritance chain and are currently * only of interest for bro_type.c. The function names only resemble * the virtualized ones for easier integration with the virtualized * code. */ typedef struct bro_type_decl { BroAttrs *attrs; BroType *type; BroString id; } BroTypeDecl; BroTypeDecl *__bro_type_decl_new(void); BroTypeDecl *__bro_type_decl_copy(BroTypeDecl *td); void __bro_type_decl_free(BroTypeDecl *td); int __bro_type_decl_read(BroTypeDecl *td, BroConn *bc); int __bro_type_decl_write(BroTypeDecl *td, BroConn *bc); uint32 __bro_type_decl_hash(BroTypeDecl *td); int __bro_type_decl_cmp(BroTypeDecl *td1, BroTypeDecl *td2); #endif broccoli-1.97-minimal/src/bro_event_reg.h0000664002342100234210000000373512523041064020275 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_event_reg_h #define broccoli_event_reg_h #include BroEventReg *__bro_event_reg_new(void); void __bro_event_reg_free(BroEventReg *reg); void __bro_event_reg_add(BroConn *bc, const char *ev_name, BroEventFunc func, void *user_data); void __bro_event_reg_add_compact(BroConn *bc, const char *ev_name, BroCompactEventFunc func, void *user_data); int __bro_event_reg_remove(BroConn *bc, const char *ev_name); int __bro_event_reg_request(BroConn *bc); void __bro_event_reg_dispatch(BroConn *bc, BroEvent *ev); BroRequest *__bro_event_request_new(int len); void __bro_event_request_free(BroRequest *req); #endif broccoli-1.97-minimal/src/bro_type_decl.c0000664002342100234210000001064312523041064020256 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include BroTypeDecl * __bro_type_decl_new(void) { BroTypeDecl *td; D_ENTER; if (! (td = calloc(1, sizeof(BroTypeDecl)))) D_RETURN_(NULL); D_RETURN_(td); } BroTypeDecl * __bro_type_decl_copy(BroTypeDecl *td) { BroTypeDecl *copy; D_ENTER; if (! td) D_RETURN_(NULL); if (! (copy = __bro_type_decl_new())) D_RETURN_(NULL); if (td->attrs && ! (copy->attrs = (BroAttrs *) __bro_sobject_copy((BroSObject *) td->attrs))) goto error_result; if (td->type && ! (copy->type = (BroType *) __bro_sobject_copy((BroSObject *) td->type))) goto error_result; if (! (bro_string_set_data(©->id, bro_string_get_data(&td->id), bro_string_get_length(&td->id)))) goto error_result; D_RETURN_(copy); error_result: __bro_type_decl_free(copy); D_RETURN_(NULL); } void __bro_type_decl_free(BroTypeDecl *td) { D_ENTER; if (! td) D_RETURN; __bro_sobject_release((BroSObject *) td->type); __bro_sobject_release((BroSObject *) td->attrs); bro_string_cleanup(&td->id); free(td); D_RETURN; } int __bro_type_decl_read(BroTypeDecl *td, BroConn *bc) { char opt; D_ENTER; if (! td || !bc) D_RETURN_(FALSE); /* Read an optional BroAttrs */ if (td->attrs) __bro_sobject_release((BroSObject *) td->attrs); td->attrs = NULL; if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { D(("Reading optional attributes in TypeDecl instance.\n")); if (! (td->attrs = (BroAttrs *) __bro_sobject_unserialize(SER_ATTRIBUTES, bc))) D_RETURN_(FALSE); } /* Read a type */ if (td->type) __bro_sobject_release((BroSObject *) td->type); td->type = NULL; D(("Reading type in in TypeDecl instance.\n")); if (! (td->type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); /* Read ID name string */ D(("Reading ID name string in TypeDecl instance.\n")); bro_string_cleanup(&td->id); if (! __bro_buf_read_string(bc->rx_buf, &td->id)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_type_decl_write(BroTypeDecl *td, BroConn *bc) { D_ENTER; if (! td || !bc) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, td->attrs ? 1 : 0)) D_RETURN_(FALSE); if (td->attrs && ! __bro_sobject_serialize((BroSObject *) td->attrs, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) td->type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &td->id)) D_RETURN_(FALSE); D_RETURN_(TRUE); } uint32 __bro_type_decl_hash(BroTypeDecl *td) { uint32 result; D_ENTER; if (! td) D_RETURN_(0); result = __bro_ht_str_hash(td->id.str_val); result ^= __bro_sobject_hash((BroSObject*) td->attrs); result ^= __bro_sobject_hash((BroSObject*) td->type); D_RETURN_(result); } int __bro_type_decl_cmp(BroTypeDecl *td1, BroTypeDecl *td2) { D_ENTER; if (! td1 || ! td2) D_RETURN_(FALSE); if (! __bro_sobject_cmp((BroSObject*) td1->attrs, (BroSObject*) td2->attrs) || ! __bro_sobject_cmp((BroSObject*) td1->type, (BroSObject*) td2->type)) D_RETURN_(FALSE); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_hashtable.h0000664002342100234210000001031512523041064020242 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_ht_h #define broccoli_ht_h #include typedef struct bro_ht BroHT; /* Hash function -- pass something in, get integer back. */ typedef uint32 (*BroHTHashFunc)(const void *data); /* Key comparison function -- compares two keys, returns %TRUE * if equal, %FALSE otherwise, NOT -1/0/1. */ typedef int (*BroHTCmpFunc)(const void *key1, const void *key2); /* Destructor function, one for keys, one for values. */ typedef void (*BroHTFreeFunc)(void *data); /** * BroHTCallback - The signature of functions used with __bro_ht_foreach() * @param key key of current hash table item * @param data value part of current hash table item. * @param user_data arbitrary user data passed through from __bro_ht_foreach(). * * Returning %FALSE signals abortion of the loop. */ typedef int (*BroHTCallback)(void *key, void *data, void *user_data); /** * __bro_ht_new - creates new hashtable. * @param hash_func hashing function to use, see BroHTHashFunc. * @param cmp_func element comparison function to use, see BroHTCmpFunc. * @param key_free_func callback for erasing key of an item, if desirable. * @param val_free_func callback for erasing data item itself, if desirable. * @param use_age_list whether to maintain an age list (%TRUE) or not (%FALSE). * * The function creates and returns a new hashtable. @p key_free_func and * @p val_free_func can be used to clean up contained elements automatically * as they are removed from the table. If you don't want this feature, * pass %NULL -- you can still iterate over all items in the table using * __bro_ht_foreach(). * * The table can optionally maintain an age list (see * __bro_ht_get_oldest() and __bro_ht_evict_oldest()), pass %TRUE to * @p use_age_list if desired. * * @returns new table, or %NULL when out of memory. */ BroHT *__bro_ht_new(BroHTHashFunc hash_func, BroHTCmpFunc cmp_func, BroHTFreeFunc key_free_func, BroHTFreeFunc val_free_func, int use_age_list); void __bro_ht_free(BroHT *ht); int __bro_ht_add(BroHT *ht, void *key, void *data); void *__bro_ht_get(BroHT *ht, const void *key); void *__bro_ht_del(BroHT *ht, void *key); int __bro_ht_get_size(BroHT *ht); void __bro_ht_foreach(BroHT *ht, BroHTCallback cb, void *user_data); /* Returns pointers to key and value of oldest item in the table, * if age list is maintained. Otherwise sets both @p key and @p data * to %NULL. */ void __bro_ht_get_oldest(BroHT *ht, void **key, void **data); /* If age list is used, removes oldest element from the table * and returns number of items in the table after eviction. * If age list is not used, does nothing and returns table size. */ int __bro_ht_evict_oldest(BroHT *ht); uint32 __bro_ht_str_hash(const void *val); int __bro_ht_str_cmp(const void *val1, const void *val2); void __bro_ht_mem_free(void *data); uint32 __bro_ht_int_hash(const void *val); int __bro_ht_int_cmp(const void *val1, const void *val2); #endif broccoli-1.97-minimal/src/bro_debug.h0000664002342100234210000000502512523041064017377 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __broccoli_debug_h #define __broccoli_debug_h #include #include #include #include void bro_debug_enter(const char *function, int line); void bro_debug_return(const char *function, int line); #ifdef BRO_DEBUG void bro_debug(const char *msg, ...); /** * D - prints debugging output * @x: debugging information. * * Use this macro to output debugging information. @x is * the content as you would pass it to printf(), including * braces to make the arguments appear as one argument to * the macro. The macro is void if BRO_DEBUG is not defined * at compile time. */ #undef D #define D(x) do { bro_debug("%u %f %s/%i ", getpid(), __bro_util_get_time(), __FILE__, __LINE__); bro_debug x ; } while (0) #undef D_ENTER #define D_ENTER bro_debug_enter(__FUNCTION__, __LINE__) #undef D_RETURN #define D_RETURN do { bro_debug_return(__FUNCTION__, __LINE__); return; } while (0) #undef D_RETURN_ #define D_RETURN_(x) do { bro_debug_return(__FUNCTION__, __LINE__); return (x); } while (0) #else #undef D #define D(x) #undef D_ENTER #define D_ENTER #undef D_RETURN #define D_RETURN return #undef D_RETURN_ #define D_RETURN_(x) return (x) #endif /* BRO_DEBUG */ #endif broccoli-1.97-minimal/src/bro_attrs.c0000664002342100234210000001351412523041064017443 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include BroAttrs * __bro_attrs_new(void) { BroAttrs *attrs; D_ENTER; if (! (attrs = calloc(1, sizeof(BroAttrs)))) D_RETURN_(NULL); __bro_attrs_init(attrs); D_RETURN_(attrs); } void __bro_attrs_init(BroAttrs *attrs) { BroSObject *sobj = (BroSObject *) attrs; D_ENTER; __bro_object_init((BroObject *) attrs); sobj->read = (BroSObjectRead) __bro_attrs_read; sobj->write = (BroSObjectWrite) __bro_attrs_write; sobj->free = (BroSObjectFree) __bro_attrs_free; sobj->clone = (BroSObjectClone) __bro_attrs_clone; sobj->hash = (BroSObjectHash) __bro_attrs_hash; sobj->cmp = (BroSObjectCmp) __bro_attrs_cmp; sobj->type_id = SER_ATTRIBUTES; D_RETURN; } void __bro_attrs_free(BroAttrs *attrs) { uint32 i; D_ENTER; __bro_sobject_release((BroSObject *) attrs->type); for (i = 0; i < attrs->num_attrs; i++) __bro_attr_free(attrs->attrs[i]); free(attrs->attrs); __bro_object_free((BroObject *) attrs); D_RETURN; } int __bro_attrs_read(BroAttrs *attrs, BroConn *bc) { uint32 i; D_ENTER; if (! __bro_object_read((BroObject *) attrs, bc)) D_RETURN_(FALSE); if (attrs->type) __bro_sobject_release((BroSObject *) attrs->type); D(("Attempting to read type in Attributes...\n")); if (! (attrs->type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) { D(("Reading type in attributes failed.\n")); D_RETURN_(FALSE); } D(("Successfully read type in attributes.\n")); if (attrs->attrs) { for (i = 0; i < attrs->num_attrs; i++) __bro_attr_free(attrs->attrs[i]); free(attrs->attrs); } if (! __bro_buf_read_int(bc->rx_buf, &attrs->num_attrs)) D_RETURN_(FALSE); if (! (attrs->attrs = calloc(attrs->num_attrs, sizeof(BroAttr*)))) D_RETURN_(FALSE); for (i = 0; i < attrs->num_attrs; i++) { BroAttr *attr; D(("Attempting to read #%d of %d Attrs in Attributes...\n", i+1, attrs->num_attrs)); if (! (attr = __bro_attr_new())) D_RETURN_(FALSE); if (! __bro_attr_read(attr, bc)) { __bro_attr_free(attr); D_RETURN_(FALSE); } attrs->attrs[i] = attr; } D_RETURN_(TRUE); } int __bro_attrs_write(BroAttrs *attrs, BroConn *bc) { uint32 i; D_ENTER; if (! __bro_object_write((BroObject *) attrs, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) attrs->type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, attrs->num_attrs)) D_RETURN_(FALSE); for (i = 0; i < attrs->num_attrs; i++) { if (! __bro_sobject_serialize((BroSObject *) attrs->attrs[i], bc)) D_RETURN_(FALSE); } D_RETURN_(TRUE); } int __bro_attrs_clone(BroAttrs *dst, BroAttrs *src) { uint32 i; D_ENTER; if (! __bro_object_clone((BroObject *) dst, (BroObject *) src)) D_RETURN_(FALSE); if (src->type && ! (dst->type = (BroType *) __bro_sobject_copy((BroSObject *) dst->type))) D_RETURN_(FALSE); if (dst->attrs) { for (i = 0; i < dst->num_attrs; i++) __bro_attr_free(dst->attrs[i]); free(dst->attrs); } dst->num_attrs = src->num_attrs; if (! (dst->attrs = calloc(dst->num_attrs, sizeof(BroAttr *)))) D_RETURN_(FALSE); for (i = 0; i < dst->num_attrs; i++) { if (! (dst->attrs[i] = __bro_attr_copy(src->attrs[i]))) D_RETURN_(FALSE); } D_RETURN_(TRUE); } uint32 __bro_attrs_hash(BroAttrs *attrs) { uint32 result, i, shift; D_ENTER; if (! attrs) D_RETURN_(0); result = __bro_sobject_hash((BroSObject*) attrs->type) ^ attrs->num_attrs; /* Cycle through the attributes and XOR their tags, also * cycling through a shifting regime shifting by 0, 8, 16, * 24, 0, etc. */ for (i = 0, shift = 0; i < attrs->num_attrs; i++, shift += 8) { uint32 val; if (shift > 24) shift = 0; val = (uint32) attrs->attrs[i]->tag; result ^= val << shift; } D_RETURN_(result); } int __bro_attrs_cmp(BroAttrs *attrs1, BroAttrs *attrs2) { uint32 i, j; D_ENTER; if (! __bro_sobject_cmp((BroSObject*) attrs1->type, (BroSObject*) attrs2->type)) D_RETURN_(FALSE); if (attrs1->num_attrs != attrs2->num_attrs) D_RETURN_(FALSE); for (i = 0, j = 0; i < attrs1->num_attrs && attrs2->num_attrs; i++, j++) { if (attrs1->attrs[i]->tag != attrs2->attrs[j]->tag) D_RETURN_(FALSE); } D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_list.c0000664002342100234210000001074712523041064017266 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include struct bro_list { struct bro_list *prev; struct bro_list *next; void *data; }; BroList * __bro_list_new(void *data) { BroList *l; l = calloc(1, sizeof(BroList)); if (l == NULL) { D(("WARNING: Unable to allocate memory in bro_list_new for BroList.\n")); return NULL; } l->prev = l->next = NULL; l->data = data; return l; } void __bro_list_free(BroList *l, BroFunc free_func) { BroList *lnext; while (l) { lnext = l->next; if (l->data && free_func) { free_func(l->data); } free(l); l = lnext; } } BroList * __bro_list_head(BroList *l) { if (!l) return NULL; while (l->prev) l = l->prev; return l; } BroList * __bro_list_next(BroList *l) { if (!l) return NULL; return l->next; } BroList * __bro_list_prev(BroList *l) { if (!l) return NULL; return l->prev; } BroList * __bro_list_nth(BroList *l, int n) { while (l && n > 0) { l = l->next; n--; } return l; } int __bro_list_length(BroList *l) { int i = 0; while (l) { i++; l = l->next; } return i; } BroList * __bro_list_append(BroList *l, void *data) { BroList *ltmp = NULL; BroList *lnew = NULL; lnew = __bro_list_new(data); if (l) { ltmp = l; while (ltmp->next) ltmp = ltmp->next; ltmp->next = lnew; } lnew->prev = ltmp; return l ? l : lnew; } BroList * __bro_list_prepend(BroList *l, void *data) { BroList *lnew; lnew = __bro_list_new(data); lnew->next = l; if (l) l->prev = lnew; return lnew; } BroList * __bro_list_insert(BroList *l, void *data) { BroList *new; /* Data item can be NULL if user wants that */ if (!l) return NULL; new = __bro_list_new(data); new->next = l->next; new->prev = l; l->next = new; if (new->next) new->next->prev = l; return new; } BroList * __bro_list_remove(BroList *l, BroList *item) { BroList *prev; BroList *next; if (!l) return NULL; prev = item->prev; next = item->next; free(item); /* first item */ if (!prev) { if (!next) return NULL; else { next->prev = NULL; return next; } } /* last item */ if (!next) { prev->next = NULL; return l; } /* middle item */ prev->next = next; next->prev = prev; return l; } void * __bro_list_data(BroList *l) { if (!l) return NULL; return l->data; } void * __bro_list_set_data(BroList *l, void *data) { void *result; if (!l) return NULL; result = l->data; l->data = data; return result; } BroList * __bro_list_move_to_front(BroList *l, BroList *item) { BroList *prev; BroList *next; if (!l || !item) return NULL; prev = item->prev; next = item->next; /* first item already */ if (!prev) return l; /* last item */ if (!next) { prev->next = NULL; item->prev = NULL; item->next = l; l->prev = item; return item; } /* middle item */ prev->next = next; next->prev = prev; item->next = l; item->prev = NULL; l->prev = item; return item; } broccoli-1.97-minimal/src/bro_attrs.h0000664002342100234210000000365712523041064017457 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_attrs_h #define broccoli_attrs_h #include #include typedef struct bro_attrs { BroObject object; BroType *type; uint32 num_attrs; BroAttr **attrs; } BroAttrs; BroAttrs *__bro_attrs_new(void); void __bro_attrs_init(BroAttrs *attrs); void __bro_attrs_free(BroAttrs *attrs); int __bro_attrs_read(BroAttrs *attrs, BroConn *bc); int __bro_attrs_write(BroAttrs *attrs, BroConn *bc); int __bro_attrs_clone(BroAttrs *dst, BroAttrs *src); uint32 __bro_attrs_hash(BroAttrs *attrs); int __bro_attrs_cmp(BroAttrs *attrs1, BroAttrs *attrs2); #endif broccoli-1.97-minimal/src/bro_vector.c0000664002342100234210000000767012523041064017616 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include BroVector * __bro_vector_new(void) { BroVector *rec; if (! (rec = calloc(1, sizeof(BroVector)))) return NULL; return rec; } void __bro_vector_free(BroVector *vec) { int i; if ( ! vec ) return; for ( i = 0; i < vec->length; ++i ) __bro_sobject_release((BroSObject*) vec->vector[i]); free(vec->vector); free(vec); } int __bro_vector_get_length(BroVector *vec) { D_ENTER; if ( ! vec ) D_RETURN_(0); D_RETURN_(vec->length); } BroVector * __bro_vector_copy(BroVector *vec) { int i; BroVector *copy; BroVal *val_copy; D_ENTER; if ( ! vec ) D_RETURN_(NULL); if ( ! (copy = __bro_vector_new()) ) D_RETURN_(NULL); if ( ! (copy->vector = calloc(vec->length, sizeof(BroVal*))) ) { __bro_vector_free(copy); D_RETURN_(NULL); } copy->length = vec->length; for ( i = 0; i < vec->length; ++i ) { val_copy = (BroVal*) __bro_sobject_copy((BroSObject*) vec->vector[i]); if ( ! val_copy ) { __bro_vector_free(copy); D_RETURN_(NULL); } copy->vector[i] = val_copy; } D_RETURN_(copy); } int __bro_vector_add_val(BroVector *vec, BroVal *val) { D_ENTER; if ( ! vec || ! val ) D_RETURN_(FALSE); vec->vector = realloc(vec->vector, (vec->length + 1) * sizeof(BroVal*)); if ( ! vec->vector ) { D(("Realloc'ing vector failed.\n")); D_RETURN_(FALSE); } vec->vector[vec->length] = val; vec->length++; D_RETURN_(TRUE); } BroVal * __bro_vector_get_nth_val(BroVector *vec, int num) { if ( ! vec || num < 0 || num >= vec->length ) return NULL; return vec->vector[num]; } int __bro_vector_set_nth_val(BroVector *vec, int num, BroVal *v) { BroVal *val; if ( ! vec || num < 0 || num >= vec->length || ! v ) return FALSE; __bro_sobject_release((BroSObject*) vec->vector[num]); vec->vector[num] = v; return TRUE; } uint32 __bro_vector_hash(BroVector *vec) { int i; uint32 result; D_ENTER; if ( ! vec ) D_RETURN_(0); result = vec->length; for ( i = 0; i < vec->length; ++i ) result ^= __bro_sobject_hash((BroSObject*) vec->vector[i]); D_RETURN_(result); } int __bro_vector_cmp(BroVector *vec1, BroVector *vec2) { int i; if ( ! vec1 || ! vec2 ) D_RETURN_(FALSE); if ( vec1->length != vec2->length ) D_RETURN_(FALSE); for ( i = 0; i < vec1->length; ++i ) if ( ! __bro_sobject_cmp((BroSObject*) vec1->vector[i], (BroSObject*) vec2->vector[i]) ) D_RETURN_(FALSE); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_types.h0000664002342100234210000003247612523041064017467 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_types_h #define broccoli_types_h #include #include #include #include #include #include #include /* Protocol version */ #define BRO_PROTOCOL_VERSION 0x07 /* Data format version */ #define BRO_DATA_FORMAT_VERSION 25 /* The maximum number of messages we queue before we start * dropping messages. Might be worth moving this to the * config file. * * FIXME: this should become configurable via the config file. * */ #define BRO_MSG_QUEUELEN_MAX 1000 /* Message codes, taken from RemoteSerializer.cc. * Don't know why the hex -- 0a-0f seem to be missing. * Doesn't really matter though. */ #define BRO_MSG_NONE 0x00 #define BRO_MSG_VERSION 0x01 #define BRO_MSG_SERIAL 0x02 #define BRO_MSG_CLOSE 0x03 #define BRO_MSG_CLOSE_ALL 0x04 #define BRO_MSG_ERROR 0x05 #define BRO_MSG_CONNECTTO 0x06 #define BRO_MSG_CONNECTED 0x07 #define BRO_MSG_REQUEST 0x08 #define BRO_MSG_LISTEN 0x09 #define BRO_MSG_LISTEN_STOP 0x0a #define BRO_MSG_STATS 0x0b #define BRO_MSG_CAPTURE_FILTER 0x0c #define BRO_MSG_REQUEST_SYNC 0x0d #define BRO_MSG_PHASE_DONE 0x0e #define BRO_MSG_PING 0x0f #define BRO_MSG_PONG 0x10 #define BRO_MSG_CAPS 0x11 #define BRO_MSG_COMPRESS 0x12 #define BRO_MSG_MAX 0x13 /* State of the handshake of a connection. Both sides * can be in the handshake phase or have finished it. */ #define BRO_CONNSTATE_SETUP 0 /* Version numbers, cache size...*/ #define BRO_CONNSTATE_HANDSHAKE 1 /* Event request, capabilities... */ #define BRO_CONNSTATE_SYNC 2 /* State synchronization */ #define BRO_CONNSTATE_RUNNING 3 /* Up and running. */ /* Capabilities we might have. */ #define BRO_CAP_COMPRESS 1 #define BRO_CAP_DONTCACHE 2 #define BRO_CAP_64BIT 4 /* not used */ #define BRO_CAP_NEW_CACHE_STRAT 8 /* not used */ #define BRO_CAP_BROCCOLI_PEER 16 /* endpoint sending capabilities uses Broccoli */ /* Message payload types -- these do not * respond to anything inside Bro and are * used only locally. */ #define BRO_MSG_CONT_NONE 0 #define BRO_MSG_CONT_RAW 1 /* BroBufs, for strings, integer arrays, etc */ #define BRO_MSG_CONT_EVENT 2 /* Events */ #define BRO_MSG_CONT_REQUEST 3 /* Requests for events etc */ #define BRO_MSG_CONT_PACKET 4 /* Pcap packets */ /* Messages between master process and I/O handler in * shared connections case. */ #define BRO_IOMSG_NONE 0 #define BRO_IOMSG_STOP 1 #define BRO_IOMSG_READ 2 #define BRO_IOMSG_WRITE 3 /* Event handler callback invocation styles */ #define BRO_CALLBACK_EXPANDED 0 /* Each argument passed separately */ #define BRO_CALLBACK_COMPACT 1 /* All arguments passed as a single BroEvArg* */ typedef struct bro_type BroType; typedef struct bro_type_list BroTypeList; typedef struct bro_record_type BroRecordType; typedef struct bro_index_type BroIndexType; typedef struct bro_table_type BroTableType; typedef struct bro_set_type BroSetType; typedef struct bro_file_type BroFileType; typedef struct bro_enum_type BroEnumType; typedef struct bro_vector_type BroVectorType; typedef struct bro_id BroID; typedef struct bro_val BroVal; typedef struct bro_list_val BroListVal; typedef struct bro_mutable_val BroMutableVal; typedef struct bro_record_val BroRecordVal; typedef struct bro_table_val BroTableVal; typedef struct bro_vector_val BroVectorVal; typedef struct bro_msg_header BroMsgHeader; typedef struct bro_msg BroMsg; typedef struct bro_event_reg BroEventReg; typedef struct bro_event_handler BroEventHandler; typedef struct bro_event_cb BroEventCB; typedef struct bro_request BroRequest; /* General per-connection state information that we keep in a separate * structure so we can put it into shared memory if required. This is * a remnant from older code, but seems to make sense to preserve. */ typedef struct bro_conn_state { /* Whether we are currently attempting a reconnect. Used to make * sure we do not attempt reconnects while we are attempting a * reconnect. :) */ int in_reconnect; /* Timestamp of the last reconnection attempt of this connection. */ time_t last_reconnect; /* Flags declaring whether or not individual transmission * directions have shut down (e.g., because of an error). */ int tx_dead; int rx_dead; /* State of the connection, for ourselves and the peer. * Connections go through a * * (1) setup * (2) handshake * (3) state synchronization * (4) normal operation * * lifecycle, of which phase 3 is optional. */ int conn_state_self; int conn_state_peer; /* True if the other side has requested synchronized state. Then * there is an additional phase in the communication. */ int sync_state_requested; /* Messages for I/O handler. Only used in shared connection case. */ int io_msg; /* If != 0, ID of writer process for messages in the tx buffer. */ pid_t io_pid; } BroConnState; /* The most important structure: Bro connection handles. * ===================================================== */ struct bro_conn { /* Flags set for this connection at creation time by the user. */ int conn_flags; /* Two numerical values used for creating identifiers based on * connection handles. */ pid_t id_pid; int id_num; /* The peer we connect to, in : format */ char *peer; /* The class of this connection. It's just an (optional) string. * If set, gets sent in the setup phase of the connection's * configuration. */ char *class; /* A similar class identifier, if sent by the remote side. */ char *peer_class; /* OpenSSL I/O buffer for communication regardless of whether * we're using encryption or not. */ BIO *bio; /* Incoming data are buffered in the following buffer * structure. Each time data arrive, Broccoli checks * whether there's enough data in the buffer to do * anything useful with in, in which case those data * are consumed and make room for more input. * * The main purpose of the buffer is to disconnect * the arrival of data from the time of processing * because we want to avoid blocking of the instrumented * application by all means. * * Note that the buffers are used in the code directly * as rx_buf/tx_buf, but may actually live in the shared * memory segments pointed to by rx_buf_shm/tx_buf_shm. */ BroBuf *rx_buf; /* Fields to mark the currently processed event in the * input buffer if event is currently processed, NULLs * otherwise: */ const char *rx_ev_start; const char *rx_ev_end; /* Similar buffer for outgoing data: */ BroBuf *tx_buf; /* A message queue plus its length counter for messages * that we haven't yet sent to the peer. */ TAILQ_HEAD(mqueue, bro_msg) msg_queue; uint msg_queue_len; /* A hashtable of all the names of events the peer accepts * from us. */ BroHT *ev_mask; /* We maintain an event handler registry per conection: * these registries define callbacks for events that we * receive and at the same time can be using to request * event delivery from the peering Bro agent. */ BroEventReg *ev_reg; /* Serialization data are cached when they will be * repeated identically. To handle this, there's a per- * connection cache implemented as a hash table: */ BroHT *io_cache; /* Size limit for io_cache. *Must* match MAX_CACHE_SIZE * value defined in Bro's RemoteSerialier.cc. */ int io_cache_maxsize; /* Storage for arbitrary user data: */ BroHT *data; #ifdef BRO_PCAP_SUPPORT uint32 pcap_link_type; #endif /* General connection state */ BroConnState *state; /* Externally provided socket to be used for connection. */ int socket; }; struct bro_msg_header { char hdr_type; uint32 hdr_peer_id; }; struct bro_msg { /* Messages get queued inside BroConns. * These are the list pointers for that. */ TAILQ_ENTRY(bro_msg) msg_queue; uint32 msg_size; /* Header of the message, a CMsg in Bro. */ struct bro_msg_header msg_header; /* A counter for identifying this message. Not used otherwise. */ int msg_num; /* We know the header size, but we need to store it * somewhere when we send the message. We use this: */ uint32 msg_header_size; /* A BRO_MSG_CONT_xxx value to identify the type of * data in the union below. This is easier to use than * using the type field in the message header all the time. */ char msg_cont_type; union { BroBuf *msg_raw; BroEvent *msg_ev; BroRequest *msg_req; #ifdef BRO_PCAP_SUPPORT BroPacket *msg_packet; #endif } msg_cont; #define msg_cont_raw msg_cont.msg_raw #define msg_cont_ev msg_cont.msg_ev #define msg_cont_req msg_cont.msg_req #define msg_cont_packet msg_cont.msg_packet }; struct bro_event { /* Name of the event, as listed in event.bif. */ BroString name; /* Timestamp (seconds since epoch) of creation of event. */ double ts; /* A list of values to pass to the event, plus the * length of the list. */ BroList *val_list; int val_len; }; struct bro_request { int req_len; char *req_dat; }; /* The Bro event registry: * ======================= * * Each Bro connection handle contains a BroEventReg structure. * In it, a list of BroEventHandlers registered. Each * handler represents one particular type of event that can * be received, and contains a list of BroEventCBs. Each of * those represents one actual callback performed when an * event for the handler is received (similarly to Bro, Broccoli * can have multiple event handlers for a single event type). * * Since the number and type of each event will vary, the callback * mechanism becomes a little tricky. When an event is received, * its parameters are deserialized accordingly. The registered * callbacks are then called with POINTERS to all these values -- * since the size of a pointer is always the same no matter what * it's pointing to, we can in fact call the callbacks with * pointers to all these arguments. The number of parameters is * currently limited to a maximum of 15. If you need that many, * chances are you'll forget one anyway ;) */ struct bro_event_cb { TAILQ_ENTRY(bro_event_cb) cb_list; /* One of the various styles of callbacks, * identified by cb_style below. */ union { BroEventFunc cb_expd; BroCompactEventFunc cb_comp; } cb_func; #define cb_expanded_func cb_func.cb_expd #define cb_compact_func cb_func.cb_comp void *cb_user_data; int cb_style; /* A BRO_CALLBACK_xxx value */ }; struct bro_event_handler { char *ev_name; TAILQ_ENTRY(bro_event_handler) handler_list; TAILQ_HEAD(cblist, bro_event_cb) cb_list; }; struct bro_event_reg { TAILQ_HEAD(hlist, bro_event_handler) handler_list; int num_handlers; }; #endif broccoli-1.97-minimal/src/bro_sem_posix.c0000664002342100234210000001017412523041064020313 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include struct bro_sem_impl { char *name; sem_t *sem; }; int __bro_sem_init(BroSem *sem, const BroConn *bc) { static int counter = 0; char sem_name[512]; D_ENTER; if (! sem || ! bc) D_RETURN_(FALSE); memset(sem, 0, sizeof(BroSem)); if (! (sem->sem_impl = calloc(1, sizeof(BroSemImpl)))) D_RETURN_(FALSE); __bro_util_snprintf(sem_name, 512, "/broccoli-%u-%i-%i", bc->id_pid, bc->id_num, counter++); sem->sem_impl->name = strdup(sem_name); sem->sem_impl->sem = sem_open(sem_name, O_CREAT, S_IRWXU, 1); if (sem->sem_impl->sem == SEM_FAILED) { if (sem->sem_impl->name) free(sem->sem_impl->name); free(sem->sem_impl); D(("POSIX semaphore creation failed: %s\n", strerror(errno))); D_RETURN_(FALSE); } D_RETURN_(TRUE); } void __bro_sem_cleanup(BroSem *sem) { D_ENTER; if (! sem || ! sem->sem_impl) D_RETURN; sem_unlink(sem->sem_impl->name); free(sem->sem_impl->name); free(sem->sem_impl); memset(sem, 0, sizeof(BroSem)); D_RETURN; } int __bro_sem_attach(BroSem *sem) { /* Unused in Posix. */ return TRUE; sem = NULL; } int __bro_sem_detach(BroSem *sem) { if (! sem || ! sem->sem_impl) return FALSE; sem_close(sem->sem_impl->sem); return TRUE; } int __bro_sem_decr(BroSem *sem) { D_ENTER; if (! sem || ! sem->sem_impl) D_RETURN_(FALSE); sem->sem_blocked++; if (sem_wait(sem->sem_impl->sem) < 0) { D(("sem_wait() error: %s\n", strerror(errno))); sem->sem_blocked--; D_RETURN_(FALSE); } sem->sem_blocked--; D_RETURN_(TRUE); } int __bro_sem_trydecr(BroSem *sem) { if (! sem || ! sem->sem_impl) return FALSE; sem->sem_blocked++; if (sem_trywait(sem->sem_impl->sem) < 0) { sem->sem_blocked--; if (errno == EAGAIN) return FALSE; D(("sem_wait() error: %s\n", strerror(errno))); return FALSE; } sem->sem_blocked--; return TRUE; } int __bro_sem_incr(BroSem *sem) { D_ENTER; if (! sem || ! sem->sem_impl) D_RETURN_(FALSE); if (sem_post(sem->sem_impl->sem) < 0) { D(("sem_post() error: %s\n", strerror(errno))); D_RETURN_(FALSE); } D_RETURN_(TRUE); } int __bro_sem_get(BroSem *sem, int *result) { if (! sem || ! sem->sem_impl || ! result) return FALSE; if (! sem_getvalue(sem->sem_impl->sem, result)) return FALSE; return TRUE; } int __bro_sem_get_blocked(BroSem *sem, int *result) { if (! sem || ! sem->sem_impl || ! result) return FALSE; *result = sem->sem_blocked; return TRUE; } broccoli-1.97-minimal/src/bro_type.h0000664002342100234210000000743112523041064017275 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_type_h #define broccoli_type_h #include #include /* Internal types used to represent a Bro type. * Taken from Type.h. */ #define BRO_INTTYPE_INT 1 #define BRO_INTTYPE_UNSIGNED 2 #define BRO_INTTYPE_DOUBLE 3 #define BRO_INTTYPE_STRING 4 #define BRO_INTTYPE_IPADDR 5 #define BRO_INTTYPE_SUBNET 6 #define BRO_INTTYPE_OTHER 7 #define BRO_INTTYPE_ERROR 8 /* typedefs are in bro_types.h */ struct bro_type { BroObject object; char tag; char internal_tag; char is_nbo; char is_base_type; /* Whether or not this is a complete type object or * just the name of type. In the latter case, type_name * (below) will contain the name of the type. */ char is_complete; BroString type_name; }; struct bro_type_list { BroType type; uint32 num_types; BroList *types; BroType *pure_type; }; struct bro_record_type { BroType type; uint32 num_fields; uint32 num_types; BroList *type_decls; }; struct bro_index_type { BroType type; BroTypeList *indices; BroType *yield_type; /* optional */ }; struct bro_table_type { BroIndexType type; }; struct bro_set_type { BroTableType type; }; struct bro_file_type { BroType type; BroType *yield; }; struct bro_enum_type { BroType type; BroHT *names; uint64 counter; }; struct bro_vector_type { BroType type; BroType *yield; }; BroType *__bro_type_new(void); BroType *__bro_type_new_of_type(int type, const char *type_name); void __bro_type_set_incomplete_impl(BroType *type, const BroString *type_name); BroTypeList *__bro_type_list_new(void); BroRecordType *__bro_record_type_new(void); void __bro_record_type_add_type(BroRecordType *rt, const char *field, BroType *type); const char *__bro_record_type_get_nth_field(BroRecordType *rt, int num); BroIndexType *__bro_index_type_new(void); void __bro_index_type_set_indices(BroIndexType *it, BroTypeList *indices); void __bro_index_type_set_yield_type(BroIndexType *it, BroType *yield_type); BroTableType *__bro_table_type_new(void); BroSetType *__bro_set_type_new(); BroEnumType *__bro_enum_type_new(void); BroFileType *__bro_file_type_new(void); BroVectorType *__bro_vector_type_new(void); #endif broccoli-1.97-minimal/src/bro_config.h0000664002342100234210000000365612523041064017566 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_config_h #define broccoli_config_h void __bro_conf_init(void); void __bro_conf_set_domain(const char *domain); void __bro_conf_set_storage_domain(const char *domain); const char *__bro_conf_get_domain(void); void __bro_conf_add_int(const char *val_name, int val); void __bro_conf_add_dbl(const char *val_name, double val); void __bro_conf_add_str(const char *val_name, char *val); int __bro_conf_get_int(const char *val_name, int *val); int __bro_conf_get_dbl(const char *val_name, double *val); const char * __bro_conf_get_str(const char *val_name); int __bro_conf_forget_item(const char *val_name); #endif broccoli-1.97-minimal/src/bro_shm.h0000664002342100234210000000325312523041064017101 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_shm_h #define broccoli_shm_h #include #include typedef struct bro_shared_mem BroSharedMem; BroSharedMem *__bro_shm_new(int size); void __bro_shm_free(BroSharedMem *shm); int __bro_shm_attach(BroSharedMem *shm); int __bro_shm_detach(BroSharedMem *shm); void *__bro_shm_get_mem(const BroSharedMem *shm); int __bro_shm_get_size(const BroSharedMem *shm); #endif broccoli-1.97-minimal/src/bro_util.h0000664002342100234210000000417212523041064017270 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_util_h #define broccoli_util_h #include #if HAVE_CONFIG_H # include #endif #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif int __bro_util_snprintf(char *str, size_t size, const char *format, ...); void __bro_util_fill_v4_addr(BroAddr *a, uint32 addr); void __bro_util_fill_subnet(BroSubnet *sn, uint32 net, uint32 width); double __bro_util_get_time(void); double __bro_util_timeval_to_double(const struct timeval *tv); int __bro_util_is_v4_addr(const BroAddr* a); #ifdef WORDS_BIGENDIAN #define __bro_util_ntohd(x) x #define __bro_util_htond(x) x #define __bro_util_ntohll(x) x #define __bro_util_htonll(x) x #else double __bro_util_htond(double d); double __bro_util_ntohd(double d); uint64 __bro_util_htonll(uint64 i); uint64 __bro_util_ntohll(uint64 i); #endif #endif broccoli-1.97-minimal/src/bro_shm_sysv.c0000664002342100234210000000546312523041064020165 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include struct bro_shared_mem { int shm_id; int shm_size; void *shm_mem; int shm_attached; }; BroSharedMem * __bro_shm_new(int size) { int shm_id; BroSharedMem *shm; if (size <= 0) return NULL; if ( (shm_id = shmget(IPC_PRIVATE,size, IPC_CREAT|IPC_EXCL|S_IRWXU)) < 0) { D(("shmget error: %s\n", strerror(errno))); return NULL; } if (! (shm = calloc(1, sizeof(BroSharedMem)))) return NULL; shm->shm_id = shm_id; shm->shm_size = size; return shm; } void __bro_shm_free(BroSharedMem *shm) { if (! shm) return; shmctl(shm->shm_id, IPC_RMID, NULL); free(shm); } void * __bro_shm_get_mem(const BroSharedMem *shm) { if (! shm || ! shm->shm_attached) return NULL; return shm->shm_mem; } int __bro_shm_get_size(const BroSharedMem *shm) { return shm->shm_size; } int __bro_shm_attach(BroSharedMem *shm) { if (! shm) return FALSE; shm->shm_mem = shmat(shm->shm_id, NULL, 0); if ((int) shm->shm_mem == -1) { D(("shmat problem: %s.\n", strerror(errno))); return FALSE; } shm->shm_attached = TRUE; return TRUE; } int __bro_shm_detach(BroSharedMem *shm) { if (! shm || ! shm->shm_attached) return FALSE; if (shmdt(shm->shm_mem) < 0) { D(("shmdt problem: %s.\n", strerror(errno))); return FALSE; } return TRUE; } broccoli-1.97-minimal/src/bro_util.c0000664002342100234210000000735412523041064017270 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #ifdef __EMX__ #include #endif #include #ifdef __MINGW32__ /* MinGW does not define a gettimeofday so we need to roll our own. * This one is largely following * http://lists.gnu.org/archive/html/bug-gnu-chess/2004-01/msg00020.html */ static int gettimeofday(struct timeval* p, void* tz /* IGNORED */){ union { long long ns100; /*time since 1 Jan 1601 in 100ns units */ FILETIME ft; } _now; GetSystemTimeAsFileTime( &(_now.ft) ); p->tv_usec=(long)((_now.ns100 / 10LL) % 1000000LL ); p->tv_sec= (long)((_now.ns100-(116444736000000000LL))/10000000LL); return 0; } #endif int __bro_util_snprintf(char *str, size_t size, const char *format, ...) { int result; va_list al; va_start(al, format); result = vsnprintf(str, size, format, al); va_end(al); str[size-1] = '\0'; return result; } void __bro_util_fill_v4_addr(BroAddr *a, uint32 addr) { if ( ! a ) return; memcpy(a->addr, BRO_IPV4_MAPPED_PREFIX, sizeof(BRO_IPV4_MAPPED_PREFIX)); a->addr[3] = addr; } void __bro_util_fill_subnet(BroSubnet *sn, uint32 net, uint32 width) { if (! sn) return; __bro_util_fill_v4_addr(&sn->sn_net, net); sn->sn_width = width; } double __bro_util_get_time(void) { struct timeval tv; if (gettimeofday(&tv, 0) < 0) return 0.0; return __bro_util_timeval_to_double(&tv); } double __bro_util_timeval_to_double(const struct timeval *tv) { if (! tv) return 0.0; return ((double) tv->tv_sec) + ((double) tv->tv_usec) / 1000000; } int __bro_util_is_v4_addr(const BroAddr *a) { return memcmp(a->addr, BRO_IPV4_MAPPED_PREFIX, sizeof(BRO_IPV4_MAPPED_PREFIX)) == 0; } #ifndef WORDS_BIGENDIAN double __bro_util_htond(double d) { /* Should work as long as doubles have an even length */ int i, dsize; double tmp; char* src = (char*) &d; char* dst = (char*) &tmp; dsize = sizeof(d) - 1; for (i = 0; i <= dsize; i++) dst[i] = src[dsize - i]; return tmp; } double __bro_util_ntohd(double d) { return __bro_util_htond(d); } uint64 __bro_util_htonll(uint64 i) { uchar c; union { uint64 i; uchar c[8]; } x; x.i = i; c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; return x.i; } uint64 __bro_util_ntohll(uint64 i) { return __bro_util_htonll(i); } #endif broccoli-1.97-minimal/src/bro_record.c0000664002342100234210000001625412523041064017570 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include BroRecord * __bro_record_new(void) { BroRecord *rec; if (! (rec = calloc(1, sizeof(BroRecord)))) return NULL; return rec; } void __bro_record_free(BroRecord *rec) { BroList *l; if (! rec) return; for (l = rec->val_list; l; l = __bro_list_next(l)) { char *field; BroSObject *obj = __bro_list_data(l); if ( (field = __bro_sobject_data_del(obj, "field"))) free(field); __bro_sobject_release(obj); } __bro_list_free(rec->val_list, NULL); free(rec); } int __bro_record_get_length(BroRecord *rec) { D_ENTER; if (! rec) D_RETURN_(0); D_RETURN_(rec->val_len); } BroRecord * __bro_record_copy(BroRecord *rec) { BroList *l; BroVal *val, *val_copy; BroRecord *copy; D_ENTER; if (! rec) D_RETURN_(NULL); if (! (copy = __bro_record_new())) D_RETURN_(NULL); for (l = rec->val_list; l; l = __bro_list_next(l)) { char *field; val = __bro_list_data(l); /* Check if it's an assigned val or not */ if (! val->val_type) { D(("Error: unassigned val in record.\n")); goto error_return; } if (! (val_copy = (BroVal *) __bro_sobject_copy((BroSObject *) val))) goto error_return; #ifdef BRO_DEBUG if (! val_copy->val_type) D(("WARNING -- typeless val duplicated as %p, original %p had type %p\n", val_copy, val, val->val_type)); #endif if (! (field = __bro_sobject_data_get((BroSObject *) val, "field"))) { D(("Val %p in record %p doesn't have a field name.\n", val, rec)); goto error_return; } __bro_sobject_data_set((BroSObject *) val_copy, "field", strdup(field)); __bro_record_add_val(copy, val_copy); } D_RETURN_(copy); error_return: __bro_record_free(copy); D_RETURN_(NULL); } void __bro_record_add_val(BroRecord *rec, BroVal *val) { if (! rec || ! val) return; rec->val_list = __bro_list_append(rec->val_list, val); rec->val_len++; } BroVal * __bro_record_get_nth_val(BroRecord *rec, int num) { BroList *l; if (! rec || num < 0 || num >= rec->val_len) return NULL; if( (l = __bro_list_nth(rec->val_list, num))) return __bro_list_data(l); return NULL; } const char * __bro_record_get_nth_name(BroRecord *rec, int num) { BroList *l; if (! rec || num < 0 || num >= rec->val_len) return NULL; if( (l = __bro_list_nth(rec->val_list, num))) return __bro_sobject_data_get((BroSObject *) __bro_list_data(l), "field"); return NULL; } BroVal * __bro_record_get_named_val(BroRecord *rec, const char *name) { BroList *l; BroVal *val; if (! rec || ! name || ! *name) return NULL; for (l = rec->val_list; l; l = __bro_list_next(l)) { char *val_name; val = __bro_list_data(l); val_name = __bro_sobject_data_get((BroSObject *) val, "field"); if (val_name && ! strcmp(val_name, name)) return val; } return NULL; } int __bro_record_set_nth_val(BroRecord *rec, int num, BroVal *v) { BroVal *val; BroList *l; if (! rec || num < 0 || num >= rec->val_len || ! v) return FALSE; if ( (l = __bro_list_nth(rec->val_list, num))) { val = __bro_list_set_data(l, v); __bro_sobject_release((BroSObject *) val); return TRUE; } return FALSE; } int __bro_record_set_nth_name(BroRecord *rec, int num, const char *name) { BroVal *val; BroList *l; if (! rec || num < 0 || num >= rec->val_len || ! name) return FALSE; if ( (l = __bro_list_nth(rec->val_list, num))) { char *val_name; val = __bro_list_data(l); val_name = __bro_sobject_data_del((BroSObject *) val, "field"); if (val_name) free(val_name); __bro_sobject_data_set((BroSObject *) val, "field", strdup(name)); return TRUE; } return FALSE; } int __bro_record_set_named_val(BroRecord *rec, const char *name, BroVal *v) { BroVal *val; BroList *l; if (! rec || ! name || !*name || ! v) return FALSE; for (l = rec->val_list; l; l = __bro_list_next(l)) { char *val_name; val = __bro_list_data(l); val_name = __bro_sobject_data_get((BroSObject *) val, "field"); if (val_name && ! strcmp(val_name, name)) { /* We're about to delete the old val, make sure it doesn't have * the name tag associated with it. */ __bro_sobject_data_del((BroSObject *) val, "field"); free(val_name); /* If the new val has a name tag, likewise delete it. */ if ( (val_name = __bro_sobject_data_del((BroSObject *) val, "field"))) free(val_name); /* Set the new val's name tag */ __bro_sobject_data_set((BroSObject *) v, "field", strdup(name)); __bro_list_set_data(l, v); __bro_sobject_release((BroSObject *) val); return TRUE; } } return FALSE; } uint32 __bro_record_hash(BroRecord *rec) { uint32 result; BroList *l; D_ENTER; if (! rec) D_RETURN_(0); result = rec->val_len; for (l = rec->val_list; l; l = __bro_list_next(l)) result ^= __bro_sobject_hash((BroSObject*) __bro_list_data(l)); D_RETURN_(result); } int __bro_record_cmp(BroRecord *rec1, BroRecord *rec2) { BroList *l1, *l2; D_ENTER; if (! rec1 || ! rec2) D_RETURN_(FALSE); if (rec1->val_len != rec2->val_len) D_RETURN_(FALSE); for (l1 = rec1->val_list, l2 = rec2->val_list; l1 && l2; l1 = __bro_list_next(l1), l2 = __bro_list_next(l2)) { if (! __bro_sobject_cmp((BroSObject*) __bro_list_data(l1), (BroSObject*) __bro_list_data(l2))) D_RETURN_(FALSE); } if (l1 || l2) { D(("WARNING -- value list inconsistency.\n")); D_RETURN_(FALSE); } D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_object.h0000664002342100234210000000376212523041064017565 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_object_h #define broccoli_object_h #include #include typedef struct bro_object { /* See comments in bro_sobject.h for how Broccoli models * classes, objects, and inheritance. --cpk */ BroSObject sobject; BroLoc *loc; } BroObject; BroObject *__bro_object_new(void); void __bro_object_init(BroObject *obj); void __bro_object_free(BroObject *obj); int __bro_object_read(BroObject *obj, BroConn *bc); int __bro_object_write(BroObject *obj, BroConn *bc); int __bro_object_clone(BroObject *dst, BroObject *src); uint32 __bro_object_hash(BroObject *obj); int __bro_object_cmp(BroObject *obj1, BroObject *obj2); #endif broccoli-1.97-minimal/src/broccoli.h.in0000664002342100234210000015326112523041064017656 0ustar johannajohanna/*! @mainpage Broccoli: The Bro Client Communications Library * See broccoli.h for the main API reference. */ /* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2007 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_h #define broccoli_h #include #include #include #include #ifdef __MINGW32__ #include #else #include #endif #include #ifdef __cplusplus extern "C" { #endif /** * bro_debug_calltrace - Debugging output switch for call tracing. * * If you have debugging support built in (i.e., your package was configured * with --enable-debug), you can enable/disable debugging output for * call tracing by setting this to 0 (off) or 1 (on). Default is off. */ extern int bro_debug_calltrace; /** * bro_debug_messages - Output switch for debugging messages. * * If you have debugging support built in (i.e., your package was configured * with --enable-debug), you can enable/disable debugging messages * by setting this to 0 (off) or 1 (on). Default is off. */ extern int bro_debug_messages; #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif /* Numeric values of Bro type identifiers, corresponding * to the values of the TypeTag enum in Bro's Type.h. Use * these values with bro_event_add_val(), bro_record_add_val(), * bro_record_get_nth_val() and bro_record_get_named_val(). */ /** * * BRO_TYPE_UNKNOWN is not used in the data exchange, * see bro_record_get_{nth,named}_val() for its use. */ #define BRO_TYPE_UNKNOWN 0 #define BRO_TYPE_BOOL 1 #define BRO_TYPE_INT 2 #define BRO_TYPE_COUNT 3 #define BRO_TYPE_COUNTER 4 #define BRO_TYPE_DOUBLE 5 #define BRO_TYPE_TIME 6 #define BRO_TYPE_INTERVAL 7 #define BRO_TYPE_STRING 8 #define BRO_TYPE_PATTERN 9 #define BRO_TYPE_ENUM 10 #define BRO_TYPE_TIMER 11 #define BRO_TYPE_PORT 12 #define BRO_TYPE_IPADDR 13 #define BRO_TYPE_SUBNET 14 #define BRO_TYPE_ANY 15 #define BRO_TYPE_TABLE 16 #define BRO_TYPE_UNION 17 #define BRO_TYPE_RECORD 18 #define BRO_TYPE_LIST 19 #define BRO_TYPE_FUNC 20 #define BRO_TYPE_FILE 21 #define BRO_TYPE_VECTOR 22 #define BRO_TYPE_ERROR 23 #define BRO_TYPE_PACKET 24 /* CAUTION -- not defined in Bro! */ #define BRO_TYPE_SET 25 /* CAUTION -- not defined in Bro! */ #define BRO_TYPE_MAX 26 /* Flags for new connections, to pass to bro_conn_new() * and bro_conn_new_str(). See manual for details. */ #define BRO_CFLAG_NONE 0 #define BRO_CFLAG_RECONNECT (1 << 0) /**< Attempt transparent reconnects */ #define BRO_CFLAG_ALWAYS_QUEUE (1 << 1) /**< Queue events sent while disconnected */ #define BRO_CFLAG_SHAREABLE (1 << 2) /**< DO NOT USE -- no longer supported */ #define BRO_CFLAG_DONTCACHE (1 << 3) /**< Ask peer not to use I/O cache (default) */ #define BRO_CFLAG_YIELD (1 << 4) /**< Process just one event at a time */ #define BRO_CFLAG_CACHE (1 << 5) /**< Ask peer to use I/O cache */ /* ---------------------------- Typedefs ----------------------------- */ @TYPEDEF_UINT@ typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; typedef unsigned char uchar; typedef struct bro_conn BroConn; typedef struct bro_event BroEvent; typedef struct bro_buf BroBuf; typedef struct bro_record BroRecord; typedef struct bro_table BroTable; typedef struct bro_table BroSet; typedef struct bro_vector BroVector; typedef struct bro_ev_meta BroEvMeta; typedef struct bro_packet BroPacket; /* ----------------------- Callback Signatures ----------------------- */ /** * BroEventFunc - The signature of expanded event callbacks. * @param bc Bro connection handle. * @param user_data user data provided to bro_event_registry_add(). * @param ... varargs. * * This is the signature of callbacks for handling received * Bro events, called in the argument-expanded style. For details * see bro_event_registry_add(). */ typedef void (*BroEventFunc) (BroConn *bc, void *user_data, ...); /** * BroCompactEventFunc - The signature of compact event callbacks. * @param bc Bro connection handle. * @param user_data user data provided to bro_event_registry_add_compact(). * @param meta metadata for the event. * * This is the signature of callbacks for handling received * Bro events, called in the compact-argument style. For details * see bro_event_registry_add_compact(). */ typedef void (*BroCompactEventFunc) (BroConn *bc, void *user_data, BroEvMeta *meta); typedef void (*BroPacketFunc) (BroConn *bc, void *user_data, const BroPacket *packet); /** * OpenSSL_lockfunc - locking function for OpenSSL thread safeness. * @param mode acquire nth lock if (mode & CRYPTO_LOCK) is true, release otherwise. * @param n lock index. You need to support at least CRYPTO_num_locks(). * @param file file from which OpenSSL invokes the callback. * @param line line in file from which OpenSSL invokes the callback. * * If you are using Broccoli in a multithreaded environment, you need * to use bro_init() with a BroCtx structure and use it to point at an * implementation of this callback. Refer to pages 74ff in O'Reilly's * OpenSSL book (by Viega et al.) for details. You could also look at * * http://www.openssl.org/support/faq.html#PROG1 * http://www.openssl.org/docs/crypto/threads.html * * but you will only curse OpenSSL even more than you already do after * reading those. */ typedef void (*OpenSSL_lock_func) (int mode, int n, const char *file, int line); /** * OpenSSL_thread_id_func - thread ID function for OpenSSL thread safeness. * @param id target pointer into which the current thread's numeric ID must be written. * * Please refer to pages 74ff in O'Reilly's OpenSSL book, and also see * the comments for OpenSSL_lockfunc(). */ typedef unsigned long (*OpenSSL_thread_id_func) (void); /** * OpenSSL_dynlock_create_func - allocator for dynamic locks, for OpenSSL thread safeness. * @param file file from which OpenSSL invokes the callback. * @param line line in file from which OpenSSL invokes the callback. * * Please refer to pages 74ff in O'Reilly's OpenSSL book, and also see * the comments for OpenSSL_lockfunc(). */ typedef struct CRYPTO_dynlock_value* (*OpenSSL_dynlock_create_func) (const char *file, int line); /** * OpenSSL_dynlock_lock_func - lock/unlock dynamic locks, for OpenSSL thread safeness. * @param mode acquire nth lock if (mode & CRYPTO_LOCK) is true, release otherwise. * @param mutex lock to lock/unlock. * @param file file from which OpenSSL invokes the callback. * @param line line in file from which OpenSSL invokes the callback. * * Please refer to pages 74ff in O'Reilly's OpenSSL book, and also see * the comments for OpenSSL_lockfunc(). */ typedef void (*OpenSSL_dynlock_lock_func) (int mode, struct CRYPTO_dynlock_value *mutex, const char *file, int line); /** * OpenSSL_dynlock_free_func - dynamic lock deallocator, for OpenSSL thread safeness. * @param mutex lock to deallocate. * @param file file from which OpenSSL invokes the callback. * @param line line in file from which OpenSSL invokes the callback. * * Please refer to pages 74ff in O'Reilly's OpenSSL book, and also see * the comments for OpenSSL_lockfunc(). */ typedef void (*OpenSSL_dynlock_free_func) (struct CRYPTO_dynlock_value *mutex, const char *file, int line); /* ---------------------------- Structures --------------------------- */ /** Initialization context for the Broccoli library. */ typedef struct bro_ctx { OpenSSL_lock_func lock_func; OpenSSL_thread_id_func id_func; OpenSSL_dynlock_create_func dl_create_func; OpenSSL_dynlock_lock_func dl_lock_func; OpenSSL_dynlock_free_func dl_free_func; } BroCtx; /** Statistical properties of a given connection. */ typedef struct bro_conn_stats { int tx_buflen; ///< Number of bytes to process in output buffer. int rx_buflen; ///< Number of bytes to process in input buffer. } BroConnStats; /** BroStrings are used to access string parameters in received events. */ typedef struct bro_string { uint32 str_len; uchar *str_val; } BroString; /** Ports in Broccoli do not only consist of a number but also indicate * whether they are TCP or UDP. */ typedef struct bro_port { uint64 port_num; /**< Port number in host byte order */ int port_proto; /**< IPPROTO_xxx */ } BroPort; /** IP addresses are 16-bytes in network byte order. * IPv4 addresses use the standard IPv4-in-IPv6 mapping: 10 bytes off, 2 bytes * on, then 4 bytes of the address. */ typedef struct bro_addr { uint32 addr[4]; /**< IP address in network byte order */ } BroAddr; /** Subnets are a 16-byte address with a prefix width in bits. */ typedef struct bro_subnet { BroAddr sn_net; /**< IP address in network byte order */ uint32 sn_width; /**< Length of prefix to consider. */ } BroSubnet; /** Encapsulation of arguments passed to an event callback, * for the compact style of argument passing. */ typedef struct bro_ev_arg { void *arg_data; /**< Pointer to the actual event argument */ int arg_type; /**< A BRO_TYPE_xxx constant */ } BroEvArg; /** Metadata for an event, passed to callbacks of the BroCompactEventFunc * prototype. */ struct bro_ev_meta { const char *ev_name; /**< The name of the event */ double ev_ts; /**< Timestamp of event, taken from BroEvent itself */ int ev_numargs;/**< How many arguments are passed */ BroEvArg *ev_args; /**< Array of BroEvArgs, one for each argument */ const uchar *ev_start; /**< Start pointer to serialized version of currently processed event */ const uchar *ev_end; /**< End pointer to serialized version of currently processed event */ }; #cmakedefine BRO_PCAP_SUPPORT #ifdef BRO_PCAP_SUPPORT #include /** Broccoli can send and receive pcap-captured packets, wrapped into * the following structure: */ struct bro_packet { double pkt_time; uint32 pkt_hdr_size; uint32 pkt_link_type; struct pcap_pkthdr pkt_pcap_hdr; const u_char *pkt_data; const char *pkt_tag; }; #endif /* ============================ API ================================== */ /* -------------------------- Initialization ------------------------- */ /** * bro_init - Initializes the library. * @param ctx pointer to a BroCtx structure. * * The function initializes the library. It MUST be called before * anything else in Broccoli. Specific initialization context may be * provided using a BroCtx structure pointed to by ctx. It may be * omitted by passing %NULL, for default values. See bro_init_ctx() for * initialization of the context structure to default values. * * @returns %TRUE if initialization succeeded, %FALSE otherwise. */ int bro_init(const BroCtx *ctx); /** * bro_ctx_init - Initializes initialization context to default values. * @param ctx pointer to a BroCtx structure. */ void bro_ctx_init(BroCtx *ctx); /* ----------------------- Connection Handling ----------------------- */ /** * bro_conn_new - Creates and returns a handle for a connection to a remote Bro. * @param ip_addr 4-byte IP address of Bro to contact, in network byte order. * @param port port of machine at @p ip_addr to contact, in network byte order. * @param flags an or-combination of the %BRO_CONN_xxx flags. * * The function creates a new Bro connection handle for communication with * Bro through a network. Depending on the flags passed in, the connection * and its setup process can be adjusted. If you don't want to pass any * flags, use %BRO_CFLAG_NONE. * * @returns pointer to a newly allocated and initialized * Bro connection structure. You need this structure for all * other calls in order to identify the connection to Bro. */ BroConn *bro_conn_new(struct in_addr *ip_addr, uint16 port, int flags); /** * bro_conn_new6 - Creates and returns a handle for a connection to a remote Bro. * @param ip_addr 16-byte IPv6 address of Bro to contact, in network byte order. * @param port port of machine at @p ip_addr to contact, in network byte order. * @param flags an or-combination of the %BRO_CONN_xxx flags. * * The function creates a new Bro connection handle for communication with * Bro through a network. Depending on the flags passed in, the connection * and its setup process can be adjusted. If you don't want to pass any * flags, use %BRO_CFLAG_NONE. * * @returns pointer to a newly allocated and initialized * Bro connection structure. You need this structure for all * other calls in order to identify the connection to Bro. */ BroConn *bro_conn_new6(struct in6_addr *ip_addr, uint16 port, int flags); /** * bro_conn_new_str - Same as bro_conn_new(), but accepts strings for hostname and port. * @param hostname string describing the host and port to connect to. * @param flags an or-combination of the %BRO_CONN_xxx flags. * * The function is identical to bro_conn_new(), but allows you to specify the * host and port to connect to in a string as ":". @p flags can * be used to adjust the connection features and the setup process. If you don't * want to pass any flags, use %BRO_CFLAG_NONE. * * @returns pointer to a newly allocated and initialized * Bro connection structure. You need this structure for all * other calls in order to identify the connection to Bro. */ BroConn *bro_conn_new_str(const char *hostname, int flags); /** * bro_conn_new_socket - Same as bro_conn_new(), but uses existing socket. * @param socket open socket. * @param flags an or-combination of the %BRO_CONN_xxx flags. * * The function is identical to bro_conn_new(), but allows you to pass in an * open socket to use for the communication. @p flags can be used to * adjust the connection features and the setup process. If you don't want to * pass any flags, use %BRO_CFLAG_NONE. * * @returns pointer to a newly allocated and initialized * Bro connection structure. You need this structure for all * other calls in order to identify the connection to Bro. */ BroConn *bro_conn_new_socket(int socket, int flags); /** * bro_conn_set_class - Sets a connection's class identifier. * @param bc connection handle. * @param classname class identifier. * * Broccoli connections can indicate that they belong to a certain class * of connections, which is needed primarily if multiple Bro/Broccoli * instances are running on the same node and connect to a single remote * peer. You can set this class with this function, and you have to do so * before calling bro_connect() since the connection class is determined * upon connection establishment. You remain responsible for the memory * pointed to by @p classname. */ void bro_conn_set_class(BroConn *bc, const char *classname); /** * bro_conn_get_peer_class - Reports connection class indicated by peer. * @param bc connection handle. * * @returns a string containing the connection class indicated by the peer, * if any, otherwise %NULL. */ const char *bro_conn_get_peer_class(const BroConn *bc); /** * bro_conn_get_connstats - Reports connection properties. * @param bc connection handle. * @param cs BroConnStats handle. * * The function fills the BroConnStats structure provided via @p cs with * information about the given connection. */ void bro_conn_get_connstats(const BroConn *bc, BroConnStats *cs); /** * bro_conn_connect - Establish connection to peer. * @param bc connection handle. * * The function attempts to set up and configure a connection to * the peer configured when the connection handle was obtained. * * @returns %TRUE on success, %FALSE on failure. */ int bro_conn_connect(BroConn *bc); /** * bro_conn_reconnect - Drop the current connection and reconnect, reusing all settings. * @param bc Bro connection handle. * * The functions drops the current connection identified by @p bc and attempts * to establish a new one with all the settings associated with @p bc, * including full handshake completion. * * @returns %TRUE if successful, %FALSE otherwise. No matter what the outcome, * you can continue to use @p bc as normal (e.g. you have to release it using * bro_conn_delete()). */ int bro_conn_reconnect(BroConn *bc); /** * bro_conn_delete - terminates and releases connection. * @param bc Bro connection handle. * * This function will terminate the given connection if necessary * and release all resources associated with the connection handle. * * * @returns %FALSE on error, %TRUE otherwise. */ int bro_conn_delete(BroConn *bc); /** * bro_conn_alive - Reports whether a connection is currently alive or has died. * @param bc Bro connection handle. * This predicate reports whether the connection handle is currently * usable for sending/receiving data or not, e.g. because the peer * died. The function does not actively check and update the * connection's state, it only reports the value of flags indicating * its status. In particular, this means that when calling * bro_conn_alive() directly after a select() on the connection's * descriptor, bro_conn_alive() may return an incorrent value. It will * however return the correct value after a subsequent call to * bro_conn_process_input(). Also note that the connection is also * dead after the connection handle is obtained and before * bro_conn_connect() is called. * * @returns %TRUE if the connection is alive, %FALSE otherwise. */ int bro_conn_alive(const BroConn *bc); /** * bro_conn_adopt_events - Makes one connection send out the same events as another. * @param src Bro connection handle for connection whose event list to adopt. * @param dst Bro connection handle for connection whose event list to change. * * The function makes the connection identified by @p dst use the same event * mask as the one identified by @p src. */ void bro_conn_adopt_events(BroConn *src, BroConn *dst); /** * bro_conn_get_fd - Returns file descriptor of a Bro connection. * @param bc Bro connection handle. * * If you need to know the file descriptor of the connection * (such as when select()ing it, etc.), use this accessor function. * * @returns file descriptor for connection @p bc, or negative value * on error. */ int bro_conn_get_fd(BroConn *bc); /** * bro_conn_process_input - Processes input sent to the sensor by Bro. * @param bc Bro connection handle. * * The function reads all input sent to the local sensor by the * Bro peering at the connection identified by @p bc. It is up * to you to find a spot in the application you're instrumenting * to make sure this is called. This function cannot block. * bro_conn_alive() will report the actual state of the connection * after a call to bro_conn_process_input(). * * @returns %TRUE if any input was processed, %FALSE otherwise. */ int bro_conn_process_input(BroConn *bc); /* ---------------------- Connection data storage -------------------- */ /* Connection handles come with a faciity to store and retrieve * arbitrary data items. Use the following functions to store, * query, and remove items from a connection handle. */ /** * bro_conn_data_set - Puts a data item into the registry. * @param bc Bro connection handle. * @param key name of the data item. * @param val data item. * * The function stores @p val under name @p key in the connection handle @p bc. * @p key is copied internally so you do not need to duplicate it before * passing. */ void bro_conn_data_set(BroConn *bc, const char *key, void *val); /** * bro_conn_data_get - Looks up a data item. * @param bc Bro connection handle. * @param key name of the data item. * * The function tries to look up the data item with name @p key and * if found, returns it. * * @returns data item if lookup was successful, %NULL otherwise. */ void *bro_conn_data_get(BroConn *bc, const char *key); /** * bro_conn_data_del - Removes a data item. * @param bc Bro connection handle. * @param key name of the data item. * * The function tries to remove the data item with name @p key. * * @returns the removed data item if it exists, %NULL otherwise. */ void *bro_conn_data_del(BroConn *bc, const char *key); /* ----------------------------- Bro Events -------------------------- */ /** * bro_event_new - Creates a new empty event with a given name. * @param event_name name of the Bro event. * * The function creates a new empty event with the given * name and returns it. * * @returns new event, or %NULL if allocation failed. */ BroEvent *bro_event_new(const char *event_name); /** * bro_event_free - Releases all memory associated with an event. * @param be event to release. * * The function releases all memory associated with @p be. Note * that you do NOT have to call this after sending an event. */ void bro_event_free(BroEvent *be); /** * bro_event_add_val - Adds a parameter to an event. * @param be event to add to. * @param type numerical type identifier (a %BRO_TYPE_xxx constant). * @param type_name optional name of specialized type. * @param val value to add to event. * * The function adds the given @p val to the argument list of * event @p be. The type of @p val is derived from @p type, and may be * specialized to the type named @p type_name. If @p type_name is not * desired, use %NULL. * * @p val remains the caller's responsibility and is copied internally. * * @returns %TRUE if the operation was successful, %FALSE otherwise. */ int bro_event_add_val(BroEvent *be, int type, const char *type_name,const void *val); /** * bro_event_set_val - Replace a value in an event. * @param be event handle. * @param val_num number of the value to replace, starting at 0. * @param type numerical type identifier (a %BRO_TYPE_xxx constant). * @param type_name optional name of specialized type. * @param val value to put in. * * The function replaces whatever value is currently stored in the * event pointed to by @p be with the value specified through the @p type and * @p val arguments. If the event does not currently hold enough * values to replace one in position @p val_num, the function does * nothing. If you want to indicate a type specialized from @p type, * use @p type_name to give its name, otherwise pass %NULL for @p type_name. * * @returns %TRUE if successful, %FALSE on error. */ int bro_event_set_val(BroEvent *be, int val_num, int type, const char *type_name, const void *val); /** * bro_event_send - Tries to send an event to a Bro agent. * @param bc Bro connection handle. * @param be event to send. * * The function tries to send @p be to the Bro agent connected * through @p bc. Regardless of the outcome, you do NOT have * to release the event afterwards using bro_event_free(). * * @returns %TRUE if the event got sent or queued for later transmission, * %FALSE on error. There are no automatic repeated send attempts * (to minimize the effect on the code that Broccoli is linked to). * If you have to make sure that everything got sent, you have * to try to empty the queue using bro_event_queue_flush(), and * also look at bro_event_queue_empty(). */ int bro_event_send(BroConn *bc, BroEvent *be); /** * bro_event_send_raw - Enqueues a serialized event directly into a connection's send buffer. * @param bc Bro connection handle. * @param data pointer to serialized event data. * @param data_len length of buffer pointed to by @p data. * * The function enqueues the given event data into @p bc's transmit buffer. * @p data_len bytes at @p data must correspond to a single event. * * @returns %TRUE if successful, %FALSE on error. */ int bro_event_send_raw(BroConn *bc, const uchar *data, int data_len); /** * bro_event_queue_length - Returns current queue length. * @param bc Bro connection handle. * * Use this function to find out how many events are currently queued * on the client side. * * @returns number of items currently queued. */ int bro_event_queue_length(BroConn *bc); /** * bro_event_queue_length_max - Returns maximum queue length. * @param bc Bro connection handle. * * Use this function to find out how many events can be queued before * events start to get dropped. * * @returns maximum possible queue size. */ int bro_event_queue_length_max(BroConn *bc); /** * bro_event_queue_flush - Tries to flush the send queue of a connection. * @param bc Bro connection handle. * * The function tries to send as many queued events to the Bro * agent as possible. * * @returns remaining queue length after flush. */ int bro_event_queue_flush(BroConn *bc); /* ------------------------ Bro Event Callbacks ---------------------- */ /** * bro_event_registry_add - Adds an expanded-argument event callback to the event registry. * @param bc Bro connection handle. * @param event_name Name of events that trigger callback. * @param func callback to invoke. * @param user_data user data passed through to the callback. * * This function registers the callback @p func to be invoked when events * of name @p event_name arrive on connection @p bc. @p user_data is passed * along to the callback, which will receive it as the second parameter. You * need to ensure that the memory @p user_data points to is valid during the * time the callback might be invoked. * * Note that this function only registers the callback in the state * associated with @p bc. If you use bro_event_registry_add() and @p bc * has not yet been connected via bro_conn_connect(), then no further * action is required. bro_conn_connect() requests any registered event types. * If however you are requesting additional event types after the connection has * been established, then you also need to call bro_event_registry_request() * in order to signal to the peering Bro that you want to receive those events. */ void bro_event_registry_add(BroConn *bc, const char *event_name, BroEventFunc func, void *user_data); /** * bro_event_registry_add_compact - Adds a compact-argument event callback to the event registry. * @param bc Bro connection handle. * @param event_name Name of events that trigger callback. * @param func callback to invoke. * @param user_data user data passed through to the callback. * * This function registers the callback @p func to be invoked when events * of name @p event_name arrive on connection @p bc. @p user_data is passed * along to the callback, which will receive it as the second parameter. You * need to ensure that the memory @p user_data points to is valid during the * time the callback might be invoked. See bro_event_registry_add() for * details. */ void bro_event_registry_add_compact(BroConn *bc, const char *event_name, BroCompactEventFunc func, void *user_data); /** * bro_event_registry_remove - Removes an event handler. * @param bc Bro connection handle. * @param event_name event to ignore from now on. * * The function removes all callbacks for event @p event_name from the * event registry for connection @p bc. */ void bro_event_registry_remove(BroConn *bc, const char *event_name); /** * bro_event_registry_request - Notifies peering Bro to send events. * @param bc Bro connection handle. * * The function requests the events you have previously requested using * bro_event_registry_add() from the Bro listening on @p bc. */ void bro_event_registry_request(BroConn *bc); /* ------------------------ Dynamic-size Buffers --------------------- */ /** * bro_buf_new - Creates a new buffer object. * * @returns a new buffer object, or %NULL on error. Use paired with * bro_buf_free(). */ BroBuf *bro_buf_new(void); /** * bro_buf_free - Releases a dynamically allocated buffer object. * @param buf buffer pointer. * * The function releases all memory held by the buffer pointed * to by @p buf. Use paired with bro_buf_new(). */ void bro_buf_free(BroBuf *buf); /** * bro_buf_append - appends data to the end of the buffer. * @param buf buffer pointer. * @param data new data to append to buffer. * @param data_len size of @p data. * * The function appends data to the end of the buffer, * enlarging it if necessary to hold the @p len new bytes. * NOTE: it does not modify the buffer pointer. It only * appends new data where buf_off is currently pointing * and updates it accordingly. If you DO want the buffer * pointer to be updated, have a look at bro_buf_ptr_write() * instead. * * @returns %TRUE if successful, %FALSE otherwise. */ int bro_buf_append(BroBuf *buf, void *data, int data_len); /** * bro_buf_consume - shrinks the buffer. * @param buf buffer pointer. * * The function removes the buffer contents between the start * of the buffer and the point where the buffer pointer * currently points to. The idea is that you call bro_buf_ptr_read() * a few times to extract data from the buffer, and then * call bro_buf_consume() to signal to the buffer that the * extracted data are no longer needed inside the buffer. */ void bro_buf_consume(BroBuf *buf); /** * bro_buf_reset - resets the buffer. * @param buf buffer pointer. * * The function resets the buffer pointers to the beginning of the * currently allocated buffer, i.e., it marks the buffer as empty. */ void bro_buf_reset(BroBuf *buf); /** * bro_buf_get - Returns pointer to actual start of buffer. * @param buf buffer pointer. * * @returns the entire buffer's contents. */ uchar *bro_buf_get(BroBuf *buf); /** * bro_buf_get_end - Returns pointer to the end of the buffer. * @param buf buffer pointer. * * @returns a pointer to the first byte in the * buffer that is not currently used. */ uchar *bro_buf_get_end(BroBuf *buf); /** * bro_buf_get_size - Returns number of bytes allocated for buffer. * @param buf buffer pointer. * * @returns the number of actual bytes allocated for the * buffer. */ uint bro_buf_get_size(BroBuf *buf); /** * bro_buf_get_used_size - Returns number of bytes currently used. * @param buf buffer pointer. * * @returns number of bytes currently used. */ uint bro_buf_get_used_size(BroBuf *buf); /** * bro_buf_ptr_get - Returns current buffer content pointer. * @param buf buffer pointer. * * @returns current buffer content pointer. */ uchar *bro_buf_ptr_get(BroBuf *buf); /** * bro_buf_ptr_tell - Returns current offset of buffer content pointer. * @param buf buffer pointer. * * @returns current offset of buffer content pointer. */ uint32 bro_buf_ptr_tell(BroBuf *buf); /** * bro_buf_ptr_seek - Adjusts buffer content pointer. * @param buf buffer pointer. * @param offset number of bytes by which to adjust pointer, positive or negative. * @param whence location relative to which to adjust. * * The function adjusts the position of @p buf's content * pointer. Call semantics are identical to fseek(), thus * use @p offset to indicate the offset by which to jump and * use %SEEK_SET, %SEEK_CUR, or %SEEK_END to specify the * position relative to which to adjust. * * @returns %TRUE if adjustment could be made, %FALSE * if not (e.g. because the offset requested is not within * legal bounds). */ int bro_buf_ptr_seek(BroBuf *buf, int offset, int whence); /** * bro_buf_ptr_check - Checks whether a number of bytes can be read. * @param buf buffer pointer. * @param size number of bytes to check for availability. * * The function checks whether @p size bytes could be read from the * buffer using bro_buf_ptr_read(). * * @returns %TRUE if @p size bytes can be read, %FALSE if not. */ int bro_buf_ptr_check(BroBuf *buf, int size); /** * bro_buf_ptr_read - Extracts a number of bytes from buffer. * @param buf buffer pointer. * @param data destination area. * @param size number of bytes to copy into @p data. * * The function copies @p size bytes into @p data if the buffer * has @p size bytes available from the current location of * the buffer content pointer onward, incrementing the content * pointer accordingly. If not, the function doesn't do anything. * It behaves thus different from the normal read() in that * it either copies the amount requested or nothing. * * @returns %TRUE if @p size bytes were copied, %FALSE if not. */ int bro_buf_ptr_read(BroBuf *buf, void *data, int size); /** * bro_buf_ptr_write - Writes a number of bytes into buffer. * @param buf buffer pointer. * @param data data to write. * @param size number of bytes to copy into @p data. * * The function writes @p size bytes of the area pointed to by @p data * into the buffer @p buf at the current location of its content pointer, * adjusting the content pointer accordingly. If the buffer doesn't have * enough space to receive @p size bytes, more space is allocated. * * @returns %TRUE if @p size bytes were copied, %FALSE if an error * occurred and the bytes could not be copied. */ int bro_buf_ptr_write(BroBuf *buf, void *data, int size); /* ------------------------ Configuration Access --------------------- */ /** * bro_conf_set_domain - Sets the current domain to use in a config file. * @param domain name of the domain, or %NULL. * * Broccoli's config files are divided into sections. At the beginning of * each config file you can have an unnamed section that will be used by * default. Case is irrelevant. By passing %NULL for @p domain, you select * the default domain, otherwise the one that matches @p domain. @p domain is * copied internally. */ void bro_conf_set_domain(const char *domain); /** * bro_conf_get_int - Retrieves an integer from the configuration. * @param val_name key name for the value. * @param val result pointer for the value. * * The function tries to find an integer item named @p val_name in the * configuration. If it is found, its value is placed into the * int pointed to by @p val. * * @returns %TRUE if @p val_name was found, %FALSE otherwise. */ int bro_conf_get_int(const char *val_name, int *val); /** * bro_conf_get_dbl - Retrieves a double float from the configuration. * @param val_name key name for the value. * @param val result pointer for the value. * * The function tries to find a double float item named @p val_name * in the configuration. If it is found, its value is placed into the * double pointed to by @p val. * * @returns %TRUE if @p val_name was found, %FALSE otherwise. */ int bro_conf_get_dbl(const char *val_name, double *val); /** * bro_conf_get_str - Retrieves an integer from the configuration. * @param val_name key name for the value. * * The function tries to find a string item named @p val_name in the * configuration. * * @returns the config item if @p val_name was found, %NULL otherwise. * A returned string is stored internally and not to be modified. If * you need to keep it around, strdup() it. */ const char *bro_conf_get_str(const char *val_name); /* ------------------------------ Strings ---------------------------- */ /** * bro_string_init - Initializes an existing string structure. * @param bs string pointer. * * The function initializes the BroString pointed to by @p bs. Use this * function before using the members of a BroString you're using on the * stack. */ void bro_string_init(BroString *bs); /** * bro_string_set - Sets a BroString's contents. * @param bs string pointer. * @param s C ASCII string. * * The function initializes the BroString pointed to by @p bs to the string * given in @p s. @p s's content is copied, so you can modify or free @p s * after calling this, and you need to call bro_string_cleanup() on the * BroString pointed to by @p bs. * * @returns %TRUE if successful, %FALSE otherwise. */ int bro_string_set(BroString *bs, const char *s); /** * bro_string_set_data - Sets a BroString's contents. * @param bs string pointer. * @param data arbitrary data. * @param data_len length of @p data. * * The function initializes the BroString pointed to by @p bs to @p data_len * bytes starting at @p data. @p data's content is copied, so you can modify * or free @p data after calling this. * * @returns %TRUE if successful, %FALSE otherwise. */ int bro_string_set_data(BroString *bs, const uchar *data, int data_len); /** * bro_string_get_data - Returns pointer to the string data. * @param bs string pointer. * * The function returns a pointer to the string's internal data. You * can copy out the string using this function in combination with * bro_string_get_length(), for obtaining the string's length. * * @returns pointer to string, or %NULL on error. */ const uchar *bro_string_get_data(const BroString *bs); /** * bro_string_get_length - Returns string's length. * @param bs string pointer. * * @returns the string's length. */ uint32 bro_string_get_length(const BroString *bs); /** * bro_string_copy - Duplicates a BroString. * @param bs string pointer. * * @returns a deep copy of the BroString pointed to by @p bs, or %NULL on * error. */ BroString *bro_string_copy(BroString *bs); /** * bro_string_assign - Duplicates a BroString's content, assigning it to an existing one. * @param src source string. * @param dst target string. * * Copies the string content pointed to by @p src into the existing * BroString pointed to by @p dst. bro_string_cleanup() is called on * @p dst before the assignment. */ void bro_string_assign(BroString *src, BroString *dst); /** * bro_string_cleanup - Cleans up existing BroString. * @param bs string pointer. * * This function releases all contents claimed by the BroString pointed * to by @p bs, without releasing that BroString structure itself. Use * this when manipulating a BroString on the stack, paired with * bro_string_init(). */ void bro_string_cleanup(BroString *bs); /** * bro_string_free - Cleans up dynamically allocated BroString. * @param bs string pointer. * * This function releases the entire BroString pointed to by @p bs, including * the BroString structure itself. */ void bro_string_free(BroString *bs); /* -------------------------- Record Handling ------------------------ */ /** * bro_record_new - Creates a new record. * * The function allocates and initializes a new empty record. BroRecords * are used for adding and retrieving record values to/from events. You * do not have to specify a record type separately when you create a * record. The type is defined implicitly by the sequence of types formed * by the sequence of values added to the record, along with the names for * each value. See the manual for details. * * @returns a new record, or %NULL on error. */ BroRecord *bro_record_new(void); /** * bro_record_free - Releases a record. * @param rec record handle. * * The function releases all memory consumed by the record pointed to * by @p rec. */ void bro_record_free(BroRecord *rec); /** * bro_record_get_length - Returns number of fields in record. * @param rec record handle. * * @returns the number of fields in the record. */ int bro_record_get_length(BroRecord *rec); /** * bro_record_add_val - Adds a value to a record. * @param rec record handle. * @param name field name of the added val. * @param type numerical type tag of the new val. * @param type_name optional name of specialized type. * @param val pointer to the new val. * * The function adds a new field to the record pointed to by @p rec and * assigns the value passed in to that field. The field name is given * in @p name, the type of the value is given in @p type and must be one of * the %BRO_TYPE_xxx constants defined in broccoli.h. The type you give * implies what data type @p val must be pointing to; see the manual for * details. If you want to indicate a type specialized from @p type, * use @p type_name to give its name, otherwise pass %NULL for @p type_name. * It is possible to leave fields unassigned, in that case, pass in * %NULL for @p val. * * @p val remains the caller's responsibility and is copied internally. * * @returns %TRUE on success, %FALSE on error. */ int bro_record_add_val(BroRecord *rec, const char *name, int type, const char *type_name, const void *val); /** * bro_record_get_nth_val - Retrieves a value from a record by field index. * @param rec record handle. * @param num field index, starting from 0. * @param type value-result argument for the expected/actual type of the value. * * The function returns the @p num'th value of the record pointed to * by @p rec, expected to be of @p type. The returned value is internal * and needs to be duplicated if you want to keep it around. Upon * return, the int pointed to by @p type tells you the type of the returned * value, as a BRO_TYPE_xxx type tag. If the int pointed to upon calling * the function has the value BRO_TYPE_UNKNOWN, no type checking is * performed and the value is returned. If it is any other type tag, * its value is compared to that of the value, and if they match, the * value is returned. Otherwise, the return value is %NULL. If you don't * care about type enforcement and don't want to know the value's type, * you may pass %NULL for @p type. * * @returns pointer to queried value on success, %NULL on error. */ void* bro_record_get_nth_val(BroRecord *rec, int num, int *type); /** * bro_record_get_nth_name - Retrieves a name from a record by field index. * @param rec record handle. * @param num field index, starting from 0. * * The function returns the @p num'th name of the record pointed to by @p rec. * * @returns field name on success, %NULL on error. */ const char* bro_record_get_nth_name(BroRecord *rec, int num); /** * bro_record_get_named_val - Retrieves a value from a record by field name. * @param rec record handle. * @param name field name. * @param type value-result argument for the expected/actual type of the value. * * The function returns the value of the field named @p name in the * record pointed to by @p rec. The returned value is internal and needs * to be duplicated if you want to keep it around. @p type works as with * bro_record_get_nth_val(), see there for more details. * * @returns pointer to queried value on success, %NULL on error. */ void* bro_record_get_named_val(BroRecord *rec, const char *name, int *type); /** * bro_record_set_nth_val - Replaces a value in a record, identified by field index. * @param rec record handle. * @param num field index, starting from 0. * @param type expected type of the value. * @param type_name optional name of specialized type. * @param val pointer to new val. * * The function replaces the @p num'th value of the record pointed to * by @p rec, expected to be of @p type. All values are copied internally * so what @p val points to stays unmodified. The value of @p type implies * what @p result must be pointing to. See the manual for details. * If you want to indicate a type specialized from @p type, use * @p type_name to give its name, otherwise pass %NULL for @p type_name. * * @returns %TRUE on success, %FALSE on error. */ int bro_record_set_nth_val(BroRecord *rec, int num, int type, const char *type_name, const void *val); /** * bro_record_set_named_val - Replaces a value in a record, identified by name. * @param rec record handle. * @param name field name. * @param type expected type of the value. * @param type_name optional name of specialized type. * @param val pointer to new val. * * The function replaces the value named @p name in the record pointed to * by @p rec, expected to be of @p type. All values are copied internally * so what @p val points to stays unmodified. The value of @p type implies * what @p result must be pointing to. See the manual for details. * If you want to indicate a type specialized from @p type, * use @p type_name to give its name, otherwise pass %NULL for @p type_name. * * @returns %TRUE on success, %FALSE on error. */ int bro_record_set_named_val(BroRecord *rec, const char *name, int type, const char *type_name, const void *val); /* -------------------------- Tables & Sets -------------------------- */ /** * BroTableCallback - The signature of callbacks for iterating over tables. * @param key a pointer to the key of a key-value pair. * @param val a pointer to @p key's corresponding value. * @param user_data user data passed through. * * This is the signature of callbacks used when iterating over all * elements stored in a BroTable. * * @returns TRUE if iteration should continue, FALSE if done. */ typedef int (*BroTableCallback) (void *key, void *val, void *user_data); BroTable *bro_table_new(void); void bro_table_free(BroTable *tbl); int bro_table_insert(BroTable *tbl, int key_type, const void *key, int val_type, const void *val); void *bro_table_find(BroTable *tbl, const void *key); int bro_table_get_size(BroTable *tbl); void bro_table_foreach(BroTable *tbl, BroTableCallback cb, void *user_data); void bro_table_get_types(BroTable *tbl, int *key_type, int *val_type); /** * BroTableCallback - The signature of callbacks for iterating over sets. * @param val a pointer to an element in the set. * @param user_data user data passed through. * * This is the signature of callbacks used when iterating over all * elements stored in a BroSet. * * @returns TRUE if iteration should continue, FALSE if done. */ typedef int (*BroSetCallback) (void *val, void *user_data); BroSet *bro_set_new(void); void bro_set_free(BroSet *set); int bro_set_insert(BroSet *set, int type, const void *val); int bro_set_find(BroSet *set, const void *key); int bro_set_get_size(BroSet *set); void bro_set_foreach(BroSet *set, BroSetCallback cb, void *user_data); void bro_set_get_type(BroSet *set, int *type); /* ----------------------------- Vectors ----------------------------- */ /** * bro_vector_new - Creates a new vector. * * The function allocates and initializes a new empty vector. * * @returns a new vector, or %NULL on error. */ BroVector *bro_vector_new(void); /** * bro_vector_free - Releases a vector. * @param vec vector handle. * * The function releases all memory consumed by the vector pointed to * by @p vec. */ void bro_vector_free(BroVector *vec); /** * bro_vector_get_length - Returns number of elements in vector. * @param vec vector handle. * * @returns the number of elements in the vector. */ int bro_vector_get_length(BroVector *vec); /** * bro_vector_add_val - Adds a value to a vector. * @param vec vector handle. * @param type numerical type tag of the new val. * @param type_name optional name of specialized type. * @param val pointer to the new val. * * The function adds a new element to the vector pointed to by @p vec and * assigns the value passed in to that field. The type of the value is given * in @p type and must be one of * the %BRO_TYPE_xxx constants defined in broccoli.h. The type you give * implies what data type @p val must be pointing to; see the manual for * details. If you want to indicate a type specialized from @p type, * use @p type_name to give its name, otherwise pass %NULL for @p type_name. * It is possible to leave fields unassigned, in that case, pass in * %NULL for @p val. * * @p val remains the caller's responsibility and is copied internally. * * @returns %TRUE on success, %FALSE on error. */ int bro_vector_add_val(BroVector *vec, int type, const char *type_name, const void *val); /** * bro_vector_get_nth_val - Retrieves a value from a vector by index. * @param vec vector handle. * @param num index, starting from 0. * @param type value-result argument for the expected/actual type of the value. * * The function returns the @p num'th value of the vector pointed to * by @p vec, expected to be of @p type. The returned value is internal * and needs to be duplicated if you want to keep it around. Upon * return, the int pointed to by @p type tells you the type of the returned * value, as a BRO_TYPE_xxx type tag. If the int pointed to upon calling * the function has the value BRO_TYPE_UNKNOWN, no type checking is * performed and the value is returned. If it is any other type tag, * its value is compared to that of the value, and if they match, the * value is returned. Otherwise, the return value is %NULL. If you don't * care about type enforcement and don't want to know the value's type, * you may pass %NULL for @p type. * * @returns pointer to queried value on success, %NULL on error. */ void* bro_vector_get_nth_val(BroVector *vec, int num, int *type); /** * bro_vector_set_nth_val - Replaces a value in a vector, identified by index. * @param vec vector handle. * @param num index, starting from 0. * @param type expected type of the value. * @param type_name optional name of specialized type. * @param val pointer to new val. * * The function replaces the @p num'th value of the vector pointed to * by @p vec, expected to be of @p type. All values are copied internally * so what @p val points to stays unmodified. The value of @p type implies * what @p result must be pointing to. See the manual for details. * If you want to indicate a type specialized from @p type, use * @p type_name to give its name, otherwise pass %NULL for @p type_name. * * @returns %TRUE on success, %FALSE on error. */ int bro_vector_set_nth_val(BroVector *vec, int num, int type, const char *type_name, const void *val); /* ----------------------- Pcap Packet Handling ---------------------- */ #ifdef BRO_PCAP_SUPPORT /** * bro_conn_set_packet_ctxt - Sets current packet context for connection. * @param bc connection handle. * @param link_type libpcap DLT linklayer type. * * The function sets the packet context for @p bc for future BroPackets * handled by this connection. */ void bro_conn_set_packet_ctxt(BroConn *bc, int link_type); /** * bro_conn_get_packet_ctxt - Gets current packet context for connection. * @param bc connection handle. * @param link_type result pointer for libpcap DLT linklayer type. * * The function returns @p bc's current packet context through @p link_type. */ void bro_conn_get_packet_ctxt(BroConn *bc, int *link_type); /** * bro_packet_new - Creates a new packet. * @param hdr pointer to libpcap packet header. * @param data pointer to libpcap packet data. * @param tag pointer to ASCII tag (0 for no tag). * * @returns a new BroPacket by copying @p hdr and @p data * internally. * Release the resulting packet using bro_packet_free(). */ BroPacket *bro_packet_new(const struct pcap_pkthdr *hdr, const u_char *data, const char* tag); /** * bro_packet_clone - Clones a packet. * @param packet packet to clone. * * @returns a copy of @p packet, or %NULL on error. */ BroPacket *bro_packet_clone(const BroPacket *packet); /** * bro_packet_free - Releases a packet. * @param packet packet to release. * * The function releases all memory occupied by a packet previously allocated * using bro_packet_new(). */ void bro_packet_free(BroPacket *packet); /** * bro_packet_send - Sends a packet over a given connection. * @param bc connection on which to send packet. * @param packet packet to send. * * The function sends @p packet to the Bro peer connected via @p bc. * * @returns %TRUE if successful, %FALSE otherwise. */ int bro_packet_send(BroConn *bc, BroPacket *packet); #endif /* --------------------------- Miscellaneous ------------------------- */ /** * bro_util_current_time - Gets current time. * * @returns the current system time as a double, in seconds, suitable * for passing to bro_event_add_time(). */ double bro_util_current_time(void); /** * bro_util_timeval_to_double - Converts timeval struct to double. * @param tv pointer to timeval structure. * * @returns a double encoding the timestamp given in @p tv in a floating * point double, with the fraction of a second between 0.0 and 1.0. */ double bro_util_timeval_to_double(const struct timeval *tv); /** * bro_util_is_v4_addr - Checks if an address is IPv4. * @param a pointer to address structure. * * @returns %TRUE if the address is IPv4, else %FALSE. */ int bro_util_is_v4_addr(const BroAddr *a); /** * The standard 12-byte prefix of a 16-byte IPv6 address that indicates * it's a mapped IPv4 address. */ extern const uint8 BRO_IPV4_MAPPED_PREFIX[12]; #ifdef __cplusplus } #endif #endif broccoli-1.97-minimal/src/bro_shm_none.c0000664002342100234210000000412412523041064020111 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include struct bro_shared_mem { void *mem; int mem_size; }; BroSharedMem * __bro_shm_new(int size) { BroSharedMem *shm; if (size <= 0) return NULL; if (! (shm = calloc(1, sizeof(BroSharedMem)))) return NULL; if (! (shm->mem = malloc(size))) { free(shm); return NULL; } shm->mem_size = size; return shm; } void __bro_shm_free(BroSharedMem *shm) { if (! shm) return; if (shm->mem) free(shm->mem); free(shm); } void * __bro_shm_get_mem(const BroSharedMem *shm) { if (! shm) return NULL; return shm->mem; } int __bro_shm_get_size(const BroSharedMem *shm) { return shm->mem_size; } int __bro_shm_attach(BroSharedMem *shm) { return TRUE; shm = NULL; } int __bro_shm_detach(BroSharedMem *shm) { return TRUE; shm = NULL; } broccoli-1.97-minimal/src/bro_attr.c0000664002342100234210000000551412523041064017261 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include BroAttr * __bro_attr_new(void) { BroAttr *attr; D_ENTER; if (! (attr = calloc(1, sizeof(BroAttr)))) D_RETURN_(NULL); D_RETURN_(attr); } BroAttr * __bro_attr_copy(BroAttr *attr) { BroAttr *copy; D_ENTER; if (! attr) D_RETURN_(NULL); if (! (copy = __bro_attr_new())) D_RETURN_(NULL); copy->tag = attr->tag; /* FIXME copy->expr = __bro_sobject_copy((BroSObject *) attr->expr); */ D_RETURN_(copy); } void __bro_attr_free(BroAttr *attr) { D_ENTER; /* FIXME __bro_expr_free(attr->expr); */ free(attr); D_RETURN; } int __bro_attr_read(BroAttr *attr, BroConn *bc) { char opt; D_ENTER; if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { /* FIXME if (attr->expr) __bro_expr_free(attr->expr); if (! (attr->expr = (BroExpr *) __bro_sobject_unserialize(SER_IS_EXPR, buf))) D_RETURN_(FALSE); */ } if (! __bro_buf_read_char(bc->rx_buf, &attr->tag)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_attr_write(BroAttr *attr, BroConn *bc) { D_ENTER; if (! __bro_buf_write_char(bc->tx_buf, attr->expr ? 1 : 0)) D_RETURN_(FALSE); if (attr->expr && ! __bro_sobject_serialize((BroSObject *) attr->expr, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, attr->tag)) D_RETURN_(FALSE); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_config.c0000664002342100234210000002526612523041064017562 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include typedef enum { BRO_CONF_INT, BRO_CONF_DBL, BRO_CONF_STR, BRO_CONF_NET, BRO_CONF_ERR } BroConfType; typedef struct bro_conf_it { char *ci_name; BroConfType ci_type; union { int ci_int; double ci_dbl; char *ci_str; } ci_val; #define ci_int ci_val.ci_int #define ci_dbl ci_val.ci_dbl #define ci_str ci_val.ci_str } BroConfIt; static char *config_file = BRO_SYSCONF_FILE; /* The name of the current domain, may be NULL. */ static char *cur_dom; /* The default domain's configuration, used when cur_dom == NULL. */ static BroHT *default_conf; /* While parsing the configuration, we switch from domain to domain * as contained in the file, but leave the user's currently selected * domain unaffected. We point to the current domain while parsing * using parsing_conf, which by default is the same as default_conf. */ static BroHT *parsing_conf; /* A hashtable of hashtables, indexed by domain names. The inner * hash tables contain BroConfIt items, indexed by strings. */ static BroHT *dom_conf; extern int __bro_parse_config(const char *filename); static BroConfIt * conf_item_new(const char *name, BroConfType type, void *val) { BroConfIt *ci; if (! (ci = calloc(1, sizeof(BroConfIt)))) return NULL; ci->ci_name = strdup(name); ci->ci_type = type; switch (type) { case BRO_CONF_INT: ci->ci_int = *((int*) val); break; case BRO_CONF_DBL: ci->ci_dbl = *((double*) val); break; case BRO_CONF_STR: ci->ci_str = strdup((char *) val); break; default: free(ci); return NULL; } return ci; } static void conf_item_free(BroConfIt *ci) { if (!ci) return; if (ci->ci_name) free(ci->ci_name); if (ci->ci_type == BRO_CONF_STR) { memset(ci->ci_str, 0, strlen(ci->ci_str)); free(ci->ci_str); ci->ci_str = NULL; } free(ci); } static int conf_permissions_ok(struct stat *st) { /* We consider the file okay if it is not a link, only * the owner can read it, and the current user can open it. */ if (S_ISREG(st->st_mode) && /* regular file */ (st->st_mode & S_IRUSR) && /* user-readable */ ! (st->st_mode & S_IXUSR) && /* not user-exec'able (paranoia) */ ! (st->st_mode & S_IRWXG) && /* no group permissions */ ! (st->st_mode & S_IRWXO)) /* no other permissions */ { if (st->st_uid == geteuid()) return TRUE; } fprintf(stderr, "Insufficient permissions for reading ~/.broccoli.conf.\n"); fprintf(stderr, "NOTE: ~/.broccoli.conf must be regular file and -rw-------\n"); return FALSE; } static char * get_passwd_home(void) { #if defined(HAVE_GETEUID) && defined(HAVE_GETPWUID) struct passwd *passwd; uid_t uid = geteuid(); if ( (passwd = getpwuid(uid))) { D(("Getting home directory from user %u's passwd entry: %s.\n", uid, passwd->pw_dir)); return strdup(passwd->pw_dir); } #endif return NULL; } void __bro_conf_init(void) { static int deja_vu = FALSE; struct stat st; char *pwd_home = NULL; char* env_config; char home_config[MAXPATHLEN]; char home_config2[MAXPATHLEN]; int try_env = TRUE, try_pwd = TRUE, debug_messages, debug_calltrace; if (deja_vu) return; home_config[0] = '\0'; home_config2[0] = '\0'; parsing_conf = default_conf = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, NULL, (BroHTFreeFunc)conf_item_free, FALSE); dom_conf = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, (BroHTFreeFunc)__bro_ht_free, FALSE); /* Now figure out what config file to read in this order of preference: * 1) BROCCOLI_CONFIG_FILE environment variable * 2) user's ~/.broccoli.conf * 3) user's $HOME/.broccoli.conf if it's different than (2) * 4) the installed/global config file determined at ./configure time */ env_config = getenv("BROCCOLI_CONFIG_FILE"); if ( env_config && stat(env_config, &st) == 0 && conf_permissions_ok(&st) ) { config_file = strdup(env_config); try_pwd = FALSE; try_env = FALSE; } if (try_pwd && (pwd_home = get_passwd_home())) { __bro_util_snprintf(home_config, MAXPATHLEN, "%s/.broccoli.conf", pwd_home); free(pwd_home); if (stat(home_config, &st) == 0 && conf_permissions_ok(&st)) { config_file = strdup(home_config); try_env = FALSE; } } if (try_env) { __bro_util_snprintf(home_config2, MAXPATHLEN, "%s/.broccoli.conf", getenv("HOME")); /* Only check this variant if it didn't yield the same file as the * pwd-based filename. */ if (strcmp(home_config, home_config2) && stat(home_config2, &st) == 0 && conf_permissions_ok(&st)) config_file = strdup(home_config2); } __bro_parse_config(config_file); deja_vu = TRUE; /* Read out debugging verbosity settings and assign if found. */ if (__bro_conf_get_int("/broccoli/debug_messages", &debug_messages)) bro_debug_messages = debug_messages; if (__bro_conf_get_int("/broccoli/debug_calltrace", &debug_calltrace)) bro_debug_calltrace = debug_calltrace; } static BroHT * assert_domain(void) { BroHT *conf = default_conf; D(("Selecting configuration domain, name is %s\n", cur_dom)); if (cur_dom && ! (conf = (BroHT *) __bro_ht_get(dom_conf, cur_dom))) { D(("Allocating domain '%s'\n", cur_dom)); conf = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, NULL, (BroHTFreeFunc)conf_item_free, FALSE); __bro_ht_add(dom_conf, strdup(cur_dom), conf); } return conf; } void __bro_conf_set_domain(const char *new_domain) { /* First reset to the default domain */ if (cur_dom) free(cur_dom); cur_dom = NULL; /* Then if given, switch to the new one. */ if (new_domain && *new_domain) { char *str; str = cur_dom = strdup(new_domain); while (*str != '\0') { *str = tolower(*str); str++; } D(("Configuration domain set to '%s'\n", cur_dom)); } } void __bro_conf_set_storage_domain(const char *storage_domain) { if (! storage_domain || ! *storage_domain) { parsing_conf = default_conf; return; } if (! (parsing_conf = (BroHT *) __bro_ht_get(dom_conf, storage_domain))) { D(("Allocating domain '%s'\n", storage_domain)); parsing_conf = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, NULL, (BroHTFreeFunc)conf_item_free, FALSE); __bro_ht_add(dom_conf, strdup(storage_domain), parsing_conf); } } const char * __bro_conf_get_domain(void) { return cur_dom; } void __bro_conf_add_int(const char *val_name, int val) { BroConfIt *ci; if (! (ci = conf_item_new(val_name, BRO_CONF_INT, &val))) return; __bro_ht_add(parsing_conf, ci->ci_name, ci); } void __bro_conf_add_dbl(const char *val_name, double val) { BroConfIt *ci; if (! (ci = conf_item_new(val_name, BRO_CONF_DBL, &val))) return; __bro_ht_add(parsing_conf, ci->ci_name, ci); } void __bro_conf_add_str(const char *val_name, char *val) { BroConfIt *ci; if (! (ci = conf_item_new(val_name, BRO_CONF_STR, val))) return; __bro_ht_add(parsing_conf, ci->ci_name, ci); } int __bro_conf_get_int(const char *val_name, int *val) { BroConfIt *ci; BroHT *conf; __bro_conf_init(); conf = assert_domain(); do { if (! (ci = __bro_ht_get(conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_INT) break; *val = ci->ci_int; return TRUE; } while (0); do { if (! (ci = __bro_ht_get(default_conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_INT) break; *val = ci->ci_int; return TRUE; } while (0); return FALSE; } int __bro_conf_get_dbl(const char *val_name, double *val) { BroConfIt *ci; BroHT *conf; __bro_conf_init(); conf = assert_domain(); do { if (! (ci = __bro_ht_get(conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_DBL) break; *val = ci->ci_dbl; return TRUE; } while (0); do { if (! (ci = __bro_ht_get(default_conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_DBL) break; *val = ci->ci_dbl; return TRUE; } while (0); return FALSE; } const char * __bro_conf_get_str(const char *val_name) { BroConfIt *ci; BroHT *conf; __bro_conf_init(); conf = assert_domain(); do { if (! (ci = __bro_ht_get(conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_STR) break; return ci->ci_str; } while (0); do { if (! (ci = __bro_ht_get(default_conf, (void*) val_name))) break; if (ci->ci_type != BRO_CONF_STR) break; return ci->ci_str; } while (0); return NULL; } int __bro_conf_forget_item(const char *val_name) { BroConfIt *ci; BroHT *conf; __bro_conf_init(); conf = assert_domain(); if (! (ci = __bro_ht_del(conf, (void*) val_name))) { if (! (ci = __bro_ht_del(default_conf, (void*) val_name))) return FALSE; } conf_item_free(ci); return TRUE; } broccoli-1.97-minimal/src/bro_event.h0000664002342100234210000000341512523041064017433 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_event_h #define broccoli_event_h #include #include BroEvent *__bro_event_new(BroString *name); void __bro_event_free(BroEvent *be); BroEvent *__bro_event_copy(BroEvent *be); const char *__bro_event_get_name(BroEvent *be); int __bro_event_serialize(BroEvent *be, BroConn *bc); BroEvent *__bro_event_unserialize(BroConn *bc); void __bro_event_add_val(BroEvent *be, BroVal *val); int __bro_event_set_val(BroEvent *be, int val_num, BroVal *val); #endif broccoli-1.97-minimal/src/CMakeLists.txt0000664002342100234210000000743712523041064020047 0ustar johannajohannaconfigure_file(${CMAKE_CURRENT_SOURCE_DIR}/broccoli.h.in ${CMAKE_CURRENT_BINARY_DIR}/broccoli.h) include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/compat) ######################################################################## ## libbroccoli target if (BRO_PCAP_SUPPORT) set(PACKET_FILES bro_packet.c bro_packet.h) endif () bison_target(Bro_Parser bro_parser.y ${CMAKE_CURRENT_BINARY_DIR}/bro_parser.c VERBOSE ${CMAKE_CURRENT_BINARY-DIR}/bro_parser.output COMPILE_FLAGS "-p bro") flex_target(Bro_Lexer bro_lexer.l ${CMAKE_CURRENT_BINARY_DIR}/bro_lexer.c COMPILE_FLAGS "-Pbro") add_flex_bison_dependency(Bro_Lexer Bro_Parser) set(broccoli_SRCS ${PACKET_FILES} ${FLEX_Bro_Lexer_INPUT} ${BISON_Bro_Parser_INPUT} ${FLEX_Bro_Lexer_OUTPUTS} ${BISON_Bro_Parser_OUTPUTS} broccoli.h bro.c bro_attr.c bro_attr.h bro_attrs.c bro_attrs.h bro_buf.h bro_buf.c bro_config.h bro_config.c bro_debug.h bro_debug.c bro_event.h bro_event.c bro_event_reg.h bro_event_reg.c bro_hashtable.h bro_hashtable.c bro_id.h bro_id.c bro_io.h bro_io.c bro_list.h bro_list.c bro_location.h bro_location.c bro_object.h bro_object.c bro_openssl.h bro_openssl.c bro_record.h bro_record.c bro_sobject.h bro_sobject.c bro_table.h bro_table.c bro_type.h bro_type.c bro_type_decl.h bro_type_decl.c bro_types.h bro_util.h bro_util.c bro_val.h bro_val.c bro_vector.h bro_vector.c ) if (ENABLE_SHARED) add_library(broccoli SHARED ${broccoli_SRCS}) set_target_properties(broccoli PROPERTIES VERSION ${SOVersion}.${SOVersionMinor}.${SOVersionRelease} SOVERSION ${SOVersion}) # When CMake 2.8.12+ is required, can stop setting INSTALL_NAME_DIR. # It's just there for older versions that don't know about # MACOSX_RPATH. set_target_properties(broccoli PROPERTIES INSTALL_NAME_DIR "@rpath") set_target_properties(broccoli PROPERTIES MACOSX_RPATH true) # BIND library is not necessary, but linked when a parent project # uses it (for consistency and also to avoid missing inet_* symbols # that can result from mismatching headers/libraries) target_link_libraries(broccoli ${OpenSSL_LIBRARIES} ${BIND_LIBRARY} ${BRO_LIBADD}) install(TARGETS broccoli DESTINATION ${INSTALL_LIB_DIR}) endif () if (ENABLE_STATIC) add_library(broccoliStatic STATIC ${broccoli_SRCS}) if (UNIX) # the output name of the static library shouldn't conflict with the # shared library because they use different extensions (.a versus .so) set_target_properties(broccoliStatic PROPERTIES OUTPUT_NAME broccoli) endif () # BIND library is not necessary, but linked when a parent project # uses it (for consistency and also to avoid missing inet_* symbols # that can result from mismatching headers/libraries) target_link_libraries(broccoliStatic ${OpenSSL_LIBRARIES} ${BIND_LIBRARY} ${BRO_LIBADD}) install(TARGETS broccoliStatic DESTINATION ${INSTALL_LIB_DIR}) endif () install(FILES ${CMAKE_CURRENT_BINARY_DIR}/broccoli.h DESTINATION include) # Set as a convenience for projects that depend on broccoli, but want the # option of building it from source set(Broccoli_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "Broccoli header directory" FORCE) if (ENABLE_SHARED) set(Broccoli_LIBRARY broccoli CACHE STRING "Broccoli library" FORCE) elseif (ENABLE_STATIC) set(Broccoli_LIBRARY broccoliStatic CACHE STRING "Broccoli library" FORCE) endif () broccoli-1.97-minimal/src/bro_location.h0000664002342100234210000000374312523041064020126 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_location_h #define broccoli_location_h #include #include typedef struct bro_loc BroLoc; struct bro_loc { BroSObject sobject; BroString filename; uint32 first_line; uint32 last_line; uint32 first_column; uint32 last_column; }; BroLoc *__bro_loc_new(void); void __bro_loc_init(BroLoc *loc); void __bro_loc_free(BroLoc *loc); int __bro_loc_read(BroLoc *loc, BroConn *bc); int __bro_loc_write(BroLoc *loc, BroConn *bc); int __bro_loc_clone(BroLoc *dst, BroLoc *src); uint32 __bro_loc_hash(BroLoc *loc); int __bro_loc_cmp(BroLoc *loc1, BroLoc *loc2); #endif broccoli-1.97-minimal/src/bro_table.c0000664002342100234210000001123212523041064017370 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include BroTable * __bro_table_new(void) { BroTable *tbl; if (! (tbl = calloc(1, sizeof(BroTable)))) return NULL; tbl->tbl_impl = __bro_ht_new((BroHTHashFunc) __bro_table_hash_key, (BroHTCmpFunc) __bro_table_cmp_key, (BroHTFreeFunc) __bro_sobject_release, (BroHTFreeFunc) __bro_sobject_release, FALSE); if (! tbl->tbl_impl) { free(tbl); return NULL; } return tbl; } void __bro_table_free(BroTable *tbl) { if (! tbl) return; __bro_ht_free(tbl->tbl_impl); free(tbl); } static int __bro_table_copy_cb(BroVal *key, BroVal *val, BroTable *dest) { __bro_table_insert(dest, key, val); return TRUE; /* Continue the iteration */ } BroTable * __bro_table_copy(BroTable *tbl) { BroVal *val, *val_copy; BroTable *copy; if (! tbl) return NULL; if (! (copy = __bro_table_new())) return NULL; __bro_ht_foreach(tbl->tbl_impl, (BroHTCallback) __bro_table_copy_cb, (void *) copy); return copy; } void __bro_table_insert(BroTable *tbl, BroVal *key, BroVal *val) { if (! tbl || ! key) /* NULL for val is okay -- that's a set. */ return; __bro_ht_add(tbl->tbl_impl, key, val); } BroVal * __bro_table_find(BroTable *tbl, const BroVal *key) { if (! tbl || ! key) return NULL; return __bro_ht_get(tbl->tbl_impl, key); } int __bro_table_get_size(BroTable *tbl) { if (! tbl) return -1; return __bro_ht_get_size(tbl->tbl_impl); } void __bro_table_foreach(BroTable *tbl, BroTableCallback cb, void *user_data) { if (! tbl || ! cb) return; __bro_ht_foreach(tbl->tbl_impl, cb, user_data); } int __bro_table_is_set(BroTable *tbl) { return tbl->tbl_val_type == BRO_TYPE_UNKNOWN; } uint32 __bro_table_hash_key(BroVal *key) { return ((BroSObject *) key)->hash((BroSObject *) key); } int __bro_table_cmp_key(BroVal *val1, BroVal *val2) { BroSObject *obj1 = (BroSObject *) val1; BroSObject *obj2 = (BroSObject *) val2; return obj1->cmp(obj1, obj2); } static int __bro_table_hash_cb(BroVal *key, BroVal *val, int *result) { *result ^= __bro_sobject_hash((BroSObject*) key); *result ^= __bro_sobject_hash((BroSObject*) val); return TRUE; } uint32 __bro_table_hash(BroTable *tbl) { uint32 result; D_ENTER; if (! tbl) D_RETURN_(0); result = __bro_ht_get_size(tbl->tbl_impl); __bro_ht_foreach(tbl->tbl_impl, (BroHTCallback) __bro_table_hash_cb, &result); D_RETURN_(result); } typedef struct bro_table_cmp { BroHT *table; int result; } BroTableCmp; static int __bro_table_cmp_cb(BroVal *key, BroVal *val, BroTableCmp *cmp) { BroVal *val2 = __bro_ht_get(cmp->table, key); if (! val2) goto no_luck; if (! __bro_sobject_cmp((BroSObject*) val, (BroSObject*) val2)) goto no_luck; return TRUE; no_luck: cmp->result = FALSE; return FALSE; } int __bro_table_cmp(BroTable *tbl1, BroTable *tbl2) { BroTableCmp cmp; D_ENTER; cmp.table = tbl2->tbl_impl; cmp.result = TRUE; if (__bro_ht_get_size(tbl1->tbl_impl) != __bro_ht_get_size(tbl2->tbl_impl)) D_RETURN_(FALSE); __bro_ht_foreach(tbl1->tbl_impl, (BroHTCallback) __bro_table_cmp_cb, &cmp); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_id.c0000664002342100234210000001617612523041064016711 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include BroID * __bro_id_new(void) { BroID *id; D_ENTER; if (! (id = calloc(1, sizeof(BroID)))) D_RETURN_(NULL); __bro_id_init(id); D_RETURN_(id); } void __bro_id_init(BroID *id) { BroSObject *sobj = (BroSObject *) id; D_ENTER; /* First initialize parent */ __bro_object_init((BroObject *) id); /* Now hook our callbacks into the vtable */ sobj->read = (BroSObjectRead) __bro_id_read; sobj->write = (BroSObjectWrite) __bro_id_write; sobj->free = (BroSObjectFree) __bro_id_free; sobj->clone = (BroSObjectClone) __bro_id_clone; sobj->hash = (BroSObjectHash) __bro_id_hash; sobj->cmp = (BroSObjectCmp) __bro_id_cmp; sobj->type_id = SER_ID; /* And finally initialize our own stuff */ bro_string_init(&id->name); id->type = __bro_type_new(); /* For now we don't have attrs + val, these get * hooked in on demand. */ D_RETURN; } void __bro_id_free(BroID *id) { D_ENTER; if (!id) D_RETURN; /* First clean up our stuff */ bro_string_cleanup(&id->name); __bro_sobject_release((BroSObject *) id->type); __bro_sobject_release((BroSObject *) id->attrs); __bro_sobject_release((BroSObject *) id->val); /* Then clean up parent -- will eventually call free() */ __bro_object_free((BroObject *) id); D_RETURN; } int __bro_id_read(BroID *id, BroConn *bc) { char opt; D_ENTER; if (! id || ! bc) D_RETURN_(FALSE); if (! __bro_object_read((BroObject *) id, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &id->name)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->scope)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->is_export)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_const)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_enum_const)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_type)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->offset)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->infer_return_type)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->weak_ref)) D_RETURN_(FALSE); if (id->type) __bro_sobject_release((BroSObject*) id->type); if (! (id->type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (id->attrs) __bro_sobject_release((BroSObject *) id->attrs); if (! (id->attrs = (BroAttrs *) __bro_sobject_unserialize(SER_ATTRIBUTES, bc))) D_RETURN_(FALSE); } if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (id->val) __bro_sobject_release((BroSObject *) id->val); if (! (id->val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) D_RETURN_(FALSE); } D_RETURN_(TRUE); } int __bro_id_write(BroID *id, BroConn *bc) { D_ENTER; if (! id || ! bc) D_RETURN_(FALSE); if (! __bro_object_write((BroObject *) id, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &id->name)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->scope)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->is_export)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_const)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_enum_const)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_type)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->offset)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->infer_return_type)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->weak_ref)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) id->type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->attrs ? 1 : 0)) D_RETURN_(FALSE); if (id->attrs && ! __bro_sobject_serialize((BroSObject *) id->attrs, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->val ? 1 : 0)) D_RETURN_(FALSE); if (id->attrs && ! __bro_sobject_serialize((BroSObject *) id->val, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_id_clone(BroID *dst, BroID *src) { BroString *string; D_ENTER; if (! __bro_object_clone((BroObject *) dst, (BroObject *) src)) D_RETURN_(FALSE); if (! (string = bro_string_copy(&src->name))) D_RETURN_(FALSE); dst->name = *string; free(string); dst->scope = src->scope; dst->is_export = src->is_export; dst->is_const = src->is_const; dst->is_enum_const = src->is_enum_const; dst->is_type = src->is_type; dst->offset = src->offset; dst->infer_return_type = src->infer_return_type; dst->weak_ref = src->weak_ref; if (src->type && ! (dst->type = (BroType *) __bro_sobject_copy((BroSObject *) src->type))) D_RETURN_(FALSE); if (src->val && ! (dst->val = (BroVal *) __bro_sobject_copy((BroSObject *) src->val))) D_RETURN_(FALSE); if (src->attrs && ! (dst->attrs = (BroAttrs *) __bro_sobject_copy((BroSObject *) src->attrs))) D_RETURN_(FALSE); D_RETURN_(TRUE); } uint32 __bro_id_hash(BroID *id) { uint32 result = 0; D_ENTER; if (! id) D_RETURN_(0); result ^= __bro_ht_str_hash(id->name.str_val); result ^= ((uint32) id->scope) << 8; result ^= (uint32) id->is_export; result ^= id->is_const; result ^= id->is_enum_const; result ^= id->is_type; result ^= id->offset; D_RETURN_(result); } int __bro_id_cmp(BroID *id1, BroID *id2) { D_ENTER; if (! id1 || ! id2) D_RETURN_(FALSE); D_RETURN_(__bro_ht_str_cmp(id1->name.str_val, id2->name.str_val)); } broccoli-1.97-minimal/src/bro.c0000664002342100234210000012062312523041064016226 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #ifdef __MINGW32__ #include #else #include #include #include #include #include #include #endif #if HAVE_CONFIG_H # include #endif #include "broccoli.h" #include "bro_debug.h" #include "bro_buf.h" #include "bro_config.h" #include "bro_hashtable.h" #include "bro_types.h" #include "bro_type.h" #include "bro_val.h" #include "bro_id.h" #include "bro_event.h" #include "bro_event_reg.h" #include "bro_io.h" #include "bro_util.h" #include "bro_openssl.h" #include "bro_record.h" #include "bro_table.h" #include "bro_vector.h" #ifdef BRO_PCAP_SUPPORT #include "bro_packet.h" #endif /* Don't attempt to reconnect more than once every 5 seconds: */ #define BRO_RECONNECT_MAX_RATE 5 /* Default maximum cache size. */ #define BRO_MAX_CACHE_SIZE 1000 /* Macro for putting safety brakes on some functions to ensure the * user is now calling bro_init() first. */ #define BRO_SAFETY_CHECK init_check(__FUNCTION__); /* Pointer to BroCtx provided by the user at initialization time. */ const BroCtx *global_ctx = NULL; /* To make MinGW happy, we provide an initialization handler for the * DLL if we are building on Windows. */ #ifdef __MINGW32__ int main() { return 0; } #endif static int conn_init_await(BroConn *bc, int conn_state) { /* Wait for a maximum of 10 seconds until the connection * reaches the desired state. We check every 0.2 seconds. */ int i = 0, intervals = 10 * 5 + 1; D_ENTER; if (bc->state->conn_state_self == conn_state) { D(("Self already in requested state.\n")); D_RETURN_(TRUE); } /* Set our own connection state to the requested one. */ bc->state->conn_state_self = conn_state; /* Wait for a while, processing the peer's input, * and return as soon as we reach the desired state. */ while (i++ < intervals) { struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 200000; if (bc->state->conn_state_peer >= conn_state) D_RETURN_(TRUE); if (select(0, NULL, NULL, NULL, &timeout) < 0) { D(("select() caused '%s'\n", strerror(errno))); D_RETURN_(FALSE); } __bro_io_process_input(bc); } D_RETURN_(FALSE); } static int conn_init_setup(BroConn *bc) { BroBuf buf; uint32 descriptor[4]; int result; D_ENTER; descriptor[0] = htonl((uint32) BRO_PROTOCOL_VERSION); descriptor[1] = htonl((uint32) BRO_MAX_CACHE_SIZE); descriptor[2] = htonl((uint32) BRO_DATA_FORMAT_VERSION); descriptor[3] = 0; /* Relative uptime of the process */ __bro_buf_init(&buf); __bro_buf_append(&buf, descriptor, 4 * sizeof(uint32)); if (bc->class) __bro_buf_append(&buf, bc->class, strlen(bc->class) + 1); if (! __bro_io_raw_queue(bc, BRO_MSG_VERSION, __bro_buf_get(&buf), __bro_buf_get_used_size(&buf))) { D(("Setup data not sent to %p\n", bc)); __bro_buf_cleanup(&buf); D_RETURN_(FALSE); } __bro_buf_cleanup(&buf); /* This phase does NOT send PHASE_END ... */ D(("Phase done to peer on %p, self now in HANDSHAKE stage.\n", bc)); result = conn_init_await(bc, BRO_CONNSTATE_HANDSHAKE); D_RETURN_(result); } static int conn_init_handshake(BroConn *bc) { uint32 caps[3]; int result; D_ENTER; /* --- Request events, if any -------------------------------------- */ if (bc->ev_reg->num_handlers > 0) __bro_event_reg_request(bc); /* --- Capabilities ------------------------------------------------ */ /* We never compress at the moment. */ /* Unless user requested caching, tell peer we do not cache. Note * that at the moment we never cache data we send, so this only * affects received data. * * We always identify ourselves as a Broccoli instance. */ caps[0] = BRO_CAP_BROCCOLI_PEER; caps[1] = 0; caps[2] = 0; caps[0] |= (bc->conn_flags & BRO_CFLAG_CACHE) ? 0 : BRO_CAP_DONTCACHE; caps[0] = htonl(caps[0]); caps[1] = htonl(caps[1]); caps[2] = htonl(caps[2]); if (! __bro_io_raw_queue(bc, BRO_MSG_CAPS, (uchar*) caps, 3 * sizeof(uint32))) { D(("Handshake data not sent to %p\n", bc)); D_RETURN_(FALSE); } /* --- End of phase ------------------------------------------------ */ if (! __bro_io_raw_queue(bc, BRO_MSG_PHASE_DONE, NULL, 0)) { D(("End-of-Handshake not sent to %p\n", bc)); D_RETURN_(FALSE); } if (bc->state->sync_state_requested) { D(("Phase done to peer on %p, sync requested, self now in SYNC stage.\n", bc)); result = conn_init_await(bc, BRO_CONNSTATE_SYNC); } else { D(("Phase done to peer on %p, no sync requested, self now in RUNNING stage.\n", bc)); result = conn_init_await(bc, BRO_CONNSTATE_RUNNING); } D_RETURN_(result); } static int conn_init_sync(BroConn *bc) { int result = TRUE; D_ENTER; /* If the peer requested synced state, we just send another phase done. * Otherwise we don't do anything and immediately move to the "running" * state. */ if (bc->state->sync_state_requested) { if (! __bro_io_raw_queue(bc, BRO_MSG_PHASE_DONE, NULL, 0)) { D(("End-of-Sync not sent to %p\n", bc)); D_RETURN_(FALSE); } D(("Phase done to peer on %p\n", bc)); } D(("Self now in RUNNING stage.\n")); result = conn_init_await(bc, BRO_CONNSTATE_RUNNING); D_RETURN_(result); } /* This function walks lock-step with the peer through * the entire handshake procedure. */ static int conn_init_configure(BroConn *bc) { if (! conn_init_setup(bc)) return FALSE; if (! conn_init_handshake(bc)) return FALSE; if (! conn_init_sync(bc)) return FALSE; return TRUE; } static int conn_init(BroConn *bc) { D_ENTER; if (! (bc->rx_buf = __bro_buf_new())) goto error_exit; if (! (bc->tx_buf = __bro_buf_new())) goto error_exit; if (! (bc->state = calloc(1, sizeof(BroConnState)))) { D(("Out of memory in conn_init.\n")); goto error_exit; } bc->state->conn_state_self = BRO_CONNSTATE_SETUP; bc->state->conn_state_peer = BRO_CONNSTATE_SETUP; if (! __bro_openssl_connect(bc)) goto error_exit; D_RETURN_(TRUE); error_exit: __bro_buf_free(bc->rx_buf); __bro_buf_free(bc->tx_buf); bc->rx_buf = NULL; bc->tx_buf = NULL; D_RETURN_(FALSE); } static void conn_free(BroConn *bc) { D_ENTER; __bro_openssl_shutdown(bc); if (bc->state) free(bc->state); __bro_buf_free(bc->rx_buf); __bro_buf_free(bc->tx_buf); bc->rx_buf = NULL; bc->tx_buf = NULL; D_RETURN; } static void init_check(const char *func) { if (global_ctx == NULL) { fprintf(stderr, "*** Broccoli error: %s called without prior initialization.\n" "*** Initialization of the Broccoli library is now required.\n" "*** See documentation for details. Aborting.\n", func); exit(-1); } } int bro_init(const BroCtx* ctx) { if (global_ctx != NULL) return TRUE; if (ctx == NULL) { ctx = calloc(1, sizeof(BroCtx)); if (ctx == NULL) { D(("Unable to allocate memory in bro_init.\n")); return FALSE; } bro_ctx_init((BroCtx*) ctx); } global_ctx = ctx; __bro_conf_init(); if (! __bro_openssl_init()) return FALSE; return TRUE; } void bro_ctx_init(BroCtx *ctx) { memset(ctx, 0, sizeof(BroCtx)); } BroConn * bro_conn_new_str(const char *hostname, int flags) { BroConn *bc; static int counter = 0; BRO_SAFETY_CHECK; D_ENTER; if (! hostname || !*hostname) D_RETURN_(NULL); if (! (bc = (BroConn *) calloc(1, sizeof(BroConn)))) { D(("Unable to allocate memory in bro_conn_new_str.\n")); D_RETURN_(NULL); } D(("Connecting to host %s\n", hostname)); bc->conn_flags = flags; bc->id_pid = getpid(); bc->id_num = counter++; bc->peer = strdup(hostname); bc->io_cache_maxsize = BRO_MAX_CACHE_SIZE; bc->socket = -1; TAILQ_INIT(&bc->msg_queue); bc->msg_queue_len = 0; if (! (bc->ev_reg = __bro_event_reg_new())) goto error_exit; if (! (bc->io_cache = __bro_ht_new(__bro_ht_int_hash, __bro_ht_int_cmp, NULL, (BroHTFreeFunc) __bro_sobject_release, TRUE))) goto error_exit; if (! (bc->data = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, NULL, FALSE))) goto error_exit; if (! (bc->ev_mask = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, NULL, FALSE))) goto error_exit; D_RETURN_(bc); error_exit: __bro_event_reg_free(bc->ev_reg); __bro_ht_free(bc->ev_mask); __bro_ht_free(bc->io_cache); __bro_ht_free(bc->data); if (bc->peer) free(bc->peer); free(bc); D_RETURN_(NULL); } BroConn * bro_conn_new(struct in_addr *ip_addr, uint16 port, int flags) { BroConn *bc; char hostname[1024]; char addr[INET_ADDRSTRLEN]; BRO_SAFETY_CHECK; D_ENTER; inet_ntop(AF_INET, ip_addr, addr, INET_ADDRSTRLEN); __bro_util_snprintf(hostname, 1024, "%s:%hu", addr, ntohs(port)); bc = bro_conn_new_str(hostname, flags); D_RETURN_(bc); } BroConn * bro_conn_new6(struct in6_addr *ip_addr, uint16 port, int flags) { BroConn *bc; char hostname[1024]; char addr[INET6_ADDRSTRLEN]; BRO_SAFETY_CHECK; D_ENTER; inet_ntop(AF_INET6, ip_addr, addr, INET6_ADDRSTRLEN); __bro_util_snprintf(hostname, 1024, "%s:%hu", addr, ntohs(port)); bc = bro_conn_new_str(hostname, flags); D_RETURN_(bc); } BroConn * bro_conn_new_socket(int fd, int flags) { BroConn *bc; BRO_SAFETY_CHECK; D_ENTER; if ( fd < 0 ) D_RETURN_(NULL); bc = bro_conn_new_str("", flags); if (! bc) D_RETURN_(NULL); bc->socket = fd; D_RETURN_(bc); } void bro_conn_set_class(BroConn *bc, const char *class) { if (! bc) return; if (bc->class) free(bc->class); bc->class = strdup(class); } const char * bro_conn_get_peer_class(const BroConn *bc) { if (! bc) return NULL; return bc->peer_class; } void bro_conn_get_connstats(const BroConn *bc, BroConnStats *cs) { if (! bc || ! cs) return; memset(cs, 0, sizeof(BroConnStats)); cs->tx_buflen = __bro_buf_get_used_size(bc->tx_buf); cs->rx_buflen = __bro_buf_get_used_size(bc->rx_buf); } int bro_conn_connect(BroConn *bc) { D_ENTER; if (! bc) D_RETURN_(FALSE); if ( (bc->conn_flags & BRO_CFLAG_SHAREABLE)) fprintf(stderr, "WARNING: BRO_CFLAG_SHAREABLE is no longer supported.\n"); if (! conn_init(bc)) D_RETURN_(FALSE); /* Handshake procedure. */ if (! conn_init_configure(bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int bro_conn_reconnect(BroConn *bc) { BroMsg *msg, *msg_first, **msg_last; int msg_queue_len; time_t current_time; D_ENTER; if (! bc) D_RETURN_(FALSE); if (bc->state->in_reconnect) D_RETURN_(FALSE); if ( (current_time = time(NULL)) > 0) { if (current_time - bc->state->last_reconnect < BRO_RECONNECT_MAX_RATE) { D(("Less than %i seconds since last reconnect attempt, not reconnecting.\n", BRO_RECONNECT_MAX_RATE)); D_RETURN_(FALSE); } bc->state->last_reconnect = current_time; } D(("Attempting reconnection...\n")); bc->state->in_reconnect = TRUE; /* NOTE: the sequencing in this function is quite tricky and very picky. * Don't move things around unneccesarily ... */ bc->state->tx_dead = bc->state->rx_dead = FALSE; /* Clean up the old connection state: */ bc->state->conn_state_self = BRO_CONNSTATE_SETUP; bc->state->conn_state_peer = BRO_CONNSTATE_SETUP; bc->state->sync_state_requested = FALSE; if (bc->bio) { BIO_free_all(bc->bio); bc->bio = NULL; } /* Attempt to establish new connection */ if (! __bro_openssl_reconnect(bc)) goto error_return; __bro_buf_reset(bc->rx_buf); __bro_buf_reset(bc->tx_buf); /* Only *after* we managed to connect, we clear the event mask for events * the peer expects, etc. If we do this earlier and fail to connect, then future * sent events never trigger a reconnect because they're never sent since * they don't seem to be requested. */ /* Temporarily unhook messages from the message queue so the new messages * get sent right away. We hook the old ones back in below. */ msg_first = bc->msg_queue.tqh_first; msg_last = bc->msg_queue.tqh_last; msg_queue_len = bc->msg_queue_len; bc->msg_queue_len = 0; TAILQ_INIT(&bc->msg_queue); __bro_ht_free(bc->ev_mask); if (! (bc->ev_mask = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, NULL, FALSE))) goto reset_error_return; __bro_ht_free(bc->io_cache); if (! (bc->io_cache = __bro_ht_new(__bro_ht_int_hash, __bro_ht_int_cmp, NULL, (BroHTFreeFunc) __bro_sobject_release, TRUE))) goto reset_error_return; if (! conn_init_configure(bc)) goto reset_error_return; /* Hook old events back in */ if (bc->msg_queue_len == 0) bc->msg_queue.tqh_first = msg_first; else { msg_first->msg_queue.tqe_prev = bc->msg_queue.tqh_last; *bc->msg_queue.tqh_last = msg_first; } bc->msg_queue.tqh_last = msg_last; bc->msg_queue_len += msg_queue_len; D(("Reconnect completed successfully.\n")); bc->state->in_reconnect = FALSE; D_RETURN_(TRUE); reset_error_return: /* If the reconnect went wrong somehow, nuke the queue and * place old queue contents back in. */ while ( (msg = bc->msg_queue.tqh_first)) { TAILQ_REMOVE(&bc->msg_queue, msg, msg_queue); __bro_io_msg_free(msg); } bc->msg_queue.tqh_first = msg_first; bc->msg_queue.tqh_last = msg_last; bc->msg_queue_len = msg_queue_len; error_return: bc->state->tx_dead = bc->state->rx_dead = TRUE; bc->state->in_reconnect = FALSE; D_RETURN_(FALSE); } int bro_conn_delete(BroConn *bc) { BroMsg *msg; D_ENTER; if (!bc || !bc->state) D_RETURN_(FALSE); if (! bc->state->tx_dead) { /* Try to flush command queue */ __bro_io_msg_queue_flush(bc); } while ( (msg = bc->msg_queue.tqh_first)) { TAILQ_REMOVE(&bc->msg_queue, msg, msg_queue); __bro_io_msg_free(msg); } __bro_ht_free(bc->ev_mask); __bro_event_reg_free(bc->ev_reg); __bro_ht_free(bc->io_cache); __bro_ht_free(bc->data); conn_free(bc); if (bc->class) free(bc->class); if (bc->peer_class) free(bc->peer_class); if (bc->peer) free(bc->peer); free(bc); D_RETURN_(TRUE); } int bro_conn_alive(const BroConn *bc) { if (!bc || !bc->state) return FALSE; return (! bc->state->tx_dead && ! bc->state->rx_dead); } static int conn_adopt_events_cb(char *ev_name, void *data, BroHT *dst) { char *key; /* If the event is already reported, ignore. */ if (__bro_ht_get(dst, ev_name)) return TRUE; D(("Adopting event %s\n", ev_name)); key = strdup(ev_name); __bro_ht_add(dst, key, key); return TRUE; data = NULL; } void bro_conn_adopt_events(BroConn *src, BroConn *dst) { D_ENTER; if (!src || !dst) D_RETURN; __bro_ht_foreach(src->ev_mask, (BroHTCallback) conn_adopt_events_cb, dst->ev_mask); D_RETURN; } int bro_conn_get_fd(BroConn *bc) { int fd; if (! bc || !bc->state || bc->state->tx_dead || bc->state->rx_dead || !bc->bio) return -1; #ifdef __MINGW32__ return 0; #else BIO_get_fd(bc->bio, &fd); return fd; #endif } int bro_conn_process_input(BroConn *bc) { if (! bc || !bc->state || bc->state->rx_dead) return FALSE; return __bro_io_process_input(bc); } int bro_event_queue_length(BroConn *bc) { if (! bc) return 0; return bc->msg_queue_len; } int bro_event_queue_length_max(BroConn *bc) { return BRO_MSG_QUEUELEN_MAX; bc = NULL; } int bro_event_queue_flush(BroConn *bc) { return __bro_io_msg_queue_flush(bc); } int bro_event_send(BroConn *bc, BroEvent *ev) { int result; D_ENTER; if (! bc || !ev) { D(("Input error\n")); D_RETURN_(FALSE); } D(("Sending event with %i args\n", __bro_list_length(ev->val_list))); result = __bro_io_event_queue(bc, ev); D_RETURN_(result); } int bro_event_send_raw(BroConn *bc, const uchar *data, int data_len) { BroBuf *buf = NULL; D_ENTER; if (! bc || !data) { D(("Input error\n")); D_RETURN_(FALSE); } if (data_len == 0) { D(("Nothing to send\n")); D_RETURN_(TRUE); } if (! (buf = __bro_buf_new())) { D(("Out of memory\n")); D_RETURN_(FALSE); } if (! __bro_buf_write_char(buf, 'e')) { __bro_buf_free(buf); D_RETURN_(FALSE); } if (! __bro_buf_write_data(buf, data, data_len)) { __bro_buf_free(buf); D_RETURN_(FALSE); } __bro_io_rawbuf_queue(bc, BRO_MSG_SERIAL, buf); __bro_io_msg_queue_flush(bc); D_RETURN_(TRUE); } void bro_conn_data_set(BroConn *bc, const char *key, void *val) { if (!bc || !key || !*key) return; __bro_ht_add(bc->data, strdup(key), val); } void * bro_conn_data_get(BroConn *bc, const char *key) { if (!bc || !key || !*key) return NULL; return __bro_ht_get(bc->data, (void *) key); } void * bro_conn_data_del(BroConn *bc, const char *key) { if (!bc || !key || !*key) return NULL; return __bro_ht_del(bc->data, (void *) key); } /* ----------------------------- Bro Events -------------------------- */ BroEvent * bro_event_new(const char *event_name) { BroString name; BroEvent *result; bro_string_set(&name, event_name); result = __bro_event_new(&name); bro_string_cleanup(&name); return result; } void bro_event_free(BroEvent *be) { __bro_event_free(be); } int bro_event_add_val(BroEvent *be, int type, const char *type_name, const void *val) { BroVal *v; D_ENTER; if (! be || ! val || type < 0 || type >= BRO_TYPE_MAX) { D(("Invalid input: (%p, %i, %p)\n", be, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) D_RETURN_(FALSE); if (! __bro_val_assign(v, val)) { __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_event_add_val(be, v); D_RETURN_(TRUE); } int bro_event_set_val(BroEvent *be, int val_num, int type, const char *type_name, const void *val) { BroVal *v; int result; D_ENTER; if (! be || ! val || type < 0 || type >= BRO_TYPE_MAX) { D(("Invalid input: (%p, %i, %p)\n", be, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) D_RETURN_(FALSE); if (! __bro_val_assign(v, val)) { __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } result = __bro_event_set_val(be, val_num, v); D_RETURN_(result); } void bro_event_registry_add(BroConn *bc, const char *event_name, BroEventFunc func, void *user_data) { __bro_event_reg_add(bc, event_name, func, user_data); } void bro_event_registry_add_compact(BroConn *bc, const char *event_name, BroCompactEventFunc func, void *user_data) { __bro_event_reg_add_compact(bc, event_name, func, user_data); } void bro_event_registry_remove(BroConn *bc, const char *event_name) { __bro_event_reg_remove(bc, event_name); } void bro_event_registry_request(BroConn *bc) { D_ENTER; if (!bc || !bc->state) D_RETURN; /* A connection that isn't up and running yet cannot request * events. The handshake phase will request any registered * events automatically. */ if (bc->state->conn_state_self != BRO_CONNSTATE_RUNNING) D_RETURN; __bro_event_reg_request(bc); D_RETURN; } /* ------------------------ Dynamic-size Buffers --------------------- */ BroBuf * bro_buf_new(void) { BroBuf *buf; if (! (buf = calloc(1, sizeof(BroBuf)))) { D(("Unable to allocate memory for buffer in bro_buf_new.\n")); return NULL; } __bro_buf_init(buf); return buf; } void bro_buf_free(BroBuf *buf) { if (!buf) return; __bro_buf_cleanup(buf); free(buf); } int bro_buf_append(BroBuf *buf, void *data, int data_len) { return __bro_buf_append(buf, data, data_len); } void bro_buf_consume(BroBuf *buf) { __bro_buf_consume(buf); } void bro_buf_reset(BroBuf *buf) { __bro_buf_reset(buf); } uchar * bro_buf_get(BroBuf *buf) { return __bro_buf_get(buf); } uchar * bro_buf_get_end(BroBuf *buf) { return __bro_buf_get_end(buf); } uint bro_buf_get_size(BroBuf *buf) { return __bro_buf_get_size(buf); } uint bro_buf_get_used_size(BroBuf *buf) { return __bro_buf_get_used_size(buf); } uchar * bro_buf_ptr_get(BroBuf *buf) { return __bro_buf_ptr_get(buf); } uint32 bro_buf_ptr_tell(BroBuf *buf) { return __bro_buf_ptr_tell(buf); } int bro_buf_ptr_seek(BroBuf *buf, int offset, int whence) { return __bro_buf_ptr_seek(buf, offset, whence); } int bro_buf_ptr_check(BroBuf *buf, int size) { return __bro_buf_ptr_check(buf, size); } int bro_buf_ptr_read(BroBuf *buf, void *data, int size) { return __bro_buf_ptr_read(buf, data, size); } int bro_buf_ptr_write(BroBuf *buf, void *data, int size) { return __bro_buf_ptr_write(buf, data, size); } /* ------------------------ Configuration Access --------------------- */ void bro_conf_set_domain(const char *domain) { BRO_SAFETY_CHECK; __bro_conf_set_domain(domain); } int bro_conf_get_int(const char *val_name, int *val) { BRO_SAFETY_CHECK; if (! val_name || ! val) return FALSE; return __bro_conf_get_int(val_name, val); } int bro_conf_get_dbl(const char *val_name, double *val) { BRO_SAFETY_CHECK; if (! val_name || ! val) return FALSE; return __bro_conf_get_dbl(val_name, val); } const char * bro_conf_get_str(const char *val_name) { BRO_SAFETY_CHECK; if (! val_name) return FALSE; return __bro_conf_get_str(val_name); } /* -------------------------- Record Handling ------------------------ */ BroRecord * bro_record_new(void) { return __bro_record_new(); } void bro_record_free(BroRecord *rec) { __bro_record_free(rec); } int bro_record_get_length(BroRecord *rec) { return __bro_record_get_length(rec); } int bro_record_add_val(BroRecord *rec, const char *name, int type, const char *type_name, const void *val) { BroVal *v; D_ENTER; if (! rec) { D(("Input error: (%p, %s, %i, %p)\n", rec, name, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) { D(("Could not get val of type %i\n", type)); D_RETURN_(FALSE); } if (! name) name = ""; __bro_sobject_data_set((BroSObject *) v, "field", strdup(name)); if (! __bro_val_assign(v, val)) { D(("Could not assign value to the new val.\n")); __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_record_add_val(rec, v); D_RETURN_(TRUE); } const char* bro_record_get_nth_name(BroRecord *rec, int num) { const char *name; if ( (name = __bro_record_get_nth_name(rec, num))) return name; return NULL; } void * bro_record_get_nth_val(BroRecord *rec, int num, int *type) { BroVal *val; int type_found; void *result = NULL; if (type && (*type < BRO_TYPE_UNKNOWN || *type >= BRO_TYPE_MAX)) { D(("Invalid value for type pointer (%i)\n", *type)); return NULL; } if (! (val = __bro_record_get_nth_val(rec, num))) return NULL; /* Now transform the val into a form expected in *result, * based on the type given in the val. */ if (! __bro_val_get_data(val, &type_found, &result)) return NULL; if (type) { if (*type != BRO_TYPE_UNKNOWN && type_found != *type) { D(("Type mismatch: expected type tag %i, found type tag %i\n", *type, type_found)); result = NULL; } *type = type_found; } return result; } void * bro_record_get_named_val(BroRecord *rec, const char *name, int *type) { BroVal *val; int type_found; void *result = NULL; if (type && (*type < BRO_TYPE_UNKNOWN || *type >= BRO_TYPE_MAX)) { D(("Invalid value for type pointer (%i)\n", *type)); return NULL; } if (! (val = __bro_record_get_named_val(rec, name))) return NULL; /* Now transform the val into a form expected in *result, * based on the type given in the val. */ if (! __bro_val_get_data(val, &type_found, &result)) return NULL; if (type) { if (*type != BRO_TYPE_UNKNOWN && type_found != *type) { D(("Type mismatch: expected type tag %i for field '%s', found tag %i\n", *type, name, type_found)); result = NULL; } *type = type_found; } return result; } int bro_record_set_nth_val(BroRecord *rec, int num, int type, const char *type_name, const void *val) { BroVal *v; char *name; D_ENTER; if (! rec || num < 0 || num >= rec->val_len || type < 0 || type >= BRO_TYPE_MAX || ! val) { D(("Input error: (%p, %i, %i, %p)\n", rec, num, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_record_get_nth_val(rec, num))) D_RETURN_(FALSE); if (! (name = __bro_sobject_data_get((BroSObject *) v, "field"))) D_RETURN_(FALSE); if (! (v = __bro_val_new_of_type(type, type_name))) { D(("Could not get val of type %i\n", type)); D_RETURN_(FALSE); } __bro_sobject_data_set((BroSObject *) v, "field", strdup(name)); if (! __bro_val_assign(v, val)) { D(("Could not assign value to the new val.\n")); __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_record_set_nth_val(rec, num, v); D_RETURN_(TRUE); } int bro_record_set_named_val(BroRecord *rec, const char *name, int type, const char *type_name, const void *val) { BroVal *v; D_ENTER; if (! rec || ! name || !*name || type < 0 || type >= BRO_TYPE_MAX || ! val) { D(("Input error: (%p, %s, %i, %p)\n", rec, name, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) { D(("Could not get val of type %i\n", type)); D_RETURN_(FALSE); } if (! __bro_val_assign(v, val)) { D(("Could not assign value to the new val.\n")); __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_record_set_named_val(rec, name, v); D_RETURN_(TRUE); } /* -------------------------- Tables & Sets -------------------------- */ BroTable * bro_table_new(void) { BroTable *tbl; D_ENTER; tbl = __bro_table_new(); D_RETURN_(tbl); } void bro_table_free(BroTable *tbl) { D_ENTER; __bro_table_free(tbl); D_RETURN; } int bro_table_insert(BroTable *tbl, int key_type, const void *key, int val_type, const void *val) { BroVal *vv = NULL; BroListVal *lv; D_ENTER; if (! tbl || !key || !val) D_RETURN_(FALSE); if (tbl->tbl_key_type != BRO_TYPE_UNKNOWN && tbl->tbl_key_type != key_type) { D(("Type mismatch when inserting key of type %d, expecting %d\n", key_type, tbl->tbl_key_type)); D_RETURN_(FALSE); } tbl->tbl_key_type = key_type; if (tbl->tbl_val_type != BRO_TYPE_UNKNOWN && tbl->tbl_val_type != val_type) { D(("Type mismatch when inserting val of type %d, expecting %d\n", val_type, tbl->tbl_val_type)); D_RETURN_(FALSE); } tbl->tbl_val_type = val_type; /* Now need to creat BroVals out of the raw data provided. * If the key_type is BRO_TYPE_LIST, it means the argument * is expected to be a BroRecord and its elements will be * used as elements of a list of values, as used internally * by Bro. For all other BRO_TYPE_xxx values, the type is * used in the obvious way. */ lv = __bro_list_val_new(); if (key_type == BRO_TYPE_LIST) { /* We need to unroll the record elements and put them * all in the list val. */ BroRecord *rec = (BroRecord*) key; int i; for (i = 0; i < __bro_record_get_length(rec); i++) { /* We can here leverage the fact that internally, all * elements of a BroRec are BroVals. */ BroVal *v = __bro_record_get_nth_val(rec, i); BroVal *v_copy = (BroVal*) __bro_sobject_copy((BroSObject*) v); __bro_list_val_append(lv, v_copy); } } else { BroVal *kv; /* In this case we actually need to create a BroVal from * the user's raw data first. */ if (! (kv = __bro_val_new_of_type(key_type, NULL))) { D(("Could not create val of type %d\n", key_type)); __bro_sobject_release((BroSObject*) lv); D_RETURN_(FALSE); } __bro_val_assign(kv, key); __bro_list_val_append(lv, kv); } if (val) { if (! (vv = __bro_val_new_of_type(val_type, NULL))) { D(("Could not crate val of type %d\n", val_type)); __bro_sobject_release((BroSObject*) lv); D_RETURN_(FALSE); } __bro_val_assign(vv, val); } __bro_table_insert(tbl, (BroVal*) lv, vv); D_RETURN_(TRUE); } void * bro_table_find(BroTable *tbl, const void *key) { BroListVal *lv; BroVal *val, *result_val; void *result = NULL; BroRecord *rec = NULL; D_ENTER; lv = __bro_list_val_new(); if (tbl->tbl_key_type == BRO_TYPE_LIST) { /* Need to interpret the given key as a record and hook its * elements into the list. Below we unhook the list from the * ListVal before releasing it. */ rec = (BroRecord *) key; lv->list = rec->val_list; lv->len = rec->val_len; } else { if (! (val = __bro_val_new_of_type(tbl->tbl_key_type, NULL))) { D(("Could not create val of type %d.\n", tbl->tbl_key_type)); __bro_sobject_release((BroSObject*) lv); D_RETURN_(NULL); } __bro_val_assign(val, key); __bro_list_val_append(lv, val); } if ( (result_val = __bro_table_find(tbl, (BroVal*) lv))) { if (! __bro_val_get_data(result_val, NULL, &result)) { __bro_sobject_release((BroSObject*) lv); D_RETURN_(NULL); } } if (rec) { lv->list = NULL; lv->len = 0; } __bro_sobject_release((BroSObject*) lv); D_RETURN_(result); } int bro_table_get_size(BroTable *tbl) { int result; D_ENTER; result = __bro_table_get_size(tbl); D_RETURN_(result); } typedef struct bro_table_cb_data { void *user_data; BroTableCallback cb; int is_set; } BroTableCBData; static int bro_table_foreach_cb(BroListVal *key, BroVal *val, BroTableCBData *data) { int result; void *key_data = NULL, *val_data = NULL; BroRecord *rec = NULL; if (__bro_list_val_get_length(key) > 1) { /* Need to shrink-wrap it into a record. */ BroList *l; rec = __bro_record_new(); for (l = key->list; l; l = __bro_list_next(l)) { BroVal *tmp = (BroVal*) __bro_list_data(l); /* __bro_record_add_val() does not internally copy the added * val. Without bumping up the val's refcount, __bro_record_free() * below would possibly nuke the val when it decrements the count * by 1. */ __bro_sobject_ref((BroSObject*) tmp); __bro_record_add_val(rec, tmp); } key_data = (void*) rec; } else { /* Direct passthrough. */ BroVal *v = __bro_list_val_get_front(key); D(("Index type is atomic, type %d/%d\n", v->val_type->tag, v->val_type->internal_tag)); if (! __bro_val_get_data(v, NULL, &key_data)) { D(("Failed to obtain user-suitable data representation.\n")); return TRUE; } } if (! data->is_set && ! __bro_val_get_data(val, NULL, &val_data)) { D(("Failed to obtain user-suitable data representation.\n")); result = FALSE; goto return_result; } result = data->cb(key_data, val_data, data->user_data); return_result: if (rec) __bro_record_free(rec); return result; } void bro_table_foreach(BroTable *tbl, BroTableCallback cb, void *user_data) { BroTableCBData data; D_ENTER; data.user_data = user_data; data.cb = cb; data.is_set = __bro_table_is_set(tbl); __bro_table_foreach(tbl, (BroTableCallback) bro_table_foreach_cb, &data); D_RETURN; } void bro_table_get_types(BroTable *tbl, int *key_type, int *val_type) { if (! tbl) return; if (key_type) *key_type = tbl->tbl_key_type; if (val_type) *val_type = tbl->tbl_val_type; } BroSet * bro_set_new(void) { BroSet *result; D_ENTER; result = (BroSet*) __bro_table_new(); D_RETURN_(result); } void bro_set_free(BroSet *set) { D_ENTER; __bro_table_free((BroTable*) set); D_RETURN; } int bro_set_insert(BroSet *set, int type, const void *val) { int result; D_ENTER; result = bro_table_insert((BroTable*) set, type, val, BRO_TYPE_UNKNOWN, NULL); D_RETURN_(result); } int bro_set_find(BroSet *set, const void *key) { int result; D_ENTER; result = (bro_table_find((BroTable*) set, key) != NULL); D_RETURN_(result); } int bro_set_get_size(BroSet *set) { int result; D_ENTER; result = __bro_table_get_size((BroTable*) set); D_RETURN_(result); } typedef struct bro_set_cb_data { void *user_data; BroSetCallback cb; } BroSetCBData; static int bro_set_foreach_cb(void *key, void *val, BroSetCBData *data) { return data->cb(key, data->user_data); } void bro_set_foreach(BroSet *set, BroSetCallback cb, void *user_data) { BroSetCBData data; D_ENTER; data.user_data = user_data; data.cb = cb; bro_table_foreach((BroTable*) set, (BroTableCallback) bro_set_foreach_cb, &data); D_RETURN; } void bro_set_get_type(BroSet *set, int *type) { return bro_table_get_types((BroTable*) set, type, NULL); } /* ------------------------------ Strings ---------------------------- */ void bro_string_init(BroString *bs) { if (! bs) return; memset(bs, 0, sizeof(BroString)); } int bro_string_set(BroString *bs, const char *s) { if (! bs || !s) return FALSE; return bro_string_set_data(bs, (const uchar *) s, strlen(s)); } int bro_string_set_data(BroString *bs, const uchar *data, int data_len) { uchar *data_copy; if (! bs || !data || data_len < 0) return FALSE; if (! (data_copy = malloc(data_len + 1))) { D(("Out of memory in bro_string_set_data.\n")); return FALSE; } memcpy(data_copy, data, data_len); data_copy[data_len] = '\0'; bs->str_len = data_len; bs->str_val = data_copy; return TRUE; } const uchar * bro_string_get_data(const BroString *bs) { return bs ? bs->str_val : NULL; } uint32 bro_string_get_length(const BroString *bs) { return bs ? bs->str_len : 0; } BroString * bro_string_copy(BroString *bs) { BroString *result; if (! bs) return NULL; if (! (result = calloc(1, sizeof(BroString)))) { D(("Unable to allocate memory for BroString in bro_string_copy.\n")); return NULL; } bro_string_assign(bs, result); return result; } void bro_string_assign(BroString *src, BroString *dst) { if (! src || ! dst) return; bro_string_cleanup(dst); dst->str_len = src->str_len; if (! (dst->str_val = malloc(dst->str_len + 1))) { D(("Out of memory.\n")); dst->str_len = 0; return; } memcpy(dst->str_val, src->str_val, dst->str_len); dst->str_val[dst->str_len] = '\0'; } void bro_string_cleanup(BroString *bs) { if (! bs) return; if (bs->str_val) free(bs->str_val); memset(bs, 0, sizeof(BroString)); } void bro_string_free(BroString *bs) { if (! bs) return; bro_string_cleanup(bs); free(bs); } /* ----------------------------- Vectors ----------------------------- */ BroVector * bro_vector_new(void) { return __bro_vector_new(); } void bro_vector_free(BroVector *vec) { __bro_vector_free(vec); } int bro_vector_get_length(BroVector *vec) { return __bro_vector_get_length(vec); } int bro_vector_add_val(BroVector *vec, int type, const char *type_name, const void *val) { BroVal *v; D_ENTER; if (! vec) { D(("Input error: (%p, %i, %p)\n", vec, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) { D(("Could not get val of type %i\n", type)); D_RETURN_(FALSE); } if (! __bro_val_assign(v, val)) { D(("Could not assign value to the new val.\n")); __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_vector_add_val(vec, v); D_RETURN_(TRUE); } void* bro_vector_get_nth_val(BroVector *vec, int num, int *type) { BroVal *val; int type_found; void *result = NULL; if (type && (*type < BRO_TYPE_UNKNOWN || *type >= BRO_TYPE_MAX)) { D(("Invalid value for type pointer (%i)\n", *type)); return NULL; } if (! (val = __bro_vector_get_nth_val(vec, num))) return NULL; /* Now transform the val into a form expected in *result, * based on the type given in the val. */ if (! __bro_val_get_data(val, &type_found, &result)) return NULL; if (type) { if (*type != BRO_TYPE_UNKNOWN && type_found != *type) { D(("Type mismatch: expected type tag %i, found type tag %i\n", *type, type_found)); result = NULL; } *type = type_found; } return result; } int bro_vector_set_nth_val(BroVector *vec, int num, int type, const char *type_name, const void *val) { BroVal *v; D_ENTER; if (! vec || num < 0 || num >= vec->length || type < 0 || type >= BRO_TYPE_MAX || ! val) { D(("Input error: (%p, %i, %i, %p)\n", vec, num, type, val)); D_RETURN_(FALSE); } if (! (v = __bro_val_new_of_type(type, type_name))) { D(("Could not get val of type %i\n", type)); D_RETURN_(FALSE); } if (! __bro_val_assign(v, val)) { D(("Could not assign value to the new val.\n")); __bro_sobject_release((BroSObject *) v); D_RETURN_(FALSE); } __bro_vector_set_nth_val(vec, num, v); D_RETURN_(TRUE); } /* ----------------------- Pcap Packet Handling ---------------------- */ #ifdef BRO_PCAP_SUPPORT void bro_conn_set_packet_ctxt(BroConn *bc, int link_type) { if (! bc) return; bc->pcap_link_type = link_type; } void bro_conn_get_packet_ctxt(BroConn *bc, int *link_type) { if (! bc) return; if (link_type) *link_type = bc->pcap_link_type; } BroPacket * bro_packet_new(const struct pcap_pkthdr *hdr, const u_char *data, const char *tag) { BroPacket *packet; if (! hdr || ! data) return NULL; if (! (packet = calloc(1, sizeof(BroPacket)))) { D(("Unable to allocate memory for packet in bro_packet_new.\n")); return NULL; } packet->pkt_pcap_hdr = *hdr; packet->pkt_tag = strdup(tag ? tag : ""); if (! (packet->pkt_data = malloc(hdr->caplen))) { D(("Unable to allocate memory for pkt->data in bro_packet_new.\n")); free(packet); return NULL; } memcpy((u_char *) packet->pkt_data, data, hdr->caplen); return packet; } BroPacket * bro_packet_clone(const BroPacket *src) { BroPacket *dst; if (! (dst = calloc(1, sizeof(BroPacket)))) { D(("Unable to allocate memory in bro_packet_clone.\n")); return NULL; } if (! __bro_packet_clone(dst, src)) { bro_packet_free(dst); return NULL; } return dst; } void bro_packet_free(BroPacket *packet) { if (! packet) return; if (packet->pkt_data) free((u_char *) packet->pkt_data); if (packet->pkt_tag) free((u_char *) packet->pkt_tag); free(packet); } int bro_packet_send(BroConn *bc, BroPacket *packet) { if (! bc || ! packet) { D(("Invalid input.\n")); return FALSE; } return __bro_io_packet_queue(bc, packet); } #endif /* --------------------------- Miscellaneous ------------------------- */ double bro_util_current_time(void) { return __bro_util_get_time(); } double bro_util_timeval_to_double(const struct timeval *tv) { return __bro_util_timeval_to_double(tv); } int bro_util_is_v4_addr(const BroAddr *a) { return __bro_util_is_v4_addr(a); } const uint8 BRO_IPV4_MAPPED_PREFIX[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; broccoli-1.97-minimal/src/bro_event.c0000664002342100234210000001251412523041064017426 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include BroEvent * __bro_event_new(BroString *name) { BroEvent *ev; if (!name) return NULL; if (! (ev = calloc(1, sizeof(BroEvent)))) return NULL; if (! bro_string_set_data(&(ev->name), name->str_val, name->str_len)) { free(ev); return NULL; } return ev; } void __bro_event_free(BroEvent *ev) { if (!ev) return; bro_string_cleanup(&ev->name); __bro_list_free(ev->val_list, (BroFunc) __bro_sobject_release); free(ev); } BroEvent * __bro_event_copy(BroEvent *ev) { BroEvent *ev_copy; BroVal *val, *val_copy; BroList *l; if (! ev) return NULL; if (! (ev_copy = __bro_event_new(&ev->name))) return NULL; for (l = ev->val_list; l; l = __bro_list_next(l)) { val = __bro_list_data(l); if (! (val_copy = (BroVal *) __bro_sobject_copy((BroSObject *) val))) { __bro_event_free(ev_copy); return NULL; } __bro_event_add_val(ev_copy, val_copy); } D(("Copied event has %i arguments.\n", __bro_list_length(ev->val_list))); return ev_copy; } const char * __bro_event_get_name(BroEvent *ev) { if (! ev) return NULL; return (const char*) ev->name.str_val; } int __bro_event_serialize(BroEvent *ev, BroConn *bc) { BroVal *val; BroList *l; D_ENTER; /* Prepare the beginning of a serialized event call -- * event identifier, event name plus argument description. */ if (! __bro_buf_write_char(bc->tx_buf, 'e')) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &ev->name)) D_RETURN_(FALSE); if (! __bro_buf_write_double(bc->tx_buf, __bro_util_get_time())) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, ev->val_len)) D_RETURN_(FALSE); /* Now serialize each remaining parameter into the buffer: */ D(("Serializing event parameters\n")); for (l = ev->val_list; l; l = __bro_list_next(l)) { val = __bro_list_data(l); if (! __bro_sobject_serialize((BroSObject *) val, bc)) D_RETURN_(FALSE); D((" Serialized one argument\n")); } D_RETURN_(TRUE); } BroEvent * __bro_event_unserialize(BroConn *bc) { int i; BroString ev_name; double ev_ts; uint32 ev_args; BroEvent *ev = NULL; BroVal *val = NULL; D_ENTER; if (! __bro_buf_read_string(bc->rx_buf, &ev_name)) { D(("Couldn't read event name.\n")); D_RETURN_(NULL); } if (! __bro_buf_read_double(bc->rx_buf, &ev_ts)) { D(("Couldn't read event time.\n")); bro_string_cleanup(&ev_name); D_RETURN_(NULL); } if (! __bro_buf_read_int(bc->rx_buf, &ev_args)) { D(("Couldn't read number of event arguments.\n")); bro_string_cleanup(&ev_name); D_RETURN_(NULL); } D(("Reading %i arguments for event %s\n", ev_args, ev_name.str_val)); ev = __bro_event_new(&ev_name); ev->ts = ev_ts; bro_string_cleanup(&ev_name); for (i = 0; i < (int) ev_args; i++) { D(("Reading parameter %i\n", i+1)); if (! (val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) { D(("Couldn't read parameter val %i.\n", i+1)); __bro_event_free(ev); D_RETURN_(NULL); } __bro_event_add_val(ev, val); } D_RETURN_(ev); } void __bro_event_add_val(BroEvent *ev, BroVal *v) { D_ENTER; ev->val_list = __bro_list_append(ev->val_list, v); ev->val_len++; D_RETURN; } int __bro_event_set_val(BroEvent *ev, int val_num, BroVal *v) { BroList *l; D_ENTER; if (val_num < 0 || val_num >= ev->val_len) { D(("Invalid val index: given %i, having %i elements.\n", val_num, ev->val_len)); D_RETURN_(FALSE); } if ( (l = __bro_list_nth(ev->val_list, val_num))) { BroVal *val = __bro_list_set_data(l, v); __bro_sobject_release((BroSObject *) val); D_RETURN_(TRUE); } D_RETURN_(FALSE); } broccoli-1.97-minimal/src/bro_sem_sysv.c0000664002342100234210000001251612523041064020157 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #define BRO_SEM_ATTEMPTS_MAX 50 #ifdef SEM_R #define BRO_SEMFLAGS SEM_A|SEM_R #else #define BRO_SEMFLAGS S_IRWXU #endif /* It's not my fault -- blame the standards and deviating * implementations for this goop. :( */ #if defined(BSD_HOST) && ! defined(__NetBSD__) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ /* Linux specific part: */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #endif struct bro_sem_impl { int sem_id; }; int __bro_sem_init(BroSem *sem, const BroConn *bc) { int sem_id = -1; union semun arg; D_ENTER; if (! sem || ! sem->sem_impl) D_RETURN_(FALSE); memset(sem, 0, sizeof(BroSem)); /* Attempt to allocate the semaphore set */ if ( (sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|BRO_SEMFLAGS)) < 0) { D(("semget error: %s\n", strerror(errno))); D_RETURN_(FALSE); } /* Initialize the semaphore. Note: I'm not 100% sure whether this * code is prone to the race condition that Stevens describes on * p. 284 of UNP Vol 2 (IPC). It would likely be safer to take * precautions, this is a FIXME. */ arg.val = 1; if (semctl(sem_id, 0, SETVAL, arg) < 0) { D(("semctl failed: %s\n", strerror(errno))); D_RETURN_(FALSE); } if (! (sem->sem_impl = calloc(1, sizeof(BroSemImpl)))) D_RETURN_(FALSE); sem->sem_impl->sem_id = sem_id; D_RETURN_(TRUE); bc = NULL; } void __bro_sem_cleanup(BroSem *sem) { D_ENTER; if (! sem || ! sem->sem_impl) D_RETURN; if (semctl(sem->sem_impl->sem_id, 0, IPC_RMID) < 0) { D(("semctl could not remove semaphore: %s.\n", strerror(errno))); } free(sem->sem_impl); memset(sem, 0, sizeof(BroSem)); D_RETURN; } int __bro_sem_attach(BroSem *sem) { /* Unused in SYSV. */ return TRUE; sem = NULL; } int __bro_sem_detach(BroSem *sem) { /* Unused in SYSV. */ return TRUE; sem = NULL; } int __bro_sem_decr(BroSem *sem) { struct sembuf opt; if (! sem || ! sem->sem_impl) return FALSE; /* This hopefully does the following atomically: * * (1) block until the semaphore's value becomes >= 1 * (2) subtracts 1 from the semaphore's value (i.e., sets it to 0) * (3) wakes up thread. * * This is how I parse Stevens UNP Vol 2 (IPC), p. 287. */ opt.sem_num = 0; opt.sem_op = -1; opt.sem_flg = 0; sem->sem_blocked++; if (semop(sem->sem_impl->sem_id, &opt, 1) < 0) { sem->sem_blocked--; return FALSE; } sem->sem_blocked--; return TRUE; } int __bro_sem_trydecr(BroSem *sem) { struct sembuf opt; if (! sem || ! sem->sem_impl) return FALSE; opt.sem_num = 0; opt.sem_op = -1; opt.sem_flg = IPC_NOWAIT; sem->sem_blocked++; if (semop(sem->sem_impl->sem_id, &opt, 1) < 0) { sem->sem_blocked--; return FALSE; } sem->sem_blocked--; return TRUE; } int __bro_sem_incr(BroSem *sem) { struct sembuf opt; if (! sem || ! sem->sem_impl) return FALSE; /* Add one to the semaphore's value. That one should * be easy ... */ opt.sem_num = 0; opt.sem_op = 1; opt.sem_flg = 0; if (semop(sem->sem_impl->sem_id, &opt, 1) < 0) return FALSE; return TRUE; } int __bro_sem_get(BroSem *sem, int *result) { if (! sem || ! sem->sem_impl || ! result) return FALSE; if (semctl(sem->sem_impl->sem_id, 0, GETVAL, result) < 0) { D(("semctl failed: %s\n", strerror(errno))); return FALSE; } return TRUE; } int __bro_sem_get_blocked(BroSem *sem, int *result) { if (! sem || ! sem->sem_impl || ! result) return FALSE; *result = sem->sem_blocked; return TRUE; } broccoli-1.97-minimal/src/bro_sem.h0000664002342100234210000000635312523041064017102 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_sem_h #define broccoli_sem_h #include typedef struct bro_sem_impl BroSemImpl; typedef struct bro_sem { int sem_blocked; BroSemImpl *sem_impl; } BroSem; /* Broccoli semaphore abstractions. * ================================ * * Semaphores are created with __bro_sem_new() and released with * __bro_sem_free(). Before being used they have to be * __bro_sem_attach()ed and after using them __bro_sem_detach()ed. * * Semaphores are initalized to 0. * * All functions can be called with NULL parameters, for robustness. */ int __bro_sem_init(BroSem *sem, const BroConn *bc); void __bro_sem_cleanup(BroSem *sem); int __bro_sem_attach(BroSem *sem); int __bro_sem_detach(BroSem *sem); /** * __bro_sem_decr - decreases semaphore. * @param sem semaphore. * * The function decreases the value of the semaphore by one, returning * if the initial value was greater than 0, and blocking otherwise. * * Returns: %TRUE on success, %FALSE otherwise. */ int __bro_sem_decr(BroSem *sem); /** * __bro_sem_trydecr - decreases semaphore, but never blocks * @param sem semaphore. * * The function decreases the value of the semaphore by one, returning * if the initial value was greater than 0. If the semaphore is * currently locked, the function returns %FALSE immediately. * * Returns: %TRUE on success, %FALSE otherwise. */ int __bro_sem_trydecr(BroSem *sem); /** * __bro_sem_incr - increases semaphore. * @param sem: semaphore. * * The function increases the value of the semaphore by 1. * * Returns: %TRUE on success, %FALSE otherwise. */ int __bro_sem_incr(BroSem *sem); /** * __bro_sem_get - returns current value of sempahore. * @param sem semaphore. * @param result result pointer. * * The function returns the current value of the semaphore through * the @p result pointer. * * Returns: %TRUE on success, %FALSE otherwise. */ int __bro_sem_get(BroSem *sem, int *result); int __bro_sem_get_blocked(BroSem *sem, int *result); #endif broccoli-1.97-minimal/src/bro_buf.h0000664002342100234210000001143612523041064017070 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_buf_h #define broccoli_buf_h #include #include /* * BroBufs are self-allocating, seekable, and read/writable * buffers. You can repeatedly append data to the buffer * while the buffer makes sure it is large enough to handle * the amount requested. A buffer has a content pointer that * points to an arbitrary location between the start of the * buffer and the first byte after the last byte currently * used in the buffer (buf_off). The content pointer can be * seeked to arbitrary locations, and data can be copied from * the buffer, adjusting the content pointer at the same time. * * Illustration: * * <---------------- allocated buffer space ------------> * <======== used buffer space ========> * ^ ^ ^ ^ * | | | | * `buf `buf_ptr `buf_off `buf_len */ struct bro_buf { uchar *buf; /* The size of the allocated buffer BUF: */ uint32 buf_len; /* The first byte in BUF after the ones occupied */ uint32 buf_off; /* A pointer to a position between the start of BUF * and BUF + BUF_OFF. */ uint32 buf_ptr; /* Flag that indicates whether or not the allocated buffer * can grow or not. It can't if we require the buffer to * live in a fixed amount of memory. */ int may_grow; }; /* See API comments in broccoli.h for details */ BroBuf *__bro_buf_new(void); /* Creates a new buffer using a given chunk of memory. We use * this for example to allocate a buffer in shared memory. */ BroBuf *__bro_buf_new_mem(u_char *mem, int mem_size); void __bro_buf_free(BroBuf *buf); /* Initializes an existing buffer structure to default values */ void __bro_buf_init(BroBuf *buf); void __bro_buf_cleanup(BroBuf *buf); int __bro_buf_append(BroBuf *buf, void *data, int data_len); void __bro_buf_consume(BroBuf *buf); void __bro_buf_reset(BroBuf *buf); uchar *__bro_buf_get(BroBuf *buf); uchar *__bro_buf_get_end(BroBuf *buf); uint __bro_buf_get_size(BroBuf *buf); uint __bro_buf_get_used_size(BroBuf *buf); uchar *__bro_buf_ptr_get(BroBuf *buf); uint32 __bro_buf_ptr_tell(BroBuf *buf); int __bro_buf_ptr_seek(BroBuf *buf, int offset, int whence); int __bro_buf_ptr_check(BroBuf *buf, int size); int __bro_buf_ptr_read(BroBuf *buf, void *data, int size); int __bro_buf_ptr_write(BroBuf *buf, const void *data, int size); /* Buffer-based I/O API --------------------------------------------- */ /* The read functions read data from the given buffer into the variables * pointed to by the arguments, the write functions to the opposite and * write the passed-in parameters into the given buffers. */ int __bro_buf_read_data(BroBuf *buf, void *dest, int size); int __bro_buf_read_char(BroBuf *buf, char *val); int __bro_buf_read_string(BroBuf *buf, BroString *val); int __bro_buf_read_double(BroBuf *buf, double *d); int __bro_buf_read_int(BroBuf *buf, uint32 *i); int __bro_buf_read_int64(BroBuf *buf, uint64 *i); int __bro_buf_read_short(BroBuf *buf, uint16 *i); int __bro_buf_write_data(BroBuf *buf, const void *data, int size); int __bro_buf_write_char(BroBuf *buf, char val); int __bro_buf_write_string(BroBuf *buf, BroString *val); int __bro_buf_write_double(BroBuf *buf, double d); int __bro_buf_write_int(BroBuf *buf, uint32 i); int __bro_buf_write_int64(BroBuf *buf, uint64 i); int __bro_buf_write_short(BroBuf *buf, uint16 i); #endif broccoli-1.97-minimal/src/bro_location.c0000664002342100234210000001132612523041064020115 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include BroLoc * __bro_loc_new(void) { BroLoc *loc; D_ENTER; if (! (loc = calloc(1, sizeof(BroLoc)))) { D_RETURN_(NULL); } __bro_loc_init(loc); D_RETURN_(loc); } void __bro_loc_init(BroLoc *loc) { BroSObject *sobj = (BroSObject *) loc; D_ENTER; __bro_sobject_init(sobj); sobj->read = (BroSObjectRead) __bro_loc_read; sobj->write = (BroSObjectWrite)__bro_loc_write; sobj->free = (BroSObjectFree) __bro_loc_free; sobj->clone = (BroSObjectClone) __bro_loc_clone; sobj->hash = (BroSObjectHash) __bro_loc_hash; sobj->cmp = (BroSObjectCmp) __bro_loc_cmp; sobj->type_id = SER_LOCATION; bro_string_init(&loc->filename); D_RETURN; } void __bro_loc_free(BroLoc *loc) { D_ENTER; if (! loc) D_RETURN; bro_string_cleanup(&loc->filename); __bro_sobject_free((BroSObject *) loc); D_RETURN; } int __bro_loc_read(BroLoc *loc, BroConn *bc) { D_ENTER; if (! loc || ! bc) D_RETURN_(FALSE); if (! __bro_sobject_read((BroSObject *) loc, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &loc->filename)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &loc->first_line)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &loc->last_line)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &loc->first_column)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &loc->last_column)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_loc_write(BroLoc *loc, BroConn *bc) { D_ENTER; if (! loc || ! bc) D_RETURN_(FALSE); if (! __bro_sobject_write((BroSObject *) loc, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &loc->filename)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, loc->first_line)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, loc->last_line)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, loc->first_column)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, loc->last_column)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_loc_clone(BroLoc *dst, BroLoc *src) { BroString *string; D_ENTER; if (! __bro_sobject_clone((BroSObject *) dst, (BroSObject *) src)) D_RETURN_(FALSE); if (! (string = bro_string_copy(&src->filename))) D_RETURN_(FALSE); dst->filename = *string; free(string); dst->first_line = src->first_line; dst->last_line = src->last_line; dst->first_column = src->first_column; dst->last_column = src->last_column; D_RETURN_(TRUE); } uint32 __bro_loc_hash(BroLoc *loc) { uint32 result; D_ENTER; if (! loc) D_RETURN_(0); result = __bro_ht_str_hash(loc->filename.str_val); result ^= loc->first_line; result ^= loc->last_line; result ^= loc->first_column; result ^= loc->last_column; D_RETURN_(result); } int __bro_loc_cmp(BroLoc *loc1, BroLoc *loc2) { D_ENTER; if (! __bro_ht_str_cmp(loc1->filename.str_val, loc2->filename.str_val)) D_RETURN_(FALSE); if (loc1->first_line != loc2->first_line || loc1->last_line != loc2->last_line || loc1->first_column < loc2->first_column || loc1->last_column < loc2->last_column || loc1->last_column > loc2->last_column) D_RETURN_(FALSE); D_RETURN_(TRUE); } broccoli-1.97-minimal/src/bro_sem_none.c0000664002342100234210000000325412523041064020111 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include struct bro_sem { }; BroSem * __bro_sem_new(const BroConn *bc) { bc = NULL; return NULL; } void __bro_sem_free(BroSem *sem) { sem = NULL; } int __bro_sem_attach(BroSem *sem) { return TRUE; sem = NULL; } int __bro_sem_detach(BroSem *sem) { return TRUE; sem = NULL; } int __bro_sem_decr(BroSem *sem) { sem = NULL; } int __bro_sem_incr(BroSem *sem) { sem = NULL; } broccoli-1.97-minimal/src/bro_io.h0000664002342100234210000001112512523041064016716 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_io_h #define broccoli_io_h #include #include /** * __bro_io_msg_new -- allocates a new message destined to a given peer. */ BroMsg * __bro_io_msg_new(char type, uint32 peer_id); /** * __bro_io_msg_free -- releases message plus any data hooked into it. * @param msg msg to free. */ void __bro_io_msg_free(BroMsg *msg); /** * __bro_io_msg_set_cont -- sets the content of a message. * @param msg message to set content of. * @param type type of the message, a BRO_MSG_CONT_xxx constant. * @param content the content itself. * * The function sets @p msg's content, of given @p type, to @p content. * Note that __bro_io_msg_free will release the data pointed to * by @p content, depending on @p type! */ void __bro_io_msg_set_cont(BroMsg *msg, int type, void *content); int __bro_io_msg_queue_flush(BroConn *bc); void __bro_io_msg_queue_dump(BroConn *bc, const char *message); /** * __bro_io_raw_queue -- enqueues raw data. * @param bc connection handle. * @param type type of the message, a BRO_MSG_xxx value. * @param data raw bytes of data * @param data_len length of @p data. * * The function enqueues a message containing raw data for a * message of type @p type. * * @returns %FALSE on error, %TRUE otherwise. */ int __bro_io_raw_queue(BroConn *bc, int type, uchar *data, int data_len); /** * __bro_io_rawbuf_queue -- enqueues raw buffer data. * @param bc connection handle. * @param type type of the message, a BRO_MSG_xxx value. * @param buf buffer with payload to be enqueued. * * The function enqueues a message containing raw buffer data for a * message of type @p type. * * NOTE: @p buf's ownership is taken over by the function. You do not * need to clean it up, and should not expect the pointer to it to * remain valid. * * @returns %FALSE on error, %TRUE otherwise. */ int __bro_io_rawbuf_queue(BroConn *bc, int type, BroBuf *buf); /** * __bro_io_event_queue -- enqueues an event. * @param bc connection handle. * @param ev event handle. * * The function enqueues an event for later transmission. * * @returns %FALSE on error, %TRUE otherwise. */ int __bro_io_event_queue(BroConn *bc, BroEvent *ev); /** * __bro_io_request_queue -- enqueues a request. * @param bc connection handle. * @param req request handle. * * The function enqueues an request for later transmission. * * @returns %FALSE on error, %TRUE otherwise. */ int __bro_io_request_queue(BroConn *bc, BroRequest *req); #ifdef BRO_PCAP_SUPPORT /** * __bro_io_packet_queue - enqueues a pcap packet. * @param bc connection handle. * @param packet pcap packet. * * The function enqueues a pcap packet wrapped via bro_packet_new() * for later transmission. * * @returns %FALSE on error, %TRUE otherwise. */ int __bro_io_packet_queue(BroConn *bc, BroPacket *packet); #endif int __bro_io_process_input(BroConn *bc); void __bro_io_writer_loop(BroConn *bc); /** * __bro_io_loop -- performs I/O in the handler process. * @param bc connection handle. * * This function is the implementation of the I/O handler processes. * It sits in a blocking loop and depending on the request sent to it via * bc->state->io_msg it performs the requested I/O operation. It does not * return unless the connection encounters an error or teardown is requested. */ void __bro_io_loop(BroConn *bc); #endif broccoli-1.97-minimal/src/bro_io.c0000664002342100234210000006754712523041064016734 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #ifdef __MINGW32__ #include #else #include #include #endif #include #include #include #include #include #include #include #include #include #include #ifdef BRO_PCAP_SUPPORT #include #endif /* A static array that can translate message types into strings so * it's clearer what's going on when debugging: */ static char * msg_type_str[] = { "BRO_MSG_NONE", "BRO_MSG_VERSION", "BRO_MSG_SERIAL", "BRO_MSG_CLOSE", "BRO_MSG_CLOSE_ALL", "BRO_MSG_ERROR", "BRO_MSG_CONNECTTO", "BRO_MSG_CONNECTED", "BRO_MSG_REQUEST", "BRO_MSG_LISTEN", "BRO_MSG_LISTEN_STOP", "BRO_MSG_STATS", "BRO_MSG_CAPTURE_FILTER", "BRO_MSG_REQUEST_SYNC", "BRO_MSG_PHASE_DONE", "BRO_MSG_PING", "BRO_MSG_PONG", "BRO_MSG_CAPS", "BRO_MSG_COMPRESS", }; static const char * msg_type_2_str(int type) { if (type < 0 || type >= BRO_MSG_MAX) return ""; return msg_type_str[type]; } /* The maximum number of attempts we make in one go in order * to extract data from the pipe. It appears that OpenSSL does * not fully hide the record-oriented transfer and repeated * writes at one end also require repeated reads at the other * end. If anyone can confirm or deny this, please get in touch. */ #define BRO_BIO_READ_ROUNDS_MAX 20 /* Reading-related --------------------------------------------------- */ static int io_read_chunk_size(BroConn *bc, uint32 *chunk_size) { if (! __bro_buf_ptr_read(bc->rx_buf, chunk_size, sizeof(uint32))) { D(("Couldn't read chunk size\n")); return FALSE; } *chunk_size = ntohl(*chunk_size); if (! __bro_buf_ptr_check(bc->rx_buf, *chunk_size)) { D(("Not all chunk data available\n")); return FALSE; } D(("We have a chunk of size %i\n", *chunk_size)); return TRUE; } static int io_read_msg_hdr(BroConn *bc, BroMsgHeader *msg_hdr) { if (! __bro_buf_ptr_read(bc->rx_buf, msg_hdr, sizeof(BroMsgHeader))) { D(("Couldn't read message header\n")); return FALSE; } msg_hdr->hdr_peer_id = ntohs(msg_hdr->hdr_peer_id); return TRUE; } static int io_msg_fill_rx(BroConn *bc) { BroBuf tmp_buf; int i, n, total = 0; if (bc->state->rx_dead) { if (! (bc->conn_flags & BRO_CFLAG_RECONNECT)) return FALSE; D(("Connection dead and we want to reconnect ...\n")); if (! bro_conn_reconnect(bc)) return FALSE; } for (i = 0; i < BRO_BIO_READ_ROUNDS_MAX; i++) { __bro_buf_init(&tmp_buf); n = __bro_openssl_read(bc, __bro_buf_get(&tmp_buf), __bro_buf_get_size(&tmp_buf)); if (n <= 0) { __bro_buf_cleanup(&tmp_buf); if (n < 0) { D(("Read returned error after %i/%i rounds and %i bytes\n", i, BRO_BIO_READ_ROUNDS_MAX, total)); return -1; } #ifdef BRO_DEBUG if (total > 0) D(("Read %i bytes in %i/%i rounds.\n", total, i, BRO_BIO_READ_ROUNDS_MAX)); #endif if (total == 0) continue; return total; } __bro_buf_append(bc->rx_buf, __bro_buf_get(&tmp_buf), n); __bro_buf_cleanup(&tmp_buf); total += n; } D(("Read %i bytes in %i/%i rounds.\n", total, i, BRO_BIO_READ_ROUNDS_MAX)); return total; } static int io_skip_chunk(BroBuf *buf, uint32 buf_off, uint32 chunk_size) { if (! buf) return FALSE; if (! __bro_buf_ptr_seek(buf, buf_off, SEEK_SET)) return FALSE; /* We skip a uint32 for the chunk size and then chunk_size * bytes. */ if (! __bro_buf_ptr_seek(buf, sizeof(uint32) + chunk_size, SEEK_CUR)) return FALSE; D(("Skipping %i + %i\n", sizeof(uint32), chunk_size)); return TRUE; } static int io_process_serialization(BroConn *bc) { BroVal vbuf; D_ENTER; if (! __bro_buf_read_char(bc->rx_buf, &vbuf.val_char)) { D(("Couldn't read serialization type\n")); D_RETURN_(FALSE); } switch (vbuf.val_char) { case 'e': { BroEvent *ev; bc->rx_ev_start = (const char*) bro_buf_ptr_get(bc->rx_buf); D(("Processing serialized event.\n")); if (! (ev = __bro_event_unserialize(bc))) { bc->rx_ev_start = bc->rx_ev_end = NULL; D_RETURN_(FALSE); } bc->rx_ev_end = (const char*) bro_buf_ptr_get(bc->rx_buf); __bro_event_reg_dispatch(bc, ev); __bro_event_free(ev); bc->rx_ev_start = bc->rx_ev_end = NULL; } break; case 'i': { BroID *id; D(("Processing serialized ID.\n")); if (! (id = (BroID *) __bro_sobject_unserialize(SER_IS_ID, bc))) D_RETURN_(FALSE); D(("ID read successfully.\n")); /* Except we don't do anything with it yet. :) */ __bro_sobject_release((BroSObject *) id); } break; case 'p': { #ifdef BRO_PCAP_SUPPORT BroPacket *packet; if (! (packet = __bro_packet_unserialize(bc))) D_RETURN_(FALSE); D(("Packet read successfully.\n")); bro_packet_free(packet); #else D_RETURN_(FALSE); #endif } break; default: /* We do not handle anything else yet -- just say * we are happy and return. */ D(("Unknown serialization of type %c\n", vbuf.val_char)); D_RETURN_(FALSE); } /* After a complete unserialization, we enforce the size limit * of the cache. We can't do it on the go as a new object that * is unserialized may still contain references to previously * cached items which we might evict. */ while (__bro_ht_get_size(bc->io_cache) > bc->io_cache_maxsize) __bro_ht_evict_oldest(bc->io_cache); D_RETURN_(TRUE); } /* Writing-related --------------------------------------------------- */ static int io_fill_raw(BroBuf *buf, BroBuf *data) { return __bro_buf_write_data(buf, __bro_buf_get(data), __bro_buf_get_used_size(data)); } static int io_fill_request(BroBuf *buf, BroRequest *req) { return __bro_buf_write_data(buf, req->req_dat, req->req_len); } static int io_fill_msg_header(BroBuf *buf, BroMsgHeader *mh) { mh->hdr_peer_id = htonl(mh->hdr_peer_id); return __bro_buf_write_data(buf, mh, sizeof(BroMsgHeader)); } static int io_msg_empty_tx(BroConn *bc) { int n; int todo; D_ENTER; if (bc->state->tx_dead && (bc->conn_flags & BRO_CFLAG_RECONNECT)) bro_conn_reconnect(bc); if (bc->state->tx_dead) { D(("Connection dead, not writing anything. Todo: %i\n", __bro_buf_get_used_size(bc->tx_buf))); D_RETURN_(FALSE); } /* This function loops until the entire buffer contents * are written out. This is not perfect but easier for now. * Revisit this as a FIXME. */ for ( ; ; ) { todo = __bro_buf_get_used_size(bc->tx_buf); if (todo == 0) D_RETURN_(TRUE); n = __bro_openssl_write(bc, __bro_buf_get(bc->tx_buf), todo); /* If we couldn't write out anything at all, then we report * failure. */ if (n < 0) { D(("SSL error -- nothing written.\n")); D_RETURN_(FALSE); } if (0 < n && n < todo) { /* We have an incomplete write. Consume what we were * able to write out. */ D(("*** Incomplete write: %i/%i\n", n, todo)); if (! __bro_buf_ptr_seek(bc->tx_buf, n, SEEK_SET)) { /* This should never happen. */ D(("*** Buffer contents are screwed :(\n")); D_RETURN_(FALSE); } __bro_buf_consume(bc->tx_buf); } D(("<<< Sent %i/%i bytes.\n", n, todo)); if (n == todo) { /* If we wrote out everything that was left, report success. */ __bro_buf_reset(bc->tx_buf); D_RETURN_(TRUE); } } } static int io_msg_fill_tx(BroConn *bc, BroMsg *msg) { int result = TRUE; D_ENTER; if (!bc || !msg) { D(("Input error.\n")); D_RETURN_(FALSE); } /* Check if anything is still left in the input buffer. In that case, * we don't fill anything in but return right away, so the message * gets queued. */ if (__bro_buf_get_used_size(bc->tx_buf) > 0) { D(("Buffer not empty; not filling!\n")); D_RETURN_(FALSE); } D((">>> Attempting write of %s\n", msg_type_2_str(msg->msg_header.hdr_type))); /* We will collect the message chunk in the connection's tx buffer. * We append stuff to it as we go along and at the end write it out. * When being sent, he buffer has the amount of octets to send at * the beginning, so the reader knows how much is coming. */ __bro_buf_reset(bc->tx_buf); msg->msg_header_size = sizeof(BroMsgHeader); if (! __bro_buf_write_int(bc->tx_buf, msg->msg_header_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } /* Hook in the Bro message header */ if (! io_fill_msg_header(bc->tx_buf, &msg->msg_header)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } if (msg->msg_cont_type != BRO_MSG_CONT_NONE) { uint32 msg_size_pos, msg_size_end; /* This starts another chunk of data (in Bro protocol speak), * but here we cannot yet know how big the chunk will be. * We save the offset in the buffer and return to it later, * overwriting the value with the then correct one. */ msg_size_pos = __bro_buf_get_used_size(bc->tx_buf); if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } /* Gather the payload of the message we are about * to send into the buffer BUF. */ switch (msg->msg_cont_type) { case BRO_MSG_CONT_RAW: D(("Filling raw data into buffer\n")); if (! io_fill_raw(bc->tx_buf, msg->msg_cont_raw)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; case BRO_MSG_CONT_EVENT: /* Check if the peer actually requested the event, and if not, * drop it silently (i.e., still return success). */ if (! __bro_ht_get(bc->ev_mask, msg->msg_cont_ev->name.str_val)) { D(("Event '%s' not requested by peer -- dropping.\n", msg->msg_cont_ev->name.str_val)); __bro_buf_reset(bc->tx_buf); /* This is not an error but a silent drop, so we * return success. */ D_RETURN_(TRUE); } D(("Filling event into buffer\n")); if (! __bro_event_serialize(msg->msg_cont_ev, bc)) { D(("Error during serialization.\n")); __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; case BRO_MSG_CONT_REQUEST: D(("Filling request into buffer\n")); if (! io_fill_request(bc->tx_buf, msg->msg_cont_req)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; #ifdef BRO_PCAP_SUPPORT case BRO_MSG_CONT_PACKET: if (! __bro_packet_serialize(msg->msg_cont_packet, bc)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; #endif default: D(("ERROR -- invalid message content code %i\n", msg->msg_cont_type)); break; } /* Now calculate length of entire transmission -- * we know where we wrote the uint32 containing the * size of the chunk, and we know where we are now, * so the length is their difference, minus the uint32 * itself. */ msg_size_end = __bro_buf_get_used_size(bc->tx_buf); msg->msg_size = msg_size_end - msg_size_pos - sizeof(uint32); D(("Serialized message sized %i bytes.\n", msg->msg_size)); if (! __bro_buf_ptr_seek(bc->tx_buf, msg_size_pos, SEEK_SET)) { D(("Cannot seek to position %u -- we're screwed.\n", msg_size_pos)); __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } } D_RETURN_(result); } static int io_msg_queue(BroConn *bc, BroMsg *msg) { D_ENTER; if (!bc || !msg) D_RETURN_(FALSE); /* If anything is left over in the buffer, write it out now. * We don't care if it succeeds or not. */ io_msg_empty_tx(bc); /* If the queue is empty, try to send right away. * If not, enqueue the event, and try to flush. */ D(("Enqueing msg of type %s\n", msg_type_2_str(msg->msg_header.hdr_type))); if (! bc->msg_queue.tqh_first) { D(("No queue yet.\n")); if (io_msg_fill_tx(bc, msg)) { D(("Message serialized.\n")); if (io_msg_empty_tx(bc)) { D(("Message sent.\n")); } __bro_io_msg_free(msg); bc->state->io_msg = BRO_IOMSG_WRITE; D_RETURN_(TRUE); } } if (bc->state->tx_dead && ! (bc->conn_flags & BRO_CFLAG_ALWAYS_QUEUE)) { D(("Connection %p disconnected, and no queuing requested: dropping message.\n", bc)); __bro_io_msg_free(msg); D_RETURN_(FALSE); } TAILQ_INSERT_TAIL(&bc->msg_queue, msg, msg_queue); bc->msg_queue_len++; D(("Queue length now %i\n", bc->msg_queue_len)); __bro_io_msg_queue_flush(bc); /* Check that the queue does not grow too big: */ while (bc->msg_queue_len > BRO_MSG_QUEUELEN_MAX) { BroMsg *msg = bc->msg_queue.tqh_first; TAILQ_REMOVE(&bc->msg_queue, msg, msg_queue); __bro_io_msg_free(msg); bc->msg_queue_len--; D(("Dropped one message due to excess queue length, now %i\n", bc->msg_queue_len)); } D_RETURN_(TRUE); } /* Non-static stuff below: ------------------------------------------- */ BroMsg * __bro_io_msg_new(char type, uint32 peer_id) { static int msg_counter = 0; BroMsg *msg; if (! (msg = calloc(1, sizeof(BroMsg)))) return NULL; msg->msg_header.hdr_type = type; msg->msg_header.hdr_peer_id = peer_id; msg->msg_cont_type = BRO_MSG_CONT_NONE; msg->msg_num = msg_counter++; return msg; } void __bro_io_msg_free(BroMsg *msg) { if (!msg) return; switch (msg->msg_cont_type) { case BRO_MSG_CONT_RAW: __bro_buf_free(msg->msg_cont_raw); break; case BRO_MSG_CONT_EVENT: __bro_event_free(msg->msg_cont_ev); break; case BRO_MSG_CONT_REQUEST: __bro_event_request_free(msg->msg_cont_req); break; #ifdef BRO_PCAP_SUPPORT case BRO_MSG_CONT_PACKET: bro_packet_free(msg->msg_cont_packet); break; #endif default: break; } free(msg); } void __bro_io_msg_set_cont(BroMsg *msg, int type, void *content) { if (!msg) return; msg->msg_cont_type = type; switch (type) { case BRO_MSG_CONT_RAW: msg->msg_cont_raw = (BroBuf*) content; D(("Setting raw buffer content for message, type now %i, buffer data: %p\n", msg->msg_cont_type, content)); break; case BRO_MSG_CONT_EVENT: msg->msg_cont_ev = (BroEvent *) content; D(("Setting event content for message, type now %i, event: %s\n", msg->msg_cont_type, msg->msg_cont.msg_ev->name.str_val)); break; case BRO_MSG_CONT_REQUEST: msg->msg_cont_req = (BroRequest *) content; D(("Setting request content for message, type now %i\n", msg->msg_cont_type)); break; #ifdef BRO_PCAP_SUPPORT case BRO_MSG_CONT_PACKET: msg->msg_cont_packet = (BroPacket *) content; break; #endif default: msg->msg_cont_type = BRO_MSG_CONT_NONE; } } int __bro_io_msg_queue_flush(BroConn *bc) { BroMsg *msg; int result; D_ENTER; if (! bc) D_RETURN_(-1); for ( ; ; ) { if (! io_msg_empty_tx(bc)) break; if (! (msg = bc->msg_queue.tqh_first)) break; if (! io_msg_fill_tx(bc, msg)) break; TAILQ_REMOVE(&bc->msg_queue, msg, msg_queue); __bro_io_msg_free(msg); bc->msg_queue_len--; bc->state->io_msg = BRO_IOMSG_WRITE; } result = bc->msg_queue_len; D_RETURN_(result); } void __bro_io_msg_queue_dump(BroConn *bc, const char *message) { BroMsg *msg; printf("%s: connection %p, length %i\n", message, bc, bc->msg_queue_len); for (msg = bc->msg_queue.tqh_first; msg; msg = msg->msg_queue.tqe_next) printf(" -- %s(%i)\n", msg_type_2_str(msg->msg_header.hdr_type), msg->msg_num); } int __bro_io_raw_queue(BroConn *bc, int type, uchar *data, int data_len) { BroMsg *msg; int result = FALSE; D_ENTER; if (!bc) D_RETURN_(FALSE); if (! (msg = __bro_io_msg_new(type, 0))) D_RETURN_(FALSE); if (data_len > 0) { BroBuf *buf; if (! (buf = __bro_buf_new())) { __bro_io_msg_free(msg); D_RETURN_(FALSE); } __bro_buf_append(buf, data, data_len); __bro_io_msg_set_cont(msg, BRO_MSG_CONT_RAW, buf); } result = io_msg_queue(bc, msg); D_RETURN_(result); } int __bro_io_rawbuf_queue(BroConn *bc, int type, BroBuf *buf) { BroMsg *msg; int result = FALSE; D_ENTER; if (!bc || !buf) D_RETURN_(FALSE); if (! (msg = __bro_io_msg_new(type, 0))) D_RETURN_(FALSE); __bro_io_msg_set_cont(msg, BRO_MSG_CONT_RAW, buf); result = io_msg_queue(bc, msg); D_RETURN_(result); } int __bro_io_event_queue(BroConn *bc, BroEvent *ev) { BroEvent *ev_copy; BroMsg *msg; int result; D_ENTER; if (!bc) D_RETURN_(FALSE); if (! (msg = __bro_io_msg_new(BRO_MSG_SERIAL, 0))) D_RETURN_(FALSE); if (! (ev_copy = __bro_event_copy(ev))) { D(("Could not clone event\n")); __bro_io_msg_free(msg); D_RETURN_(FALSE); } __bro_io_msg_set_cont(msg, BRO_MSG_CONT_EVENT, ev_copy); result = io_msg_queue(bc, msg); D_RETURN_(result); } int __bro_io_request_queue(BroConn *bc, BroRequest *req) { BroMsg *msg; int result; D_ENTER; if (!bc) D_RETURN_(FALSE); if (! (msg = __bro_io_msg_new(BRO_MSG_REQUEST, 0))) D_RETURN_(FALSE); __bro_io_msg_set_cont(msg, BRO_MSG_CONT_REQUEST, req); result = io_msg_queue(bc, msg); D_RETURN_(result); } #ifdef BRO_PCAP_SUPPORT int __bro_io_packet_queue(BroConn *bc, BroPacket *packet) { BroPacket *clone; BroMsg *msg; int result; D_ENTER; if (!bc) D_RETURN_(FALSE); if (! (msg = __bro_io_msg_new(BRO_MSG_SERIAL, 0))) D_RETURN_(FALSE); if (! (clone = bro_packet_clone(packet))) { __bro_io_msg_free(msg); D_RETURN_(FALSE); } __bro_io_msg_set_cont(msg, BRO_MSG_CONT_PACKET, clone); result = io_msg_queue(bc, msg); D_RETURN_(result); } #endif int __bro_io_process_input(BroConn *bc) { uint32 buf_off, chunk_size; BroMsgHeader msg_hdr; int result = FALSE; D_ENTER; /* Read all available data into receive buffer. Our socket is * nonblocking so if nothing's available we'll be back right * away. If nothing was read, the subsequent for loop will exit * right away, so the io_msg_fill_rx() return code need not be * checked here. */ io_msg_fill_rx(bc); /* Try to process as much in the input buffer as we can */ for ( ; ; ) { D(("----- Attempting to extract a message\n")); /* Get the current offset of the buffer pointer to make * sure we can reset to it if things go wrong. */ buf_off = __bro_buf_ptr_tell(bc->rx_buf); /* Now check the buffer contents and see if there's enough * for us to analyze it. Start with a uint32 for the size * of the first chunk, and then the chunk itself. */ if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (chunk_size != sizeof(BroMsgHeader)) { D(("Received chunk should be %i bytes, but is %i\n", sizeof(BroMsgHeader), chunk_size)); io_skip_chunk(bc->rx_buf, buf_off, chunk_size); result = TRUE; continue; } if (! io_read_msg_hdr(bc, &msg_hdr)) goto reset_return; switch (msg_hdr.hdr_type) { case BRO_MSG_REQUEST: { char *tmp = NULL, *tmp2 = NULL; D(("Received MSQ_REQUEST\n")); /* We need to read another chunk, whose data will contain * a sequence of 0-terminated strings, each one being the * name of an event that the peering Bro is interested in. */ if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (! (tmp = (char *) malloc(chunk_size * sizeof(char)))) goto reset_return; if (! __bro_buf_read_data(bc->rx_buf, tmp, chunk_size)) { free(tmp); goto reset_return; } for (tmp2 = tmp; tmp2 < tmp + chunk_size; tmp2 = tmp2 + strlen(tmp2) + 1) { char *key; if (__bro_ht_get(bc->ev_mask, tmp2)) continue; key = strdup(tmp2); __bro_ht_add(bc->ev_mask, key, key); D(("Will report event '%s'\n", tmp2)); } D(("Now reporting %i event(s).\n", __bro_ht_get_size(bc->ev_mask))); free(tmp); } break; case BRO_MSG_VERSION: { uchar *data; uint32 proto_version; uint32 cache_size; uint32 data_version; uint32 runtime; /* unused */ D(("Received MSG_VERSION\n")); /* We need to read another chunk for the raw data. */ if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (! (data = malloc(sizeof(uchar) * chunk_size))) goto reset_return; if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size)) { free(data); goto reset_return; } proto_version = ntohl(((uint32 *) data)[0]); cache_size = ntohl(((uint32 *) data)[1]); data_version = ntohl(((uint32 *) data)[2]); runtime = ntohl(((uint32 *) data)[3]); /* If there are more bytes than required for the 4 uint32s * used above, it means that the peer has sent a connection class * identifier. Extract and register in the handle. */ if (chunk_size > 4 * sizeof(uint32)) { if (bc->peer_class) free(bc->peer_class); bc->peer_class = strdup((char *) (data + 4 * sizeof(uint32))); } if (proto_version != BRO_PROTOCOL_VERSION) { D(("EEEK -- we speak protocol version %i, peer speeks %i. Aborting.\n", BRO_PROTOCOL_VERSION, proto_version)); __bro_openssl_shutdown(bc); free(data); goto reset_return; } else { D(("Protocols compatible, we speak version %i\n", BRO_PROTOCOL_VERSION)); } if (data_version != 0 && data_version != BRO_DATA_FORMAT_VERSION) { D(("EEEK -- we speak data format version %i, peer speeks %i. Aborting.\n", BRO_DATA_FORMAT_VERSION, data_version)); __bro_openssl_shutdown(bc); free(data); goto reset_return; } else { D(("Data formats compatible, we speak version %i\n", BRO_DATA_FORMAT_VERSION)); } bc->io_cache_maxsize = cache_size; D(("Receiver cache size set to %i entries.\n", cache_size)); free(data); bc->state->conn_state_peer = BRO_CONNSTATE_HANDSHAKE; D(("VERSION received, on %p, peer now in HANDSHAKE stage.\n")); } break; case BRO_MSG_SERIAL: { uint32 pre_serial; D(("Received MSQ_SERIAL\n")); pre_serial = __bro_buf_ptr_tell(bc->rx_buf); if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (! io_process_serialization(bc)) io_skip_chunk(bc->rx_buf, pre_serial, chunk_size); } break; case BRO_MSG_CAPTURE_FILTER: { uint32 pre_capture; D(("Received MSQ_CAPTURE_FILTER\n")); pre_capture = __bro_buf_ptr_tell(bc->rx_buf); if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; io_skip_chunk(bc->rx_buf, pre_capture, chunk_size); } break; case BRO_MSG_PHASE_DONE: /* No additional content for this one. */ switch (bc->state->conn_state_peer) { case BRO_CONNSTATE_HANDSHAKE: /* When we complete the handshake phase, it depends * on whether or not the peer has requested synced * state. If so, enter the sync phase, otherwise * we're up and running. */ if (bc->state->sync_state_requested) { bc->state->conn_state_peer = BRO_CONNSTATE_SYNC; D(("Phase done from peer on %p, sync requested, peer now in SYNC stage.\n", bc)); } else { bc->state->conn_state_peer = BRO_CONNSTATE_RUNNING; D(("Phase done from peer on %p, no sync requested, peer now in RUNNING stage.\n", bc)); } break; case BRO_CONNSTATE_SYNC: bc->state->conn_state_peer = BRO_CONNSTATE_RUNNING; D(("Phase done from peer on %p, peer now in RUNNING stage.\n", bc)); break; default: D(("Ignoring PHASE_DONE in conn state %i/%i on conn %p\n", bc->state->conn_state_self, bc->state->conn_state_peer, bc)); } break; case BRO_MSG_REQUEST_SYNC: { uchar *data; D(("Received MSQ_REQUEST_SYNC, peer now in SYNC stage.\n")); bc->state->sync_state_requested = 1; bc->state->conn_state_peer = BRO_CONNSTATE_SYNC; /* We need to read another chunk for the raw data. */ if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (! (data = malloc(sizeof(uchar) * chunk_size))) goto reset_return; if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size)) { free(data); goto reset_return; } D(("Skipping sync interpretation\n")); free(data); break; } case BRO_MSG_CAPS: { uchar *data; D(("Received MSG_CAPS\n")); /* We need to read another chunk for the raw data. */ if (! io_read_chunk_size(bc, &chunk_size)) goto reset_return; if (! (data = malloc(sizeof(uchar) * chunk_size))) goto reset_return; if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size)) { free(data); goto reset_return; } D(("Skipping capabilities interpretation\n")); free(data); break; } default: D(("Skipping unknown message type %i\n", msg_hdr.hdr_type)); break; } __bro_buf_consume(bc->rx_buf); result = TRUE; if ((bc->conn_flags & BRO_CFLAG_YIELD) && bc->state->conn_state_self == BRO_CONNSTATE_RUNNING && bc->state->conn_state_peer == BRO_CONNSTATE_RUNNING) break; } reset_return: __bro_buf_ptr_seek(bc->rx_buf, buf_off, SEEK_SET); D_RETURN_(result); } void __bro_io_loop(BroConn *bc) { D_ENTER; for ( ; ; ) { D(("I/O loop iteration\n")); switch (bc->state->io_msg) { case BRO_IOMSG_STOP: D(("I/O process %u exiting by request.\n", getpid())); __bro_openssl_shutdown(bc); exit(0); case BRO_IOMSG_WRITE: if (bc->state->tx_dead) break; if (! io_msg_empty_tx(bc)) { D(("I/O handler %u encountered write error.\n", getpid())); __bro_openssl_shutdown(bc); } break; case BRO_IOMSG_READ: if (bc->state->rx_dead) break; if (io_msg_fill_rx(bc) < 0) { D(("I/O handler %u encountered read error.\n", getpid())); __bro_openssl_shutdown(bc); } break; } bc->state->io_msg = BRO_IOMSG_NONE; } } broccoli-1.97-minimal/src/bro_packet.h0000664002342100234210000000315212523041064017557 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_packet_h #define broccoli_packet_h BroPacket *__bro_packet_unserialize(BroConn *bc); int __bro_packet_serialize(BroPacket *packet, BroConn *bc); int __bro_packet_read(BroPacket *packet, BroConn *bc); int __bro_packet_write(BroPacket *packet, BroConn *bc); int __bro_packet_clone(BroPacket *dst, const BroPacket *src); #endif broccoli-1.97-minimal/src/bro_sobject.c0000664002342100234210000003001512523041064017732 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include #include #include #include #include static uint32 __bro_sobject_hash_impl(BroSObject *obj); static int __bro_sobject_cmp_impl(BroSObject *obj1, BroSObject *obj2); /* Factory for object instances -- essentially a mapping from a type ID * to a function taking no arguments and returning an object derived * from BroSObject. */ typedef struct bro_obj_factory_entry { uint16 type_id; BroSObject *(* create)(void); } BroObjFactoryEntry; static BroObjFactoryEntry obj_factories[] = { { SER_OBJ, (BroSObjectNew) __bro_object_new }, { SER_VAL, (BroSObjectNew) __bro_val_new }, { SER_INTERVAL_VAL, (BroSObjectNew) __bro_val_new }, { SER_PORT_VAL, (BroSObjectNew) __bro_val_new }, { SER_ADDR_VAL, (BroSObjectNew) __bro_val_new }, { SER_SUBNET_VAL, (BroSObjectNew) __bro_val_new }, { SER_STRING_VAL, (BroSObjectNew) __bro_val_new }, { SER_ENUM_VAL, (BroSObjectNew) __bro_val_new }, { SER_LIST_VAL, (BroSObjectNew) __bro_list_val_new }, { SER_MUTABLE_VAL, (BroSObjectNew) __bro_mutable_val_new }, { SER_RECORD_VAL, (BroSObjectNew) __bro_record_val_new }, { SER_TABLE_VAL, (BroSObjectNew) __bro_table_val_new }, { SER_VECTOR_VAL, (BroSObjectNew) __bro_vector_val_new }, { SER_TYPE, (BroSObjectNew) __bro_type_new }, { SER_TYPE_LIST, (BroSObjectNew) __bro_type_list_new }, { SER_INDEX_TYPE, (BroSObjectNew) __bro_index_type_new }, { SER_TABLE_TYPE, (BroSObjectNew) __bro_table_type_new }, { SER_SET_TYPE, (BroSObjectNew) __bro_set_type_new }, { SER_RECORD_TYPE, (BroSObjectNew) __bro_record_type_new }, { SER_FILE_TYPE, (BroSObjectNew) __bro_file_type_new }, { SER_ENUM_TYPE, (BroSObjectNew) __bro_enum_type_new }, { SER_VECTOR_TYPE, (BroSObjectNew) __bro_vector_type_new }, { SER_ATTRIBUTES, (BroSObjectNew) __bro_attrs_new }, { SER_ID, (BroSObjectNew) __bro_id_new }, { SER_LOCATION, (BroSObjectNew) __bro_loc_new }, }; BroSObject * __bro_sobject_create(uint16 type_id) { int i, num_factories; D_ENTER; num_factories = sizeof(obj_factories) / sizeof(BroObjFactoryEntry); for (i = 0; i < num_factories; i++) { if (obj_factories[i].type_id == type_id && obj_factories[i].create) { BroSObject *result = obj_factories[i].create(); D_RETURN_(result); } } D(("Creation of object type 0x%04x failed.\n", type_id)); D_RETURN_(NULL); } void __bro_sobject_release(BroSObject *obj) { D_ENTER; if (! obj) D_RETURN; obj->ref_count--; if (obj->ref_count > 0) { D(("Object %p has non-zero refcount, not releasing\n", obj)); D_RETURN; } if (obj->free) obj->free(obj); D_RETURN; } void __bro_sobject_ref(BroSObject *obj) { obj->ref_count++; } BroSObject * __bro_sobject_copy(BroSObject *obj) { BroSObject *clone; D_ENTER; if (! obj) D_RETURN_(NULL); if (! (clone = __bro_sobject_create(obj->type_id))) D_RETURN_(NULL); if (clone->clone) clone->clone(clone, obj); D_RETURN_(clone); } BroSObject * __bro_sobject_new(void) { BroSObject *obj; D_ENTER; if (! (obj = calloc(1, sizeof(BroSObject)))) D_RETURN_(NULL); __bro_sobject_init(obj); D_RETURN_(obj); } void __bro_sobject_init(BroSObject *obj) { D_ENTER; obj->ref_count = 1; if (! (obj->data = __bro_ht_new(__bro_ht_str_hash, __bro_ht_str_cmp, __bro_ht_mem_free, NULL, FALSE))) { D(("Out of memory.\n")); /* FIXME -- add return value to initializer methods. */ } obj->read = __bro_sobject_read; obj->write = __bro_sobject_write; obj->free = __bro_sobject_free; obj->clone = __bro_sobject_clone; obj->hash = __bro_sobject_hash_impl; obj->cmp = __bro_sobject_cmp_impl; D_RETURN; } void __bro_sobject_free(BroSObject *obj) { D_ENTER; if (! obj) D_RETURN; __bro_ht_free(obj->data); free(obj); D_RETURN; } int __bro_sobject_clone(BroSObject *dst, BroSObject *src) { D_ENTER; dst->perm_id = src->perm_id; dst->type_id = src->type_id; /* Should aready be set, but what the heck .. */ dst->ref_count = 1; /* We don't clone the contents of the data hashtable -- * actually we can't right now ... */ D_RETURN_(TRUE); } static uint32 __bro_sobject_hash_impl(BroSObject *obj) { uint32 result; D_ENTER; if (! obj) D_RETURN_(0); result = obj->perm_id ^ (uint32) obj->type_id; D_RETURN_(result); } static int __bro_sobject_cmp_impl(BroSObject *obj1, BroSObject *obj2) { D_ENTER; if (! obj1 || ! obj2) D_RETURN_(FALSE); if (obj1->perm_id != obj2->perm_id) D_RETURN_(FALSE); D_RETURN_(TRUE); } uint32 __bro_sobject_hash(BroSObject *obj) { D_ENTER; if (! obj) D_RETURN_(0); D_RETURN_(obj->hash(obj)); } int __bro_sobject_cmp(BroSObject *obj1, BroSObject *obj2) { D_ENTER; if (! obj1 || !obj2) D_RETURN_(FALSE); D_RETURN_(obj1->cmp(obj1, obj2)); } int __bro_sobject_serialize(BroSObject *obj, BroConn *bc) { char full_obj; D_ENTER; if (! obj || !bc) D_RETURN_(FALSE); /* Special case for types: they indicate at the very beginning * whether they're transferred in their entirety or just via * their name (in which case we can't do much at the moment). */ if ( (obj->type_id & SER_TYPE_MASK) == SER_IS_TYPE) { BroType *type = (BroType *) obj; D(("Serializing type %X as type\n", obj->type_id)); if (! __bro_buf_write_char(bc->tx_buf, type->is_complete)) D_RETURN_(FALSE); if (! type->is_complete) { if (! __bro_buf_write_string(bc->tx_buf, &type->type_name)) D_RETURN_(FALSE); D(("Type sent by type-name '%s' only.\n", bro_string_get_data(&type->type_name))); D_RETURN_(TRUE); } } /* FIXME: for now we never use the serialization cache when sending. */ full_obj = 1; if (! __bro_buf_write_char(bc->tx_buf, full_obj)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, obj->perm_id)) D_RETURN_(FALSE); if (! obj->write(obj, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroSObject * __bro_sobject_unserialize(uint16 type_id_wanted, BroConn *bc) { BroSObject *obj; char full_obj; uint32 perm_id; uint16 type_id; D_ENTER; if (! bc) D_RETURN_(NULL); /* Same special case for types as in __bro_sobject_serialize(). */ if ( (type_id_wanted & SER_TYPE_MASK) == SER_IS_TYPE) { D(("Unserializing a type, checking for name-only format.\n")); if (! __bro_buf_read_char(bc->rx_buf, &full_obj)) D_RETURN_(NULL); if (! full_obj) { BroString tmp; bro_string_init(&tmp); /* We only get the name. */ if (! __bro_buf_read_string(bc->rx_buf, &tmp)) D_RETURN_(FALSE); /* We don't really have a namespace in which we can now * look up the type, so there's not much we can do! */ D(("Received name-only type '%s', reporting failure.\n", bro_string_get_data(&tmp))); D_RETURN_(FALSE); } } if (! __bro_buf_read_char(bc->rx_buf, &full_obj)) D_RETURN_(NULL); if (! __bro_buf_read_int(bc->rx_buf, &perm_id)) D_RETURN_(NULL); if (! full_obj) { #ifdef BRO_DEBUG if (! (bc->conn_flags & BRO_CFLAG_CACHE)) D(("WARNING: no caching requested, yet peer sends cached data.\n")); #endif if (! (obj = __bro_ht_get(bc->io_cache, (void *)(uintptr_t) perm_id))) { D(("Cache inconsistency: cache should contain object %i\n", perm_id)); D_RETURN_(NULL); } __bro_sobject_ref(obj); D(("Returning object %i/%p from cache.\n", perm_id, obj)); D_RETURN_(obj); } if (! __bro_buf_read_short(bc->rx_buf, &type_id)) D_RETURN_(NULL); /* Now check if the stuff that's arriving is actually an * instance of the type we'd like to see -- we can only do * primitive checking for inherited types (when we want to * know that it's a type, say, but we cannot know what exact * kind of type) -- so we just check whether all the bits set * in both type id's match: */ if ((type_id_wanted & SER_TYPE_MASK) != (type_id & SER_TYPE_MASK)) { D(("Type mismatch in serialization: wanted %04x, got %04x.\n", type_id_wanted, type_id)); D_RETURN_(NULL); } if (! (obj = __bro_sobject_create(type_id))) D_RETURN_(NULL); /* Polymorphism: depending on the constructor of the object, * this call will start from the bottom of the hierarchy and * read members in step by step, so by the time we return * from this function the object is fully unserialized. */ D(("Attempting read of object %i of type 0x%04x...\n", perm_id, type_id)); if (! obj->read(obj, bc)) { D(("Reading object %i of type 0x%04x FAILED.\n", perm_id, type_id)); __bro_sobject_release(obj); D_RETURN_(NULL); } /* If we have asked the peer to use caching, * make sure the object is in the cache: */ if ( (bc->conn_flags & BRO_CFLAG_CACHE) && ! __bro_ht_get(bc->io_cache, (void *)(uintptr_t) perm_id)) { D(("Storing object %i in cache.\n", perm_id)); __bro_ht_add(bc->io_cache, (void *)(uintptr_t) perm_id, obj); obj->perm_id = perm_id; __bro_sobject_ref(obj); } D(("Object %i of type 0x%04x unserialized successfully.\n", perm_id, type_id)); D_RETURN_(obj); } int __bro_sobject_read(BroSObject *obj, BroConn *bc) { D_ENTER; D_RETURN_(TRUE); obj = NULL; bc = NULL; } int __bro_sobject_write(BroSObject *obj, BroConn *bc) { D_ENTER; if (! __bro_buf_write_short(bc->tx_buf, obj->type_id)) D_RETURN_(FALSE); D_RETURN_(TRUE); } void __bro_sobject_data_set(BroSObject *obj, const char *key, void *val) { D_ENTER; if (! obj || ! key || ! *key) D_RETURN; __bro_ht_add(obj->data, strdup(key), val); /* D(("Setting data item '%s' in object %p\n", key, obj)); */ D_RETURN; } void * __bro_sobject_data_get(BroSObject *obj, const char *key) { void *result; if (! obj || ! key || ! *key) return NULL; result = __bro_ht_get(obj->data, (void *) key); /* D(("Retrieving data item '%s' from object %p yields %p\n", key, obj, result)); */ return result; } void * __bro_sobject_data_del(BroSObject *obj, const char *key) { void *result; D_ENTER; if (! obj || ! key || ! *key) D_RETURN_(NULL); result = __bro_ht_del(obj->data, (void *) key); /* D(("Removing data item '%s' from object %p yields %p\n", key, obj, result)); */ D_RETURN_(result); } broccoli-1.97-minimal/src/bro_debug.c0000664002342100234210000000430312523041064017370 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include int bro_debug_calltrace = 0; int bro_debug_messages = 0; static int calldepth = 0; static void debug_whitespace(void) { int i; for (i = 0; i < 2*calldepth; i++) fprintf(stderr, "-"); } void bro_debug(const char *fmt, ...) { va_list argp; if (bro_debug_messages) { va_start(argp, fmt); vfprintf(stderr, fmt, argp); va_end(argp); } } void bro_debug_enter(const char *function, int line) { if (! bro_debug_calltrace) return; fprintf(stderr, "%u ", getpid()); calldepth++; debug_whitespace(); fprintf(stderr, "> %s(%i)\n", function, line); } void bro_debug_return(const char *function, int line) { if (! bro_debug_calltrace) return; fprintf(stderr, "%u <", getpid()); debug_whitespace(); fprintf(stderr, " %s(%i)\n", function, line); if (--calldepth < 0) calldepth = 0; } broccoli-1.97-minimal/src/bro_val.c0000664002342100234210000013241112523041064017066 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include #include #include #include #include #include #include /* The virtual implementations of BroSObject's functions are * kept static in this module, and so are the ..._init() methods * not currently needed by other, derived classes. */ static void __bro_val_init(BroVal *val); static void __bro_val_free(BroVal *val); static int __bro_val_read(BroVal *val, BroConn *bc); static int __bro_val_write(BroVal *val, BroConn *bc); static int __bro_val_clone(BroVal *dst, BroVal *src); static uint32 __bro_val_hash(BroVal *val); static int __bro_val_cmp(BroVal *val1, BroVal *val2); static void *__bro_val_get(BroVal *val); static void __bro_list_val_init(BroListVal *lv); static void __bro_list_val_free(BroListVal *lv); static int __bro_list_val_read(BroListVal *lv, BroConn *bc); static int __bro_list_val_write(BroListVal *lv, BroConn *bc); static int __bro_list_val_clone(BroListVal *dst, BroListVal *src); static uint32 __bro_list_val_hash(BroListVal *lv); static int __bro_list_val_cmp(BroListVal *lv1, BroListVal *lv2); static BroList *__bro_list_val_get(BroListVal *lv); static void __bro_mutable_val_init(BroMutableVal *mv); static void __bro_mutable_val_free(BroMutableVal *mv); static int __bro_mutable_val_read(BroMutableVal *mv, BroConn *bc); static int __bro_mutable_val_write(BroMutableVal *mv, BroConn *bc); static int __bro_mutable_val_clone(BroMutableVal *dst, BroMutableVal *src); static uint32 __bro_mutable_val_hash(BroMutableVal *mv); static int __bro_mutable_val_cmp(BroMutableVal *mv1, BroMutableVal *mv2); static void __bro_record_val_init(BroRecordVal *rv); static void __bro_record_val_free(BroRecordVal *rv); static int __bro_record_val_read(BroRecordVal *rv, BroConn *bc); static int __bro_record_val_write(BroRecordVal *rv, BroConn *bc); static int __bro_record_val_clone(BroRecordVal *dst, BroRecordVal *src); static uint32 __bro_record_val_hash(BroRecordVal *rv); static int __bro_record_val_cmp(BroRecordVal *rv1, BroRecordVal *rv2); static void *__bro_record_val_get(BroRecordVal *rv); static void __bro_table_val_init(BroTableVal *tv); static void __bro_table_val_free(BroTableVal *tv); static int __bro_table_val_read(BroTableVal *tv, BroConn *bc); static int __bro_table_val_write(BroTableVal *tv, BroConn *bc); static int __bro_table_val_clone(BroTableVal *dst, BroTableVal *src); static uint32 __bro_table_val_hash(BroTableVal *tv); static int __bro_table_val_cmp(BroTableVal *tv1, BroTableVal *tv2); static void *__bro_table_val_get(BroTableVal *tv); static void __bro_vector_val_init(BroVectorVal *tv); static void __bro_vector_val_free(BroVectorVal *tv); static int __bro_vector_val_read(BroVectorVal *tv, BroConn *bc); static int __bro_vector_val_write(BroVectorVal *tv, BroConn *bc); static int __bro_vector_val_clone(BroVectorVal *dst, BroVectorVal *src); static uint32 __bro_vector_val_hash(BroVectorVal *tv); static int __bro_vector_val_cmp(BroVectorVal *tv1, BroVectorVal *tv2); static void *__bro_vector_val_get(BroVectorVal *tv); BroVal * __bro_val_new(void) { BroVal *val; D_ENTER; if (! (val = calloc(1, sizeof(BroVal)))) D_RETURN_(NULL); __bro_val_init(val); D_RETURN_(val); } BroVal * __bro_val_new_of_type(int type, const char *type_name) { BroVal *val; D_ENTER; switch (type) { case BRO_TYPE_BOOL: case BRO_TYPE_INT: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: case BRO_TYPE_INTERVAL: case BRO_TYPE_STRING: case BRO_TYPE_TIMER: case BRO_TYPE_PORT: case BRO_TYPE_IPADDR: case BRO_TYPE_SUBNET: case BRO_TYPE_ENUM: if (! (val = __bro_val_new())) D_RETURN_(NULL); break; case BRO_TYPE_SET: /* A hack -- sets are table vals, but have set type, * at least while Bro still has SetType. */ case BRO_TYPE_TABLE: if (! (val = (BroVal *) __bro_table_val_new())) D_RETURN_(NULL); break; case BRO_TYPE_RECORD: if (! (val = (BroVal *) __bro_record_val_new())) D_RETURN_(NULL); break; case BRO_TYPE_VECTOR: if ( ! (val = (BroVal *) __bro_vector_val_new()) ) D_RETURN_(NULL); break; case BRO_TYPE_PATTERN: case BRO_TYPE_ANY: case BRO_TYPE_UNION: case BRO_TYPE_LIST: case BRO_TYPE_FUNC: case BRO_TYPE_FILE: case BRO_TYPE_ERROR: default: D(("Unsupported value type %i\n", type)); D_RETURN_(NULL); } if (! (val->val_type = __bro_type_new_of_type(type, type_name))) { __bro_val_free(val); D_RETURN_(NULL); } D_RETURN_(val); } int __bro_val_assign(BroVal *val, const void *data) { D_ENTER; if (! val) { D(("Input error: (%p, %p)\n", val, data)); D_RETURN_(FALSE); } if (! data) { if (val->val_type) { __bro_sobject_release((BroSObject *) val->val_type); val->val_type = NULL; } D(("Marked val %p as unassigned.\n", val)); D_RETURN_(TRUE); } /* If we intend to assign data to the val, it must have a type. */ if (! val->val_type) { D(("Cannot assign to val without a type.\n")); D_RETURN_(FALSE); } switch (val->val_type->tag) { case BRO_TYPE_BOOL: { int tmp = *((int *) data); val->val.char_val = (tmp != 0 ? 1 : 0); } break; case BRO_TYPE_INT: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: case BRO_TYPE_ENUM: val->val_int64 = *((uint64 *) data); break; case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: case BRO_TYPE_INTERVAL: val->val_double = *((double *) data); break; case BRO_TYPE_STRING: { BroString *str = (BroString *) data; bro_string_set_data(&val->val_str, str->str_val, str->str_len); } break; case BRO_TYPE_PORT: { BroPort *tmp = (BroPort *) data; if (tmp->port_proto != IPPROTO_TCP && tmp->port_proto != IPPROTO_UDP && tmp->port_proto != IPPROTO_ICMP) { __bro_sobject_release((BroSObject *) data); D_RETURN_(FALSE); } val->val_port = *tmp; } break; case BRO_TYPE_IPADDR: val->val_addr = *((BroAddr *) data); break; case BRO_TYPE_SUBNET: val->val_subnet = *((BroSubnet *) data); break; case BRO_TYPE_RECORD: { BroList *l; BroVal *tmp_val; BroRecordVal *rv = (BroRecordVal *) val; BroRecord *rec = (BroRecord *) data; if (rv->rec) __bro_record_free(rv->rec); rv->rec = __bro_record_copy(rec); /* Record vals also have a record type, copy that: */ for (l = rec->val_list; l; l = __bro_list_next(l)) { char *field; tmp_val = __bro_list_data(l); if (! tmp_val->val_type) { D(("Cannot create record type component from val without type.\n")); D_RETURN_(FALSE); } if (! (field = __bro_sobject_data_get((BroSObject *) tmp_val, "field"))) { D(("Val in record doesn't have field name associated with it.\n")); D_RETURN_(FALSE); } __bro_record_type_add_type((BroRecordType *) val->val_type, field, tmp_val->val_type);; } } break; case BRO_TYPE_TABLE: { BroTableVal *tv = (BroTableVal *) val; BroTable *table = (BroTable *) data; if (tv->table) __bro_table_free(tv->table); tv->table = __bro_table_copy(table); /* XXX need to create the appropriate content in (BroTableType*) val->val_type! */ } break; case BRO_TYPE_VECTOR: { BroVectorVal* vv = (BroVectorVal*) val; BroVector* vec = (BroVector*) data; if ( vv->vec ) __bro_vector_free(vv->vec); vv->vec = __bro_vector_copy(vec); /* XXX need to create the appropriate content in (BroVectorType*) val->val_type! */ break; } case BRO_TYPE_PATTERN: case BRO_TYPE_TIMER: case BRO_TYPE_ANY: case BRO_TYPE_UNION: case BRO_TYPE_LIST: case BRO_TYPE_FUNC: case BRO_TYPE_FILE: case BRO_TYPE_ERROR: D(("Type %i currently unsupported.\n", val->val_type->tag)); D_RETURN_(FALSE); default: D(("Unknown type identifier %i\n", val->val_type->tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static void __bro_val_init(BroVal *val) { BroSObject *sobj = (BroSObject *) val; D_ENTER; __bro_object_init((BroObject *) val); sobj->read = (BroSObjectRead) __bro_val_read; sobj->write = (BroSObjectWrite) __bro_val_write; sobj->free = (BroSObjectFree) __bro_val_free; sobj->clone = (BroSObjectClone) __bro_val_clone; sobj->hash = (BroSObjectHash) __bro_val_hash; sobj->cmp = (BroSObjectCmp) __bro_val_cmp; /* Note: we don't know yet what type_id we'll be using since * that will depend on the type object hooked into this val. * We take care of that when we're serializing this val out * in that case. */ sobj->type_id = SER_VAL; val->get_data = __bro_val_get; D_RETURN; } static void __bro_val_free(BroVal *val) { D_ENTER; /* If there is no type in the val, then it's unassigned and * hence there won't be anything to clean up anyway. */ if (val->val_type) { switch (val->val_type->tag) { case BRO_TYPE_STRING: bro_string_cleanup(&val->val_str); break; default: /* Nothing to do */ break; } } __bro_sobject_release((BroSObject *) val->val_type); __bro_object_free((BroObject *) val); D_RETURN; } int __bro_val_get_type_num(const BroVal *val) { if (! val) return 0; return val->val_type->tag; } int __bro_val_get_data(BroVal *val, int *type, void **data) { if (! val || ! data) return FALSE; if (! val->get_data) return FALSE; if (type && val->val_type) *type = val->val_type->tag; *data = val->get_data(val); return TRUE; } static int __bro_val_read(BroVal *val, BroConn *bc) { uint32 tmp; int i; D_ENTER; if (! val || !bc) D_RETURN_(FALSE); if (! __bro_object_read((BroObject *) val, bc)) D_RETURN_(FALSE); /* Read type */ if (val->val_type) { __bro_sobject_release((BroSObject *) val->val_type); val->val_type = NULL; } if (! (val->val_type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); D(("Type in val has type tags %i/%i\n", val->val_type->tag, val->val_type->internal_tag)); switch (val->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: /* Hack for ports */ if (val->val_type->tag == BRO_TYPE_PORT) { uint64 tmp; if (! __bro_buf_read_int64(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if ( (tmp & 0xf0000) == 0x10000 ) val->val_port.port_proto = IPPROTO_TCP; else if ( (tmp & 0xf0000) == 0x20000 ) val->val_port.port_proto = IPPROTO_UDP; else if ( (tmp & 0xf0000) == 0x30000 ) val->val_port.port_proto = IPPROTO_ICMP; val->val_port.port_num = (tmp & 0xFFFF); } else { if (! __bro_buf_read_int64(bc->rx_buf, &val->val_int64)) D_RETURN_(FALSE); } break; case BRO_INTTYPE_DOUBLE: if (! __bro_buf_read_double(bc->rx_buf, &val->val_double)) D_RETURN_(FALSE); break; case BRO_INTTYPE_STRING: if (! __bro_buf_read_string(bc->rx_buf, &val->val_str)) D_RETURN_(FALSE); break; case BRO_INTTYPE_IPADDR: if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if (tmp != 1 && tmp != 4) { D(("Bad IP addresses word length: %d.\n", tmp)); D_RETURN_(FALSE); } if ( tmp == 1 ) { if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); __bro_util_fill_v4_addr(&val->val_addr, ntohl(tmp)); } else { for ( i = 0; i < tmp; ++i ) { if (! __bro_buf_read_int(bc->rx_buf, &val->val_addr.addr[i])) D_RETURN_(FALSE); val->val_addr.addr[i] = ntohl(val->val_addr.addr[i]); } } break; case BRO_INTTYPE_SUBNET: if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if (tmp != 1 && tmp != 4) { D(("Bad IP addresses word length: %d.\n", tmp)); D_RETURN_(FALSE); } if ( tmp == 1 ) { if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); __bro_util_fill_v4_addr(&val->val_subnet.sn_net, ntohl(tmp)); } else { for ( i = 0; i < tmp; ++i ) { if (! __bro_buf_read_int(bc->rx_buf, &val->val_subnet.sn_net.addr[i])) D_RETURN_(FALSE); val->val_subnet.sn_net.addr[i] = ntohl(val->val_subnet.sn_net.addr[i]); } } if (! __bro_buf_read_int(bc->rx_buf, &val->val_subnet.sn_width)) D_RETURN_(FALSE); break; case BRO_INTTYPE_OTHER: /* See Val.cc around 165 -- these are handled by derived classes. * We only make sure here it's not functions and not files. */ if (val->val_type->tag != BRO_TYPE_FUNC && val->val_type->tag != BRO_TYPE_FILE) break; /* Otherwise fall through to warning. */ default: D(("Unsupported internal type tag: %i\n", val->val_type->internal_tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_val_write(BroVal *val, BroConn *bc) { BroType *type; BroSObject *obj; int i; D_ENTER; if (! val || !bc) D_RETURN_(FALSE); /* We need to make sure that the BroSObject at the root has the * correct type_id (a SER_xxx value). This depends on the type object * so map the type tag of that object to a SER_xxx value: */ if (! val->val_type) { D(("Val %p doesn't have a type.\n", val)); D_RETURN_(FALSE); } type = (BroType *) val->val_type; obj = (BroSObject *) val; switch (type->tag) { case BRO_TYPE_BOOL: case BRO_TYPE_INT: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: case BRO_TYPE_STRING: case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: obj->type_id = SER_VAL; break; case BRO_TYPE_ENUM: obj->type_id = SER_ENUM_VAL; break; case BRO_TYPE_PORT: obj->type_id = SER_PORT_VAL; break; case BRO_TYPE_INTERVAL: obj->type_id = SER_INTERVAL_VAL; break; case BRO_TYPE_IPADDR: obj->type_id = SER_ADDR_VAL; break; case BRO_TYPE_SUBNET: obj->type_id = SER_SUBNET_VAL; break; case BRO_TYPE_RECORD: obj->type_id = SER_RECORD_VAL; break; case BRO_TYPE_VECTOR: obj->type_id = SER_VECTOR_VAL; break; default: D(("Val %p's type unhandled: type tag is %i.\n", val, type->tag)); D_RETURN_(FALSE); } if (! __bro_object_write((BroObject *) val, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) val->val_type, bc)) D_RETURN_(FALSE); switch (val->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: /* Hack for ports */ if (val->val_type->tag == BRO_TYPE_PORT) { uint64 tmp = val->val_port.port_num; if (val->val_port.port_proto == IPPROTO_TCP) tmp |= 0x10000; else if (val->val_port.port_proto == IPPROTO_UDP) tmp |= 0x20000; else if (val->val_port.port_proto == IPPROTO_ICMP) tmp |= 0x30000; if (! __bro_buf_write_int64(bc->tx_buf, tmp)) D_RETURN_(FALSE); } else { if (! __bro_buf_write_int64(bc->tx_buf, val->val_int64)) D_RETURN_(FALSE); } break; case BRO_INTTYPE_DOUBLE: if (! __bro_buf_write_double(bc->tx_buf, val->val_double)) D_RETURN_(FALSE); break; case BRO_INTTYPE_STRING: if (! __bro_buf_write_string(bc->tx_buf, &val->val_str)) D_RETURN_(FALSE); break; case BRO_INTTYPE_IPADDR: if ( __bro_util_is_v4_addr(&val->val_addr) ) i = 1; else i = 4; if (! __bro_buf_write_int(bc->tx_buf, i)) D_RETURN_(FALSE); for ( i = 4 - i; i < 4; ++i ) if (! __bro_buf_write_int(bc->tx_buf, htonl(val->val_addr.addr[i]))) D_RETURN_(FALSE); break; case BRO_INTTYPE_SUBNET: if ( __bro_util_is_v4_addr(&val->val_subnet.sn_net) ) i = 1; else i = 4; if (! __bro_buf_write_int(bc->tx_buf, i)) D_RETURN_(FALSE); for ( i = 4 - i; i < 4; ++i ) if (! __bro_buf_write_int(bc->tx_buf, htonl(val->val_subnet.sn_net.addr[i]))) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, val->val_subnet.sn_width)) D_RETURN_(FALSE); break; case BRO_INTTYPE_OTHER: /* That's fine, will be handled in derived classes * like __bro_record_val_write(). */ break; default: D(("Unknown internal type tag: %i\n", val->val_type->internal_tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_val_clone(BroVal *dst, BroVal *src) { D_ENTER; if (! __bro_object_clone((BroObject *) dst, (BroObject *) src)) { D(("Cloning parent failed.\n")); D_RETURN_(FALSE); } if (src->val_type && ! (dst->val_type = (BroType *) __bro_sobject_copy((BroSObject *) src->val_type))) { D(("Cloning type failed.\n")); D_RETURN_(FALSE); } switch (dst->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: /* Hack for ports */ if (src->val_type->tag == BRO_TYPE_PORT) dst->val_port = src->val_port; else dst->val_int64 = src->val_int64; break; case BRO_INTTYPE_IPADDR: dst->val_addr = src->val_addr; break; case BRO_INTTYPE_DOUBLE: dst->val_double = src->val_double; break; case BRO_INTTYPE_STRING: bro_string_assign(&src->val_str, &dst->val_str); break; case BRO_INTTYPE_SUBNET: dst->val_subnet = src->val_subnet; break; case BRO_INTTYPE_OTHER: /* That's okay, handled in subtype */ break; default: D(("Unknown internal type tag: %i\n", dst->val_type->internal_tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static uint32 __bro_val_hash(BroVal *val) { uint32 result; int i; D_ENTER; if (! val) D_RETURN_(0); result = __bro_sobject_hash((BroSObject*) val->val_type); switch (val->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: result ^= val->val_int64; break; case BRO_INTTYPE_IPADDR: for ( i = 0; i < 4; ++i ) result ^= val->val_addr.addr[i]; break; case BRO_INTTYPE_DOUBLE: result ^= (uint32) val->val_double; break; case BRO_INTTYPE_STRING: result ^= __bro_ht_str_hash(val->val_str.str_val); break; case BRO_INTTYPE_SUBNET: for ( i = 0; i < 4; ++i ) result ^= val->val_subnet.sn_net.addr[i]; result ^= val->val_subnet.sn_width; break; case BRO_INTTYPE_OTHER: D(("WARNING -- __bro_val_hash() invoked on derived type.\n")); break; default: D(("Unknown internal type tag: %i\n", val->val_type->internal_tag)); break; } D_RETURN_(result); } static int __bro_val_cmp(BroVal *val1, BroVal *val2) { int i; D_ENTER; if (! val1 || ! val2) D_RETURN_(FALSE); if (! __bro_sobject_cmp((BroSObject*) val1->val_type, (BroSObject*) val2->val_type)) D_RETURN_(FALSE); switch (val1->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: if (val1->val_int64 != val2->val_int64) D_RETURN_(FALSE); break; case BRO_INTTYPE_IPADDR: for (i = 3; i >= 0; --i) if (val1->val_addr.addr[i] != val2->val_addr.addr[i]) D_RETURN_(FALSE); break; case BRO_INTTYPE_DOUBLE: if (val1->val_double != val2->val_double) D_RETURN_(FALSE); break; case BRO_INTTYPE_STRING: if (! __bro_ht_str_cmp(val1->val_str.str_val, val2->val_str.str_val)) D_RETURN_(FALSE); break; case BRO_INTTYPE_SUBNET: for (i = 3; i >= 0; --i) if (val1->val_subnet.sn_net.addr[i] != val2->val_subnet.sn_net.addr[i]) D_RETURN_(FALSE); if (val1->val_subnet.sn_width != val2->val_subnet.sn_width) D_RETURN_(FALSE); break; case BRO_INTTYPE_OTHER: D(("WARNING -- __bro_val_cmp() invoked on derived type.\n")); break; default: D(("Unknown internal type tag: %i\n", val1->val_type->internal_tag)); break; } D_RETURN_(TRUE); } static void * __bro_val_get(BroVal *val) { /* Following the comments in broccoli.h, we return atomic values * as copies into *result, and complex types (i.e., structs) have * all members assigned to point to internal values so the user * does not have to clean up the returned value. The user can * still keep those values around if necessary by copying them. */ if (! val->val_type) { D(("No type in val %p\n", val)); return NULL; } switch (val->val_type->tag) { case BRO_TYPE_BOOL: case BRO_TYPE_INT: case BRO_TYPE_ENUM: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: return &val->val_int64; case BRO_TYPE_IPADDR: return &val->val_addr; case BRO_TYPE_PORT: return &val->val_port; case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: case BRO_TYPE_INTERVAL: return &val->val_double; case BRO_TYPE_STRING: return &val->val_str; case BRO_TYPE_SUBNET: return &val->val_subnet; case BRO_TYPE_RECORD: D(("WARNING: Inheritance broken -- record types should not be handled here.\n")); return NULL; case BRO_TYPE_TABLE: D(("WARNING: Inheritance broken -- table types should not be handled here.\n")); return NULL; default: D(("Type %i currently not extractable.\n", val->val_type->tag)); } return NULL; } BroListVal * __bro_list_val_new(void) { BroListVal *val; D_ENTER; if (! (val = calloc(1, sizeof(BroListVal)))) D_RETURN_(NULL); __bro_list_val_init(val); D_RETURN_(val); } static void __bro_list_val_init(BroListVal *lv) { BroSObject *sobj = (BroSObject *) lv; BroVal *val = (BroVal *) lv; D_ENTER; __bro_val_init((BroVal *) lv); sobj->read = (BroSObjectRead) __bro_list_val_read; sobj->write = (BroSObjectWrite) __bro_list_val_write; sobj->free = (BroSObjectFree) __bro_list_val_free; sobj->clone = (BroSObjectClone) __bro_list_val_clone; sobj->hash = (BroSObjectHash) __bro_list_val_hash; sobj->cmp = (BroSObjectCmp) __bro_list_val_cmp; sobj->type_id = SER_LIST_VAL; val->get_data = (BroValAccessor) __bro_list_val_get; D_RETURN; } static void __bro_list_val_free(BroListVal *lv) { D_ENTER; if (! lv) D_RETURN; __bro_list_free(lv->list, (BroFunc) __bro_sobject_release); __bro_val_free((BroVal *) lv); D_RETURN; } static int __bro_list_val_read(BroListVal *lv, BroConn *bc) { int i; uint32 ui; D_ENTER; if (! __bro_val_read((BroVal *) lv, bc)) D_RETURN_(FALSE); __bro_list_free(lv->list, (BroFunc) __bro_sobject_release); lv->list = NULL; if (! __bro_buf_read_char(bc->rx_buf, &lv->type_tag)) goto error_return; if (! __bro_buf_read_int(bc->rx_buf, &ui)) goto error_return; lv->len = (int) ui; for (i = 0; i < lv->len; i++) { BroVal *val; if (! (val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) goto error_return; lv->list = __bro_list_append(lv->list, val); } D_RETURN_(TRUE); error_return: __bro_list_free(lv->list, (BroFunc) __bro_sobject_release); lv->list = NULL; D_RETURN_(FALSE); } static int __bro_list_val_write(BroListVal *lv, BroConn *bc) { BroList *l; D_ENTER; if (! __bro_val_write((BroVal *) lv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, lv->type_tag)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, lv->len)) D_RETURN_(FALSE); for (l = lv->list; l; l = __bro_list_next(l)) { BroVal *val = __bro_list_data(l); if (! __bro_sobject_serialize((BroSObject *) val, bc)) D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_list_val_clone(BroListVal *dst, BroListVal *src) { BroList *l; D_ENTER; if (! __bro_val_clone((BroVal *) dst, (BroVal *) src)) D_RETURN_(FALSE); dst->type_tag = src->type_tag; dst->len = src->len; if (dst->list) { __bro_list_free(dst->list, (BroFunc) __bro_sobject_release); dst->list = NULL; } for (l = src->list; l; l = __bro_list_next(l)) dst->list = __bro_list_append(dst->list, __bro_sobject_copy(__bro_list_data(l))); D_RETURN_(TRUE); } static uint32 __bro_list_val_hash(BroListVal *lv) { uint32 result; BroList *l; D_ENTER; if (! lv) D_RETURN_(0); result = lv->len ^ lv->type_tag; for (l = lv->list; l; l = __bro_list_next(l)) result ^= __bro_sobject_hash((BroSObject *) __bro_list_data(l)); D_RETURN_(result); } static int __bro_list_val_cmp(BroListVal *lv1, BroListVal *lv2) { BroList *l1, *l2; D_ENTER; if (! lv1 || ! lv2) D_RETURN_(FALSE); if (lv1->len != lv2->len || lv1->type_tag != lv2->type_tag) D_RETURN_(FALSE); for (l1 = lv1->list, l2 = lv2->list; l1 && l2; l1 = __bro_list_next(l1), l2 = __bro_list_next(l2)) { if (! __bro_sobject_cmp((BroSObject*) __bro_list_data(l1), (BroSObject*) __bro_list_data(l2))) D_RETURN_(FALSE); } if (l1 || l2) { D(("WARNING -- list length inconsistency.\n")); D_RETURN_(FALSE); } D_RETURN_(TRUE); } static BroList * __bro_list_val_get(BroListVal *lv) { D_ENTER; D_RETURN_(lv->list); } void __bro_list_val_append(BroListVal *lv, BroVal *val) { D_ENTER; if (! lv || ! val) D_RETURN; lv->list = __bro_list_append(lv->list, val); lv->len++; D_RETURN; } BroVal * __bro_list_val_pop_front(BroListVal *lv) { BroVal *result; BroList *l; D_ENTER; if (! lv) D_RETURN_(NULL); result = (BroVal*) __bro_list_data(lv->list); lv->list = __bro_list_remove(lv->list, lv->list); D_RETURN_(result); } BroVal * __bro_list_val_get_front(BroListVal *lv) { BroVal *result; BroList *l; D_ENTER; if (! lv) D_RETURN_(NULL); D_RETURN_((BroVal*) __bro_list_data(lv->list)); } int __bro_list_val_get_length(BroListVal *lv) { D_ENTER; if (! lv) D_RETURN_(0); D_RETURN_(lv->len); } BroMutableVal * __bro_mutable_val_new(void) { BroMutableVal *val; D_ENTER; if (! (val = calloc(1, sizeof(BroMutableVal)))) D_RETURN_(NULL); __bro_mutable_val_init(val); D_RETURN_(val); } static void __bro_mutable_val_init(BroMutableVal *mv) { BroSObject *sobj = (BroSObject *) mv; D_ENTER; __bro_val_init((BroVal *) mv); sobj->read = (BroSObjectRead) __bro_mutable_val_read; sobj->write = (BroSObjectWrite) __bro_mutable_val_write; sobj->free = (BroSObjectFree) __bro_mutable_val_free; sobj->clone = (BroSObjectClone) __bro_mutable_val_clone; sobj->hash = (BroSObjectHash) __bro_mutable_val_hash; sobj->cmp = (BroSObjectCmp) __bro_mutable_val_cmp; sobj->type_id = SER_MUTABLE_VAL; /* BroMutableVal inherits __bro_val_get and doesn't override it. */ D_RETURN; } static void __bro_mutable_val_free(BroMutableVal *mv) { D_ENTER; __bro_sobject_release((BroSObject *) mv->id); __bro_val_free((BroVal *) mv); D_RETURN; } static int __bro_mutable_val_read(BroMutableVal *mv, BroConn *bc) { BroString tmp; D_ENTER; bro_string_init(&tmp); if (! __bro_val_read((BroVal *) mv, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &mv->props)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &tmp)) D_RETURN_(FALSE); /* FIXME: now need to obtain real BroID from that name */ bro_string_cleanup(&tmp); D_RETURN_(TRUE); } static int __bro_mutable_val_write(BroMutableVal *mv, BroConn *bc) { D_ENTER; if (! __bro_val_write((BroVal *) mv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, mv->props)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, (mv->id ? &mv->id->name : NULL))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static int __bro_mutable_val_clone(BroMutableVal *dst, BroMutableVal *src) { D_ENTER; if (! __bro_val_clone((BroVal *) dst, (BroVal *) src)) D_RETURN_(FALSE); if (src->id && ! (dst->id = (BroID *) __bro_sobject_copy((BroSObject *) src->id))) D_RETURN_(FALSE); src->props = dst->props; D_RETURN_(TRUE); } static uint32 __bro_mutable_val_hash(BroMutableVal *mv) { uint32 result; D_ENTER; if (! mv) D_RETURN_(0); result = __bro_id_hash(mv->id) ^ mv->props; D_RETURN_(result); } static int __bro_mutable_val_cmp(BroMutableVal *mv1, BroMutableVal *mv2) { D_ENTER; if (! mv1 || ! mv2) D_RETURN_(FALSE); if (! __bro_id_cmp(mv1->id, mv2->id)) D_RETURN_(FALSE); if (mv1->props != mv2->props) D_RETURN_(FALSE); D_RETURN_(TRUE); } BroRecordVal * __bro_record_val_new(void) { BroRecordVal *val; D_ENTER; if (! (val = calloc(1, sizeof(BroRecordVal)))) D_RETURN_(NULL); __bro_record_val_init(val); D_RETURN_(val); } static void __bro_record_val_init(BroRecordVal *rv) { BroSObject *sobj = (BroSObject *) rv; BroVal *val = (BroVal *) rv; D_ENTER; __bro_mutable_val_init((BroMutableVal *) rv); sobj->read = (BroSObjectRead) __bro_record_val_read; sobj->write = (BroSObjectWrite) __bro_record_val_write; sobj->free = (BroSObjectFree) __bro_record_val_free; sobj->clone = (BroSObjectClone) __bro_record_val_clone; sobj->hash = (BroSObjectHash) __bro_record_val_hash; sobj->cmp = (BroSObjectCmp) __bro_record_val_cmp; sobj->type_id = SER_RECORD_VAL; val->get_data = (BroValAccessor) __bro_record_val_get; D_RETURN; } static void __bro_record_val_free(BroRecordVal *rv) { D_ENTER; if (! rv) D_RETURN; __bro_record_free(rv->rec); __bro_mutable_val_free((BroMutableVal *) rv); D_RETURN; } static int __bro_record_val_read(BroRecordVal *rv, BroConn *bc) { char opt; uint32 i, len; BroVal *val; D_ENTER; if (! __bro_mutable_val_read((BroMutableVal *) rv, bc)) D_RETURN_(FALSE); /* Clean out old vals, if any */ __bro_record_free(rv->rec); if (! (rv->rec = __bro_record_new())) D_RETURN_(FALSE); /* Read in new vals */ if (! __bro_buf_read_int(bc->rx_buf, &len)) goto error_return; for (i = 0; i < len; i++) { const char *field_name; BroVal *rv_val = (BroVal *) rv; BroType *rv_type = rv_val->val_type; D(("Reading val %i/%i into record %p of val %p\n", i+1, len, rv->rec, rv)); if (! __bro_buf_read_char(bc->rx_buf, &opt)) goto error_return; if (opt) { if (! (val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) { D(("WARNING -- unserializing record element failed.\n")); goto error_return; } } else { /* We need an empty val if none was given in order to maintain * a chain of vals nonetheless -- the missing type in this new * val indicates that it is an unassigned val. */ D(("WARNING -- unassigned val.\n")); if (! (val = __bro_val_new())) goto error_return; } __bro_record_add_val(rv->rec, val); if (! (field_name = __bro_record_type_get_nth_field((BroRecordType *) rv_type, i))) { D(("WARNING -- record type field %i has no name.\n", i)); goto error_return; } __bro_record_set_nth_name(rv->rec, i, field_name); } D_RETURN_(TRUE); error_return: __bro_record_free(rv->rec); rv->rec = NULL; D_RETURN_(FALSE); } static int __bro_record_val_write(BroRecordVal *rv, BroConn *bc) { BroList *l; BroVal *val; int i; D_ENTER; if (! rv->rec) D_RETURN_(FALSE); if (! __bro_mutable_val_write((BroMutableVal *) rv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, rv->rec->val_len)) D_RETURN_(FALSE); D(("Writing out %i vals in record %p.\n", rv->rec->val_len, rv->rec)); for (i = 0, l = rv->rec->val_list; l; i++, l = __bro_list_next(l)) { val = __bro_list_data(l); D(("Val %i/%p's type: %p\n", i, val, val->val_type)); if (! __bro_buf_write_char(bc->tx_buf, (val->val_type ? 1 :0))) D_RETURN_(FALSE); if (val->val_type) { if (! __bro_sobject_serialize((BroSObject *) val, bc)) D_RETURN_(FALSE); } } D_RETURN_(TRUE); } static int __bro_record_val_clone(BroRecordVal *dst, BroRecordVal *src) { D_ENTER; if (! __bro_mutable_val_clone((BroMutableVal *) dst, (BroMutableVal *) src)) D_RETURN_(FALSE); if (src->rec && ! (dst->rec = __bro_record_copy(src->rec))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_record_val_hash(BroRecordVal *rv) { uint32 result; D_ENTER; if (! rv) D_RETURN_(0); result = __bro_record_hash(rv->rec); D_RETURN_(result); } static int __bro_record_val_cmp(BroRecordVal *rv1, BroRecordVal *rv2) { D_ENTER; if (! rv1 || ! rv2) D_RETURN_(FALSE); if (! __bro_record_cmp(rv1->rec, rv2->rec)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static void * __bro_record_val_get(BroRecordVal *rv) { return rv->rec; } BroTableVal * __bro_table_val_new(void) { BroTableVal *val; D_ENTER; if (! (val = calloc(1, sizeof(BroTableVal)))) D_RETURN_(NULL); __bro_table_val_init(val); D_RETURN_(val); } static void __bro_table_val_init(BroTableVal *tbl) { BroSObject *sobj = (BroSObject *) tbl; BroVal *val = (BroVal *) tbl; D_ENTER; __bro_mutable_val_init((BroMutableVal *) tbl); sobj->read = (BroSObjectRead) __bro_table_val_read; sobj->write = (BroSObjectWrite) __bro_table_val_write; sobj->free = (BroSObjectFree) __bro_table_val_free; sobj->clone = (BroSObjectClone) __bro_table_val_clone; sobj->hash = (BroSObjectHash) __bro_table_val_hash; sobj->cmp = (BroSObjectCmp) __bro_table_val_cmp; sobj->type_id = SER_TABLE_VAL; val->get_data = (BroValAccessor) __bro_table_val_get; D_RETURN; } static void __bro_table_val_free(BroTableVal *tbl) { D_ENTER; if (! tbl) D_RETURN; __bro_table_free(tbl->table); __bro_attrs_free(tbl->attrs); __bro_mutable_val_free((BroMutableVal *) tbl); D_RETURN; } static int __bro_table_val_read(BroTableVal *tbl, BroConn *bc) { double d; char opt; int num_keys = 0, num_vals = 0; D_ENTER; if (! __bro_mutable_val_read((BroMutableVal *) tbl, bc)) D_RETURN_(FALSE); /* Clean out old vals, if any */ __bro_table_free(tbl->table); if (! (tbl->table = __bro_table_new())) D_RETURN_(FALSE); /* expire_time, currently unused */ if (! __bro_buf_read_double(bc->rx_buf, &d)) goto error_return; if (! __bro_buf_read_char(bc->rx_buf, &opt)) goto error_return; if (opt) { if (! (tbl->attrs = (BroAttrs *) __bro_sobject_unserialize(SER_ATTRIBUTES, bc))) { D(("WARNING -- unserializing table attributes failed.\n")); goto error_return; } } if (! __bro_buf_read_char(bc->rx_buf, &opt)) goto error_return; if (opt) { D(("WARNING -- cannot unserialize expression, try to use table without expiration expression.\n")); goto error_return; } /* Table entries are next: */ for ( ; ; ) { BroType *type; BroListVal *keys = NULL; BroVal *val = NULL; BroIndexType *itype = NULL; int i, len, key_type = 0, val_type = 0; double d; if (! __bro_buf_read_char(bc->rx_buf, &opt)) goto error_return; /* End of set members is announced if opt is 0: */ if (! opt) break; if (! (keys = (BroListVal *) __bro_sobject_unserialize(SER_LIST_VAL, bc))) goto error_return; /* If this isn't a set, we have a value associated with the keys too. */ type = ((BroVal *) tbl)->val_type; itype = (BroIndexType*) type; num_vals++; if (itype->yield_type) { if (! (val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) goto error_return; val_type = val->val_type->tag; num_keys++; } /* If the key is a composite, we report BRO_TYPE_LIST to the user, * so the user can access the individual values via a record. If * the key is atomic, we extract its type and use it directly. */ if (keys->len > 1) key_type = BRO_TYPE_LIST; else if (keys->len == 1) key_type = __bro_list_val_get_front(keys)->val_type->tag; else goto error_return; if (tbl->table->tbl_key_type != BRO_TYPE_UNKNOWN && tbl->table->tbl_key_type != key_type) { D(("Type mismatch when unserializing key of type %d, expecting %d\n", key_type, tbl->table->tbl_key_type)); goto error_return; } tbl->table->tbl_key_type = key_type; if (tbl->table->tbl_val_type != BRO_TYPE_UNKNOWN && tbl->table->tbl_val_type != val_type) { D(("Type mismatch when unserializing val of type %d, expecting %d\n", val_type, tbl->table->tbl_val_type)); goto error_return; } tbl->table->tbl_val_type = val_type; /* Eat two doubles -- one for the last access time and * one for when the item is supposed to expire. * XXX: currently unimplemented. */ if (! __bro_buf_read_double(bc->rx_buf, &d) || ! __bro_buf_read_double(bc->rx_buf, &d)) goto error_return; /* The key type of a BroTable is always a BroListVal, even * though it might well have only a single element. * * Since we just unserialized it, we pass on ownership of * both key and value to the table. */ __bro_table_insert(tbl->table, (BroVal*) keys, val); } D_RETURN_(TRUE); error_return: __bro_table_free(tbl->table); tbl->table = NULL; D_RETURN_(FALSE); } static int __bro_table_val_write_cb_direct(BroVal *key, BroVal *val, BroConn *bc) { if (! __bro_sobject_serialize((BroSObject *) key, bc)) return FALSE; if (val && ! __bro_sobject_serialize((BroSObject *) val, bc)) return FALSE; return TRUE; } static int __bro_table_val_write_cb_unpack(BroVal *key, BroRecordVal *val, BroConn *bc) { BroRecord *rec = 0; BroListVal *lv = 0; if ( ! val ) return FALSE; rec = val->rec; lv = __bro_list_val_new(); /* Just hook the list into the list val, we unhook below. */ lv->list = rec->val_list; lv->len = rec->val_len; if (! __bro_sobject_serialize((BroSObject *) lv, bc)) goto error_return; if (! __bro_sobject_serialize((BroSObject *) val, bc)) goto error_return; lv->list = NULL; __bro_list_val_free(lv); return TRUE; error_return: lv->list = NULL; __bro_list_val_free(lv); return FALSE; } static int __bro_table_val_write(BroTableVal *tbl, BroConn *bc) { double d = 0; char opt = 0; D_ENTER; if (! __bro_mutable_val_write((BroMutableVal *) tbl, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_double(bc->tx_buf, d)) D_RETURN_(FALSE); /* XXX For now we neever send any attributes, nor an expire expr */ if (! __bro_buf_write_char(bc->tx_buf, opt)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, opt)) D_RETURN_(FALSE); /* How we iterate depends on whether the index type is atomic or not. * If atomic, we use __bro_table_val_write_cb_direct(), otherwise * we use ..._unpack(), which converts the elements of the RecordVal * into a ListVal before sending. */ if (__bro_table_val_has_atomic_key(tbl)) __bro_table_foreach(tbl->table, (BroTableCallback) __bro_table_val_write_cb_direct, bc); else __bro_table_foreach(tbl->table, (BroTableCallback) __bro_table_val_write_cb_unpack, bc); D_RETURN_(TRUE); } static int __bro_table_val_clone(BroTableVal *dst, BroTableVal *src) { D_ENTER; if (! __bro_mutable_val_clone((BroMutableVal *) dst, (BroMutableVal *) src)) D_RETURN_(FALSE); if (src->table && ! (dst->table = __bro_table_copy(src->table))) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_table_val_hash(BroTableVal *tv) { uint32 result; D_ENTER; if (! tv) D_RETURN_(0); result = __bro_sobject_hash((BroSObject*) tv->table_type); result ^= __bro_sobject_hash((BroSObject*) tv->attrs); result ^= __bro_table_hash(tv->table); D_RETURN_(result); } static int __bro_table_val_cmp(BroTableVal *tv1, BroTableVal *tv2) { D_ENTER; if (! tv1 || ! tv2) D_RETURN_(FALSE); if (! __bro_sobject_cmp((BroSObject*) tv1->table_type, (BroSObject*) tv2->table_type)) D_RETURN_(FALSE); if (! __bro_table_cmp(tv1->table, tv2->table)) D_RETURN_(FALSE); D_RETURN_(TRUE); } static void * __bro_table_val_get(BroTableVal *tbl) { return tbl->table; } int __bro_table_val_has_atomic_key(BroTableVal *tbl) { if (! tbl || ! tbl->table_type) return FALSE; return ((BroIndexType *) tbl->table_type)->indices->num_types == 1; } BroVectorVal * __bro_vector_val_new(void) { BroVectorVal *val; D_ENTER; if ( ! (val = calloc(1, sizeof(BroVectorVal))) ) D_RETURN_(NULL); __bro_vector_val_init(val); D_RETURN_(val); } static void __bro_vector_val_init(BroVectorVal *vv) { BroSObject *sobj = (BroSObject*) vv; BroVal* val = (BroVal*) vv; D_ENTER; __bro_mutable_val_init((BroMutableVal*) vv); sobj->read = (BroSObjectRead) __bro_vector_val_read; sobj->write = (BroSObjectWrite) __bro_vector_val_write; sobj->free = (BroSObjectFree) __bro_vector_val_free; sobj->clone = (BroSObjectClone) __bro_vector_val_clone; sobj->hash = (BroSObjectHash) __bro_vector_val_hash; sobj->cmp = (BroSObjectCmp) __bro_vector_val_cmp; sobj->type_id = SER_VECTOR_VAL; val->get_data = (BroValAccessor) __bro_vector_val_get; D_RETURN; } static void __bro_vector_val_free(BroVectorVal *vv) { D_ENTER; if ( ! vv ) D_RETURN; __bro_vector_free(vv->vec); __bro_mutable_val_free((BroMutableVal*) vv); D_RETURN; } static int __bro_vector_val_read(BroVectorVal *vv, BroConn *bc) { char opt; uint32 i, len; BroVal *val; D_ENTER; if ( ! __bro_mutable_val_read((BroMutableVal*) vv, bc) ) D_RETURN_(FALSE); __bro_vector_free(vv->vec); if ( ! (vv->vec = __bro_vector_new()) ) D_RETURN_(FALSE); if ( ! __bro_buf_read_int(bc->rx_buf, &len) ) goto error_return; for ( i = 0; i < len; i++ ) { D(("Reading val %i/%i into vector %p of val %p\n", i+1, len, vv->vec, vv)); if ( ! __bro_buf_read_char(bc->rx_buf, &opt) ) goto error_return; if ( opt ) { if ( ! (val = (BroVal*) __bro_sobject_unserialize(SER_IS_VAL, bc)) ) { D(("WARNING -- unserializing vector element failed.\n")); goto error_return; } } else { D(("WARNING -- unassigned val.\n")); if ( ! (val = __bro_val_new()) ) goto error_return; } if ( ! __bro_vector_add_val(vv->vec, val) ) { D(("WARNING -- failed to append element %i", i+1)); goto error_return; } } D_RETURN_(TRUE); error_return: __bro_vector_free(vv->vec); vv->vec = NULL; D_RETURN_(FALSE); } static int __bro_vector_val_write(BroVectorVal *vv, BroConn *bc) { BroVal *val; int i; D_ENTER; if ( ! vv->vec ) D_RETURN_(FALSE); if (! __bro_mutable_val_write((BroMutableVal *) vv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, vv->vec->length)) D_RETURN_(FALSE); D(("Writing out %i vals in vector %p.\n", vv->vec->length, vv->vec)); for ( i = 0; i < vv->vec->length; ++i ) { val = vv->vec->vector[i]; D(("Val %i/%p's type: %p\n", i, val, val->val_type)); if ( ! __bro_buf_write_char(bc->tx_buf, (val->val_type ? 1 : 0)) ) D_RETURN_(FALSE); if ( val->val_type ) if ( ! __bro_sobject_serialize((BroSObject*) val, bc) ) D_RETURN_(FALSE); } D_RETURN_(TRUE); } static int __bro_vector_val_clone(BroVectorVal *dst, BroVectorVal *src) { D_ENTER; if (! __bro_mutable_val_clone((BroMutableVal *) dst, (BroMutableVal *) src)) D_RETURN_(FALSE); if ( src->vec && ! (dst->vec = __bro_vector_copy(src->vec)) ) D_RETURN_(FALSE); D_RETURN_(TRUE); } static uint32 __bro_vector_val_hash(BroVectorVal *vv) { uint32 result; D_ENTER; if ( ! vv ) D_RETURN_(0); result = __bro_vector_hash(vv->vec); D_RETURN_(result); } static int __bro_vector_val_cmp(BroVectorVal *vv1, BroVectorVal *vv2) { D_ENTER; if ( ! vv1 || ! vv2 ) D_RETURN_(FALSE); if ( ! __bro_vector_cmp(vv1->vec, vv2->vec) ) D_RETURN_(FALSE); D_RETURN_(TRUE); } static void *__bro_vector_val_get(BroVectorVal *vv) { return vv->vec; } broccoli-1.97-minimal/src/bro_parser.y0000664002342100234210000000427612523041064017635 0ustar johannajohanna%{ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "bro_debug.h" #include "bro_config.h" int brolex(void); int broparse(void); int broerror(char *, ...); #define yylex brolex #define yyparse broparse #define yyerror broerror int bro_parse_errors = 0; int bro_parse_lineno = 0; const char *bro_parse_filename = NULL; %} %union { int i; char *s; double d; } %token BROINT %token BROWORD BROSTRING %token BRODOUBLE %% configfile: | options ; options: option | options option ; option: domain | intopt | stringopt | floatopt ; intopt: BROWORD BROINT { __bro_conf_add_int($1, $2); free($1); } ; stringopt: BROWORD BROSTRING { __bro_conf_add_str($1, $2); free($1); free($2); } | BROWORD BROWORD { __bro_conf_add_str($1, $2); free($1); free($2); } ; floatopt: BROWORD BRODOUBLE { __bro_conf_add_dbl($1, $2); free($1); } ; domain: '[' BROWORD ']' { __bro_conf_set_storage_domain($2); free($2); } ; %% int yyerror(char *fmt, ...) { va_list ap; bro_parse_errors++; #ifdef BRO_DEBUG va_start(ap, fmt); fprintf(stderr, "%s:%d: ", bro_parse_filename, bro_parse_lineno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); #endif return 0; } int __bro_parse_config(const char *filename) { const char *domain; extern FILE *broin; /* Save the current config domain */ if ( (domain = __bro_conf_get_domain())) domain = strdup(domain); D(("Parsing configuration from '%s'.\n", filename)); if (! (broin = fopen(filename, "r"))) { D(("Error opening config file %s: %s\n", filename, strerror(errno))); return -1; } bro_parse_lineno = 1; bro_parse_filename = filename; bro_parse_errors = 0; yyparse(); fclose(broin); /* Reset the config domain to the original one. */ __bro_conf_set_domain(domain); return (bro_parse_errors ? -1 : 0); } broccoli-1.97-minimal/src/bro_object.c0000664002342100234210000000753612523041064017563 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #ifdef __EMX__ #include #endif #include #include #include BroObject * __bro_object_new(void) { BroObject *obj; D_ENTER; if (! (obj = calloc(1, sizeof(BroObject)))) D_RETURN_(NULL); __bro_object_init(obj); D_RETURN_(obj); } void __bro_object_init(BroObject *obj) { BroSObject *sobj = (BroSObject *) obj; D_ENTER; __bro_sobject_init(sobj); sobj->read = (BroSObjectRead) __bro_object_read; sobj->write = (BroSObjectWrite)__bro_object_write; sobj->free = (BroSObjectFree) __bro_object_free; sobj->clone = (BroSObjectClone) __bro_object_clone; sobj->hash = (BroSObjectHash) __bro_object_hash; sobj->cmp = (BroSObjectCmp) __bro_object_cmp; D_RETURN; } void __bro_object_free(BroObject *obj) { D_ENTER; if (! obj) D_RETURN; __bro_sobject_release((BroSObject *) obj->loc); __bro_sobject_free((BroSObject *) obj); D_RETURN; } int __bro_object_read(BroObject *obj, BroConn *bc) { char opt; D_ENTER; if (! __bro_sobject_read((BroSObject *) obj, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (! (obj->loc = (BroLoc *) __bro_sobject_unserialize(SER_LOCATION, bc))) D_RETURN_(FALSE); } D_RETURN_(TRUE); } int __bro_object_write(BroObject *obj, BroConn *bc) { D_ENTER; if (! __bro_sobject_write((BroSObject *) obj, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, obj->loc ? 1 : 0)) D_RETURN_(FALSE); if (obj->loc && ! __bro_sobject_serialize((BroSObject *) obj->loc, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); } int __bro_object_clone(BroObject *dst, BroObject *src) { D_ENTER; if (! __bro_sobject_clone((BroSObject *) dst, (BroSObject *) src)) { D(("Cloning parent failed.\n")); D_RETURN_(FALSE); } if (src->loc && ! (dst->loc = (BroLoc *) __bro_sobject_copy((BroSObject *) src->loc))) { D(("Cloning location failed.\n")); D_RETURN_(FALSE); } D_RETURN_(TRUE); } uint32 __bro_object_hash(BroObject *obj) { uint32 result; D_ENTER; if (! obj) D_RETURN_(0); result = __bro_sobject_hash((BroSObject *) obj); result ^= __bro_loc_hash(obj->loc); D_RETURN_(result); } int __bro_object_cmp(BroObject *obj1, BroObject *obj2) { D_ENTER; if (! obj1 || ! obj2) D_RETURN_(FALSE); D_RETURN_(__bro_loc_cmp(obj1->loc, obj2->loc)); } broccoli-1.97-minimal/src/bro_openssl.h0000664002342100234210000000420512523041064017773 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_openssl_h #define broccoli_openssl_h #include int __bro_openssl_init(void); int __bro_openssl_encrypted(void); int __bro_openssl_rand_bytes(u_char *buf, int num); int __bro_openssl_connect(BroConn *bc); /* Like __bro_openssl_connect, but uses gross manual-connect hack to make * sure peer is actually available. */ int __bro_openssl_reconnect(BroConn *bc); void __bro_openssl_shutdown(BroConn *bc); int __bro_openssl_read(BroConn *bc, uchar *buf, uint buf_size); /** * __bro_openssl_write - writes a chunk of data to the connection. * @param bc Bro connection handle. * @param buf buffer of data to write. * @param buf_size size of buffer pointed to by @p buf. * * Returns: value < 0 on error, 1 if all data was written, 0 * otherwise (*no* data being written). */ int __bro_openssl_write(BroConn *bc, uchar *buf, uint buf_size); #endif broccoli-1.97-minimal/src/bro_sobject.h0000664002342100234210000002723612523041064017752 0ustar johannajohanna/* B R O C C O L I -- The Bro Client Communications Library Copyright (C) 2004-2008 Christian Kreibich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef broccoli_serial_object_h #define broccoli_serial_object_h #include #include /* A whole bunch of definitons taken straight out of Bro and run through cpp :) * These are type tags -- see explanation in SerialTypes.h in the Bro tree. We use * these tags to map to the default constructor implementation for an * object upon unserialization. */ #define SER_TYPE_MASK 0xff00 #define SER_NONE 0 /* "Abstract" parent classes, not used directly */ #define SER_IS_OBJ 0x8000 #define SER_IS_CONNECTION (0x0100 | SER_IS_OBJ) #define SER_IS_TIMER 0x0200 #define SER_IS_TCP_ENDPOINT 0x0300 #define SER_IS_TCP_ANALYZER (0x0400 | SER_IS_OBJ) #define SER_IS_TCP_ENDPOINT_ANALYZER (0x0500 | SER_IS_OBJ) #define SER_IS_TCP_CONTENTS 0x0600 #define SER_IS_REASSEMBLER 0x0700 #define SER_IS_VAL (0x0800 | SER_IS_OBJ) #define SER_IS_EXPR (0x0900 | SER_IS_OBJ) #define SER_IS_TYPE (0x0a00 | SER_IS_OBJ) #define SER_IS_STMT (0x0b00 | SER_IS_OBJ) #define SER_IS_ATTRIBUTES (0x0c00 | SER_IS_OBJ) #define SER_IS_EVENT_HANDLER 0x0d00 #define SER_IS_FILE (0x0e00 | SER_IS_OBJ) #define SER_IS_FUNC (0x0f00 | SER_IS_OBJ) #define SER_IS_ID (0x1000 | SER_IS_OBJ) #define SER_IS_STATE_ACCESS 0x1100 #define SER_IS_CASE (0x1200 | SER_IS_OBJ) #define SER_IS_LOCATION 0x1300 #define SER_IS_RE_MATCHER 0x1400 /* Usable derivations */ #define SER_OBJ (1 | SER_IS_OBJ) #define SER_VAL (1 | SER_IS_VAL) #define SER_INTERVAL_VAL (2 | SER_IS_VAL) #define SER_PORT_VAL (3 | SER_IS_VAL) #define SER_ADDR_VAL (4 | SER_IS_VAL) #define SER_SUBNET_VAL (5 | SER_IS_VAL) #define SER_STRING_VAL (6 | SER_IS_VAL) #define SER_PATTERN_VAL (7 | SER_IS_VAL) #define SER_LIST_VAL (8 | SER_IS_VAL) #define SER_TABLE_VAL (9 | SER_IS_VAL) #define SER_RECORD_VAL (10 | SER_IS_VAL) #define SER_ENUM_VAL (11 | SER_IS_VAL) #define SER_VECTOR_VAL (12 | SER_IS_VAL) #define SER_MUTABLE_VAL (13 | SER_IS_VAL) #define SER_EXPR (1 | SER_IS_EXPR) #define SER_NAME_EXPR (2 | SER_IS_EXPR) #define SER_CONST_EXPR (3 | SER_IS_EXPR) #define SER_UNARY_EXPR (4 | SER_IS_EXPR) #define SER_BINARY_EXPR (5 | SER_IS_EXPR) #define SER_INCR_EXPR (6 | SER_IS_EXPR) #define SER_NOT_EXPR (7 | SER_IS_EXPR) #define SER_POS_EXPR (8 | SER_IS_EXPR) #define SER_NEG_EXPR (9 | SER_IS_EXPR) #define SER_ADD_EXPR (10 | SER_IS_EXPR) #define SER_SUB_EXPR (11 | SER_IS_EXPR) #define SER_TIMES_EXPR (12 | SER_IS_EXPR) #define SER_DIVIDE_EXPR (13 | SER_IS_EXPR) #define SER_MOD_EXPR (14 | SER_IS_EXPR) #define SER_BOOL_EXPR (15 | SER_IS_EXPR) #define SER_EQ_EXPR (16 | SER_IS_EXPR) #define SER_REL_EXPR (17 | SER_IS_EXPR) #define SER_COND_EXPR (18 | SER_IS_EXPR) #define SER_REF_EXPR (19 | SER_IS_EXPR) #define SER_ASSIGN_EXPR (20 | SER_IS_EXPR) #define SER_INDEX_EXPR (21 | SER_IS_EXPR) #define SER_FIELD_EXPR (22 | SER_IS_EXPR) #define SER_HAS_FIELD_EXPR (23 | SER_IS_EXPR) #define SER_RECORD_CONSTRUCTOR_EXPR (24 | SER_IS_EXPR) #define SER_FIELD_ASSIGN_EXPR (25 | SER_IS_EXPR) // No longer used by Bro. // #define SER_RECORD_MATCH_EXPR (26 | SER_IS_EXPR) #define SER_ARITH_COERCE_EXPR (27 | SER_IS_EXPR) #define SER_RECORD_COERCE_EXPR (28 | SER_IS_EXPR) #define SER_FLATTEN_EXPR (29 | SER_IS_EXPR) #define SER_SCHEDULE_EXPR (30 | SER_IS_EXPR) #define SER_IN_EXPR (31 | SER_IS_EXPR) #define SER_CALL_EXPR (32 | SER_IS_EXPR) #define SER_EVENT_EXPR (33 | SER_IS_EXPR) #define SER_LIST_EXPR (34 | SER_IS_EXPR) #define SER_RECORD_ASSIGN_EXPR (35 | SER_IS_EXPR) #define SER_TYPE (1 | SER_IS_TYPE) #define SER_TYPE_LIST (2 | SER_IS_TYPE) #define SER_INDEX_TYPE (3 | SER_IS_TYPE) #define SER_TABLE_TYPE (4 | SER_IS_TYPE) #define SER_SET_TYPE (5 | SER_IS_TYPE) #define SER_FUNC_TYPE (6 | SER_IS_TYPE) #define SER_RECORD_TYPE (7 | SER_IS_TYPE) #define SER_SUBNET_TYPE (8 | SER_IS_TYPE) #define SER_FILE_TYPE (9 | SER_IS_TYPE) #define SER_ENUM_TYPE (10 | SER_IS_TYPE) #define SER_VECTOR_TYPE (11 | SER_IS_TYPE) #define SER_ATTRIBUTES (1 | SER_IS_ATTRIBUTES) #define SER_EVENT_HANDLER (1 | SER_IS_EVENT_HANDLER) #define SER_FILE (1 | SER_IS_FILE) #define SER_FUNC (1 | SER_IS_FUNC) #define SER_BRO_FUNC (2 | SER_IS_FUNC) #define SER_DEBUG_FUNC (3 | SER_IS_FUNC) #define SER_BUILTIN_FUNC (4 | SER_IS_FUNC) #define SER_ID (1 | SER_IS_ID) #define SER_STATE_ACCESS (1 | SER_IS_STATE_ACCESS) #define SER_CASE (1 | SER_IS_CASE) #define SER_LOCATION (1 | SER_IS_LOCATION) #define SER_RE_MATCHER (1 | SER_IS_RE_MATCHER) typedef struct bro_serial_object BroSObject; typedef BroSObject *(* BroSObjectNew) (void); /* Signatures for all functions which we virtualize. */ typedef int (* BroSObjectRead) (BroSObject *obj, BroConn *bc); typedef int (* BroSObjectWrite) (BroSObject *obj, BroConn *bc); typedef void (* BroSObjectFree) (BroSObject *obj); typedef int (* BroSObjectClone) (BroSObject *dst, BroSObject *src); typedef uint32 (* BroSObjectHash) (BroSObject *obj); typedef int (* BroSObjectCmp) (BroSObject *obj1, BroSObject *obj2); /* BroSObjects are the base "class" of objects that can be serialized. * They mirror SerialObj in Bro. The way Broccoli realizes classes, * objects, and inheritance is as follows: * * (1) There is no distinction between classes and the objects that * are created from them. That means that each object carries with * it all the function pointers needed to implement polymorphism. * Yes, this wastes space, but for now I don't think it wastes * enough to justify the additional complexity of explicit-class, * Gtk-style object orientation in C. * * (2) Currently, the only virtualized functions are the ones defined * in BroSObject below, though this may change in the future. * These functions implement reading/writing from/to a buffer, * cleanup, cloning, hashing to a uint32, and strcmp()-style * instance comparison. * * Implementations of these functions need to work in typical OO * fashion, i.e., they may need to call the implementation of the * parent "class" explicitly. This is the case for the (un)seriali- * zation functions (which need to read/write all elements of the * inheritance chain. It is not the case for the virtual ..._hash() * and ..._cmp() implementations, which usually define equality * and the computed hash value exclusively from the most derived * type's values. * * (3) Instances of BroSObject are usually created either by * unserializing them from a buffer (via __bro_sobject_unserialize()) * or by specialized "constructors" in inherited classes. The * main constructor of this sort if __bro_val_new_of_type(), which * initializes BroVals with correct type information. * * Instances of BroSObject are to be deallocated via * __bro_sobject_release(). Since BroSObjects may be referenced * in multiple locations (the serialization cache being a main * example), you must not explicitly release the memory associated * with a BroSObject but let the BroSObject implementation decide * when to do so. */ struct bro_serial_object { /* The value by which the object is identified in the * serialization cache. */ uint32 perm_id; /* One of the SER_xxx values above to identify the type * of object upon (un)serialization. */ uint16 type_id; /* Reference count, used for unserialized objects that * sit in the connection's serialization cache and may * be referenced by multiple SObjects. */ int ref_count; /* Storage for arbitrary user data: */ BroHT *data; BroSObjectRead read; BroSObjectWrite write; BroSObjectFree free; BroSObjectClone clone; BroSObjectHash hash; BroSObjectCmp cmp; }; BroSObject *__bro_sobject_create(uint16 type_id); void __bro_sobject_release(BroSObject *obj); void __bro_sobject_ref(BroSObject *obj); BroSObject *__bro_sobject_copy(BroSObject *obj); BroSObject *__bro_sobject_new(void); void __bro_sobject_init(BroSObject *obj); void __bro_sobject_free(BroSObject *obj); /* We need the connection handle for the next two and not just * a buffer because we might need the cache associated with the * connection. */ int __bro_sobject_serialize(BroSObject *obj, BroConn *bc); BroSObject *__bro_sobject_unserialize(uint16 type_id, BroConn *bc); /* Hash a SObject or compare them. These are the virtualized * functions -- the actual implementation of these functions * for SObjects themselves are static in bro_sobject.c. */ uint32 __bro_sobject_hash(BroSObject *obj); int __bro_sobject_cmp(BroSObject *obj1, BroSObject *obj2); int __bro_sobject_read(BroSObject *obj, BroConn *bc); int __bro_sobject_write(BroSObject *obj, BroConn *bc); int __bro_sobject_clone(BroSObject *dst, BroSObject *src); /* Our base class has a facility for associating arbitrary stuff * with each instance. Make sure to clean up the associated items * before releasing the instance, because the object doesn't know * how to do this. */ void __bro_sobject_data_set(BroSObject *obj, const char *key, void *val); void *__bro_sobject_data_get(BroSObject *obj, const char *key); void *__bro_sobject_data_del(BroSObject *obj, const char *key); #endif broccoli-1.97-minimal/src/bro_lexer.l0000664002342100234210000000210112523041064017424 0ustar johannajohanna%option noyywrap %{ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "broccoli.h" #include "bro_debug.h" #include "bro_parser.h" int broerror(char *fmt, ...); #define yyerror broerror #define yylval brolval extern int bro_parse_lineno; %} %% [\[\]] return yytext[0]; yes|true|on { yylval.i = 1; return BROINT; } no|false|off { yylval.i = 0; return BROINT; } [ \t]+ ; [0-9]+ { yylval.i = strtol(yytext, NULL, 10); return BROINT; } [0-9]+\.[0-9]+ { yylval.d = strtod(yytext, NULL); return BRODOUBLE; } \".*\" { yylval.s = strdup(yytext+1); yylval.s[strlen(yylval.s) - 1] = '\0'; return BROSTRING; } [[:alnum:][:punct:]]+ { yylval.s = strdup(yytext); return BROWORD; } "#".*\n { bro_parse_lineno++; } "//".*\n { bro_parse_lineno++; } \n { bro_parse_lineno++; } . { D(("Syntax error: '%s'\n", yytext)); } %% broccoli-1.97-minimal/Makefile0000664002342100234210000000321712523041064016150 0ustar johannajohanna# # A simple static wrapper for a number of standard Makefile targets, # mostly just forwarding to build/Makefile. This is provided only for # convenience and supports only a subset of what CMake's Makefile # to offer. For more, execute that one directly. # BUILD=build REPO=`basename \`git config --get remote.origin.url | sed 's/^[^:]*://g'\`` VERSION_FULL=$(REPO)-`cat VERSION` VERSION_MIN=$(REPO)-`cat VERSION`-minimal HAVE_MODULES=git submodule | grep -v cmake >/dev/null all: configured $(MAKE) -C $(BUILD) $@ doc: configured $(MAKE) -C $(BUILD) $@ install: configured $(MAKE) -C $(BUILD) $@ clean: configured docclean $(MAKE) -C $(BUILD) $@ docclean: configured $(MAKE) -C $(BUILD) $@ dist: @rm -rf $(VERSION_FULL) $(VERSION_FULL).tgz @rm -rf $(VERSION_MIN) $(VERSION_MIN).tgz @git clone --recursive . $(VERSION_FULL) >/dev/null 2>&1 @find $(VERSION_FULL) -name .git\* | xargs rm -rf @tar -czf $(VERSION_FULL).tgz $(VERSION_FULL) && echo Package: $(VERSION_FULL).tgz && rm -rf $(VERSION_FULL) @$(HAVE_MODULES) && git clone . $(VERSION_MIN) >/dev/null 2>&1 || exit 0 @$(HAVE_MODULES) && (cd $(VERSION_MIN) && git submodule update --init cmake >/dev/null 2>&1) || exit 0 @$(HAVE_MODULES) && find $(VERSION_MIN) -name .git\* | xargs rm -rf || exit 0 @$(HAVE_MODULES) && tar -czf $(VERSION_MIN).tgz $(VERSION_MIN) && echo Package: $(VERSION_MIN).tgz && rm -rf $(VERSION_MIN) || exit 0 distclean: rm -rf $(BUILD) .PHONY : configured configured: @test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 ) @test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )