mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

This is so that people working from the current stable version can still start using git.
4044 lines
No EOL
81 KiB
HTML
4044 lines
No EOL
81 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Using Broccoli</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
|
|
REL="HOME"
|
|
TITLE="Broccoli: The Bro Client Communications Library"
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Installing Broccoli"
|
|
HREF="c54.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Broccoli API Reference"
|
|
HREF="api.html"><LINK
|
|
REL="STYLESHEET"
|
|
TYPE="text/css"
|
|
HREF="stylesheet.css"></HEAD
|
|
><BODY
|
|
CLASS="CHAPTER"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Broccoli: The Bro Client Communications Library</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="c54.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="api.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="CHAPTER"
|
|
><H1
|
|
><A
|
|
NAME="AEN84"
|
|
></A
|
|
>Chapter 3. Using Broccoli</H1
|
|
><DIV
|
|
CLASS="TOC"
|
|
><DL
|
|
><DT
|
|
><B
|
|
>Table of Contents</B
|
|
></DT
|
|
><DT
|
|
>3.1. <A
|
|
HREF="c84.html#AEN87"
|
|
>Obtaining information about your build using <TT
|
|
CLASS="FILENAME"
|
|
>broccoli-config</TT
|
|
></A
|
|
></DT
|
|
><DT
|
|
>3.2. <A
|
|
HREF="c84.html#AEN121"
|
|
>Suggestions for instrumenting applications</A
|
|
></DT
|
|
><DT
|
|
>3.3. <A
|
|
HREF="c84.html#AEN134"
|
|
>The Broccoli API</A
|
|
></DT
|
|
><DT
|
|
>3.4. <A
|
|
HREF="c84.html#AEN738"
|
|
>Configuring encrypted communication</A
|
|
></DT
|
|
><DT
|
|
>3.5. <A
|
|
HREF="c84.html#AEN785"
|
|
>Configuring event reception in Bro policies</A
|
|
></DT
|
|
><DT
|
|
>3.6. <A
|
|
HREF="c84.html#AEN819"
|
|
>Configuring debugging output</A
|
|
></DT
|
|
><DT
|
|
>3.7. <A
|
|
HREF="c84.html#AEN843"
|
|
>Test programs</A
|
|
></DT
|
|
></DL
|
|
></DIV
|
|
><P
|
|
> </P
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN87"
|
|
>3.1. Obtaining information about your build using <TT
|
|
CLASS="FILENAME"
|
|
>broccoli-config</TT
|
|
></A
|
|
></H1
|
|
><P
|
|
> 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:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--build</B
|
|
> prints the name of the machine the build was
|
|
made on, when, and whether debugging support was enabled or not.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--prefix</B
|
|
> prints the directory in the filesystem
|
|
below which Broccoli was installed.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--version</B
|
|
> prints the version of the distribution
|
|
you have installed.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--libs</B
|
|
> prints the flags to pass to the
|
|
linker in order to link in the Broccoli library.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--cflags</B
|
|
> prints the flags to pass to the
|
|
compiler in order to properly include Broccoli's header file.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>--config</B
|
|
> prints the location of the system-wide
|
|
config file your installation will use.</P
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
><P
|
|
> The <TT
|
|
CLASS="FILENAME"
|
|
>--cflags</TT
|
|
> and <TT
|
|
CLASS="FILENAME"
|
|
>--libs</TT
|
|
> flags
|
|
are the suggested way of obtaining the necessary information for integrating
|
|
Broccoli into your build environment. It is generally recommended to use
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>broccoli-config</TT
|
|
> for this purpose, rather than, say,
|
|
develop new <B
|
|
CLASS="COMMAND"
|
|
>autoconf </B
|
|
> tests.
|
|
If you use the <B
|
|
CLASS="COMMAND"
|
|
>autoconf</B
|
|
>/<B
|
|
CLASS="COMMAND"
|
|
>automake</B
|
|
>
|
|
tools, we recommend something along the following lines for your
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>configure</TT
|
|
> script:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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)
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> You can then use the compiler/linker flags in your Makefile.in/ams by
|
|
substituting in the values accordingly, which might look as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>CFLAGS = -W -Wall -g -DFOOBAR @broccoli_cflags@
|
|
LDFLAGS = -L/usr/lib/foobar @broccoli_libs@
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN121"
|
|
>3.2. Suggestions for instrumenting applications</A
|
|
></H1
|
|
><P
|
|
> Often you will want to make existing applications Bro-aware,
|
|
that is, <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>instrument</B
|
|
></SPAN
|
|
> 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
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>#ifdef</CODE
|
|
>/<CODE
|
|
CLASS="FUNCTION"
|
|
>#endif</CODE
|
|
>
|
|
statements you can still build the original application, using the
|
|
instrumented source tree. The <TT
|
|
CLASS="FILENAME"
|
|
>broccoli-config</TT
|
|
> script helps you in doing so because
|
|
it already adds <CODE
|
|
CLASS="FUNCTION"
|
|
>-DBROCCOLI</CODE
|
|
> to the compiler flags
|
|
reported when run with the <TT
|
|
CLASS="FILENAME"
|
|
>--cflags</TT
|
|
> option:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>cpk25@localhost:/home/cpk25 > broccoli-config --cflags
|
|
-I/usr/local/include -I/usr/local/include -DBROCCOLI
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> So simply surround all inserted code with a preprocessor check
|
|
for <CODE
|
|
CLASS="FUNCTION"
|
|
>BROCCOLI</CODE
|
|
> and you will be able to
|
|
build the original application as soon as <CODE
|
|
CLASS="FUNCTION"
|
|
>BROCCOLI</CODE
|
|
>
|
|
is not defined.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN134"
|
|
>3.3. The Broccoli API</A
|
|
></H1
|
|
><P
|
|
> 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 <TT
|
|
CLASS="FILENAME"
|
|
>broccoli.h</TT
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#ifdef BROCCOLI
|
|
#include <broccoli.h>
|
|
#endif
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>A note on Broccoli's memory management philosophy:</B
|
|
></SPAN
|
|
></P
|
|
><P
|
|
>Broccoli generally does not release objects you allocate.
|
|
The approach taken is "you clean up what you allocate."
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN143"
|
|
>3.3.1. Initialization</A
|
|
></H2
|
|
><P
|
|
> Broccoli requires global initialization before most of its
|
|
other other functions can be used. Generally, the way to
|
|
initialize Broccoli is as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>bro_init(NULL);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> The argument to
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_init()</CODE
|
|
>
|
|
provides optional initialization context, and may be kept
|
|
<CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
> for normal use. If required, you may
|
|
allocate a <TT
|
|
CLASS="FILENAME"
|
|
>BroCtx</TT
|
|
> structure locally,
|
|
initialize it using
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_ctx_init()</CODE
|
|
>,
|
|
fill in additional values as required and and subsequently pass it to
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_init()</CODE
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>BroCtx ctx;
|
|
bro_ctx_init(&ctx);
|
|
/* Make adjustments to the context structure as required... */
|
|
bro_init(&ctx);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
> The <TT
|
|
CLASS="FILENAME"
|
|
>BroCtx</TT
|
|
> structure currently contains
|
|
a set of five different callback function pointers. These
|
|
are <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>required</B
|
|
></SPAN
|
|
> 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
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>BroCtx</TT
|
|
> structure. The O'Reilly book
|
|
"Network Security with OpenSSL" by Viega et al. shows how to
|
|
implement these callbacks.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>You <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>must</B
|
|
></SPAN
|
|
> call
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_init()</CODE
|
|
>
|
|
at the start of your application. Undefined behavior may result
|
|
if you don't.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN167"
|
|
>3.3.2. Data types in Broccoli</A
|
|
></H2
|
|
><P
|
|
> Broccoli declares a number of data types in <TT
|
|
CLASS="FILENAME"
|
|
>broccoli.h</TT
|
|
> 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:
|
|
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>Simple signed and unsigned types: <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
>, <SPAN
|
|
CLASS="TYPE"
|
|
>uint</SPAN
|
|
>,
|
|
<SPAN
|
|
CLASS="TYPE"
|
|
>uint32</SPAN
|
|
>, <SPAN
|
|
CLASS="TYPE"
|
|
>uint16</SPAN
|
|
> and <SPAN
|
|
CLASS="TYPE"
|
|
>uchar</SPAN
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Connection handles: <SPAN
|
|
CLASS="TYPE"
|
|
>BroConn</SPAN
|
|
>, kept opaque.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Bro events: <SPAN
|
|
CLASS="TYPE"
|
|
>BroEvent</SPAN
|
|
>, kept opaque.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Buffer objects: <SPAN
|
|
CLASS="TYPE"
|
|
>BroBuf</SPAN
|
|
>, kept opaque. See the separate
|
|
<A
|
|
HREF="c84.html#AEN696"
|
|
>section on buffer management</A
|
|
> for details.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Ports: <SPAN
|
|
CLASS="TYPE"
|
|
>BroPort</SPAN
|
|
> for network ports, defined as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>typedef struct bro_port {
|
|
uint16 port_num; /* port number in host byte order */
|
|
int port_proto; /* IPPROTO_xxx */
|
|
} BroPort;
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Records: <SPAN
|
|
CLASS="TYPE"
|
|
>BroRecord</SPAN
|
|
>, kept opaque. See the separate
|
|
<A
|
|
HREF="c84.html#AEN554"
|
|
>section on record handling</A
|
|
> for details.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Strings (character and binary): <SPAN
|
|
CLASS="TYPE"
|
|
>BroString</SPAN
|
|
>, defined as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>typedef struct bro_string {
|
|
int str_len;
|
|
char *str_val;
|
|
} BroString;
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> BroStrings are mostly kept transparent for convenience; please have a look at the
|
|
string API:
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-INIT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_init()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-SET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_set()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-SET-DATA"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_set_data()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-COPY"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_copy()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-CLEANUP"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_cleanup()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-STRING-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_free()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Tables: <SPAN
|
|
CLASS="TYPE"
|
|
>BroTable</SPAN
|
|
>, kept opaque. See the separate
|
|
<A
|
|
HREF="c84.html#AEN599"
|
|
>section on table handling</A
|
|
> for details.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Sets: <SPAN
|
|
CLASS="TYPE"
|
|
>BroSet</SPAN
|
|
>, kept opaque. See the separate
|
|
<A
|
|
HREF="c84.html#AEN636"
|
|
>section on table handling</A
|
|
> for details.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Subnets: <SPAN
|
|
CLASS="TYPE"
|
|
>BroSubnet</SPAN
|
|
>, defined as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>typedef struct bro_subnet
|
|
{
|
|
uint32 sn_net; /* IP address in network byte order */
|
|
uint32 sn_width; /* Length of prefix to consider. */
|
|
} BroSubnet;
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN226"
|
|
>3.3.3. Managing connections</A
|
|
></H2
|
|
><P
|
|
> 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.)
|
|
</P
|
|
><P
|
|
>
|
|
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 <CODE
|
|
CLASS="FUNCTION"
|
|
>BroConn</CODE
|
|
>
|
|
structures, which are kept opaque. Use
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_new()</CODE
|
|
></A
|
|
> or
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-NEW-STR"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_new_str()</CODE
|
|
></A
|
|
>
|
|
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.
|
|
</P
|
|
><P
|
|
> To write a Broccoli-enabled server, you first need to implement the usual
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>socket()</CODE
|
|
> / <CODE
|
|
CLASS="FUNCTION"
|
|
>bind()</CODE
|
|
> /
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>listen()</CODE
|
|
> / <CODE
|
|
CLASS="FUNCTION"
|
|
>accept()</CODE
|
|
> routine.
|
|
Once you have obtained a file descriptor for the new connection from <CODE
|
|
CLASS="FUNCTION"
|
|
>accept()</CODE
|
|
>,
|
|
you pass it to the third function that returns a <CODE
|
|
CLASS="FUNCTION"
|
|
>BroConn</CODE
|
|
>
|
|
handle,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-NEW-SOCKET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_new_socket()</CODE
|
|
></A
|
|
>.
|
|
The rest of the connection handling then proceeds as in the client scenario.
|
|
</P
|
|
><P
|
|
>
|
|
All three calls accept additional flags for fine-tuning connection behaviour.
|
|
These flags are:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_NONE</CODE
|
|
>: no functionality. Use when
|
|
no flags are desired.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_RECONNECT</CODE
|
|
>:
|
|
When using this option, Broccoli will attempt to reconnect to the peer
|
|
after lost connectivity transparently. Essentially whenever you try to
|
|
read from or write to the peer and its connection 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-ALIVE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_alive()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_ALWAYS_QUEUE</CODE
|
|
>:
|
|
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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-ALIVE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_alive()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_DONTCACHE</CODE
|
|
>:
|
|
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.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_CACHE</CODE
|
|
>:
|
|
When using this option, Broccoli will ask the peer to use caching on
|
|
the objects it sends to us. Caching is normally disabled.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_CFLAG_YIELD</CODE
|
|
>: When
|
|
using this option,
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_process_input()</CODE
|
|
>
|
|
processes at most one event at a time and then
|
|
returns.
|
|
</P
|
|
></LI
|
|
></UL
|
|
>
|
|
|
|
</P
|
|
><P
|
|
> By obtaining a connection handle, you do not also establish a connection right
|
|
away. This is done using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-CONNECT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_connect()</CODE
|
|
></A
|
|
>.
|
|
The main reason for this is to allow you to subscribe to events
|
|
(using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add()</CODE
|
|
></A
|
|
>,
|
|
see <A
|
|
HREF="c84.html#AEN461"
|
|
>below</A
|
|
>)
|
|
before establishing the connection. Upon returning from
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-CONNECT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_connect()</CODE
|
|
></A
|
|
>
|
|
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
|
|
<A
|
|
HREF="c84.html#AEN738"
|
|
>"Configuring encrypted communication"</A
|
|
> below for more
|
|
information on setting up enncryption.
|
|
The port numbers Bro agents and Broccoli applications listen on can vary from peer
|
|
to peer.
|
|
</P
|
|
><P
|
|
> Finally, <A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-DELETE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_delete()</CODE
|
|
></A
|
|
>
|
|
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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-GET-FD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_get_fd()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> Or simply use the string-based version:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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. */
|
|
}
|
|
|
|
/* ... */
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN286"
|
|
>3.3.4. Connection classes</A
|
|
></H2
|
|
><P
|
|
> 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 likey want to receive different types of events.
|
|
</P
|
|
><P
|
|
> Broccoli lets you set the class of a connection using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-SET-CLASS"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_set_class()</CODE
|
|
></A
|
|
>.
|
|
When using this feature, you need to call that function before issuing a
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-CONNECT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_connect()</CODE
|
|
></A
|
|
>,
|
|
since the class of a connection is determined at connection startup.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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. */
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> If your peer is a Bro node, you need to match the chosen connection class in
|
|
the remote Bro's <CODE
|
|
CLASS="FUNCTION"
|
|
>Remote::destinations</CODE
|
|
> configuration.
|
|
See <A
|
|
HREF="c84.html#AEN785"
|
|
>below</A
|
|
> for how to do this.
|
|
Finally, in order to obtain the class of a connection as indicated by the remote side, use
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-GET-PEER-CLASS"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_get_peer_class()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN300"
|
|
>3.3.5. Composing and sending events</A
|
|
></H2
|
|
><P
|
|
> 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.
|
|
</P
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
> <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Bro peers ignore unrequested events.</B
|
|
></SPAN
|
|
>
|
|
</P
|
|
><P
|
|
> 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 <A
|
|
HREF="c84.html#AEN785"
|
|
>below</A
|
|
>
|
|
and for now assume that our remote peer is configured to receive the
|
|
events we send.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> 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 <CODE
|
|
CLASS="FUNCTION"
|
|
>remote_conn</CODE
|
|
> events
|
|
containing the information we asked for. The definition of our
|
|
requesting event could look as follows in the Bro policy:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>event report_conns(req_id: int, dest_host: string, dest_port: port, min_size: count);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> First, create a new event:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>BroEvent *ev;
|
|
|
|
if (! (ev = bro_event_new("report_conns"))) {
|
|
/* Error handling - could not allocate new event. */
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-ADD-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_add_val()</CODE
|
|
></A
|
|
>
|
|
All values are passed as <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>pointer arguments</B
|
|
></SPAN
|
|
> 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.
|
|
<A
|
|
HREF="c84.html#TABLE-1"
|
|
>Table 1</A
|
|
> lists the value types that Broccoli supports along with
|
|
the type identifier and data structures to point to.
|
|
</P
|
|
><DIV
|
|
CLASS="TABLE"
|
|
><A
|
|
NAME="TABLE-1"
|
|
></A
|
|
><P
|
|
><B
|
|
>Table 3-1. Types, type tags, and data structures for event parameters in Broccoli</B
|
|
></P
|
|
><TABLE
|
|
BORDER="1"
|
|
FRAME="vsides"
|
|
RULES="all"
|
|
CLASS="CALSTABLE"
|
|
><COL><COL><COL><THEAD
|
|
><TR
|
|
><TH
|
|
ALIGN="CENTER"
|
|
>Type</TH
|
|
><TH
|
|
ALIGN="CENTER"
|
|
>Type tag</TH
|
|
><TH
|
|
ALIGN="CENTER"
|
|
>Data type pointed to</TH
|
|
></TR
|
|
></THEAD
|
|
><TBODY
|
|
><TR
|
|
><TD
|
|
>Boolean</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_BOOL</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>int</CODE
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Integer value</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_INT</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>int</CODE
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Counter (nonnegative integers)</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_COUNT</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>uint32</CODE
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Enums (enumerated values)</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_ENUM</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>int</CODE
|
|
> (see also the description of
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-ADD-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_add_val()</CODE
|
|
></A
|
|
>'s
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>type_name</CODE
|
|
> argument below)</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Floating-point number</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_DOUBLE</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>double</CODE
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Timestamp</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_TIME</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>double</CODE
|
|
> (see also
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-UTIL-TIMEVAL-TO-DOUBLE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_util_timeval_to_double()</CODE
|
|
></A
|
|
> and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-UTIL-CURRENT-TIME"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_util_current_time()</CODE
|
|
></A
|
|
>)</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Time interval</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_INTERVAL</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>double</CODE
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Strings (text and binary)</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_STRING</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroString</CODE
|
|
> (see also the family of <CODE
|
|
CLASS="FUNCTION"
|
|
>bro_string_xxx()</CODE
|
|
> functions)</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Network ports</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_PORT</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroPort</CODE
|
|
>, with the port number in host byte order</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>IPv4 address</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_IPADDR</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>uint32</CODE
|
|
>, in network byte order</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>IPv4 network</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_NET</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>uint32</CODE
|
|
>, in network byte order</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>IPv4 subnet</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_SUBNET</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroSubnet</CODE
|
|
>, with the sn_net member in network byte order</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Record</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_RECORD</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroRecord</CODE
|
|
> (see also the family of
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_xxx()</CODE
|
|
> functions and their
|
|
explanation below)</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Table</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_TABLE</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroTable</CODE
|
|
> (see also the family of
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_xxx()</CODE
|
|
> functions and their
|
|
explanation below)</TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
>Record</TD
|
|
><TD
|
|
><CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_SET</CODE
|
|
></TD
|
|
><TD
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroSet</CODE
|
|
> (see also the family of
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_xxx()</CODE
|
|
> functions and their
|
|
explanation below)</TD
|
|
></TR
|
|
></TBODY
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> Knowing these, we can now compose a
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>request_connections</CODE
|
|
> event:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> The third argument to
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-ADD-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_add_val()</CODE
|
|
></A
|
|
>
|
|
lets you specify a specialization of the types listed in
|
|
<A
|
|
HREF="c84.html#TABLE-1"
|
|
>Table 1</A
|
|
>. This is generally not necessary
|
|
except for one situationn: When using <CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_ENUM</CODE
|
|
>. 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 <CODE
|
|
CLASS="FUNCTION"
|
|
>transport_type</CODE
|
|
> defined in
|
|
Bro's <TT
|
|
CLASS="FILENAME"
|
|
>bro.init</TT
|
|
>, you would use
|
|
<TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>int transport_proto = 2;
|
|
/* ... */
|
|
bro_event_add_val(ev, BRO_TYPE_ENUM, "transport_proto", &transport_proto);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
to get the equivalent of "udp" on the remote side. The same system is used
|
|
to point out type names when calling
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-SET-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_set_val()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-ADD-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_add_val()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-SET-NTH-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_set_nth_val()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-SET-NAMED-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_set_named_val()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><P
|
|
> All that's left to do now is to send off the event. For this, use
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-SEND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_send()</CODE
|
|
></A
|
|
>
|
|
and pass it the connection handle and the event. The function returns
|
|
<CODE
|
|
CLASS="CONSTANT"
|
|
>TRUE</CODE
|
|
> when the event could be sent right away or if
|
|
it was queued for later delivery. <CODE
|
|
CLASS="CONSTANT"
|
|
>FALSE</CODE
|
|
> is returned
|
|
on error. If the event get queued, this does not indicate an error —
|
|
likely the connection was just not
|
|
ready to send the event at this point. Whenever you call
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-SEND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_send()</CODE
|
|
></A
|
|
>,
|
|
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.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>bro_event_send(bc, ev);
|
|
bro_event_free(ev);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> Two other functions may be useful to you:
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-QUEUE-LENGTH"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_queue_length()</CODE
|
|
></A
|
|
>
|
|
tells you how many events are currently queued, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-QUEUE-FLUSH"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_queue_flush()</CODE
|
|
></A
|
|
>
|
|
attempts to flush the current event queue and returns the number of events that do remain
|
|
in the queue after the flush. <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Note:</B
|
|
></SPAN
|
|
> you do not normally need
|
|
to call this function, queue flushing is attempted every time you send an event.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN461"
|
|
>3.3.6. Receiving events</A
|
|
></H2
|
|
><P
|
|
> Receiving events is a little more work because you need to
|
|
</P
|
|
><P
|
|
></P
|
|
><OL
|
|
TYPE="1"
|
|
><LI
|
|
><P
|
|
>tell Broccoli what to do when requested events arrive,</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>let the remote Bro agent know that you would like to receive those events,</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>find a spot in the code path suitable for extracting and processing arriving events.</P
|
|
></LI
|
|
></OL
|
|
><P
|
|
> Each of these steps is explained in the following sections.
|
|
</P
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN472"
|
|
>3.3.6.1. Implementing event callbacks</A
|
|
></H3
|
|
><P
|
|
> 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.
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Expanded argument passing.</B
|
|
></SPAN
|
|
> 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.
|
|
</P
|
|
><P
|
|
> In order to register a callback with expanded argument passing, use
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add()</CODE
|
|
></A
|
|
>
|
|
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 <TT
|
|
CLASS="FILENAME"
|
|
>BroEventFunc</TT
|
|
> type, and any user data (or
|
|
<CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
>) you want to see passed to the callback on
|
|
each invocation. The callback's type is defined rather generically as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>typedef void (*BroEventFunc) (BroConn *bc, void *user_data, ...);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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. <CODE
|
|
CLASS="FUNCTION"
|
|
>BroEventFunc</CODE
|
|
>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 <A
|
|
HREF="c84.html#TABLE-1"
|
|
>Table 1</A
|
|
>
|
|
again for a summary of those types. Record types are more involved and are
|
|
addressed in more detail <A
|
|
HREF="c84.html#AEN554"
|
|
>below</A
|
|
>.
|
|
</P
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="90%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>Note that <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>all</B
|
|
></SPAN
|
|
> parameters are passed to the
|
|
callback as pointers, even elementary types such as <CODE
|
|
CLASS="CONSTANT"
|
|
>int</CODE
|
|
>s
|
|
that would normally be passed directly.
|
|
Also note that Broccoli manages the lifecycle of event parameters
|
|
and therefore you do <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>not</B
|
|
></SPAN
|
|
> have to clean them up inside
|
|
the event handler.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> Continuing our example, we will want to process the connection reports
|
|
that contain the responses to our <CODE
|
|
CLASS="FUNCTION"
|
|
>report_conns</CODE
|
|
>
|
|
event. Let's assume those look as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>event remote_conn(req_id: int, conn: connection);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> The reply events contain the request ID so we can associate requests
|
|
with replies, and a connection record (defined in <TT
|
|
CLASS="FILENAME"
|
|
>bro.init</TT
|
|
>
|
|
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:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>void remote_conn_cb(BroConn *bc, void *user_data, int *req_id, BroRecord *conn);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add()</CODE
|
|
></A
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>bro_event_registry_add(bc, "remote_conn", remote_conn_cb, NULL);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> In this case we have no additional data to be passed into the
|
|
callback, so we use <CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
> for the last argument.
|
|
If you have multiple events you are interested in, register
|
|
each one in this fashion.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Compact argument passing.</B
|
|
></SPAN
|
|
> 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
|
|
<SPAN
|
|
CLASS="TYPE"
|
|
>BroEvMeta</SPAN
|
|
> 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 <A
|
|
HREF="c84.html#TABLE-1"
|
|
>Table 1</A
|
|
>),
|
|
and the arguments themselves.
|
|
</P
|
|
><P
|
|
> In order to register a callback with compact argument passing, use
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD-COMPACT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add_compact()</CODE
|
|
></A
|
|
>
|
|
and pass it similar arguments as you'd use with
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add()</CODE
|
|
></A
|
|
>.
|
|
The callback's type is defined as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>typedef void (*BroCompactEventFunc) (BroConn *bc, void *user_data, BroEvMeta *meta);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="90%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>As before, Broccoli manages the lifecycle of event parameters.
|
|
You do not have to clean up the <SPAN
|
|
CLASS="TYPE"
|
|
>BroEvMeta</SPAN
|
|
>
|
|
structure or any of its contents.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> Below is sample code for extracting the arguments form the <SPAN
|
|
CLASS="TYPE"
|
|
>BroEvMeta</SPAN
|
|
>
|
|
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.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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;
|
|
|
|
/* ... */
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> Finally, register the callback using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-ADD-COMPACT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_add_compact()</CODE
|
|
></A
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>bro_event_registry_add_compact(bc, "remote_conn", remote_conn_cb, NULL);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN527"
|
|
>3.3.6.2. Requesting event delivery</A
|
|
></H3
|
|
><P
|
|
> 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 <A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-CONNECT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_connect()</CODE
|
|
></A
|
|
>,
|
|
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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-EVENT-REGISTRY-REQUEST"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_event_registry_request()</CODE
|
|
></A
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>bro_event_registry_request(bc);
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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).
|
|
</P
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Note that at the moment you cannot unrequest events, nor
|
|
can you request events based on predicates on the values of the
|
|
events' arguments.</B
|
|
></SPAN
|
|
></P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN539"
|
|
>3.3.6.3. Reading events from the connection handle</A
|
|
></H3
|
|
><P
|
|
> 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.
|
|
</P
|
|
><P
|
|
> 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
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>select()</CODE
|
|
> on the file handle associated with a <SPAN
|
|
CLASS="TYPE"
|
|
>BroConn</SPAN
|
|
>.
|
|
The former case is particularly straightforward; all you need to do is
|
|
call
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-PROCESS-INPUT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_process_input()</CODE
|
|
></A
|
|
>,
|
|
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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-GET-FD"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_get_fd()</CODE
|
|
></A
|
|
>
|
|
to obtain the file descriptor of your connection and then incorporate that
|
|
in your standard <CODE
|
|
CLASS="FUNCTION"
|
|
>FD_SET</CODE
|
|
>/<CODE
|
|
CLASS="FUNCTION"
|
|
>select()</CODE
|
|
>
|
|
code. Once you have determined that data in fact are ready to be read from
|
|
the obtained file descriptor, you can then try another
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-PROCESS-INPUT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_process_input()</CODE
|
|
></A
|
|
>,
|
|
this time knowing that it'll find something to dispatch.
|
|
</P
|
|
><P
|
|
> 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.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN554"
|
|
>3.3.7. Handling records</A
|
|
></H2
|
|
><P
|
|
> 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 <SPAN
|
|
CLASS="TYPE"
|
|
>BroRecord</SPAN
|
|
>, 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.
|
|
</P
|
|
><P
|
|
> Note that all fields in a record must be assigned before it can be shipped.
|
|
</P
|
|
><P
|
|
> The API for record composition consists of
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_new()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_free()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-ADD-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_add_val()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-SET-NTH-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_set_nth_val()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-SET-NAMED-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_set_named_val()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><P
|
|
> On records that use field names, the names of individual fields can be extracted using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-GET-NTH-NAME"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_get_nth_name()</CODE
|
|
></A
|
|
>.
|
|
Extracting values from a record is done using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-GET-NTH-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_get_nth_val()</CODE
|
|
></A
|
|
> and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-RECORD-GET-NAMED-VAL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_record_get_named_val()</CODE
|
|
></A
|
|
>.
|
|
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 <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
> holding a
|
|
<SPAN
|
|
CLASS="TYPE"
|
|
>BRO_TYPE_xxx</SPAN
|
|
> value (see again <A
|
|
HREF="c84.html#TABLE-1"
|
|
>Table 1</A
|
|
> for a
|
|
summary of those types) or <CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
>. The pointer, if not
|
|
<CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
>, serves two purposes: type checking and type retrieval.
|
|
Type checking is performed if the value of the <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
> upon calling the
|
|
functions is not <SPAN
|
|
CLASS="TYPE"
|
|
>BRO_TYPE_UNKNOWN</SPAN
|
|
>. The type tag of the requested record
|
|
field then has to match the type tag stored in the <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
>, otherwise
|
|
<CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
> is returned. If the <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
> stores <SPAN
|
|
CLASS="TYPE"
|
|
>BRO_TYPE_UNKNOWN</SPAN
|
|
>
|
|
upon calling, no type-checking is performed. In <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>both</B
|
|
></SPAN
|
|
> cases,
|
|
the <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>actual</B
|
|
></SPAN
|
|
> type of the
|
|
requested record field is returned in the <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
> pointed to upon
|
|
return from the function. Since you have no guarantees of the type of the value
|
|
upon return if you pass <CODE
|
|
CLASS="CONSTANT"
|
|
>NULL</CODE
|
|
> as the <SPAN
|
|
CLASS="TYPE"
|
|
>int</SPAN
|
|
> pointer,
|
|
this is a bad idea and either <SPAN
|
|
CLASS="TYPE"
|
|
>BRO_TYPE_UNKNOWN</SPAN
|
|
> or another type value
|
|
should always be used.
|
|
</P
|
|
><P
|
|
> For example, you could extract the value of the record field "label", which
|
|
we assume should be a string, in the following ways:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>BroRecord *rec = /* obtained somehow */
|
|
BroString *string;
|
|
int type;
|
|
|
|
/* --- Example 1 --- */
|
|
|
|
type = BRO_TYPE_STRING; /* Use type-checking, will not accept other type */
|
|
|
|
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 existant 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 */
|
|
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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 <CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_RECORD</CODE
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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 */
|
|
}
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN599"
|
|
>3.3.8. Handling tables</A
|
|
></H2
|
|
><P
|
|
> 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
|
|
<SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>composite</B
|
|
></SPAN
|
|
>, i.e., it may consist of an ordered
|
|
sequence ofdifferent types, or it can be <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>direct</B
|
|
></SPAN
|
|
>,
|
|
i.e., consisting of a single type (such as an integer, a string, or
|
|
a record).
|
|
</P
|
|
><P
|
|
> The API for table manipulation consists of
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_new()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_free()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-INSERT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_insert()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-FIND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_find()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-GET-SIZE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_get_size()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-GET-TYPES"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_get_types()</CODE
|
|
></A
|
|
>,
|
|
and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-FOREACH"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_foreach()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><P
|
|
> 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-GET-TYPES"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_get_types()</CODE
|
|
></A
|
|
>.
|
|
Should the types not have been determined yet, <CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_UNKNOWN</CODE
|
|
>
|
|
will result. Also, as with records,
|
|
values inserted into the table are copied internally, and the ones passed
|
|
to the insertion functions remain unaffected.
|
|
</P
|
|
><P
|
|
> In contrast to records, table entries can be iterated. By passing a function
|
|
of signature
|
|
<A
|
|
HREF="broccoli-broccoli.html#BROTABLECALLBACK"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>BroTableCallback()</CODE
|
|
></A
|
|
>
|
|
and a pointer to data of your choosing,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-TABLE-FOREACH"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_table_foreach()</CODE
|
|
></A
|
|
>
|
|
will invoke the given function for each key/value pair stored in the table.
|
|
Return <CODE
|
|
CLASS="CONSTANT"
|
|
>TRUE</CODE
|
|
> to keep the iteration going, or <CODE
|
|
CLASS="CONSTANT"
|
|
>FALSE</CODE
|
|
>
|
|
to stop it.
|
|
</P
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
> 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 <CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_LIST</CODE
|
|
>
|
|
as the type of the record, as opposed to <CODE
|
|
CLASS="CONSTANT"
|
|
>BRO_TYPE_RECORD</CODE
|
|
>.
|
|
Broccoli will then know to interpret the record
|
|
as an ordered sequence of items making up a composite element, not a regular
|
|
record.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> <TT
|
|
CLASS="FILENAME"
|
|
>brotable.c</TT
|
|
> in the test subdirectory of the Broccoli tree
|
|
contains an extensive example of using tables with composite as well as direct
|
|
indexing types.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN636"
|
|
>3.3.9. Handling sets</A
|
|
></H2
|
|
><P
|
|
> Sets are essentially tables with void value types.
|
|
The API for set manipulation consists of
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_new()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_free()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-INSERT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_insert()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-FIND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_find()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-GET-SIZE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_get_size()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-GET-TYPE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_get_type()</CODE
|
|
></A
|
|
>,
|
|
and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-SET-FOREACH"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_set_foreach()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN653"
|
|
>3.3.10. Associating data with connections</A
|
|
></H2
|
|
><P
|
|
> You will often find that you would like to connect data with
|
|
a <TT
|
|
CLASS="FILENAME"
|
|
>BroConn</TT
|
|
>. 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-DATA-SET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_data_set()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-DATA-GET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_data_get()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-DATA-DEL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_data_del()</CODE
|
|
></A
|
|
>.
|
|
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
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>bro_disconnect()</CODE
|
|
>.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN665"
|
|
>3.3.11. Configuration files</A
|
|
></H2
|
|
><P
|
|
>
|
|
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).
|
|
</P
|
|
><P
|
|
> A configuration is read from a single configuration file.
|
|
This file can be read from two different locations:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>The system-wide configuration file. You can obtain the location
|
|
of this config file by running <TT
|
|
CLASS="FILENAME"
|
|
>broccoli-config --config</TT
|
|
>.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Alternatively, a per-user configuration file stored in <TT
|
|
CLASS="FILENAME"
|
|
>~/.broccoli.conf</TT
|
|
>
|
|
can be used.
|
|
</P
|
|
></LI
|
|
></UL
|
|
>
|
|
If a user has a configuration file in <TT
|
|
CLASS="FILENAME"
|
|
>~/.broccoli.conf</TT
|
|
>,
|
|
it is used exclusively, otherwise the global one is used.
|
|
</P
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
><TT
|
|
CLASS="FILENAME"
|
|
>~/.broccoli.conf</TT
|
|
> 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 <CODE
|
|
CLASS="FUNCTION"
|
|
>-rw-------</CODE
|
|
> or <CODE
|
|
CLASS="FUNCTION"
|
|
>-r--------</CODE
|
|
>.
|
|
</B
|
|
></SPAN
|
|
></P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
> 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:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># This is the Broccoli system-wide configuration file.
|
|
#
|
|
# Entries are of the form <identifier> <value>, 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"
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># This section contains all settings for myapp.
|
|
[ myapp ]
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONF-GET-STR"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conf_get_str()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONF-GET-INT"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conf_get_int()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONF-GET-DBL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conf_get_dbl()</CODE
|
|
></A
|
|
>.
|
|
You can switch between sections using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONF-SET-DOMAIN"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conf_set_domain()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN696"
|
|
>3.3.12. Using dynamic buffers</A
|
|
></H2
|
|
><P
|
|
> Broccoli provides an API for dynamically allocatable, growable, shrinkable,
|
|
and consumable buffers with <CODE
|
|
CLASS="FUNCTION"
|
|
>BroBuf</CODE
|
|
>s. You may or may
|
|
not find this useful — Broccoli mainly provides this feature in
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>broccoli.h</TT
|
|
> because these buffers are used internally
|
|
anyway and because they are 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.
|
|
</P
|
|
><P
|
|
> The buffers work as follows. The structure implementing a buffer is
|
|
called BroBuf. BroBufs are initialized to a default size when created via
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_new()</CODE
|
|
></A
|
|
>,
|
|
and released using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_free()</CODE
|
|
></A
|
|
>.
|
|
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 end of the buffer's used contents using
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-APPEND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_append()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> <---------------- allocated buffer space ------------>
|
|
<======== used buffer space ========>
|
|
^ ^ ^ ^
|
|
| | | |
|
|
`buf `buf_ptr `buf_off `buf_len
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> Have a look at the following functions for the details:
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-NEW"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_new()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-FREE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_free()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-APPEND"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_append()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-CONSUME"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_consume()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-RESET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_reset()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-GET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_get()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-GET-END"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_get_end()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-GET-SIZE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_get_size()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-GET-USED-SIZE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_get_used_size()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-PTR-GET"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_ptr_get()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-PTR-TELL"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_ptr_tell()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-PTR-SEEK"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_ptr_seek()</CODE
|
|
></A
|
|
>,
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-PTR-CHECK"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_ptr_check()</CODE
|
|
></A
|
|
>, and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-BUF-PTR-READ"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_buf_ptr_read()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN738"
|
|
>3.4. Configuring encrypted communication</A
|
|
></H1
|
|
><P
|
|
> 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.
|
|
</P
|
|
><P
|
|
> The OpenSSL command line tool <B
|
|
CLASS="COMMAND"
|
|
>openssl</B
|
|
> can be used to create all
|
|
files neccessary, but its unstructured arguments and poor documentation make it
|
|
a pain to use and waste lots of people a lot of time<A
|
|
NAME="AEN743"
|
|
HREF="#FTN.AEN743"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
>. Therefore, the Bro distribution comes with two scripts,
|
|
<B
|
|
CLASS="COMMAND"
|
|
>ca-create</B
|
|
> and <B
|
|
CLASS="COMMAND"
|
|
>ca-issue</B
|
|
>. You use the former
|
|
once to set up your CA, and the latter to create a certificate for each of the Bro
|
|
peers in your infrastructure.
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>ca-create</B
|
|
> lets you choose a directory in which the
|
|
CA maintains its files. If you set <CODE
|
|
CLASS="VARNAME"
|
|
>BRO_CA_DIR</CODE
|
|
> in your
|
|
environment, it will be used for this purpose. After entering a passphrase
|
|
for the private key of your CA, you can find the self-signed certificate
|
|
of your CA in <TT
|
|
CLASS="FILENAME"
|
|
>$BRO_CA_DIR/ca_cert.pem</TT
|
|
>.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><B
|
|
CLASS="COMMAND"
|
|
>ca-issue</B
|
|
> first requires the directory of the CA,
|
|
offering <TT
|
|
CLASS="FILENAME"
|
|
>$BRO_CA_DIR</TT
|
|
> if that is found. It asks you for
|
|
a prefix for the certificate to be generated, for the passphrase of the
|
|
private key of the CA so the new certificate can be signed, for the
|
|
passphrase for the new private key, and for a few parameters that make up
|
|
the "distinguished name" of the certificate. This name (i.e., the combination
|
|
of all the fields you enter a value for) must be unique among all your Bro
|
|
peers. Once that is done, you find a new certificate named
|
|
<TT
|
|
CLASS="FILENAME"
|
|
><prefix>.pem</TT
|
|
> in your current
|
|
directory. This file actually consists of two of the three cryptographic
|
|
documents mentioned above, namely the new certificate and the private key.
|
|
We refer to it as "certificate" for simplicity.
|
|
</P
|
|
></LI
|
|
></UL
|
|
>
|
|
In order to enable encrypted communication for your Broccoli application, you
|
|
need to put the CA certificate and the peer certificate in the
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/ca_cert</CODE
|
|
> and
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/host_cert</CODE
|
|
> keys, respectively, in the configuration file.
|
|
Optionally, you can store the private key in a separate file specified by
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/host_key</CODE
|
|
>.
|
|
To quickly enable/disable a certificate configuration, the
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/use_ssl</CODE
|
|
> key can be used.
|
|
<DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>This is where you configure whether to use encrypted or unencrypted
|
|
connections.</B
|
|
></SPAN
|
|
></P
|
|
><P
|
|
>If the <CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/use_ssl</CODE
|
|
> 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.
|
|
</P
|
|
><P
|
|
>If the <CODE
|
|
CLASS="VARNAME"
|
|
>/broccoli/use_ssl</CODE
|
|
> key is <SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>not</B
|
|
></SPAN
|
|
>
|
|
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.
|
|
</P
|
|
><P
|
|
>In no case does an SSL-enabled setup ever fall back to a cleartext one.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
>
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>/broccoli/use_ssl yes
|
|
/broccoli/ca_cert <path>/ca_cert.pem
|
|
/broccoli/host_cert <path>/bro_cert.pem
|
|
/broccoli/host_key <path>/bro_cert.key
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> In a Bro policy, you need to load the <TT
|
|
CLASS="FILENAME"
|
|
>listen-ssl.bro</TT
|
|
> policy and
|
|
redef <CODE
|
|
CLASS="VARNAME"
|
|
>ssl_ca_certificate</CODE
|
|
> and <CODE
|
|
CLASS="VARNAME"
|
|
>ssl_private_key</CODE
|
|
>,
|
|
defined in <TT
|
|
CLASS="FILENAME"
|
|
>bro.init</TT
|
|
>:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>@load listen-ssl
|
|
|
|
redef ssl_ca_certificate = "<path>/ca_cert.pem";
|
|
redef ssl_private_key = "<path>/bro.pem";
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>/broccoli/host_pass foobar
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>Make sure that access to your configuration is restricted.</B
|
|
></SPAN
|
|
></P
|
|
><P
|
|
> 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
|
|
<A
|
|
HREF="c84.html#AEN665"
|
|
>configuration files</A
|
|
> for details.
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN785"
|
|
>3.5. Configuring event reception in Bro policies</A
|
|
></H1
|
|
><P
|
|
> Before a remote Bro will accept your connection and your events, it needs to have its
|
|
policy configured accordingly:
|
|
<P
|
|
></P
|
|
><OL
|
|
TYPE="1"
|
|
><LI
|
|
><P
|
|
>Load either <TT
|
|
CLASS="FILENAME"
|
|
>listen-ssl</TT
|
|
> or <TT
|
|
CLASS="FILENAME"
|
|
>listen-clear</TT
|
|
>,
|
|
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.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
> 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 <CODE
|
|
CLASS="VARNAME"
|
|
>listen_port_ssl</CODE
|
|
> or
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>listen_port_clear</CODE
|
|
> variables from <TT
|
|
CLASS="FILENAME"
|
|
>listen-clear.bro</TT
|
|
>
|
|
or <TT
|
|
CLASS="FILENAME"
|
|
>listen-ssl.bro</TT
|
|
>, respectively. Have a look at these policies as well
|
|
as <TT
|
|
CLASS="FILENAME"
|
|
>remote.bro</TT
|
|
> for the default values. Here is the policy
|
|
for the unencrypted case:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>@load listen-clear
|
|
|
|
redef listen_port_clear = 12345/tcp;
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> Including the settings for the cryptographic files introduced in the previous section,
|
|
here is the encrypted one:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>@load listen-ssl
|
|
|
|
redef listen_port_ssl = 12345/tcp;
|
|
redef ssl_ca_certificate = "<path>/ca_cert.pem";
|
|
redef ssl_private_key = "<path>/bro.pem";
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></LI
|
|
><LI
|
|
><P
|
|
> The policy controlling which peers a Bro agent will communicate with and how this
|
|
communication will happen are defined in the <CODE
|
|
CLASS="VARNAME"
|
|
>destinations</CODE
|
|
> table
|
|
defined in <TT
|
|
CLASS="FILENAME"
|
|
>remote.bro</TT
|
|
>. This table contains entries of type
|
|
<SPAN
|
|
CLASS="TYPE"
|
|
>Destination</SPAN
|
|
>, 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 (defaults are
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>default_port_ssl</CODE
|
|
> and <CODE
|
|
CLASS="VARNAME"
|
|
>default_port_clear</CODE
|
|
>, also
|
|
defined in <TT
|
|
CLASS="FILENAME"
|
|
>remote.bro</TT
|
|
>), a retry timeout, whether to use SSL,
|
|
and the class of a connection as set on the Broccoli side via
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-CONN-SET-CLASS"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_conn_set_class()</CODE
|
|
></A
|
|
>.
|
|
</P
|
|
><P
|
|
> An example could look as follows:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> redef Remote::destinations += {
|
|
["broping"] = [$host = 127.0.0.1, $class="broping", $events = /ping/, $connect=F, $ssl=F]
|
|
};
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> This example is taken from <TT
|
|
CLASS="FILENAME"
|
|
>broping.bro</TT
|
|
>, the policy the
|
|
remote Bro must run when you want to use the <B
|
|
CLASS="COMMAND"
|
|
>broping</B
|
|
> tool
|
|
explained in the <A
|
|
HREF="c84.html#AEN843"
|
|
>section on testing</A
|
|
> 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.
|
|
</P
|
|
></LI
|
|
></OL
|
|
>
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN819"
|
|
>3.6. Configuring debugging output</A
|
|
></H1
|
|
><P
|
|
> If your Broccoli installation was configured with <B
|
|
CLASS="COMMAND"
|
|
>--enable-debug</B
|
|
>,
|
|
Broccoli will report two kinds of debugging information: (<SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>i</B
|
|
></SPAN
|
|
>)
|
|
function call traces and
|
|
(<SPAN
|
|
CLASS="emphasis"
|
|
><B
|
|
CLASS="EMPHASIS"
|
|
>ii</B
|
|
></SPAN
|
|
>) individual debugging messages. Both are enabled by default, but can be adjusted
|
|
in two ways.
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>In the configuration file: in the appropriate section of the configuration
|
|
file, you can set the keys <CODE
|
|
CLASS="FUNCTION"
|
|
>/broccoli/debug_messages</CODE
|
|
> and
|
|
<CODE
|
|
CLASS="FUNCTION"
|
|
>/broccoli/debug_calltrace</CODE
|
|
> to <CODE
|
|
CLASS="FUNCTION"
|
|
>on</CODE
|
|
>/<CODE
|
|
CLASS="FUNCTION"
|
|
>off</CODE
|
|
>
|
|
to enable/disable the corresponding output.
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>In code: you can set the variables
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-DEBUG-CALLTRACE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_debug_calltrace</CODE
|
|
></A
|
|
> and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-DEBUG-MESSAGES"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_debug_messages</CODE
|
|
></A
|
|
>
|
|
to 1/0 at any time to enable/disable the corresponding output.
|
|
</P
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
><P
|
|
> By default, debugging output is inactive (even with debuggin support compiled in).
|
|
You need to enable it explicitly either in your code by assigning 1 to
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-DEBUG-CALLTRACE"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_debug_calltrace</CODE
|
|
></A
|
|
> and
|
|
<A
|
|
HREF="broccoli-broccoli.html#BRO-DEBUG-MESSAGES"
|
|
><CODE
|
|
CLASS="FUNCTION"
|
|
>bro_debug_messages</CODE
|
|
></A
|
|
>,
|
|
or by enabling it in the configuration file.
|
|
</P
|
|
></DIV
|
|
><BR
|
|
CLEAR="all"><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="AEN843"
|
|
>3.7. Test programs</A
|
|
></H1
|
|
><P
|
|
> The Broccoli distribution comes with a few small test programs,
|
|
located in the <TT
|
|
CLASS="FILENAME"
|
|
>test/</TT
|
|
> directory of the tree.
|
|
The most notable one is <CODE
|
|
CLASS="FUNCTION"
|
|
>broping</CODE
|
|
>
|
|
<A
|
|
NAME="AEN848"
|
|
HREF="#FTN.AEN848"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
>, 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 <TT
|
|
CLASS="FILENAME"
|
|
>broping.bro</TT
|
|
> or
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>broping-record.bro</TT
|
|
> policies. You can find these
|
|
in the <TT
|
|
CLASS="FILENAME"
|
|
>test/</TT
|
|
> directory of the source tree, and
|
|
in <TT
|
|
CLASS="FILENAME"
|
|
><prefix>/share/broccoli</TT
|
|
> in the installed
|
|
version. <TT
|
|
CLASS="FILENAME"
|
|
>broping.bro</TT
|
|
> 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
|
|
<CODE
|
|
CLASS="VARNAME"
|
|
>destinations</CODE
|
|
> variable accordingly.
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>@load listen-clear;
|
|
|
|
global ping_log = open_log_file("ping");
|
|
|
|
redef Remote::destinations += {
|
|
["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);
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> <CODE
|
|
CLASS="FUNCTION"
|
|
>broping</CODE
|
|
> sends ping events to Bro. Bro accepts those because they are configured
|
|
accordingly in the destinations table. As shown in the policy, ping events
|
|
trigger pong events, and <CODE
|
|
CLASS="FUNCTION"
|
|
>broccoli</CODE
|
|
> requests delivery of all pong events back to it.
|
|
When running <CODE
|
|
CLASS="FUNCTION"
|
|
>broping</CODE
|
|
>, you'll see something like this:
|
|
</P
|
|
><TABLE
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
BGCOLOR="#eaeaf0"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>cpk25@localhost:/home/cpk25/devel/broccoli > ./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
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><H3
|
|
CLASS="FOOTNOTES"
|
|
>Notes</H3
|
|
><TABLE
|
|
BORDER="0"
|
|
CLASS="FOOTNOTES"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN743"
|
|
HREF="c84.html#AEN743"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>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".
|
|
</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN848"
|
|
HREF="c84.html#AEN848"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>Pronunciation is said to be somewhere on the continuum between
|
|
"brooping" and "burping".</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="c54.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="api.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Installing Broccoli</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Broccoli API Reference</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |