diff --git a/doc/conf.py.in b/doc/conf.py.in
index 8959c0b2c9..2e93e82502 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext'))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['bro', 'rst_directive']
+extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@@ -40,7 +40,7 @@ master_doc = 'index'
# General information about the project.
project = u'Bro'
-copyright = u'2011, The Bro Project'
+copyright = u'2012, The Bro Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -169,6 +169,7 @@ html_sidebars = {
# Output file base name for HTML help builder.
htmlhelp_basename = 'Broxygen'
+html_add_permalinks = None
# -- Options for LaTeX output --------------------------------------------------
@@ -208,7 +209,6 @@ latex_documents = [
# If false, no module index is generated.
#latex_domain_indices = True
-
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
@@ -217,3 +217,6 @@ man_pages = [
('index', 'bro', u'Bro Documentation',
[u'The Bro Project'], 1)
]
+
+# -- Options for todo plugin --------------------------------------------
+todo_include_todos=True
diff --git a/doc/ext/adapt-toc.py b/doc/ext/adapt-toc.py
new file mode 100644
index 0000000000..12ee006977
--- /dev/null
+++ b/doc/ext/adapt-toc.py
@@ -0,0 +1,29 @@
+
+import sys
+import re
+
+# Removes the first TOC level, which is just the page title.
+def process_html_toc(app, pagename, templatename, context, doctree):
+
+ if not "toc" in context:
+ return
+
+ toc = context["toc"]
+
+ lines = toc.strip().split("\n")
+ lines = lines[2:-2]
+
+ toc = "\n".join(lines)
+ toc = "
" + toc
+
+ context["toc"] = toc
+
+ # print >>sys.stderr, pagename
+ # print >>sys.stderr, context["toc"]
+ # print >>sys.stderr, "-----"
+ # print >>sys.stderr, toc
+ # print >>sys.stderr, "===="
+
+def setup(app):
+ app.connect('html-page-context', process_html_toc)
+
diff --git a/doc/faq.rst b/doc/faq.rst
index cc45d5faa2..b72b933136 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -72,34 +72,30 @@ Usage
How can I identify backscatter?
-------------------------------
-Identifying backscatter via connections labeled as ``OTH`` is not
-a reliable means to detect backscatter. Use rather the following
-procedure:
-
-* Enable connection history via ``redef record_state_history=T`` to
- track all control/data packet types in connection logs.
-
-* Backscatter is now visible in terms of connections that never had an
- initial ``SYN`` but started instead with a ``SYN-ACK`` or ``RST``
- (though this latter generally is just discarded).
+Identifying backscatter via connections labeled as ``OTH`` is not a reliable
+means to detect backscatter. Backscatter is however visible by interpreting
+the contents of the ``history`` field in the ``conn.log`` file. The basic idea
+is to watch for connections that never had an initial ``SYN`` but started
+instead with a ``SYN-ACK`` or ``RST`` (though this latter generally is just
+discarded). Here are some history fields which provide backscatter examples:
+``hAFf``, ``r``. Refer to the conn protocol analysis scripts to interpret the
+individual character meanings in the history field.
Is there help for understanding Bro's resource consumption?
-----------------------------------------------------------
There are two scripts that collect statistics on resource usage:
-``stats.bro`` and ``profiling.bro``. The former is quite lightweight,
-while the latter should only be used for debugging. Furthermore,
-there's also ``print-globals.bro``, which prints the size of all
-global script variable at termination.
+``misc/stats.bro`` and ``misc/profiling.bro``. The former is quite
+lightweight, while the latter should only be used for debugging.
How can I capture packets as an unprivileged user?
--------------------------------------------------
-Normally, unprivileged users cannot capture packets from a network
-interface, which means they would not be able to use Bro to read/analyze
-live traffic. However, there are ways to enable packet capture
-permission for non-root users, which is worth doing in the context of
-using Bro to monitor live traffic
+Normally, unprivileged users cannot capture packets from a network interface,
+which means they would not be able to use Bro to read/analyze live traffic.
+However, there are operating system specific ways to enable packet capture
+permission for non-root users, which is worth doing in the context of using
+Bro to monitor live traffic.
With Linux Capabilities
^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/logging.rst b/doc/logging.rst
index 2817cadd45..2b5a7167b3 100644
--- a/doc/logging.rst
+++ b/doc/logging.rst
@@ -43,13 +43,14 @@ Basics
======
The data fields that a stream records are defined by a record type
-specified when it is created. Let's look at the script generating
-Bro's connection summaries as an example,
-``base/protocols/conn/main.bro``. It defines a record ``Conn::Info``
-that lists all the fields that go into ``conn.log``, each marked with
-a ``&log`` attribute indicating that it is part of the information
-written out. To write a log record, the script then passes an instance
-of ``Conn::Info`` to the logging framework's ``Log::write`` function.
+specified when it is created. Let's look at the script generating Bro's
+connection summaries as an example,
+:doc:`scripts/base/protocols/conn/main`. It defines a record
+:bro:type:`Conn::Info` that lists all the fields that go into
+``conn.log``, each marked with a ``&log`` attribute indicating that it
+is part of the information written out. To write a log record, the
+script then passes an instance of :bro:type:`Conn::Info` to the logging
+framework's :bro:id:`Log::write` function.
By default, each stream automatically gets a filter named ``default``
that generates the normal output by recording all record fields into a
@@ -66,7 +67,7 @@ To create new a new output file for an existing stream, you can add a
new filter. A filter can, e.g., restrict the set of fields being
logged:
-.. code:: bro:
+.. code:: bro
event bro_init()
{
@@ -85,14 +86,15 @@ Note the fields that are set for the filter:
``path``
The filename for the output file, without any extension (which
may be automatically added by the writer). Default path values
- are generated by taking the stream's ID and munging it
- slightly. ``Conn::LOG`` is converted into ``conn``,
- ``PacketFilter::LOG`` is converted into ``packet_filter``, and
- ``Notice::POLICY_LOG`` is converted into ``notice_policy``.
+ are generated by taking the stream's ID and munging it slightly.
+ :bro:enum:`Conn::LOG` is converted into ``conn``,
+ :bro:enum:`PacketFilter::LOG` is converted into
+ ``packet_filter``, and :bro:enum:`Notice::POLICY_LOG` is
+ converted into ``notice_policy``.
``include``
A set limiting the fields to the ones given. The names
- correspond to those in the ``Conn::LOG`` record, with
+ correspond to those in the :bro:type:`Conn::Info` record, with
sub-records unrolled by concatenating fields (separated with
dots).
@@ -158,10 +160,10 @@ further for example to log information by subnets or even by IP
address. Be careful, however, as it is easy to create many files very
quickly ...
-.. sidebar:
+.. sidebar:: A More Generic Path Function
- The show ``split_log`` method has one draw-back: it can be used
- only with the ``Conn::Log`` stream as the record type is hardcoded
+ The ``split_log`` method has one draw-back: it can be used
+ only with the :bro:enum:`Conn::LOG` stream as the record type is hardcoded
into its argument list. However, Bro allows to do a more generic
variant:
@@ -201,8 +203,8 @@ Extending
You can add further fields to a log stream by extending the record
type that defines its content. Let's say we want to add a boolean
-field ``is_private`` to ``Conn::Info`` that indicates whether the
-originator IP address is part of the RFC1918 space:
+field ``is_private`` to :bro:type:`Conn::Info` that indicates whether the
+originator IP address is part of the :rfc:`1918` space:
.. code:: bro
@@ -234,10 +236,10 @@ Notes:
- For extending logs this way, one needs a bit of knowledge about how
the script that creates the log stream is organizing its state
keeping. Most of the standard Bro scripts attach their log state to
- the ``connection`` record where it can then be accessed, just as the
- ``c$conn`` above. For example, the HTTP analysis adds a field ``http
- : HTTP::Info`` to the ``connection`` record. See the script
- reference for more information.
+ the :bro:type:`connection` record where it can then be accessed, just
+ as the ``c$conn`` above. For example, the HTTP analysis adds a field
+ ``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection`
+ record. See the script reference for more information.
- When extending records as shown above, the new fields must always be
declared either with a ``&default`` value or as ``&optional``.
@@ -251,8 +253,8 @@ Sometimes it is helpful to do additional analysis of the information
being logged. For these cases, a stream can specify an event that will
be generated every time a log record is written to it. All of Bro's
default log streams define such an event. For example, the connection
-log stream raises the event ``Conn::log_conn(rec: Conn::Info)``: You
-could use that for example for flagging when an a connection to
+log stream raises the event :bro:id:`Conn::log_conn`. You
+could use that for example for flagging when a connection to
specific destination exceeds a certain duration:
.. code:: bro
@@ -279,11 +281,32 @@ real-time.
Rotation
--------
+By default, no log rotation occurs, but it's globally controllable for all
+filters by redefining the :bro:id:`Log::default_rotation_interval` option:
+
+.. code:: bro
+
+ redef Log::default_rotation_interval = 1 hr;
+
+Or specifically for certain :bro:type:`Log::Filter` instances by setting
+their ``interv`` field. Here's an example of changing just the
+:bro:enum:`Conn::LOG` stream's default filter rotation.
+
+.. code:: bro
+
+ event bro_init()
+ {
+ local f = Log::get_filter(Conn::LOG, "default");
+ f$interv = 1 min;
+ Log::remove_filter(Conn::LOG, "default");
+ Log::add_filter(Conn::LOG, f);
+ }
+
ASCII Writer Configuration
--------------------------
The ASCII writer has a number of options for customizing the format of
-its output, see XXX.bro.
+its output, see :doc:`scripts/base/frameworks/logging/writers/ascii`.
Adding Streams
==============
@@ -321,8 +344,8 @@ example for the ``Foo`` module:
Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]);
}
-You can also the state to the ``connection`` record to make it easily
-accessible across event handlers:
+You can also add the state to the :bro:type:`connection` record to make
+it easily accessible across event handlers:
.. code:: bro
@@ -330,7 +353,7 @@ accessible across event handlers:
foo: Info &optional;
}
-Now you can use the ``Log::write`` method to output log records and
+Now you can use the :bro:id:`Log::write` method to output log records and
save the logged ``Foo::Info`` record into the connection record:
.. code:: bro
@@ -343,9 +366,9 @@ save the logged ``Foo::Info`` record into the connection record:
}
See the existing scripts for how to work with such a new connection
-field. A simple example is ``base/protocols/syslog/main.bro``.
+field. A simple example is :doc:`scripts/base/protocols/syslog/main`.
-When you are developing scripts that add data to the ``connection``
+When you are developing scripts that add data to the :bro:type:`connection`
record, care must be given to when and how long data is stored.
Normally data saved to the connection record will remain there for the
duration of the connection and from a practical perspective it's not
diff --git a/doc/quickstart.rst b/doc/quickstart.rst
index 0534186cde..da780e70df 100644
--- a/doc/quickstart.rst
+++ b/doc/quickstart.rst
@@ -31,15 +31,15 @@ See the `bro downloads page`_ for currently supported/targeted platforms.
* RPM
-.. console::
+ .. console::
- sudo yum localinstall Bro-all*.rpm
+ sudo yum localinstall Bro-all*.rpm
* DEB
-.. console::
+ .. console::
- sudo gdebi Bro-all-*.deb
+ sudo gdebi Bro-all-*.deb
* MacOS Disk Image with Installer
@@ -56,26 +56,32 @@ Building From Source
Required Dependencies
~~~~~~~~~~~~~~~~~~~~~
+The following dependencies are required to build Bro:
+
* RPM/RedHat-based Linux:
-.. console::
+ .. console::
- sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
+ sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
* DEB/Debian-based Linux:
-.. console::
+ .. console::
- sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
+ sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
* FreeBSD
Most required dependencies should come with a minimal FreeBSD install
except for the following.
-.. console::
+ .. console::
- sudo pkg_add -r cmake swig bison python
+ sudo pkg_add -r bash cmake swig bison python
+
+ Note that ``bash`` needs to be in ``PATH``, which by default it is
+ not. The FreeBSD package installs the binary into
+ ``/usr/local/bin``.
* Mac OS X
@@ -99,21 +105,21 @@ sending emails.
* RPM/RedHat-based Linux:
-.. console::
+ .. console::
- sudo yum install GeoIP-devel sendmail
+ sudo yum install GeoIP-devel sendmail
* DEB/Debian-based Linux:
-.. console::
+ .. console::
- sudo apt-get install libgeoip-dev sendmail
+ sudo apt-get install libgeoip-dev sendmail
* Ports-based FreeBSD
-.. console::
+ .. console::
- sudo pkg_add -r GeoIP
+ sudo pkg_add -r GeoIP
sendmail is typically already available.
diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst
index e6a9e9b829..ef6738a1a6 100644
--- a/doc/scripts/builtins.rst
+++ b/doc/scripts/builtins.rst
@@ -6,113 +6,630 @@ Types
The Bro scripting language supports the following built-in types.
-.. TODO: add documentation
-
.. bro:type:: void
+ An internal Bro type representing an absence of a type. Should
+ most often be seen as a possible function return type.
+
.. bro:type:: bool
+ Reflects a value with one of two meanings: true or false. The two
+ ``bool`` constants are ``T`` and ``F``.
+
.. bro:type:: int
+ A numeric type representing a signed integer. An ``int`` constant
+ is a string of digits preceded by a ``+`` or ``-`` sign, e.g.
+ ``-42`` or ``+5``. When using type inferencing use care so that the
+ intended type is inferred, e.g. ``local size_difference = 0`` will
+ infer the :bro:type:`count` while ``local size_difference = +0``
+ will infer :bro:type:`int`.
+
.. bro:type:: count
+ A numeric type representing an unsigned integer. A ``count``
+ constant is a string of digits, e.g. ``1234`` or ``0``.
+
.. bro:type:: counter
+ An alias to :bro:type:`count`
+
+.. TODO: is there anything special about this type?
+
.. bro:type:: double
+ A numeric type representing a double-precision floating-point
+ number. Floating-point constants are written as a string of digits
+ with an optional decimal point, optional scale-factor in scientific
+ notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``,
+ ``-1234e0``, ``3.14159``, and ``.003e-23``.
+
.. bro:type:: time
+ A temporal type representing an absolute time. There is currently
+ no way to specify a ``time`` constant, but one can use the
+ :bro:id:`current_time` or :bro:id:`network_time` built-in functions
+ to assign a value to a ``time``-typed variable.
+
.. bro:type:: interval
+ A temporal type representing a relative time. An ``interval``
+ constant can be written as a numeric constant followed by a time
+ unit where the time unit is one of ``usec``, ``sec``, ``min``,
+ ``hr``, or ``day`` which respectively represent microseconds,
+ seconds, minutes, hours, and days. Whitespace between the numeric
+ constant and time unit is optional. Appending the letter "s" to the
+ time unit in order to pluralize it is also optional (to no semantic
+ effect). Examples of ``interval`` constants are ``3.5 min`` and
+ ``3.5mins``. An ``interval`` can also be negated, for example ``-
+ 12 hr`` represents "twelve hours in the past". Intervals also
+ support addition, subtraction, multiplication, division, and
+ comparison operations.
+
.. bro:type:: string
+ A type used to hold character-string values which represent text.
+ String constants are created by enclosing text in double quotes (")
+ and the backslash character (\) introduces escape sequences.
+
+ Note that Bro represents strings internally as a count and vector of
+ bytes rather than a NUL-terminated byte string (although string
+ constants are also automatically NUL-terminated). This is because
+ network traffic can easily introduce NULs into strings either by
+ nature of an application, inadvertently, or maliciously. And while
+ NULs are allowed in Bro strings, when present in strings passed as
+ arguments to many functions, a run-time error can occur as their
+ presence likely indicates a sort of problem. In that case, the
+ string will also only be represented to the user as the literal
+ "" string.
+
.. bro:type:: pattern
+ A type representing regular-expression patterns which can be used
+ for fast text-searching operations. Pattern constants are created
+ by enclosing text within forward slashes (/) and is the same syntax
+ as the patterns supported by the `flex lexical analyzer
+ `_. The speed of
+ regular expression matching does not depend on the complexity or
+ size of the patterns. Patterns support two types of matching, exact
+ and embedded.
+
+ In exact matching the ``==`` equality relational operator is used
+ with one :bro:type:`string` operand and one :bro:type:`pattern`
+ operand to check whether the full string exactly matches the
+ pattern. In this case, the ``^`` beginning-of-line and ``$``
+ end-of-line anchors are redundant since pattern is implicitly
+ anchored to the beginning and end of the line to facilitate an exact
+ match. For example::
+
+ "foo" == /foo|bar/
+
+ yields true, while::
+
+ /foo|bar/ == "foobar"
+
+ yields false. The ``!=`` operator would yield the negation of ``==``.
+
+ In embedded matching the ``in`` operator is again used with one
+ :bro:type:`string` operand and one :bro:type:`pattern` operand
+ (which must be on the left-hand side), but tests whether the pattern
+ appears anywhere within the given string. For example::
+
+ /foo|bar/ in "foobar"
+
+ yields true, while::
+
+ /^oob/ in "foobar"
+
+ is false since "oob" does not appear at the start of "foobar". The
+ ``!in`` operator would yield the negation of ``in``.
+
.. bro:type:: enum
+ A type allowing the specification of a set of related values that
+ have no further structure. The only operations allowed on
+ enumerations are equality comparisons and they do not have
+ associated values or ordering. An example declaration:
+
+ .. code:: bro
+
+ type color: enum { Red, White, Blue, };
+
+ The last comma is after ``Blue`` is optional.
+
.. bro:type:: timer
+.. TODO: is this a type that's exposed to users?
+
.. bro:type:: port
+ A type representing transport-level port numbers. Besides TCP and
+ UDP ports, there is a concept of an ICMP "port" where the source
+ port is the ICMP message type and the destination port the ICMP
+ message code. A ``port`` constant is written as an unsigned integer
+ followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
+
+ Ports can be compared for equality and also for ordering. When
+ comparing order across transport-level protocols, ``/unknown`` <
+ ``/tcp`` < ``/udp`` < ``icmp``, for example ``65535/tcp`` is smaller
+ than ``0/udp``.
+
.. bro:type:: addr
-.. bro:type:: net
+ A type representing an IP address. Currently, Bro defaults to only
+ supporting IPv4 addresses unless configured/built with
+ ``--enable-brov6``, in which case, IPv6 addresses are supported.
+
+ IPv4 address constants are written in "dotted quad" format,
+ ``A1.A2.A3.A4``, where Ai all lie between 0 and 255.
+
+ IPv6 address constants are written as colon-separated hexadecimal form
+ as described by :rfc:`2373`.
+
+ Hostname constants can also be used, but since a hostname can
+ correspond to multiple IP addresses, the type of such variable is a
+ :bro:type:`set` of :bro:type:`addr` elements. For example:
+
+ .. code:: bro
+
+ local a = www.google.com;
+
+ Addresses can be compared for (in)equality using ``==`` and ``!=``.
+ They can also be masked with ``/`` to produce a :bro:type:`subnet`:
+
+ .. code:: bro
+
+ local a: addr = 192.168.1.100;
+ local s: subnet = 192.168.0.0/16;
+ if ( a/16 == s )
+ print "true";
+
+ And checked for inclusion within a :bro:type:`subnet` using ``in`` :
+
+ .. code:: bro
+
+ local a: addr = 192.168.1.100;
+ local s: subnet = 192.168.0.0/16;
+ if ( a in s )
+ print "true";
.. bro:type:: subnet
+ A type representing a block of IP addresses in CIDR notation. A
+ ``subnet`` constant is written as an :bro:type:`addr` followed by a
+ slash (/) and then the network prefix size specified as a decimal
+ number. For example, ``192.168.0.0/16``.
+
.. bro:type:: any
+ Used to bypass strong typing. For example, a function can take an
+ argument of type ``any`` when it may be of different types.
+
.. bro:type:: table
-.. bro:type:: union
+ An associate array that maps from one set of values to another. The
+ values being mapped are termed the *index* or *indices* and the
+ result of the mapping is called the *yield*. Indexing into tables
+ is very efficient, and internally it is just a single hash table
+ lookup.
-.. bro:type:: record
+ The table declaration syntax is::
-.. bro:type:: types
+ table [ type^+ ] of type
-.. bro:type:: func
+ where *type^+* is one or more types, separated by commas. For example:
-.. bro:type:: file
+ .. code:: bro
-.. bro:type:: vector
+ global a: table[count] of string;
-.. TODO: below are kind of "special cases" that bro knows about?
+ declares a table indexed by :bro:type:`count` values and yielding
+ :bro:type:`string` values. The yield type can also be more complex:
+
+ .. code:: bro
+
+ global a: table[count] of table[addr, port] of string;
+
+ which declared a table indexed by :bro:type:`count` and yielding
+ another :bro:type:`table` which is indexed by an :bro:type:`addr`
+ and :bro:type:`port` to yield a :bro:type:`string`.
+
+ Initialization of tables occurs by enclosing a set of initializers within
+ braces, for example:
+
+ .. code:: bro
+
+ global t: table[count] of string = {
+ [11] = "eleven",
+ [5] = "five",
+ };
+
+ Accessing table elements if provided by enclosing values within square
+ brackets (``[]``), for example:
+
+ .. code:: bro
+
+ t[13] = "thirteen";
+
+ And membership can be tested with ``in``:
+
+ .. code:: bro
+
+ if ( 13 in t )
+ ...
+
+ Iterate over tables with a ``for`` loop:
+
+ .. code:: bro
+
+ local t: table[count] of string;
+ for ( n in t )
+ ...
+
+ local services: table[addr, port] of string;
+ for ( [a, p] in services )
+ ...
+
+ Remove individual table elements with ``delete``:
+
+ .. code:: bro
+
+ delete t[13];
+
+ Nothing happens if the element with value ``13`` isn't present in
+ the table.
+
+ Table size can be obtained by placing the table identifier between
+ vertical pipe (|) characters:
+
+ .. code:: bro
+
+ |t|
.. bro:type:: set
+ A set is like a :bro:type:`table`, but it is a collection of indices
+ that do not map to any yield value. They are declared with the
+ syntax::
+
+ set [ type^+ ]
+
+ where *type^+* is one or more types separated by commas.
+
+ Sets are initialized by listing elements enclosed by curly braces:
+
+ .. code:: bro
+
+ global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp };
+ global s2: set[port, string] = { [21/tcp, "ftp"], [23/tcp, "telnet"] };
+
+ The types are explicitly shown in the example above, but they could
+ have been left to type inference.
+
+ Set membership is tested with ``in``:
+
+ .. code:: bro
+
+ if ( 21/tcp in s )
+ ...
+
+ Elements are added with ``add``:
+
+ .. code:: bro
+
+ add s[22/tcp];
+
+ And removed with ``delete``:
+
+ .. code:: bro
+
+ delete s[21/tcp];
+
+ Set size can be obtained by placing the set identifier between
+ vertical pipe (|) characters:
+
+ .. code:: bro
+
+ |s|
+
+.. bro:type:: vector
+
+ A vector is like a :bro:type:`table`, except it's always indexed by a
+ :bro:type:`count`. A vector is declared like:
+
+ .. code:: bro
+
+ global v: vector of string;
+
+ And can be initialized with the vector constructor:
+
+ .. code:: bro
+
+ global v: vector of string = vector("one", "two", "three");
+
+ Adding an element to a vector involves accessing/assigning it:
+
+ .. code:: bro
+
+ v[3] = "four"
+
+ Note how the vector indexing is 0-based.
+
+ Vector size can be obtained by placing the vector identifier between
+ vertical pipe (|) characters:
+
+ .. code:: bro
+
+ |v|
+
+.. bro:type:: record
+
+ A ``record`` is a collection of values. Each value has a field name
+ and a type. Values do not need to have the same type and the types
+ have no restrictions. An example record type definition:
+
+ .. code:: bro
+
+ type MyRecordType: record {
+ c: count;
+ s: string &optional;
+ };
+
+ Access to a record field uses the dollar sign (``$``) operator:
+
+ .. code:: bro
+
+ global r: MyRecordType;
+ r$c = 13;
+
+ Record assignment can be done field by field or as a whole like:
+
+ .. code:: bro
+
+ r = [$c = 13, $s = "thirteen"];
+
+ When assigning a whole record value, all fields that are not
+ :bro:attr:`&optional` or have a :bro:attr:`&default` attribute must
+ be specified.
+
+ To test for existence of field that is :bro:attr:`&optional`, use the
+ ``?$`` operator:
+
+ .. code:: bro
+
+ if ( r?$s )
+ ...
+
+.. bro:type:: file
+
+ Bro supports writing to files, but not reading from them. For
+ example, declare, open, and write to a file and finally close it
+ like:
+
+ .. code:: bro
+
+ global f: file = open("myfile");
+ print f, "hello, world";
+ close(f);
+
+ Writing to files like this for logging usually isn't recommend, for better
+ logging support see :doc:`/logging`.
+
+.. bro:type:: func
+
+ See :bro:type:`function`.
+
.. bro:type:: function
+ Function types in Bro are declared using::
+
+ function( argument* ): type
+
+ where *argument* is a (possibly empty) comma-separated list of
+ arguments, and *type* is an optional return type. For example:
+
+ .. code:: bro
+
+ global greeting: function(name: string): string;
+
+ Here ``greeting`` is an identifier with a certain function type.
+ The function body is not defined yet and ``greeting`` could even
+ have different function body values at different times. To define
+ a function including a body value, the syntax is like:
+
+ .. code:: bro
+
+ function greeting(name: string): string
+ {
+ return "Hello, " + name;
+ }
+
+ Note that in the definition above, it's not necessary for us to have
+ done the first (forward) declaration of ``greeting`` as a function
+ type, but when it is, the argument list and return type much match
+ exactly.
+
+ Function types don't need to have a name and can be assigned anonymously:
+
+ .. code:: bro
+
+ greeting = function(name: string): string { return "Hi, " + name; };
+
+ And finally, the function can be called like:
+
+ .. code:: bro
+
+ print greeting("Dave");
+
.. bro:type:: event
+ Event handlers are nearly identical in both syntax and semantics to
+ a :bro:type:`function`, with the two differences being that event
+ handlers have no return type since they never return a value, and
+ you cannot call an event handler. Instead of directly calling an
+ event handler from a script, event handler bodies are executed when
+ they are invoked by one of three different methods:
+
+ - From the event engine
+
+ When the event engine detects an event for which you have
+ defined a corresponding event handler, it queues an event for
+ that handler. The handler is invoked as soon as the event
+ engine finishes processing the current packet and flushing the
+ invocation of other event handlers that were queued first.
+
+ - With the ``event`` statement from a script
+
+ Immediately queuing invocation of an event handler occurs like:
+
+ .. code:: bro
+
+ event password_exposed(user, password);
+
+ This assumes that ``password_exposed`` was previously declared
+ as an event handler type with compatible arguments.
+
+ - Via the ``schedule`` expression in a script
+
+ This delays the invocation of event handlers until some time in
+ the future. For example:
+
+ .. code:: bro
+
+ schedule 5 secs { password_exposed(user, password) };
+
+ Multiple event handler bodies can be defined for the same event handler
+ identifier and the body of each will be executed in turn. Ordering
+ of execution can be influenced with :bro:attr:`&priority`.
+
Attributes
----------
-The Bro scripting language supports the following built-in attributes.
-
-.. TODO: add documentation
+Attributes occur at the end of type/event declarations and change their
+behavior. The syntax is ``&key`` or ``&key=val``, e.g., ``type T:
+set[count] &read_expire=5min`` or ``event foo() &priority=-3``. The Bro
+scripting language supports the following built-in attributes.
.. bro:attr:: &optional
+ Allows record field to be missing. For example the type ``record {
+ a: int, b: port &optional }`` could be instantiated both as
+ singleton ``[$a=127.0.0.1]`` or pair ``[$a=127.0.0.1, $b=80/tcp]``.
+
.. bro:attr:: &default
+ Uses a default value for a record field or container elements. For
+ example, ``table[int] of string &default="foo" }`` would create
+ table that returns The :bro:type:`string` ``"foo"`` for any
+ non-existing index.
+
.. bro:attr:: &redef
+ Allows for redefinition of initial object values. This is typically
+ used with constants, for example, ``const clever = T &redef;`` would
+ allow the constant to be redifined at some later point during script
+ execution.
+
.. bro:attr:: &rotate_interval
+ Rotates a file after a specified interval.
+
.. bro:attr:: &rotate_size
+ Rotates af file after it has reached a given size in bytes.
+
.. bro:attr:: &add_func
+.. TODO: needs to be documented.
+
.. bro:attr:: &delete_func
+.. TODO: needs to be documented.
+
.. bro:attr:: &expire_func
+ Called right before a container element expires.
+
.. bro:attr:: &read_expire
+ Specifies a read expiration timeout for container elements. That is,
+ the element expires after the given amount of time since the last
+ time it has been read. Note that a write also counts as a read.
+
.. bro:attr:: &write_expire
+ Specifies a write expiration timeout for container elements. That
+ is, the element expires after the given amount of time since the
+ last time it has been written.
+
.. bro:attr:: &create_expire
+ Specifies a creation expiration timeout for container elements. That
+ is, the element expires after the given amount of time since it has
+ been inserted into the container, regardless of any reads or writes.
+
.. bro:attr:: &persistent
+ Makes a variable persistent, i.e., its value is writen to disk (per
+ default at shutdown time).
+
.. bro:attr:: &synchronized
+ Synchronizes variable accesses across nodes. The value of a
+ ``&synchronized`` variable is automatically propagated to all peers
+ when it changes.
+
.. bro:attr:: &postprocessor
+.. TODO: needs to be documented.
+
.. bro:attr:: &encrypt
+ Encrypts files right before writing them to disk.
+
+.. TODO: needs to be documented in more detail.
+
.. bro:attr:: &match
+.. TODO: needs to be documented.
+
.. bro:attr:: &disable_print_hook
+ Deprecated. Will be removed.
+
.. bro:attr:: &raw_output
+ Opens a file in raw mode, i.e., non-ASCII characters are not
+ escaped.
+
.. bro:attr:: &mergeable
+ Prefers set union to assignment for synchronized state. This
+ attribute is used in conjunction with :bro:attr:`&synchronized`
+ container types: when the same container is updated at two peers
+ with different value, the propagation of the state causes a race
+ condition, where the last update succeeds. This can cause
+ inconsistencies and can be avoided by unifying the two sets, rather
+ than merely overwriting the old value.
+
.. bro:attr:: &priority
+ Specifies the execution priority of an event handler. Higher values
+ are executed before lower ones. The default value is 0.
+
.. bro:attr:: &group
+ Groups event handlers such that those in the same group can be
+ jointly activated or deactivated.
+
.. bro:attr:: &log
+ Writes a record field to the associated log stream.
+
+.. bro:attr:: &error_handler
+
+.. TODO: needs documented
+
.. bro:attr:: (&tracked)
+
+.. TODO: needs documented or removed if it's not used anywhere.
diff --git a/doc/signatures.rst b/doc/signatures.rst
index e2f9a8d702..a1e70f8e6f 100644
--- a/doc/signatures.rst
+++ b/doc/signatures.rst
@@ -34,7 +34,7 @@ Let's look at an example signature first:
This signature asks Bro to match the regular expression ``.*root`` on
all TCP connections going to port 80. When the signature triggers, Bro
-will raise an event ``signature_match`` of the form:
+will raise an event :bro:id:`signature_match` of the form:
.. code:: bro
@@ -45,20 +45,20 @@ triggered the match, ``msg`` is the string specified by the
signature's event statement (``Found root!``), and data is the last
piece of payload which triggered the pattern match.
-To turn such ``signature_match`` events into actual alarms, you can
-load Bro's ``signature.bro`` script. This script contains a default
-event handler that raises ``SensitiveSignature`` :doc:`Notices `
+To turn such :bro:id:`signature_match` events into actual alarms, you can
+load Bro's :doc:`/scripts/base/frameworks/signatures/main` script.
+This script contains a default event handler that raises
+:bro:enum:`Signatures::Sensitive_Signature` :doc:`Notices `
(as well as others; see the beginning of the script).
As signatures are independent of Bro's policy scripts, they are put
into their own file(s). There are two ways to specify which files
contain signatures: By using the ``-s`` flag when you invoke Bro, or
-by extending the Bro variable ``signatures_files`` using the ``+=``
+by extending the Bro variable :bro:id:`signature_files` using the ``+=``
operator. If a signature file is given without a path, it is searched
along the normal ``BROPATH``. The default extension of the file name
is ``.sig``, and Bro appends that automatically when neccesary.
-
Signature language
==================
@@ -90,7 +90,7 @@ one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``; and
against. The following keywords are defined:
``src-ip``/``dst-ip ``
- Source and destination address, repectively. Addresses can be
+ Source and destination address, respectively. Addresses can be
given as IP addresses or CIDR masks.
``src-port``/``dst-port`` ````
@@ -126,7 +126,7 @@ CIDR notation for netmasks and is translated into a corresponding
bitmask applied to the packet's value prior to the comparison (similar
to the optional ``& integer``).
-Putting all together, this is an example conditiation that is
+Putting all together, this is an example condition that is
equivalent to ``dst- ip == 1.2.3.4/16, 5.6.7.8/24``:
.. code:: bro-sig
@@ -134,7 +134,7 @@ equivalent to ``dst- ip == 1.2.3.4/16, 5.6.7.8/24``:
header ip[16:4] == 1.2.3.4/16, 5.6.7.8/24
Internally, the predefined header conditions are in fact just
-short-cuts and mappend into a generic condition.
+short-cuts and mapped into a generic condition.
Content Conditions
~~~~~~~~~~~~~~~~~~
@@ -265,7 +265,7 @@ Actions define what to do if a signature matches. Currently, there are
two actions defined:
``event ``
- Raises a ``signature_match`` event. The event handler has the
+ Raises a :bro:id:`signature_match` event. The event handler has the
following type:
.. code:: bro
@@ -339,10 +339,10 @@ Things to keep in mind when writing signatures
respectively. Generally, Bro follows `flex's regular expression
syntax
`_.
- See the DPD signatures in ``policy/sigs/dpd.bro`` for some examples
+ See the DPD signatures in ``base/frameworks/dpd/dpd.sig`` for some examples
of fairly complex payload patterns.
-* The data argument of the ``signature_match`` handler might not carry
+* The data argument of the :bro:id:`signature_match` handler might not carry
the full text matched by the regular expression. Bro performs the
matching incrementally as packets come in; when the signature
eventually fires, it can only pass on the most recent chunk of data.
diff --git a/scripts/base/frameworks/cluster/__load__.bro b/scripts/base/frameworks/cluster/__load__.bro
index bccb35dbb1..0f9003514d 100644
--- a/scripts/base/frameworks/cluster/__load__.bro
+++ b/scripts/base/frameworks/cluster/__load__.bro
@@ -9,10 +9,10 @@ redef peer_description = Cluster::node;
# Add a cluster prefix.
@prefixes += cluster
-## If this script isn't found anywhere, the cluster bombs out.
-## Loading the cluster framework requires that a script by this name exists
-## somewhere in the BROPATH. The only thing in the file should be the
-## cluster definition in the :bro:id:`Cluster::nodes` variable.
+# If this script isn't found anywhere, the cluster bombs out.
+# Loading the cluster framework requires that a script by this name exists
+# somewhere in the BROPATH. The only thing in the file should be the
+# cluster definition in the :bro:id:`Cluster::nodes` variable.
@load cluster-layout
@if ( Cluster::node in Cluster::nodes )
diff --git a/scripts/base/frameworks/cluster/main.bro b/scripts/base/frameworks/cluster/main.bro
index 2e7fc32d8b..1e89e9b2a7 100644
--- a/scripts/base/frameworks/cluster/main.bro
+++ b/scripts/base/frameworks/cluster/main.bro
@@ -1,21 +1,45 @@
+##! A framework for establishing and controlling a cluster of Bro instances.
+##! In order to use the cluster framework, a script named
+##! ``cluster-layout.bro`` must exist somewhere in Bro's script search path
+##! which has a cluster definition of the :bro:id:`Cluster::nodes` variable.
+##! The ``CLUSTER_NODE`` environment variable or :bro:id:`Cluster::node`
+##! must also be sent and the cluster framework loaded as a package like
+##! ``@load base/frameworks/cluster``.
+
@load base/frameworks/control
module Cluster;
export {
+ ## The cluster logging stream identifier.
redef enum Log::ID += { LOG };
-
+
+ ## The record type which contains the column fields of the cluster log.
type Info: record {
+ ## The time at which a cluster message was generated.
ts: time;
+ ## A message indicating information about the cluster's operation.
message: string;
} &log;
-
+
+ ## Types of nodes that are allowed to participate in the cluster
+ ## configuration.
type NodeType: enum {
+ ## A dummy node type indicating the local node is not operating
+ ## within a cluster.
NONE,
+ ## A node type which is allowed to view/manipulate the configuration
+ ## of other nodes in the cluster.
CONTROL,
+ ## A node type responsible for log and policy management.
MANAGER,
+ ## A node type for relaying worker node communication and synchronizing
+ ## worker node state.
PROXY,
+ ## The node type doing all the actual traffic analysis.
WORKER,
+ ## A node acting as a traffic recorder using the
+ ## `Time Machine `_ software.
TIME_MACHINE,
};
@@ -49,30 +73,38 @@ export {
## Record type to indicate a node in a cluster.
type Node: record {
+ ## Identifies the type of cluster node in this node's configuration.
node_type: NodeType;
+ ## The IP address of the cluster node.
ip: addr;
+ ## The port to which the this local node can connect when
+ ## establishing communication.
p: port;
-
## Identifier for the interface a worker is sniffing.
interface: string &optional;
-
- ## Manager node this node uses. For workers and proxies.
+ ## Name of the manager node this node uses. For workers and proxies.
manager: string &optional;
- ## Proxy node this node uses. For workers and managers.
+ ## Name of the proxy node this node uses. For workers and managers.
proxy: string &optional;
- ## Worker nodes that this node connects with. For managers and proxies.
+ ## Names of worker nodes that this node connects with.
+ ## For managers and proxies.
workers: set[string] &optional;
+ ## Name of a time machine node with which this node connects.
time_machine: string &optional;
};
## This function can be called at any time to determine if the cluster
## framework is being enabled for this run.
+ ##
+ ## Returns: True if :bro:id:`Cluster::node` has been set.
global is_enabled: function(): bool;
## This function can be called at any time to determine what type of
## cluster node the current Bro instance is going to be acting as.
## If :bro:id:`Cluster::is_enabled` returns false, then
## :bro:enum:`Cluster::NONE` is returned.
+ ##
+ ## Returns: The :bro:type:`Cluster::NodeType` the calling node acts as.
global local_node_type: function(): NodeType;
## This gives the value for the number of workers currently connected to,
diff --git a/scripts/base/frameworks/cluster/nodes/proxy.bro b/scripts/base/frameworks/cluster/nodes/proxy.bro
index 426a5c26fc..e38a5e9109 100644
--- a/scripts/base/frameworks/cluster/nodes/proxy.bro
+++ b/scripts/base/frameworks/cluster/nodes/proxy.bro
@@ -1,3 +1,7 @@
+##! Redefines the options common to all proxy nodes within a Bro cluster.
+##! In particular, proxies are not meant to produce logs locally and they
+##! do not forward events anywhere, they mainly synchronize state between
+##! worker nodes.
@prefixes += cluster-proxy
diff --git a/scripts/base/frameworks/cluster/nodes/worker.bro b/scripts/base/frameworks/cluster/nodes/worker.bro
index 454cf57c85..61d5228c88 100644
--- a/scripts/base/frameworks/cluster/nodes/worker.bro
+++ b/scripts/base/frameworks/cluster/nodes/worker.bro
@@ -1,3 +1,7 @@
+##! Redefines some options common to all worker nodes within a Bro cluster.
+##! In particular, worker nodes do not produce logs locally, instead they
+##! send them off to a manager node for processing.
+
@prefixes += cluster-worker
## Don't do any local logging.
diff --git a/scripts/base/frameworks/cluster/setup-connections.bro b/scripts/base/frameworks/cluster/setup-connections.bro
index 4e91036c55..b5a0d25e1f 100644
--- a/scripts/base/frameworks/cluster/setup-connections.bro
+++ b/scripts/base/frameworks/cluster/setup-connections.bro
@@ -1,3 +1,6 @@
+##! This script establishes communication among all nodes in a cluster
+##! as defined by :bro:id:`Cluster::nodes`.
+
@load ./main
@load base/frameworks/communication
diff --git a/scripts/base/frameworks/communication/main.bro b/scripts/base/frameworks/communication/main.bro
index 01c608c8db..04772f57aa 100644
--- a/scripts/base/frameworks/communication/main.bro
+++ b/scripts/base/frameworks/communication/main.bro
@@ -1,11 +1,13 @@
-##! Connect to remote Bro or Broccoli instances to share state and/or transfer
-##! events.
+##! Facilitates connecting to remote Bro or Broccoli instances to share state
+##! and/or transfer events.
@load base/frameworks/packet-filter
module Communication;
export {
+
+ ## The communication logging stream identifier.
redef enum Log::ID += { LOG };
## Which interface to listen on (0.0.0.0 for any interface).
@@ -21,14 +23,25 @@ export {
## compression.
global compression_level = 0 &redef;
+ ## A record type containing the column fields of the communication log.
type Info: record {
+ ## The network time at which a communication event occurred.
ts: time &log;
+ ## The peer name (if any) for which a communication event is concerned.
peer: string &log &optional;
+ ## Where the communication event message originated from, that is,
+ ## either from the scripting layer or inside the Bro process.
src_name: string &log &optional;
+ ## .. todo:: currently unused.
connected_peer_desc: string &log &optional;
+ ## .. todo:: currently unused.
connected_peer_addr: addr &log &optional;
+ ## .. todo:: currently unused.
connected_peer_port: port &log &optional;
+ ## The severity of the communication event message.
level: string &log &optional;
+ ## A message describing the communication event between Bro or
+ ## Broccoli instances.
message: string &log;
};
@@ -77,7 +90,7 @@ export {
auth: bool &default = F;
## If not set, no capture filter is sent.
- ## If set to "", the default cature filter is sent.
+ ## If set to "", the default capture filter is sent.
capture_filter: string &optional;
## Whether to use SSL-based communication.
@@ -96,11 +109,25 @@ export {
## The table of Bro or Broccoli nodes that Bro will initiate connections
## to or respond to connections from.
global nodes: table[string] of Node &redef;
-
+
+ ## A table of peer nodes for which this node issued a
+ ## :bro:id:`Communication::connect_peer` call but with which a connection
+ ## has not yet been established or with which a connection has been
+ ## closed and is currently in the process of retrying to establish.
+ ## When a connection is successfully established, the peer is removed
+ ## from the table.
global pending_peers: table[peer_id] of Node;
+
+ ## A table of peer nodes for which this node has an established connection.
+ ## Peers are automatically removed if their connection is closed and
+ ## automatically added back if a connection is re-established later.
global connected_peers: table[peer_id] of Node;
- ## Connect to nodes[node], independent of its "connect" flag.
+ ## Connect to a node in :bro:id:`Communication::nodes` independent
+ ## of its "connect" flag.
+ ##
+ ## peer: the string used to index a particular node within the
+ ## :bro:id:`Communication::nodes` table.
global connect_peer: function(peer: string);
}
diff --git a/scripts/base/frameworks/control/main.bro b/scripts/base/frameworks/control/main.bro
index 5aabaa4bac..4fe8872801 100644
--- a/scripts/base/frameworks/control/main.bro
+++ b/scripts/base/frameworks/control/main.bro
@@ -1,43 +1,30 @@
-##! This is a utility script that sends the current values of all &redef'able
-##! consts to a remote Bro then sends the :bro:id:`configuration_update` event
-##! and terminates processing.
-##!
-##! Intended to be used from the command line like this when starting a controller::
-##!
-##! bro frameworks/control/controller Control::host= Control::port= Control::cmd= [Control::arg=]
-##!
-##! A controllee only needs to load the controllee script in addition
-##! to the specific analysis scripts desired. It may also need a node
-##! configured as a controller node in the communications nodes configuration::
-##!
-##! bro frameworks/control/controllee
-##!
-##! To use the framework as a controllee, it only needs to be loaded and
-##! the controlled node need to accept all events in the "Control::" namespace
-##! from the host where the control actions will be performed from along with
-##! using the "control" class.
+##! The control framework provides the foundation for providing "commands"
+##! that can be taken remotely at runtime to modify a running Bro instance
+##! or collect information from the running instance.
module Control;
export {
- ## This is the address of the host that will be controlled.
+ ## The address of the host that will be controlled.
const host = 0.0.0.0 &redef;
- ## This is the port of the host that will be controlled.
+ ## The port of the host that will be controlled.
const host_port = 0/tcp &redef;
- ## This is the command that is being done. It's typically set on the
- ## command line and influences whether this instance starts up as a
- ## controller or controllee.
+ ## The command that is being done. It's typically set on the
+ ## command line.
const cmd = "" &redef;
## This can be used by commands that take an argument.
const arg = "" &redef;
+ ## Events that need to be handled by controllers.
const controller_events = /Control::.*_request/ &redef;
+
+ ## Events that need to be handled by controllees.
const controllee_events = /Control::.*_response/ &redef;
- ## These are the commands that can be given on the command line for
+ ## The commands that can currently be given on the command line for
## remote control.
const commands: set[string] = {
"id_value",
@@ -45,15 +32,15 @@ export {
"net_stats",
"configuration_update",
"shutdown",
- };
+ } &redef;
## Variable IDs that are to be ignored by the update process.
- const ignore_ids: set[string] = {
- };
+ const ignore_ids: set[string] = { };
## Event for requesting the value of an ID (a variable).
global id_value_request: event(id: string);
- ## Event for returning the value of an ID after an :bro:id:`id_request` event.
+ ## Event for returning the value of an ID after an
+ ## :bro:id:`Control::id_value_request` event.
global id_value_response: event(id: string, val: string);
## Requests the current communication status.
@@ -68,7 +55,8 @@ export {
## Inform the remote Bro instance that it's configuration may have been updated.
global configuration_update_request: event();
- ## This event is a wrapper and alias for the :bro:id:`configuration_update_request` event.
+ ## This event is a wrapper and alias for the
+ ## :bro:id:`Control::configuration_update_request` event.
## This event is also a primary hooking point for the control framework.
global configuration_update: event();
## Message in response to a configuration update request.
diff --git a/scripts/base/frameworks/dpd/main.bro b/scripts/base/frameworks/dpd/main.bro
index d9288bdd04..e8488c3ec1 100644
--- a/scripts/base/frameworks/dpd/main.bro
+++ b/scripts/base/frameworks/dpd/main.bro
@@ -7,14 +7,16 @@ module DPD;
redef signature_files += "base/frameworks/dpd/dpd.sig";
export {
+ ## Add the DPD logging stream identifier.
redef enum Log::ID += { LOG };
+ ## The record type defining the columns to log in the DPD logging stream.
type Info: record {
## Timestamp for when protocol analysis failed.
ts: time &log;
## Connection unique ID.
uid: string &log;
- ## Connection ID.
+ ## Connection ID containing the 4-tuple which identifies endpoints.
id: conn_id &log;
## Transport protocol for the violation.
proto: transport_proto &log;
diff --git a/scripts/base/frameworks/intel/main.bro b/scripts/base/frameworks/intel/main.bro
index 648c32bc57..9ee1c75100 100644
--- a/scripts/base/frameworks/intel/main.bro
+++ b/scripts/base/frameworks/intel/main.bro
@@ -11,7 +11,7 @@
# user_name
# file_name
# file_md5
-# x509_cert - DER encoded, not PEM (ascii armored)
+# x509_md5
# Example tags:
# infrastructure
@@ -25,6 +25,7 @@
module Intel;
export {
+ ## The intel logging stream identifier.
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
@@ -33,72 +34,117 @@ export {
Detection,
};
+ ## Record type used for logging information from the intelligence framework.
+ ## Primarily for problems or oddities with inserting and querying data.
+ ## This is important since the content of the intelligence framework can
+ ## change quite dramatically during runtime and problems may be introduced
+ ## into the data.
type Info: record {
+ ## The current network time.
ts: time &log;
+ ## Represents the severity of the message.
## This value should be one of: "info", "warn", "error"
level: string &log;
+ ## The message.
message: string &log;
};
+ ## Record to represent metadata associated with a single piece of
+ ## intelligence.
type MetaData: record {
+ ## A description for the data.
desc: string &optional;
+ ## A URL where more information may be found about the intelligence.
url: string &optional;
+ ## The time at which the data was first declared to be intelligence.
first_seen: time &optional;
+ ## When this data was most recent inserted into the framework.
latest_seen: time &optional;
+ ## Arbitrary text tags for the data.
tags: set[string];
};
+ ## Record to represent a singular piece of intelligence.
type Item: record {
+ ## If the data is an IP address, this hold the address.
ip: addr &optional;
+ ## If the data is textual, this holds the text.
str: string &optional;
+ ## If the data is numeric, this holds the number.
num: int &optional;
+ ## The subtype of the data for when either the $str or $num fields are
+ ## given. If one of those fields are given, this field must be present.
subtype: string &optional;
+ ## The next five fields are temporary until a better model for
+ ## attaching metadata to an intelligence item is created.
desc: string &optional;
url: string &optional;
first_seen: time &optional;
latest_seen: time &optional;
tags: set[string];
- ## These single string tags are throw away until pybroccoli supports sets
+ ## These single string tags are throw away until pybroccoli supports sets.
tag1: string &optional;
tag2: string &optional;
tag3: string &optional;
};
+ ## Record model used for constructing queries against the intelligence
+ ## framework.
type QueryItem: record {
- ip: addr &optional;
- str: string &optional;
- num: int &optional;
- subtype: string &optional;
+ ## If an IP address is being queried for, this field should be given.
+ ip: addr &optional;
+ ## If a string is being queried for, this field should be given.
+ str: string &optional;
+ ## If numeric data is being queried for, this field should be given.
+ num: int &optional;
+ ## If either a string or number is being queried for, this field should
+ ## indicate the subtype of the data.
+ subtype: string &optional;
- or_tags: set[string] &optional;
- and_tags: set[string] &optional;
+ ## A set of tags where if a single metadata record attached to an item
+ ## has any one of the tags defined in this field, it will match.
+ or_tags: set[string] &optional;
+ ## A set of tags where a single metadata record attached to an item
+ ## must have all of the tags defined in this field.
+ and_tags: set[string] &optional;
## The predicate can be given when searching for a match. It will
- ## be tested against every :bro:type:`MetaData` item associated with
- ## the data being matched on. If it returns T a single time, the
- ## matcher will consider that the item has matched.
- pred: function(meta: Intel::MetaData): bool &optional;
+ ## be tested against every :bro:type:`Intel::MetaData` item associated
+ ## with the data being matched on. If it returns T a single time, the
+ ## matcher will consider that the item has matched. This field can
+ ## be used for constructing arbitrarily complex queries that may not
+ ## be possible with the $or_tags or $and_tags fields.
+ pred: function(meta: Intel::MetaData): bool &optional;
};
-
+ ## Function to insert data into the intelligence framework.
+ ##
+ ## item: The data item.
+ ##
+ ## Returns: T if the data was successfully inserted into the framework,
+ ## otherwise it returns F.
global insert: function(item: Item): bool;
+
+ ## A wrapper for the :bro:id:`Intel::insert` function. This is primarily
+ ## used as the external API for inserting data into the intelligence
+ ## using Broccoli.
global insert_event: event(item: Item);
+
+ ## Function for matching data within the intelligence framework.
global matcher: function(item: QueryItem): bool;
-
- type MetaDataStore: table[count] of MetaData;
- type DataStore: record {
- ip_data: table[addr] of MetaDataStore;
- ## The first string is the actual value and the second string is the subtype.
- string_data: table[string, string] of MetaDataStore;
- int_data: table[int, string] of MetaDataStore;
- };
- global data_store: DataStore;
-
-
}
+type MetaDataStore: table[count] of MetaData;
+type DataStore: record {
+ ip_data: table[addr] of MetaDataStore;
+ # The first string is the actual value and the second string is the subtype.
+ string_data: table[string, string] of MetaDataStore;
+ int_data: table[int, string] of MetaDataStore;
+};
+global data_store: DataStore;
+
event bro_init()
{
Log::create_stream(Intel::LOG, [$columns=Info]);
diff --git a/scripts/base/frameworks/logging/main.bro b/scripts/base/frameworks/logging/main.bro
index 440773233d..2c36b3001e 100644
--- a/scripts/base/frameworks/logging/main.bro
+++ b/scripts/base/frameworks/logging/main.bro
@@ -1,16 +1,16 @@
##! The Bro logging interface.
##!
-##! See XXX for a introduction to Bro's logging framework.
+##! See :doc:`/logging` for a introduction to Bro's logging framework.
module Log;
-# Log::ID and Log::Writer are defined in bro.init due to circular dependencies.
+# Log::ID and Log::Writer are defined in types.bif due to circular dependencies.
export {
- ## If true, is local logging is by default enabled for all filters.
+ ## If true, local logging is by default enabled for all filters.
const enable_local_logging = T &redef;
- ## If true, is remote logging is by default enabled for all filters.
+ ## If true, remote logging is by default enabled for all filters.
const enable_remote_logging = T &redef;
## Default writer to use if a filter does not specify
@@ -23,21 +23,24 @@ export {
columns: any;
## Event that will be raised once for each log entry.
- ## The event receives a single same parameter, an instance of type ``columns``.
+ ## The event receives a single same parameter, an instance of type
+ ## ``columns``.
ev: any &optional;
};
- ## Default function for building the path values for log filters if not
- ## speficied otherwise by a filter. The default implementation uses ``id``
+ ## Builds the default path values for log filters if not otherwise
+ ## specified by a filter. The default implementation uses *id*
## to derive a name.
##
- ## id: The log stream.
+ ## id: The ID associated with the log stream.
+ ##
## path: A suggested path value, which may be either the filter's
## ``path`` if defined, else a previous result from the function.
## If no ``path`` is defined for the filter, then the first call
## to the function will contain an empty string.
+ ##
## rec: An instance of the streams's ``columns`` type with its
- ## fields set to the values to logged.
+ ## fields set to the values to be logged.
##
## Returns: The path to be used for the filter.
global default_path_func: function(id: ID, path: string, rec: any) : string &redef;
@@ -46,7 +49,7 @@ export {
## Information passed into rotation callback functions.
type RotationInfo: record {
- writer: Writer; ##< Writer.
+ writer: Writer; ##< The :bro:type:`Log::Writer` being used.
fname: string; ##< Full name of the rotated file.
path: string; ##< Original path value.
open: time; ##< Time when opened.
@@ -57,25 +60,26 @@ export {
## Default rotation interval. Zero disables rotation.
const default_rotation_interval = 0secs &redef;
- ## Default naming format for timestamps embedded into filenames. Uses a strftime() style.
+ ## Default naming format for timestamps embedded into filenames.
+ ## Uses a ``strftime()`` style.
const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef;
## Default shell command to run on rotated files. Empty for none.
const default_rotation_postprocessor_cmd = "" &redef;
- ## Specifies the default postprocessor function per writer type. Entries in this
- ## table are initialized by each writer type.
+ ## Specifies the default postprocessor function per writer type.
+ ## Entries in this table are initialized by each writer type.
const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef;
- ## Filter customizing logging.
+ ## A filter type describes how to customize logging streams.
type Filter: record {
## Descriptive name to reference this filter.
name: string;
- ## The writer to use.
+ ## The logging writer implementation to use.
writer: Writer &default=default_writer;
- ## Predicate indicating whether a log entry should be recorded.
+ ## Indicates whether a log entry should be recorded.
## If not given, all entries are recorded.
##
## rec: An instance of the streams's ``columns`` type with its
@@ -101,13 +105,15 @@ export {
## easy to flood the disk by returning a new string for each
## connection ...
##
- ## id: The log stream.
+ ## id: The ID associated with the log stream.
+ ##
## path: A suggested path value, which may be either the filter's
## ``path`` if defined, else a previous result from the function.
## If no ``path`` is defined for the filter, then the first call
## to the function will contain an empty string.
+ ##
## rec: An instance of the streams's ``columns`` type with its
- ## fields set to the values to logged.
+ ## fields set to the values to be logged.
##
## Returns: The path to be used for the filter.
path_func: function(id: ID, path: string, rec: any): string &optional;
@@ -129,27 +135,183 @@ export {
## Rotation interval.
interv: interval &default=default_rotation_interval;
- ## Callback function to trigger for rotated files. If not set,
- ## the default comes out of default_rotation_postprocessors.
+ ## Callback function to trigger for rotated files. If not set, the
+ ## default comes out of :bro:id:`Log::default_rotation_postprocessors`.
postprocessor: function(info: RotationInfo) : bool &optional;
};
## Sentinel value for indicating that a filter was not found when looked up.
- const no_filter: Filter = [$name=""]; # Sentinel.
+ const no_filter: Filter = [$name=""];
- # TODO: Document.
+ ## Creates a new logging stream with the default filter.
+ ##
+ ## id: The ID enum to be associated with the new logging stream.
+ ##
+ ## stream: A record defining the content that the new stream will log.
+ ##
+ ## Returns: True if a new logging stream was successfully created and
+ ## a default filter added to it.
+ ##
+ ## .. bro:see:: Log::add_default_filter Log::remove_default_filter
global create_stream: function(id: ID, stream: Stream) : bool;
+
+ ## Enables a previously disabled logging stream. Disabled streams
+ ## will not be written to until they are enabled again. New streams
+ ## are enabled by default.
+ ##
+ ## id: The ID associated with the logging stream to enable.
+ ##
+ ## Returns: True if the stream is re-enabled or was not previously disabled.
+ ##
+ ## .. bro:see:: Log::disable_stream
global enable_stream: function(id: ID) : bool;
+
+ ## Disables a currently enabled logging stream. Disabled streams
+ ## will not be written to until they are enabled again. New streams
+ ## are enabled by default.
+ ##
+ ## id: The ID associated with the logging stream to disable.
+ ##
+ ## Returns: True if the stream is now disabled or was already disabled.
+ ##
+ ## .. bro:see:: Log::enable_stream
global disable_stream: function(id: ID) : bool;
+
+ ## Adds a custom filter to an existing logging stream. If a filter
+ ## with a matching ``name`` field already exists for the stream, it
+ ## is removed when the new filter is successfully added.
+ ##
+ ## id: The ID associated with the logging stream to filter.
+ ##
+ ## filter: A record describing the desired logging parameters.
+ ##
+ ## Returns: True if the filter was sucessfully added, false if
+ ## the filter was not added or the *filter* argument was not
+ ## the correct type.
+ ##
+ ## .. bro:see:: Log::remove_filter Log::add_default_filter
+ ## Log::remove_default_filter
global add_filter: function(id: ID, filter: Filter) : bool;
+
+ ## Removes a filter from an existing logging stream.
+ ##
+ ## id: The ID associated with the logging stream from which to
+ ## remove a filter.
+ ##
+ ## name: A string to match against the ``name`` field of a
+ ## :bro:type:`Log::Filter` for identification purposes.
+ ##
+ ## Returns: True if the logging stream's filter was removed or
+ ## if no filter associated with *name* was found.
+ ##
+ ## .. bro:see:: Log::remove_filter Log::add_default_filter
+ ## Log::remove_default_filter
global remove_filter: function(id: ID, name: string) : bool;
- global get_filter: function(id: ID, name: string) : Filter; # Returns no_filter if not found.
+
+ ## Gets a filter associated with an existing logging stream.
+ ##
+ ## id: The ID associated with a logging stream from which to
+ ## obtain one of its filters.
+ ##
+ ## name: A string to match against the ``name`` field of a
+ ## :bro:type:`Log::Filter` for identification purposes.
+ ##
+ ## Returns: A filter attached to the logging stream *id* matching
+ ## *name* or, if no matches are found returns the
+ ## :bro:id:`Log::no_filter` sentinel value.
+ ##
+ ## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter
+ ## Log::remove_default_filter
+ global get_filter: function(id: ID, name: string) : Filter;
+
+ ## Writes a new log line/entry to a logging stream.
+ ##
+ ## id: The ID associated with a logging stream to be written to.
+ ##
+ ## columns: A record value describing the values of each field/column
+ ## to write to the log stream.
+ ##
+ ## Returns: True if the stream was found and no error occurred in writing
+ ## to it or if the stream was disabled and nothing was written.
+ ## False if the stream was was not found, or the *columns*
+ ## argument did not match what the stream was initially defined
+ ## to handle, or one of the stream's filters has an invalid
+ ## ``path_func``.
+ ##
+ ## .. bro:see: Log::enable_stream Log::disable_stream
global write: function(id: ID, columns: any) : bool;
+
+ ## Sets the buffering status for all the writers of a given logging stream.
+ ## A given writer implementation may or may not support buffering and if it
+ ## doesn't then toggling buffering with this function has no effect.
+ ##
+ ## id: The ID associated with a logging stream for which to
+ ## enable/disable buffering.
+ ##
+ ## buffered: Whether to enable or disable log buffering.
+ ##
+ ## Returns: True if buffering status was set, false if the logging stream
+ ## does not exist.
+ ##
+ ## .. bro:see:: Log::flush
global set_buf: function(id: ID, buffered: bool): bool;
+
+ ## Flushes any currently buffered output for all the writers of a given
+ ## logging stream.
+ ##
+ ## id: The ID associated with a logging stream for which to flush buffered
+ ## data.
+ ##
+ ## Returns: True if all writers of a log stream were signalled to flush
+ ## buffered data or if the logging stream is disabled,
+ ## false if the logging stream does not exist.
+ ##
+ ## .. bro:see:: Log::set_buf Log::enable_stream Log::disable_stream
global flush: function(id: ID): bool;
+
+ ## Adds a default :bro:type:`Log::Filter` record with ``name`` field
+ ## set as "default" to a given logging stream.
+ ##
+ ## id: The ID associated with a logging stream for which to add a default
+ ## filter.
+ ##
+ ## Returns: The status of a call to :bro:id:`Log::add_filter` using a
+ ## default :bro:type:`Log::Filter` argument with ``name`` field
+ ## set to "default".
+ ##
+ ## .. bro:see:: Log::add_filter Log::remove_filter
+ ## Log::remove_default_filter
global add_default_filter: function(id: ID) : bool;
+
+ ## Removes the :bro:type:`Log::Filter` with ``name`` field equal to
+ ## "default".
+ ##
+ ## id: The ID associated with a logging stream from which to remove the
+ ## default filter.
+ ##
+ ## Returns: The status of a call to :bro:id:`Log::remove_filter` using
+ ## "default" as the argument.
+ ##
+ ## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter
global remove_default_filter: function(id: ID) : bool;
+ ## Runs a command given by :bro:id:`Log::default_rotation_postprocessor_cmd`
+ ## on a rotated file. Meant to be called from postprocessor functions
+ ## that are added to :bro:id:`Log::default_rotation_postprocessors`.
+ ##
+ ## info: A record holding meta-information about the log being rotated.
+ ##
+ ## npath: The new path of the file (after already being rotated/processed
+ ## by writer-specific postprocessor as defined in
+ ## :bro:id:`Log::default_rotation_postprocessors`.
+ ##
+ ## Returns: True when :bro:id:`Log::default_rotation_postprocessor_cmd`
+ ## is empty or the system command given by it has been invoked
+ ## to postprocess a rotated log file.
+ ##
+ ## .. bro:see:: Log::default_rotation_date_format
+ ## Log::default_rotation_postprocessor_cmd
+ ## Log::default_rotation_postprocessors
global run_rotation_postprocessor_cmd: function(info: RotationInfo, npath: string) : bool;
}
diff --git a/scripts/base/frameworks/logging/postprocessors/scp.bro b/scripts/base/frameworks/logging/postprocessors/scp.bro
index ee709ebd5e..3aadc5bbf3 100644
--- a/scripts/base/frameworks/logging/postprocessors/scp.bro
+++ b/scripts/base/frameworks/logging/postprocessors/scp.bro
@@ -1,29 +1,51 @@
##! This script defines a postprocessing function that can be applied
##! to a logging filter in order to automatically SCP (secure copy)
##! a log stream (or a subset of it) to a remote host at configurable
-##! rotation time intervals.
+##! rotation time intervals. Generally, to use this functionality
+##! you must handle the :bro:id:`bro_init` event and do the following
+##! in your handler:
+##!
+##! 1) Create a new :bro:type:`Log::Filter` record that defines a name/path,
+##! rotation interval, and set the ``postprocessor`` to
+##! :bro:id:`Log::scp_postprocessor`.
+##! 2) Add the filter to a logging stream using :bro:id:`Log::add_filter`.
+##! 3) Add a table entry to :bro:id:`Log::scp_destinations` for the filter's
+##! writer/path pair which defines a set of :bro:type:`Log::SCPDestination`
+##! records.
module Log;
export {
- ## This postprocessor SCP's the rotated-log to all the remote hosts
+ ## Secure-copies the rotated-log to all the remote hosts
## defined in :bro:id:`Log::scp_destinations` and then deletes
## the local copy of the rotated-log. It's not active when
## reading from trace files.
+ ##
+ ## info: A record holding meta-information about the log file to be
+ ## postprocessed.
+ ##
+ ## Returns: True if secure-copy system command was initiated or
+ ## if no destination was configured for the log as described
+ ## by *info*.
global scp_postprocessor: function(info: Log::RotationInfo): bool;
## A container that describes the remote destination for the SCP command
## argument as ``user@host:path``.
type SCPDestination: record {
+ ## The remote user to log in as. A trust mechanism should be
+ ## pre-established.
user: string;
+ ## The remote host to which to transfer logs.
host: string;
+ ## The path/directory on the remote host to send logs.
path: string;
};
## A table indexed by a particular log writer and filter path, that yields
## a set remote destinations. The :bro:id:`Log::scp_postprocessor`
## function queries this table upon log rotation and performs a secure
- ## copy of the rotated-log to each destination in the set.
+ ## copy of the rotated-log to each destination in the set. This
+ ## table can be modified at run-time.
global scp_destinations: table[Writer, string] of set[SCPDestination];
## Default naming format for timestamps embedded into log filenames
diff --git a/scripts/base/frameworks/logging/writers/ascii.bro b/scripts/base/frameworks/logging/writers/ascii.bro
index c285512dd5..fa1fcd6797 100644
--- a/scripts/base/frameworks/logging/writers/ascii.bro
+++ b/scripts/base/frameworks/logging/writers/ascii.bro
@@ -1,4 +1,5 @@
-##! Interface for the ascii log writer.
+##! Interface for the ASCII log writer. Redefinable options are available
+##! to tweak the output format of ASCII logs.
module LogAscii;
@@ -7,7 +8,8 @@ export {
## into files. This is primarily for debugging purposes.
const output_to_stdout = F &redef;
- ## If true, include a header line with column names.
+ ## If true, include a header line with column names and description
+ ## of the other ASCII logging options that were used.
const include_header = T &redef;
## Prefix for the header line if included.
diff --git a/scripts/base/frameworks/metrics/cluster.bro b/scripts/base/frameworks/metrics/cluster.bro
index 6835c5bb9b..4804bc5005 100644
--- a/scripts/base/frameworks/metrics/cluster.bro
+++ b/scripts/base/frameworks/metrics/cluster.bro
@@ -13,11 +13,11 @@
module Metrics;
export {
- ## This value allows a user to decide how large of result groups the
- ## workers should transmit values.
+ ## Allows a user to decide how large of result groups the
+ ## workers should transmit values for cluster metric aggregation.
const cluster_send_in_groups_of = 50 &redef;
- ## This is the percent of the full threshold value that needs to be met
+ ## The percent of the full threshold value that needs to be met
## on a single worker for that worker to send the value to its manager in
## order for it to request a global view for that value. There is no
## requirement that the manager requests a global view for the index
@@ -25,11 +25,11 @@ export {
## recently.
const cluster_request_global_view_percent = 0.1 &redef;
- ## This event is sent by the manager in a cluster to initiate the
+ ## Event sent by the manager in a cluster to initiate the
## collection of metrics values for a filter.
global cluster_filter_request: event(uid: string, id: ID, filter_name: string);
- ## This event is sent by nodes that are collecting metrics after receiving
+ ## Event sent by nodes that are collecting metrics after receiving
## a request for the metric filter from the manager.
global cluster_filter_response: event(uid: string, id: ID, filter_name: string, data: MetricTable, done: bool);
@@ -40,12 +40,12 @@ export {
global cluster_index_request: event(uid: string, id: ID, filter_name: string, index: Index);
## This event is sent by nodes in response to a
- ## :bro:id:`cluster_index_request` event.
+ ## :bro:id:`Metrics::cluster_index_request` event.
global cluster_index_response: event(uid: string, id: ID, filter_name: string, index: Index, val: count);
## This is sent by workers to indicate that they crossed the percent of the
## current threshold by the percentage defined globally in
- ## :bro:id:`cluster_request_global_view_percent`
+ ## :bro:id:`Metrics::cluster_request_global_view_percent`
global cluster_index_intermediate_response: event(id: Metrics::ID, filter_name: string, index: Metrics::Index, val: count);
## This event is scheduled internally on workers to send result chunks.
diff --git a/scripts/base/frameworks/metrics/main.bro b/scripts/base/frameworks/metrics/main.bro
index f53a86a977..d322d128fe 100644
--- a/scripts/base/frameworks/metrics/main.bro
+++ b/scripts/base/frameworks/metrics/main.bro
@@ -1,13 +1,16 @@
-##! This is the implementation of the metrics framework.
+##! The metrics framework provides a way to count and measure data.
@load base/frameworks/notice
module Metrics;
export {
+ ## The metrics logging stream identifier.
redef enum Log::ID += { LOG };
+ ## Identifiers for metrics to collect.
type ID: enum {
+ ## Blank placeholder value.
NOTHING,
};
@@ -15,10 +18,13 @@ export {
## current value to the logging stream.
const default_break_interval = 15mins &redef;
- ## This is the interval for how often notices will happen after they have
- ## already fired.
+ ## This is the interval for how often threshold based notices will happen
+ ## after they have already fired.
const renotice_interval = 1hr &redef;
+ ## Represents a thing which is having metrics collected for it. An instance
+ ## of this record type and a :bro:type:`Metrics::ID` together represent a
+ ## single measurement.
type Index: record {
## Host is the value to which this metric applies.
host: addr &optional;
@@ -37,17 +43,30 @@ export {
network: subnet &optional;
} &log;
+ ## The record type that is used for logging metrics.
type Info: record {
+ ## Timestamp at which the metric was "broken".
ts: time &log;
+ ## What measurement the metric represents.
metric_id: ID &log;
+ ## The name of the filter being logged. :bro:type:`Metrics::ID` values
+ ## can have multiple filters which represent different perspectives on
+ ## the data so this is necessary to understand the value.
filter_name: string &log;
+ ## What the metric value applies to.
index: Index &log;
+ ## The simple numeric value of the metric.
value: count &log;
};
- # TODO: configure a metrics filter logging stream to log the current
+ # TODO: configure a metrics filter logging stream to log the current
# metrics configuration in case someone is looking through
# old logs and the configuration has changed since then.
+
+ ## Filters define how the data from a metric is aggregated and handled.
+ ## Filters can be used to set how often the measurements are cut or "broken"
+ ## and logged or how the data within them is aggregated. It's also
+ ## possible to disable logging and use filters for thresholding.
type Filter: record {
## The :bro:type:`Metrics::ID` that this filter applies to.
id: ID &optional;
@@ -62,7 +81,7 @@ export {
aggregation_mask: count &optional;
## This is essentially a mapping table between addresses and subnets.
aggregation_table: table[subnet] of subnet &optional;
- ## The interval at which the metric should be "broken" and written
+ ## The interval at which this filter should be "broken" and written
## to the logging stream. The counters are also reset to zero at
## this time so any threshold based detection needs to be set to a
## number that should be expected to happen within this period.
@@ -79,7 +98,7 @@ export {
notice_threshold: count &optional;
## A series of thresholds at which to generate notices.
notice_thresholds: vector of count &optional;
- ## How often this notice should be raised for this metric index. It
+ ## How often this notice should be raised for this filter. It
## will be generated everytime it crosses a threshold, but if the
## $break_interval is set to 5mins and this is set to 1hr the notice
## only be generated once per hour even if something crosses the
@@ -87,15 +106,43 @@ export {
notice_freq: interval &optional;
};
+ ## Function to associate a metric filter with a metric ID.
+ ##
+ ## id: The metric ID that the filter should be associated with.
+ ##
+ ## filter: The record representing the filter configuration.
global add_filter: function(id: ID, filter: Filter);
+
+ ## Add data into a :bro:type:`Metrics::ID`. This should be called when
+ ## a script has measured some point value and is ready to increment the
+ ## counters.
+ ##
+ ## id: The metric ID that the data represents.
+ ##
+ ## index: The metric index that the value is to be added to.
+ ##
+ ## increment: How much to increment the counter by.
global add_data: function(id: ID, index: Index, increment: count);
+
+ ## Helper function to represent a :bro:type:`Metrics::Index` value as
+ ## a simple string
+ ##
+ ## index: The metric index that is to be converted into a string.
+ ##
+ ## Returns: A string reprentation of the metric index.
global index2str: function(index: Index): string;
- # This is the event that is used to "finish" metrics and adapt the metrics
- # framework for clustered or non-clustered usage.
+ ## Event that is used to "finish" metrics and adapt the metrics
+ ## framework for clustered or non-clustered usage.
+ ##
+ ## ..note: This is primarily intended for internal use.
global log_it: event(filter: Filter);
+ ## Event to access metrics records as they are passed to the logging framework.
global log_metrics: event(rec: Info);
+
+ ## Type to store a table of metrics values. Interal use only!
+ type MetricTable: table[Index] of count &default=0;
}
redef record Notice::Info += {
@@ -105,7 +152,6 @@ redef record Notice::Info += {
global metric_filters: table[ID] of vector of Filter = table();
global filter_store: table[ID, string] of Filter = table();
-type MetricTable: table[Index] of count &default=0;
# This is indexed by metric ID and stream filter name.
global store: table[ID, string] of MetricTable = table() &default=table();
diff --git a/scripts/base/frameworks/notice/actions/email_admin.bro b/scripts/base/frameworks/notice/actions/email_admin.bro
index 56c0d5853d..7484a1c606 100644
--- a/scripts/base/frameworks/notice/actions/email_admin.bro
+++ b/scripts/base/frameworks/notice/actions/email_admin.bro
@@ -1,3 +1,8 @@
+##! Adds a new notice action type which can be used to email notices
+##! to the administrators of a particular address space as set by
+##! :bro:id:`Site::local_admins` if the notice contains a source
+##! or destination address that lies within their space.
+
@load ../main
@load base/utils/site
@@ -6,8 +11,8 @@ module Notice;
export {
redef enum Action += {
## Indicate that the generated email should be addressed to the
- ## appropriate email addresses as found in the
- ## :bro:id:`Site::addr_to_emails` variable based on the relevant
+ ## appropriate email addresses as found by the
+ ## :bro:id:`Site::get_emails` function based on the relevant
## address or addresses indicated in the notice.
ACTION_EMAIL_ADMIN
};
diff --git a/scripts/base/frameworks/notice/actions/page.bro b/scripts/base/frameworks/notice/actions/page.bro
index f88064ac47..16a3463126 100644
--- a/scripts/base/frameworks/notice/actions/page.bro
+++ b/scripts/base/frameworks/notice/actions/page.bro
@@ -1,3 +1,5 @@
+##! Allows configuration of a pager email address to which notices can be sent.
+
@load ../main
module Notice;
@@ -5,7 +7,7 @@ module Notice;
export {
redef enum Action += {
## Indicates that the notice should be sent to the pager email address
- ## configured in the :bro:id:`mail_page_dest` variable.
+ ## configured in the :bro:id:`Notice::mail_page_dest` variable.
ACTION_PAGE
};
diff --git a/scripts/base/frameworks/notice/actions/pp-alarms.bro b/scripts/base/frameworks/notice/actions/pp-alarms.bro
index 609f6a6bf1..82fda6db6c 100644
--- a/scripts/base/frameworks/notice/actions/pp-alarms.bro
+++ b/scripts/base/frameworks/notice/actions/pp-alarms.bro
@@ -1,6 +1,6 @@
-#! Notice extension that mails out a pretty-printed version of alarm.log
-#! in regular intervals, formatted for better human readability. If activated,
-#! that replaces the default summary mail having the raw log output.
+##! Notice extension that mails out a pretty-printed version of alarm.log
+##! in regular intervals, formatted for better human readability. If activated,
+##! that replaces the default summary mail having the raw log output.
@load base/frameworks/cluster
@load ../main
@@ -14,9 +14,8 @@ export {
## Address to send the pretty-printed reports to. Default if not set is
## :bro:id:`Notice::mail_dest`.
const mail_dest_pretty_printed = "" &redef;
-
## If an address from one of these networks is reported, we mark
- ## the entry with an addition quote symbol (i.e., ">"). Many MUAs
+ ## the entry with an additional quote symbol (i.e., ">"). Many MUAs
## then highlight such lines differently.
global flag_nets: set[subnet] &redef;
diff --git a/scripts/base/frameworks/notice/cluster.bro b/scripts/base/frameworks/notice/cluster.bro
index 7270e14933..281901cf31 100644
--- a/scripts/base/frameworks/notice/cluster.bro
+++ b/scripts/base/frameworks/notice/cluster.bro
@@ -1,4 +1,6 @@
-##! Implements notice functionality across clusters.
+##! Implements notice functionality across clusters. Worker nodes
+##! will disable notice/alarm logging streams and forward notice
+##! events to the manager node for logging/processing.
@load ./main
@load base/frameworks/cluster
@@ -7,10 +9,15 @@ module Notice;
export {
## This is the event used to transport notices on the cluster.
+ ##
+ ## n: The notice information to be sent to the cluster manager for
+ ## further processing.
global cluster_notice: event(n: Notice::Info);
}
+## Manager can communicate notice suppression to workers.
redef Cluster::manager2worker_events += /Notice::begin_suppression/;
+## Workers needs need ability to forward notices to manager.
redef Cluster::worker2manager_events += /Notice::cluster_notice/;
@if ( Cluster::local_node_type() != Cluster::MANAGER )
diff --git a/scripts/base/frameworks/notice/extend-email/hostnames.bro b/scripts/base/frameworks/notice/extend-email/hostnames.bro
index 17a597678d..2ec6dbb23f 100644
--- a/scripts/base/frameworks/notice/extend-email/hostnames.bro
+++ b/scripts/base/frameworks/notice/extend-email/hostnames.bro
@@ -1,3 +1,8 @@
+##! Loading this script extends the :bro:enum:`Notice::ACTION_EMAIL` action
+##! by appending to the email the hostnames associated with
+##! :bro:type:`Notice::Info`'s *src* and *dst* fields as determined by a
+##! DNS lookup.
+
@load ../main
module Notice;
diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro
index 70cf613b72..e9b29e7392 100644
--- a/scripts/base/frameworks/notice/main.bro
+++ b/scripts/base/frameworks/notice/main.bro
@@ -2,8 +2,7 @@
##! are odd or potentially bad. Decisions of the meaning of various notices
##! need to be done per site because Bro does not ship with assumptions about
##! what is bad activity for sites. More extensive documetation about using
-##! the notice framework can be found in the documentation section of the
-##! http://www.bro-ids.org/ website.
+##! the notice framework can be found in :doc:`/notice`.
module Notice;
@@ -21,10 +20,10 @@ export {
## Scripts creating new notices need to redef this enum to add their own
## specific notice types which would then get used when they call the
## :bro:id:`NOTICE` function. The convention is to give a general category
- ## along with the specific notice separating words with underscores and using
- ## leading capitals on each word except for abbreviations which are kept in
- ## all capitals. For example, SSH::Login is for heuristically guessed
- ## successful SSH logins.
+ ## along with the specific notice separating words with underscores and
+ ## using leading capitals on each word except for abbreviations which are
+ ## kept in all capitals. For example, SSH::Login is for heuristically
+ ## guessed successful SSH logins.
type Type: enum {
## Notice reporting a count of how often a notice occurred.
Tally,
@@ -49,26 +48,37 @@ export {
};
## The notice framework is able to do automatic notice supression by
- ## utilizing the $identifier field in :bro:type:`Info` records.
+ ## utilizing the $identifier field in :bro:type:`Notice::Info` records.
## Set this to "0secs" to completely disable automated notice suppression.
const default_suppression_interval = 1hrs &redef;
type Info: record {
+ ## An absolute time indicating when the notice occurred, defaults
+ ## to the current network time.
ts: time &log &optional;
- uid: string &log &optional;
- id: conn_id &log &optional;
- ## These are shorthand ways of giving the uid and id to a notice. The
+ ## A connection UID which uniquely identifies the endpoints
+ ## concerned with the notice.
+ uid: string &log &optional;
+
+ ## A connection 4-tuple identifying the endpoints concerned with the
+ ## notice.
+ id: conn_id &log &optional;
+
+ ## A shorthand way of giving the uid and id to a notice. The
## reference to the actual connection will be deleted after applying
## the notice policy.
conn: connection &optional;
+ ## A shorthand way of giving the uid and id to a notice. The
+ ## reference to the actual connection will be deleted after applying
+ ## the notice policy.
iconn: icmp_conn &optional;
## The transport protocol. Filled automatically when either conn, iconn
## or p is specified.
proto: transport_proto &log &optional;
- ## The :bro:enum:`Notice::Type` of the notice.
+ ## The :bro:type:`Notice::Type` of the notice.
note: Type &log;
## The human readable message for the notice.
msg: string &log &optional;
@@ -105,7 +115,7 @@ export {
## Adding a string "token" to this set will cause the notice framework's
## built-in emailing functionality to delay sending the email until
## either the token has been removed or the email has been delayed
- ## for :bro:id:`max_email_delay`.
+ ## for :bro:id:`Notice::max_email_delay`.
email_delay_tokens: set[string] &optional;
## This field is to be provided when a notice is generated for the
@@ -151,8 +161,9 @@ export {
## This is the record that defines the items that make up the notice policy.
type PolicyItem: record {
- ## This is the exact positional order in which the :bro:type:`PolicyItem`
- ## records are checked. This is set internally by the notice framework.
+ ## This is the exact positional order in which the
+ ## :bro:type:`Notice::PolicyItem` records are checked.
+ ## This is set internally by the notice framework.
position: count &log &optional;
## Define the priority for this check. Items are checked in ordered
## from highest value (10) to lowest value (0).
@@ -172,9 +183,9 @@ export {
## be supressed.
suppress_for: interval &log &optional;
};
-
- ## This is the where the :bro:id:`Notice::policy` is defined. All notice
- ## processing is done through this variable.
+
+ ## Defines a notice policy that is extensible on a per-site basis.
+ ## All notice processing is done through this variable.
const policy: set[PolicyItem] = {
[$pred(n: Notice::Info) = { return (n$note in Notice::ignored_types); },
$halt=T, $priority = 9],
@@ -203,8 +214,9 @@ export {
## Local system sendmail program.
const sendmail = "/usr/sbin/sendmail" &redef;
- ## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action
- ## or to send bulk alarm logs on rotation with :bro:enum:`ACTION_ALARM`.
+ ## Email address to send notices with the :bro:enum:`Notice::ACTION_EMAIL`
+ ## action or to send bulk alarm logs on rotation with
+ ## :bro:enum:`Notice::ACTION_ALARM`.
const mail_dest = "" &redef;
## Address that emails will be from.
@@ -219,14 +231,20 @@ export {
## A log postprocessing function that implements emailing the contents
## of a log upon rotation to any configured :bro:id:`Notice::mail_dest`.
## The rotated log is removed upon being sent.
+ ##
+ ## info: A record containing the rotated log file information.
+ ##
+ ## Returns: True.
global log_mailing_postprocessor: function(info: Log::RotationInfo): bool;
## This is the event that is called as the entry point to the
## notice framework by the global :bro:id:`NOTICE` function. By the time
## this event is generated, default values have already been filled out in
- ## the :bro:type:`Notice::Info` record and synchronous functions in the
- ## :bro:id:`Notice:sync_functions` have already been called. The notice
+ ## the :bro:type:`Notice::Info` record and synchronous functions in the
+ ## :bro:id:`Notice::sync_functions` have already been called. The notice
## policy has also been applied.
+ ##
+ ## n: The record containing notice data.
global notice: event(n: Info);
## This is a set of functions that provide a synchronous way for scripts
@@ -243,30 +261,55 @@ export {
const sync_functions: set[function(n: Notice::Info)] = set() &redef;
## This event is generated when a notice begins to be suppressed.
+ ##
+ ## n: The record containing notice data regarding the notice type
+ ## about to be suppressed.
global begin_suppression: event(n: Notice::Info);
+
## This event is generated on each occurence of an event being suppressed.
+ ##
+ ## n: The record containing notice data regarding the notice type
+ ## being suppressed.
global suppressed: event(n: Notice::Info);
+
## This event is generated when a notice stops being suppressed.
+ ##
+ ## n: The record containing notice data regarding the notice type
+ ## that was being suppressed.
global end_suppression: event(n: Notice::Info);
## Call this function to send a notice in an email. It is already used
- ## by default with the built in :bro:enum:`ACTION_EMAIL` and
- ## :bro:enum:`ACTION_PAGE` actions.
+ ## by default with the built in :bro:enum:`Notice::ACTION_EMAIL` and
+ ## :bro:enum:`Notice::ACTION_PAGE` actions.
+ ##
+ ## n: The record of notice data to email.
+ ##
+ ## dest: The intended recipient of the notice email.
+ ##
+ ## extend: Whether to extend the email using the ``email_body_sections``
+ ## field of *n*.
global email_notice_to: function(n: Info, dest: string, extend: bool);
## Constructs mail headers to which an email body can be appended for
## sending with sendmail.
+ ##
## subject_desc: a subject string to use for the mail
+ ##
## dest: recipient string to use for the mail
+ ##
## Returns: a string of mail headers to which an email body can be appended
global email_headers: function(subject_desc: string, dest: string): string;
-
- ## This event can be handled to access the :bro:type:`Info`
+
+ ## This event can be handled to access the :bro:type:`Notice::Info`
## record as it is sent on to the logging framework.
+ ##
+ ## rec: The record containing notice data before it is logged.
global log_notice: event(rec: Info);
-
- ## This is an internal wrapper for the global NOTICE function. Please
+
+ ## This is an internal wrapper for the global :bro:id:`NOTICE` function;
## disregard.
+ ##
+ ## n: The record of notice data.
global internal_NOTICE: function(n: Notice::Info);
}
@@ -445,9 +488,10 @@ event notice(n: Notice::Info) &priority=-5
event Notice::begin_suppression(n);
}
}
-
-## This determines if a notice is being suppressed. It is only used
-## internally as part of the mechanics for the global NOTICE function.
+
+## This determines if a notice is being suppressed. It is only used
+## internally as part of the mechanics for the global :bro:id:`NOTICE`
+## function.
function is_being_suppressed(n: Notice::Info): bool
{
if ( n?$identifier && [n$note, n$identifier] in suppressing )
diff --git a/scripts/base/frameworks/notice/weird.bro b/scripts/base/frameworks/notice/weird.bro
index 379409532c..f894a42464 100644
--- a/scripts/base/frameworks/notice/weird.bro
+++ b/scripts/base/frameworks/notice/weird.bro
@@ -1,3 +1,12 @@
+##! This script provides a default set of actions to take for "weird activity"
+##! events generated from Bro's event engine. Weird activity is defined as
+##! unusual or exceptional activity that can indicate malformed connections,
+##! traffic that doesn't conform to a particular protocol, malfunctioning
+##! or misconfigured hardware, or even an attacker attempting to avoid/confuse
+##! a sensor. Without context, it's hard to judge whether a particular
+##! category of weird activity is interesting, but this script provides
+##! a starting point for the user.
+
@load base/utils/conn-ids
@load base/utils/site
@load ./main
@@ -5,6 +14,7 @@
module Weird;
export {
+ ## The weird logging stream identifier.
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
@@ -12,6 +22,7 @@ export {
Activity,
};
+ ## The record type which contains the column fields of the weird log.
type Info: record {
## The time when the weird occurred.
ts: time &log;
@@ -32,19 +43,32 @@ export {
peer: string &log &optional;
};
+ ## Types of actions that may be taken when handling weird activity events.
type Action: enum {
+ ## A dummy action indicating the user does not care what internal
+ ## decision is made regarding a given type of weird.
ACTION_UNSPECIFIED,
+ ## No action is to be taken.
ACTION_IGNORE,
+ ## Log the weird event every time it occurs.
ACTION_LOG,
+ ## Log the weird event only once.
ACTION_LOG_ONCE,
+ ## Log the weird event once per connection.
ACTION_LOG_PER_CONN,
+ ## Log the weird event once per originator host.
ACTION_LOG_PER_ORIG,
+ ## Always generate a notice associated with the weird event.
ACTION_NOTICE,
+ ## Generate a notice associated with the weird event only once.
ACTION_NOTICE_ONCE,
+ ## Generate a notice for the weird event once per connection.
ACTION_NOTICE_PER_CONN,
+ ## Generate a notice for the weird event once per originator host.
ACTION_NOTICE_PER_ORIG,
};
+ ## A table specifying default/recommended actions per weird type.
const actions: table[string] of Action = {
["unsolicited_SYN_response"] = ACTION_IGNORE,
["above_hole_data_without_any_acks"] = ACTION_LOG,
@@ -201,7 +225,7 @@ export {
["fragment_overlap"] = ACTION_LOG_PER_ORIG,
["fragment_protocol_inconsistency"] = ACTION_LOG,
["fragment_size_inconsistency"] = ACTION_LOG_PER_ORIG,
- ## These do indeed happen!
+ # These do indeed happen!
["fragment_with_DF"] = ACTION_LOG,
["incompletely_captured_fragment"] = ACTION_LOG,
["bad_IP_checksum"] = ACTION_LOG_PER_ORIG,
@@ -215,8 +239,8 @@ export {
## and weird name into this set.
const ignore_hosts: set[addr, string] &redef;
- # But don't ignore these (for the weird file), it's handy keeping
- # track of clustered checksum errors.
+ ## Don't ignore repeats for weirds in this set. For example,
+ ## it's handy keeping track of clustered checksum errors.
const weird_do_not_ignore_repeats = {
"bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum",
"bad_ICMP_checksum",
@@ -236,7 +260,11 @@ export {
## A state set which tracks unique weirds solely by the name to reduce
## duplicate notices from being raised.
global did_notice: set[string, string] &create_expire=1day &redef;
-
+
+ ## Handlers of this event are invoked one per write to the weird
+ ## logging stream before the data is actually written.
+ ##
+ ## rec: The weird columns about to be logged to the weird stream.
global log_weird: event(rec: Info);
}
diff --git a/scripts/base/frameworks/packet-filter/main.bro b/scripts/base/frameworks/packet-filter/main.bro
index 1097315172..16e3ff9789 100644
--- a/scripts/base/frameworks/packet-filter/main.bro
+++ b/scripts/base/frameworks/packet-filter/main.bro
@@ -9,17 +9,22 @@
module PacketFilter;
export {
+ ## Add the packet filter logging stream.
redef enum Log::ID += { LOG };
-
+
+ ## Add notice types related to packet filter errors.
redef enum Notice::Type += {
## This notice is generated if a packet filter is unable to be compiled.
Compile_Failure,
- ## This notice is generated if a packet filter is unable to be installed.
+ ## This notice is generated if a packet filter is fails to install.
Install_Failure,
};
-
+
+ ## The record type defining columns to be logged in the packet filter
+ ## logging stream.
type Info: record {
+ ## The time at which the packet filter installation attempt was made.
ts: time &log;
## This is a string representation of the node that applied this
@@ -40,7 +45,7 @@ export {
## By default, Bro will examine all packets. If this is set to false,
## it will dynamically build a BPF filter that only select protocols
## for which the user has loaded a corresponding analysis script.
- ## The latter used to be default for Bro versions < 1.6. That has now
+ ## The latter used to be default for Bro versions < 2.0. That has now
## changed however to enable port-independent protocol analysis.
const all_packets = T &redef;
diff --git a/scripts/base/frameworks/packet-filter/netstats.bro b/scripts/base/frameworks/packet-filter/netstats.bro
index 69b5026515..9fbaa5cd1d 100644
--- a/scripts/base/frameworks/packet-filter/netstats.bro
+++ b/scripts/base/frameworks/packet-filter/netstats.bro
@@ -1,4 +1,6 @@
##! This script reports on packet loss from the various packet sources.
+##! When Bro is reading input from trace files, this script will not
+##! report any packet loss statistics.
@load base/frameworks/notice
@@ -6,7 +8,7 @@ module PacketFilter;
export {
redef enum Notice::Type += {
- ## Bro reported packets dropped by the packet filter.
+ ## Indicates packets were dropped by the packet filter.
Dropped_Packets,
};
diff --git a/scripts/base/frameworks/reporter/main.bro b/scripts/base/frameworks/reporter/main.bro
index e70106f39a..3c19005364 100644
--- a/scripts/base/frameworks/reporter/main.bro
+++ b/scripts/base/frameworks/reporter/main.bro
@@ -1,21 +1,36 @@
##! This framework is intended to create an output and filtering path for
##! internal messages/warnings/errors. It should typically be loaded to
-##! avoid Bro spewing internal messages to standard error.
+##! avoid Bro spewing internal messages to standard error and instead log
+##! them to a file in a standard way. Note that this framework deals with
+##! the handling of internally-generated reporter messages, for the
+##! interface into actually creating reporter messages from the scripting
+##! layer, use the built-in functions in :doc:`/scripts/base/reporter.bif`.
module Reporter;
export {
+ ## The reporter logging stream identifier.
redef enum Log::ID += { LOG };
-
+
+ ## An indicator of reporter message severity.
type Level: enum {
+ ## Informational, not needing specific attention.
INFO,
+ ## Warning of a potential problem.
WARNING,
+ ## A non-fatal error that should be addressed, but doesn't
+ ## terminate program execution.
ERROR
};
-
+
+ ## The record type which contains the column fields of the reporter log.
type Info: record {
+ ## The network time at which the reporter event was generated.
ts: time &log;
+ ## The severity of the reporter message.
level: Level &log;
+ ## An info/warning/error message that could have either been
+ ## generated from the internal Bro core or at the scripting-layer.
message: string &log;
## This is the location in a Bro script where the message originated.
## Not all reporter messages will have locations in them though.
diff --git a/scripts/base/frameworks/signatures/main.bro b/scripts/base/frameworks/signatures/main.bro
index 4811fdd5a9..26f78a68d1 100644
--- a/scripts/base/frameworks/signatures/main.bro
+++ b/scripts/base/frameworks/signatures/main.bro
@@ -1,30 +1,36 @@
-##! Script level signature support.
+##! Script level signature support. See the
+##! :doc:`signature documentation ` for more information about
+##! Bro's signature engine.
@load base/frameworks/notice
module Signatures;
export {
+ ## Add various signature-related notice types.
redef enum Notice::Type += {
- ## Generic for alarm-worthy
+ ## Generic notice type for notice-worthy signature matches.
Sensitive_Signature,
## Host has triggered many signatures on the same host. The number of
- ## signatures is defined by the :bro:id:`vert_scan_thresholds` variable.
+ ## signatures is defined by the
+ ## :bro:id:`Signatures::vert_scan_thresholds` variable.
Multiple_Signatures,
- ## Host has triggered the same signature on multiple hosts as defined by the
- ## :bro:id:`horiz_scan_thresholds` variable.
+ ## Host has triggered the same signature on multiple hosts as defined
+ ## by the :bro:id:`Signatures::horiz_scan_thresholds` variable.
Multiple_Sig_Responders,
- ## The same signature has triggered multiple times for a host. The number
- ## of times the signature has be trigger is defined by the
- ## :bro:id:`count_thresholds` variable. To generate this notice, the
- ## :bro:enum:`SIG_COUNT_PER_RESP` action must be set for the signature.
+ ## The same signature has triggered multiple times for a host. The
+ ## number of times the signature has been triggered is defined by the
+ ## :bro:id:`Signatures::count_thresholds` variable. To generate this
+ ## notice, the :bro:enum:`Signatures::SIG_COUNT_PER_RESP` action must
+ ## bet set for the signature.
Count_Signature,
## Summarize the number of times a host triggered a signature. The
- ## interval between summaries is defined by the :bro:id:`summary_interval`
- ## variable.
+ ## interval between summaries is defined by the
+ ## :bro:id:`Signatures::summary_interval` variable.
Signature_Summary,
};
+ ## The signature logging stream identifier.
redef enum Log::ID += { LOG };
## These are the default actions you can apply to signature matches.
@@ -39,8 +45,8 @@ export {
SIG_QUIET,
## Generate a notice.
SIG_LOG,
- ## The same as :bro:enum:`SIG_FILE`, but ignore for aggregate/scan
- ## processing.
+ ## The same as :bro:enum:`Signatures::SIG_LOG`, but ignore for
+ ## aggregate/scan processing.
SIG_FILE_BUT_NO_SCAN,
## Generate a notice and set it to be alarmed upon.
SIG_ALARM,
@@ -49,22 +55,33 @@ export {
## Alarm once and then never again.
SIG_ALARM_ONCE,
## Count signatures per responder host and alarm with the
- ## :bro:enum:`Count_Signature` notice if a threshold defined by
- ## :bro:id:`count_thresholds` is reached.
+ ## :bro:enum:`Signatures::Count_Signature` notice if a threshold
+ ## defined by :bro:id:`Signatures::count_thresholds` is reached.
SIG_COUNT_PER_RESP,
## Don't alarm, but generate per-orig summary.
SIG_SUMMARY,
};
-
+
+ ## The record type which contains the column fields of the signature log.
type Info: record {
+ ## The network time at which a signature matching type of event to
+ ## be logged has occurred.
ts: time &log;
+ ## The host which triggered the signature match event.
src_addr: addr &log &optional;
+ ## The host port on which the signature-matching activity occurred.
src_port: port &log &optional;
+ ## The destination host which was sent the payload that triggered the
+ ## signature match.
dst_addr: addr &log &optional;
+ ## The destination host port which was sent the payload that triggered
+ ## the signature match.
dst_port: port &log &optional;
## Notice associated with signature event
note: Notice::Type &log;
+ ## The name of the signature that matched.
sig_id: string &log &optional;
+ ## A more descriptive message of the signature-matching event.
event_msg: string &log &optional;
## Extracted payload data or extra message.
sub_msg: string &log &optional;
@@ -82,22 +99,26 @@ export {
## Signature IDs that should always be ignored.
const ignored_ids = /NO_DEFAULT_MATCHES/ &redef;
- ## Alarm if, for a pair [orig, signature], the number of different
- ## responders has reached one of the thresholds.
+ ## Generate a notice if, for a pair [orig, signature], the number of
+ ## different responders has reached one of the thresholds.
const horiz_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef;
- ## Alarm if, for a pair [orig, resp], the number of different signature
- ## matches has reached one of the thresholds.
+ ## Generate a notice if, for a pair [orig, resp], the number of different
+ ## signature matches has reached one of the thresholds.
const vert_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef;
- ## Alarm if a :bro:enum:`SIG_COUNT_PER_RESP` signature is triggered as
- ## often as given by one of these thresholds.
+ ## Generate a notice if a :bro:enum:`Signatures::SIG_COUNT_PER_RESP`
+ ## signature is triggered as often as given by one of these thresholds.
const count_thresholds = { 5, 10, 50, 100, 500, 1000, 10000, 1000000, } &redef;
- ## The interval between when :bro:id:`Signature_Summary` notices are
- ## generated.
+ ## The interval between when :bro:enum:`Signatures::Signature_Summary`
+ ## notice are generated.
const summary_interval = 1 day &redef;
-
+
+ ## This event can be handled to access/alter data about to be logged
+ ## to the signature logging stream.
+ ##
+ ## rec: The record of signature data about to be logged.
global log_signature: event(rec: Info);
}
diff --git a/scripts/base/frameworks/software/main.bro b/scripts/base/frameworks/software/main.bro
index 574886288a..f5bbf00a2f 100644
--- a/scripts/base/frameworks/software/main.bro
+++ b/scripts/base/frameworks/software/main.bro
@@ -1,5 +1,5 @@
##! This script provides the framework for software version detection and
-##! parsing, but doesn't actually do any detection on it's own. It relys on
+##! parsing but doesn't actually do any detection on it's own. It relys on
##! other protocol specific scripts to parse out software from the protocols
##! that they analyze. The entry point for providing new software detections
##! to this framework is through the :bro:id:`Software::found` function.
@@ -10,39 +10,44 @@
module Software;
export {
-
+ ## The software logging stream identifier.
redef enum Log::ID += { LOG };
-
+
+ ## Scripts detecting new types of software need to redef this enum to add
+ ## their own specific software types which would then be used when they
+ ## create :bro:type:`Software::Info` records.
type Type: enum {
+ ## A placeholder type for when the type of software is not known.
UNKNOWN,
- OPERATING_SYSTEM,
- DATABASE_SERVER,
- # There are a number of ways to detect printers on the
- # network, we just need to codify them in a script and move
- # this out of here. It isn't currently used for anything.
- PRINTER,
};
-
+
+ ## A structure to represent the numeric version of software.
type Version: record {
- major: count &optional; ##< Major version number
- minor: count &optional; ##< Minor version number
- minor2: count &optional; ##< Minor subversion number
- addl: string &optional; ##< Additional version string (e.g. "beta42")
+ ## Major version number
+ major: count &optional;
+ ## Minor version number
+ minor: count &optional;
+ ## Minor subversion number
+ minor2: count &optional;
+ ## Additional version string (e.g. "beta42")
+ addl: string &optional;
} &log;
-
+
+ ## The record type that is used for representing and logging software.
type Info: record {
- ## The time at which the software was first detected.
+ ## The time at which the software was detected.
ts: time &log;
## The IP address detected running the software.
host: addr &log;
- ## The type of software detected (e.g. WEB_SERVER)
+ ## The type of software detected (e.g. :bro:enum:`HTTP::SERVER`).
software_type: Type &log &default=UNKNOWN;
- ## Name of the software (e.g. Apache)
+ ## Name of the software (e.g. Apache).
name: string &log;
- ## Version of the software
+ ## Version of the software.
version: Version &log;
## The full unparsed version string found because the version parsing
- ## doesn't work 100% reliably and this acts as a fall back in the logs.
+ ## doesn't always work reliably in all cases and this acts as a
+ ## fallback in the logs.
unparsed_version: string &log &optional;
## This can indicate that this software being detected should
@@ -55,37 +60,48 @@ export {
force_log: bool &default=F;
};
- ## The hosts whose software should be detected and tracked.
+ ## Hosts whose software should be detected and tracked.
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
const asset_tracking = LOCAL_HOSTS &redef;
-
## Other scripts should call this function when they detect software.
## unparsed_version: This is the full string from which the
## :bro:type:`Software::Info` was extracted.
+ ##
+ ## id: The connection id where the software was discovered.
+ ##
+ ## info: A record representing the software discovered.
+ ##
## Returns: T if the software was logged, F otherwise.
global found: function(id: conn_id, info: Software::Info): bool;
- ## This function can take many software version strings and parse them
+ ## Take many common software version strings and parse them
## into a sensible :bro:type:`Software::Version` record. There are
## still many cases where scripts may have to have their own specific
## version parsing though.
+ ##
+ ## unparsed_version: The raw version string.
+ ##
+ ## host: The host where the software was discovered.
+ ##
+ ## software_type: The type of software.
+ ##
+ ## Returns: A complete record ready for the :bro:id:`Software::found` function.
global parse: function(unparsed_version: string,
host: addr,
software_type: Type): Info;
- ## Compare two versions.
+ ## Compare two version records.
+ ##
## Returns: -1 for v1 < v2, 0 for v1 == v2, 1 for v1 > v2.
## If the numerical version numbers match, the addl string
## is compared lexicographically.
global cmp_versions: function(v1: Version, v2: Version): int;
- ## This type represents a set of software. It's used by the
- ## :bro:id:`tracked` variable to store all known pieces of software
- ## for a particular host. It's indexed with the name of a piece of
- ## software such as "Firefox" and it yields a
- ## :bro:type:`Software::Info` record with more information about the
- ## software.
+ ## Type to represent a collection of :bro:type:`Software::Info` records.
+ ## It's indexed with the name of a piece of software such as "Firefox"
+ ## and it yields a :bro:type:`Software::Info` record with more information
+ ## about the software.
type SoftwareSet: table[string] of Info;
## The set of software associated with an address. Data expires from
diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro
index 5e334496c6..200947938d 100644
--- a/scripts/base/init-bare.bro
+++ b/scripts/base/init-bare.bro
@@ -2,172 +2,311 @@
@load base/types.bif
# Type declarations
+
+## An ordered array of strings. The entries are indexed by succesive numbers. Note
+## that it depends on the usage whether the first index is zero or one.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type string_array: table[count] of string;
+
+## A set of strings.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type string_set: set[string];
+
+## A set of addresses.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type addr_set: set[addr];
+
+## A set of counts.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type count_set: set[count];
+
+## A vector of counts, used by some builtin functions to store a list of indices.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type index_vec: vector of count;
+
+## A vector of strings.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type string_vec: vector of string;
+## A table of strings indexed by strings.
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type table_string_of_string: table[string] of string;
-type transport_proto: enum { unknown_transport, tcp, udp, icmp };
+## A connection's transport-layer protocol. Note that Bro uses the term
+## "connection" broadly, using flow semantics for ICMP and UDP.
+type transport_proto: enum {
+ unknown_transport, ##< An unknown transport-layer protocol.
+ tcp, ##< TCP.
+ udp, ##< UDP.
+ icmp ##< ICMP.
+};
+## A connection's identifying 4-tuple of endpoints and ports.
+##
+## .. note:: It's actually a 5-tuple: the transport-layer protocol is stored as
+## part of the port values, `orig_p` and `resp_p`, and can be extracted from them
+## with :bro:id:`get_port_transport_proto`.
type conn_id: record {
- orig_h: addr;
- orig_p: port;
- resp_h: addr;
- resp_p: port;
+ orig_h: addr; ##< The originator's IP address.
+ orig_p: port; ##< The originator's port number.
+ resp_h: addr; ##< The responder's IP address.
+ resp_p: port; ##< The responder's port number.
} &log;
+## Specifics about an ICMP conversation. ICMP events typically pass this in
+## addition to :bro:type:`conn_id`.
+##
+## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent
+## icmp_time_exceeded icmp_unreachable
type icmp_conn: record {
- orig_h: addr;
- resp_h: addr;
- itype: count;
- icode: count;
- len: count;
-};
-
-type icmp_hdr: record {
- icmp_type: count; ##< type of message
+ orig_h: addr; ##< The originator's IP address.
+ resp_h: addr; ##< The responder's IP address.
+ itype: count; ##< The ICMP type of the packet that triggered the instantiation of the record.
+ icode: count; ##< The ICMP code of the packet that triggered the instantiation of the record.
+ len: count; ##< The length of the ICMP payload of the packet that triggered the instantiation of the record.
};
+## Packet context part of an ICMP message. The fields of this record reflect the
+## packet that is described by the context.
+##
+## .. bro:see:: icmp_time_exceeded icmp_unreachable
type icmp_context: record {
- id: conn_id;
- len: count;
- proto: count;
- frag_offset: count;
+ id: conn_id; ##< The packet's 4-tuple.
+ len: count; ##< The lenght of the packet's IP header.
+ proto: count; ##< The packet's transport-layer protocol.
+ frag_offset: count; ##< The packet's fragementation offset.
+ ## True if the packet's IP header is fully included in the context. If that is not
+ ## the case, the other fields will all be set to null values.
bad_hdr_len: bool;
- bad_checksum: bool;
- MF: bool;
- DF: bool;
+ bad_checksum: bool; ##< True if the packet's IP checksum is not correct.
+ MF: bool; ##< True if the packets *more fragements* flag is set.
+ DF: bool; ##< True if the packets *don't fragment* flag is set.
};
+# A DNS mapping between IP address and hostname resolved by Bro's internal
+# resolver.
+#
+# .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+# dns_mapping_unverified dns_mapping_valid
type dns_mapping: record {
+ ## The time when the mapping was created, which corresponds to the when the DNS
+ ## query was sent out.
creation_time: time;
-
+ ## If the mapping is the result of a name lookup, the queried host name; otherwise
+ ## empty.
req_host: string;
+ ## If the mapping is the result of a pointer lookup, the queried address; otherwise
+ ## null.
req_addr: addr;
-
+ ## True if the lookup returned success. Only then, the result ields are valid.
valid: bool;
+ ## If the mapping is the result of a pointer lookup, the resolved hostname;
+ ## otherwise empty.
hostname: string;
+ ## If the mapping is the result of an address lookup, the resolved address(es);
+ ## otherwise empty.
addrs: addr_set;
};
+## A parsed host/port combination describing server endpoint for an upcoming
+## data transfert.
+##
+## .. bro:see:: fmt_ftp_port parse_eftp_port parse_ftp_epsv parse_ftp_pasv
+## parse_ftp_port
type ftp_port: record {
- h: addr;
- p: port;
- valid: bool; ##< true if format was right
-};
-
-type endpoint: record {
- size: count; ##< logical size (for TCP: from seq numbers)
- state: count;
-
- ## Number of packets on the wire
- ## Set if :bro:id:`use_conn_size_analyzer` is true.
- num_pkts: count &optional;
- ## Number of IP-level bytes on the wire
- ## Set if :bro:id:`use_conn_size_analyzer` is true.
- num_bytes_ip: count &optional;
+ h: addr; ##< The host's address.
+ p: port; ##< The host's port.
+ valid: bool; ##< True if format was right. Only then, *h* and *p* are valid.
};
+## Statistics about what a TCP endpoint sent.
+##
+## .. bro:see:: conn_stats
type endpoint_stats: record {
- num_pkts: count;
- num_rxmit: count;
- num_rxmit_bytes: count;
- num_in_order: count;
- num_OO: count;
- num_repl: count;
+ num_pkts: count; ##< Number of packets.
+ num_rxmit: count; ##< Number of retransmission.
+ num_rxmit_bytes: count; ##< Number of retransmitted bytes.
+ num_in_order: count; ##< Number of in-order packets.
+ num_OO: count; ##< Number out-of-order packets.
+ num_repl: count; ##< Number of replicated packets (last packet was sent again).
+ ## Endian type used by the endpoint, if it it could be determined from the sequence
+ ## numbers used. This is one of :bro:see:`ENDIAN_UNKNOWN`, :bro:see:`ENDIAN_BIG`,
+ ## :bro:see:`ENDIAN_LITTLE`, and :bro:see:`ENDIAN_CONFUSED`.
endian_type: count;
};
+## A unique analyzer instance ID. Each time instantiates a protocol analyzers
+## for a connection, it assigns it a unique ID that can be used to reference
+## that instance.
+##
+## .. bro:see:: analyzer_name disable_analyzer protocol_confirmation
+## protocol_violation
+##
+## .. todo::While we declare an alias for the type here, the events/functions still
+## use ``count``. That should be changed.
type AnalyzerID: count;
+## Statistics about an endpoint.
+##
+## todo::Where is this used?
+type endpoint: record {
+ size: count; ##< Logical size of data sent (for TCP: derived from sequence numbers).
+ ## Endpoint state. For TCP connection, one of the constants:
+ ## :bro:see:`TCP_INACTIVE` :bro:see:`TCP_SYN_SENT` :bro:see:`TCP_SYN_ACK_SENT`
+ ## :bro:see:`TCP_PARTIAL` :bro:see:`TCP_ESTABLISHED` :bro:see:`TCP_CLOSED`
+ ## :bro:see:`TCP_RESET`. For UDP, one of :bro:see:`UDP_ACTIVE` and
+ ## :bro:see:`UDP_INACTIVE`.
+ state: count;
+ ## Number of packets sent. Only set if :bro:id:`use_conn_size_analyzer` is true.
+ num_pkts: count &optional;
+ ## Number of IP-level bytes sent. Only set if :bro:id:`use_conn_size_analyzer` is
+ ## true.
+ num_bytes_ip: count &optional;
+};
+
+# A connection. This is Bro's basic connection type describing IP- and
+# transport-layer information about the conversation. Note that Bro uses a
+# liberal interpreation of "connection" and associates instances of this type
+# also with UDP and ICMP flows.
type connection: record {
- id: conn_id;
- orig: endpoint;
- resp: endpoint;
- start_time: time;
+ id: conn_id; ##< The connection's identifying 4-tuple.
+ orig: endpoint; ##< Statistics about originator side.
+ resp: endpoint; ##< Statistics about responder side.
+ start_time: time; ##< The timestamp of the connection's first packet.
+ ## The duration of the conversation. Roughly speaking, this is the interval between
+ ## first and last data packet (low-level TCP details may adjust it somewhat in
+ ## ambigious cases).
duration: interval;
- service: string_set; ##< if empty, service hasn't been determined
- addl: string;
- hot: count; ##< how hot; 0 = don't know or not hot
- history: string;
+ ## The set of services the connection is using as determined by Bro's dynamic
+ ## protocol detection. Each entry is the label of an analyzer that confirmed that
+ ## it could parse the connection payload. While typically, there will be at
+ ## most one entry for each connection, in principle it is possible that more than
+ ## one protocol analyzer is able to parse the same data. If so, all will
+ ## be recorded. Also note that the recorced services are independent of any
+ ## transport-level protocols.
+ service: set[string];
+ addl: string; ##< Deprecated.
+ hot: count; ##< Deprecated.
+ history: string; ##< State history of TCP connections. See *history* in :bro:see:`Conn::Info`.
+ ## A globally unique connection identifier. For each connection, Bro creates an ID
+ ## that is very likely unique across independent Bro runs. These IDs can thus be
+ ## used to tag and locate information associated with that connection.
uid: string;
};
+## Fields of a SYN packet.
+##
+## .. bro:see:: connection_SYN_packet
type SYN_packet: record {
- is_orig: bool;
- DF: bool;
- ttl: count;
- size: count;
- win_size: count;
- win_scale: int;
- MSS: count;
- SACK_OK: bool;
+ is_orig: bool; ##< True if the packet was sent the connection's originator.
+ DF: bool; ##< True if the *don't fragment* is set in the IP header.
+ ttl: count; ##< The IP header's time-to-live.
+ size: count; ##< The size of the packet's payload as specified in the IP header.
+ win_size: count; ##< The window size from the TCP header.
+ win_scale: int; ##< The window scale option if present, or -1 if not.
+ MSS: count; ##< The maximum segement size if present, or 0 if not.
+ SACK_OK: bool; ##< True if the *SACK* option is present.
};
-## This record is used for grabbing packet capturing information from
-## the core with the :bro:id:`net_stats` BiF. All counts are cumulative.
+## Packet capture statistics. All counts are cumulative.
+##
+## .. bro:see:: net_stats
type NetStats: record {
- pkts_recvd: count &default=0; ##< Packets received by Bro.
- pkts_dropped: count &default=0; ##< Packets dropped.
- pkts_link: count &default=0; ##< Packets seen on the link (not always available).
+ pkts_recvd: count &default=0; ##< Packets received by Bro.
+ pkts_dropped: count &default=0; ##< Packets reported dropped by the system.
+ ## Packets seen on the link. Note that this may differ
+ ## from *pkts_recvd* because of a potential capture_filter. See
+ ## :doc:`/scripts/base/frameworks/packet-filter/main`. Depending on the packet
+ ## capture system, this value may not be available and will then be always set to
+ ## zero.
+ pkts_link: count &default=0;
};
+## Statistics about Bro's resource consumption.
+##
+## .. bro:see:: resource_usage
+##
+## .. note:: All process-level values refer to Bro's main process only, not to
+## the child process it spawns for doing communication.
type bro_resources: record {
- version: string; ##< Bro version string
- debug: bool; ##< true if compiled with --enable-debug
- start_time: time; ##< start time of process
- real_time: interval; ##< elapsed real time since Bro started running
- user_time: interval; ##< user CPU seconds
- system_time: interval; ##< system CPU seconds
- mem: count; ##< maximum memory consumed, in KB
- minor_faults: count; ##< page faults not requiring actual I/O
- major_faults: count; ##< page faults requiring actual I/O
- num_swap: count; ##< times swapped out
- blocking_input: count; ##< blocking input operations
- blocking_output: count; ##< blocking output operations
- num_context: count; ##< number of involuntary context switches
+ version: string; ##< Bro version string.
+ debug: bool; ##< True if compiled with --enable-debug.
+ start_time: time; ##< Start time of process.
+ real_time: interval; ##< Elapsed real time since Bro started running.
+ user_time: interval; ##< User CPU seconds.
+ system_time: interval; ##< System CPU seconds.
+ mem: count; ##< Maximum memory consumed, in KB.
+ minor_faults: count; ##< Page faults not requiring actual I/O.
+ major_faults: count; ##< Page faults requiring actual I/O.
+ num_swap: count; ##< Times swapped out.
+ blocking_input: count; ##< Blocking input operations.
+ blocking_output: count; ##< Blocking output operations.
+ num_context: count; ##< Number of involuntary context switches.
- num_TCP_conns: count; ##< current number of TCP connections
- num_UDP_conns: count;
- num_ICMP_conns: count;
- num_fragments: count; ##< current number of fragments pending reassembly
- num_packets: count; ##< total number packets processed to date
- num_timers: count; ##< current number of pending timers
- num_events_queued: count; ##< total number of events queued so far
- num_events_dispatched: count; ##< same for events dispatched
+ num_TCP_conns: count; ##< Current number of TCP connections in memory.
+ num_UDP_conns: count; ##< Current number of UDP flows in memory.
+ num_ICMP_conns: count; ##< Current number of ICMP flows in memory.
+ num_fragments: count; ##< Current number of fragments pending reassembly.
+ num_packets: count; ##< Total number packets processed to date.
+ num_timers: count; ##< Current number of pending timers.
+ num_events_queued: count; ##< Total number of events queued so far.
+ num_events_dispatched: count; ##< Total number of events dispatched so far.
- max_TCP_conns: count; ##< maximum number of TCP connections, etc.
- max_UDP_conns: count;
- max_ICMP_conns: count;
- max_fragments: count;
- max_timers: count;
+ max_TCP_conns: count; ##< Maximum number of concurrent TCP connections so far.
+ max_UDP_conns: count; ##< Maximum number of concurrent UDP connections so far.
+ max_ICMP_conns: count; ##< Maximum number of concurrent ICMP connections so far.
+ max_fragments: count; ##< Maximum number of concurrently buffered fragements so far.
+ max_timers: count; ##< Maximum number of concurrent timers pending so far.
};
-
-## Summary statistics of all DFA_State_Caches.
+## Summary statistics of all regular expression matchers.
+##
+## .. bro:see:: get_matcher_stats
type matcher_stats: record {
- matchers: count; ##< number of distinct RE matchers
- dfa_states: count; ##< number of DFA states across all matchers
- computed: count; ##< number of computed DFA state transitions
- mem: count; ##< number of bytes used by DFA states
- hits: count; ##< number of cache hits
- misses: count; ##< number of cache misses
- avg_nfa_states: count; ##< average # NFA states across all matchers
+ matchers: count; ##< Number of distinct RE matchers.
+ dfa_states: count; ##< Number of DFA states across all matchers.
+ computed: count; ##< Number of computed DFA state transitions.
+ mem: count; ##< Number of bytes used by DFA states.
+ hits: count; ##< Number of cache hits.
+ misses: count; ##< Number of cache misses.
+ avg_nfa_states: count; ##< Average number of NFA states across all matchers.
};
-## Info provided to gap_report, and also available by get_gap_summary().
+## Statistics about number of gaps in TCP connections.
+##
+## .. bro:see:: gap_report get_gap_summary
type gap_info: record {
- ack_events: count; ##< how many ack events *could* have had gaps
- ack_bytes: count; ##< how many bytes those covered
- gap_events: count; ##< how many *did* have gaps
- gap_bytes: count; ##< how many bytes were missing in the gaps:
+ ack_events: count; ##< How many ack events *could* have had gaps.
+ ack_bytes: count; ##< How many bytes those covered.
+ gap_events: count; ##< How many *did* have gaps.
+ gap_bytes: count; ##< How many bytes were missing in the gaps.
};
-# This record should be read-only.
+## Deprecated.
+##
+## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere
+## else.
type packet: record {
conn: connection;
is_orig: bool;
@@ -175,38 +314,92 @@ type packet: record {
timestamp: time;
};
-type var_sizes: table[string] of count; ##< indexed by var's name, returns size
+## Table type used to map variable names to their memory allocation.
+##
+## .. bro:see:: global_sizes
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
+type var_sizes: table[string] of count;
+## Meta-information about a script-level identifier.
+##
+## .. bro:see:: global_ids id_table
type script_id: record {
- type_name: string;
- exported: bool;
- constant: bool;
- enum_constant: bool;
- redefinable: bool;
- value: any &optional;
+ type_name: string; ##< The name of the identifier's type.
+ exported: bool; ##< True if the identifier is exported.
+ constant: bool; ##< True if the identifier is a constant.
+ enum_constant: bool; ##< True if the identifier is an enum value.
+ redefinable: bool; ##< True if the identifier is declared with the :bro:attr:`&redef` attribute.
+ value: any &optional; ##< The current value of the identifier.
};
+## Table type used to map script-level identifiers to meta-information
+## describing them.
+##
+## .. bro:see:: global_ids script_id
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type id_table: table[string] of script_id;
+## Meta-information about a record-field.
+##
+## .. bro:see:: record_fields record_field_table
type record_field: record {
- type_name: string;
- log: bool;
+ type_name: string; ##< The name of the field's type.
+ log: bool; ##< True of the field is declared with :bro:attr:`&log` attribute.
+ ## The current value of the field in the record instance passed into
+ ## :bro:see:`record_fields` (if it has one).
value: any &optional;
- default_val: any &optional;
+ default_val: any &optional; ##< The value of the :bro:attr:`&default` attribute if defined.
};
+## Table type used to map record field declarations to meta-information describing
+## them.
+##
+## .. bro:see:: record_fields record_field
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type record_field_table: table[string] of record_field;
+# todo::Do we still needs these here? Can they move into the packet filter
+# framework?
+#
# The following two variables are defined here until the core is not
# dependent on the names remaining as they are now.
-## This is the list of capture filters indexed by some user-definable ID.
+
+## Set of BPF capture filters to use for capturing, indexed by a user-definable
+## ID (which must be unique). If Bro is *not* configured to examine
+## :bro:id:`PacketFilter::all_packets`, all packets matching at least
+## one of the filters in this table (and all in :bro:id:`restrict_filters`)
+## will be analyzed.
+##
+## .. bro:see:: PacketFilter PacketFilter::all_packets
+## PacketFilter::unrestricted_filter restrict_filters
global capture_filters: table[string] of string &redef;
-## This is the list of restriction filters indexed by some user-definable ID.
+
+## Set of BPF filters to restrict capturing, indexed by a user-definable ID (which
+## must be unique). If Bro is *not* configured to examine
+## :bro:id:`PacketFilter::all_packets`, only packets matching *all* of the
+## filters in this table (and any in :bro:id:`capture_filters`) will be
+## analyzed.
+##
+## .. bro:see:: PacketFilter PacketFilter::all_packets
+## PacketFilter::unrestricted_filter capture_filters
global restrict_filters: table[string] of string &redef;
-# {precompile,install}_pcap_filter identify the filter by IDs
+## Enum type identifying dynamic BPF filters. These are used by
+## :bro:see:`precompile_pcap_filter` and :bro:see:`precompile_pcap_filter`.
type PcapFilterID: enum { None };
+## Deprecated.
+##
+## .. bro:see:: anonymize_addr
type IPAddrAnonymization: enum {
KEEP_ORIG_ADDR,
SEQUENTIALLY_NUMBERED,
@@ -215,34 +408,54 @@ type IPAddrAnonymization: enum {
PREFIX_PRESERVING_MD5,
};
+## Deprecated.
+##
+## .. bro:see:: anonymize_addr
type IPAddrAnonymizationClass: enum {
- ORIG_ADDR, ##< client address
- RESP_ADDR, ##< server address
+ ORIG_ADDR,
+ RESP_ADDR,
OTHER_ADDR,
};
-
-## Events are generated by event_peer's (which may be either ourselves, or
-## some remote process).
+## A locally unique ID identifying a communication peer. The ID is returned by
+## :bro:id:`connect`.
+##
+## .. bro:see:: connect Communication
type peer_id: count;
+## A communication peer.
+##
+## .. bro:see:: complete_handshake disconnect finished_send_state
+## get_event_peer get_local_event_peer remote_capture_filter
+## remote_connection_closed remote_connection_error
+## remote_connection_established remote_connection_handshake_done
+## remote_event_registered remote_log_peer remote_pong
+## request_remote_events request_remote_logs request_remote_sync
+## send_capture_filter send_current_packet send_id send_ping send_state
+## set_accept_state set_compression_level
+##
+## .. todo::The type's name is to narrow these days, should rename.
type event_peer: record {
- id: peer_id; ##< locally unique ID of peer (returned by connect())
- host: addr;
+ id: peer_id; ##< Locally unique ID of peer (returned by :bro:id:`connect`).
+ host: addr; ##< The IP address of the peer.
+ ## Either the port we connected to at the peer; or our port the peer
+ ## connected to if the session is remotely initiated.
p: port;
- is_local: bool; ##< true if this peer describes the current process.
- descr: string; ##< source's external_source_description
- class: string &optional; # self-assigned class of the peer
+ is_local: bool; ##< True if this record describes the local process.
+ descr: string; ##< The peer's :bro:see:`peer_description`.
+ class: string &optional; ##< The self-assigned *class* of the peer. See :bro:see:`Communication::Node`.
};
+## Deprecated.
+##
+## .. bro:see:: rotate_file rotate_file_by_name rotate_interval
type rotate_info: record {
- old_name: string; ##< original filename
- new_name: string; ##< file name after rotation
- open: time; ##< time when opened
- close: time; ##< time when closed
+ old_name: string; ##< Original filename.
+ new_name: string; ##< File name after rotation.
+ open: time; ##< Time when opened.
+ close: time; ##< Time when closed.
};
-
### The following aren't presently used, though they should be.
# # Structures needed for subsequence computations (str_smith_waterman):
# #
@@ -251,6 +464,9 @@ type rotate_info: record {
# SW_MULTIPLE,
# };
+## Paramerts for the Smith-Waterman algorithm.
+##
+## .. bro:see:: str_smith_waterman
type sw_params: record {
## Minimum size of a substring, minimum "granularity".
min_strlen: count &default = 3;
@@ -259,45 +475,73 @@ type sw_params: record {
sw_variant: count &default = 0;
};
+## Helper type for return value of Smith-Waterman algorithm.
+##
+## .. bro:see:: str_smith_waterman sw_substring_vec sw_substring sw_align_vec sw_params
type sw_align: record {
- str: string; ##< string a substring is part of
- index: count; ##< at which offset
+ str: string; ##< String a substring is part of.
+ index: count; ##< Offset substring is located.
};
+## Helper type for return value of Smith-Waterman algorithm.
+##
+## .. bro:see:: str_smith_waterman sw_substring_vec sw_substring sw_align sw_params
type sw_align_vec: vector of sw_align;
+## Helper type for return value of Smith-Waterman algorithm.
+##
+## .. bro:see:: str_smith_waterman sw_substring_vec sw_align_vec sw_align sw_params
+##
type sw_substring: record {
- str: string; ##< a substring
- aligns: sw_align_vec; ##< all strings of which it's a substring
- new: bool; ##< true if start of new alignment
+ str: string; ##< A substring.
+ aligns: sw_align_vec; ##< All strings of which it's a substring.
+ new: bool; ##< True if start of new alignment.
};
+## Return type for Smith-Waterman algorithm.
+##
+## .. bro:see:: str_smith_waterman sw_substring sw_align_vec sw_align sw_params
+##
+## .. todo:: We need this type definition only for declaring builtin functions via
+## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
+## then remove this alias.
type sw_substring_vec: vector of sw_substring;
-## Policy-level handling of pcap packets.
+## Policy-level representation of a packet passed on by libpcap. The data includes
+## the complete packet as returned by libpcap, including the link-layer header.
+##
+## .. bro:see:: dump_packet get_current_packet
type pcap_packet: record {
- ts_sec: count;
- ts_usec: count;
- caplen: count;
- len: count;
- data: string;
+ ts_sec: count; ##< The non-fractional part of the packet's timestamp (i.e., full seconds since the epoch).
+ ts_usec: count; ##< The fractional part of the packet's timestamp.
+ caplen: count; ##< The number of bytes captured (<= *len*).
+ len: count; ##< The length of the packet in bytes, including `_ for more information, Bro uses the same
+## code.
+##
+## .. bro:see:: entropy_test_add entropy_test_finish entropy_test_init find_entropy
type entropy_test_result: record {
- entropy: double;
- chi_square: double;
- mean: double;
- monte_carlo_pi: double;
- serial_correlation: double;
+ entropy: double; ##< Information density.
+ chi_square: double; ##< Chi-Square value.
+ mean: double; ##< Arithmetic Mean.
+ monte_carlo_pi: double; ##< Monte-carlo value for pi.
+ serial_correlation: double; ##< Serial correlation coefficient.
};
# Prototypes of Bro built-in functions.
@@ -305,13 +549,19 @@ type entropy_test_result: record {
@load base/bro.bif
@load base/reporter.bif
+## Deprecated. This is superseded by the new logging framework.
global log_file_name: function(tag: string): string &redef;
+
+## Deprecated. This is superseded by the new logging framework.
global open_log_file: function(tag: string): file &redef;
-## Where to store the persistent state.
+## Specifies a directory for Bro store its persistent state. All globals can
+## be declared persistent via the :bro:attr:`&persistent` attribute.
const state_dir = ".state" &redef;
-## Length of the delays added when storing state incrementally.
+## Length of the delays inserted when storing state incrementally. To avoid
+## dropping packets when serializing larger volumes of persistent state to
+## disk, Bro interleaves the operation with continued packet processing.
const state_write_delay = 0.01 secs &redef;
global done_with_network = F;
@@ -328,6 +578,7 @@ function open_log_file(tag: string): file
return open(log_file_name(tag));
}
+## Internal function.
function add_interface(iold: string, inew: string): string
{
if ( iold == "" )
@@ -335,8 +586,12 @@ function add_interface(iold: string, inew: string): string
else
return fmt("%s %s", iold, inew);
}
+
+## Network interfaces to listen on. Use ``redef interfaces += "eth0"`` to
+## extend.
global interfaces = "" &add_func = add_interface;
+## Internal function.
function add_signature_file(sold: string, snew: string): string
{
if ( sold == "" )
@@ -344,11 +599,15 @@ function add_signature_file(sold: string, snew: string): string
else
return cat(sold, " ", snew);
}
+
+## Signature files to read. Use ``redef signature_files += "foo.sig"`` to
+## extend. Signature files will be searched relative to ``BRO_PATH``.
global signature_files = "" &add_func = add_signature_file;
+## ``p0f`` fingerprint file to use. Will be searched relative to ``BRO_PATH``.
const passive_fingerprint_file = "base/misc/p0f.fp" &redef;
-# TODO: testing to see if I can remove these without causing problems.
+# todo::testing to see if I can remove these without causing problems.
#const ftp = 21/tcp;
#const ssh = 22/tcp;
#const telnet = 23/tcp;
@@ -361,17 +620,24 @@ const passive_fingerprint_file = "base/misc/p0f.fp" &redef;
#const bgp = 179/tcp;
#const rlogin = 513/tcp;
-const TCP_INACTIVE = 0;
-const TCP_SYN_SENT = 1;
-const TCP_SYN_ACK_SENT = 2;
-const TCP_PARTIAL = 3;
-const TCP_ESTABLISHED = 4;
-const TCP_CLOSED = 5;
-const TCP_RESET = 6;
+# TCP values for :bro:see:`endpoint` *state* field.
+# todo::these should go into an enum to make them autodoc'able.
+const TCP_INACTIVE = 0; ##< Endpoint is still inactive.
+const TCP_SYN_SENT = 1; ##< Endpoint has sent SYN.
+const TCP_SYN_ACK_SENT = 2; ##< Endpoint has sent SYN/ACK.
+const TCP_PARTIAL = 3; ##< Endpoint has sent data but no initial SYN.
+const TCP_ESTABLISHED = 4; ##< Endpoint has finished initial handshake regularly.
+const TCP_CLOSED = 5; ##< Endpoint has closed connection.
+const TCP_RESET = 6; ##< Endpoint has sent RST.
+
+# UDP values for :bro:see:`endpoint` *state* field.
+# todo::these should go into an enum to make them autodoc'able.
+const UDP_INACTIVE = 0; ##< Endpoint is still inactive.
+const UDP_ACTIVE = 1; ##< Endpoint has sent something.
## If true, don't verify checksums. Useful for running on altered trace
-## files, and for saving a few cycles, but of course dangerous, too ...
-## Note that the -C command-line option overrides the setting of this
+## files, and for saving a few cycles, but at the risk of analyzing invalid
+## data. Note that the ``-C`` command-line option overrides the setting of this
## variable.
const ignore_checksums = F &redef;
@@ -379,13 +645,13 @@ const ignore_checksums = F &redef;
## (one missing its initial establishment negotiation) is seen.
const partial_connection_ok = T &redef;
-## If true, instantiate connection state when a SYN ack is seen
-## but not the initial SYN (even if partial_connection_ok is false).
+## If true, instantiate connection state when a SYN/ACK is seen but not the initial
+## SYN (even if :bro:see:`partial_connection_ok` is false).
const tcp_SYN_ack_ok = T &redef;
-## If a connection state is removed there may still be some undelivered
-## data waiting in the reassembler. If true, pass this to the signature
-## engine before flushing the state.
+## If true, pass any undelivered to the signature engine before flushing the state.
+## If a connection state is removed, there may still be some data waiting in the
+## reassembler.
const tcp_match_undelivered = T &redef;
## Check up on the result of an initial SYN after this much time.
@@ -416,33 +682,55 @@ const tcp_reset_delay = 5 secs &redef;
const tcp_partial_close_delay = 3 secs &redef;
## If a connection belongs to an application that we don't analyze,
-## time it out after this interval. If 0 secs, then don't time it out.
+## time it out after this interval. If 0 secs, then don't time it out (but
+## :bro:see:`tcp_inactivity_timeout`/:bro:see:`udp_inactivity_timeout`/:bro:see:`icmp_inactivity_timeout`
+## still apply).
const non_analyzed_lifetime = 0 secs &redef;
-## If a connection is inactive, time it out after this interval.
-## If 0 secs, then don't time it out.
+## If a TCP connection is inactive, time it out after this interval. If 0 secs,
+## then don't time it out.
+##
+## .. bro:see:: udp_inactivity_timeout icmp_inactivity_timeout set_inactivity_timeout
const tcp_inactivity_timeout = 5 min &redef;
-## See :bro:id:`tcp_inactivity_timeout`
+
+## If a UDP flow is inactive, time it out after this interval. If 0 secs, then
+## don't time it out.
+##
+## .. bro:see:: tcp_inactivity_timeout icmp_inactivity_timeout set_inactivity_timeout
const udp_inactivity_timeout = 1 min &redef;
-## See :bro:id:`tcp_inactivity_timeout`
+
+## If an ICMP flow is inactive, time it out after this interval. If 0 secs, then
+## don't time it out.
+##
+## .. bro:see:: tcp_inactivity_timeout udp_inactivity_timeout set_inactivity_timeout
const icmp_inactivity_timeout = 1 min &redef;
-## This many FINs/RSTs in a row constitutes a "storm".
+## Number of FINs/RSTs in a row that constitute a "storm". Storms are reported via
+## as ``weird`` via the notice framework, and they must also come within
+## intervals of at most :bro:see:`tcp_storm_interarrival_thresh`.
+##
+## .. bro:see:: tcp_storm_interarrival_thresh
const tcp_storm_thresh = 1000 &redef;
-## The FINs/RSTs must come with this much time or less between them.
+## FINs/RSTs must come with this much time or less between them to be
+## considered a "storm".
+##
+## .. bro:see:: tcp_storm_thresh
const tcp_storm_interarrival_thresh = 1 sec &redef;
-## Maximum amount of data that might plausibly be sent in an initial
-## flight (prior to receiving any acks). Used to determine whether we
-## must not be seeing our peer's acks. Set to zero to turn off this
-## determination.
+## Maximum amount of data that might plausibly be sent in an initial flight (prior
+## to receiving any acks). Used to determine whether we must not be seeing our
+## peer's ACKs. Set to zero to turn off this determination.
+##
+## .. bro:see:: tcp_max_above_hole_without_any_acks tcp_excessive_data_without_further_acks
const tcp_max_initial_window = 4096;
-## If we're not seeing our peer's acks, the maximum volume of data above
-## a sequence hole that we'll tolerate before assuming that there's
-## been a packet drop and we should give up on tracking a connection.
-## If set to zero, then we don't ever give up.
+## If we're not seeing our peer's ACKs, the maximum volume of data above a sequence
+## hole that we'll tolerate before assuming that there's been a packet drop and we
+## should give up on tracking a connection. If set to zero, then we don't ever give
+## up.
+##
+## .. bro:see:: tcp_max_initial_window tcp_excessive_data_without_further_acks
const tcp_max_above_hole_without_any_acks = 4096;
## If we've seen this much data without any of it being acked, we give up
@@ -450,87 +738,160 @@ const tcp_max_above_hole_without_any_acks = 4096;
## stuff. If set to zero, then we don't ever give up. Ideally, Bro would
## track the current window on a connection and use it to infer that data
## has in fact gone too far, but for now we just make this quite beefy.
+##
+## .. bro:see:: tcp_max_initial_window tcp_max_above_hole_without_any_acks
const tcp_excessive_data_without_further_acks = 10 * 1024 * 1024;
-## For services without a handler, these sets define which
-## side of a connection is to be reassembled.
+## For services without an a handler, these sets define originator-side ports that
+## still trigger reassembly.
+##
+## .. :bro:see:: tcp_reassembler_ports_resp
const tcp_reassembler_ports_orig: set[port] = {} &redef;
-## See :bro:id:`tcp_reassembler_ports_orig`
+
+## For services without an a handler, these sets define responder-side ports that
+## still trigger reassembly.
+##
+## .. :bro:see:: tcp_reassembler_ports_orig
const tcp_reassembler_ports_resp: set[port] = {} &redef;
-## These sets define destination ports for which the contents
-## of the originator (responder, respectively) stream should
-## be delivered via tcp_contents.
+## Defines destination TCP ports for which the contents of the originator stream
+## should be delivered via :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_resp tcp_content_deliver_all_orig
+## tcp_content_deliver_all_resp udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_content_deliver_all_resp tcp_contents
const tcp_content_delivery_ports_orig: table[port] of bool = {} &redef;
-## See :bro:id:`tcp_content_delivery_ports_orig`
+
+## Defines destination TCP ports for which the contents of the responder stream should
+## be delivered via :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig tcp_content_deliver_all_orig
+## tcp_content_deliver_all_resp udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_content_deliver_all_resp tcp_contents
const tcp_content_delivery_ports_resp: table[port] of bool = {} &redef;
-# To have all TCP orig->resp/resp->orig traffic reported via tcp_contents,
-# redef these to T.
+## If true, all TCP originator-side traffic is reported via
+## :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp
+## tcp_content_deliver_all_resp udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_content_deliver_all_resp tcp_contents
const tcp_content_deliver_all_orig = F &redef;
-## See :bro:id:`tcp_content_deliver_all_orig`
+
+## If true, all TCP responder-side traffic is reported via
+## :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig
+## tcp_content_delivery_ports_resp
+## tcp_content_deliver_all_orig udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_content_deliver_all_resp tcp_contents
const tcp_content_deliver_all_resp = F &redef;
-## These sets define destination ports for which the contents
-## of the originator (responder, respectively) stream should
-## be delivered via udp_contents.
+## Defines UDP destination ports for which the contents of the originator stream
+## should be delivered via :bro:see:`udp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig
+## tcp_content_delivery_ports_resp
+## tcp_content_deliver_all_orig tcp_content_deliver_all_resp
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_content_deliver_all_resp udp_contents
const udp_content_delivery_ports_orig: table[port] of bool = {} &redef;
-## See :bro:id:`udp_content_delivery_ports_orig`
+
+## Defines UDP destination ports for which the contents of the originator stream
+## should be delivered via :bro:see:`udp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig
+## tcp_content_delivery_ports_resp tcp_content_deliver_all_orig
+## tcp_content_deliver_all_resp udp_content_delivery_ports_orig
+## udp_content_deliver_all_orig udp_content_deliver_all_resp udp_contents
const udp_content_delivery_ports_resp: table[port] of bool = {} &redef;
-## To have all UDP orig->resp/resp->orig traffic reported via udp_contents,
-## redef these to T.
+## If true, all UDP originator-side traffic is reported via
+## :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig
+## tcp_content_delivery_ports_resp tcp_content_deliver_all_resp
+## tcp_content_delivery_ports_orig udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_resp
+## udp_contents
const udp_content_deliver_all_orig = F &redef;
-## See :bro:id:`udp_content_deliver_all_orig`
+
+## If true, all UDP responder-side traffic is reported via
+## :bro:see:`tcp_contents`.
+##
+## .. bro:see:: tcp_content_delivery_ports_orig
+## tcp_content_delivery_ports_resp tcp_content_deliver_all_resp
+## tcp_content_delivery_ports_orig udp_content_delivery_ports_orig
+## udp_content_delivery_ports_resp udp_content_deliver_all_orig
+## udp_contents
const udp_content_deliver_all_resp = F &redef;
-## Check for expired table entries after this amount of time
+## Check for expired table entries after this amount of time.
+##
+## .. bro:see:: table_incremental_step table_expire_delay
const table_expire_interval = 10 secs &redef;
-## When expiring/serializing, don't work on more than this many table
-## entries at a time.
+## When expiring/serializing table entries, don't work on more than this many table
+## at a time.
+##
+## .. bro:see:: table_expire_interval table_expire_delay
const table_incremental_step = 5000 &redef;
-## When expiring, wait this amount of time before checking the next chunk
-## of entries.
+## When expiring table entries, wait this amount of time before checking the next
+## chunk of entries.
+##
+## .. :bro:see:: table_expire_interval table_incremental_step
const table_expire_delay = 0.01 secs &redef;
## Time to wait before timing out a DNS request.
const dns_session_timeout = 10 sec &redef;
-## Time to wait before timing out a NTP request.
+
+## Time to wait before timing out an NTP request.
const ntp_session_timeout = 300 sec &redef;
-## Time to wait before timing out a RPC request.
+
+## Time to wait before timing out an RPC request.
const rpc_timeout = 24 sec &redef;
-## Time window for reordering packets (to deal with timestamp
-## discrepency between multiple packet sources).
-const packet_sort_window = 0 usecs &redef;
-
-## How long to hold onto fragments for possible reassembly. A value
-## of 0.0 means "forever", which resists evasion, but can lead to
-## state accrual.
+## How long to hold onto fragments for possible reassembly. A value of 0.0 means
+## "forever", which resists evasion, but can lead to state accrual.
const frag_timeout = 0.0 sec &redef;
+## Time window for reordering packets. This is used for dealing with timestamp
+## discrepency between multiple packet sources.
+##
+## .. note:: Setting this can have a major performance impact as now packets need
+## to be potentially copied and buffered.
+const packet_sort_window = 0 usecs &redef;
+
## If positive, indicates the encapsulation header size that should
-## be skipped over for each captured packet ....
+## be skipped. This either applies to all packets, or if
+## :bro:see:`tunnel_port` is set, only to packets on that port.
+##
+## .. :bro:see:: tunnel_port
const encap_hdr_size = 0 &redef;
-## ... or just for the following UDP port.
+
+## A UDP port that specifies which connections to apply :bro:see:`encap_hdr_size`
+## to.
+##
+## .. :bro:see:: encap_hdr_size
const tunnel_port = 0/udp &redef;
-## Whether to use the ConnSize analyzer to count the number of
-## packets and IP-level bytes transfered by each endpoint. If
-## true, these values are returned in the connection's endpoint
-## record val.
+## Whether to use the ``ConnSize`` analyzer to count the number of packets and
+## IP-level bytes transfered by each endpoint. If true, these values are returned
+## in the connection's :bro:see:`endpoint` record value.
const use_conn_size_analyzer = T &redef;
-const UDP_INACTIVE = 0;
-const UDP_ACTIVE = 1; # means we've seen something from this endpoint
-
-const ENDIAN_UNKNOWN = 0;
-const ENDIAN_LITTLE = 1;
-const ENDIAN_BIG = 2;
-const ENDIAN_CONFUSED = 3;
+# todo::these should go into an enum to make them autodoc'able.
+const ENDIAN_UNKNOWN = 0; ##< Endian not yet determined.
+const ENDIAN_LITTLE = 1; ##< Little endian.
+const ENDIAN_BIG = 2; ##< Big endian.
+const ENDIAN_CONFUSED = 3; ##< Tried to determine endian, but failed.
+## Deprecated.
function append_addl(c: connection, addl: string)
{
if ( c$addl == "" )
@@ -540,6 +901,7 @@ function append_addl(c: connection, addl: string)
c$addl = fmt("%s %s", c$addl, addl);
}
+## Deprecated.
function append_addl_marker(c: connection, addl: string, marker: string)
{
if ( c$addl == "" )
@@ -550,54 +912,65 @@ function append_addl_marker(c: connection, addl: string, marker: string)
}
-# Values for set_contents_file's "direction" argument.
-# TODO: these should go into an enum to make them autodoc'able
-const CONTENTS_NONE = 0; # turn off recording of contents
-const CONTENTS_ORIG = 1; # record originator contents
-const CONTENTS_RESP = 2; # record responder contents
-const CONTENTS_BOTH = 3; # record both originator and responder contents
-
-const ICMP_UNREACH_NET = 0;
-const ICMP_UNREACH_HOST = 1;
-const ICMP_UNREACH_PROTOCOL = 2;
-const ICMP_UNREACH_PORT = 3;
-const ICMP_UNREACH_NEEDFRAG = 4;
-const ICMP_UNREACH_ADMIN_PROHIB = 13;
-# The above list isn't exhaustive ...
+# Values for :bro:see:`set_contents_file` *direction* argument.
+# todo::these should go into an enum to make them autodoc'able
+const CONTENTS_NONE = 0; ##< Turn off recording of contents.
+const CONTENTS_ORIG = 1; ##< Record originator contents.
+const CONTENTS_RESP = 2; ##< Record responder contents.
+const CONTENTS_BOTH = 3; ##< Record both originator and responder contents.
+# Values for code of ICMP *unreachable* messages. The list is not exhaustive.
+# todo::these should go into an enum to make them autodoc'able
+#
+# .. bro:see:: :bro:see:`icmp_unreachable `
+const ICMP_UNREACH_NET = 0; ##< Network unreachable.
+const ICMP_UNREACH_HOST = 1; ##< Host unreachable.
+const ICMP_UNREACH_PROTOCOL = 2; ##< Protocol unreachable.
+const ICMP_UNREACH_PORT = 3; ##< Port unreachable.
+const ICMP_UNREACH_NEEDFRAG = 4; ##< Fragement needed.
+const ICMP_UNREACH_ADMIN_PROHIB = 13; ##< Adminstratively prohibited.
# Definitions for access to packet headers. Currently only used for
# discarders.
-const IPPROTO_IP = 0; # dummy for IP
-const IPPROTO_ICMP = 1; # control message protocol
-const IPPROTO_IGMP = 2; # group mgmt protocol
-const IPPROTO_IPIP = 4; # IP encapsulation in IP
-const IPPROTO_TCP = 6; # TCP
-const IPPROTO_UDP = 17; # user datagram protocol
-const IPPROTO_RAW = 255; # raw IP packet
+# todo::these should go into an enum to make them autodoc'able
+const IPPROTO_IP = 0; ##< Dummy for IP.
+const IPPROTO_ICMP = 1; ##< Control message protocol.
+const IPPROTO_IGMP = 2; ##< Group management protocol.
+const IPPROTO_IPIP = 4; ##< IP encapsulation in IP.
+const IPPROTO_TCP = 6; ##< TCP.
+const IPPROTO_UDP = 17; ##< User datagram protocol.
+const IPPROTO_RAW = 255; ##< Raw IP packet.
+## Values extracted from an IP header.
+##
+## .. bro:see:: pkt_hdr discarder_check_ip
type ip_hdr: record {
- hl: count; ##< header length (in bytes)
- tos: count; ##< type of service
- len: count; ##< total length
- id: count; ##< identification
- ttl: count; ##< time to live
- p: count; ##< protocol
- src: addr; ##< source address
- dst: addr; ##< dest address
+ hl: count; ##< Header length in bytes.
+ tos: count; ##< Type of service.
+ len: count; ##< Total length.
+ id: count; ##< Identification.
+ ttl: count; ##< Time to live.
+ p: count; ##< Protocol.
+ src: addr; ##< Source address.
+ dst: addr; ##< Destination address.
};
-## TCP flags.
-const TH_FIN = 1;
-const TH_SYN = 2;
-const TH_RST = 4;
-const TH_PUSH = 8;
-const TH_ACK = 16;
-const TH_URG = 32;
-const TH_FLAGS = 63; ##< (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG)
+# TCP flags.
+#
+# todo::these should go into an enum to make them autodoc'able
+const TH_FIN = 1; ##< FIN.
+const TH_SYN = 2; ##< SYN.
+const TH_RST = 4; ##< RST.
+const TH_PUSH = 8; ##< PUSH.
+const TH_ACK = 16; ##< ACK.
+const TH_URG = 32; ##< URG.
+const TH_FLAGS = 63; ##< Mask combining all flags.
+## Values extracted from a TCP header.
+##
+## .. bro:see:: pkt_hdr discarder_check_tcp
type tcp_hdr: record {
- sport: port; ##< source port
+ sport: port; ##< source port.
dport: port; ##< destination port
seq: count; ##< sequence number
ack: count; ##< acknowledgement number
@@ -607,36 +980,114 @@ type tcp_hdr: record {
win: count; ##< window
};
+## Values extracted from a UDP header.
+##
+## .. bro:see:: pkt_hdr discarder_check_udp
type udp_hdr: record {
sport: port; ##< source port
dport: port; ##< destination port
ulen: count; ##< udp length
};
-
-## Holds an ip_hdr and one of tcp_hdr, udp_hdr, or icmp_hdr.
-type pkt_hdr: record {
- ip: ip_hdr;
- tcp: tcp_hdr &optional;
- udp: udp_hdr &optional;
- icmp: icmp_hdr &optional;
+## Values extracted from an ICMP header.
+##
+## .. bro:see:: pkt_hdr discarder_check_icmp
+type icmp_hdr: record {
+ icmp_type: count; ##< type of message
};
+## A packet header, consisting of an IP header and transport-layer header.
+##
+## .. bro:see:: new_packet
+type pkt_hdr: record {
+ ip: ip_hdr; ##< The IP header.
+ tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet.
+ udp: udp_hdr &optional; ##< The UDP header if a UDP packet.
+ icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet.
+};
-## If you add elements here, then for a given BPF filter as index, when
-## a packet matching that filter is captured, the corresponding event handler
-## will be invoked.
+## Definition of "secondary filters". A secondary filter is a BPF filter given as
+## index in this table. For each such filter, the corresponding event is raised for
+## all matching packets.
global secondary_filters: table[string] of event(filter: string, pkt: pkt_hdr)
&redef;
-global discarder_maxlen = 128 &redef; ##< maximum amount of data passed to fnc
+## Maximum length of payload passed to discarder functions.
+##
+## .. :bro:see:: discarder_check_tcp discarder_check_udp discarder_check_icmp
+## discarder_check_ip
+global discarder_maxlen = 128 &redef;
+## Function for skipping packets based on their IP header. If defined, this
+## function will be called for all IP packets before Bro performs any further
+## analysis. If the function signals to discard a packet, no further processing
+## will be performed on it.
+##
+## i: The IP header of the considered packet.
+##
+## Returns: True if the packet should not be analyzed any further.
+##
+## .. :bro:see:: discarder_check_tcp discarder_check_udp discarder_check_icmp
+## discarder_maxlen
+##
+## .. note:: This is very low-level functionality and potentially expensive.
+## Avoid using it.
global discarder_check_ip: function(i: ip_hdr): bool;
-global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool;
-global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool;
-global discarder_check_icmp: function(i: ip_hdr, ih: icmp_hdr): bool;
-# End of definition of access to packet headers, discarders.
+## Function for skipping packets based on their TCP header. If defined, this
+## function will be called for all TCP packets before Bro performs any further
+## analysis. If the function signals to discard a packet, no further processing
+## will be performed on it.
+##
+## i: The IP header of the considered packet.
+## t: The TCP header.
+## d: Up to :bro:see:`discarder_maxlen` bytes of the TCP payload.
+##
+## Returns: True if the packet should not be analyzed any further.
+##
+## .. :bro:see:: discarder_check_ip discarder_check_udp discarder_check_icmp
+## discarder_maxlen
+##
+## .. note:: This is very low-level functionality and potentially expensive.
+## Avoid using it.
+global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool;
+
+## Function for skipping packets based on their UDP header. If defined, this
+## function will be called for all UDP packets before Bro performs any further
+## analysis. If the function signals to discard a packet, no further processing
+## will be performed on it.
+##
+## i: The IP header of the considered packet.
+## t: The UDP header.
+## d: Up to :bro:see:`discarder_maxlen` bytes of the UDP payload.
+##
+## Returns: True if the packet should not be analyzed any further.
+##
+## .. :bro:see:: discarder_check_ip discarder_check_tcp discarder_check_icmp
+## discarder_maxlen
+##
+## .. note:: This is very low-level functionality and potentially expensive.
+## Avoid using it.
+global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool;
+
+## Function for skipping packets based on their ICMP header. If defined, this
+## function will be called for all ICMP packets before Bro performs any further
+## analysis. If the function signals to discard a packet, no further processing
+## will be performed on it.
+##
+## i: The IP header of the considered packet.
+## ih: The ICMP header.
+##
+## Returns: True if the packet should not be analyzed any further.
+##
+## .. :bro:see:: discarder_check_ip discarder_check_tcp discarder_check_udp
+## discarder_maxlen
+##
+## .. note:: This is very low-level functionality and potentially expensive.
+## Avoid using it.
+global discarder_check_icmp: function(i: ip_hdr, ih: icmp_hdr): bool;
+
+## Bro's watchdog interval.
const watchdog_interval = 10 sec &redef;
## The maximum number of timers to expire after processing each new
@@ -650,56 +1101,141 @@ const max_timer_expires = 300 &redef;
const max_remote_events_processed = 10 &redef;
# These need to match the definitions in Login.h.
-# TODO: use enum to make them autodoc'able
-const LOGIN_STATE_AUTHENTICATE = 0; # trying to authenticate
-const LOGIN_STATE_LOGGED_IN = 1; # successful authentication
-const LOGIN_STATE_SKIP = 2; # skip any further processing
-const LOGIN_STATE_CONFUSED = 3; # we're confused
+#
+# .. bro:see:: get_login_state
+#
+# todo::use enum to make them autodoc'able
+const LOGIN_STATE_AUTHENTICATE = 0; # Trying to authenticate.
+const LOGIN_STATE_LOGGED_IN = 1; # Successful authentication.
+const LOGIN_STATE_SKIP = 2; # Skip any further processing.
+const LOGIN_STATE_CONFUSED = 3; # We're confused.
# It would be nice to replace these function definitions with some
# form of parameterized types.
+
+## Returns minimum of two ``double`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The minimum of *a* and *b*.
function min_double(a: double, b: double): double { return a < b ? a : b; }
+
+## Returns maximum of two ``double`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The maximum of *a* and *b*.
function max_double(a: double, b: double): double { return a > b ? a : b; }
+
+## Returns minimum of two ``interval`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The minimum of *a* and *b*.
function min_interval(a: interval, b: interval): interval { return a < b ? a : b; }
+
+## Returns maximum of two ``interval`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The maximum of *a* and *b*.
function max_interval(a: interval, b: interval): interval { return a > b ? a : b; }
+
+## Returns minimum of two ``count`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The minimum of *a* and *b*.
function min_count(a: count, b: count): count { return a < b ? a : b; }
+
+## Returns maximum of two ``count`` values.
+##
+## a: First value.
+## b: Second value.
+##
+## Returns: The maximum of *a* and *b*.
function max_count(a: count, b: count): count { return a > b ? a : b; }
+## TODO.
global skip_authentication: set[string] &redef;
+
+## TODO.
global direct_login_prompts: set[string] &redef;
+
+## TODO.
global login_prompts: set[string] &redef;
+
+## TODO.
global login_non_failure_msgs: set[string] &redef;
+
+## TODO.
global login_failure_msgs: set[string] &redef;
+
+## TODO.
global login_success_msgs: set[string] &redef;
+
+## TODO.
global login_timeouts: set[string] &redef;
+## A MIME header key/value pair.
+##
+## .. bro:see:: mime_header_list http_all_headers mime_all_headers mime_one_header
type mime_header_rec: record {
- name: string;
- value: string;
+ name: string; ##< The header name.
+ value: string; ##< The header value.
};
+
+## A list of MIME headers.
+##
+## .. bro:see:: mime_header_rec http_all_headers mime_all_headers
type mime_header_list: table[count] of mime_header_rec;
+
+## The length of MIME data segments delivered to handlers of
+## :bro:see:`mime_segment_data`.
+##
+## .. bro:see:: mime_segment_data mime_segment_overlap_length
global mime_segment_length = 1024 &redef;
+
+## The number of bytes of overlap between successive segments passed to
+## :bro:see:`mime_segment_data`.
global mime_segment_overlap_length = 0 &redef;
+## An RPC portmapper mapping.
+##
+## .. bro:see:: pm_mappings
type pm_mapping: record {
- program: count;
- version: count;
- p: port;
+ program: count; ##< The RPC program.
+ version: count; ##< The program version.
+ p: port; ##< The port.
};
+## Table of RPC portmapper mappings.
+##
+## .. bro:see:: pm_request_dump
type pm_mappings: table[count] of pm_mapping;
+## An RPC portmapper request.
+##
+## .. bro:see:: pm_attempt_getport pm_request_getport
type pm_port_request: record {
- program: count;
- version: count;
- is_tcp: bool;
+ program: count; ##< The RPC program.
+ version: count; ##< The program version.
+ is_tcp: bool; ##< True if using TCP.
};
+## An RPC portmapper *callit* request.
+##
+## .. bro:see:: pm_attempt_callit pm_request_callit
type pm_callit_request: record {
- program: count;
- version: count;
- proc: count;
- arg_size: count;
+ program: count; ##< The RPC program.
+ version: count; ##< The program version.
+ proc: count; ##< The procedure being called.
+ arg_size: count; ##< The size of the argument.
};
# See const.bif
@@ -713,6 +1249,10 @@ type pm_callit_request: record {
# const RPC_AUTH_ERROR = 7;
# const RPC_UNKNOWN_ERROR = 8;
+## Mapping of numerical RPC status codes to readable messages.
+##
+## .. bro:see:: pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset rpc_dialogue rpc_reply
const RPC_status = {
[RPC_SUCCESS] = "ok",
[RPC_PROG_UNAVAIL] = "prog unavail",
@@ -728,247 +1268,307 @@ const RPC_status = {
module NFS3;
export {
- ## Should the read and write events return the file data that has been
- ## read/written?
+ ## If true, :bro:see:`nfs_proc_read` and :bro:see:`nfs_proc_write` events return
+ ## the file data that has been read/written.
+ ##
+ ## .. .. bro:see:: return_data_max return_data_first_only
const return_data = F &redef;
- ## If bro:id:`nfs_return_data` is true, how much data should be returned at most.
+ ## If bro:id:`NFS3::return_data` is true, how much data should be returned at
+ ## most.
const return_data_max = 512 &redef;
- ## If nfs_return_data is true, whether to *only* return data if the read or write
- ## offset is 0, i.e., only return data for the beginning of the file.
+ ## If bro:id:`NFS3::return_data` is true, whether to *only* return data if the read
+ ## or write offset is 0, i.e., only return data for the beginning of the file.
const return_data_first_only = T &redef;
- ## This record summarizes the general results and status of NFSv3 request/reply
- ## pairs. It's part of every NFSv3 event.
+ ## Record summarizing the general results and status of NFSv3 request/reply pairs.
+ ##
+ ## Note that when *rpc_stats* or *nfs_stats* indicates not successful, the reply
+ ## record passed to the correpsonding event will be empty and contain uninitialized
+ ## fields, so don't use it. Also note that time and duration values might not be
+ ## fully accurate. For TCP, we record times when the corresponding chunk of data
+ ## is delivered to the analyzer. Depending on the reassembler, this might be well
+ ## after the first packet of the request was received.
+ ##
+ ## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup
+ ## nfs_proc_mkdir nfs_proc_not_implemented nfs_proc_null
+ ## nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove
+ ## nfs_proc_rmdir nfs_proc_write nfs_reply_status
type info_t: record {
- ## If this indicates not successful, the reply record in the
- ## events will be empty and contain uninitialized fields, so
- ## don't use it.
- rpc_stat: rpc_status;
+ ## The RPC status.
+ rpc_stat: rpc_status;
+ ## The NFS status.
nfs_stat: status_t;
-
- ## The start time, duration, and length in bytes of the request (call). Note that
- ## the start and end time might not be accurate. For TCP, we record the
- ## time when a chunk of data is delivered to the analyzer. Depending on the
- ## Reassembler, this might be well after the first packet of the request
- ## was received.
+ ## The start time of the request.
req_start: time;
- ## See :bro:id:`req_start`
+ ## The duration of the request.
req_dur: interval;
- ## See :bro:id:`req_start`
+ ## The length in bytes of the request.
req_len: count;
-
- ## Like :bro:id:`req_start` but for reply.
+ ## The start time of the reply.
rep_start: time;
- ## Like :bro:id:`req_dur` but for reply.
+ ## The duration of the reply.
rep_dur: interval;
- ## Like :bro:id:`req_len` but for reply.
+ ## The length in bytes of the reply.
rep_len: count;
};
- # NFSv3 types. Type names are based on RFC 1813.
+ ## NFS file attributes. Field names are based on RFC 1813.
+ ##
+ ## .. bro:see:: nfs_proc_getattr
type fattr_t: record {
- ftype: file_type_t;
- mode: count;
- nlink: count;
- uid: count;
- gid: count;
- size: count;
- used: count;
- rdev1: count;
- rdev2: count;
- fsid: count;
- fileid: count;
- atime: time;
- mtime: time;
- ctime: time;
+ ftype: file_type_t; ##< File type.
+ mode: count; ##< Mode
+ nlink: count; ##< Number of links.
+ uid: count; ##< User ID.
+ gid: count; ##< Group ID.
+ size: count; ##< Size.
+ used: count; ##< TODO.
+ rdev1: count; ##< TODO.
+ rdev2: count; ##< TODO.
+ fsid: count; ##< TODO.
+ fileid: count; ##< TODO.
+ atime: time; ##< Time of last access.
+ mtime: time; ##< Time of last modification.
+ ctime: time; ##< Time of creation.
};
+ ## NFS *readdir* arguments.
+ ##
+ ## .. bro:see:: nfs_proc_readdir
type diropargs_t : record {
- dirfh: string; ##< the file handle of the directory
- fname: string; ##< the name of the file we are interested in
+ dirfh: string; ##< The file handle of the directory.
+ fname: string; ##< The name of the file we are interested in.
};
- # Note, we don't need a "post_op_attr" type. We use an "fattr_t &optional"
- # instead.
-
- ## If the lookup failed, dir_attr may be set.
- ## If the lookup succeeded, fh is always set and obj_attr and dir_attr may be set.
+ ## NFS lookup reply. If the lookup failed, *dir_attr* may be set. If the lookup
+ ## succeeded, *fh* is always set and *obj_attr* and *dir_attr* may be set.
+ ##
+ ## .. bro:see:: nfs_proc_lookup
type lookup_reply_t: record {
- fh: string &optional; ##< file handle of object looked up
- obj_attr: fattr_t &optional; ##< optional attributes associated w/ file
- dir_attr: fattr_t &optional; ##< optional attributes associated w/ dir.
+ fh: string &optional; ##< File handle of object looked up.
+ obj_attr: fattr_t &optional; ##< Optional attributes associated w/ file
+ dir_attr: fattr_t &optional; ##< Optional attributes associated w/ dir.
};
+ ## NFS *read* arguments.
+ ##
+ ## .. bro:see:: nfs_proc_read
type readargs_t: record {
- fh: string; ##< file handle to read from
- offset: count; ##< offset in file
- size: count; ##< number of bytes to read
+ fh: string; ##< File handle to read from.
+ offset: count; ##< Offset in file.
+ size: count; ##< Number of bytes to read.
};
- ## If the lookup fails, attr may be set. If the lookup succeeds, attr may be set
- ## and all other fields are set.
+ ## NFS *read* reply. If the lookup fails, *attr* may be set. If the lookup succeeds,
+ ## *attr* may be set and all other fields are set.
type read_reply_t: record {
- attr: fattr_t &optional; ##< attributes
- size: count &optional; ##< number of bytes read
- eof: bool &optional; ##< did the read end at EOF
- data: string &optional; ##< the actual data; not yet implemented.
+ attr: fattr_t &optional; ##< Attributes.
+ size: count &optional; ##< Number of bytes read.
+ eof: bool &optional; ##< Sid the read end at EOF.
+ data: string &optional; ##< The actual data; not yet implemented.
};
- ## If the request fails, attr may be set. If the request succeeds, attr may be
- ## set and all other fields are set.
+ ## NFS *readline* reply. If the request fails, *attr* may be set. If the request
+ ## succeeds, *attr* may be set and all other fields are set.
+ ##
+ ## .. bro:see:: nfs_proc_readlink
type readlink_reply_t: record {
- attr: fattr_t &optional; ##< attributes
- nfspath: string &optional; ##< the contents of the symlink; in general a pathname as text
+ attr: fattr_t &optional; ##< Attributes.
+ nfspath: string &optional; ##< Contents of the symlink; in general a pathname as text.
};
+ ## NFS *write* arguments.
+ ##
+ ## .. bro:see:: nfs_proc_write
type writeargs_t: record {
- fh: string; ##< file handle to write to
- offset: count; ##< offset in file
- size: count; ##< number of bytes to write
- stable: stable_how_t; ##< how and when data is commited
- data: string &optional; ##< the actual data; not implemented yet
+ fh: string; ##< File handle to write to.
+ offset: count; ##< Offset in file.
+ size: count; ##< Number of bytes to write.
+ stable: stable_how_t; ##< How and when data is commited.
+ data: string &optional; ##< The actual data; not implemented yet.
};
+ ## NFS *wcc* attributes.
+ ##
+ ## .. bro:see:: NFS3::write_reply_t
type wcc_attr_t: record {
- size: count;
- atime: time;
- mtime: time;
+ size: count; ##< The dize.
+ atime: time; ##< Access time.
+ mtime: time; ##< Modification time.
};
- ## If the request fails, pre|post attr may be set. If the request succeeds,
- ## pre|post attr may be set and all other fields are set.
+ ## NFS *write* reply. If the request fails, *pre|post* attr may be set. If the
+ ## request succeeds, *pre|post* attr may be set and all other fields are set.
+ ##
+ ## .. bro:see:: nfs_proc_write
type write_reply_t: record {
- preattr: wcc_attr_t &optional; ##< pre operation attributes
- postattr: fattr_t &optional; ##< post operation attributes
- size: count &optional;
- commited: stable_how_t &optional;
- verf: count &optional; ##< write verifier cookue
+ preattr: wcc_attr_t &optional; ##< Pre operation attributes.
+ postattr: fattr_t &optional; ##< Post operation attributes.
+ size: count &optional; ##< Size.
+ commited: stable_how_t &optional; ##< TODO.
+ verf: count &optional; ##< Write verifier cookie.
};
- ## reply for create, mkdir, symlink
- ## If the proc failed, dir_*_attr may be set. If the proc succeeded, fh and
- ## the attr's may be set. Note: no guarantee that fh is set after
- ## success.
+ ## NFS reply for *create*, *mkdir*, and *symlink*. If the proc
+ ## failed, *dir_\*_attr* may be set. If the proc succeeded, *fh* and the *attr*'s
+ ## may be set. Note: no guarantee that *fh* is set after success.
+ ##
+ ## .. bro:see:: nfs_proc_create nfs_proc_mkdir
type newobj_reply_t: record {
- fh: string &optional; ##< file handle of object created
- obj_attr: fattr_t &optional; ##< optional attributes associated w/ new object
- dir_pre_attr: wcc_attr_t &optional; ##< optional attributes associated w/ dir
- dir_post_attr: fattr_t &optional; ##< optional attributes associated w/ dir
+ fh: string &optional; ##< File handle of object created.
+ obj_attr: fattr_t &optional; ##< Optional attributes associated w/ new object.
+ dir_pre_attr: wcc_attr_t &optional; ##< Optional attributes associated w/ dir.
+ dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir.
};
- ## reply for remove, rmdir
- ## Corresponds to "wcc_data" in the spec.
+ ## NFS reply for *remove*, *rmdir*. Corresponds to *wcc_data* in the spec.
+ ##
+ ## .. bro:see:: nfs_proc_remove nfs_proc_rmdir
type delobj_reply_t: record {
- dir_pre_attr: wcc_attr_t &optional; ##< optional attributes associated w/ dir
- dir_post_attr: fattr_t &optional; ##< optional attributes associated w/ dir
+ dir_pre_attr: wcc_attr_t &optional; ##< Optional attributes associated w/ dir.
+ dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir.
};
- ## This record is used for both readdir and readdirplus.
+ ## NFS *readdir* arguments. Used for both *readdir* and *readdirplus*.
+ ##
+ ## .. bro:see:: nfs_proc_readdir
type readdirargs_t: record {
- isplus: bool; ##< is this a readdirplus request?
- dirfh: string; ##< the directory filehandle
- cookie: count; ##< cookie / pos in dir; 0 for first call
- cookieverf: count; ##< the cookie verifier
- dircount: count; ##< "count" field for readdir; maxcount otherwise (in bytes)
- maxcount: count &optional; ##< only used for readdirplus. in bytes
+ isplus: bool; ##< Is this a readdirplus request?
+ dirfh: string; ##< The directory filehandle.
+ cookie: count; ##< Cookie / pos in dir; 0 for first call.
+ cookieverf: count; ##< The cookie verifier.
+ dircount: count; ##< "count" field for readdir; maxcount otherwise (in bytes).
+ maxcount: count &optional; ##< Only used for readdirplus. in bytes.
};
- ## fh and attr are used for readdirplus. However, even for readdirplus they may
- ## not be filled out.
+ ## NFS *direntry*. *fh* and *attr* are used for *readdirplus*. However, even
+ ## for *readdirplus* they may not be filled out.
+ ##
+ ## .. bro:see:: NFS3::direntry_vec_t NFS3::readdir_reply_t
type direntry_t: record {
- fileid: count; ##< e.g., inode number
- fname: string; ##< filename
- cookie: count;
- attr: fattr_t &optional; ##< readdirplus: the FH attributes for the entry
- fh: string &optional; ##< readdirplus: the FH for the entry
+ fileid: count; ##< E.g., inode number.
+ fname: string; ##< Filename.
+ cookie: count; ##< Cookie value.
+ attr: fattr_t &optional; ##< *readdirplus*: the *fh* attributes for the entry.
+ fh: string &optional; ##< *readdirplus*: the *fh* for the entry
};
+ ## Vector of NFS *direntry*.
+ ##
+ ## .. bro:see:: NFS3::readdir_reply_t
type direntry_vec_t: vector of direntry_t;
- ## Used for readdir and readdirplus.
- ## If error: dir_attr might be set. If success: dir_attr may be set, all others
+ ## NFS *readdir* reply. Used for *readdir* and *readdirplus*. If an is
+ ## returned, *dir_attr* might be set. On success, *dir_attr* may be set, all others
## must be set.
type readdir_reply_t: record {
- isplus: bool; ##< is the reply for a readdirplus request
- dir_attr: fattr_t &optional;
- cookieverf: count &optional;
- entries: direntry_vec_t &optional;
- eof: bool; ##< if true, no more entries in dir.
+ isplus: bool; ##< True if the reply for a *readdirplus* request.
+ dir_attr: fattr_t &optional; ##< Directory attributes.
+ cookieverf: count &optional; ##< TODO.
+ entries: direntry_vec_t &optional; ##< Returned directory entries.
+ eof: bool; ##< If true, no more entries in directory.
};
+ ## NFS *fsstat*.
type fsstat_t: record {
- attrs: fattr_t &optional;
- tbytes: double;
- fbytes: double;
- abytes: double;
- tfiles: double;
- ffiles: double;
- afiles: double;
- invarsec: interval;
+ attrs: fattr_t &optional; ##< Attributes.
+ tbytes: double; ##< TODO.
+ fbytes: double; ##< TODO.
+ abytes: double; ##< TODO.
+ tfiles: double; ##< TODO.
+ ffiles: double; ##< TODO.
+ afiles: double; ##< TODO.
+ invarsec: interval; ##< TODO.
};
} # end export
module GLOBAL;
+## An NTP message.
+##
+## .. bro:see:: ntp_message
type ntp_msg: record {
- id: count;
- code: count;
- stratum: count;
- poll: count;
- precision: int;
- distance: interval;
- dispersion: interval;
- ref_t: time;
- originate_t: time;
- receive_t: time;
- xmit_t: time;
+ id: count; ##< Message ID.
+ code: count; ##< Message code.
+ stratum: count; ##< Stratum.
+ poll: count; ##< Poll.
+ precision: int; ##< Precision.
+ distance: interval; ##< Distance.
+ dispersion: interval; ##< Dispersion.
+ ref_t: time; ##< Reference time.
+ originate_t: time; ##< Originating time.
+ receive_t: time; ##< Receive time.
+ xmit_t: time; ##< Send time.
};
-## Maps Samba command numbers to descriptive names.
+## Maps SMB command numbers to descriptive names.
global samba_cmds: table[count] of string &redef
&default = function(c: count): string
{ return fmt("samba-unknown-%d", c); };
+## An SMB command header.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction
+## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect
+## smb_com_write_andx smb_error smb_get_dfs_referral smb_message
type smb_hdr : record {
- command: count;
- status: count;
- flags: count;
- flags2: count;
- tid: count;
- pid: count;
- uid: count;
- mid: count;
+ command: count; ##< The command number (see :bro:see:`samba_cmds` ).
+ status: count; ##< The status code.
+ flags: count; ##< Flag set 1.
+ flags2: count; ##< Flag set 2.
+ tid: count; ##< TODO.
+ pid: count; ##< Process ID.
+ uid: count; ##< User ID.
+ mid: count; ##< TODO.
};
+## An SMB transaction.
+##
+## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2
type smb_trans : record {
- word_count: count;
- total_param_count: count;
- total_data_count: count;
- max_param_count: count;
- max_data_count: count;
- max_setup_count: count;
+ word_count: count; ##< TODO.
+ total_param_count: count; ##< TODO.
+ total_data_count: count; ##< TODO.
+ max_param_count: count; ##< TODO.
+ max_data_count: count; ##< TODO.
+ max_setup_count: count; ##< TODO.
# flags: count;
# timeout: count;
- param_count: count;
- param_offset: count;
- data_count: count;
- data_offset: count;
- setup_count: count;
- setup0: count;
- setup1: count;
- setup2: count;
- setup3: count;
- byte_count: count;
- parameters: string;
+ param_count: count; ##< TODO.
+ param_offset: count; ##< TODO.
+ data_count: count; ##< TODO.
+ data_offset: count; ##< TODO.
+ setup_count: count; ##< TODO.
+ setup0: count; ##< TODO.
+ setup1: count; ##< TODO.
+ setup2: count; ##< TODO.
+ setup3: count; ##< TODO.
+ byte_count: count; ##< TODO.
+ parameters: string; ##< TODO.
};
+
+## SMB transaction data.
+##
+## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2
+##
+## .. todo:: Should this really be a record type?
type smb_trans_data : record {
- data : string;
+ data : string; ##< The transaction's data.
};
+## Deprecated.
+##
+## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere
+## else.
type smb_tree_connect : record {
flags: count;
password: string;
@@ -976,177 +1576,268 @@ type smb_tree_connect : record {
service: string;
};
+## Deprecated.
+##
+## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere
+## else.
type smb_negotiate : table[count] of string;
-## A list of router addresses offered by the server.
+## A list of router addresses offered by a DHCP server.
+##
+## .. bro:see:: dhcp_ack dhcp_offer
type dhcp_router_list: table[count] of addr;
+## A DHCP message.
+##
+## .. bro:see:: dhcp_ack dhcp_decline dhcp_discover dhcp_inform dhcp_nak
+## dhcp_offer dhcp_release dhcp_request
type dhcp_msg: record {
- op: count; ##< message OP code. 1 = BOOTREQUEST, 2 = BOOTREPLY
- m_type: count; ##< the type of DHCP message
- xid: count; ##< transaction ID of a DHCP session
- h_addr: string; ##< hardware address of the client
- ciaddr: addr; ##< original IP address of the client
- yiaddr: addr; ##< IP address assigned to the client
+ op: count; ##< Message OP code. 1 = BOOTREQUEST, 2 = BOOTREPLY
+ m_type: count; ##< The type of DHCP message.
+ xid: count; ##< Transaction ID of a DHCP session.
+ h_addr: string; ##< Hardware address of the client.
+ ciaddr: addr; ##< Original IP address of the client.
+ yiaddr: addr; ##< IP address assigned to the client.
};
+## A DNS message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_message
+## dns_query_reply dns_rejected dns_request
type dns_msg: record {
- id: count;
+ id: count; ##< Transaction ID.
- opcode: count;
- rcode: count;
+ opcode: count; ##< Operation code.
+ rcode: count; ##< Return code.
- QR: bool;
- AA: bool;
- TC: bool;
- RD: bool;
- RA: bool;
- Z: count;
+ QR: bool; ##< Query response flag.
+ AA: bool; ##< Authoritative answer flag.
+ TC: bool; ##< Truncated packet flag.
+ RD: bool; ##< Recursion desired flag.
+ RA: bool; ##< Recursion available flag.
+ Z: count; ##< TODO.
- num_queries: count;
- num_answers: count;
- num_auth: count;
- num_addl: count;
+ num_queries: count; ##< Number of query records.
+ num_answers: count; ##< Number of answer records.
+ num_auth: count; ##< Number of authoritative records.
+ num_addl: count; ##< Number of additional records.
};
+## A DNS SOA record.
+##
+## .. bro:see:: dns_SOA_reply
type dns_soa: record {
- mname: string; ##< primary source of data for zone
- rname: string; ##< mailbox for responsible person
- serial: count; ##< version number of zone
- refresh: interval; ##< seconds before refreshing
- retry: interval; ##< how long before retrying failed refresh
- expire: interval; ##< when zone no longer authoritative
- minimum: interval; ##< minimum TTL to use when exporting
+ mname: string; ##< Primary source of data for zone.
+ rname: string; ##< Mailbox for responsible person.
+ serial: count; ##< Version number of zone.
+ refresh: interval; ##< Seconds before refreshing.
+ retry: interval; ##< How long before retrying failed refresh.
+ expire: interval; ##< When zone no longer authoritative.
+ minimum: interval; ##< Minimum TTL to use when exporting.
};
+## An additional DNS EDNS record.
+##
+## .. bro:see:: dns_EDNS_addl
type dns_edns_additional: record {
- query: string;
- qtype: count;
- t: count;
- payload_size: count;
- extended_rcode: count;
- version: count;
- z_field: count;
- TTL: interval;
- is_query: count;
+ query: string; ##< Query.
+ qtype: count; ##< Query type.
+ t: count; ##< TODO.
+ payload_size: count; ##< TODO.
+ extended_rcode: count; ##< Extended return code.
+ version: count; ##< Version.
+ z_field: count; ##< TODO.
+ TTL: interval; ##< Time-to-live.
+ is_query: count; ##< TODO.
};
+## An additional DNS TSIG record.
+##
+## bro:see:: dns_TSIG_addl
type dns_tsig_additional: record {
- query: string;
- qtype: count;
- alg_name: string;
- sig: string;
- time_signed: time;
- fudge: time;
- orig_id: count;
- rr_error: count;
- is_query: count;
+ query: string; ##< Query.
+ qtype: count; ##< Query type.
+ alg_name: string; ##< Algorithm name.
+ sig: string; ##< Signature.
+ time_signed: time; ##< Time when signed.
+ fudge: time; ##< TODO.
+ orig_id: count; ##< TODO.
+ rr_error: count; ##< TODO.
+ is_query: count; ##< TODO.
};
-# Different values for "answer_type" in the following. DNS_QUERY
-# shouldn't occur, it's just for completeness.
-# TODO: use enums to help autodoc
-const DNS_QUERY = 0;
-const DNS_ANS = 1;
-const DNS_AUTH = 2;
-const DNS_ADDL = 3;
+# DNS answer types.
+#
+# .. .. bro:see:: dns_answerr
+#
+# todo::use enum to make them autodoc'able
+const DNS_QUERY = 0; ##< A query. This shouldn't occur, just for completeness.
+const DNS_ANS = 1; ##< An answer record.
+const DNS_AUTH = 2; ##< An authorative record.
+const DNS_ADDL = 3; ##< An additional record.
+## The general part of a DNS reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply
+## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply
+## dns_TXT_reply dns_WKS_reply
type dns_answer: record {
+ ## Answer type. One of :bro:see:`DNS_QUERY`, :bro:see:`DNS_ANS`,
+ ## :bro:see:`DNS_AUTH` and :bro:see:`DNS_ADDL`.
answer_type: count;
- query: string;
- qtype: count;
- qclass: count;
- TTL: interval;
+ query: string; ##< Query.
+ qtype: count; ##< Query type.
+ qclass: count; ##< Query class.
+ TTL: interval; ##< Time-to-live.
};
-## For servers in these sets, omit processing the AUTH records
-## they include in their replies.
+## For DNS servers in these sets, omit processing the AUTH records they include in
+## their replies.
+##
+## .. bro:see:: dns_skip_all_auth dns_skip_addl
global dns_skip_auth: set[addr] &redef;
-## For servers in these sets, omit processing the ADDL records
-## they include in their replies.
+
+## For DNS servers in these sets, omit processing the ADDL records they include in
+## their replies.
+##
+## .. bro:see:: dns_skip_all_addl dns_skip_auth
global dns_skip_addl: set[addr] &redef;
-## If the following are true, then all AUTH records are skipped.
+## If true, all DNS AUTH records are skipped.
+##
+## .. bro:see:: dns_skip_all_addl dns_skip_auth
global dns_skip_all_auth = T &redef;
-## If the following are true, then all ADDL records are skipped.
+
+## If true, all DNS ADDL records are skipped.
+##
+## .. bro:see:: dns_skip_all_auth dns_skip_addl
global dns_skip_all_addl = T &redef;
-## If a DNS request includes more than this many queries, assume it's
-## non-DNS traffic and do not process it. Set to 0 to turn off this
-## functionality.
+## If a DNS request includes more than this many queries, assume it's non-DNS
+## traffic and do not process it. Set to 0 to turn off this functionality.
global dns_max_queries = 5;
-## The maxiumum size in bytes for an SSL cipherspec. If we see a packet that
-## has bigger cipherspecs, we won't do a comparisons of cipherspecs.
+## The maxiumum size in bytes for an SSL cipher specifcation. If we see a packet
+## that has bigger cipherspecs, we won't do a comparisons of cipherspecs.
const ssl_max_cipherspec_size = 68 &redef;
-type X509_extensions: table[count] of string;
+# todo::Is this still used?
+# type X509_extensions: table[count] of string;
+## An X509 certificate.
+##
+## .. bro:see:: x509_certificate
type X509: record {
- version: count;
- serial: string;
- subject: string;
- issuer: string;
- not_valid_before: time;
- not_valid_after: time;
+ version: count; ##< Version number.
+ serial: string; ##< Serial number.
+ subject: string; ##< Subject.
+ issuer: string; ##< Issuer.
+ not_valid_before: time; ##< Timestamp before when certificate is not valid.
+ not_valid_after: time; ##< Timestamp after when certificate is not valid.
};
-## This is indexed with the CA's name and yields a DER (binary) encoded certificate.
-const root_ca_certs: table[string] of string = {} &redef;
+# This is indexed with the CA's name and yields a DER (binary) encoded certificate.
+# todo::Is this still used?
+# const root_ca_certs: table[string] of string = {} &redef;
+## HTTP session statistics.
+##
+## .. bro:see:: http_stats
type http_stats_rec: record {
- num_requests: count;
- num_replies: count;
- request_version: double;
- reply_version: double;
+ num_requests: count; ##< Number of requests.
+ num_replies: count; ##< Number of replies.
+ request_version: double; ##< HTTP version of the requests.
+ reply_version: double; ##< HTTP Version of the replies.
};
+## HTTP message statistics.
+##
+## .. bro:see:: http_message_done
type http_message_stat: record {
- ## when the request/reply line was complete
+ ## When the request/reply line was complete.
start: time;
- ## whether the message is interrupted
- interrupted: bool;
- ## reason phrase if interrupted
- finish_msg: string;
- ## length of body processed (before finished/interrupted)
- body_length: count;
- ## total len of gaps within body_length
- content_gap_length: count;
- ## length of headers (including the req/reply line, but not CR/LF's)
- header_length: count;
+ ## Whether the message was interrupted.
+ interrupted: bool;
+ ## Reason phrase if interrupted.
+ finish_msg: string;
+ ## Length of body processed (before finished/interrupted).
+ body_length: count;
+ ## Total length of gaps within body_length.
+ content_gap_length: count;
+ ## Length of headers (including the req/reply line, but not CR/LF's).
+ header_length: count;
};
+## Maximum number of HTTP entity data delivered to events. The amount of data
+## can be limited for better performance, zero disables truncation.
+##
+## .. bro:see:: http_entity_data skip_http_entity_data skip_http_data
global http_entity_data_delivery_size = 1500 &redef;
-## Truncate URIs longer than this to prevent over-long URIs (usually sent
-## by worms) from slowing down event processing. A value of -1 means "do
-## not truncate".
+## Skip HTTP data for performance considerations. The skipped
+## portion will not go through TCP reassembly.
+##
+## .. bro:see:: http_entity_data skip_http_entity_data http_entity_data_delivery_size
+const skip_http_data = F &redef;
+
+## Maximum length of HTTP URIs passed to events. Longer ones will be truncated
+## to prevent over-long URIs (usually sent by worms) from slowing down event
+## processing. A value of -1 means "do not truncate".
+##
+## .. bro:see:: http_request
const truncate_http_URI = -1 &redef;
-## IRC-related globals to which the event engine is sensitive.
+## IRC join information.
+##
+## .. bro:see:: irc_join_list
type irc_join_info: record {
nick: string;
channel: string;
password: string;
usermode: string;
};
+
+## Set of IRC join information.
+##
+## .. bro:see:: irc_join_message
type irc_join_list: set[irc_join_info];
+
+## Deprecated.
+##
+## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere
+## else.
global irc_servers : set[addr] &redef;
-## Stepping-stone globals.
+## Internal to the stepping stone detector.
const stp_delta: interval &redef;
+
+## Internal to the stepping stone detector.
const stp_idle_min: interval &redef;
-## Don't do analysis on these sources. Used to avoid overload from scanners.
+## Internal to the stepping stone detector.
global stp_skip_src: set[addr] &redef;
+## Deprecated.
const interconn_min_interarrival: interval &redef;
+
+## Deprecated.
const interconn_max_interarrival: interval &redef;
+
+## Deprecated.
const interconn_max_keystroke_pkt_size: count &redef;
+
+## Deprecated.
const interconn_default_pkt_size: count &redef;
+
+## Deprecated.
const interconn_stat_period: interval &redef;
+
+## Deprecated.
const interconn_stat_backoff: double &redef;
+## Deprecated.
type interconn_endp_stats: record {
num_pkts: count;
num_keystrokes_two_in_row: count;
@@ -1160,9 +1851,13 @@ type interconn_endp_stats: record {
num_normal_lines: count;
};
+## Deprecated.
const backdoor_stat_period: interval &redef;
+
+## Deprecated.
const backdoor_stat_backoff: double &redef;
+## Deprecated.
type backdoor_endp_stats: record {
is_partial: bool;
num_pkts: count;
@@ -1174,295 +1869,422 @@ type backdoor_endp_stats: record {
num_7bit_ascii: count;
};
+## Description of a signature match.
+##
+## .. bro:see:: signature_match
type signature_state: record {
- sig_id: string; ##< ID of the signature
- conn: connection; ##< Current connection
- is_orig: bool; ##< True if current endpoint is originator
- payload_size: count; ##< Payload size of the first pkt of curr. endpoint
-
+ sig_id: string; ##< ID of the matching signature.
+ conn: connection; ##< Matching connection.
+ is_orig: bool; ##< True if matching endpoint is originator.
+ payload_size: count; ##< Payload size of the first matching packet of current endpoint.
};
-# This type is no longer used
-# TODO: remove any use of this from the core.
+# Deprecated.
+#
+# .. todo:: This type is no longer used. Remove any reference of this from the
+# core.
type software_version: record {
- major: int; # Major version number
- minor: int; # Minor version number
- minor2: int; # Minor subversion number
- addl: string; # Additional version string (e.g. "beta42")
+ major: int;
+ minor: int;
+ minor2: int;
+ addl: string;
};
-# This type is no longer used
-# TODO: remove any use of this from the core.
+# Deprecated.
+#
+# .. todo:: This type is no longer used. Remove any reference of this from the
+# core.
type software: record {
- name: string; # Unique name of a software, e.g., "OS"
+ name: string;
version: software_version;
};
-# The following describe the quality of signature matches used
-# for passive fingerprinting.
+## Quality of passive fingerprinting matches.
+##
+## .. .. bro:see:: OS_version
type OS_version_inference: enum {
- direct_inference, generic_inference, fuzzy_inference,
+ direct_inference, ##< TODO.
+ generic_inference, ##< TODO.
+ fuzzy_inference, ##< TODO.
};
+## Passive fingerprinting match.
+##
+## .. bro:see:: OS_version_found
type OS_version: record {
- genre: string; # Linux, Windows, AIX, ...
- detail: string; # kernel version or such
- dist: count; # how far is the host away from the sensor (TTL)?
- match_type: OS_version_inference;
+ genre: string; ##< Linux, Windows, AIX, ...
+ detail: string; ##< Lernel version or such.
+ dist: count; ##< How far is the host away from the sensor (TTL)?.
+ match_type: OS_version_inference; ##< Quality of the match.
};
-# Defines for which subnets we should do passive fingerprinting.
+## Defines for which subnets we should do passive fingerprinting.
+##
+## .. bro:see:: OS_version_found
global generate_OS_version_event: set[subnet] &redef;
-# Type used to report load samples via load_sample(). For now,
-# it's a set of names (event names, source file names, and perhaps
-# 's, which were seen during the sample.
+# Type used to report load samples via :bro:see:`load_sample`. For now, it's a
+# set of names (event names, source file names, and perhaps ````, which were seen during the sample.
type load_sample_info: set[string];
-# NetFlow-related data structures.
-
-## The following provides a mean to sort together NetFlow headers and flow
-## records at the script level. rcvr_id equals the name of the file
-## (e.g., netflow.dat) or the socket address (e.g., 127.0.0.1:5555),
-## or an explicit name if specified to -y or -Y; pdu_id is just a serial
-## number, ignoring any overflows.
+## ID for NetFlow header. This is primarily a means to sort together NetFlow
+## headers and flow records at the script level.
type nfheader_id: record {
+ ## Name of the NetFlow file (e.g., ``netflow.dat``) or the receiving socket address
+ ## (e.g., ``127.0.0.1:5555``), or an explicit name if specified to
+ ## ``-y`` or ``-Y``.
rcvr_id: string;
+ ## A serial number, ignoring any overflows.
pdu_id: count;
};
+## A NetFlow v5 header.
+##
+## .. bro:see:: netflow_v5_header
type nf_v5_header: record {
- h_id: nfheader_id; ##< ID for sorting, per the above
- cnt: count;
- sysuptime: interval; ##< router's uptime
- exporttime: time; ##< when the data was exported
- flow_seq: count;
- eng_type: count;
- eng_id: count;
- sample_int: count;
- exporter: addr;
+ h_id: nfheader_id; ##< ID for sorting.
+ cnt: count; ##< TODO.
+ sysuptime: interval; ##< Router's uptime.
+ exporttime: time; ##< When the data was exported.
+ flow_seq: count; ##< Sequence number.
+ eng_type: count; ##< Engine type.
+ eng_id: count; ##< Engine ID.
+ sample_int: count; ##< Sampling interval.
+ exporter: addr; ##< Exporter address.
};
-type nf_v5_record: record {
- h_id: nfheader_id;
- id: conn_id;
- nexthop: addr;
- input: count;
- output: count;
- pkts: count;
- octets: count;
- first: time;
- last: time;
- tcpflag_fin: bool; ##< Taken from tcpflags in NF V5; or directly.
- tcpflag_syn: bool;
- tcpflag_rst: bool;
- tcpflag_psh: bool;
- tcpflag_ack: bool;
- tcpflag_urg: bool;
- proto: count;
- tos: count;
- src_as: count;
- dst_as: count;
- src_mask: count;
- dst_mask: count;
+## A NetFlow v5 record.
+##
+## .. bro:see:: netflow_v5_record
+type nf_v5_record: record {
+ h_id: nfheader_id; ##< ID for sorting.
+ id: conn_id; ##< Connection ID.
+ nexthop: addr; ##< Address of next hop.
+ input: count; ##< Input interface.
+ output: count; ##< Output interface.
+ pkts: count; ##< Number of packets.
+ octets: count; ##< Number of bytes.
+ first: time; ##< Timestamp of first packet.
+ last: time; ##< Timestamp of last packet.
+ tcpflag_fin: bool; ##< FIN flag for TCP flows.
+ tcpflag_syn: bool; ##< SYN flag for TCP flows.
+ tcpflag_rst: bool; ##< RST flag for TCP flows.
+ tcpflag_psh: bool; ##< PSH flag for TCP flows.
+ tcpflag_ack: bool; ##< ACK flag for TCP flows.
+ tcpflag_urg: bool; ##< URG flag for TCP flows.
+ proto: count; ##< IP protocol.
+ tos: count; ##< Type of service.
+ src_as: count; ##< Source AS.
+ dst_as: count; ##< Destination AS.
+ src_mask: count; ##< Source mask.
+ dst_mask: count; ##< Destination mask.
};
-## The peer record and the corresponding set type used by the
-## BitTorrent analyzer.
+## A BitTorrent peer.
+##
+## .. bro:see:: bittorrent_peer_set
type bittorrent_peer: record {
- h: addr;
- p: port;
+ h: addr; ##< The peer's address.
+ p: port; ##< The peer's port.
};
+
+## A set of BitTorrent peers.
+##
+## .. bro:see:: bt_tracker_response
type bittorrent_peer_set: set[bittorrent_peer];
-## The benc value record and the corresponding table type used by the
-## BitTorrenttracker analyzer. Note that "benc" = Bencode ("Bee-Encode"),
-## per http://en.wikipedia.org/wiki/Bencode.
+## BitTorrent "benc" value. Note that "benc" = Bencode ("Bee-Encode"), per
+## http://en.wikipedia.org/wiki/Bencode.
+##
+## .. bro:see:: bittorrent_benc_dir
type bittorrent_benc_value: record {
- i: int &optional;
- s: string &optional;
- d: string &optional;
- l: string &optional;
+ i: int &optional; ##< TODO.
+ s: string &optional; ##< TODO.
+ d: string &optional; ##< TODO.
+ l: string &optional; ##< TODO.
};
+
+## A table of BitTorrent "benc" values.
+##
+## .. bro:see:: bt_tracker_response
type bittorrent_benc_dir: table[string] of bittorrent_benc_value;
-## The header table type used by the bittorrenttracker analyzer.
+## Header table type used by BitTorrent analyzer.
+##
+## .. bro:see:: bt_tracker_request bt_tracker_response
+## bt_tracker_response_not_ok
type bt_tracker_headers: table[string] of string;
@load base/event.bif
-# The filter the user has set via the -f command line options, or
-# empty if none.
+## BPF filter the user has set via the -f command line options. Empty if none.
const cmd_line_bpf_filter = "" &redef;
-## Rotate logs every x interval.
+## Deprecated.
const log_rotate_interval = 0 sec &redef;
-## If set, rotate logs at given time + i * log_rotate_interval.
-## (string is time in 24h format, e.g., "18:00").
+## Deprecated.
const log_rotate_base_time = "0:00" &redef;
-## Rotate logs when they reach this size (in bytes). Note, the
-## parameter is a double rather than a count to enable easy expression
-## of large values such as 1e7 or exceeding 2^32.
+## Deprecated.
const log_max_size = 0.0 &redef;
-## Default public key for encrypting log files.
+## Deprecated.
const log_encryption_key = "" &redef;
-## Write profiling info into this file.
+## Write profiling info into this file in regular intervals. The easiest way to
+## activate profiling is loading :doc:`/scripts/policy/misc/profiling`.
+##
+## .. bro:see:: profiling_interval expensive_profiling_multiple segment_profiling
global profiling_file: file &redef;
-## Update interval for profiling (0 disables).
+## Update interval for profiling (0 disables). The easiest way to activate
+## profiling is loading :doc:`/scripts/policy/misc/profiling`.
+##
+## .. bro:see:: profiling_file expensive_profiling_multiple segment_profiling
const profiling_interval = 0 secs &redef;
-## Multiples of profiling_interval at which (expensive) memory
-## profiling is done (0 disables).
+## Multiples of profiling_interval at which (more expensive) memory profiling is
+## done (0 disables).
+##
+## .. bro:see:: profiling_interval profiling_file segment_profiling
const expensive_profiling_multiple = 0 &redef;
## If true, then write segment profiling information (very high volume!)
-## in addition to statistics.
+## in addition to profiling statistics.
+##
+## .. bro:see:: profiling_interval expensive_profiling_multiple profiling_file
const segment_profiling = F &redef;
-## Output packet profiling information every secs (mode 1),
-## every packets (mode 2), or every bytes (mode 3).
-## Mode 0 disables.
+## Output modes for packet profiling information.
+##
+## .. bro:see:: pkt_profile_mode pkt_profile_freq pkt_profile_mode pkt_profile_file
type pkt_profile_modes: enum {
- PKT_PROFILE_MODE_NONE,
- PKT_PROFILE_MODE_SECS,
- PKT_PROFILE_MODE_PKTS,
- PKT_PROFILE_MODE_BYTES,
+ PKT_PROFILE_MODE_NONE, ##< No output.
+ PKT_PROFILE_MODE_SECS, ##< Output every :bro:see:`pkt_profile_freq` seconds.
+ PKT_PROFILE_MODE_PKTS, ##< Output every :bro:see:`pkt_profile_freq` packets.
+ PKT_PROFILE_MODE_BYTES, ##< Output every :bro:see:`pkt_profile_freq` bytes.
};
+
+## Output modes for packet profiling information.
+##
+## .. bro:see:: pkt_profile_modes pkt_profile_freq pkt_profile_mode pkt_profile_file
const pkt_profile_mode = PKT_PROFILE_MODE_NONE &redef;
## Frequency associated with packet profiling.
+##
+## .. bro:see:: pkt_profile_modes pkt_profile_mode pkt_profile_mode pkt_profile_file
const pkt_profile_freq = 0.0 &redef;
## File where packet profiles are logged.
+##
+## .. bro:see:: pkt_profile_modes pkt_profile_freq pkt_profile_mode pkt_profile_mode
global pkt_profile_file: file &redef;
-## Rate at which to generate load_sample events, *if* you've also
-## defined a load_sample handler. Units are inverse number of packets;
-## e.g., a value of 20 means "roughly one in every 20 packets".
+## Rate at which to generate :bro:see:`load_sample` events. As all
+## events, the event is only generated if you've also defined a
+## :bro:see:`load_sample` handler. Units are inverse number of packets; e.g., a
+## value of 20 means "roughly one in every 20 packets".
+##
+## .. bro:see:: load_sample
global load_sample_freq = 20 &redef;
-## Rate at which to generate gap_report events assessing to what
-## degree the measurement process appears to exhibit loss.
+## Rate at which to generate :bro:see:`gap_report` events assessing to what degree
+## the measurement process appears to exhibit loss.
+##
+## .. bro:see:: gap_report
const gap_report_freq = 1.0 sec &redef;
-## Whether we want content_gap and drop reports for partial connections
-## (a connection is partial if it is missing a full handshake). Note that
-## gap reports for partial connections might not be reliable.
+## Whether we want :bro:see:`content_gap` and :bro:see:`gap_report` for partial
+## connections. A connection is partial if it is missing a full handshake. Note
+## that gap reports for partial connections might not be reliable.
+##
+## .. bro:see:: content_gap gap_report partial_connection
const report_gaps_for_partial = F &redef;
-## Globals associated with entire-run statistics on gaps (useful
-## for final summaries).
-
-## The CA certificate file to authorize remote Bros.
+## The CA certificate file to authorize remote Bros/Broccolis.
+##
+## .. bro:see:: ssl_private_key ssl_passphrase
const ssl_ca_certificate = "" &redef;
## File containing our private key and our certificate.
+##
+## .. bro:see:: ssl_ca_certificate ssl_passphrase
const ssl_private_key = "" &redef;
## The passphrase for our private key. Keeping this undefined
## causes Bro to prompt for the passphrase.
+##
+## .. bro:see:: ssl_private_key ssl_ca_certificate
const ssl_passphrase = "" &redef;
-## Whether the Bro-level packet filter drops packets per default or not.
+## Default mode for Bro's user-space dynamic packet filter. If true, packets that
+## aren't explicitly allowed through, are dropped from any further processing.
+##
+## .. note:: This is not the BPF packet filter but an additional dynamic filter
+## that Bro optionally applies just before normal processing starts.
+##
+## .. bro:see:: install_dst_addr_filter install_dst_net_filter
+## install_src_addr_filter install_src_net_filter uninstall_dst_addr_filter
+## uninstall_dst_net_filter uninstall_src_addr_filter uninstall_src_net_filter
const packet_filter_default = F &redef;
## Maximum size of regular expression groups for signature matching.
const sig_max_group_size = 50 &redef;
-## If true, send logger messages to syslog.
+## Deprecated. No longer functional.
const enable_syslog = F &redef;
-## This is transmitted to peers receiving our events.
+## Description transmitted to remote communication peers for identification.
const peer_description = "bro" &redef;
-## If true, broadcast events/state received from one peer to other peers.
+## If true, broadcast events received from one peer to all other peers.
+##
+## .. bro:see:: forward_remote_state_changes
##
-## .. note:: These options are only temporary. They will disappear when we get
-## a more sophisticated script-level communication framework.
+## .. note:: This option is only temporary and will disappear once we get a more
+## sophisticated script-level communication framework.
const forward_remote_events = F &redef;
-## See :bro:id:`forward_remote_events`
+
+## If true, broadcast state updates received from one peer to all other peers.
+##
+## .. bro:see:: forward_remote_events
+##
+## .. note:: This option is only temporary and will disappear once we get a more
+## sophisticated script-level communication framework.
const forward_remote_state_changes = F &redef;
+## Place-holder constant indicating "no peer".
const PEER_ID_NONE = 0;
-## Whether to use the connection tracker.
+## Deprecated.
+##
+## .. todo:: The connection compressor is scheduled to be removed from Bro.
const use_connection_compressor = F &redef;
-## Whether compressor should handle refused connections itself.
+## Deprecated.
+##
+## .. todo:: The connection compressor is scheduled to be removed from Bro.
const cc_handle_resets = F &redef;
-## Whether compressor should only take care of initial SYNs.
-## (By default on, this is basically "connection compressor lite".)
+## Deprecated.
+##
+## .. todo:: The connection compressor is scheduled to be removed from Bro.
const cc_handle_only_syns = T &redef;
-## Whether compressor instantiates full state when originator sends a
-## non-control packet.
+## Deprecated.
+##
+## .. todo:: The connection compressor is scheduled to be removed from Bro.
const cc_instantiate_on_data = F &redef;
-# Signature payload pattern types
-# TODO: use enum to help autodoc
-const SIG_PATTERN_PAYLOAD = 0;
-const SIG_PATTERN_HTTP = 1;
-const SIG_PATTERN_FTP = 2;
-const SIG_PATTERN_FINGER = 3;
+# Signature payload pattern types.
+# todo::use enum to help autodoc
+# todo::Still used?
+#const SIG_PATTERN_PAYLOAD = 0;
+#const SIG_PATTERN_HTTP = 1;
+#const SIG_PATTERN_FTP = 2;
+#const SIG_PATTERN_FINGER = 3;
-# Log-levels for remote_log.
-# Eventually we should create a general logging framework and merge these in.
-# TODO: use enum to help autodoc
-const REMOTE_LOG_INFO = 1;
-const REMOTE_LOG_ERROR = 2;
+# Deprecated.
+# todo::Should use the new logging framework directly.
+const REMOTE_LOG_INFO = 1; ##< Deprecated.
+const REMOTE_LOG_ERROR = 2; ##< Deprecated.
-# Sources for remote_log.
-# TODO: use enum to help autodoc
-const REMOTE_SRC_CHILD = 1;
-const REMOTE_SRC_PARENT = 2;
-const REMOTE_SRC_SCRIPT = 3;
+# Source of logging messages from the communication framework.
+# todo::these should go into an enum to make them autodoc'able.
+const REMOTE_SRC_CHILD = 1; ##< Message from the child process.
+const REMOTE_SRC_PARENT = 2; ##< Message from the parent process.
+const REMOTE_SRC_SCRIPT = 3; ##< Message from a policy script.
## Synchronize trace processing at a regular basis in pseudo-realtime mode.
+##
+## .. bro:see:: remote_trace_sync_peers
const remote_trace_sync_interval = 0 secs &redef;
-## Number of peers across which to synchronize trace processing.
+## Number of peers across which to synchronize trace processing in
+## pseudo-realtime mode.
+##
+## .. bro:see:: remote_trace_sync_interval
const remote_trace_sync_peers = 0 &redef;
-## Whether for &synchronized state to send the old value as a consistency check.
+## Whether for :bro:attr:`&synchronized` state to send the old value as a
+## consistency check.
const remote_check_sync_consistency = F &redef;
## Analyzer tags. The core automatically defines constants
-## ANALYZER_*, e.g., ANALYZER_HTTP.
+## ``ANALYZER_*``, e.g., ``ANALYZER_HTTP``.
+##
+## .. bro:see:: dpd_config
+##
+## .. todo::We should autodoc these automaticallty generated constants.
type AnalyzerTag: count;
-# DPD configuration.
-
+## Set of ports activating a particular protocol analysis.
+##
+## .. bro:see:: dpd_config
type dpd_protocol_config: record {
- ports: set[port] &optional;
+ ports: set[port] &optional; ##< Set of ports.
};
+## Port configuration for Bro's "dynamic protocol detection". Protocol
+## analyzers can be activated via either well-known ports or content analysis.
+## This table defines the ports.
+##
+## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
+## dpd_match_only_beginning dpd_ignore_ports
const dpd_config: table[AnalyzerTag] of dpd_protocol_config = {} &redef;
## Reassemble the beginning of all TCP connections before doing
-## signature-matching for protocol detection.
+## signature-matching. Enabling this provides more accurate matching at the
+## expensive of CPU cycles.
+##
+## .. bro:see:: dpd_config dpd_buffer_size
+## dpd_match_only_beginning dpd_ignore_ports
+##
+## .. note:: Despite the name, this option affects *all* signature matching, not
+## only signatures used for dynamic protocol detection.
const dpd_reassemble_first_packets = T &redef;
-## Size of per-connection buffer in bytes. If the buffer is full, data is
-## deleted and lost to analyzers that are activated afterwards.
+## Size of per-connection buffer used for dynamic protocol detection. For each
+## connection, Bro buffers this initial amount of payload in memory so that
+## complete protocol analysis can start even after the initial packets have
+## already passed through (i.e., when a DPD signature matches only later).
+## However, once the buffer is full, data is deleted and lost to analyzers that are
+## activated afterwards. Then only analyzers that can deal with partial
+## connections will be able to analyze the session.
+##
+## .. bro:see:: dpd_reassemble_first_packets dpd_config dpd_match_only_beginning
+## dpd_ignore_ports
const dpd_buffer_size = 1024 &redef;
## If true, stops signature matching if dpd_buffer_size has been reached.
+##
+## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
+## dpd_config dpd_ignore_ports
+##
+## .. note:: Despite the name, this option affects *all* signature matching, not
+## only signatures used for dynamic protocol detection.
const dpd_match_only_beginning = T &redef;
-## If true, don't consider any ports for deciding which analyzer to use.
+## If true, don't consider any ports for deciding which protocol analyzer to
+## use. If so, the value of :bro:see:`dpd_config` is ignored.
+##
+## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
+## dpd_match_only_beginning dpd_config
const dpd_ignore_ports = F &redef;
-## Ports which the core considers being likely used by servers.
+## Ports which the core considers being likely used by servers. For ports in
+## this set, is may heuristically decide to flip the direction of the
+## connection if it misses the initial handshake.
const likely_server_ports: set[port] &redef;
-## Set of all ports for which we know an analyzer.
+## Deprated. Set of all ports for which we know an analyzer, built by
+## :doc:`/scripts/base/frameworks/dpd/main`.
+##
+## .. todo::This should be defined by :doc:`/scripts/base/frameworks/dpd/main`
+## itself we still need it.
global dpd_analyzer_ports: table[port] of set[AnalyzerTag];
## Per-incident timer managers are drained after this amount of inactivity.
@@ -1474,35 +2296,39 @@ const time_machine_profiling = F &redef;
## If true, warns about unused event handlers at startup.
const check_for_unused_event_handlers = F &redef;
-## If true, dumps all invoked event handlers at startup.
-const dump_used_event_handlers = F &redef;
+# If true, dumps all invoked event handlers at startup.
+# todo::Still used?
+# const dump_used_event_handlers = F &redef;
-## If true, we suppress prints to local files if we have a receiver for
-## print_hook events. Ignored for files with a &disable_print_hook attribute.
+## Deprecated.
const suppress_local_output = F &redef;
## Holds the filename of the trace file given with -w (empty if none).
+##
+## .. bro:see:: record_all_packets
const trace_output_file = "";
-## If a trace file is given, dump *all* packets seen by Bro into it.
-## By default, Bro applies (very few) heuristics to reduce the volume.
-## A side effect of setting this to true is that we can write the
-## packets out before we actually process them, which can be helpful
-## for debugging in case the analysis triggers a crash.
+## If a trace file is given with ``-w``, dump *all* packets seen by Bro into it. By
+## default, Bro applies (very few) heuristics to reduce the volume. A side effect
+## of setting this to true is that we can write the packets out before we actually
+## process them, which can be helpful for debugging in case the analysis triggers a
+## crash.
+##
+## .. bro:see:: trace_output_file
const record_all_packets = F &redef;
-## Some connections (e.g., SSH) retransmit the acknowledged last
-## byte to keep the connection alive. If ignore_keep_alive_rexmit
-## is set to T, such retransmissions will be excluded in the rexmit
-## counter in conn_stats.
+## Ignore certain TCP retransmissions for :bro:see:`conn_stats`. Some connections
+## (e.g., SSH) retransmit the acknowledged last byte to keep the connection alive.
+## If *ignore_keep_alive_rexmit* is set to true, such retransmissions will be
+## excluded in the rexmit counter in :bro:see:`conn_stats`.
+##
+## .. bro:see:: conn_stats
const ignore_keep_alive_rexmit = F &redef;
-## Skip HTTP data portions for performance considerations (the skipped
-## portion will not go through TCP reassembly).
-const skip_http_data = F &redef;
-
## Whether the analysis engine parses IP packets encapsulated in
-## UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro.
+## UDP tunnels.
+##
+## .. bro:see:: tunnel_port
const parse_udp_tunnels = F &redef;
## Number of bytes per packet to capture from live interfaces.
diff --git a/scripts/base/protocols/conn/contents.bro b/scripts/base/protocols/conn/contents.bro
index feabb1303c..2e6b547ab1 100644
--- a/scripts/base/protocols/conn/contents.bro
+++ b/scripts/base/protocols/conn/contents.bro
@@ -1,23 +1,27 @@
##! This script can be used to extract either the originator's data or the
##! responders data or both. By default nothing is extracted, and in order
##! to actually extract data the ``c$extract_orig`` and/or the
-##! ``c$extract_resp`` variable must be set to T. One way to achieve this
-##! would be to handle the connection_established event elsewhere and set the
-##! extract_orig and extract_resp options there. However, there may be trouble
-##! with the timing due the event queue delay.
-##! This script does not work well in a cluster context unless it has a
-##! remotely mounted disk to write the content files to.
+##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
+##! would be to handle the :bro:id:`connection_established` event elsewhere
+##! and set the ``extract_orig`` and ``extract_resp`` options there.
+##! However, there may be trouble with the timing due to event queue delay.
+##!
+##! .. note::
+##!
+##! This script does not work well in a cluster context unless it has a
+##! remotely mounted disk to write the content files to.
@load base/utils/files
module Conn;
export {
- ## The prefix given to files as they are opened on disk.
+ ## The prefix given to files containing extracted connections as they are
+ ## opened on disk.
const extraction_prefix = "contents" &redef;
- ## If this variable is set to T, then all contents of all files will be
- ## extracted.
+ ## If this variable is set to ``T``, then all contents of all connections
+ ## will be extracted.
const default_extract = F &redef;
}
diff --git a/scripts/base/protocols/conn/inactivity.bro b/scripts/base/protocols/conn/inactivity.bro
index 04dab62470..28df192de3 100644
--- a/scripts/base/protocols/conn/inactivity.bro
+++ b/scripts/base/protocols/conn/inactivity.bro
@@ -4,7 +4,7 @@
module Conn;
export {
- ## Define inactivty timeouts by the service detected being used over
+ ## Define inactivity timeouts by the service detected being used over
## the connection.
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
# For interactive services, allow longer periods of inactivity.
diff --git a/scripts/base/protocols/conn/main.bro b/scripts/base/protocols/conn/main.bro
index 751fe8f6cf..34ec12fa56 100644
--- a/scripts/base/protocols/conn/main.bro
+++ b/scripts/base/protocols/conn/main.bro
@@ -1,17 +1,33 @@
+##! This script manages the tracking/logging of general information regarding
+##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
+##! be interpreted using flow semantics (sequence of packets from a source
+##! host/post to a destination host/port). Further, ICMP "ports" are to
+##! be interpreted as the source port meaning the ICMP message type and
+##! the destination port being the ICMP message code.
+
@load base/utils/site
module Conn;
export {
+ ## The connection logging stream identifier.
redef enum Log::ID += { LOG };
+ ## The record type which contains column fields of the connection log.
type Info: record {
## This is the time of the first packet.
ts: time &log;
+ ## A unique identifier of a connection.
uid: string &log;
+ ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
+ ## The transport layer protocol of the connection.
proto: transport_proto &log;
+ ## An identification of an application protocol being sent over the
+ ## the connection.
service: string &log &optional;
+ ## How long the connection lasted. For 3-way or 4-way connection
+ ## tear-downs, this will not include the final ACK.
duration: interval &log &optional;
## The number of payload bytes the originator sent. For TCP
## this is taken from sequence numbers and might be inaccurate
@@ -51,8 +67,8 @@ export {
## have been completed prior to the packet loss.
missed_bytes: count &log &default=0;
- ## Records the state history of (TCP) connections as
- ## a string of letters.
+ ## Records the state history of connections as a string of letters.
+ ## For TCP connections the meaning of those letters is:
##
## ====== ====================================================
## Letter Meaning
@@ -71,7 +87,8 @@ export {
## originator and lower case then means the responder.
## Also, there is compression. We only record one "d" in each direction,
## for instance. I.e., we just record that data went in that direction.
- ## This history is not meant to encode how much data that happened to be.
+ ## This history is not meant to encode how much data that happened to
+ ## be.
history: string &log &optional;
## Number of packets the originator sent.
## Only set if :bro:id:`use_conn_size_analyzer` = T
@@ -85,7 +102,9 @@ export {
## Number IP level bytes the responder sent. See ``orig_pkts``.
resp_ip_bytes: count &log &optional;
};
-
+
+ ## Event that can be handled to access the :bro:type:`Conn::Info`
+ ## record as it is sent on to the logging framework.
global log_conn: event(rec: Info);
}
diff --git a/scripts/base/protocols/dns/consts.bro b/scripts/base/protocols/dns/consts.bro
index b57170dded..fbf4aba008 100644
--- a/scripts/base/protocols/dns/consts.bro
+++ b/scripts/base/protocols/dns/consts.bro
@@ -4,9 +4,9 @@
module DNS;
export {
- const PTR = 12;
- const EDNS = 41;
- const ANY = 255;
+ const PTR = 12; ##< RR TYPE value for a domain name pointer.
+ const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
+ const ANY = 255; ##< A QTYPE value describing a request for all records.
## Mapping of DNS query type codes to human readable string representation.
const query_types = {
@@ -29,50 +29,43 @@ export {
[ANY] = "*",
} &default = function(n: count): string { return fmt("query-%d", n); };
- const code_types = {
- [0] = "X0",
- [1] = "Xfmt",
- [2] = "Xsrv",
- [3] = "Xnam",
- [4] = "Ximp",
- [5] = "X[",
- } &default="?";
-
## Errors used for non-TSIG/EDNS types.
const base_errors = {
- [0] = "NOERROR", ##< No Error
- [1] = "FORMERR", ##< Format Error
- [2] = "SERVFAIL", ##< Server Failure
- [3] = "NXDOMAIN", ##< Non-Existent Domain
- [4] = "NOTIMP", ##< Not Implemented
- [5] = "REFUSED", ##< Query Refused
- [6] = "YXDOMAIN", ##< Name Exists when it should not
- [7] = "YXRRSET", ##< RR Set Exists when it should not
- [8] = "NXRRSet", ##< RR Set that should exist does not
- [9] = "NOTAUTH", ##< Server Not Authoritative for zone
- [10] = "NOTZONE", ##< Name not contained in zone
- [11] = "unassigned-11", ##< available for assignment
- [12] = "unassigned-12", ##< available for assignment
- [13] = "unassigned-13", ##< available for assignment
- [14] = "unassigned-14", ##< available for assignment
- [15] = "unassigned-15", ##< available for assignment
- [16] = "BADVERS", ##< for EDNS, collision w/ TSIG
- [17] = "BADKEY", ##< Key not recognized
- [18] = "BADTIME", ##< Signature out of time window
- [19] = "BADMODE", ##< Bad TKEY Mode
- [20] = "BADNAME", ##< Duplicate key name
- [21] = "BADALG", ##< Algorithm not supported
- [22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt
- [3842] = "BADSIG", ##< 16 <= number collision with EDNS(16);
- ##< this is a translation from TSIG(16)
+ [0] = "NOERROR", # No Error
+ [1] = "FORMERR", # Format Error
+ [2] = "SERVFAIL", # Server Failure
+ [3] = "NXDOMAIN", # Non-Existent Domain
+ [4] = "NOTIMP", # Not Implemented
+ [5] = "REFUSED", # Query Refused
+ [6] = "YXDOMAIN", # Name Exists when it should not
+ [7] = "YXRRSET", # RR Set Exists when it should not
+ [8] = "NXRRSet", # RR Set that should exist does not
+ [9] = "NOTAUTH", # Server Not Authoritative for zone
+ [10] = "NOTZONE", # Name not contained in zone
+ [11] = "unassigned-11", # available for assignment
+ [12] = "unassigned-12", # available for assignment
+ [13] = "unassigned-13", # available for assignment
+ [14] = "unassigned-14", # available for assignment
+ [15] = "unassigned-15", # available for assignment
+ [16] = "BADVERS", # for EDNS, collision w/ TSIG
+ [17] = "BADKEY", # Key not recognized
+ [18] = "BADTIME", # Signature out of time window
+ [19] = "BADMODE", # Bad TKEY Mode
+ [20] = "BADNAME", # Duplicate key name
+ [21] = "BADALG", # Algorithm not supported
+ [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
+ [3842] = "BADSIG", # 16 <= number collision with EDNS(16);
+ # this is a translation from TSIG(16)
} &default = function(n: count): string { return fmt("rcode-%d", n); };
- # This deciphers EDNS Z field values.
+ ## This deciphers EDNS Z field values.
const edns_zfield = {
[0] = "NOVALUE", # regular entry
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
} &default="?";
+ ## Possible values of the CLASS field in resource records or QCLASS field
+ ## in query messages.
const classes = {
[1] = "C_INTERNET",
[2] = "C_CSNET",
@@ -81,4 +74,4 @@ export {
[254] = "C_NONE",
[255] = "C_ANY",
} &default = function(n: count): string { return fmt("qclass-%d", n); };
-}
\ No newline at end of file
+}
diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro
index b8cfc7b44e..56107fd02d 100644
--- a/scripts/base/protocols/dns/main.bro
+++ b/scripts/base/protocols/dns/main.bro
@@ -1,38 +1,80 @@
+##! Base DNS analysis script which tracks and logs DNS queries along with
+##! their responses.
+
@load ./consts
module DNS;
export {
+ ## The DNS logging stream identifier.
redef enum Log::ID += { LOG };
+ ## The record type which contains the column fields of the DNS log.
type Info: record {
+ ## The earliest time at which a DNS protocol message over the
+ ## associated connection is observed.
ts: time &log;
+ ## A unique identifier of the connection over which DNS messages
+ ## are being transferred.
uid: string &log;
+ ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
+ ## The transport layer protocol of the connection.
proto: transport_proto &log;
+ ## A 16 bit identifier assigned by the program that generated the
+ ## DNS query. Also used in responses to match up replies to
+ ## outstanding queries.
trans_id: count &log &optional;
+ ## The domain name that is the subject of the DNS query.
query: string &log &optional;
+ ## The QCLASS value specifying the class of the query.
qclass: count &log &optional;
+ ## A descriptive name for the class of the query.
qclass_name: string &log &optional;
+ ## A QTYPE value specifying the type of the query.
qtype: count &log &optional;
+ ## A descriptive name for the type of the query.
qtype_name: string &log &optional;
+ ## The response code value in DNS response messages.
rcode: count &log &optional;
+ ## A descriptive name for the response code value.
rcode_name: string &log &optional;
+ ## Whether the message is a query (F) or response (T).
QR: bool &log &default=F;
+ ## The Authoritative Answer bit for response messages specifies that
+ ## the responding name server is an authority for the domain name
+ ## in the question section.
AA: bool &log &default=F;
+ ## The Truncation bit specifies that the message was truncated.
TC: bool &log &default=F;
+ ## The Recursion Desired bit indicates to a name server to recursively
+ ## purse the query.
RD: bool &log &default=F;
+ ## The Recursion Available bit in a response message indicates if
+ ## the name server supports recursive queries.
RA: bool &log &default=F;
+ ## A reserved field that is currently supposed to be zero in all
+ ## queries and responses.
Z: count &log &default=0;
+ ## The set of resource descriptions in answer of the query.
answers: vector of string &log &optional;
+ ## The caching intervals of the associated RRs described by the
+ ## ``answers`` field.
TTLs: vector of interval &log &optional;
- ## This value indicates if this request/response pair is ready to be logged.
+ ## This value indicates if this request/response pair is ready to be
+ ## logged.
ready: bool &default=F;
+ ## The total number of resource records in a reply message's answer
+ ## section.
total_answers: count &optional;
+ ## The total number of resource records in a reply message's answer,
+ ## authority, and additional sections.
total_replies: count &optional;
};
+ ## A record type which tracks the status of DNS queries for a given
+ ## :bro:type:`connection`.
type State: record {
## Indexed by query id, returns Info record corresponding to
## query/response which haven't completed yet.
@@ -44,11 +86,21 @@ export {
finished_answers: set[count] &optional;
};
+ ## An event that can be handled to access the :bro:type:`DNS::Info`
+ ## record as it is sent to the logging framework.
global log_dns: event(rec: Info);
## This is called by the specific dns_*_reply events with a "reply" which
## may not represent the full data available from the resource record, but
## it's generally considered a summarization of the response(s).
+ ##
+ ## c: The connection record for which to fill in DNS reply data.
+ ##
+ ## msg: The DNS message header information for the response.
+ ##
+ ## ans: The general information of a RR response.
+ ##
+ ## reply: The specific response information according to RR type/class.
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
}
diff --git a/scripts/base/protocols/ftp/file-extract.bro b/scripts/base/protocols/ftp/file-extract.bro
index db5c8a0afa..7cee4995ba 100644
--- a/scripts/base/protocols/ftp/file-extract.bro
+++ b/scripts/base/protocols/ftp/file-extract.bro
@@ -1,4 +1,4 @@
-##! File extraction for FTP.
+##! File extraction support for FTP.
@load ./main
@load base/utils/files
@@ -6,7 +6,7 @@
module FTP;
export {
- ## Pattern of file mime types to extract from FTP entity bodies.
+ ## Pattern of file mime types to extract from FTP transfers.
const extract_file_types = /NO_DEFAULT/ &redef;
## The on-disk prefix for files to be extracted from FTP-data transfers.
@@ -14,10 +14,15 @@ export {
}
redef record Info += {
- ## The file handle for the file to be extracted
+ ## On disk file where it was extracted to.
extraction_file: file &log &optional;
+ ## Indicates if the current command/response pair should attempt to
+ ## extract the file if a file was transferred.
extract_file: bool &default=F;
+
+ ## Internal tracking of the total number of files extracted during this
+ ## session.
num_extracted_files: count &default=0;
};
@@ -33,7 +38,6 @@ event file_transferred(c: connection, prefix: string, descr: string,
if ( extract_file_types in s$mime_type )
{
s$extract_file = T;
- add s$tags["extracted_file"];
++s$num_extracted_files;
}
}
diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro
index e8eb96d3ee..9e16804a32 100644
--- a/scripts/base/protocols/ftp/main.bro
+++ b/scripts/base/protocols/ftp/main.bro
@@ -1,11 +1,7 @@
##! The logging this script does is primarily focused on logging FTP commands
##! along with metadata. For example, if files are transferred, the argument
##! will take on the full path that the client is at along with the requested
-##! file name.
-##!
-##! TODO:
-##!
-##! * Handle encrypted sessions correctly (get an example?)
+##! file name.
@load ./utils-commands
@load base/utils/paths
@@ -14,38 +10,64 @@
module FTP;
export {
+ ## The FTP protocol logging stream identifier.
redef enum Log::ID += { LOG };
-
+
+ ## List of commands that should have their command/response pairs logged.
+ const logged_commands = {
+ "APPE", "DELE", "RETR", "STOR", "STOU", "ACCT"
+ } &redef;
+
## This setting changes if passwords used in FTP sessions are captured or not.
const default_capture_password = F &redef;
+ ## User IDs that can be considered "anonymous".
+ const guest_ids = { "anonymous", "ftp", "guest" } &redef;
+
type Info: record {
+ ## Time when the command was sent.
ts: time &log;
uid: string &log;
id: conn_id &log;
+ ## User name for the current FTP session.
user: string &log &default="";
+ ## Password for the current FTP session if captured.
password: string &log &optional;
+ ## Command given by the client.
command: string &log &optional;
+ ## Argument for the command if one is given.
arg: string &log &optional;
-
+
+ ## Libmagic "sniffed" file type if the command indicates a file transfer.
mime_type: string &log &optional;
+ ## Libmagic "sniffed" file description if the command indicates a file transfer.
mime_desc: string &log &optional;
+ ## Size of the file if the command indicates a file transfer.
file_size: count &log &optional;
+
+ ## Reply code from the server in response to the command.
reply_code: count &log &optional;
+ ## Reply message from the server in response to the command.
reply_msg: string &log &optional;
+ ## Arbitrary tags that may indicate a particular attribute of this command.
tags: set[string] &log &default=set();
- ## By setting the CWD to '/.', we can indicate that unless something
+ ## Current working directory that this session is in. By making
+ ## the default value '/.', we can indicate that unless something
## more concrete is discovered that the existing but unknown
## directory is ok to use.
cwd: string &default="/.";
+
+ ## Command that is currently waiting for a response.
cmdarg: CmdArg &optional;
+ ## Queue for commands that have been sent but not yet responded to
+ ## are tracked here.
pending_commands: PendingCmds;
- ## This indicates if the session is in active or passive mode.
+ ## Indicates if the session is in active or passive mode.
passive: bool &default=F;
- ## This determines if the password will be captured for this request.
+ ## Determines if the password will be captured for this request.
capture_password: bool &default=default_capture_password;
};
@@ -56,22 +78,12 @@ export {
y: count;
z: count;
};
-
- # TODO: add this back in some form. raise a notice again?
- #const excessive_filename_len = 250 &redef;
- #const excessive_filename_trunc_len = 32 &redef;
-
- ## These are user IDs that can be considered "anonymous".
- const guest_ids = { "anonymous", "ftp", "guest" } &redef;
- ## The list of commands that should have their command/response pairs logged.
- const logged_commands = {
- "APPE", "DELE", "RETR", "STOR", "STOU", "ACCT"
- } &redef;
-
- ## This function splits FTP reply codes into the three constituent
+ ## Parse FTP reply codes into the three constituent single digit values.
global parse_ftp_reply_code: function(code: count): ReplyCode;
-
+
+ ## Event that can be handled to access the :bro:type:`FTP::Info`
+ ## record as it is sent on to the logging framework.
global log_ftp: event(rec: Info);
}
diff --git a/scripts/base/protocols/ftp/utils-commands.bro b/scripts/base/protocols/ftp/utils-commands.bro
index 40dacf9b66..ddfad3e08d 100644
--- a/scripts/base/protocols/ftp/utils-commands.bro
+++ b/scripts/base/protocols/ftp/utils-commands.bro
@@ -2,14 +2,22 @@ module FTP;
export {
type CmdArg: record {
+ ## Time when the command was sent.
ts: time;
+ ## Command.
cmd: string &default="";
+ ## Argument for the command if one was given.
arg: string &default="";
+ ## Counter to track how many commands have been executed.
seq: count &default=0;
};
-
+
+ ## Structure for tracking pending commands in the event that the client
+ ## sends a large number of commands before the server has a chance to
+ ## reply.
type PendingCmds: table[count] of CmdArg;
-
+
+ ## Possible response codes for a wide variety of FTP commands.
const cmd_reply_code: set[string, count] = {
# According to RFC 959
["", [120, 220, 421]],
diff --git a/scripts/base/protocols/http/file-extract.bro b/scripts/base/protocols/http/file-extract.bro
index ffb925ae28..466d18c3b4 100644
--- a/scripts/base/protocols/http/file-extract.bro
+++ b/scripts/base/protocols/http/file-extract.bro
@@ -8,29 +8,24 @@
module HTTP;
export {
- ## Pattern of file mime types to extract from HTTP entity bodies.
+ ## Pattern of file mime types to extract from HTTP response entity bodies.
const extract_file_types = /NO_DEFAULT/ &redef;
## The on-disk prefix for files to be extracted from HTTP entity bodies.
const extraction_prefix = "http-item" &redef;
redef record Info += {
- ## This field can be set per-connection to determine if the entity body
- ## will be extracted. It must be set to T on or before the first
- ## entity_body_data event.
- extracting_file: bool &default=F;
-
- ## This is the holder for the file handle as the file is being written
- ## to disk.
+ ## On-disk file where the response body was extracted to.
extraction_file: file &log &optional;
- };
-
- redef record State += {
- entity_bodies: count &default=0;
+
+ ## Indicates if the response body is to be extracted or not. Must be
+ ## set before or by the first :bro:id:`http_entity_data` event for the
+ ## content.
+ extract_file: bool &default=F;
};
}
-event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=5
+event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=-5
{
# Client body extraction is not currently supported in this script.
if ( is_orig )
@@ -41,8 +36,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
if ( c$http?$mime_type &&
extract_file_types in c$http$mime_type )
{
- c$http$extracting_file = T;
- local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", ++c$http_state$entity_bodies);
+ c$http$extract_file = T;
+ }
+
+ if ( c$http$extract_file )
+ {
+ local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", c$http_state$current_response);
local fname = generate_extraction_filename(extraction_prefix, c, suffix);
c$http$extraction_file = open(fname);
@@ -50,12 +49,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
}
}
- if ( c$http$extracting_file )
+ if ( c$http?$extraction_file )
print c$http$extraction_file, data;
}
event http_end_entity(c: connection, is_orig: bool)
{
- if ( c$http$extracting_file )
+ if ( c$http?$extraction_file )
close(c$http$extraction_file);
}
diff --git a/scripts/base/protocols/http/file-hash.bro b/scripts/base/protocols/http/file-hash.bro
index 094a905eeb..7e8e5cceaf 100644
--- a/scripts/base/protocols/http/file-hash.bro
+++ b/scripts/base/protocols/http/file-hash.bro
@@ -11,7 +11,8 @@ export {
};
redef record Info += {
- ## The MD5 sum for a file transferred over HTTP will be stored here.
+ ## MD5 sum for a file transferred over HTTP calculated from the
+ ## response body.
md5: string &log &optional;
## This value can be set per-transfer to determine per request
@@ -19,8 +20,8 @@ export {
## set to T at the time of or before the first chunk of body data.
calc_md5: bool &default=F;
- ## This boolean value indicates if an MD5 sum is currently being
- ## calculated for the current file transfer.
+ ## Indicates if an MD5 sum is being calculated for the current
+ ## request/response pair.
calculating_md5: bool &default=F;
};
diff --git a/scripts/base/protocols/http/file-ident.bro b/scripts/base/protocols/http/file-ident.bro
index de209d2785..f2cb9d19ac 100644
--- a/scripts/base/protocols/http/file-ident.bro
+++ b/scripts/base/protocols/http/file-ident.bro
@@ -1,5 +1,4 @@
-##! This script is involved in the identification of file types in HTTP
-##! response bodies.
+##! Identification of file types in HTTP response bodies with file content sniffing.
@load base/frameworks/signatures
@load base/frameworks/notice
@@ -15,27 +14,23 @@ module HTTP;
export {
redef enum Notice::Type += {
- # This notice is thrown when the file extension doesn't
- # seem to match the file contents.
+ ## Indicates when the file extension doesn't seem to match the file contents.
Incorrect_File_Type,
};
redef record Info += {
- ## This will record the mime_type identified.
+ ## Mime type of response body identified by content sniffing.
mime_type: string &log &optional;
- ## This indicates that no data of the current file transfer has been
+ ## Indicates that no data of the current file transfer has been
## seen yet. After the first :bro:id:`http_entity_data` event, it
- ## will be set to T.
+ ## will be set to F.
first_chunk: bool &default=T;
};
-
- redef enum Tags += {
- IDENTIFIED_FILE
- };
- # Create regexes that *should* in be in the urls for specifics mime types.
- # Notices are thrown if the pattern doesn't match the url for the file type.
+ ## Mapping between mime types and regular expressions for URLs
+ ## The :bro:enum:`HTTP::Incorrect_File_Type` notice is generated if the pattern
+ ## doesn't match the mime type that was discovered.
const mime_types_extensions: table[string] of pattern = {
["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/,
} &redef;
diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro
index 59107bb4c7..6571548145 100644
--- a/scripts/base/protocols/http/main.bro
+++ b/scripts/base/protocols/http/main.bro
@@ -1,3 +1,7 @@
+##! Implements base functionality for HTTP analysis. The logging model is
+##! to log request/response pairs and all relevant metadata together in
+##! a single record.
+
@load base/utils/numbers
@load base/utils/files
@@ -8,6 +12,7 @@ export {
## Indicate a type of attack or compromise in the record to be logged.
type Tags: enum {
+ ## Placeholder.
EMPTY
};
@@ -15,64 +20,69 @@ export {
const default_capture_password = F &redef;
type Info: record {
- ts: time &log;
- uid: string &log;
- id: conn_id &log;
- ## This represents the pipelined depth into the connection of this
+ ## Timestamp for when the request happened.
+ ts: time &log;
+ uid: string &log;
+ id: conn_id &log;
+ ## Represents the pipelined depth into the connection of this
## request/response transaction.
- trans_depth: count &log;
- ## The verb used in the HTTP request (GET, POST, HEAD, etc.).
- method: string &log &optional;
- ## The value of the HOST header.
- host: string &log &optional;
- ## The URI used in the request.
- uri: string &log &optional;
- ## The value of the "referer" header. The comment is deliberately
+ trans_depth: count &log;
+ ## Verb used in the HTTP request (GET, POST, HEAD, etc.).
+ method: string &log &optional;
+ ## Value of the HOST header.
+ host: string &log &optional;
+ ## URI used in the request.
+ uri: string &log &optional;
+ ## Value of the "referer" header. The comment is deliberately
## misspelled like the standard declares, but the name used here is
## "referrer" spelled correctly.
- referrer: string &log &optional;
- ## The value of the User-Agent header from the client.
- user_agent: string &log &optional;
- ## The actual uncompressed content size of the data transferred from
+ referrer: string &log &optional;
+ ## Value of the User-Agent header from the client.
+ user_agent: string &log &optional;
+ ## Actual uncompressed content size of the data transferred from
## the client.
- request_body_len: count &log &default=0;
- ## The actual uncompressed content size of the data transferred from
+ request_body_len: count &log &default=0;
+ ## Actual uncompressed content size of the data transferred from
## the server.
response_body_len: count &log &default=0;
- ## The status code returned by the server.
+ ## Status code returned by the server.
status_code: count &log &optional;
- ## The status message returned by the server.
+ ## Status message returned by the server.
status_msg: string &log &optional;
- ## The last 1xx informational reply code returned by the server.
+ ## Last seen 1xx informational reply code returned by the server.
info_code: count &log &optional;
- ## The last 1xx informational reply message returned by the server.
+ ## Last seen 1xx informational reply message returned by the server.
info_msg: string &log &optional;
- ## The filename given in the Content-Disposition header
- ## sent by the server.
+ ## Filename given in the Content-Disposition header sent by the server.
filename: string &log &optional;
- ## This is a set of indicators of various attributes discovered and
+ ## A set of indicators of various attributes discovered and
## related to a particular request/response pair.
tags: set[Tags] &log;
- ## The username if basic-auth is performed for the request.
+ ## Username if basic-auth is performed for the request.
username: string &log &optional;
- ## The password if basic-auth is performed for the request.
+ ## Password if basic-auth is performed for the request.
password: string &log &optional;
- ## This determines if the password will be captured for this request.
+ ## Determines if the password will be captured for this request.
capture_password: bool &default=default_capture_password;
## All of the headers that may indicate if the request was proxied.
proxied: set[string] &log &optional;
};
+ ## Structure to maintain state for an HTTP connection with multiple
+ ## requests and responses.
type State: record {
+ ## Pending requests.
pending: table[count] of Info;
- current_response: count &default=0;
+ ## Current request in the pending queue.
current_request: count &default=0;
+ ## Current response in the pending queue.
+ current_response: count &default=0;
};
- ## The list of HTTP headers typically used to indicate a proxied request.
+ ## A list of HTTP headers typically used to indicate proxied requests.
const proxy_headers: set[string] = {
"FORWARDED",
"X-FORWARDED-FOR",
@@ -83,6 +93,8 @@ export {
"PROXY-CONNECTION",
} &redef;
+ ## Event that can be handled to access the HTTP record as it is sent on
+ ## to the logging framework.
global log_http: event(rec: Info);
}
diff --git a/scripts/base/protocols/http/utils.bro b/scripts/base/protocols/http/utils.bro
index 6e2583bc75..0f2666fade 100644
--- a/scripts/base/protocols/http/utils.bro
+++ b/scripts/base/protocols/http/utils.bro
@@ -5,8 +5,31 @@
module HTTP;
export {
+ ## Given a string containing a series of key-value pairs separated by "=",
+ ## this function can be used to parse out all of the key names.
+ ##
+ ## data: The raw data, such as a URL or cookie value.
+ ##
+ ## kv_splitter: A regular expression representing the separator between
+ ## key-value pairs.
+ ##
+ ## Returns: A vector of strings containing the keys.
global extract_keys: function(data: string, kv_splitter: pattern): string_vec;
+
+ ## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
+ ## edge cases such as proxied requests appropriately.
+ ##
+ ## rec: An :bro:type:`HTTP::Info` record.
+ ##
+ ## Returns: A URL, not prefixed by "http://".
global build_url: function(rec: Info): string;
+
+ ## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
+ ## edge cases such as proxied requests appropriately.
+ ##
+ ## rec: An :bro:type:`HTTP::Info` record.
+ ##
+ ## Returns: A URL prefixed with "http://".
global build_url_http: function(rec: Info): string;
}
diff --git a/scripts/base/protocols/irc/dcc-send.bro b/scripts/base/protocols/irc/dcc-send.bro
index b2a48a472a..9604848777 100644
--- a/scripts/base/protocols/irc/dcc-send.bro
+++ b/scripts/base/protocols/irc/dcc-send.bro
@@ -5,8 +5,9 @@
##! but that connection will actually be between B and C which could be
##! analyzed on a different worker.
##!
-##! Example line from IRC server indicating that the DCC SEND is about to start:
-##! PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A
+
+# Example line from IRC server indicating that the DCC SEND is about to start:
+# PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A
@load ./main
@load base/utils/files
@@ -14,24 +15,25 @@
module IRC;
export {
- redef enum Tag += { EXTRACTED_FILE };
-
## Pattern of file mime types to extract from IRC DCC file transfers.
const extract_file_types = /NO_DEFAULT/ &redef;
- ## The on-disk prefix for files to be extracted from IRC DCC file transfers.
+ ## On-disk prefix for files to be extracted from IRC DCC file transfers.
const extraction_prefix = "irc-dcc-item" &redef;
redef record Info += {
- dcc_file_name: string &log &optional;
- dcc_file_size: count &log &optional;
- dcc_mime_type: string &log &optional;
+ ## DCC filename requested.
+ dcc_file_name: string &log &optional;
+ ## Size of the DCC transfer as indicated by the sender.
+ dcc_file_size: count &log &optional;
+ ## Sniffed mime type of the file.
+ dcc_mime_type: string &log &optional;
## The file handle for the file to be extracted
- extraction_file: file &log &optional;
+ extraction_file: file &log &optional;
- ## A boolean to indicate if the current file transfer should be extraced.
- extract_file: bool &default=F;
+ ## A boolean to indicate if the current file transfer should be extracted.
+ extract_file: bool &default=F;
## The count of the number of file that have been extracted during the session.
num_extracted_files: count &default=0;
@@ -54,8 +56,10 @@ event file_transferred(c: connection, prefix: string, descr: string,
if ( extract_file_types == irc$dcc_mime_type )
{
irc$extract_file = T;
- add irc$tags[EXTRACTED_FILE];
+ }
+ if ( irc$extract_file )
+ {
local suffix = fmt("%d.dat", ++irc$num_extracted_files);
local fname = generate_extraction_filename(extraction_prefix, c, suffix);
irc$extraction_file = open(fname);
@@ -76,7 +80,7 @@ event file_transferred(c: connection, prefix: string, descr: string,
Log::write(IRC::LOG, irc);
irc$command = tmp;
- if ( irc$extract_file && irc?$extraction_file )
+ if ( irc?$extraction_file )
set_contents_file(id, CONTENTS_RESP, irc$extraction_file);
# Delete these values in case another DCC transfer
diff --git a/scripts/base/protocols/irc/main.bro b/scripts/base/protocols/irc/main.bro
index e74eea21f1..2bf2a9bbb9 100644
--- a/scripts/base/protocols/irc/main.bro
+++ b/scripts/base/protocols/irc/main.bro
@@ -1,36 +1,38 @@
-##! This is the script that implements the core IRC analysis support. It only
-##! logs a very limited subset of the IRC protocol by default. The points
-##! that it logs at are NICK commands, USER commands, and JOIN commands. It
-##! log various bits of meta data as indicated in the :bro:type:`Info` record
-##! along with the command at the command arguments.
+##! Implements the core IRC analysis support. The logging model is to log
+##! IRC commands along with the associated response and some additional
+##! metadata about the connection if it's available.
module IRC;
export {
+
redef enum Log::ID += { LOG };
- type Tag: enum {
- EMPTY
- };
-
type Info: record {
+ ## Timestamp when the command was seen.
ts: time &log;
uid: string &log;
id: conn_id &log;
+ ## Nick name given for the connection.
nick: string &log &optional;
+ ## User name given for the connection.
user: string &log &optional;
- channels: set[string] &log &optional;
-
+
+ ## Command given by the client.
command: string &log &optional;
+ ## Value for the command given by the client.
value: string &log &optional;
+ ## Any additional data for the command.
addl: string &log &optional;
- tags: set[Tag] &log;
};
+ ## Event that can be handled to access the IRC record as it is sent on
+ ## to the logging framework.
global irc_log: event(rec: Info);
}
redef record connection += {
+ ## IRC session information.
irc: Info &optional;
};
diff --git a/scripts/base/protocols/ssh/main.bro b/scripts/base/protocols/ssh/main.bro
index 3a60244184..0d3439bb1f 100644
--- a/scripts/base/protocols/ssh/main.bro
+++ b/scripts/base/protocols/ssh/main.bro
@@ -14,15 +14,17 @@
module SSH;
export {
+ ## The SSH protocol logging stream identifier.
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
- ## This indicates that a heuristically detected "successful" SSH
+ ## Indicates that a heuristically detected "successful" SSH
## authentication occurred.
Login
};
type Info: record {
+ ## Time when the SSH connection began.
ts: time &log;
uid: string &log;
id: conn_id &log;
@@ -34,11 +36,11 @@ export {
## would be set for the opposite situation.
# TODO: handle local-local and remote-remote better.
direction: Direction &log &optional;
- ## The software string given by the client.
+ ## Software string given by the client.
client: string &log &optional;
- ## The software string given by the server.
+ ## Software string given by the server.
server: string &log &optional;
- ## The amount of data returned from the server. This is currently
+ ## Amount of data returned from the server. This is currently
## the only measure of the success heuristic and it is logged to
## assist analysts looking at the logs to make their own determination
## about the success on a case-by-case basis.
@@ -48,8 +50,8 @@ export {
done: bool &default=F;
};
- ## The size in bytes at which the SSH connection is presumed to be
- ## successful.
+ ## The size in bytes of data sent by the server at which the SSH
+ ## connection is presumed to be successful.
const authentication_data_size = 5500 &redef;
## If true, we tell the event engine to not look at further data
@@ -58,14 +60,16 @@ export {
## kinds of analyses (e.g., tracking connection size).
const skip_processing_after_detection = F &redef;
- ## This event is generated when the heuristic thinks that a login
+ ## Event that is generated when the heuristic thinks that a login
## was successful.
global heuristic_successful_login: event(c: connection);
- ## This event is generated when the heuristic thinks that a login
+ ## Event that is generated when the heuristic thinks that a login
## failed.
global heuristic_failed_login: event(c: connection);
+ ## Event that can be handled to access the :bro:type:`SSH::Info`
+ ## record as it is sent on to the logging framework.
global log_ssh: event(rec: Info);
}
diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro
index 9d8bc68fd5..9d16ab18ba 100644
--- a/scripts/base/protocols/ssl/consts.bro
+++ b/scripts/base/protocols/ssl/consts.bro
@@ -1,23 +1,29 @@
module SSL;
export {
-
const SSLv2 = 0x0002;
const SSLv3 = 0x0300;
const TLSv10 = 0x0301;
const TLSv11 = 0x0302;
+ const TLSv12 = 0x0303;
+ ## Mapping between the constants and string values for SSL/TLS versions.
const version_strings: table[count] of string = {
[SSLv2] = "SSLv2",
[SSLv3] = "SSLv3",
[TLSv10] = "TLSv10",
[TLSv11] = "TLSv11",
+ [TLSv12] = "TLSv12",
} &default="UNKNOWN";
-
+
+ ## Mapping between numeric codes and human readable strings for alert
+ ## levels.
const alert_levels: table[count] of string = {
[1] = "warning",
[2] = "fatal",
} &default=function(i: count):string { return fmt("unknown-%d", i); };
-
+
+ ## Mapping between numeric codes and human readable strings for alert
+ ## descriptions..
const alert_descriptions: table[count] of string = {
[0] = "close_notify",
[10] = "unexpected_message",
@@ -50,7 +56,10 @@ export {
[114] = "bad_certificate_hash_value",
[115] = "unknown_psk_identity",
} &default=function(i: count):string { return fmt("unknown-%d", i); };
-
+
+ ## Mapping between numeric codes and human readable strings for SSL/TLS
+ ## extensions.
+ # More information can be found here:
# http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
const extensions: table[count] of string = {
[0] = "server_name",
@@ -69,10 +78,11 @@ export {
[13] = "signature_algorithms",
[14] = "use_srtp",
[35] = "SessionTicket TLS",
+ [13172] = "next_protocol_negotiation",
[65281] = "renegotiation_info"
} &default=function(i: count):string { return fmt("unknown-%d", i); };
- ## SSLv2
+ # SSLv2
const SSLv20_CK_RC4_128_WITH_MD5 = 0x010080;
const SSLv20_CK_RC4_128_EXPORT40_WITH_MD5 = 0x020080;
const SSLv20_CK_RC2_128_CBC_WITH_MD5 = 0x030080;
@@ -81,7 +91,7 @@ export {
const SSLv20_CK_DES_64_CBC_WITH_MD5 = 0x060040;
const SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x0700C0;
- ## TLS
+ # TLS
const TLS_NULL_WITH_NULL_NULL = 0x0000;
const TLS_RSA_WITH_NULL_MD5 = 0x0001;
const TLS_RSA_WITH_NULL_SHA = 0x0002;
@@ -298,13 +308,11 @@ export {
const SSL_RSA_WITH_DES_CBC_MD5 = 0xFF82;
const SSL_RSA_WITH_3DES_EDE_CBC_MD5 = 0xFF83;
const TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
-
- # --- This is a table of all known cipher specs.
- # --- It can be used for detecting unknown ciphers and for
- # --- converting the cipher spec constants into a human readable format.
-
+
+ ## This is a table of all known cipher specs. It can be used for
+ ## detecting unknown ciphers and for converting the cipher spec constants
+ ## into a human readable format.
const cipher_desc: table[count] of string = {
- # --- sslv20 ---
[SSLv20_CK_RC4_128_EXPORT40_WITH_MD5] =
"SSLv20_CK_RC4_128_EXPORT40_WITH_MD5",
[SSLv20_CK_RC4_128_WITH_MD5] = "SSLv20_CK_RC4_128_WITH_MD5",
@@ -316,7 +324,6 @@ export {
"SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5",
[SSLv20_CK_DES_64_CBC_WITH_MD5] = "SSLv20_CK_DES_64_CBC_WITH_MD5",
- # --- TLS ---
[TLS_NULL_WITH_NULL_NULL] = "TLS_NULL_WITH_NULL_NULL",
[TLS_RSA_WITH_NULL_MD5] = "TLS_RSA_WITH_NULL_MD5",
[TLS_RSA_WITH_NULL_SHA] = "TLS_RSA_WITH_NULL_SHA",
@@ -529,7 +536,8 @@ export {
[SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2",
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2",
} &default="UNKNOWN";
-
+
+ ## Mapping between the constants and string values for SSL/TLS errors.
const x509_errors: table[count] of string = {
[0] = "ok",
[1] = "unable to get issuer cert",
diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro
index 4b2fa39696..0b280a6bcf 100644
--- a/scripts/base/protocols/ssl/main.bro
+++ b/scripts/base/protocols/ssl/main.bro
@@ -1,3 +1,6 @@
+##! Base SSL analysis script. This script logs information about the SSL/TLS
+##! handshaking and encryption establishment process.
+
@load ./consts
module SSL;
@@ -6,47 +9,57 @@ export {
redef enum Log::ID += { LOG };
type Info: record {
+ ## Time when the SSL connection began.
ts: time &log;
uid: string &log;
id: conn_id &log;
+ ## SSL/TLS version the server offered.
version: string &log &optional;
+ ## SSL/TLS cipher suite the server chose.
cipher: string &log &optional;
+ ## Value of the Server Name Indicator SSL/TLS extension. It
+ ## indicates the server name that the client was requesting.
server_name: string &log &optional;
+ ## Session ID offered by the client for session resumption.
session_id: string &log &optional;
+ ## Subject of the X.509 certificate offered by the server.
subject: string &log &optional;
+ ## NotValidBefore field value from the server certificate.
not_valid_before: time &log &optional;
+ ## NotValidAfter field value from the serve certificate.
not_valid_after: time &log &optional;
+ ## Last alert that was seen during the connection.
last_alert: string &log &optional;
-
+
+ ## Full binary server certificate stored in DER format.
cert: string &optional;
+ ## Chain of certificates offered by the server to validate its
+ ## complete signing chain.
cert_chain: vector of string &optional;
- ## This stores the analyzer id used for the analyzer instance attached
+ ## The analyzer ID used for the analyzer instance attached
## to each connection. It is not used for logging since it's a
## meaningless arbitrary number.
analyzer_id: count &optional;
};
-
- ## This is where the default root CA bundle is defined. By loading the
+
+ ## The default root CA bundle. By loading the
## mozilla-ca-list.bro script it will be set to Mozilla's root CA list.
const root_certs: table[string] of string = {} &redef;
-
+
## If true, detach the SSL analyzer from the connection to prevent
## continuing to process encrypted traffic. Helps with performance
## (especially with large file transfers).
const disable_analyzer_after_detection = T &redef;
-
+
## The openssl command line utility. If it's in the path the default
## value will work, otherwise a full path string can be supplied for the
## utility.
const openssl_util = "openssl" &redef;
-
+
+ ## Event that can be handled to access the SSL
+ ## record as it is sent on to the logging framework.
global log_ssl: event(rec: Info);
-
- const ports = {
- 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
- 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
- } &redef;
}
redef record connection += {
@@ -73,6 +86,11 @@ redef capture_filters += {
["xmpps"] = "tcp port 5223",
};
+const ports = {
+ 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
+ 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
+};
+
redef dpd_config += {
[[ANALYZER_SSL]] = [$ports = ports]
};
diff --git a/scripts/base/protocols/syslog/consts.bro b/scripts/base/protocols/syslog/consts.bro
index f08e7f71d7..dce1877ecf 100644
--- a/scripts/base/protocols/syslog/consts.bro
+++ b/scripts/base/protocols/syslog/consts.bro
@@ -1,6 +1,9 @@
+##! Constants definitions for syslog.
+
module Syslog;
export {
+ ## Mapping between the constants and string values for syslog facilities.
const facility_codes: table[count] of string = {
[0] = "KERN",
[1] = "USER",
@@ -27,7 +30,8 @@ export {
[22] = "LOCAL6",
[23] = "LOCAL7",
} &default=function(c: count): string { return fmt("?-%d", c); };
-
+
+ ## Mapping between the constants and string values for syslog severities.
const severity_codes: table[count] of string = {
[0] = "EMERG",
[1] = "ALERT",
diff --git a/scripts/base/protocols/syslog/main.bro b/scripts/base/protocols/syslog/main.bro
index 2acc843ea8..79f89d5e71 100644
--- a/scripts/base/protocols/syslog/main.bro
+++ b/scripts/base/protocols/syslog/main.bro
@@ -1,4 +1,5 @@
-##! Core script support for logging syslog messages.
+##! Core script support for logging syslog messages. This script represents
+##! one syslog message as one logged record.
@load ./consts
@@ -8,19 +9,23 @@ export {
redef enum Log::ID += { LOG };
type Info: record {
+ ## Timestamp of when the syslog message was seen.
ts: time &log;
uid: string &log;
id: conn_id &log;
+ ## Protocol over which the message was seen.
proto: transport_proto &log;
+ ## Syslog facility for the message.
facility: string &log;
+ ## Syslog severity for the message.
severity: string &log;
+ ## The plain text message.
message: string &log;
};
-
- const ports = { 514/udp } &redef;
}
redef capture_filters += { ["syslog"] = "port 514" };
+const ports = { 514/udp } &redef;
redef dpd_config += { [ANALYZER_SYSLOG_BINPAC] = [$ports = ports] };
redef likely_server_ports += { 514/udp };
diff --git a/scripts/base/utils/site.bro b/scripts/base/utils/site.bro
index 536c891572..4aeb70fe3f 100644
--- a/scripts/base/utils/site.bro
+++ b/scripts/base/utils/site.bro
@@ -18,7 +18,7 @@ export {
const local_nets: set[subnet] &redef;
## This is used for retrieving the subnet when you multiple
- ## :bro:id:`local_nets`. A membership query can be done with an
+ ## :bro:id:`Site::local_nets`. A membership query can be done with an
## :bro:type:`addr` and the table will yield the subnet it was found
## within.
global local_nets_table: table[subnet] of subnet = {};
diff --git a/scripts/policy/frameworks/control/controllee.bro b/scripts/policy/frameworks/control/controllee.bro
index 798ab8814a..b4769764f4 100644
--- a/scripts/policy/frameworks/control/controllee.bro
+++ b/scripts/policy/frameworks/control/controllee.bro
@@ -1,3 +1,12 @@
+##! The controllee portion of the control framework. Load this script if remote
+##! runtime control of the Bro process is desired.
+##!
+##! A controllee only needs to load the controllee script in addition
+##! to the specific analysis scripts desired. It may also need a node
+##! configured as a controller node in the communications nodes configuration::
+##!
+##! bro frameworks/control/controllee
+
@load base/frameworks/control
# If an instance is a controllee, it implicitly needs to listen for remote
# connections.
diff --git a/scripts/policy/frameworks/control/controller.bro b/scripts/policy/frameworks/control/controller.bro
index cb76a8b322..39647095db 100644
--- a/scripts/policy/frameworks/control/controller.bro
+++ b/scripts/policy/frameworks/control/controller.bro
@@ -1,3 +1,10 @@
+##! This is a utility script that implements the controller interface for the
+##! control framework. It's intended to be run to control a remote Bro
+##! and then shutdown.
+##!
+##! It's intended to be used from the command line like this::
+##! bro frameworks/control/controller Control::host= Control::port= Control::cmd= [Control::arg=]
+
@load base/frameworks/control
@load base/frameworks/communication
diff --git a/scripts/policy/frameworks/metrics/conn-example.bro b/scripts/policy/frameworks/metrics/conn-example.bro
index b3800c3ed3..974012963b 100644
--- a/scripts/policy/frameworks/metrics/conn-example.bro
+++ b/scripts/policy/frameworks/metrics/conn-example.bro
@@ -1,3 +1,6 @@
+##! An example of using the metrics framework to collect connection metrics
+##! aggregated into /24 CIDR ranges.
+
@load base/frameworks/metrics
@load base/utils/site
diff --git a/scripts/policy/frameworks/metrics/http-example.bro b/scripts/policy/frameworks/metrics/http-example.bro
index 50b18b2a27..58ca4e6614 100644
--- a/scripts/policy/frameworks/metrics/http-example.bro
+++ b/scripts/policy/frameworks/metrics/http-example.bro
@@ -1,9 +1,17 @@
+##! Provides an example of aggregating and limiting collection down to
+##! only local networks. Additionally, the status code for the response from
+##! the request is added into the metric.
+
@load base/frameworks/metrics
@load base/protocols/http
@load base/utils/site
redef enum Metrics::ID += {
+ ## Measures HTTP requests indexed on both the request host and the response
+ ## code from the server.
HTTP_REQUESTS_BY_STATUS_CODE,
+
+ ## Currently unfinished and not working.
HTTP_REQUESTS_BY_HOST_HEADER,
};
@@ -11,13 +19,13 @@ event bro_init()
{
# TODO: these are waiting on a fix with table vals + records before they will work.
#Metrics::add_filter(HTTP_REQUESTS_BY_HOST_HEADER,
- # [$pred(index: Index) = { return Site:is_local_addr(index$host) },
+ # [$pred(index: Metrics::Index) = { return Site::is_local_addr(index$host); },
# $aggregation_mask=24,
- # $break_interval=5mins]);
- #
- ## Site::local_nets must be defined in order for this to actually do anything.
- #Metrics::add_filter(HTTP_REQUESTS_BY_STATUS_CODE, [$aggregation_table=Site::local_nets_table,
- # $break_interval=5mins]);
+ # $break_interval=1min]);
+
+ # Site::local_nets must be defined in order for this to actually do anything.
+ Metrics::add_filter(HTTP_REQUESTS_BY_STATUS_CODE, [$aggregation_table=Site::local_nets_table,
+ $break_interval=1min]);
}
event HTTP::log_http(rec: HTTP::Info)
diff --git a/scripts/policy/frameworks/metrics/ssl-example.bro b/scripts/policy/frameworks/metrics/ssl-example.bro
index 46dd0e4741..5ec675779a 100644
--- a/scripts/policy/frameworks/metrics/ssl-example.bro
+++ b/scripts/policy/frameworks/metrics/ssl-example.bro
@@ -1,3 +1,8 @@
+##! Provides an example of using the metrics framework to collect the number
+##! of times a specific server name indicator value is seen in SSL session
+##! establishments. Names ending in google.com are being filtered out as an
+##! example of the predicate based filtering in metrics filters.
+
@load base/frameworks/metrics
@load base/protocols/ssl
diff --git a/scripts/policy/frameworks/software/version-changes.bro b/scripts/policy/frameworks/software/version-changes.bro
index 6d46151f0f..974a23dc76 100644
--- a/scripts/policy/frameworks/software/version-changes.bro
+++ b/scripts/policy/frameworks/software/version-changes.bro
@@ -1,3 +1,7 @@
+##! Provides the possibly to define software names that are interesting to
+##! watch for changes. A notice is generated if software versions change on a
+##! host.
+
@load base/frameworks/notice
@load base/frameworks/software
@@ -5,24 +9,17 @@ module Software;
export {
redef enum Notice::Type += {
- ## For certain softwares, a version changing may matter. In that case,
+ ## For certain software, a version changing may matter. In that case,
## this notice will be generated. Software that matters if the version
## changes can be configured with the
## :bro:id:`Software::interesting_version_changes` variable.
Software_Version_Change,
};
- ## Some software is more interesting when the version changes and this
+ ## Some software is more interesting when the version changes and this is
## a set of all software that should raise a notice when a different
## version is seen on a host.
- const interesting_version_changes: set[string] = {
- "SSH"
- } &redef;
-
- ## Some software is more interesting when the version changes and this
- ## a set of all software that should raise a notice when a different
- ## version is seen on a host.
- const interesting_type_changes: set[string] = {};
+ const interesting_version_changes: set[string] = { } &redef;
}
event log_software(rec: Info)
diff --git a/scripts/policy/frameworks/software/vulnerable.bro b/scripts/policy/frameworks/software/vulnerable.bro
index 0ce949b83d..c2c2ba5b32 100644
--- a/scripts/policy/frameworks/software/vulnerable.bro
+++ b/scripts/policy/frameworks/software/vulnerable.bro
@@ -1,3 +1,7 @@
+##! Provides a variable to define vulnerable versions of software and if a
+##! a version of that software as old or older than the defined version a
+##! notice will be generated.
+
@load base/frameworks/notice
@load base/frameworks/software
@@ -5,6 +9,7 @@ module Software;
export {
redef enum Notice::Type += {
+ ## Indicates that a vulnerable version of software was detected.
Vulnerable_Version,
};
@@ -18,6 +23,7 @@ event log_software(rec: Info)
if ( rec$name in vulnerable_versions &&
cmp_versions(rec$version, vulnerable_versions[rec$name]) <= 0 )
{
- NOTICE([$note=Vulnerable_Version, $src=rec$host, $msg=software_fmt(rec)]);
+ NOTICE([$note=Vulnerable_Version, $src=rec$host,
+ $msg=fmt("A vulnerable version of software was detected: %s", software_fmt(rec))]);
}
}
diff --git a/scripts/policy/integration/barnyard2/main.bro b/scripts/policy/integration/barnyard2/main.bro
index c2f1c790d3..1d38d80809 100644
--- a/scripts/policy/integration/barnyard2/main.bro
+++ b/scripts/policy/integration/barnyard2/main.bro
@@ -15,7 +15,7 @@ export {
alert: AlertData &log;
};
- ## This can convert a Barnyard :bro:type:`PacketID` value to a
+ ## This can convert a Barnyard :bro:type:`Barnyard2::PacketID` value to a
## :bro:type:`conn_id` value in the case that you might need to index
## into an existing data structure elsewhere within Bro.
global pid2cid: function(p: PacketID): conn_id;
diff --git a/scripts/policy/misc/capture-loss.bro b/scripts/policy/misc/capture-loss.bro
index 87fc80be67..b2d23020f8 100644
--- a/scripts/policy/misc/capture-loss.bro
+++ b/scripts/policy/misc/capture-loss.bro
@@ -42,9 +42,9 @@ export {
const watch_interval = 15mins &redef;
## The percentage of missed data that is considered "too much"
- ## when the :bro:enum:`Too_Much_Loss` notice should be generated.
- ## The value is expressed as a double between 0 and 1 with 1 being
- ## 100%
+ ## when the :bro:enum:`CaptureLoss::Too_Much_Loss` notice should be
+ ## generated. The value is expressed as a double between 0 and 1 with 1
+ ## being 100%
const too_much_loss: double = 0.1 &redef;
}
diff --git a/scripts/policy/misc/trim-trace-file.bro b/scripts/policy/misc/trim-trace-file.bro
index 3caa41c06b..8a7781b628 100644
--- a/scripts/policy/misc/trim-trace-file.bro
+++ b/scripts/policy/misc/trim-trace-file.bro
@@ -10,7 +10,8 @@ export {
## This event can be generated externally to this script if on-demand
## tracefile rotation is required with the caveat that the script doesn't
## currently attempt to get back on schedule automatically and the next
- ## trim will likely won't happen on the :bro:id:`trim_interval`.
+ ## trim will likely won't happen on the
+ ## :bro:id:`TrimTraceFile::trim_interval`.
global go: event(first_trim: bool);
}
diff --git a/scripts/policy/protocols/conn/known-hosts.bro b/scripts/policy/protocols/conn/known-hosts.bro
index 017b6c8a25..8914a5a22a 100644
--- a/scripts/policy/protocols/conn/known-hosts.bro
+++ b/scripts/policy/protocols/conn/known-hosts.bro
@@ -8,8 +8,10 @@
module Known;
export {
+ ## The known-hosts logging stream identifier.
redef enum Log::ID += { HOSTS_LOG };
-
+
+ ## The record type which contains the column fields of the known-hosts log.
type HostsInfo: record {
## The timestamp at which the host was detected.
ts: time &log;
@@ -19,7 +21,7 @@ export {
};
## The hosts whose existence should be logged and tracked.
- ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
+ ## See :bro:type:`Host` for possible choices.
const host_tracking = LOCAL_HOSTS &redef;
## The set of all known addresses to store for preventing duplicate
@@ -28,7 +30,9 @@ export {
## Maintain the list of known hosts for 24 hours so that the existence
## of each individual address is logged each day.
global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
-
+
+ ## An event that can be handled to access the :bro:type:`Known::HostsInfo`
+ ## record as it is sent on to the logging framework.
global log_known_hosts: event(rec: HostsInfo);
}
diff --git a/scripts/policy/protocols/conn/known-services.bro b/scripts/policy/protocols/conn/known-services.bro
index 9d58f3a9fb..f494a30f82 100644
--- a/scripts/policy/protocols/conn/known-services.bro
+++ b/scripts/policy/protocols/conn/known-services.bro
@@ -8,29 +8,41 @@
module Known;
export {
+ ## The known-services logging stream identifier.
redef enum Log::ID += { SERVICES_LOG };
-
+
+ ## The record type which contains the column fields of the known-services
+ ## log.
type ServicesInfo: record {
+ ## The time at which the service was detected.
ts: time &log;
+ ## The host address on which the service is running.
host: addr &log;
+ ## The port number on which the service is running.
port_num: port &log;
+ ## The transport-layer protocol which the service uses.
port_proto: transport_proto &log;
+ ## A set of protocols that match the service's connection payloads.
service: set[string] &log;
-
- done: bool &default=F;
};
## The hosts whose services should be tracked and logged.
+ ## See :bro:type:`Host` for possible choices.
const service_tracking = LOCAL_HOSTS &redef;
-
+
+ ## Tracks the set of daily-detected services for preventing the logging
+ ## of duplicates, but can also be inspected by other scripts for
+ ## different purposes.
global known_services: set[addr, port] &create_expire=1day &synchronized;
-
+
+ ## Event that can be handled to access the :bro:type:`Known::ServicesInfo`
+ ## record as it is sent on to the logging framework.
global log_known_services: event(rec: ServicesInfo);
}
redef record connection += {
- ## This field is to indicate whether or not the processing for detecting
- ## and logging the service for this connection is complete.
+ # This field is to indicate whether or not the processing for detecting
+ # and logging the service for this connection is complete.
known_services_done: bool &default=F;
};
diff --git a/scripts/policy/protocols/ftp/detect.bro b/scripts/policy/protocols/ftp/detect.bro
index abb62e08fc..e1bd627921 100644
--- a/scripts/policy/protocols/ftp/detect.bro
+++ b/scripts/policy/protocols/ftp/detect.bro
@@ -7,7 +7,7 @@ module FTP;
export {
redef enum Notice::Type += {
- ## This indicates that a successful response to a "SITE EXEC"
+ ## Indicates that a successful response to a "SITE EXEC"
## command/arg pair was seen.
Site_Exec_Success,
};
diff --git a/scripts/policy/protocols/ftp/software.bro b/scripts/policy/protocols/ftp/software.bro
index 622357a608..8834e5cd2e 100644
--- a/scripts/policy/protocols/ftp/software.bro
+++ b/scripts/policy/protocols/ftp/software.bro
@@ -12,8 +12,10 @@ module FTP;
export {
redef enum Software::Type += {
- FTP_CLIENT,
- FTP_SERVER,
+ ## Identifier for FTP clients in the software framework.
+ CLIENT,
+ ## Not currently implemented.
+ SERVER,
};
}
@@ -21,7 +23,7 @@ event ftp_request(c: connection, command: string, arg: string) &priority=4
{
if ( command == "CLNT" )
{
- local si = Software::parse(arg, c$id$orig_h, FTP_CLIENT);
+ local si = Software::parse(arg, c$id$orig_h, CLIENT);
Software::found(c$id, si);
}
}
diff --git a/scripts/policy/protocols/http/detect-MHR.bro b/scripts/policy/protocols/http/detect-MHR.bro
index fca3bb1ac9..a0e3cb50fb 100644
--- a/scripts/policy/protocols/http/detect-MHR.bro
+++ b/scripts/policy/protocols/http/detect-MHR.bro
@@ -1,8 +1,8 @@
-##! This script takes MD5 sums of files transferred over HTTP and checks them with
-##! Team Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
+##! Detect file downloads over HTTP that have MD5 sums matching files in Team
+##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
##! By default, not all file transfers will have MD5 sums calculated. Read the
-##! documentation for the :doc:base/protocols/http/file-hash.bro script to see how to
-##! configure which transfers will have hashes calculated.
+##! documentation for the :doc:base/protocols/http/file-hash.bro script to see
+##! how to configure which transfers will have hashes calculated.
@load base/frameworks/notice
@load base/protocols/http
diff --git a/scripts/policy/protocols/http/detect-intel.bro b/scripts/policy/protocols/http/detect-intel.bro
index 6da4d8d1e1..281d705c13 100644
--- a/scripts/policy/protocols/http/detect-intel.bro
+++ b/scripts/policy/protocols/http/detect-intel.bro
@@ -1,4 +1,4 @@
-##! Intelligence based HTTP detections.
+##! Intelligence based HTTP detections. Not yet working!
@load base/protocols/http/main
@load base/protocols/http/utils
diff --git a/scripts/policy/protocols/http/detect-sqli.bro b/scripts/policy/protocols/http/detect-sqli.bro
index 3927ce811e..a92565c63a 100644
--- a/scripts/policy/protocols/http/detect-sqli.bro
+++ b/scripts/policy/protocols/http/detect-sqli.bro
@@ -16,7 +16,9 @@ export {
};
redef enum Metrics::ID += {
+ ## Metric to track SQL injection attackers.
SQLI_ATTACKER,
+ ## Metrics to track SQL injection victims.
SQLI_VICTIM,
};
@@ -30,17 +32,17 @@ export {
COOKIE_SQLI,
};
- ## This defines the threshold that determines if an SQL injection attack
+ ## Defines the threshold that determines if an SQL injection attack
## is ongoing based on the number of requests that appear to be SQL
## injection attacks.
const sqli_requests_threshold = 50 &redef;
- ## Interval at which to watch for the :bro:id:`sqli_requests_threshold`
- ## variable to be crossed. At the end of each interval the counter is
- ## reset.
+ ## Interval at which to watch for the
+ ## :bro:id:`HTTP::sqli_requests_threshold` variable to be crossed.
+ ## At the end of each interval the counter is reset.
const sqli_requests_interval = 5min &redef;
- ## This regular expression is used to match URI based SQL injections
+ ## Regular expression is used to match URI based SQL injections.
const match_sql_injection_uri =
/[\?&][^[:blank:]\x00-\x37\|]+?=[\-[:alnum:]%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+.*?([hH][aA][vV][iI][nN][gG]|[uU][nN][iI][oO][nN]|[eE][xX][eE][cC]|[sS][eE][lL][eE][cC][tT]|[dD][eE][lL][eE][tT][eE]|[dD][rR][oO][pP]|[dD][eE][cC][lL][aA][rR][eE]|[cC][rR][eE][aA][tT][eE]|[iI][nN][sS][eE][rR][tT])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+/
| /[\?&][^[:blank:]\x00-\x37\|]+?=[\-0-9%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+([xX]?[oO][rR]|[nN]?[aA][nN][dD])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+['"]?(([^a-zA-Z&]+)?=|[eE][xX][iI][sS][tT][sS])/
diff --git a/scripts/policy/protocols/http/detect-webapps.bro b/scripts/policy/protocols/http/detect-webapps.bro
index 4a94d1adbd..a13d64679a 100644
--- a/scripts/policy/protocols/http/detect-webapps.bro
+++ b/scripts/policy/protocols/http/detect-webapps.bro
@@ -1,3 +1,5 @@
+##! Detect and log web applications through the software framework.
+
@load base/frameworks/signatures
@load base/frameworks/software
@load base/protocols/http
@@ -10,10 +12,12 @@ redef Signatures::ignored_ids += /^webapp-/;
export {
redef enum Software::Type += {
+ ## Identifier for web applications in the software framework.
WEB_APPLICATION,
};
redef record Software::Info += {
+ ## Most root URL where the software was discovered.
url: string &optional &log;
};
}
diff --git a/scripts/policy/protocols/http/software-browser-plugins.bro b/scripts/policy/protocols/http/software-browser-plugins.bro
index db9eafd1a7..a035a2dcfc 100644
--- a/scripts/policy/protocols/http/software-browser-plugins.bro
+++ b/scripts/policy/protocols/http/software-browser-plugins.bro
@@ -1,5 +1,5 @@
-##! This script take advantage of a few ways that installed plugin information
-##! leaks from web browsers.
+##! Detect browser plugins as they leak through requests to Omniture
+##! advertising servers.
@load base/protocols/http
@load base/frameworks/software
@@ -13,6 +13,7 @@ export {
};
redef enum Software::Type += {
+ ## Identifier for browser plugins in the software framework.
BROWSER_PLUGIN
};
}
diff --git a/scripts/policy/protocols/http/software.bro b/scripts/policy/protocols/http/software.bro
index 8732634359..8907d0853e 100644
--- a/scripts/policy/protocols/http/software.bro
+++ b/scripts/policy/protocols/http/software.bro
@@ -6,8 +6,11 @@ module HTTP;
export {
redef enum Software::Type += {
+ ## Identifier for web servers in the software framework.
SERVER,
+ ## Identifier for app servers in the software framework.
APPSERVER,
+ ## Identifier for web browsers in the software framework.
BROWSER,
};
diff --git a/scripts/policy/protocols/http/var-extraction-cookies.bro b/scripts/policy/protocols/http/var-extraction-cookies.bro
index 2b3f282b03..610c6e1381 100644
--- a/scripts/policy/protocols/http/var-extraction-cookies.bro
+++ b/scripts/policy/protocols/http/var-extraction-cookies.bro
@@ -1,4 +1,4 @@
-##! This script extracts and logs variables from cookies sent by clients
+##! Extracts and logs variables names from cookies sent by clients.
@load base/protocols/http/main
@load base/protocols/http/utils
@@ -6,6 +6,7 @@
module HTTP;
redef record Info += {
+ ## Variable names extracted from all cookies.
cookie_vars: vector of string &optional &log;
};
diff --git a/scripts/policy/protocols/http/var-extraction-uri.bro b/scripts/policy/protocols/http/var-extraction-uri.bro
index b03474bb94..27ee89d6f2 100644
--- a/scripts/policy/protocols/http/var-extraction-uri.bro
+++ b/scripts/policy/protocols/http/var-extraction-uri.bro
@@ -1,10 +1,12 @@
-##! This script extracts and logs variables from the requested URI
+##! Extracts and log variables from the requested URI in the default HTTP
+##! logging stream.
@load base/protocols/http
module HTTP;
redef record Info += {
+ ## Variable names from the URI.
uri_vars: vector of string &optional &log;
};
diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro
index 3abe185d58..aa6e920c12 100644
--- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro
+++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro
@@ -1,3 +1,5 @@
+##! Detect hosts which are doing password guessing attacks and/or password
+##! bruteforcing over SSH.
@load base/protocols/ssh
@load base/frameworks/metrics
@@ -9,17 +11,17 @@ module SSH;
export {
redef enum Notice::Type += {
## Indicates that a host has been identified as crossing the
- ## :bro:id:`password_guesses_limit` threshold with heuristically
+ ## :bro:id:`SSH::password_guesses_limit` threshold with heuristically
## determined failed logins.
Password_Guessing,
## Indicates that a host previously identified as a "password guesser"
- ## has now had a heuristically successful login attempt.
+ ## has now had a heuristically successful login attempt. This is not
+ ## currently implemented.
Login_By_Password_Guesser,
};
redef enum Metrics::ID += {
- ## This metric is to measure failed logins with the hope of detecting
- ## bruteforcing hosts.
+ ## Metric is to measure failed logins.
FAILED_LOGIN,
};
@@ -37,7 +39,7 @@ export {
## client subnets and the yield value represents server subnets.
const ignore_guessers: table[subnet] of subnet &redef;
- ## Keeps track of hosts identified as guessing passwords.
+ ## Tracks hosts identified as guessing passwords.
global password_guessers: set[addr]
&read_expire=guessing_timeout+1hr &synchronized &redef;
}
diff --git a/scripts/policy/protocols/ssh/geo-data.bro b/scripts/policy/protocols/ssh/geo-data.bro
index daa05f4ebc..0f8bb932fe 100644
--- a/scripts/policy/protocols/ssh/geo-data.bro
+++ b/scripts/policy/protocols/ssh/geo-data.bro
@@ -1,5 +1,4 @@
-##! This implements all of the additional information and geodata detections
-##! for SSH analysis.
+##! Geodata based detections for SSH analysis.
@load base/frameworks/notice
@load base/protocols/ssh
@@ -19,8 +18,8 @@ export {
remote_location: geo_location &log &optional;
};
- ## The set of countries for which you'd like to throw notices upon
- ## successful login
+ ## The set of countries for which you'd like to generate notices upon
+ ## successful login.
const watched_countries: set[string] = {"RO"} &redef;
}
diff --git a/scripts/policy/protocols/ssh/interesting-hostnames.bro b/scripts/policy/protocols/ssh/interesting-hostnames.bro
index 5771770916..f79c67ede9 100644
--- a/scripts/policy/protocols/ssh/interesting-hostnames.bro
+++ b/scripts/policy/protocols/ssh/interesting-hostnames.bro
@@ -10,9 +10,9 @@ module SSH;
export {
redef enum Notice::Type += {
- ## Generated if a login originates or responds with a host and the
+ ## Generated if a login originates or responds with a host where the
## reverse hostname lookup resolves to a name matched by the
- ## :bro:id:`interesting_hostnames` regular expression.
+ ## :bro:id:`SSH::interesting_hostnames` regular expression.
Interesting_Hostname_Login,
};
diff --git a/scripts/policy/protocols/ssh/software.bro b/scripts/policy/protocols/ssh/software.bro
index a239655270..44704ec845 100644
--- a/scripts/policy/protocols/ssh/software.bro
+++ b/scripts/policy/protocols/ssh/software.bro
@@ -1,4 +1,4 @@
-##! This script extracts SSH client and server information from SSH
+##! Extracts SSH client and server information from SSH
##! connections and forwards it to the software framework.
@load base/frameworks/software
@@ -7,7 +7,9 @@ module SSH;
export {
redef enum Software::Type += {
+ ## Identifier for SSH clients in the software framework.
SERVER,
+ ## Identifier for SSH servers in the software framework.
CLIENT,
};
}
diff --git a/scripts/policy/protocols/ssl/cert-hash.bro b/scripts/policy/protocols/ssl/cert-hash.bro
index 1e47ccac2e..32a165a946 100644
--- a/scripts/policy/protocols/ssl/cert-hash.bro
+++ b/scripts/policy/protocols/ssl/cert-hash.bro
@@ -1,4 +1,4 @@
-##! This script calculates MD5 sums for server DER formatted certificates.
+##! Calculate MD5 sums for server DER formatted certificates.
@load base/protocols/ssl
@@ -6,6 +6,7 @@ module SSL;
export {
redef record Info += {
+ ## MD5 sum of the raw server certificate.
cert_hash: string &log &optional;
};
}
diff --git a/scripts/policy/protocols/ssl/expiring-certs.bro b/scripts/policy/protocols/ssl/expiring-certs.bro
index 0e4db56bc3..80616e6a99 100644
--- a/scripts/policy/protocols/ssl/expiring-certs.bro
+++ b/scripts/policy/protocols/ssl/expiring-certs.bro
@@ -1,6 +1,6 @@
-##! This script can be used to generate notices when X.509 certificates over
-##! SSL/TLS are expired or going to expire based on the date and time values
-##! stored within the certificate.
+##! Generate notices when X.509 certificates over SSL/TLS are expired or
+##! going to expire soon based on the date and time values stored within the
+##! certificate.
@load base/protocols/ssl
@load base/frameworks/notice
@@ -24,12 +24,13 @@ export {
## The category of hosts you would like to be notified about which have
## certificates that are going to be expiring soon. By default, these
- ## notices will be suppressed by the notice framework for 1 day.
+ ## notices will be suppressed by the notice framework for 1 day after
+ ## a particular certificate has had a notice generated.
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
const notify_certs_expiration = LOCAL_HOSTS &redef;
## The time before a certificate is going to expire that you would like to
- ## start receiving :bro:enum:`Certificate_Expires_Soon` notices.
+ ## start receiving :bro:enum:`SSL::Certificate_Expires_Soon` notices.
const notify_when_cert_expiring_in = 30days &redef;
}
diff --git a/scripts/policy/protocols/ssl/extract-certs-pem.bro b/scripts/policy/protocols/ssl/extract-certs-pem.bro
index e6a740c215..420c60a4fd 100644
--- a/scripts/policy/protocols/ssl/extract-certs-pem.bro
+++ b/scripts/policy/protocols/ssl/extract-certs-pem.bro
@@ -2,7 +2,7 @@
##! after being converted to PEM files. The certificates will be stored in
##! a single file, one for local certificates and one for remote certificates.
##!
-##! A couple of things to think about with this script::
+##! ..note::
##!
##! - It doesn't work well on a cluster because each worker will write its
##! own certificate files and no duplicate checking is done across
@@ -20,15 +20,15 @@
module SSL;
export {
- ## Setting to control if host certificates offered by the defined hosts
+ ## Control if host certificates offered by the defined hosts
## will be written to the PEM certificates file.
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
const extract_certs_pem = LOCAL_HOSTS &redef;
}
-## This is an internally maintained variable to prevent relogging of
-## certificates that have already been seen. It is indexed on an md5 sum of
-## the certificate.
+# This is an internally maintained variable to prevent relogging of
+# certificates that have already been seen. It is indexed on an md5 sum of
+# the certificate.
global extracted_certs: set[string] = set() &read_expire=1hr &redef;
event ssl_established(c: connection) &priority=5
diff --git a/scripts/policy/protocols/ssl/known-certs.bro b/scripts/policy/protocols/ssl/known-certs.bro
index 669432e4d9..3986a9aa1e 100644
--- a/scripts/policy/protocols/ssl/known-certs.bro
+++ b/scripts/policy/protocols/ssl/known-certs.bro
@@ -1,5 +1,4 @@
-##! This script can be used to log information about certificates while
-##! attempting to avoid duplicate logging.
+##! Log information about certificates while attempting to avoid duplicate logging.
@load base/utils/directions-and-hosts
@load base/protocols/ssl
@@ -36,6 +35,8 @@ export {
## in the set is for storing the DER formatted certificate's MD5 hash.
global certs: set[addr, string] &create_expire=1day &synchronized &redef;
+ ## Event that can be handled to access the loggable record as it is sent
+ ## on to the logging framework.
global log_known_certs: event(rec: CertsInfo);
}
diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro
index 5a663864d2..03624eac84 100644
--- a/scripts/policy/protocols/ssl/validate-certs.bro
+++ b/scripts/policy/protocols/ssl/validate-certs.bro
@@ -14,8 +14,7 @@ export {
};
redef record Info += {
- ## This stores and logs the result of certificate validation for
- ## this connection.
+ ## Result of certificate validation for this connection.
validation_status: string &log &optional;
};
diff --git a/scripts/site/local-manager.bro b/scripts/site/local-manager.bro
index c933207603..5e6005f21e 100644
--- a/scripts/site/local-manager.bro
+++ b/scripts/site/local-manager.bro
@@ -1,9 +1 @@
-##! Local site policy loaded only by the manager in a cluster.
-
-@load base/frameworks/notice
-
-# If you are running a cluster you should define your Notice::policy here
-# so that notice processing occurs on the manager.
-redef Notice::policy += {
-
-};
+##! Local site policy loaded only by the manager if Bro is running as a cluster.
diff --git a/scripts/site/local-proxy.bro b/scripts/site/local-proxy.bro
index 1b71cc1870..478ba6d048 100644
--- a/scripts/site/local-proxy.bro
+++ b/scripts/site/local-proxy.bro
@@ -1,2 +1 @@
##! Local site policy loaded only by the proxies if Bro is running as a cluster.
-
diff --git a/scripts/site/local.bro b/scripts/site/local.bro
index 8e1f4d802b..9681f7a75c 100644
--- a/scripts/site/local.bro
+++ b/scripts/site/local.bro
@@ -1,22 +1,29 @@
-##! Local site policy. Customize as appropriate. This file will not be
-##! overwritten when upgrading or reinstalling.
+##! Local site policy. Customize as appropriate.
+##!
+##! This file will not be overwritten when upgrading or reinstalling!
-# Load the script to log which script were loaded during each run
+# This script logs which scripts were loaded during each run.
@load misc/loaded-scripts
# Apply the default tuning scripts for common tuning settings.
@load tuning/defaults
-# Vulnerable versions of software to generate notices for when discovered.
+# Generate notices when vulnerable versions of software are discovered.
# The default is to only monitor software found in the address space defined
# as "local". Refer to the software framework's documentation for more
# information.
@load frameworks/software/vulnerable
+
+# Example vulnerable software. This needs to be updated and maintained over
+# time as new vulnerabilities are discovered.
redef Software::vulnerable_versions += {
["Flash"] = [$major=10,$minor=2,$minor2=153,$addl="1"],
["Java"] = [$major=1,$minor=6,$minor2=0,$addl="22"],
};
+# Detect software changing (e.g. attacker installing hacked SSHD).
+@load frameworks/software/version-changes
+
# This adds signatures to detect cleartext forward and reverse windows shells.
redef signature_files += "frameworks/signatures/detect-windows-shells.sig";
@@ -25,13 +32,15 @@ redef signature_files += "frameworks/signatures/detect-windows-shells.sig";
# redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 0] };
# Load all of the scripts that detect software in various protocols.
-@load protocols/http/software
-#@load protocols/http/detect-webapps
@load protocols/ftp/software
@load protocols/smtp/software
@load protocols/ssh/software
+@load protocols/http/software
+# The detect-webapps script could possibly cause performance trouble when
+# running on live traffic. Enable it cautiously.
+#@load protocols/http/detect-webapps
-# Load the script to detect DNS results pointing toward your Site::local_nets
+# This script detects DNS results pointing toward your Site::local_nets
# where the name is not part of your local DNS zone and is being hosted
# externally. Requires that the Site::local_zones variable is defined.
@load protocols/dns/detect-external-names
@@ -39,15 +48,12 @@ redef signature_files += "frameworks/signatures/detect-windows-shells.sig";
# Script to detect various activity in FTP sessions.
@load protocols/ftp/detect
-# Detect software changing (e.g. attacker installing hacked SSHD).
-@load frameworks/software/version-changes
-
# Scripts that do asset tracking.
@load protocols/conn/known-hosts
@load protocols/conn/known-services
@load protocols/ssl/known-certs
-# Load the script to enable SSL/TLS certificate validation.
+# This script enables SSL/TLS certificate validation.
@load protocols/ssl/validate-certs
# If you have libGeoIP support built in, do some geographic detections and
@@ -60,5 +66,5 @@ redef signature_files += "frameworks/signatures/detect-windows-shells.sig";
# Detect MD5 sums in Team Cymru's Malware Hash Registry.
@load protocols/http/detect-MHR
-# Detect SQL injection attacks
+# Detect SQL injection attacks.
@load protocols/http/detect-sqli
diff --git a/src/BroDoc.cc b/src/BroDoc.cc
index 91aed5ec62..b20db727ff 100644
--- a/src/BroDoc.cc
+++ b/src/BroDoc.cc
@@ -170,13 +170,26 @@ void BroDoc::WriteDocFile() const
{
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
+ WriteToDoc(":tocdepth: 3\n\n");
+
WriteSectionHeading(doc_title.c_str(), '=');
- WriteToDoc("\n:download:`Original Source File <%s>`\n\n",
- downloadable_filename.c_str());
+ WriteStringList(".. bro:namespace:: %s\n", modules);
- WriteSectionHeading("Overview", '-');
- WriteStringList("%s\n", "%s\n\n", summary);
+ WriteToDoc("\n");
+
+ // WriteSectionHeading("Overview", '-');
+ WriteStringList("%s\n", summary);
+
+ WriteToDoc("\n");
+
+ if ( ! modules.empty() )
+ {
+ WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
+ // WriteStringList(":bro:namespace:`%s`", modules);
+ WriteStringList("``%s``, ", "``%s``", modules);
+ WriteToDoc("\n");
+ }
if ( ! imports.empty() )
{
@@ -196,39 +209,38 @@ void BroDoc::WriteDocFile() const
WriteToDoc("\n");
}
+ WriteToDoc(":Source File: :download:`%s`\n",
+ downloadable_filename.c_str());
+
WriteToDoc("\n");
WriteInterface("Summary", '~', '#', true, true);
- if ( ! modules.empty() )
- {
- WriteSectionHeading("Namespaces", '~');
- WriteStringList(".. bro:namespace:: %s\n", modules);
- WriteToDoc("\n");
- }
-
if ( ! notices.empty() )
- WriteBroDocObjList(notices, "Notices", '~');
+ WriteBroDocObjList(notices, "Notices", '#');
- WriteInterface("Public Interface", '-', '~', true, false);
+ if ( port_analysis.size() || packet_filter.size() )
+ WriteSectionHeading("Configuration Changes", '#');
if ( ! port_analysis.empty() )
{
- WriteSectionHeading("Port Analysis", '-');
+ WriteSectionHeading("Port Analysis", '^');
WriteToDoc("Loading this script makes the following changes to "
":bro:see:`dpd_config`.\n\n");
- WriteStringList("%s", port_analysis);
+ WriteStringList("%s, ", "%s", port_analysis);
}
if ( ! packet_filter.empty() )
{
- WriteSectionHeading("Packet Filter", '-');
+ WriteSectionHeading("Packet Filter", '^');
WriteToDoc("Loading this script makes the following changes to "
":bro:see:`capture_filters`.\n\n");
WriteToDoc("Filters added::\n\n");
WriteToDoc("%s\n", packet_filter.c_str());
}
+ WriteInterface("Detailed Interface", '~', '#', true, false);
+
#if 0 // Disabled for now.
BroDocObjList::const_iterator it;
bool hasPrivateIdentifiers = false;
@@ -243,7 +255,7 @@ void BroDoc::WriteDocFile() const
}
if ( hasPrivateIdentifiers )
- WriteInterface("Private Interface", '-', '~', false, false);
+ WriteInterface("Private Interface", '~', '#', false, false);
#endif
}
diff --git a/src/bro.bif b/src/bro.bif
index c78ae5bffe..121f310682 100644
--- a/src/bro.bif
+++ b/src/bro.bif
@@ -1,4 +1,8 @@
-# Definitions of Bro built-in functions.
+##! A collection of built-in functions that implement a variety of things
+##! such as general programming algorithms, string processing, math functions,
+##! introspection, type conversion, file/directory manipulation, packet
+##! filtering, inter-process communication and controlling protocol analyzer
+##! behavior.
%%{ // C segment
#include
@@ -317,474 +321,48 @@ static int next_fmt(const char*& fmt, val_list* args, ODesc* d, int& n)
}
%%}
-function length%(v: any%): count
- %{
- TableVal* tv = v->Type()->Tag() == TYPE_TABLE ? v->AsTableVal() : 0;
-
- if ( tv )
- return new Val(tv->Size(), TYPE_COUNT);
-
- else if ( v->Type()->Tag() == TYPE_VECTOR )
- return new Val(v->AsVectorVal()->Size(), TYPE_COUNT);
-
- else
- {
- builtin_error("length() requires a table/set/vector argument");
- return new Val(0, TYPE_COUNT);
- }
- %}
-
-function same_object%(o1: any, o2: any%): bool
- %{
- return new Val(o1 == o2, TYPE_BOOL);
- %}
-
-function clear_table%(v: any%): any
- %{
- if ( v->Type()->Tag() == TYPE_TABLE )
- v->AsTableVal()->RemoveAll();
- else
- builtin_error("clear_table() requires a table/set argument");
-
- return 0;
- %}
-
-function cat%(...%): string
- %{
- ODesc d;
- loop_over_list(@ARG@, i)
- @ARG@[i]->Describe(&d);
-
- BroString* s = new BroString(1, d.TakeBytes(), d.Len());
- s->SetUseFreeToDelete(true);
-
- return new StringVal(s);
- %}
-
-function record_type_to_vector%(rt: string%): string_vec
- %{
- VectorVal* result = new VectorVal(string_vec);
-
- ID* id = lookup_ID(rt->CheckString(), GLOBAL_MODULE_NAME);
-
- if ( id )
- {
- RecordType *type = id->Type()->AsRecordType();
- for ( int i = 0; i < type->NumFields(); ++i )
- {
- StringVal* val = new StringVal(type->FieldName(i));
- result->Assign(i+1, val, 0);
- }
- Unref(id);
- }
- else
- reporter->InternalError("internal record type %s missing",
- rt->CheckString());
-
- return result;
- %}
-
-
-function cat_sep%(sep: string, def: string, ...%): string
- %{
- ODesc d;
- int pre_size = 0;
-
- loop_over_list(@ARG@, i)
- {
- // Skip named parameters.
- if ( i < 2 )
- continue;
-
- if ( i > 2 )
- d.Add(sep->CheckString(), 0);
-
- Val* v = @ARG@[i];
- if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() )
- v = def;
-
- v->Describe(&d);
- }
-
- BroString* s = new BroString(1, d.TakeBytes(), d.Len());
- s->SetUseFreeToDelete(true);
-
- return new StringVal(s);
- %}
-
-function fmt%(...%): string
- %{
- if ( @ARGC@ == 0 )
- return new StringVal("");
-
- Val* fmt_v = @ARG@[0];
- if ( fmt_v->Type()->Tag() != TYPE_STRING )
- return bro_cat(frame, @ARGS@);
-
- const char* fmt = fmt_v->AsString()->CheckString();
- ODesc d;
- int n = 0;
-
- while ( next_fmt(fmt, @ARGS@, &d, n) )
- ;
-
- if ( n < @ARGC@ - 1 )
- builtin_error("too many arguments for format", fmt_v);
-
- else if ( n >= @ARGC@ )
- builtin_error("too few arguments for format", fmt_v);
-
- BroString* s = new BroString(1, d.TakeBytes(), d.Len());
- s->SetUseFreeToDelete(true);
-
- return new StringVal(s);
- %}
-
-function type_name%(t: any%): string
- %{
- ODesc d;
- t->Type()->Describe(&d);
-
- BroString* s = new BroString(1, d.TakeBytes(), d.Len());
- s->SetUseFreeToDelete(true);
-
- return new StringVal(s);
- %}
-
-function to_int%(str: string%): int
- %{
- const char* s = str->CheckString();
- char* end_s;
-
- long l = strtol(s, &end_s, 10);
- int i = int(l);
-
-#if 0
- // Not clear we should complain. For example, is " 205 "
- // a legal conversion?
- if ( s[0] == '\0' || end_s[0] != '\0' )
- builtin_error("bad conversion to integer", @ARG@[0]);
-#endif
-
- return new Val(i, TYPE_INT);
- %}
-
-function int_to_count%(n: int%): count
- %{
- if ( n < 0 )
- {
- builtin_error("bad conversion to count", @ARG@[0]);
- n = 0;
- }
- return new Val(n, TYPE_COUNT);
- %}
-
-function double_to_count%(d: double%): count
- %{
- if ( d < 0.0 )
- builtin_error("bad conversion to count", @ARG@[0]);
-
- return new Val(bro_uint_t(rint(d)), TYPE_COUNT);
- %}
-
-function to_count%(str: string%): count
- %{
- const char* s = str->CheckString();
- char* end_s;
-
- uint64 u = (uint64) strtoll(s, &end_s, 10);
-
- if ( s[0] == '\0' || end_s[0] != '\0' )
- {
- builtin_error("bad conversion to count", @ARG@[0]);
- u = 0;
- }
-
- return new Val(u, TYPE_COUNT);
- %}
-
-function interval_to_double%(i: interval%): double
- %{
- return new Val(i, TYPE_DOUBLE);
- %}
-
-function time_to_double%(t: time%): double
- %{
- return new Val(t, TYPE_DOUBLE);
- %}
-
-function double_to_time%(d: double%): time
- %{
- return new Val(d, TYPE_TIME);
- %}
-
-function double_to_interval%(d: double%): interval
- %{
- return new Val(d, TYPE_INTERVAL);
- %}
-
-function addr_to_count%(a: addr%): count
- %{
-#ifdef BROv6
- if ( ! is_v4_addr(a) )
- {
- builtin_error("conversion of non-IPv4 address to count", @ARG@[0]);
- return new Val(0, TYPE_COUNT);
- }
-
- uint32 addr = to_v4_addr(a);
-#else
- uint32 addr = a;
-#endif
- return new Val(ntohl(addr), TYPE_COUNT);
- %}
-
-function port_to_count%(p: port%): count
- %{
- return new Val(p->Port(), TYPE_COUNT);
- %}
-
-function count_to_port%(c: count, t: transport_proto%): port
- %{
- return new PortVal(c, (TransportProto)(t->InternalInt()));
- %}
-
-function floor%(d: double%): double
- %{
- return new Val(floor(d), TYPE_DOUBLE);
- %}
-
-function to_addr%(ip: string%): addr
- %{
- char* s = ip->AsString()->Render();
- Val* ret = new AddrVal(s);
- delete [] s;
- return ret;
- %}
-
-function count_to_v4_addr%(ip: count%): addr
- %{
- if ( ip > 4294967295LU )
- {
- builtin_error("conversion of non-IPv4 count to addr", @ARG@[0]);
- return new AddrVal(uint32(0));
- }
-
- return new AddrVal(htonl(uint32(ip)));
- %}
-
-# Interprets the first 4 bytes of 'b' as an IPv4 address in network order.
-function raw_bytes_to_v4_addr%(b: string%): addr
- %{
- uint32 a = 0;
-
- if ( b->Len() < 4 )
- builtin_error("too short a string as input to raw_bytes_to_v4_addr()");
-
- else
- {
- const u_char* bp = b->Bytes();
- a = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
- }
-
- return new AddrVal(htonl(a));
- %}
-
-function to_port%(num: count, proto: transport_proto%): port
- %{
- return new PortVal(num, (TransportProto)proto->AsEnum());
- %}
-
-function mask_addr%(a: addr, top_bits_to_keep: count%): subnet
- %{
- return new SubNetVal(mask_addr(a, top_bits_to_keep), top_bits_to_keep);
- %}
-
-# Take some top bits (e.g. subnet address) from a1 and the other
-# bits (intra-subnet part) from a2 and merge them to get a new address.
-# This is useful for anonymizing at subnet level while preserving
-# serial scans.
-function remask_addr%(a1: addr, a2: addr, top_bits_from_a1: count%): addr
- %{
-#ifdef BROv6
- if ( ! is_v4_addr(a1) || ! is_v4_addr(a2) )
- {
- builtin_error("cannot use remask_addr on IPv6 addresses");
- return new AddrVal(a1);
- }
-
- uint32 x1 = to_v4_addr(a1);
- uint32 x2 = to_v4_addr(a2);
-#else
- uint32 x1 = a1;
- uint32 x2 = a2;
-#endif
- return new AddrVal(
- mask_addr(x1, top_bits_from_a1) |
- (x2 ^ mask_addr(x2, top_bits_from_a1)) );
- %}
-
-function is_tcp_port%(p: port%): bool
- %{
- return new Val(p->IsTCP(), TYPE_BOOL);
- %}
-
-function is_udp_port%(p: port%): bool
- %{
- return new Val(p->IsUDP(), TYPE_BOOL);
- %}
-
-function is_icmp_port%(p: port%): bool
- %{
- return new Val(p->IsICMP(), TYPE_BOOL);
- %}
-
-function reading_live_traffic%(%): bool
- %{
- return new Val(reading_live, TYPE_BOOL);
- %}
-
-function reading_traces%(%): bool
- %{
- return new Val(reading_traces, TYPE_BOOL);
- %}
-
-function open%(f: string%): file
- %{
- const char* file = f->CheckString();
-
- if ( streq(file, "-") )
- return new Val(new BroFile(stdout, "-", "w"));
- else
- return new Val(new BroFile(file, "w"));
- %}
-
-function open_for_append%(f: string%): file
- %{
- return new Val(new BroFile(f->CheckString(), "a"));
- %}
-
-function close%(f: file%): bool
- %{
- return new Val(f->Close(), TYPE_BOOL);
- %}
-
-function write_file%(f: file, data: string%): bool
- %{
- if ( ! f )
- return new Val(0, TYPE_BOOL);
-
- return new Val(f->Write((const char*) data->Bytes(), data->Len()),
- TYPE_BOOL);
- %}
-
-function set_buf%(f: file, buffered: bool%): any
- %{
- f->SetBuf(buffered);
- return new Val(0, TYPE_VOID);
- %}
-
-function flush_all%(%): bool
- %{
- return new Val(fflush(0) == 0, TYPE_BOOL);
- %}
-
-function mkdir%(f: string%): bool
- %{
- const char* filename = f->CheckString();
- if ( mkdir(filename, 0777) < 0 && errno != EEXIST )
- {
- builtin_error("cannot create directory", @ARG@[0]);
- return new Val(0, TYPE_BOOL);
- }
- else
- return new Val(1, TYPE_BOOL);
- %}
-
-function active_file%(f: file%): bool
- %{
- return new Val(f->IsOpen(), TYPE_BOOL);
- %}
-
-function active_connection%(id: conn_id%): bool
- %{
- Connection* c = sessions->FindConnection(id);
- return new Val(c ? 1 : 0, TYPE_BOOL);
- %}
-
-# Note, you *must* first make sure that the connection is active
-# (e.g., by calling active_connection()) before invoking this.
-function connection_record%(cid: conn_id%): connection
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( c )
- return c->BuildConnVal();
- else
- {
- // Hard to recover from this until we have union types ...
- builtin_error("connection ID not a known connection (fatal)", cid);
- exit(0);
- return 0;
- }
- %}
-
-%%{
-EnumVal* map_conn_type(TransportProto tp)
- {
- switch ( tp ) {
- case TRANSPORT_UNKNOWN:
- return new EnumVal(0, transport_proto);
- break;
-
- case TRANSPORT_TCP:
- return new EnumVal(1, transport_proto);
- break;
-
- case TRANSPORT_UDP:
- return new EnumVal(2, transport_proto);
- break;
-
- case TRANSPORT_ICMP:
- return new EnumVal(3, transport_proto);
- break;
-
- default:
- reporter->InternalError("bad connection type in map_conn_type()");
- }
-
- // Cannot be reached;
- assert(false);
- return 0; // Make compiler happy.
- }
-%%}
-
-function get_conn_transport_proto%(cid: conn_id%): transport_proto
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- {
- builtin_error("unknown connection id in get_conn_transport_proto()", cid);
- return new EnumVal(0, transport_proto);
- }
-
- return map_conn_type(c->ConnTransport());
- %}
-
-function get_port_transport_proto%(p: port%): transport_proto
- %{
- return map_conn_type(p->PortType());
- %}
-
+# ===========================================================================
+#
+# Core
+#
+# ===========================================================================
+
+## Returns the current wall-clock time.
+##
+## In general, you should use :bro:id:`network_time` instead
+## unless you are using Bro for non-networking uses (such as general
+## scripting; not particularly recommended), because otherwise your script
+## may behave very differently on live traffic versus played-back traffic
+## from a save file.
+##
+## Returns: The wall-clock time.
+##
+## .. bro:see:: network_time
function current_time%(%): time
%{
return new Val(current_time(), TYPE_TIME);
%}
+## Returns the timestamp of the last packet processed. This function returns
+## the timestamp of the most recently read packet, whether read from a
+## live network interface or from a save file.
+##
+## Returns: The timestamp of the packet processed.
+##
+## .. bro:see:: current_time
function network_time%(%): time
%{
return new Val(network_time, TYPE_TIME);
%}
+## Returns a system environment variable.
+##
+## var: The name of the variable whose value to request.
+##
+## Returns: The system environment variable identified by *var*, or an empty
+## string if it is not defined.
+##
+## .. bro:see:: setenv
function getenv%(var: string%): string
%{
const char* env_val = getenv(var->CheckString());
@@ -793,50 +371,40 @@ function getenv%(var: string%): string
return new StringVal(env_val);
%}
+## Sets a system environment variable.
+##
+## var: The name of the variable.
+##
+## val: The (new) value of the variable *var*.
+##
+## Returns: True on success.
+##
+## .. bro:see:: getenv
function setenv%(var: string, val: string%): bool
%{
- int result = setenv(var->AsString()->CheckString(),
+ int result = setenv(var->AsString()->CheckString(),
val->AsString()->CheckString(), 1);
-
+
if ( result < 0 )
return new Val(0, TYPE_BOOL);
return new Val(1, TYPE_BOOL);
%}
-function sqrt%(x: double%): double
- %{
- if ( x < 0 )
- {
- reporter->Error("negative sqrt argument");
- return new Val(-1.0, TYPE_DOUBLE);
- }
-
- return new Val(sqrt(x), TYPE_DOUBLE);
- %}
-
-function exp%(d: double%): double
- %{
- return new Val(exp(d), TYPE_DOUBLE);
- %}
-
-# Natural log.
-function ln%(d: double%): double
- %{
- return new Val(log(d), TYPE_DOUBLE);
- %}
-
-# Common log.
-function log10%(d: double%): double
- %{
- return new Val(log10(d), TYPE_DOUBLE);
- %}
-
+## Shuts down the Bro process immediately.
+##
+## .. todo: Change function signature to ``exit(code: int): any``.
function exit%(%): int
%{
exit(0);
return 0;
%}
+## Gracefully shut down Bro by terminating outstanding processing.
+##
+## Returns: True after successful termination and false when Bro is still in
+## the process of shutting down.
+##
+## .. bro:see:: bro_is_terminating
function terminate%(%): bool
%{
if ( terminating )
@@ -893,12 +461,41 @@ static int do_system(const char* s)
}
%%}
+## Invokes a command via the ``system`` function of the OS.
+## The command runs in the background with ``stdout`` redirecting to
+## ``stderr``. Here is a usage example:
+## ``system(fmt("rm \"%s\"", str_shell_escape(sniffed_data)));``
+##
+## str: The command to execute.
+##
+## Returns: The return value from the OS ``system`` function.
+##
+## .. bro:see:: system_env str_shell_escape piped_exec
+##
+## .. note::
+##
+## Note that this corresponds to the status of backgrounding the
+## given command, not to the exit status of the command itself. A
+## value of 127 corresponds to a failure to execute ``sh``, and -1
+## to an internal system failure.
function system%(str: string%): int
%{
int result = do_system(str->CheckString());
return new Val(result, TYPE_INT);
%}
+## Invokes a command via the ``system`` function of the OS with a prepared
+## environment. The function is essentially the same as :bro:id:`system`,
+## but changes the environment before invoking the command.
+##
+## str: The command to execute.
+##
+## env: A :bro:type:`set` or :bro:type:`table` with the environment variables
+## in the form of key-value pairs (where the value is optional).
+##
+## Returns: The return value from the OS ``system`` function.
+##
+## .. bro:see:: system str_shell_escape piped_exec
function system_env%(str: string, env: any%): int
%{
if ( env->Type()->Tag() != TYPE_TABLE )
@@ -917,816 +514,43 @@ function system_env%(str: string, env: any%): int
return new Val(result, TYPE_INT);
%}
-
-%%{
-static Val* parse_eftp(const char* line)
- {
- RecordVal* r = new RecordVal(ftp_port);
-
- int net_proto = 0; // currently not used
- uint32 addr = 0;
- int port = 0;
- int good = 0;
-
- if ( line )
- {
- while ( isspace(*line) ) // skip whitespace
- ++line;
-
- char delimiter = *line;
- good = 1;
- char* next_delim;
-
- ++line; // cut off delimiter
- net_proto = strtol(line, &next_delim, 10); // currently ignored
- if ( *next_delim != delimiter )
- good = 0;
-
- line = next_delim + 1;
- if ( *line != delimiter ) // default of 0 is ok
- {
- addr = dotted_to_addr(line);
- if ( addr == 0 )
- good = 0;
- }
-
- // FIXME: check for garbage between IP and delimiter.
- line = strchr(line, delimiter);
-
- ++line; // now the port
- port = strtol(line, &next_delim, 10);
- if ( *next_delim != delimiter )
- good = 0;
- }
-
- r->Assign(0, new AddrVal(addr));
- r->Assign(1, new PortVal(port, TRANSPORT_TCP));
- r->Assign(2, new Val(good, TYPE_BOOL));
-
- return r;
- }
-%%}
-
-%%{
-static Val* parse_port(const char* line)
- {
- RecordVal* r = new RecordVal(ftp_port);
-
- int bytes[6];
- if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d",
- &bytes[0], &bytes[1], &bytes[2],
- &bytes[3], &bytes[4], &bytes[5]) == 6 )
- {
- int good = 1;
-
- for ( int i = 0; i < 6; ++i )
- if ( bytes[i] < 0 || bytes[i] > 255 )
- {
- good = 0;
- break;
- }
-
- uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) |
- (bytes[2] << 8) | bytes[3];
- uint32 port = (bytes[4] << 8) | bytes[5];
-
- // Since port is unsigned, no need to check for < 0.
- if ( port > 65535 )
- {
- port = 0;
- good = 0;
- }
-
- r->Assign(0, new AddrVal(htonl(addr)));
- r->Assign(1, new PortVal(port, TRANSPORT_TCP));
- r->Assign(2, new Val(good, TYPE_BOOL));
- }
- else
- {
- r->Assign(0, new AddrVal(uint32(0)));
- r->Assign(1, new PortVal(0, TRANSPORT_TCP));
- r->Assign(2, new Val(0, TYPE_BOOL));
- }
-
- return r;
- }
-%%}
-
-# Returns true if the given connection exists, false otherwise.
-function connection_exists%(c: conn_id%): bool
+## Opens a program with ``popen`` and writes a given string to the returned
+## stream to send it to the opened process's stdin.
+##
+## program: The program to execute.
+##
+## to_write: Data to pipe to the opened program's process via ``stdin``.
+##
+## Returns: True on success.
+##
+## .. bro:see:: system system_env
+function piped_exec%(program: string, to_write: string%): bool
%{
- if ( sessions->FindConnection(c) )
- return new Val(1, TYPE_BOOL);
- else
- return new Val(0, TYPE_BOOL);
- %}
+ const char* prog = program->CheckString();
-# For a given connection ID, returns the corresponding "connection" record.
-# Generates a run-time error and returns a dummy value if the connection
-# doesn't exist.
-function lookup_connection%(cid: conn_id%): connection
- %{
- Connection* conn = sessions->FindConnection(cid);
- if ( conn )
- return conn->BuildConnVal();
-
- builtin_error("connection ID not a known connection", cid);
-
- // Return a dummy connection record.
- RecordVal* c = new RecordVal(connection_type);
-
- RecordVal* id_val = new RecordVal(conn_id);
- id_val->Assign(0, new AddrVal((unsigned int) 0));
- id_val->Assign(1, new PortVal(ntohs(0), TRANSPORT_UDP));
- id_val->Assign(2, new AddrVal((unsigned int) 0));
- id_val->Assign(3, new PortVal(ntohs(0), TRANSPORT_UDP));
- c->Assign(0, id_val);
-
- RecordVal* orig_endp = new RecordVal(endpoint);
- orig_endp->Assign(0, new Val(0, TYPE_COUNT));
- orig_endp->Assign(1, new Val(int(0), TYPE_COUNT));
-
- RecordVal* resp_endp = new RecordVal(endpoint);
- resp_endp->Assign(0, new Val(0, TYPE_COUNT));
- resp_endp->Assign(1, new Val(int(0), TYPE_COUNT));
-
- c->Assign(1, orig_endp);
- c->Assign(2, resp_endp);
-
- c->Assign(3, new Val(network_time, TYPE_TIME));
- c->Assign(4, new Val(0.0, TYPE_INTERVAL));
- c->Assign(5, new TableVal(string_set)); // service
- c->Assign(6, new StringVal("")); // addl
- c->Assign(7, new Val(0, TYPE_COUNT)); // hot
- c->Assign(8, new StringVal("")); // history
-
- return c;
- %}
-
-function skip_further_processing%(cid: conn_id%): bool
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_BOOL);
-
- c->SetSkip(1);
- return new Val(1, TYPE_BOOL);
- %}
-
-function set_record_packets%(cid: conn_id, do_record: bool%): bool
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_BOOL);
-
- c->SetRecordPackets(do_record);
- return new Val(1, TYPE_BOOL);
- %}
-
-function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_BOOL);
-
- c->GetRootAnalyzer()->SetContentsFile(direction, f);
- return new Val(1, TYPE_BOOL);
- %}
-
-function get_contents_file%(cid: conn_id, direction: count%): file
- %{
- Connection* c = sessions->FindConnection(cid);
- BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0;
-
- if ( f )
- {
- Ref(f);
- return new Val(f);
- }
-
- // Return some sort of error value.
- if ( ! c )
- builtin_error("unknown connection id in get_contents_file()", cid);
- else
- builtin_error("no contents file for given direction");
-
- return new Val(new BroFile(stderr, "-", "w"));
- %}
-
-function get_file_name%(f: file%): string
- %{
+ FILE* f = popen(prog, "w");
if ( ! f )
- return new StringVal("");
-
- return new StringVal(f->Name());
- %}
-
-# Set an individual inactivity timeout for this connection
-# (overrides the global inactivity_timeout). Returns previous
-# timeout interval.
-function set_inactivity_timeout%(cid: conn_id, t: interval%): interval
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_INTERVAL);
-
- double old_timeout = c->InactivityTimeout();
- c->SetInactivityTimeout(t);
-
- return new Val(old_timeout, TYPE_INTERVAL);
- %}
-
-function get_login_state%(cid: conn_id%): count
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
+ {
+ reporter->Error("Failed to popen %s", prog);
return new Val(0, TYPE_BOOL);
+ }
- Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login);
- if ( ! la )
+ const u_char* input_data = to_write->Bytes();
+ int input_data_len = to_write->Len();
+
+ int bytes_written = fwrite(input_data, 1, input_data_len, f);
+
+ pclose(f);
+
+ if ( bytes_written != input_data_len )
+ {
+ reporter->Error("Failed to write all given data to %s", prog);
return new Val(0, TYPE_BOOL);
+ }
- return new Val(int(static_cast(la)->LoginState()),
- TYPE_COUNT);
- %}
-
-function set_login_state%(cid: conn_id, new_state: count%): bool
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_BOOL);
-
- Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login);
- if ( ! la )
- return new Val(0, TYPE_BOOL);
-
- static_cast(la)->SetLoginState(login_state(new_state));
return new Val(1, TYPE_BOOL);
%}
-%%{
-#include "TCP.h"
-%%}
-
-function get_orig_seq%(cid: conn_id%): count
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_COUNT);
-
- if ( c->ConnTransport() != TRANSPORT_TCP )
- return new Val(0, TYPE_COUNT);
-
- Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP);
- if ( tc )
- return new Val(static_cast(tc)->OrigSeq(),
- TYPE_COUNT);
- else
- {
- reporter->Error("connection does not have TCP analyzer");
- return new Val(0, TYPE_COUNT);
- }
- %}
-
-function get_resp_seq%(cid: conn_id%): count
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- return new Val(0, TYPE_COUNT);
-
- if ( c->ConnTransport() != TRANSPORT_TCP )
- return new Val(0, TYPE_COUNT);
-
- Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP);
- if ( tc )
- return new Val(static_cast(tc)->RespSeq(),
- TYPE_COUNT);
- else
- {
- reporter->Error("connection does not have TCP analyzer");
- return new Val(0, TYPE_COUNT);
- }
- %}
-
-# These convert addresses <-> n3.n2.n1.n0.in-addr.arpa
-function ptr_name_to_addr%(s: string%): addr
- %{
- int a[4];
- uint32 addr;
-
- if ( sscanf(s->CheckString(),
- "%d.%d.%d.%d.in-addr.arpa",
- a, a+1, a+2, a+3) != 4 )
- {
- builtin_error("bad PTR name", @ARG@[0]);
- addr = 0;
- }
- else
- addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
-
- return new AddrVal(htonl(addr));
- %}
-
-function addr_to_ptr_name%(a: addr%): string
- %{
- // ## Question:
- // uint32 addr = ntohl((*args)[0]->InternalUnsigned());
- uint32 addr;
-#ifdef BROv6
- if ( is_v4_addr(a) )
- addr = a[3];
- else
- {
- builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
- addr = 0;
- }
-#else
- addr = a;
-#endif
-
- addr = ntohl(addr);
- uint32 a3 = (addr >> 24) & 0xff;
- uint32 a2 = (addr >> 16) & 0xff;
- uint32 a1 = (addr >> 8) & 0xff;
- uint32 a0 = addr & 0xff;
-
- char buf[256];
- sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3);
-
- return new StringVal(buf);
- %}
-
-# Transforms n0.n1.n2.n3 -> addr.
-function parse_dotted_addr%(s: string%): addr
- %{
- return new AddrVal(dotted_to_addr(s->CheckString()));
- %}
-
-function parse_ftp_port%(s: string%): ftp_port
- %{
- return parse_port(s->CheckString());
- %}
-
-function parse_eftp_port%(s: string%): ftp_port
- %{
- return parse_eftp(s->CheckString());
- %}
-
-function parse_ftp_pasv%(str: string%): ftp_port
- %{
- const char* s = str->CheckString();
- const char* line = strchr(s, '(');
- if ( line )
- ++line; // move past '('
- else if ( (line = strstr(s, "PORT")) )
- line += 5; // Skip over
- else if ( (line = strchr(s, ',')) )
- { // Look for comma-separated list.
- while ( --line >= s && isdigit(*line) )
- ; // Back up over preceding digits.
- ++line; // now points to first digit, or beginning of s
- }
-
- return parse_port(line);
- %}
-
-function parse_ftp_epsv%(str: string%): ftp_port
- %{
- const char* s = str->CheckString();
- const char* line = strchr(s, '(');
- if ( line )
- ++line; // move past '('
- return parse_eftp(line);
- %}
-
-function fmt_ftp_port%(a: addr, p: port%): string
- %{
-#ifdef BROv6
- if ( ! is_v4_addr(a) )
- builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
-
- uint32 addr = to_v4_addr(a);
-#else
- uint32 addr = a;
-#endif
- addr = ntohl(addr);
- uint32 pn = p->Port();
- return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
- addr >> 24, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff,
- pn >> 8, pn & 0xff));
- %}
-
-function decode_netbios_name%(name: string%): string
- %{
- char buf[16];
- char result[16];
- const u_char* s = name->Bytes();
- int i, j;
-
- for ( i = 0, j = 0; i < 16; ++i )
- {
- char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A';
- char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A';
- buf[i] = ((c0 - 'A') << 4) + (c1 - 'A');
- }
-
- for ( i = 0; i < 15; ++i )
- {
- if ( isalnum(buf[i]) || ispunct(buf[i]) ||
- // \x01\x02 is seen in at least one case as the first two bytes.
- // I think that any \x01 and \x02 should always be passed through.
- buf[i] < 3 )
- result[i] = buf[i];
- else
- break;
- }
-
- return new StringVal(i, result);
- %}
-
-function decode_netbios_name_type%(name: string%): count
- %{
- const u_char* s = name->Bytes();
- char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A');
- return new Val(return_val, TYPE_COUNT);
- %}
-
-%%{
-#include "HTTP.h"
-
-const char* conn_id_string(Val* c)
- {
- Val* id = (*(c->AsRecord()))[0];
- const val_list* vl = id->AsRecord();
-
- addr_type orig_h = (*vl)[0]->AsAddr();
- uint32 orig_p = (*vl)[1]->AsPortVal()->Port();
- addr_type resp_h = (*vl)[2]->AsAddr();
- uint32 resp_p = (*vl)[3]->AsPortVal()->Port();
-
- return fmt("%s/%u -> %s/%u\n", dotted_addr(orig_h), orig_p, dotted_addr(resp_h), resp_p);
- }
-%%}
-
-# Skip data of the HTTP entity on the connection
-function skip_http_entity_data%(c: connection, is_orig: bool%): any
- %{
- AnalyzerID id = mgr.CurrentAnalyzer();
- if ( id )
- {
- Analyzer* ha = c->FindAnalyzer(id);
-
- if ( ha )
- {
- if ( ha->GetTag() == AnalyzerTag::HTTP )
- static_cast(ha)->SkipEntityData(is_orig);
- else
- reporter->Error("non-HTTP analyzer associated with connection record");
- }
- else
- reporter->Error("could not find analyzer for skip_http_entity_data");
-
- }
- else
- reporter->Error("no analyzer associated with connection record");
-
- return 0;
- %}
-
-# Unescape all characters in the URI, i.e. decode every %xx group.
-#
-# Note that unescaping reserved characters may cause loss of
-# information (see below).
-#
-# RFC 2396: A URI is always in an "escaped" form, since escaping or
-# unescaping a completed URI might change its semantics. Normally,
-# the only time escape encodings can safely be made is when the URI
-# is being created from its component parts.
-
-function unescape_URI%(URI: string%): string
- %{
- const u_char* line = URI->Bytes();
- const u_char* const line_end = line + URI->Len();
-
- return new StringVal(unescape_URI(line, line_end, 0));
- %}
-
-%%{
-#include "SMTP.h"
-%%}
-
-# Skip smtp_data till next mail
-function skip_smtp_data%(c: connection%): any
- %{
- Analyzer* sa = c->FindAnalyzer(AnalyzerTag::SMTP);
- if ( sa )
- static_cast(sa)->SkipData();
- return 0;
- %}
-
-
-function bytestring_to_hexstr%(bytestring: string%): string
- %{
- bro_uint_t len = bytestring->AsString()->Len();
- const u_char* bytes = bytestring->AsString()->Bytes();
- char hexstr[(2 * len) + 1];
-
- hexstr[0] = 0;
- for ( bro_uint_t i = 0; i < len; ++i )
- snprintf(hexstr + (2 * i), 3, "%.2hhx", bytes[i]);
-
- return new StringVal(hexstr);
- %}
-
-%%{
-extern const char* bro_version();
-%%}
-
-function net_stats%(%): NetStats
- %{
- unsigned int recv = 0;
- unsigned int drop = 0;
- unsigned int link = 0;
-
- loop_over_list(pkt_srcs, i)
- {
- PktSrc* ps = pkt_srcs[i];
-
- struct PktSrc::Stats stat;
- ps->Statistics(&stat);
- recv += stat.received;
- drop += stat.dropped;
- link += stat.link;
- }
-
- RecordVal* ns = new RecordVal(net_stats);
- ns->Assign(0, new Val(recv, TYPE_COUNT));
- ns->Assign(1, new Val(drop, TYPE_COUNT));
- ns->Assign(2, new Val(link, TYPE_COUNT));
-
- return ns;
- %}
-
-function resource_usage%(%): bro_resources
- %{
- struct rusage r;
-
- if ( getrusage(RUSAGE_SELF, &r) < 0 )
- reporter->InternalError("getrusage() failed in bro_resource_usage()");
-
- double elapsed_time = current_time() - bro_start_time;
-
- double user_time =
- double(r.ru_utime.tv_sec) + double(r.ru_utime.tv_usec) / 1e6;
- double system_time =
- double(r.ru_stime.tv_sec) + double(r.ru_stime.tv_usec) / 1e6;
-
- RecordVal* res = new RecordVal(bro_resources);
- int n = 0;
-
- res->Assign(n++, new StringVal(bro_version()));
-
-#ifdef DEBUG
- res->Assign(n++, new Val(1, TYPE_COUNT));
-#else
- res->Assign(n++, new Val(0, TYPE_COUNT));
-#endif
-
- res->Assign(n++, new Val(bro_start_time, TYPE_TIME));
-
- res->Assign(n++, new IntervalVal(elapsed_time, Seconds));
- res->Assign(n++, new IntervalVal(user_time, Seconds));
- res->Assign(n++, new IntervalVal(system_time, Seconds));
-
- unsigned int total_mem;
- get_memory_usage(&total_mem, 0);
- res->Assign(n++, new Val(unsigned(total_mem), TYPE_COUNT));
-
- res->Assign(n++, new Val(unsigned(r.ru_minflt), TYPE_COUNT));
- res->Assign(n++, new Val(unsigned(r.ru_majflt), TYPE_COUNT));
- res->Assign(n++, new Val(unsigned(r.ru_nswap), TYPE_COUNT));
- res->Assign(n++, new Val(unsigned(r.ru_inblock), TYPE_COUNT));
- res->Assign(n++, new Val(unsigned(r.ru_oublock), TYPE_COUNT));
- res->Assign(n++, new Val(unsigned(r.ru_nivcsw), TYPE_COUNT));
-
- SessionStats s;
- if ( sessions )
- sessions->GetStats(s);
-
-#define ADD_STAT(x) \
- res->Assign(n++, new Val(unsigned(sessions ? x : 0), TYPE_COUNT));
-
- ADD_STAT(s.num_TCP_conns);
- ADD_STAT(s.num_UDP_conns);
- ADD_STAT(s.num_ICMP_conns);
- ADD_STAT(s.num_fragments);
- ADD_STAT(s.num_packets);
- ADD_STAT(s.num_timers);
- ADD_STAT(s.num_events_queued);
- ADD_STAT(s.num_events_dispatched);
- ADD_STAT(s.max_TCP_conns);
- ADD_STAT(s.max_UDP_conns);
- ADD_STAT(s.max_ICMP_conns);
- ADD_STAT(s.max_fragments);
- ADD_STAT(s.max_timers);
-
- return res;
- %}
-
-function get_matcher_stats%(%): matcher_stats
- %{
- RuleMatcher::Stats s;
- memset(&s, 0, sizeof(s));
-
- if ( rule_matcher )
- rule_matcher->GetStats(&s);
-
- RecordVal* r = new RecordVal(matcher_stats);
- r->Assign(0, new Val(s.matchers, TYPE_COUNT));
- r->Assign(1, new Val(s.dfa_states, TYPE_COUNT));
- r->Assign(2, new Val(s.computed, TYPE_COUNT));
- r->Assign(3, new Val(s.mem, TYPE_COUNT));
- r->Assign(4, new Val(s.hits, TYPE_COUNT));
- r->Assign(5, new Val(s.misses, TYPE_COUNT));
- r->Assign(6, new Val(s.avg_nfa_states, TYPE_COUNT));
-
- return r;
- %}
-
-function get_gap_summary%(%): gap_info
- %{
- RecordVal* r = new RecordVal(gap_info);
- r->Assign(0, new Val(tot_ack_events, TYPE_COUNT));
- r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT));
- r->Assign(2, new Val(tot_gap_events, TYPE_COUNT));
- r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT));
-
- return r;
- %}
-
-function val_size%(v: any%): count
- %{
- return new Val(v->MemoryAllocation(), TYPE_COUNT);
- %}
-
-function global_sizes%(%): var_sizes
- %{
- TableVal* sizes = new TableVal(var_sizes);
- PDict(ID)* globals = global_scope()->Vars();
- IterCookie* c = globals->InitForIteration();
-
- ID* id;
- while ( (id = globals->NextEntry(c)) )
- if ( id->HasVal() && ! id->IsInternalGlobal() )
- {
- Val* id_name = new StringVal(id->Name());
- Val* id_size = new Val(id->ID_Val()->MemoryAllocation(),
- TYPE_COUNT);
- sizes->Assign(id_name, id_size);
- Unref(id_name);
- }
-
- return sizes;
- %}
-
-function global_ids%(%): id_table
- %{
- TableVal* ids = new TableVal(id_table);
- PDict(ID)* globals = global_scope()->Vars();
- IterCookie* c = globals->InitForIteration();
-
- ID* id;
- while ( (id = globals->NextEntry(c)) )
- {
- if ( id->IsInternalGlobal() )
- continue;
-
- RecordVal* rec = new RecordVal(script_id);
- rec->Assign(0, new StringVal(type_name(id->Type()->Tag())));
- rec->Assign(1, new Val(id->IsExport(), TYPE_BOOL));
- rec->Assign(2, new Val(id->IsConst(), TYPE_BOOL));
- rec->Assign(3, new Val(id->IsEnumConst(), TYPE_BOOL));
- rec->Assign(4, new Val(id->IsRedefinable(), TYPE_BOOL));
-
- if ( id->HasVal() )
- {
- Val* val = id->ID_Val();
- Ref(val);
- rec->Assign(5, val);
- }
-
- Val* id_name = new StringVal(id->Name());
- ids->Assign(id_name, rec);
- Unref(id_name);
- }
-
- return ids;
- %}
-
-function record_fields%(rec: any%): record_field_table
- %{
- TableVal* fields = new TableVal(record_field_table);
-
- RecordVal* rv = rec->AsRecordVal();
- RecordType* rt = rv->Type()->AsRecordType();
-
- if ( rt->Tag() != TYPE_RECORD )
- {
- reporter->Error("non-record passed to record_fields");
- return fields;
- }
-
- for ( int i = 0; i < rt->NumFields(); ++i )
- {
- BroType* ft = rt->FieldType(i);
- TypeDecl* fd = rt->FieldDecl(i);
- Val* fv = rv->Lookup(i);
-
- if ( fv )
- Ref(fv);
-
- bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0);
-
- RecordVal* nr = new RecordVal(record_field);
- nr->Assign(0, new StringVal(type_name(rt->Tag())));
- nr->Assign(1, new Val(logged, TYPE_BOOL));
- nr->Assign(2, fv);
- nr->Assign(3, rt->FieldDefault(i));
-
- Val* field_name = new StringVal(rt->FieldName(i));
- fields->Assign(field_name, nr);
- Unref(field_name);
- }
-
- return fields;
- %}
-
-%%{
-#include "Anon.h"
-%%}
-
-# Preserve prefix as original one in anonymization.
-function preserve_prefix%(a: addr, width: count%): any
- %{
- AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
- if ( ip_anon )
- {
-#ifdef BROv6
- if ( ! is_v4_addr(a) )
- builtin_error("preserve_prefix() not supported for IPv6 addresses");
- else
- ip_anon->PreservePrefix(a[3], width);
-#else
- ip_anon->PreservePrefix(a, width);
-#endif
- }
-
-
- return 0;
- %}
-
-function preserve_subnet%(a: subnet%): any
- %{
- DEBUG_MSG("%s/%d\n", dotted_addr(a->AsAddr()), a->Width());
- AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
- if ( ip_anon )
- {
-#ifdef BROv6
- if ( ! is_v4_addr(a->AsAddr()) )
- builtin_error("preserve_subnet() not supported for IPv6 addresses");
- else
- ip_anon->PreservePrefix(a->AsAddr()[3], a->Width());
-#else
- ip_anon->PreservePrefix(a->AsAddr(), a->Width());
-#endif
- }
-
- return 0;
- %}
-
-# Anonymize given IP address.
-function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr
- %{
- int anon_class = cl->InternalInt();
- if ( anon_class < 0 || anon_class >= NUM_ADDR_ANONYMIZATION_CLASSES )
- builtin_error("anonymize_addr(): invalid ip addr anonymization class");
-
-#ifdef BROv6
- if ( ! is_v4_addr(a) )
- {
- builtin_error("anonymize_addr() not supported for IPv6 addresses");
- return 0;
- }
- else
- return new AddrVal(anonymize_ip(a[3],
- (enum ip_addr_anonymization_class_t) anon_class));
-#else
- return new AddrVal(anonymize_ip(a,
- (enum ip_addr_anonymization_class_t) anon_class));
-#endif
- %}
-
%%{
static void hash_md5_val(val_list& vlist, unsigned char digest[16])
{
@@ -1760,6 +584,17 @@ static void hmac_md5_val(val_list& vlist, unsigned char digest[16])
}
%%}
+## Computes the MD5 hash value of the provided list of arguments.
+##
+## Returns: The MD5 hash value of the concatenated arguments.
+##
+## .. bro:see:: md5_hmac md5_hash_init md5_hash_update md5_hash_finish
+##
+## .. note::
+##
+## This function performs a one-shot computation of its arguments.
+## For incremental hash computation, see :bro:id:`md5_hash_init` and
+## friends.
function md5_hash%(...%): string
%{
unsigned char digest[16];
@@ -1767,6 +602,13 @@ function md5_hash%(...%): string
return new StringVal(md5_digest_print(digest));
%}
+## Computes an HMAC-MD5 hash value of the provided list of arguments. The HMAC
+## secret key is generated from available entropy when Bro starts up, or it can
+## be specified for repeatability using the ``-K`` command line flag.
+##
+## Returns: The HMAC-MD5 hash value of the concatenated arguments.
+##
+## .. bro:see:: md5_hash md5_hash_init md5_hash_update md5_hash_finish
function md5_hmac%(...%): string
%{
unsigned char digest[16];
@@ -1787,6 +629,20 @@ BroString* convert_index_to_string(Val* index)
}
%%}
+## Initializes MD5 state to enable incremental hash computation. After
+## initializing the MD5 state with this function, you can feed data to
+## :bro:id:`md5_hash_update` and finally need to call :bro:id:`md5_hash_finish`
+## to finish the computation and get the final hash value.
+##
+## For example, when computing incremental MD5 values of transferred files in
+## multiple concurrent HTTP connections, one would call ``md5_hash_init(c$id)``
+## once before invoking ``md5_hash_update(c$id, some_more_data)`` in the
+## :bro:id:`http_entity_data` event handler. When all data has arrived, a call
+## to :bro:id:`md5_hash_finish` returns the final hash value.
+##
+## index: The unique identifier to associate with this hash computation.
+##
+## .. bro:see:: md5_hash md5_hmac md5_hash_update md5_hash_finish
function md5_hash_init%(index: any%): bool
%{
BroString* s = convert_index_to_string(index);
@@ -1804,6 +660,15 @@ function md5_hash_init%(index: any%): bool
return new Val(status, TYPE_BOOL);
%}
+## Update the MD5 value associated with a given index. It is required to
+## call :bro:id:`md5_hash_init` once before calling this
+## function.
+##
+## index: The unique identifier to associate with this hash computation.
+##
+## data: The data to add to the hash computation.
+##
+## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_finish
function md5_hash_update%(index: any, data: string%): bool
%{
BroString* s = convert_index_to_string(index);
@@ -1819,6 +684,13 @@ function md5_hash_update%(index: any, data: string%): bool
return new Val(status, TYPE_BOOL);
%}
+## Returns the final MD5 digest of an incremental hash computation.
+##
+## index: The unique identifier of this hash computation.
+##
+## Returns: The hash value associated with the computation at *index*.
+##
+## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_update
function md5_hash_finish%(index: any%): string
%{
BroString* s = convert_index_to_string(index);
@@ -1838,7 +710,18 @@ function md5_hash_finish%(index: any%): string
return printable_digest;
%}
-# Wrappings for rand() and srand()
+## Generates a random number.
+##
+## max: The maximum value the random number.
+##
+## Returns: a random positive integer in the interval *[0, max)*.
+##
+## .. bro:see:: srand
+##
+## .. note::
+##
+## This function is a wrapper about the function ``rand`` provided by
+## the OS.
function rand%(max: count%): count
%{
int result;
@@ -1846,565 +729,333 @@ function rand%(max: count%): count
return new Val(result, TYPE_COUNT);
%}
+## Sets the seed for subsequent :bro:id:`rand` calls.
+##
+## seed: The seed for the PRNG.
+##
+## .. bro:see:: rand
+##
+## .. note::
+##
+## This function is a wrapper about the function ``srand`` provided
+## by the OS.
function srand%(seed: count%): any
%{
srand(seed);
return 0;
%}
-function decode_base64%(s: string%): string
- %{
- BroString* t = decode_base64(s->AsString());
- if ( t )
- return new StringVal(t);
- else
- {
- reporter->Error("error in decoding string %s", s->CheckString());
- return new StringVal("");
- }
- %}
+%%{
+#include
+%%}
-function decode_base64_custom%(s: string, a: string%): string
+## Send a string to syslog.
+##
+## s: The string to log via syslog
+function syslog%(s: string%): any
%{
- BroString* t = decode_base64(s->AsString(), a->AsString());
- if ( t )
- return new StringVal(t);
- else
- {
- reporter->Error("error in decoding string %s", s->CheckString());
- return new StringVal("");
- }
+ reporter->Syslog("%s", s->CheckString());
+ return 0;
%}
%%{
-#include "DCE_RPC.h"
-
-typedef struct {
- uint32 time_low;
- uint16 time_mid;
- uint16 time_hi_and_version;
- uint8 clock_seq_hi_and_reserved;
- uint8 clock_seq_low;
- uint8 node[6];
-} bro_uuid_t;
+extern "C" {
+#include
+}
%%}
-function uuid_to_string%(uuid: string%): string
+## Determines the MIME type of a piece of data using ``libmagic``.
+##
+## data: The data to find the MIME type for.
+##
+## return_mime: If true, the function returns a short MIME type string (e.g.,
+## ``text/plain`` instead of a more elaborate textual description.
+##
+## Returns: The MIME type of *data*.
+function identify_data%(data: string, return_mime: bool%): string
%{
- if ( uuid->Len() != 16 )
- return new StringVal("");
+ const char* descr = "";
- bro_uuid_t* id = (bro_uuid_t*) uuid->Bytes();
+ static magic_t magic_mime = 0;
+ static magic_t magic_descr = 0;
- static char s[1024];
- char* sp = s;
+ magic_t* magic = return_mime ? &magic_mime : &magic_descr;
- sp += snprintf(sp, s + sizeof(s) - sp,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- id->time_low, id->time_mid, id->time_hi_and_version,
- id->clock_seq_hi_and_reserved, id->clock_seq_low,
- id->node[0],
- id->node[1],
- id->node[2],
- id->node[3],
- id->node[4],
- id->node[5]);
-
- return new StringVal(s);
- %}
-
-
-# The following functions convert strings into patterns at run-time. As the
-# computed NFAs and DFAs cannot be cleanly deallocated (at least for now),
-# they can only be used at initialization time.
-
-function merge_pattern%(p1: pattern, p2: pattern%): pattern
- %{
- if ( bro_start_network_time != 0.0 )
+ if( ! *magic )
{
- builtin_error("merge_pattern can only be called at init time");
- return 0;
+ *magic = magic_open(return_mime ? MAGIC_MIME : MAGIC_NONE);
+
+ if ( ! *magic )
+ {
+ reporter->Error("can't init libmagic: %s", magic_error(*magic));
+ return new StringVal("");
+ }
+
+ if ( magic_load(*magic, 0) < 0 )
+ {
+ reporter->Error("can't load magic file: %s", magic_error(*magic));
+ magic_close(*magic);
+ *magic = 0;
+ return new StringVal("");
+ }
}
- RE_Matcher* re = new RE_Matcher();
- re->AddPat(p1->PatternText());
- re->AddPat(p2->PatternText());
- re->Compile();
- return new PatternVal(re);
+ descr = magic_buffer(*magic, data->Bytes(), data->Len());
+
+ return new StringVal(descr);
%}
%%{
-char* to_pat_str(int sn, const char* ss)
- {
- const char special_re_char[] = "^$-:\"\\/|*+?.(){}[]";
-
- char* pat = new char[sn * 4 + 1];
- int pat_len = 0;
-
- for ( int i = 0; i < sn; ++i )
- {
- if ( ! strchr(special_re_char, ss[i]) )
- pat[pat_len++] = ss[i];
- else
- {
- pat[pat_len++] = '\\';
- pat[pat_len++] = ss[i];
- }
- }
- pat[pat_len] = '\0';
- return pat;
- }
+#include
+static map entropy_states;
%%}
-function convert_for_pattern%(s: string%): string
+## Performs an entropy test on the given data.
+## See http://www.fourmilab.ch/random.
+##
+## data: The data to compute the entropy for.
+##
+## Returns: The result of the entropy test, which contains the following
+## fields.
+##
+## - ``entropy``: The information density expressed as a number of
+## bits per character.
+##
+## - ``chi_square``: The chi-square test value expressed as an
+## absolute number and a percentage which indicates how
+## frequently a truly random sequence would exceed the value
+## calculated, i.e., the degree to which the sequence tested is
+## suspected of being non-random.
+##
+## If the percentage is greater than 99% or less than 1%, the
+## sequence is almost certainly not random. If the percentage is
+## between 99% and 95% or between 1% and 5%, the sequence is
+## suspect. Percentages between 90\% and 95\% and 5\% and 10\%
+## indicate the sequence is "almost suspect."
+##
+## - ``mean``: The arithmetic mean of all the bytes. If the data
+## are close to random, it should be around 127.5.
+##
+## - ``monte_carlo_pi``: Each successive sequence of six bytes is
+## used as 24-bit *x* and *y* coordinates within a square. If
+## the distance of the randomly-generated point is less than the
+## radius of a circle inscribed within the square, the six-byte
+## sequence is considered a "hit." The percentage of hits can
+## be used to calculate the value of pi. For very large streams
+## the value will approach the correct value of pi if the
+## sequence is close to random.
+##
+## - ``serial_correlation``: This quantity measures the extent to
+## which each byte in the file depends upon the previous byte.
+## For random sequences this value will be close to zero.
+##
+## .. bro:see:: entropy_test_init entropy_test_add entropy_test_finish
+function find_entropy%(data: string%): entropy_test_result
%{
- char* t = to_pat_str(s->Len(), (const char*)(s->Bytes()));
- StringVal* ret = new StringVal(t);
- delete [] t;
- return ret;
+ double montepi, scc, ent, mean, chisq;
+ montepi = scc = ent = mean = chisq = 0.0;
+ RecordVal* ent_result = new RecordVal(entropy_test_result);
+ RandTest *rt = new RandTest();
+
+ rt->add((char*) data->Bytes(), data->Len());
+ rt->end(&ent, &chisq, &mean, &montepi, &scc);
+ delete rt;
+
+ ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
+ ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
+ ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
+ ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE));
+ ent_result->Assign(4, new Val(scc, TYPE_DOUBLE));
+ return ent_result;
%}
-function string_to_pattern%(s: string, convert: bool%): pattern
+## Initializes data structures for incremental entropy calculation.
+##
+## index: An arbitrary unique value per distinct computation.
+##
+## Returns: True on success.
+##
+## .. bro:see:: find_entropy entropy_test_add entropy_test_finish
+function entropy_test_init%(index: any%): bool
%{
- if ( bro_start_network_time != 0.0 )
+ BroString* s = convert_index_to_string(index);
+ int status = 0;
+
+ if ( entropy_states.count(*s) < 1 )
{
- builtin_error("string_to_pattern can only be called at init time");
- return 0;
+ entropy_states[*s] = new RandTest();
+ status = 1;
}
- const char* ss = (const char*) (s->Bytes());
- int sn = s->Len();
- char* pat;
+ delete s;
+ return new Val(status, TYPE_BOOL);
+ %}
+
+## Adds data to an incremental entropy calculation. Before using this function,
+## one needs to invoke :bro:id:`entropy_test_init`.
+##
+## data: The data to add to the entropy calculation.
+##
+## index: An arbitrary unique value that identifies a particular entropy
+## computation.
+##
+## Returns: True on success.
+##
+## .. bro:see:: find_entropy entropy_test_add entropy_test_finish
+function entropy_test_add%(index: any, data: string%): bool
+ %{
+ BroString* s = convert_index_to_string(index);
+ int status = 0;
+
+ if ( entropy_states.count(*s) > 0 )
+ {
+ entropy_states[*s]->add((char*) data->Bytes(), data->Len());
+ status = 1;
+ }
+
+ delete s;
+ return new Val(status, TYPE_BOOL);
+ %}
+
+## Finishes an incremental entropy calculation. Before using this function,
+## one needs to initialize the computation with :bro:id:`entropy_test_init` and
+## add data to it via :bro:id:`entropy_test_add`.
+##
+## index: An arbitrary unique value that identifies a particular entropy
+## computation.
+##
+## Returns: The result of the entropy test. See :bro:id:`find_entropy` for a
+## description of the individual components.
+##
+## .. bro:see:: find_entropy entropy_test_init entropy_test_add
+function entropy_test_finish%(index: any%): entropy_test_result
+ %{
+ BroString* s = convert_index_to_string(index);
+ double montepi, scc, ent, mean, chisq;
+ montepi = scc = ent = mean = chisq = 0.0;
+ RecordVal* ent_result = new RecordVal(entropy_test_result);
+
+ if ( entropy_states.count(*s) > 0 )
+ {
+ RandTest *rt = entropy_states[*s];
+ rt->end(&ent, &chisq, &mean, &montepi, &scc);
+ entropy_states.erase(*s);
+ delete rt;
+ }
+
+ ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
+ ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
+ ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
+ ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE));
+ ent_result->Assign(4, new Val(scc, TYPE_DOUBLE));
+
+ delete s;
+ return ent_result;
+ %}
+
+## Creates an identifier that is unique with high probability.
+##
+## prefix: A custom string prepended to the result.
+##
+## .. bro:see:: unique_id_from
+function unique_id%(prefix: string%) : string
+ %{
+ char tmp[20];
+ uint64 uid = calculate_unique_id(UID_POOL_DEFAULT_SCRIPT);
+ return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
+ %}
+
+## Creates an identifier that is unique with high probability.
+##
+## pool: A seed for determinism.
+##
+## prefix: A custom string prepended to the result.
+##
+## .. bro:see:: unique_id
+function unique_id_from%(pool: int, prefix: string%) : string
+ %{
+ pool += UID_POOL_CUSTOM_SCRIPT; // Make sure we don't conflict with internal pool.
+
+ char tmp[20];
+ uint64 uid = calculate_unique_id(pool);
+ return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
+ %}
+
+# ===========================================================================
+#
+# Generic Programming
+#
+# ===========================================================================
+
+## Removes all elements from a set or table.
+##
+## v: The set or table
+##
+## Returns: The cleared set/table or 0 if *v* is not a set/table type.
+function clear_table%(v: any%): any
+ %{
+ if ( v->Type()->Tag() == TYPE_TABLE )
+ v->AsTableVal()->RemoveAll();
+ else
+ builtin_error("clear_table() requires a table/set argument");
+
+ return 0;
+ %}
+
+## Returns the number of elements in a container. This function works with all
+## container types, i.e., sets, tables, and vectors.
+##
+## v: The container whose elements are counted.
+##
+## Returns: The number of elements in *v*.
+function length%(v: any%): count
+ %{
+ TableVal* tv = v->Type()->Tag() == TYPE_TABLE ? v->AsTableVal() : 0;
+
+ if ( tv )
+ return new Val(tv->Size(), TYPE_COUNT);
+
+ else if ( v->Type()->Tag() == TYPE_VECTOR )
+ return new Val(v->AsVectorVal()->Size(), TYPE_COUNT);
- if ( convert )
- pat = to_pat_str(sn, ss);
else
{
- pat = new char[sn+1];
- memcpy(pat, ss, sn);
- pat[sn] = '\0';
+ builtin_error("length() requires a table/set/vector argument");
+ return new Val(0, TYPE_COUNT);
}
-
- RE_Matcher* re = new RE_Matcher(pat);
- delete [] pat;
- re->Compile();
- return new PatternVal(re);
%}
-# Precompile a pcap filter.
-function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool
+## Checks whether two objects reference the same internal object. This function
+## uses equality comparison of C++ raw pointer values to determine if the two
+## objects are the same.
+##
+## o1: The first object.
+##
+## o2: The second object.
+##
+## Returns: True if *o1* and *o2* are equal.
+function same_object%(o1: any, o2: any%): bool
%{
- bool success = true;
-
- loop_over_list(pkt_srcs, i)
- {
- pkt_srcs[i]->ClearErrorMsg();
-
- if ( ! pkt_srcs[i]->PrecompileFilter(id->ForceAsInt(),
- s->CheckString()) )
- {
- reporter->Error("precompile_pcap_filter: %s",
- pkt_srcs[i]->ErrorMsg());
- success = false;
- }
- }
-
- return new Val(success, TYPE_BOOL);
+ return new Val(o1 == o2, TYPE_BOOL);
%}
-# Install precompiled pcap filter.
-function install_pcap_filter%(id: PcapFilterID%): bool
+## Returns the number bytes that a value occupies in memory.
+##
+## v: The value
+##
+## Returns: The number of bytes that *v* occupies.
+function val_size%(v: any%): count
%{
- bool success = true;
-
- loop_over_list(pkt_srcs, i)
- {
- pkt_srcs[i]->ClearErrorMsg();
-
- if ( ! pkt_srcs[i]->SetFilter(id->ForceAsInt()) )
- success = false;
- }
-
- return new Val(success, TYPE_BOOL);
+ return new Val(v->MemoryAllocation(), TYPE_COUNT);
%}
-# If last pcap function failed, returns a descriptive error message
-function pcap_error%(%): string
- %{
- loop_over_list(pkt_srcs, i)
- {
- const char* err = pkt_srcs[i]->ErrorMsg();
- if ( *err )
- return new StringVal(err);
- }
-
- return new StringVal("no error");
- %}
-
-# Install filter to drop packets from a source (addr/subnet) with a given
-# probability (0.0-1.0) if none of the given TCP flags is set.
-function install_src_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
- %{
- sessions->GetPacketFilter()->AddSrc(ip, tcp_flags, prob);
- return new Val(1, TYPE_BOOL);
- %}
-
-function install_src_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool
- %{
- sessions->GetPacketFilter()->AddSrc(snet, tcp_flags, prob);
- return new Val(1, TYPE_BOOL);
- %}
-
-# Remove the filter for the source.
-function uninstall_src_addr_filter%(ip: addr%) : bool
- %{
- return new Val(sessions->GetPacketFilter()->RemoveSrc(ip), TYPE_BOOL);
- %}
-
-function uninstall_src_net_filter%(snet: subnet%) : bool
- %{
- return new Val(sessions->GetPacketFilter()->RemoveSrc(snet), TYPE_BOOL);
- %}
-
-# Same for destination.
-function install_dst_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
- %{
- sessions->GetPacketFilter()->AddDst(ip, tcp_flags, prob);
- return new Val(1, TYPE_BOOL);
- %}
-
-function install_dst_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool
- %{
- sessions->GetPacketFilter()->AddDst(snet, tcp_flags, prob);
- return new Val(1, TYPE_BOOL);
- %}
-
-function uninstall_dst_addr_filter%(ip: addr%) : bool
- %{
- return new Val(sessions->GetPacketFilter()->RemoveDst(ip), TYPE_BOOL);
- %}
-
-function uninstall_dst_net_filter%(snet: subnet%) : bool
- %{
- return new Val(sessions->GetPacketFilter()->RemoveDst(snet), TYPE_BOOL);
- %}
-
-function checkpoint_state%(%) : bool
- %{
- return new Val(persistence_serializer->WriteState(true), TYPE_BOOL);
- %}
-
-function dump_config%(%) : bool
- %{
- return new Val(persistence_serializer->WriteConfig(true), TYPE_BOOL);
- %}
-
-function rescan_state%(%) : bool
- %{
- return new Val(persistence_serializer->ReadAll(false, true), TYPE_BOOL);
- %}
-
-function capture_events%(filename: string%) : bool
- %{
- if ( ! event_serializer )
- event_serializer = new FileSerializer();
- else
- event_serializer->Close();
-
- return new Val(event_serializer->Open(
- (const char*) filename->CheckString()), TYPE_BOOL);
- %}
-
-function capture_state_updates%(filename: string%) : bool
- %{
- if ( ! state_serializer )
- state_serializer = new FileSerializer();
- else
- state_serializer->Close();
-
- return new Val(state_serializer->Open(
- (const char*) filename->CheckString()), TYPE_BOOL);
- %}
-
-function connect%(ip: addr, p: port, our_class: string, retry: interval, ssl: bool%) : count
- %{
- return new Val(uint32(remote_serializer->Connect(ip, p->Port(),
- our_class->CheckString(), retry, ssl)),
- TYPE_COUNT);
- %}
-
-function disconnect%(p: event_peer%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->CloseConnection(id), TYPE_BOOL);
- %}
-
-function request_remote_events%(p: event_peer, handlers: pattern%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->RequestEvents(id, handlers),
- TYPE_BOOL);
- %}
-
-function request_remote_sync%(p: event_peer, auth: bool%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->RequestSync(id, auth), TYPE_BOOL);
- %}
-
-function request_remote_logs%(p: event_peer%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->RequestLogs(id), TYPE_BOOL);
- %}
-
-function set_accept_state%(p: event_peer, accept: bool%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->SetAcceptState(id, accept),
- TYPE_BOOL);
- %}
-
-function set_compression_level%(p: event_peer, level: count%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->SetCompressionLevel(id, level),
- TYPE_BOOL);
- %}
-
-function listen%(ip: addr, p: port, ssl: bool %) : bool
- %{
- return new Val(remote_serializer->Listen(ip, p->Port(), ssl), TYPE_BOOL);
- %}
-
-function is_remote_event%(%) : bool
- %{
- return new Val(mgr.CurrentSource() != SOURCE_LOCAL, TYPE_BOOL);
- %}
-
-function send_state%(p: event_peer%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(persistence_serializer->SendState(id, true), TYPE_BOOL);
- %}
-
-# Send the value of the given global ID to the peer (which might
-# then install it locally).
-function send_id%(p: event_peer, id: string%) : bool
- %{
- RemoteSerializer::PeerID pid = p->AsRecordVal()->Lookup(0)->AsCount();
-
- ID* i = global_scope()->Lookup(id->CheckString());
- if ( ! i )
- {
- reporter->Error("send_id: no global id %s", id->CheckString());
- return new Val(0, TYPE_BOOL);
- }
-
- SerialInfo info(remote_serializer);
- return new Val(remote_serializer->SendID(&info, pid, *i), TYPE_BOOL);
- %}
-
-# Gracely shut down communication.
-function terminate_communication%(%) : bool
- %{
- return new Val(remote_serializer->Terminate(), TYPE_BOOL);
- %}
-
-function complete_handshake%(p: event_peer%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->CompleteHandshake(id), TYPE_BOOL);
- %}
-
-function send_ping%(p: event_peer, seq: count%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->SendPing(id, seq), TYPE_BOOL);
- %}
-
-function send_current_packet%(p: event_peer%) : bool
- %{
- Packet pkt("");
-
- if ( ! current_pktsrc ||
- ! current_pktsrc->GetCurrentPacket(&pkt.hdr, &pkt.pkt) )
- return new Val(0, TYPE_BOOL);
-
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
-
- pkt.time = pkt.hdr->ts.tv_sec + double(pkt.hdr->ts.tv_usec) / 1e6;
- pkt.hdr_size = current_pktsrc->HdrSize();
- pkt.link_type = current_pktsrc->LinkType();
-
- SerialInfo info(remote_serializer);
- return new Val(remote_serializer->SendPacket(&info, id, pkt), TYPE_BOOL);
- %}
-
-function do_profiling%(%) : bool
- %{
- if ( profiling_logger )
- profiling_logger->Log();
-
- return new Val(1, TYPE_BOOL);
- %}
-
-function get_event_peer%(%) : event_peer
- %{
- SourceID src = mgr.CurrentSource();
-
- if ( src == SOURCE_LOCAL )
- {
- RecordVal* p = mgr.GetLocalPeerVal();
- Ref(p);
- return p;
- }
-
- if ( ! remote_serializer )
- reporter->InternalError("remote_serializer not initialized");
-
- Val* v = remote_serializer->GetPeerVal(src);
- if ( ! v )
- {
- reporter->Error("peer %d does not exist anymore", int(src));
- RecordVal* p = mgr.GetLocalPeerVal();
- Ref(p);
- return p;
- }
-
- return v;
- %}
-
-function get_local_event_peer%(%) : event_peer
- %{
- RecordVal* p = mgr.GetLocalPeerVal();
- Ref(p);
- return p;
- %}
-
-
-function send_capture_filter%(p: event_peer, s: string%) : bool
- %{
- RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
- return new Val(remote_serializer->SendCaptureFilter(id, s->CheckString()), TYPE_BOOL);
- %}
-
-function make_connection_persistent%(c: connection%) : bool
- %{
- c->MakePersistent();
- return new Val(1, TYPE_BOOL);
- %}
-
-function is_local_interface%(ip: addr%) : bool
- %{
- static uint32* addrs;
- static int len = -1;
-
- if ( len < 0 )
- {
- char host[MAXHOSTNAMELEN];
-
- strcpy(host, "localhost");
- gethostname(host, MAXHOSTNAMELEN);
- host[MAXHOSTNAMELEN-1] = '\0';
-
- struct hostent* ent = gethostbyname(host);
-
- for ( len = 0; ent->h_addr_list[len]; ++len )
- ;
-
- addrs = new uint32[len + 1];
- for ( int i = 0; i < len; i++ )
- addrs[i] = *(uint32*) ent->h_addr_list[i];
-
- addrs[len++] = 0x0100007f; // 127.0.0.1
- }
-
-#ifdef BROv6
- if ( ! is_v4_addr(ip) )
- {
- builtin_error("is_local_interface() only supports IPv4 addresses");
- return new Val(0, TYPE_BOOL);
- }
-
- uint32 ip4 = to_v4_addr(ip);
-#else
- uint32 ip4 = ip;
-#endif
-
- for ( int i = 0; i < len; i++ )
- if ( addrs[i] == ip4 )
- return new Val(1, TYPE_BOOL);
-
- return new Val(0, TYPE_BOOL);
- %}
-
-function dump_current_packet%(file_name: string%) : bool
- %{
- const struct pcap_pkthdr* hdr;
- const u_char* pkt;
-
- if ( ! current_pktsrc ||
- ! current_pktsrc->GetCurrentPacket(&hdr, &pkt) )
- return new Val(0, TYPE_BOOL);
-
- if ( ! addl_pkt_dumper )
- addl_pkt_dumper = new PktDumper(0, true);
-
- addl_pkt_dumper->Open(file_name->CheckString());
- addl_pkt_dumper->Dump(hdr, pkt);
-
- return new Val(! addl_pkt_dumper->IsError(), TYPE_BOOL);
- %}
-
-function get_current_packet%(%) : pcap_packet
- %{
- const struct pcap_pkthdr* hdr;
- const u_char* data;
- RecordVal* pkt = new RecordVal(pcap_packet);
-
- if ( ! current_pktsrc ||
- ! current_pktsrc->GetCurrentPacket(&hdr, &data) )
- {
- pkt->Assign(0, new Val(0, TYPE_COUNT));
- pkt->Assign(1, new Val(0, TYPE_COUNT));
- pkt->Assign(2, new Val(0, TYPE_COUNT));
- pkt->Assign(3, new Val(0, TYPE_COUNT));
- pkt->Assign(4, new StringVal(""));
- return pkt;
- }
-
- pkt->Assign(0, new Val(uint32(hdr->ts.tv_sec), TYPE_COUNT));
- pkt->Assign(1, new Val(uint32(hdr->ts.tv_usec), TYPE_COUNT));
- pkt->Assign(2, new Val(hdr->caplen, TYPE_COUNT));
- pkt->Assign(3, new Val(hdr->len, TYPE_COUNT));
- pkt->Assign(4, new StringVal(hdr->caplen, (const char*) data));
-
- return pkt;
- %}
-
-function dump_packet%(pkt: pcap_packet, file_name: string%) : bool
- %{
- struct pcap_pkthdr hdr;
- const val_list* pkt_vl = pkt->AsRecord();
-
- hdr.ts.tv_sec = (*pkt_vl)[0]->AsCount();
- hdr.ts.tv_usec = (*pkt_vl)[1]->AsCount();
- hdr.caplen = (*pkt_vl)[2]->AsCount();
- hdr.len = (*pkt_vl)[3]->AsCount();
-
- if ( ! addl_pkt_dumper )
- addl_pkt_dumper = new PktDumper(0, true);
-
- addl_pkt_dumper->Open(file_name->CheckString());
- addl_pkt_dumper->Dump(&hdr, (*pkt_vl)[4]->AsString()->Bytes());
-
- return new Val(addl_pkt_dumper->IsError(), TYPE_BOOL);
- %}
-
-# The return value is the old size of the vector.
-# ### Need better type checking on the argument here and in subsequent
-# vector builtins -- probably need to update "bif" code generator.
+## Resizes a vector.
+##
+## aggr: The vector instance.
+##
+## newsize: The new size of *aggr*.
+##
+## Returns: The old size of *aggr* and 0 if *aggr* is not a :bro:type:`vector`.
function resize%(aggr: any, newsize: count%) : count
%{
if ( aggr->Type()->Tag() != TYPE_VECTOR )
@@ -2416,7 +1067,14 @@ function resize%(aggr: any, newsize: count%) : count
return new Val(aggr->AsVectorVal()->Resize(newsize), TYPE_COUNT);
%}
-# Returns true if any element is T.
+## Tests whether a boolean vector (``vector of bool``) has *any* true
+## element.
+##
+## v: The boolean vector instance.
+##
+## Returns: True if any element in *v* is true.
+##
+## .. bro:see:: all_set
function any_set%(v: any%) : bool
%{
if ( v->Type()->Tag() != TYPE_VECTOR ||
@@ -2434,7 +1092,18 @@ function any_set%(v: any%) : bool
return new Val(false, TYPE_BOOL);
%}
-# Returns true if all elements are T (missing counts as F).
+## Tests whether *all* elements of a boolean vector (``vector of bool``) are
+## true.
+##
+## v: The boolean vector instance.
+##
+## Returns: True iff all elements in *v* are true.
+##
+## .. bro:see:: any_set
+##
+## .. note::
+##
+## Missing elements count as false.
function all_set%(v: any%) : bool
%{
if ( v->Type()->Tag() != TYPE_VECTOR ||
@@ -2452,9 +1121,6 @@ function all_set%(v: any%) : bool
return new Val(true, TYPE_BOOL);
%}
-# sort() takes a vector and comparison function on the elements and
-# sorts the vector in place. It returns the original vector.
-
%%{
static Func* sort_function_comp = 0;
static Val** index_map = 0; // used for indirect sorting to support order()
@@ -2505,6 +1171,16 @@ bool indirect_int_sort_function(int a, int b)
}
%%}
+## Sorts a vector in place. The second argument is a comparison function that
+## takes two arguments: if the vector type is \verb|vector of T|, then the
+## comparison function must be ``function(a: T, b: T): bool``, which returns
+## ``a < b`` for some type-specific notion of the less-than operator.
+##
+## v: The vector instance to sort.
+##
+## Returns: The original vector.
+##
+## .. bro:see:: order
function sort%(v: any, ...%) : any
%{
v->Ref(); // we always return v
@@ -2558,6 +1234,15 @@ function sort%(v: any, ...%) : any
return v;
%}
+## Returns the order of the elements in a vector according to some
+## comparison function. See :bro:id:`sort` for details about the comparison
+## function.
+##
+## v: The vector whose order to compute.
+##
+## Returns: A ``vector of count`` with the indices of the ordered elements.
+##
+## .. bro:see:: sort
function order%(v: any, ...%) : index_vec
%{
VectorVal* result_v =
@@ -2635,65 +1320,699 @@ function order%(v: any, ...%) : index_vec
return result_v;
%}
-%%{
-// Experimental code to add support for IDMEF XML output based on
-// notices. For now, we're implementing it as a builtin you can call on an
-// notices record.
+# ===========================================================================
+#
+# String Processing
+#
+# ===========================================================================
-#ifdef USE_IDMEF
-extern "C" {
-#include
-}
-#endif
-
-#include
-
-char* port_to_string(PortVal* port)
- {
- char buf[256]; // to hold sprintf results on port numbers
- snprintf(buf, sizeof(buf), "%u", port->Port());
- return copy_string(buf);
- }
-
-%%}
-
-function generate_idmef%(src_ip: addr, src_port: port,
- dst_ip: addr, dst_port: port%) : bool
+## Returns the concatenation of the string representation of its arguments. The
+## arguments can be of any type. For example, ``cat("foo", 3, T)`` returns
+## ``"foo3T"``.
+##
+## Returns: A string concatentation of all arguments.
+function cat%(...%): string
%{
-#ifdef USE_IDMEF
- xmlNodePtr message =
- newIDMEF_Message(newAttribute("version","1.0"),
- newAlert(newCreateTime(NULL),
- newSource(
- newNode(newAddress(
- newAttribute("category","ipv4-addr"),
- newSimpleElement("address",
- copy_string(dotted_addr(src_ip))),
- NULL), NULL),
- newService(
- newSimpleElement("port",
- port_to_string(src_port)),
- NULL), NULL),
- newTarget(
- newNode(newAddress(
- newAttribute("category","ipv4-addr"),
- newSimpleElement("address",
- copy_string(dotted_addr(dst_ip))),
- NULL), NULL),
- newService(
- newSimpleElement("port",
- port_to_string(dst_port)),
- NULL), NULL), NULL), NULL);
+ ODesc d;
+ loop_over_list(@ARG@, i)
+ @ARG@[i]->Describe(&d);
- // if ( validateCurrentDoc() )
- printCurrentMessage(stderr);
- return new Val(1, TYPE_BOOL);
-#else
- builtin_error("Bro was not configured for IDMEF support");
- return new Val(0, TYPE_BOOL);
-#endif
+ BroString* s = new BroString(1, d.TakeBytes(), d.Len());
+ s->SetUseFreeToDelete(true);
+
+ return new StringVal(s);
%}
+## Concatenates all arguments, with a separator placed between each one. This
+## function is similar to :bro:id:`cat`, but places a separator between each
+## given argument. If any of the variable arguments is an empty string it is
+## replaced by a given default string instead.
+##
+## sep: The separator to place betwen each argument.
+##
+## def: The default string to use when an argument is the empty string.
+##
+## Returns: A concatenation of all arguments with *sep* between each one and
+## empty strings replaced with *def*.
+##
+## .. bro:see:: cat string_cat cat_string_array cat_string_array_n
+function cat_sep%(sep: string, def: string, ...%): string
+ %{
+ ODesc d;
+ int pre_size = 0;
+
+ loop_over_list(@ARG@, i)
+ {
+ // Skip named parameters.
+ if ( i < 2 )
+ continue;
+
+ if ( i > 2 )
+ d.Add(sep->CheckString(), 0);
+
+ Val* v = @ARG@[i];
+ if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() )
+ v = def;
+
+ v->Describe(&d);
+ }
+
+ BroString* s = new BroString(1, d.TakeBytes(), d.Len());
+ s->SetUseFreeToDelete(true);
+
+ return new StringVal(s);
+ %}
+
+## Produces a formatted string à la ``printf``. The first argument is the
+## *format string* and specifies how subsequent arguments are converted for
+## output. It is composed of zero or more directives: ordinary characters (not
+## ``%``), which are copied unchanged to the output, and conversion
+## specifications, each of which fetches zero or more subsequent arguments.
+## Conversion specifications begin with ``%`` and the arguments must properly
+## correspond to the specifier. After the ``%``, the following characters
+## may appear in sequence:
+##
+## - ``%``: Literal ``%``
+##
+## - ``-``: Left-align field
+##
+## - ``[0-9]+``: The field width (< 128)
+##
+## - ``.``: Precision of floating point specifiers ``[efg]`` (< 128)
+##
+## - ``A``: Escape NUL bytes, i.e., replace ``0`` with ``\0``
+##
+## - ``[DTdxsefg]``: Format specifier
+##
+## - ``[DT]``: ISO timestamp with microsecond precision
+##
+## - ``d``: Signed/Unsigned integer (using C-style ``%lld|``/``%llu``
+## for ``int``/``count``)
+##
+## - ``x``: Unsigned hexadecimal (using C-style ``%llx``);
+## addresses/ports are converted to host-byte order
+##
+## - ``s``: Escaped string
+##
+## - ``[efg]``: Double
+##
+## Returns: Given no arguments, :bro:id:`fmt` returns an empty string. Given a
+## non-string first argument, :bro:id:`fmt` returns the concatenation
+## of all its arguments, per :bro:id:`cat`. Finally, given the wrong
+## number of additional arguments for the given format specifier,
+## :bro:id:`fmt` generates a run-time error.
+##
+## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n
+function fmt%(...%): string
+ %{
+ if ( @ARGC@ == 0 )
+ return new StringVal("");
+
+ Val* fmt_v = @ARG@[0];
+ if ( fmt_v->Type()->Tag() != TYPE_STRING )
+ return bro_cat(frame, @ARGS@);
+
+ const char* fmt = fmt_v->AsString()->CheckString();
+ ODesc d;
+ int n = 0;
+
+ while ( next_fmt(fmt, @ARGS@, &d, n) )
+ ;
+
+ if ( n < @ARGC@ - 1 )
+ builtin_error("too many arguments for format", fmt_v);
+
+ else if ( n >= @ARGC@ )
+ builtin_error("too few arguments for format", fmt_v);
+
+ BroString* s = new BroString(1, d.TakeBytes(), d.Len());
+ s->SetUseFreeToDelete(true);
+
+ return new StringVal(s);
+ %}
+
+# ===========================================================================
+#
+# Math
+#
+# ===========================================================================
+
+## Chops off any decimal digits of the given double, i.e., computes the
+## "floor" of it. For example, ``floor(3.14)`` returns ``3.0``.
+##
+## d: The :bro:type:`double` to manipulate.
+##
+## Returns: The next lowest integer of *d* as :bro:type:`double`.
+##
+## .. bro:see:: sqrt exp ln log10
+function floor%(d: double%): double
+ %{
+ return new Val(floor(d), TYPE_DOUBLE);
+ %}
+
+## Computes the square root of a :bro:type:`double`.
+##
+## x: The number to compute the square root of.
+##
+## Returns: The square root of *x*.
+##
+## .. bro:see:: floor exp ln log10
+function sqrt%(x: double%): double
+ %{
+ if ( x < 0 )
+ {
+ reporter->Error("negative sqrt argument");
+ return new Val(-1.0, TYPE_DOUBLE);
+ }
+
+ return new Val(sqrt(x), TYPE_DOUBLE);
+ %}
+
+## Computes the exponential function.
+##
+## d: The argument to the exponential function.
+##
+## Returns: *e* to the power of *d*.
+##
+## .. bro:see:: floor sqrt ln log10
+function exp%(d: double%): double
+ %{
+ return new Val(exp(d), TYPE_DOUBLE);
+ %}
+
+## Computes the natural logarithm of a number.
+##
+## d: The argument to the logarithm.
+##
+## Returns: The natural logarithm of *d*.
+##
+## .. bro:see:: exp floor sqrt log10
+function ln%(d: double%): double
+ %{
+ return new Val(log(d), TYPE_DOUBLE);
+ %}
+
+## Computes the common logarithm of a number.
+##
+## d: The argument to the logarithm.
+##
+## Returns: The common logarithm of *d*.
+##
+## .. bro:see:: exp floor sqrt ln
+function log10%(d: double%): double
+ %{
+ return new Val(log10(d), TYPE_DOUBLE);
+ %}
+
+# ===========================================================================
+#
+# Introspection
+#
+# ===========================================================================
+
+## Determines whether *c* has been received externally. For example,
+## Broccoli or the Time Machine can send packets to Bro via a mechanism that
+## one step lower than sending events. This function checks whether the packets
+## of a connection stem from one of these external *packet sources*.
+##
+## c: The connection to test.
+##
+## Returns: True if *c* has been received externally.
+function is_external_connection%(c: connection%) : bool
+ %{
+ return new Val(c && c->IsExternal(), TYPE_BOOL);
+ %}
+
+## Returns the ID of the analyzer which raised the current event.
+##
+## Returns: The ID of the analyzer which raised hte current event, or 0 if
+## none.
+function current_analyzer%(%) : count
+ %{
+ return new Val(mgr.CurrentAnalyzer(), TYPE_COUNT);
+ %}
+
+## Returns Bro's process ID.
+##
+## Returns: Bro's process ID.
+function getpid%(%) : count
+ %{
+ return new Val(getpid(), TYPE_COUNT);
+ %}
+
+%%{
+extern const char* bro_version();
+%%}
+
+## Returns the Bro version string.
+##
+## Returns: Bro's version, e.g., 2.0-beta-47-debug.
+function bro_version%(%): string
+ %{
+ return new StringVal(bro_version());
+ %}
+
+## Converts a record type name to a vector of strings, where each element is
+## the name of a record field. Nested records are flattened.
+##
+## rt: The name of the record type.
+##
+## Returns: A string vector with the field names of *rt*.
+function record_type_to_vector%(rt: string%): string_vec
+ %{
+ VectorVal* result =
+ new VectorVal(internal_type("string_vec")->AsVectorType());
+
+ RecordType *type = internal_type(rt->CheckString())->AsRecordType();
+
+ if ( type )
+ {
+ for ( int i = 0; i < type->NumFields(); ++i )
+ {
+ StringVal* val = new StringVal(type->FieldName(i));
+ result->Assign(i+1, val, 0);
+ }
+ }
+
+ return result;
+ %}
+
+## Returns the type name of an arbitrary Bro variable.
+##
+## t: An arbitrary object.
+##
+## Returns: The type name of *t*.
+function type_name%(t: any%): string
+ %{
+ ODesc d;
+ t->Type()->Describe(&d);
+
+ BroString* s = new BroString(1, d.TakeBytes(), d.Len());
+ s->SetUseFreeToDelete(true);
+
+ return new StringVal(s);
+ %}
+
+## Checks whether Bro reads traffic from one or more network interfaces (as
+## opposed to from a network trace in a file). Note that this function returns
+## true even after Bro has stopped reading network traffic, for example due to
+## receiving a termination signal.
+##
+## Returns: True if reading traffic from a network interface.
+##
+## .. bro:see:: reading_traces
+function reading_live_traffic%(%): bool
+ %{
+ return new Val(reading_live, TYPE_BOOL);
+ %}
+
+## Checks whether Bro reads traffic from a trace file (as opposed to from a
+## network interface).
+##
+## Returns: True if reading traffic from a network trace.
+##
+## .. bro:see:: reading_live_traffic
+function reading_traces%(%): bool
+ %{
+ return new Val(reading_traces, TYPE_BOOL);
+ %}
+
+## Returns statistics about the number of packets *(i)* received by Bro,
+## *(ii)* dropped, and *(iii)* seen on the link (not always available).
+##
+## Returns: A record of packet statistics.
+##
+## .. bro:see:: do_profiling
+## resource_usage
+## get_matcher_stats
+## dump_rule_stats
+## get_gap_summary
+function net_stats%(%): NetStats
+ %{
+ unsigned int recv = 0;
+ unsigned int drop = 0;
+ unsigned int link = 0;
+
+ loop_over_list(pkt_srcs, i)
+ {
+ PktSrc* ps = pkt_srcs[i];
+
+ struct PktSrc::Stats stat;
+ ps->Statistics(&stat);
+ recv += stat.received;
+ drop += stat.dropped;
+ link += stat.link;
+ }
+
+ RecordVal* ns = new RecordVal(net_stats);
+ ns->Assign(0, new Val(recv, TYPE_COUNT));
+ ns->Assign(1, new Val(drop, TYPE_COUNT));
+ ns->Assign(2, new Val(link, TYPE_COUNT));
+
+ return ns;
+ %}
+
+## Returns Bro process statistics, such as real/user/sys CPU time, memory
+## usage, page faults, number of TCP/UDP/ICMP connections, timers, and events
+## queued/dispatched.
+##
+## Returns: A record with resource usage statistics.
+##
+## .. bro:see:: do_profiling
+## net_stats
+## get_matcher_stats
+## dump_rule_stats
+## get_gap_summary
+function resource_usage%(%): bro_resources
+ %{
+ struct rusage r;
+
+ if ( getrusage(RUSAGE_SELF, &r) < 0 )
+ reporter->InternalError("getrusage() failed in bro_resource_usage()");
+
+ double elapsed_time = current_time() - bro_start_time;
+
+ double user_time =
+ double(r.ru_utime.tv_sec) + double(r.ru_utime.tv_usec) / 1e6;
+ double system_time =
+ double(r.ru_stime.tv_sec) + double(r.ru_stime.tv_usec) / 1e6;
+
+ RecordVal* res = new RecordVal(bro_resources);
+ int n = 0;
+
+ res->Assign(n++, new StringVal(bro_version()));
+
+#ifdef DEBUG
+ res->Assign(n++, new Val(1, TYPE_COUNT));
+#else
+ res->Assign(n++, new Val(0, TYPE_COUNT));
+#endif
+
+ res->Assign(n++, new Val(bro_start_time, TYPE_TIME));
+
+ res->Assign(n++, new IntervalVal(elapsed_time, Seconds));
+ res->Assign(n++, new IntervalVal(user_time, Seconds));
+ res->Assign(n++, new IntervalVal(system_time, Seconds));
+
+ unsigned int total_mem;
+ get_memory_usage(&total_mem, 0);
+ res->Assign(n++, new Val(unsigned(total_mem), TYPE_COUNT));
+
+ res->Assign(n++, new Val(unsigned(r.ru_minflt), TYPE_COUNT));
+ res->Assign(n++, new Val(unsigned(r.ru_majflt), TYPE_COUNT));
+ res->Assign(n++, new Val(unsigned(r.ru_nswap), TYPE_COUNT));
+ res->Assign(n++, new Val(unsigned(r.ru_inblock), TYPE_COUNT));
+ res->Assign(n++, new Val(unsigned(r.ru_oublock), TYPE_COUNT));
+ res->Assign(n++, new Val(unsigned(r.ru_nivcsw), TYPE_COUNT));
+
+ SessionStats s;
+ if ( sessions )
+ sessions->GetStats(s);
+
+#define ADD_STAT(x) \
+ res->Assign(n++, new Val(unsigned(sessions ? x : 0), TYPE_COUNT));
+
+ ADD_STAT(s.num_TCP_conns);
+ ADD_STAT(s.num_UDP_conns);
+ ADD_STAT(s.num_ICMP_conns);
+ ADD_STAT(s.num_fragments);
+ ADD_STAT(s.num_packets);
+ ADD_STAT(s.num_timers);
+ ADD_STAT(s.num_events_queued);
+ ADD_STAT(s.num_events_dispatched);
+ ADD_STAT(s.max_TCP_conns);
+ ADD_STAT(s.max_UDP_conns);
+ ADD_STAT(s.max_ICMP_conns);
+ ADD_STAT(s.max_fragments);
+ ADD_STAT(s.max_timers);
+
+ return res;
+ %}
+
+## Returns statistics about the regular expression engine, such as the number
+## of distinct matchers, DFA states, DFA state transitions, memory usage of
+## DFA states, cache hits/misses, and average number of NFA states across all
+## matchers.
+##
+## Returns: A record with matcher statistics.
+##
+## .. bro:see:: do_profiling
+## net_stats
+## resource_usage
+## dump_rule_stats
+## get_gap_summary
+function get_matcher_stats%(%): matcher_stats
+ %{
+ RuleMatcher::Stats s;
+ memset(&s, 0, sizeof(s));
+
+ if ( rule_matcher )
+ rule_matcher->GetStats(&s);
+
+ RecordVal* r = new RecordVal(matcher_stats);
+ r->Assign(0, new Val(s.matchers, TYPE_COUNT));
+ r->Assign(1, new Val(s.dfa_states, TYPE_COUNT));
+ r->Assign(2, new Val(s.computed, TYPE_COUNT));
+ r->Assign(3, new Val(s.mem, TYPE_COUNT));
+ r->Assign(4, new Val(s.hits, TYPE_COUNT));
+ r->Assign(5, new Val(s.misses, TYPE_COUNT));
+ r->Assign(6, new Val(s.avg_nfa_states, TYPE_COUNT));
+
+ return r;
+ %}
+
+## Returns statistics about TCP gaps.
+##
+## Returns: A record with TCP gap statistics.
+##
+## .. bro:see:: do_profiling
+## net_stats
+## resource_usage
+## dump_rule_stats
+## get_matcher_stats
+function get_gap_summary%(%): gap_info
+ %{
+ RecordVal* r = new RecordVal(gap_info);
+ r->Assign(0, new Val(tot_ack_events, TYPE_COUNT));
+ r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT));
+ r->Assign(2, new Val(tot_gap_events, TYPE_COUNT));
+ r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT));
+
+ return r;
+ %}
+
+## Generates a table of the size of all global variables. The table index is
+## the variable name and the value the variable size in bytes.
+##
+## Returns: A table that maps variable names to their sizes.
+##
+## .. bro:see:: global_ids
+function global_sizes%(%): var_sizes
+ %{
+ TableVal* sizes = new TableVal(var_sizes);
+ PDict(ID)* globals = global_scope()->Vars();
+ IterCookie* c = globals->InitForIteration();
+
+ ID* id;
+ while ( (id = globals->NextEntry(c)) )
+ if ( id->HasVal() && ! id->IsInternalGlobal() )
+ {
+ Val* id_name = new StringVal(id->Name());
+ Val* id_size = new Val(id->ID_Val()->MemoryAllocation(),
+ TYPE_COUNT);
+ sizes->Assign(id_name, id_size);
+ Unref(id_name);
+ }
+
+ return sizes;
+ %}
+
+## Generates a table with information about all global identifiers. The table
+## value is a record containing the type name of the identifier, whether it is
+## exported, a constant, an enum constant, redefinable, and its value (if it
+## has one).
+##
+## Returns: A table that maps identifier names to information about them.
+##
+## .. bro:see:: global_sizes
+function global_ids%(%): id_table
+ %{
+ TableVal* ids = new TableVal(id_table);
+ PDict(ID)* globals = global_scope()->Vars();
+ IterCookie* c = globals->InitForIteration();
+
+ ID* id;
+ while ( (id = globals->NextEntry(c)) )
+ {
+ if ( id->IsInternalGlobal() )
+ continue;
+
+ RecordVal* rec = new RecordVal(script_id);
+ rec->Assign(0, new StringVal(type_name(id->Type()->Tag())));
+ rec->Assign(1, new Val(id->IsExport(), TYPE_BOOL));
+ rec->Assign(2, new Val(id->IsConst(), TYPE_BOOL));
+ rec->Assign(3, new Val(id->IsEnumConst(), TYPE_BOOL));
+ rec->Assign(4, new Val(id->IsRedefinable(), TYPE_BOOL));
+
+ if ( id->HasVal() )
+ {
+ Val* val = id->ID_Val();
+ Ref(val);
+ rec->Assign(5, val);
+ }
+
+ Val* id_name = new StringVal(id->Name());
+ ids->Assign(id_name, rec);
+ Unref(id_name);
+ }
+
+ return ids;
+ %}
+
+## Returns the value of a global identifier.
+##
+## id: The global identifier.
+##
+## Returns the value of *id*. If *id* does not describe a valid identifier, the
+## function returns the string ``""`` or ``""``.
+function lookup_ID%(id: string%) : any
+ %{
+ ID* i = global_scope()->Lookup(id->CheckString());
+ if ( ! i )
+ return new StringVal("");
+
+ if ( ! i->ID_Val() )
+ return new StringVal("");
+
+ return i->ID_Val()->Ref();
+ %}
+
+## Generates meta data about a record fields. The returned information
+## includes the field name, whether it is logged, its value (if it has one),
+## and its default value (if specified).
+##
+## rec: The record to inspect.
+##
+## Returns: A table that describes the fields of a record.
+function record_fields%(rec: any%): record_field_table
+ %{
+ TableVal* fields = new TableVal(record_field_table);
+
+ RecordVal* rv = rec->AsRecordVal();
+ RecordType* rt = rv->Type()->AsRecordType();
+
+ if ( rt->Tag() != TYPE_RECORD )
+ {
+ reporter->Error("non-record passed to record_fields");
+ return fields;
+ }
+
+ for ( int i = 0; i < rt->NumFields(); ++i )
+ {
+ BroType* ft = rt->FieldType(i);
+ TypeDecl* fd = rt->FieldDecl(i);
+ Val* fv = rv->Lookup(i);
+
+ if ( fv )
+ Ref(fv);
+
+ bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0);
+
+ RecordVal* nr = new RecordVal(record_field);
+ nr->Assign(0, new StringVal(type_name(rt->Tag())));
+ nr->Assign(1, new Val(logged, TYPE_BOOL));
+ nr->Assign(2, fv);
+ nr->Assign(3, rt->FieldDefault(i));
+
+ Val* field_name = new StringVal(rt->FieldName(i));
+ fields->Assign(field_name, nr);
+ Unref(field_name);
+ }
+
+ return fields;
+ %}
+
+## Enables detailed collections of statistics about CPU/memory usage,
+## connections, TCP states/reassembler, DNS lookups, timers, and script-level
+## state. The script variable :bro:id:`profiling_file` holds the name of the
+## file.
+##
+## .. bro:see:: net_stats
+## resource_usage
+## get_matcher_stats
+## dump_rule_stats
+## get_gap_summary
+function do_profiling%(%) : bool
+ %{
+ if ( profiling_logger )
+ profiling_logger->Log();
+
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Checks whether a given IP address belongs to a local interface.
+##
+## ip: The IP address to check.
+##
+## Returns: True if *ip* belongs to a local interface.
+function is_local_interface%(ip: addr%) : bool
+ %{
+ static uint32* addrs;
+ static int len = -1;
+
+ if ( len < 0 )
+ {
+ char host[MAXHOSTNAMELEN];
+
+ strcpy(host, "localhost");
+ gethostname(host, MAXHOSTNAMELEN);
+ host[MAXHOSTNAMELEN-1] = '\0';
+
+ struct hostent* ent = gethostbyname(host);
+
+ for ( len = 0; ent->h_addr_list[len]; ++len )
+ ;
+
+ addrs = new uint32[len + 1];
+ for ( int i = 0; i < len; i++ )
+ addrs[i] = *(uint32*) ent->h_addr_list[i];
+
+ addrs[len++] = 0x0100007f; // 127.0.0.1
+ }
+
+#ifdef BROv6
+ if ( ! is_v4_addr(ip) )
+ {
+ builtin_error("is_local_interface() only supports IPv4 addresses");
+ return new Val(0, TYPE_BOOL);
+ }
+
+ uint32 ip4 = to_v4_addr(ip);
+#else
+ uint32 ip4 = ip;
+#endif
+
+ for ( int i = 0; i < len; i++ )
+ if ( addrs[i] == ip4 )
+ return new Val(1, TYPE_BOOL);
+
+ return new Val(0, TYPE_BOOL);
+ %}
+
+## Write rule matcher statistics (DFA states, transitions, memory usage, cache
+## hits/misses) to a file.
+##
+## f: The file to write to.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: do_profiling
+## resource_usage
+## get_matcher_stats
+## net_stats
+## get_gap_summary
+##
+## .. todo:: The return value should be changed to any or check appropriately.
function dump_rule_stats%(f: file%): bool
%{
if ( rule_matcher )
@@ -2702,90 +2021,831 @@ function dump_rule_stats%(f: file%): bool
return new Val(1, TYPE_BOOL);
%}
+## Checks wheter Bro is terminating.
+##
+## Returns: True if Bro is in the process of shutting down.
+##
+## .. bro:see: terminate
function bro_is_terminating%(%): bool
%{
return new Val(terminating, TYPE_BOOL);
%}
-function rotate_file%(f: file%): rotate_info
+## Returns the hostname of the machine Bro runs on.
+##
+## Returns: The hostname of the machine Bro runs on.
+function gethostname%(%) : string
%{
- RecordVal* info = f->Rotate();
- if ( info )
- return info;
+ char buffer[MAXHOSTNAMELEN];
+ if ( gethostname(buffer, MAXHOSTNAMELEN) < 0 )
+ strcpy(buffer, "");
- // Record indicating error.
- info = new RecordVal(rotate_info);
- info->Assign(0, new StringVal(""));
- info->Assign(1, new StringVal(""));
- info->Assign(2, new Val(0, TYPE_TIME));
- info->Assign(3, new Val(0, TYPE_TIME));
-
- return info;
+ buffer[MAXHOSTNAMELEN-1] = '\0';
+ return new StringVal(buffer);
%}
-function rotate_file_by_name%(f: string%): rotate_info
+# ===========================================================================
+#
+# Conversion
+#
+# ===========================================================================
+
+## Converts a :bro:type:`string` to a :bro:type:`int`.
+##
+## str: The :bro:type:`string` to convert.
+##
+## Returns: The :bro:type:`string` *str* as :bro:type:`int`.
+##
+## .. bro:see:: to_addr to_port
+function to_int%(str: string%): int
%{
- RecordVal* info = new RecordVal(rotate_info);
+ const char* s = str->CheckString();
+ char* end_s;
- bool is_pkt_dumper = false;
- bool is_addl_pkt_dumper = false;
+ long l = strtol(s, &end_s, 10);
+ int i = int(l);
- // Special case: one of current dump files.
- if ( pkt_dumper && streq(pkt_dumper->FileName(), f->CheckString()) )
- {
- is_pkt_dumper = true;
- pkt_dumper->Close();
- }
+#if 0
+ // Not clear we should complain. For example, is " 205 "
+ // a legal conversion?
+ if ( s[0] == '\0' || end_s[0] != '\0' )
+ builtin_error("bad conversion to integer", @ARG@[0]);
+#endif
- if ( addl_pkt_dumper &&
- streq(addl_pkt_dumper->FileName(), f->CheckString()) )
- {
- is_addl_pkt_dumper = true;
- addl_pkt_dumper->Close();
- }
-
- FILE* file = rotate_file(f->CheckString(), info);
- if ( ! file )
- {
- // Record indicating error.
- info->Assign(0, new StringVal(""));
- info->Assign(1, new StringVal(""));
- info->Assign(2, new Val(0, TYPE_TIME));
- info->Assign(3, new Val(0, TYPE_TIME));
- return info;
- }
-
- fclose(file);
-
- if ( is_pkt_dumper )
- {
- info->Assign(2, new Val(pkt_dumper->OpenTime(), TYPE_TIME));
- pkt_dumper->Open();
- }
-
- if ( is_addl_pkt_dumper )
- info->Assign(2, new Val(addl_pkt_dumper->OpenTime(), TYPE_TIME));
-
- return info;
+ return new Val(i, TYPE_INT);
%}
-function calc_next_rotate%(i: interval%) : interval
+
+## Converts a (positive) :bro:type:`int` to a :bro:type:`count`.
+##
+## n: The :bro:type:`int` to convert.
+##
+## Returns: The :bro:type:`int` *n* as unsigned integer or 0 if *n* < 0.
+function int_to_count%(n: int%): count
%{
- const char* base_time = log_rotate_base_time ?
- log_rotate_base_time->AsString()->CheckString() : 0;
- return new Val(calc_next_rotate(i, base_time), TYPE_INTERVAL);
+ if ( n < 0 )
+ {
+ builtin_error("bad conversion to count", @ARG@[0]);
+ n = 0;
+ }
+ return new Val(n, TYPE_COUNT);
%}
-function file_size%(f: string%) : double
+## Converts a :bro:type:`double` to a :bro:type:`count`.
+##
+## d: The :bro:type:`double` to convert.
+##
+## Returns: The :bro:type:`double` *d* as unsigned integer or 0 if *d* < 0.0.
+##
+## .. bro:see:: double_to_time
+function double_to_count%(d: double%): count
%{
- struct stat s;
+ if ( d < 0.0 )
+ builtin_error("bad conversion to count", @ARG@[0]);
- if ( stat(f->CheckString(), &s) < 0 )
- return new Val(-1.0, TYPE_DOUBLE);
-
- return new Val(double(s.st_size), TYPE_DOUBLE);
+ return new Val(bro_uint_t(rint(d)), TYPE_COUNT);
%}
+## Converts a :bro:type:`string` to a :bro:type:`count`.
+##
+## str: The :bro:type:`string` to convert.
+##
+## Returns: The :bro:type:`string` *str* as unsigned integer or if in invalid
+## format.
+##
+## .. bro:see:: to_addr to_int to_port
+function to_count%(str: string%): count
+ %{
+ const char* s = str->CheckString();
+ char* end_s;
+
+ uint64 u = (uint64) strtoll(s, &end_s, 10);
+
+ if ( s[0] == '\0' || end_s[0] != '\0' )
+ {
+ builtin_error("bad conversion to count", @ARG@[0]);
+ u = 0;
+ }
+
+ return new Val(u, TYPE_COUNT);
+ %}
+
+## Converts an :bro:type:`interval` to a :bro:type:`double`.
+##
+## i: The :bro:type:`interval` to convert.
+##
+## Returns: The :bro:type:`interval` *i* as :bro:type:`double`.
+##
+## .. bro:see:: double_to_interval
+function interval_to_double%(i: interval%): double
+ %{
+ return new Val(i, TYPE_DOUBLE);
+ %}
+
+## Converts a :bro:type:`time` value to a :bro:type:`double`.
+##
+## t: The :bro:type:`interval` to convert.
+##
+## Returns: The :bro:type:`time` value *t* as :bro:type:`double`.
+##
+## .. bro:see:: double_to_time
+function time_to_double%(t: time%): double
+ %{
+ return new Val(t, TYPE_DOUBLE);
+ %}
+
+## Converts a :bro:type:`time` value to a :bro:type:`double`.
+##
+## t: The :bro:type:`interval` to convert.
+##
+## Returns: The :bro:type:`time` value *t* as :bro:type:`double`.
+##
+## .. bro:see:: time_to_double double_to_count
+function double_to_time%(d: double%): time
+ %{
+ return new Val(d, TYPE_TIME);
+ %}
+
+## Converts a :bro:type:`double` to an :bro:type:`interval`.
+##
+## d: The :bro:type:`double` to convert.
+##
+## Returns: The :bro:type:`double` *d* as :bro:type:`interval`.
+##
+## .. bro:see:: interval_to_double
+function double_to_interval%(d: double%): interval
+ %{
+ return new Val(d, TYPE_INTERVAL);
+ %}
+
+## Converts a :bro:type:`addr` to a :bro:type:`count`.
+##
+## a: The :bro:type:`addr` to convert.
+##
+## Returns: The :bro:type:`addr` *a* as :bro:type:`count`.
+##
+## .. bro:see:: addr_to_ptr_name
+function addr_to_count%(a: addr%): count
+ %{
+#ifdef BROv6
+ if ( ! is_v4_addr(a) )
+ {
+ builtin_error("conversion of non-IPv4 address to count", @ARG@[0]);
+ return new Val(0, TYPE_COUNT);
+ }
+
+ uint32 addr = to_v4_addr(a);
+#else
+ uint32 addr = a;
+#endif
+ return new Val(ntohl(addr), TYPE_COUNT);
+ %}
+
+## Converts a :bro:type:`port` to a :bro:type:`count`.
+##
+## p: The :bro:type:`port` to convert.
+##
+## Returns: The :bro:type:`port` *p* as :bro:type:`count`.
+##
+## .. bro:see:: count_to_port
+function port_to_count%(p: port%): count
+ %{
+ return new Val(p->Port(), TYPE_COUNT);
+ %}
+
+## Converts a :bro:type:`count` and ``transport_proto`` to a :bro:type:`port`.
+##
+## c: The :bro:type:`count` to convert.
+##
+## Returns: The :bro:type:`count` *c* as :bro:type:`port`.
+##
+## .. bro:see:: port_to_count
+function count_to_port%(c: count, t: transport_proto%): port
+ %{
+ return new PortVal(c, (TransportProto)(t->InternalInt()));
+ %}
+
+## Converts a :bro:type:`string` to an :bro:type:`addr`.
+##
+## ip: The :bro:type:`string` to convert.
+##
+## Returns: The :bro:type:`string` *ip* as :bro:type:`addr`.
+##
+## .. bro:see:: to_count to_int to_port count_to_v4_addr raw_bytes_to_v4_addr
+function to_addr%(ip: string%): addr
+ %{
+ char* s = ip->AsString()->Render();
+ Val* ret = new AddrVal(s);
+ delete [] s;
+ return ret;
+ %}
+
+## Converts a :bro:type:`count` to an :bro:type:`addr`.
+##
+## ip: The :bro:type:`count` to convert.
+##
+## Returns: The :bro:type:`count` *ip* as :bro:type:`addr`.
+##
+## .. bro:see:: raw_bytes_to_v4_addr to_addr
+function count_to_v4_addr%(ip: count%): addr
+ %{
+ if ( ip > 4294967295LU )
+ {
+ builtin_error("conversion of non-IPv4 count to addr", @ARG@[0]);
+ return new AddrVal(uint32(0));
+ }
+
+ return new AddrVal(htonl(uint32(ip)));
+ %}
+
+## Converts a :bro:type:`string` of bytes into an IP address. In particular,
+## this function interprets the first 4 bytes of the string as an IPv4 address
+## in network order.
+##
+## b: The raw bytes (:bro:type:`string`) to convert.
+##
+## Returns: The byte :bro:type:`string` *ip* as :bro:type:`addr`.
+##
+## .. bro:see:: raw_bytes_to_v4_addr to_addr
+function raw_bytes_to_v4_addr%(b: string%): addr
+ %{
+ uint32 a = 0;
+
+ if ( b->Len() < 4 )
+ builtin_error("too short a string as input to raw_bytes_to_v4_addr()");
+
+ else
+ {
+ const u_char* bp = b->Bytes();
+ a = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
+ }
+
+ return new AddrVal(htonl(a));
+ %}
+
+## Creates a :bro:type:`port` from a given number and transport protocol.
+##
+## num: The port number.
+##
+## proto: THe transport protocol of the port.
+##
+## Returns: A :bro:type:`port` with number *num* and transport protocol
+## *proto*.
+##
+## .. bro:see:: to_addr to_count to_int
+function to_port%(num: count, proto: transport_proto%): port
+ %{
+ return new PortVal(num, (TransportProto)proto->AsEnum());
+ %}
+
+## Converts a reverse pointer name to an address. For example,
+## ``1.0.168.192.in-addr.arpa`` to ``192.168.0.1``.
+##
+## s: The string with the reverse pointer name.
+##
+## Returns: The IP address corresponding to *s*.
+##
+## .. bro:see:: addr_to_ptr_name parse_dotted_addr
+function ptr_name_to_addr%(s: string%): addr
+ %{
+ int a[4];
+ uint32 addr;
+
+ if ( sscanf(s->CheckString(),
+ "%d.%d.%d.%d.in-addr.arpa",
+ a, a+1, a+2, a+3) != 4 )
+ {
+ builtin_error("bad PTR name", @ARG@[0]);
+ addr = 0;
+ }
+ else
+ addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
+
+ return new AddrVal(htonl(addr));
+ %}
+
+## Converts an IP address to a reverse pointer name. For example,
+## ``192.168.0.1`` to ``1.0.168.192.in-addr.arpa``.
+##
+## a: The IP address to convert to a reverse pointer name.
+##
+## Returns: The reverse pointer representation of *a*.
+##
+## .. bro:see:: addr_to_count ptr_name_to_addr parse_dotted_addr
+function addr_to_ptr_name%(a: addr%): string
+ %{
+ // ## Question:
+ // uint32 addr = ntohl((*args)[0]->InternalUnsigned());
+ uint32 addr;
+#ifdef BROv6
+ if ( is_v4_addr(a) )
+ addr = a[3];
+ else
+ {
+ builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
+ addr = 0;
+ }
+#else
+ addr = a;
+#endif
+
+ addr = ntohl(addr);
+ uint32 a3 = (addr >> 24) & 0xff;
+ uint32 a2 = (addr >> 16) & 0xff;
+ uint32 a1 = (addr >> 8) & 0xff;
+ uint32 a0 = addr & 0xff;
+
+ char buf[256];
+ sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3);
+
+ return new StringVal(buf);
+ %}
+
+# Transforms n0.n1.n2.n3 -> addr.
+
+## Converts a decimal dotted IP address in a :bro:type:`string` to an
+## :bro:type:`addr` type.
+##
+## s: The IP address in the form ``n0.n1.n2.n3``.
+##
+## Returns: The IP address as type :bro:type:`addr`.
+##
+## .. bro:see:: addr_to_ptr_name parse_dotted_addr addr_to_count
+function parse_dotted_addr%(s: string%): addr
+ %{
+ return new AddrVal(dotted_to_addr(s->CheckString()));
+ %}
+
+%%{
+static Val* parse_port(const char* line)
+ {
+ RecordVal* r = new RecordVal(ftp_port);
+
+ int bytes[6];
+ if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d",
+ &bytes[0], &bytes[1], &bytes[2],
+ &bytes[3], &bytes[4], &bytes[5]) == 6 )
+ {
+ int good = 1;
+
+ for ( int i = 0; i < 6; ++i )
+ if ( bytes[i] < 0 || bytes[i] > 255 )
+ {
+ good = 0;
+ break;
+ }
+
+ uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) |
+ (bytes[2] << 8) | bytes[3];
+ uint32 port = (bytes[4] << 8) | bytes[5];
+
+ // Since port is unsigned, no need to check for < 0.
+ if ( port > 65535 )
+ {
+ port = 0;
+ good = 0;
+ }
+
+ r->Assign(0, new AddrVal(htonl(addr)));
+ r->Assign(1, new PortVal(port, TRANSPORT_TCP));
+ r->Assign(2, new Val(good, TYPE_BOOL));
+ }
+ else
+ {
+ r->Assign(0, new AddrVal(uint32(0)));
+ r->Assign(1, new PortVal(0, TRANSPORT_TCP));
+ r->Assign(2, new Val(0, TYPE_BOOL));
+ }
+
+ return r;
+ }
+
+static Val* parse_eftp(const char* line)
+ {
+ RecordVal* r = new RecordVal(ftp_port);
+
+ int net_proto = 0; // currently not used
+ uint32 addr = 0;
+ int port = 0;
+ int good = 0;
+
+ if ( line )
+ {
+ while ( isspace(*line) ) // skip whitespace
+ ++line;
+
+ char delimiter = *line;
+ good = 1;
+ char* next_delim;
+
+ ++line; // cut off delimiter
+ net_proto = strtol(line, &next_delim, 10); // currently ignored
+ if ( *next_delim != delimiter )
+ good = 0;
+
+ line = next_delim + 1;
+ if ( *line != delimiter ) // default of 0 is ok
+ {
+ addr = dotted_to_addr(line);
+ if ( addr == 0 )
+ good = 0;
+ }
+
+ // FIXME: check for garbage between IP and delimiter.
+ line = strchr(line, delimiter);
+
+ ++line; // now the port
+ port = strtol(line, &next_delim, 10);
+ if ( *next_delim != delimiter )
+ good = 0;
+ }
+
+ r->Assign(0, new AddrVal(addr));
+ r->Assign(1, new PortVal(port, TRANSPORT_TCP));
+ r->Assign(2, new Val(good, TYPE_BOOL));
+
+ return r;
+ }
+%%}
+
+## Converts a string representation of the FTP PORT command to an ``ftp_port``.
+##
+## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``.
+##
+## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
+##
+## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
+function parse_ftp_port%(s: string%): ftp_port
+ %{
+ return parse_port(s->CheckString());
+ %}
+
+## Converts a string representation of the FTP EPRT command to an ``ftp_port``.
+## (see `RFC 2428 `_).
+## The format is ``EPRT``,
+## where ```` is a delimiter in the ASCII range 33-126 (usually ``|``).
+##
+## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``.
+##
+## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
+##
+## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
+function parse_eftp_port%(s: string%): ftp_port
+ %{
+ return parse_eftp(s->CheckString());
+ %}
+
+## Converts the result of the FTP PASV command to an ``ftp_port``.
+##
+## str: The string containing the result of the FTP PASV command.
+##
+## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
+##
+## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port
+function parse_ftp_pasv%(str: string%): ftp_port
+ %{
+ const char* s = str->CheckString();
+ const char* line = strchr(s, '(');
+ if ( line )
+ ++line; // move past '('
+ else if ( (line = strstr(s, "PORT")) )
+ line += 5; // Skip over
+ else if ( (line = strchr(s, ',')) )
+ { // Look for comma-separated list.
+ while ( --line >= s && isdigit(*line) )
+ ; // Back up over preceding digits.
+ ++line; // now points to first digit, or beginning of s
+ }
+
+ return parse_port(line);
+ %}
+
+## Converts the result of the FTP EPSV command to an ``ftp_port``.
+## See `RFC 2428 `_.
+## The format is `` ()``, where ```` is a
+## delimiter in the ASCII range 33-126 (usually ``|``).
+##
+## str: The string containing the result of the FTP PASV command.
+##
+## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
+##
+## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port
+function parse_ftp_epsv%(str: string%): ftp_port
+ %{
+ const char* s = str->CheckString();
+ const char* line = strchr(s, '(');
+ if ( line )
+ ++line; // move past '('
+ return parse_eftp(line);
+ %}
+
+## Formats an IP address and TCP port as an FTP PORT command. For example,
+## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``.
+##
+## a: The IP address.
+##
+## p: The TCP port.
+##
+## Returns: The FTP PORT string.
+##
+## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv
+function fmt_ftp_port%(a: addr, p: port%): string
+ %{
+#ifdef BROv6
+ if ( ! is_v4_addr(a) )
+ builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
+
+ uint32 addr = to_v4_addr(a);
+#else
+ uint32 addr = a;
+#endif
+ addr = ntohl(addr);
+ uint32 pn = p->Port();
+ return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
+ addr >> 24, (addr >> 16) & 0xff,
+ (addr >> 8) & 0xff, addr & 0xff,
+ pn >> 8, pn & 0xff));
+ %}
+
+## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203.
+##
+## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF:``.
+##
+## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``.
+##
+## .. bro:see:: decode_netbios_name_type
+function decode_netbios_name%(name: string%): string
+ %{
+ char buf[16];
+ char result[16];
+ const u_char* s = name->Bytes();
+ int i, j;
+
+ for ( i = 0, j = 0; i < 16; ++i )
+ {
+ char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A';
+ char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A';
+ buf[i] = ((c0 - 'A') << 4) + (c1 - 'A');
+ }
+
+ for ( i = 0; i < 15; ++i )
+ {
+ if ( isalnum(buf[i]) || ispunct(buf[i]) ||
+ // \x01\x02 is seen in at least one case as the first two bytes.
+ // I think that any \x01 and \x02 should always be passed through.
+ buf[i] < 3 )
+ result[i] = buf[i];
+ else
+ break;
+ }
+
+ return new StringVal(i, result);
+ %}
+
+## Converts a NetBIOS name type to its corresonding numeric value.
+## See http://support.microsoft.com/kb/163409.
+##
+## name: The NetBIOS name type.
+##
+## Returns: The numeric value of *name*.
+##
+## .. bro:see:: decode_netbios_name
+function decode_netbios_name_type%(name: string%): count
+ %{
+ const u_char* s = name->Bytes();
+ char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A');
+ return new Val(return_val, TYPE_COUNT);
+ %}
+
+## Converts a string of bytes into its hexadecimal representation, e.g.,
+## ``"04"`` to ``"3034"``.
+##
+## bytestring: The string of bytes.
+##
+## Returns: The hexadecimal reprsentation of *bytestring*.
+##
+## .. bro:see:: hexdump
+function bytestring_to_hexstr%(bytestring: string%): string
+ %{
+ bro_uint_t len = bytestring->AsString()->Len();
+ const u_char* bytes = bytestring->AsString()->Bytes();
+ char hexstr[(2 * len) + 1];
+
+ hexstr[0] = 0;
+ for ( bro_uint_t i = 0; i < len; ++i )
+ snprintf(hexstr + (2 * i), 3, "%.2hhx", bytes[i]);
+
+ return new StringVal(hexstr);
+ %}
+
+## Decodes a Base64-encoded string.
+##
+## s: The Base64-encoded string.
+##
+## Returns: The decoded version of *s*.
+##
+## .. bro:see:: decode_base64_custom
+function decode_base64%(s: string%): string
+ %{
+ BroString* t = decode_base64(s->AsString());
+ if ( t )
+ return new StringVal(t);
+ else
+ {
+ reporter->Error("error in decoding string %s", s->CheckString());
+ return new StringVal("");
+ }
+ %}
+
+## Decodes a Base64-encoded string with a custom alphabet.
+##
+## s: The Base64-encoded string.
+##
+## a: The custom alphabet. The empty string indicates the default alphabet. The
+## lengh of *a* must bt 64. For example, a custom alphabet could be
+## ``"!#$%&/(),-.:;<>@[]^ `_{|}~abcdefghijklmnopqrstuvwxyz0123456789+?"``.
+##
+## Returns: The decoded version of *s*.
+##
+## .. bro:see:: decode_base64
+function decode_base64_custom%(s: string, a: string%): string
+ %{
+ BroString* t = decode_base64(s->AsString(), a->AsString());
+ if ( t )
+ return new StringVal(t);
+ else
+ {
+ reporter->Error("error in decoding string %s", s->CheckString());
+ return new StringVal("");
+ }
+ %}
+
+%%{
+#include "DCE_RPC.h"
+
+typedef struct {
+ uint32 time_low;
+ uint16 time_mid;
+ uint16 time_hi_and_version;
+ uint8 clock_seq_hi_and_reserved;
+ uint8 clock_seq_low;
+ uint8 node[6];
+} bro_uuid_t;
+%%}
+
+## Converts a bytes representation of a UUID into its string form. For example,
+## given a string of 16 bytes, it produces an output string in this format:
+## ``550e8400-e29b-41d4-a716-446655440000``.
+## See ``_.
+##
+## uuid: The 16 bytes of the UUID.
+##
+## Returns: The string representation of *uuid*.
+function uuid_to_string%(uuid: string%): string
+ %{
+ if ( uuid->Len() != 16 )
+ return new StringVal("");
+
+ bro_uuid_t* id = (bro_uuid_t*) uuid->Bytes();
+
+ static char s[1024];
+ char* sp = s;
+
+ sp += snprintf(sp, s + sizeof(s) - sp,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ id->time_low, id->time_mid, id->time_hi_and_version,
+ id->clock_seq_hi_and_reserved, id->clock_seq_low,
+ id->node[0],
+ id->node[1],
+ id->node[2],
+ id->node[3],
+ id->node[4],
+ id->node[5]);
+
+ return new StringVal(s);
+ %}
+
+## Merges and compiles two regular expressions at initialization time.
+##
+## p1: The first pattern.
+##
+## p2: The second pattern.
+##
+## Returns: The compiled pattern of the concatentation of *p1* and *p2*.
+##
+## .. bro:see:: convert_for_pattern string_to_pattern
+##
+## .. note::
+##
+## This function must be called at Bro startup time, e.g., in the event
+## :bro:id:`bro_init`.
+function merge_pattern%(p1: pattern, p2: pattern%): pattern
+ %{
+ if ( bro_start_network_time != 0.0 )
+ {
+ builtin_error("merge_pattern can only be called at init time");
+ return 0;
+ }
+
+ RE_Matcher* re = new RE_Matcher();
+ re->AddPat(p1->PatternText());
+ re->AddPat(p2->PatternText());
+ re->Compile();
+ return new PatternVal(re);
+ %}
+
+%%{
+char* to_pat_str(int sn, const char* ss)
+ {
+ const char special_re_char[] = "^$-:\"\\/|*+?.(){}[]";
+
+ char* pat = new char[sn * 4 + 1];
+ int pat_len = 0;
+
+ for ( int i = 0; i < sn; ++i )
+ {
+ if ( ! strchr(special_re_char, ss[i]) )
+ pat[pat_len++] = ss[i];
+ else
+ {
+ pat[pat_len++] = '\\';
+ pat[pat_len++] = ss[i];
+ }
+ }
+ pat[pat_len] = '\0';
+ return pat;
+ }
+%%}
+
+## Escapes a string so that it becomes a valid :bro:type:`pattern` and can be
+## used with the :bro:id:`string_to_pattern`. Any character from the set
+## ``^$-:"\/|*+?.(){}[]`` is prefixed with a ``\``.
+##
+## s: The string to escape.
+##
+## Returns: An escaped version of *s* that has the structure of a valid
+## :bro:type:`pattern`.
+##
+## .. bro:see:: merge_pattern string_to_pattern
+##
+function convert_for_pattern%(s: string%): string
+ %{
+ char* t = to_pat_str(s->Len(), (const char*)(s->Bytes()));
+ StringVal* ret = new StringVal(t);
+ delete [] t;
+ return ret;
+ %}
+
+## Converts a :bro:type:`string` into a :bro:type:`pattern`.
+##
+## s: The string to convert.
+##
+## convert: If true, *s* is first passed through the function
+## :bro:id:`convert_for_pattern` to escape special characters of
+## patterns.
+##
+## Returns: *s* as :bro:type:`pattern`.
+##
+## .. bro:see:: convert_for_pattern merge_pattern
+##
+## .. note::
+##
+## This function must be called at Bro startup time, e.g., in the event
+## :bro:id:`bro_init`.
+function string_to_pattern%(s: string, convert: bool%): pattern
+ %{
+ if ( bro_start_network_time != 0.0 )
+ {
+ builtin_error("string_to_pattern can only be called at init time");
+ return 0;
+ }
+
+ const char* ss = (const char*) (s->Bytes());
+ int sn = s->Len();
+ char* pat;
+
+ if ( convert )
+ pat = to_pat_str(sn, ss);
+ else
+ {
+ pat = new char[sn+1];
+ memcpy(pat, ss, sn);
+ pat[sn] = '\0';
+ }
+
+ RE_Matcher* re = new RE_Matcher(pat);
+ delete [] pat;
+ re->Compile();
+ return new PatternVal(re);
+ %}
+
+## Formats a given time value according to a format string.
+##
+## fmt: The format string. See ``man strftime`` for the syntax.
+##
+## d: The time value.
+##
+## Returns: The time *d* formatted according to *fmt*.
function strftime%(fmt: string, d: time%) : string
%{
static char buffer[128];
@@ -2798,27 +2858,377 @@ function strftime%(fmt: string, d: time%) : string
return new StringVal(buffer);
%}
-function match_signatures%(c: connection, pattern_type: int, s: string,
- bol: bool, eol: bool,
- from_orig: bool, clear: bool%) : bool
+# ===========================================================================
+#
+# Network Type Processing
+#
+# ===========================================================================
+
+## Masks an address down to the number of given upper bits. For example,
+## ``mask_addr(1.2.3.4, 18)`` returns ``1.2.0.0``.
+##
+## a: The address to mask.
+##
+## top_bits_to_keep: The number of top bits to keep in *a*; must be greater
+## than 0 and less than 33.
+##
+## Returns: The address *a* masked down to *top_bits_to_keep* bits.
+##
+## .. bro:see:: remask_addr
+function mask_addr%(a: addr, top_bits_to_keep: count%): subnet
%{
- if ( ! rule_matcher )
- return new Val(0, TYPE_BOOL);
-
- c->Match((Rule::PatternType) pattern_type, s->Bytes(), s->Len(),
- from_orig, bol, eol, clear);
-
- return new Val(1, TYPE_BOOL);
+ return new SubNetVal(mask_addr(a, top_bits_to_keep), top_bits_to_keep);
%}
-function gethostname%(%) : string
+## Takes some top bits (e.g., subnet address) from one address and the other
+## bits (intra-subnet part) from a second address and merges them to get a new
+## address. This is useful for anonymizing at subnet level while preserving
+## serial scans.
+##
+## a1: The address to mask with *top_bits_from_a1*.
+##
+## a2: The address to take the remaining bits from.
+##
+## top_bits_from_a1: The number of top bits to keep in *a1*; must be greater
+## than 0 and less than 33.
+##
+## Returns: The address *a* masked down to *top_bits_to_keep* bits.
+##
+## .. bro:see:: mask_addr
+function remask_addr%(a1: addr, a2: addr, top_bits_from_a1: count%): addr
%{
- char buffer[MAXHOSTNAMELEN];
- if ( gethostname(buffer, MAXHOSTNAMELEN) < 0 )
- strcpy(buffer, "");
+#ifdef BROv6
+ if ( ! is_v4_addr(a1) || ! is_v4_addr(a2) )
+ {
+ builtin_error("cannot use remask_addr on IPv6 addresses");
+ return new AddrVal(a1);
+ }
- buffer[MAXHOSTNAMELEN-1] = '\0';
- return new StringVal(buffer);
+ uint32 x1 = to_v4_addr(a1);
+ uint32 x2 = to_v4_addr(a2);
+#else
+ uint32 x1 = a1;
+ uint32 x2 = a2;
+#endif
+ return new AddrVal(
+ mask_addr(x1, top_bits_from_a1) |
+ (x2 ^ mask_addr(x2, top_bits_from_a1)) );
+ %}
+
+## Checks whether a given :bro:type:`port` has TCP as transport protocol.
+##
+## p: The :bro:type:`port` to check.
+##
+## Returns: True iff *p* is a TCP port.
+##
+## .. bro:see:: is_udp_port is_icmp_port
+function is_tcp_port%(p: port%): bool
+ %{
+ return new Val(p->IsTCP(), TYPE_BOOL);
+ %}
+
+## Checks whether a given :bro:type:`port` has UDP as transport protocol.
+##
+## p: The :bro:type:`port` to check.
+##
+## Returns: True iff *p* is a UDP port.
+##
+## .. bro:see:: is_icmp_port is_tcp_port
+function is_udp_port%(p: port%): bool
+ %{
+ return new Val(p->IsUDP(), TYPE_BOOL);
+ %}
+
+## Checks whether a given :bro:type:`port` has ICMP as transport protocol.
+##
+## p: The :bro:type:`port` to check.
+##
+## Returns: True iff *p* is a ICMP port.
+##
+## .. bro:see:: is_tcp_port is_udp_port
+function is_icmp_port%(p: port%): bool
+ %{
+ return new Val(p->IsICMP(), TYPE_BOOL);
+ %}
+
+%%{
+EnumVal* map_conn_type(TransportProto tp)
+ {
+ switch ( tp ) {
+ case TRANSPORT_UNKNOWN:
+ return new EnumVal(0, transport_proto);
+ break;
+
+ case TRANSPORT_TCP:
+ return new EnumVal(1, transport_proto);
+ break;
+
+ case TRANSPORT_UDP:
+ return new EnumVal(2, transport_proto);
+ break;
+
+ case TRANSPORT_ICMP:
+ return new EnumVal(3, transport_proto);
+ break;
+
+ default:
+ reporter->InternalError("bad connection type in map_conn_type()");
+ }
+
+ // Cannot be reached;
+ assert(false);
+ return 0; // Make compiler happy.
+ }
+%%}
+
+## Extracts the transport protocol from a connection.
+##
+## cid: The connection identifier.
+##
+## Returns: The transport protocol of the connection identified by *id*.
+##
+## .. bro:see:: get_port_transport_proto
+## get_orig_seq get_resp_seq
+function get_conn_transport_proto%(cid: conn_id%): transport_proto
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ {
+ builtin_error("unknown connection id in get_conn_transport_proto()", cid);
+ return new EnumVal(0, transport_proto);
+ }
+
+ return map_conn_type(c->ConnTransport());
+ %}
+
+## Extracts the transport protocol from a :bro:type:`port`.
+##
+## p: The port.
+##
+## Returns: The transport protocol of the port *p*.
+##
+## .. bro:see:: get_conn_transport_proto
+## get_orig_seq get_resp_seq
+function get_port_transport_proto%(p: port%): transport_proto
+ %{
+ return map_conn_type(p->PortType());
+ %}
+
+## Checks whether a connection is (still) active.
+##
+## c: The connection id to check.
+##
+## Returns: True if the connection identified by *c* exists.
+##
+## .. bro:see:: lookup_connection
+function connection_exists%(c: conn_id%): bool
+ %{
+ if ( sessions->FindConnection(c) )
+ return new Val(1, TYPE_BOOL);
+ else
+ return new Val(0, TYPE_BOOL);
+ %}
+
+## Returns the :bro:type:`connection` record for a given connection identifier.
+##
+## cid: The connection ID.
+##
+## Returns: The :bro:type:`connection` record for *cid*. If *cid* does not point
+## to an existing connection, the function generates a run-time error
+## and returns a dummy value.
+##
+## .. bro:see:: connection_exists
+function lookup_connection%(cid: conn_id%): connection
+ %{
+ Connection* conn = sessions->FindConnection(cid);
+ if ( conn )
+ return conn->BuildConnVal();
+
+ builtin_error("connection ID not a known connection", cid);
+
+ // Return a dummy connection record.
+ RecordVal* c = new RecordVal(connection_type);
+
+ RecordVal* id_val = new RecordVal(conn_id);
+ id_val->Assign(0, new AddrVal((unsigned int) 0));
+ id_val->Assign(1, new PortVal(ntohs(0), TRANSPORT_UDP));
+ id_val->Assign(2, new AddrVal((unsigned int) 0));
+ id_val->Assign(3, new PortVal(ntohs(0), TRANSPORT_UDP));
+ c->Assign(0, id_val);
+
+ RecordVal* orig_endp = new RecordVal(endpoint);
+ orig_endp->Assign(0, new Val(0, TYPE_COUNT));
+ orig_endp->Assign(1, new Val(int(0), TYPE_COUNT));
+
+ RecordVal* resp_endp = new RecordVal(endpoint);
+ resp_endp->Assign(0, new Val(0, TYPE_COUNT));
+ resp_endp->Assign(1, new Val(int(0), TYPE_COUNT));
+
+ c->Assign(1, orig_endp);
+ c->Assign(2, resp_endp);
+
+ c->Assign(3, new Val(network_time, TYPE_TIME));
+ c->Assign(4, new Val(0.0, TYPE_INTERVAL));
+ c->Assign(5, new TableVal(string_set)); // service
+ c->Assign(6, new StringVal("")); // addl
+ c->Assign(7, new Val(0, TYPE_COUNT)); // hot
+ c->Assign(8, new StringVal("")); // history
+
+ return c;
+ %}
+
+%%{
+#include "HTTP.h"
+
+const char* conn_id_string(Val* c)
+ {
+ Val* id = (*(c->AsRecord()))[0];
+ const val_list* vl = id->AsRecord();
+
+ addr_type orig_h = (*vl)[0]->AsAddr();
+ uint32 orig_p = (*vl)[1]->AsPortVal()->Port();
+ addr_type resp_h = (*vl)[2]->AsAddr();
+ uint32 resp_p = (*vl)[3]->AsPortVal()->Port();
+
+ return fmt("%s/%u -> %s/%u\n", dotted_addr(orig_h), orig_p, dotted_addr(resp_h), resp_p);
+ }
+%%}
+
+## Skips the data of the HTTP entity.
+##
+## c: The HTTP connection.
+##
+## is_orig: If true, the client data is skipped and the server data otherwise.
+##
+## .. bro:see:: skip_smtp_data
+function skip_http_entity_data%(c: connection, is_orig: bool%): any
+ %{
+ AnalyzerID id = mgr.CurrentAnalyzer();
+ if ( id )
+ {
+ Analyzer* ha = c->FindAnalyzer(id);
+
+ if ( ha )
+ {
+ if ( ha->GetTag() == AnalyzerTag::HTTP )
+ static_cast(ha)->SkipEntityData(is_orig);
+ else
+ reporter->Error("non-HTTP analyzer associated with connection record");
+ }
+ else
+ reporter->Error("could not find analyzer for skip_http_entity_data");
+
+ }
+ else
+ reporter->Error("no analyzer associated with connection record");
+
+ return 0;
+ %}
+
+## Unescapes all characters in a URI, i.e., decodes every ``%xx`` group.
+##
+## URI: The URI to unescape.
+##
+## Returns: The unescaped URI with all ``%xx`` groups decoded.
+##
+## .. note::
+##
+## Unescaping reserved characters may cause loss of information. RFC 2396:
+## A URI is always in an "escaped" form, since escaping or unescaping a
+## completed URI might change its semantics. Normally, the only time
+## escape encodings can safely be made is when the URI is being created
+## from its component parts.
+function unescape_URI%(URI: string%): string
+ %{
+ const u_char* line = URI->Bytes();
+ const u_char* const line_end = line + URI->Len();
+
+ return new StringVal(unescape_URI(line, line_end, 0));
+ %}
+
+## Writes the current packet to a file.
+##
+## file_name: The name of the file to write the packet to.
+##
+## Returns: True on success.
+##
+## .. bro:see:: dump_packet get_current_packet send_current_packet
+function dump_current_packet%(file_name: string%) : bool
+ %{
+ const struct pcap_pkthdr* hdr;
+ const u_char* pkt;
+
+ if ( ! current_pktsrc ||
+ ! current_pktsrc->GetCurrentPacket(&hdr, &pkt) )
+ return new Val(0, TYPE_BOOL);
+
+ if ( ! addl_pkt_dumper )
+ addl_pkt_dumper = new PktDumper(0, true);
+
+ addl_pkt_dumper->Open(file_name->CheckString());
+ addl_pkt_dumper->Dump(hdr, pkt);
+
+ return new Val(! addl_pkt_dumper->IsError(), TYPE_BOOL);
+ %}
+
+## Returns the currently processed PCAP packet.
+##
+## Returns: The currently processed packet, which is as a record
+## containing the timestamp, ``snaplen``, and packet data.
+##
+## .. bro:see:: dump_current_packet dump_packet send_current_packet
+function get_current_packet%(%) : pcap_packet
+ %{
+ const struct pcap_pkthdr* hdr;
+ const u_char* data;
+ RecordVal* pkt = new RecordVal(pcap_packet);
+
+ if ( ! current_pktsrc ||
+ ! current_pktsrc->GetCurrentPacket(&hdr, &data) )
+ {
+ pkt->Assign(0, new Val(0, TYPE_COUNT));
+ pkt->Assign(1, new Val(0, TYPE_COUNT));
+ pkt->Assign(2, new Val(0, TYPE_COUNT));
+ pkt->Assign(3, new Val(0, TYPE_COUNT));
+ pkt->Assign(4, new StringVal(""));
+ return pkt;
+ }
+
+ pkt->Assign(0, new Val(uint32(hdr->ts.tv_sec), TYPE_COUNT));
+ pkt->Assign(1, new Val(uint32(hdr->ts.tv_usec), TYPE_COUNT));
+ pkt->Assign(2, new Val(hdr->caplen, TYPE_COUNT));
+ pkt->Assign(3, new Val(hdr->len, TYPE_COUNT));
+ pkt->Assign(4, new StringVal(hdr->caplen, (const char*) data));
+
+ return pkt;
+ %}
+
+## Writes a given packet to a file.
+##
+## pkt: The PCAP packet.
+##
+## file_name: The name of the file to write *pkt* to.
+##
+## Returns: True on success
+##
+## .. bro:see:: get_current_packet dump_current_packet send_current_packet
+function dump_packet%(pkt: pcap_packet, file_name: string%) : bool
+ %{
+ struct pcap_pkthdr hdr;
+ const val_list* pkt_vl = pkt->AsRecord();
+
+ hdr.ts.tv_sec = (*pkt_vl)[0]->AsCount();
+ hdr.ts.tv_usec = (*pkt_vl)[1]->AsCount();
+ hdr.caplen = (*pkt_vl)[2]->AsCount();
+ hdr.len = (*pkt_vl)[3]->AsCount();
+
+ if ( ! addl_pkt_dumper )
+ addl_pkt_dumper = new PktDumper(0, true);
+
+ addl_pkt_dumper->Open(file_name->CheckString());
+ addl_pkt_dumper->Dump(&hdr, (*pkt_vl)[4]->AsString()->Bytes());
+
+ return new Val(addl_pkt_dumper->IsError(), TYPE_BOOL);
%}
%%{
@@ -2886,8 +3296,15 @@ private:
};
%%}
-# These two functions issue DNS lookups asynchronously and delay the
-# function result. Therefore, they can only be called inside a when-condition.
+## Issues an asynchronous reverse DNS lookup and delays the function result.
+## This function can therefore only be called inside a ``when`` condition,
+## e.g., ``when ( local host = lookup_addr(10.0.0.1) ) { f(host); }``.
+##
+## host: The IP address to lookup.
+##
+## Returns: The DNS name of *host*.
+##
+## .. bro:see:: lookup_hostname
function lookup_addr%(host: addr%) : string
%{
// FIXME: It should be easy to adapt the function to synchronous
@@ -2929,6 +3346,15 @@ function lookup_addr%(host: addr%) : string
return 0;
%}
+## Issues an asynchronous DNS lookup and delays the function result.
+## This function can therefore only be called inside a ``when`` condition,
+## e.g., ``when ( local h = lookup_hostname("www.bro-ids.org") ) { f(h); }``.
+##
+## host: The hostname to lookup.
+##
+## Returns: A set of DNS A records associated with *host*.
+##
+## .. bro:see:: lookup_addr
function lookup_hostname%(host: string%) : addr_set
%{
// FIXME: Is should be easy to adapt the function to synchronous
@@ -2949,110 +3375,6 @@ function lookup_hostname%(host: string%) : addr_set
return 0;
%}
-# Stop Bro's packet processing.
-function suspend_processing%(%) : any
- %{
- net_suspend_processing();
- return 0;
- %}
-
-# Resume Bro's packet processing.
-function continue_processing%(%) : any
- %{
- net_continue_processing();
- return 0;
- %}
-
-%%{
-#include "DPM.h"
-%%}
-
-# Schedule analyzer for a future connection.
-function expect_connection%(orig: addr, resp: addr, resp_p: port,
- analyzer: count, tout: interval%) : bool
- %{
- dpm->ExpectConnection(orig, resp, resp_p->Port(), resp_p->PortType(),
- (AnalyzerTag::Tag) analyzer, tout, 0);
- return new Val(1, TYPE_BOOL);
- %}
-
-# Disables the analyzer which raised the current event (if the analyzer
-# belongs to the given connection).
-function disable_analyzer%(cid: conn_id, aid: count%) : bool
- %{
- Connection* c = sessions->FindConnection(cid);
- if ( ! c )
- {
- reporter->Error("cannot find connection");
- return new Val(0, TYPE_BOOL);
- }
-
- Analyzer* a = c->FindAnalyzer(aid);
- if ( ! a )
- {
- reporter->Error("connection does not have analyzer specified to disable");
- return new Val(0, TYPE_BOOL);
- }
-
- a->Remove();
- return new Val(1, TYPE_BOOL);
- %}
-
-# Translate analyzer type into an ASCII string.
-function analyzer_name%(aid: count%) : string
- %{
- return new StringVal(Analyzer::GetTagName((AnalyzerTag::Tag) aid));
- %}
-
-function lookup_ID%(id: string%) : any
- %{
- ID* i = global_scope()->Lookup(id->CheckString());
- if ( ! i )
- return new StringVal("");
-
- if ( ! i->ID_Val() )
- return new StringVal("");
-
- return i->ID_Val()->Ref();
- %}
-
-# Stop propagating &synchronized accesses.
-function suspend_state_updates%(%) : any
- %{
- if ( remote_serializer )
- remote_serializer->SuspendStateUpdates();
- return 0;
- %}
-
-# Resume propagating &synchronized accesses.
-function resume_state_updates%(%) : any
- %{
- if ( remote_serializer )
- remote_serializer->ResumeStateUpdates();
- return 0;
- %}
-
-# Return ID of analyzer which raised current event, or 0 if none.
-function current_analyzer%(%) : count
- %{
- return new Val(mgr.CurrentAnalyzer(), TYPE_COUNT);
- %}
-
-# Returns Bro's process id.
-function getpid%(%) : count
- %{
- return new Val(getpid(), TYPE_COUNT);
- %}
-%%{
-#include
-%%}
-
-function syslog%(s: string%): any
- %{
- reporter->Syslog("%s", s->CheckString());
- return 0;
- %}
-
%%{
#ifdef USE_GEOIP
extern "C" {
@@ -3075,7 +3397,14 @@ static GeoIP* open_geoip_db(GeoIPDBTypes type)
#endif
%%}
-# Return a record with the city, region, and country of an IPv4 address.
+## Performs a geo-lookup of an IP address.
+## Requires Bro to be built with ``libgeoip``.
+##
+## a: The IP address to lookup.
+##
+## Returns: A record with country, region, city, latitude, and longitude.
+##
+## .. bro:see:: lookup_asn
function lookup_location%(a: addr%) : geo_location
%{
RecordVal* location = new RecordVal(geo_location);
@@ -3203,6 +3532,13 @@ function lookup_location%(a: addr%) : geo_location
return location;
%}
+## Performs an AS lookup of an IP address.
+##
+## a: The IP address to lookup.
+##
+## Returns: The number of the AS that contains *a*.
+##
+## .. bro:see:: lookup_location
function lookup_asn%(a: addr%) : count
%{
#ifdef USE_GEOIP
@@ -3267,181 +3603,6 @@ function lookup_asn%(a: addr%) : count
return new Val(0, TYPE_COUNT);
%}
-# Returns true if connection has been received externally.
-function is_external_connection%(c: connection%) : bool
- %{
- return new Val(c && c->IsExternal(), TYPE_BOOL);
- %}
-
-# Function equivalent of the &disable_print_hook attribute.
-function disable_print_hook%(f: file%): any
- %{
- f->DisablePrintHook();
- return 0;
- %}
-
-# Function equivalent of the &raw_output attribute.
-function enable_raw_output%(f: file%): any
- %{
- f->EnableRawOutput();
- return 0;
- %}
-
-%%{
-extern "C" {
-#include
-}
-%%}
-
-function identify_data%(data: string, return_mime: bool%): string
- %{
- const char* descr = "";
-
- static magic_t magic_mime = 0;
- static magic_t magic_descr = 0;
-
- magic_t* magic = return_mime ? &magic_mime : &magic_descr;
-
- if( ! *magic )
- {
- *magic = magic_open(return_mime ? MAGIC_MIME : MAGIC_NONE);
-
- if ( ! *magic )
- {
- reporter->Error("can't init libmagic: %s", magic_error(*magic));
- return new StringVal("");
- }
-
- if ( magic_load(*magic, 0) < 0 )
- {
- reporter->Error("can't load magic file: %s", magic_error(*magic));
- magic_close(*magic);
- *magic = 0;
- return new StringVal("");
- }
- }
-
- descr = magic_buffer(*magic, data->Bytes(), data->Len());
-
- return new StringVal(descr);
- %}
-
-function enable_event_group%(group: string%) : any
- %{
- event_registry->EnableGroup(group->CheckString(), true);
- return 0;
- %}
-
-function disable_event_group%(group: string%) : any
- %{
- event_registry->EnableGroup(group->CheckString(), false);
- return 0;
- %}
-
-
-%%{
-#include
-static map entropy_states;
-%%}
-
-function find_entropy%(data: string%): entropy_test_result
- %{
- double montepi, scc, ent, mean, chisq;
- montepi = scc = ent = mean = chisq = 0.0;
- RecordVal* ent_result = new RecordVal(entropy_test_result);
- RandTest *rt = new RandTest();
-
- rt->add((char*) data->Bytes(), data->Len());
- rt->end(&ent, &chisq, &mean, &montepi, &scc);
- delete rt;
-
- ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
- ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
- ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
- ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE));
- ent_result->Assign(4, new Val(scc, TYPE_DOUBLE));
- return ent_result;
- %}
-
-function entropy_test_init%(index: any%): bool
- %{
- BroString* s = convert_index_to_string(index);
- int status = 0;
-
- if ( entropy_states.count(*s) < 1 )
- {
- entropy_states[*s] = new RandTest();
- status = 1;
- }
-
- delete s;
- return new Val(status, TYPE_BOOL);
- %}
-
-function entropy_test_add%(index: any, data: string%): bool
- %{
- BroString* s = convert_index_to_string(index);
- int status = 0;
-
- if ( entropy_states.count(*s) > 0 )
- {
- entropy_states[*s]->add((char*) data->Bytes(), data->Len());
- status = 1;
- }
-
- delete s;
- return new Val(status, TYPE_BOOL);
- %}
-
-function entropy_test_finish%(index: any%): entropy_test_result
- %{
- BroString* s = convert_index_to_string(index);
- double montepi, scc, ent, mean, chisq;
- montepi = scc = ent = mean = chisq = 0.0;
- RecordVal* ent_result = new RecordVal(entropy_test_result);
-
- if ( entropy_states.count(*s) > 0 )
- {
- RandTest *rt = entropy_states[*s];
- rt->end(&ent, &chisq, &mean, &montepi, &scc);
- entropy_states.erase(*s);
- delete rt;
- }
-
- ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
- ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
- ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
- ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE));
- ent_result->Assign(4, new Val(scc, TYPE_DOUBLE));
-
- delete s;
- return ent_result;
- %}
-
-function bro_has_ipv6%(%) : bool
- %{
-#ifdef BROv6
- return new Val(1, TYPE_BOOL);
-#else
- return new Val(0, TYPE_BOOL);
-#endif
- %}
-
-function unique_id%(prefix: string%) : string
- %{
- char tmp[20];
- uint64 uid = calculate_unique_id(UID_POOL_DEFAULT_SCRIPT);
- return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
- %}
-
-function unique_id_from%(pool: int, prefix: string%) : string
- %{
- pool += UID_POOL_CUSTOM_SCRIPT; // Make sure we don't conflict with internal pool.
-
- char tmp[20];
- uint64 uid = calculate_unique_id(pool);
- return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
- %}
%%{
#include
#include
@@ -3467,6 +3628,21 @@ X509* d2i_X509_(X509** px, const u_char** in, int len)
%%}
+## Verifies a certificate.
+##
+## der_cert: The X.509 certificate in DER format.
+##
+## cert_stack: Specifies a certificate chain to validate against, with index 0
+## typically being the root CA. Bro uses the Mozilla root CA list
+## by default.
+##
+## root_certs: A list of additional root certificates that extends
+## *cert_stack*.
+##
+## Returns: A status code of the verification which can be converted into an
+## ASCII string via :bro:id:`x509_err2str`.
+##
+## .. bro:see:: x509_err2str
function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count
%{
X509_STORE* ctx = 0;
@@ -3547,11 +3723,24 @@ function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: tabl
return new Val((uint64) csc.error, TYPE_COUNT);
%}
+## Converts a certificate verification error code into an ASCII string.
+##
+## err_num: The error code.
+##
+## Returns: A string representation of *err_num*.
+##
+## .. bro:see:: x509_verify
function x509_err2str%(err_num: count%): string
%{
return new StringVal(X509_verify_cert_error_string(err_num));
%}
+## Converts UNIX file permissions given by a mode to an ASCII string.
+##
+## mode: The permisssions, e.g., 644 or 755.
+##
+## Returns: A string representation of *mode* in the format
+## ``rw[xsS]rw[xsS]rw[xtT]``.
function NFS3::mode2string%(mode: count%): string
%{
char str[12];
@@ -3638,41 +3827,999 @@ function NFS3::mode2string%(mode: count%): string
return new StringVal(str);
%}
-## Opens a program with popen() and writes a given string to the returned
-## stream to send it to the opened process's stdin.
-## program: a string naming the program to execute
-## to_write: a string to pipe to the opened program's process over stdin
-## Returns: F if popen'ing the program failed, else T
-function piped_exec%(program: string, to_write: string%): bool
+# ===========================================================================
+#
+# Controlling Analyzer Behavior
+#
+# ===========================================================================
+
+%%{
+#include "DPM.h"
+%%}
+
+## Schedules an analyzer for a future connection from a given IP address and
+## port. The function ignores the scheduling request if the connection did
+## not occur within the specified time interval.
+##
+## orig: The IP address originating a connection in the future.
+##
+## resp: The IP address responding to a connection from *orig*.
+##
+## resp_p: The destination port at *resp*.
+##
+## analyzer: The analyzer ID.
+##
+## tout: The timeout interval after which to ignore the scheduling request.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: disable_analyzer analyzer_name
+##
+## .. todo:: The return value should be changed to any.
+function expect_connection%(orig: addr, resp: addr, resp_p: port,
+ analyzer: count, tout: interval%) : bool
%{
- const char* prog = program->CheckString();
-
- FILE* f = popen(prog, "w");
- if ( ! f )
- {
- reporter->Error("Failed to popen %s", prog);
- return new Val(0, TYPE_BOOL);
- }
-
- const u_char* input_data = to_write->Bytes();
- int input_data_len = to_write->Len();
-
- int bytes_written = fwrite(input_data, 1, input_data_len, f);
-
- pclose(f);
-
- if ( bytes_written != input_data_len )
- {
- reporter->Error("Failed to write all given data to %s", prog);
- return new Val(0, TYPE_BOOL);
- }
-
+ dpm->ExpectConnection(orig, resp, resp_p->Port(), resp_p->PortType(),
+ (AnalyzerTag::Tag) analyzer, tout, 0);
return new Val(1, TYPE_BOOL);
%}
-## Enables the communication system. Note that by default,
-## communication is off until explicitly enabled, and all other calls
-## to communication-related BiFs' will be ignored until done so.
+## Disables the analyzer which raised the current event (if the analyzer
+## belongs to the given connection).
+##
+## cid: The connection identifier.
+##
+## aid: The analyzer ID.
+##
+## Returns: True if the connection identified by *cid* exists and has analyzer
+## *aid*.
+##
+## .. bro:see:: expect_connection analyzer_name
+function disable_analyzer%(cid: conn_id, aid: count%) : bool
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ {
+ reporter->Error("cannot find connection");
+ return new Val(0, TYPE_BOOL);
+ }
+
+ Analyzer* a = c->FindAnalyzer(aid);
+ if ( ! a )
+ {
+ reporter->Error("connection does not have analyzer specified to disable");
+ return new Val(0, TYPE_BOOL);
+ }
+
+ a->Remove();
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Translate an analyzer type to an ASCII string.
+##
+## aid: The analyzer ID.
+##
+## Returns: The analyzer *aid* as string.
+##
+## .. bro:see:: expect_connection disable_analyzer current_analyzer
+function analyzer_name%(aid: count%) : string
+ %{
+ return new StringVal(Analyzer::GetTagName((AnalyzerTag::Tag) aid));
+ %}
+
+## Informs Bro that it should skip any further processing of the contents of
+## a given connection. In particular, Bro will refrain from reassembling the
+## TCP byte stream and from generating events relating to any analyzers that
+## have been processing the connection.
+##
+## cid: The connection ID.
+##
+## Returns: False if *id* does not point to an active connection and true
+## otherwise.
+##
+## .. note::
+##
+## Bro will still generate connection-oriented events such as
+## :bro:id:`connection_finished`.
+function skip_further_processing%(cid: conn_id%): bool
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_BOOL);
+
+ c->SetSkip(1);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Controls whether packet contents belonging to a connection should be
+## recorded (when ``-w`` option is provided on the command line).
+##
+## cid: The connection identifier.
+##
+## do_record: True to enable packet contens and false to disable for the
+## connection identified by *cid*.
+##
+## Returns: False if *id* does not point to an active connection and true
+## otherwise.
+##
+## .. bro:see:: skip_further_processing
+##
+## .. note::
+##
+## This is independent of whether Bro processes the packets of this
+## connection, which is controlled separately by
+## :bro:id:`skip_further_processing`.
+##
+## .. bro:see: get_contents_file set_contents_file
+function set_record_packets%(cid: conn_id, do_record: bool%): bool
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_BOOL);
+
+ c->SetRecordPackets(do_record);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Associates a file handle with a connection for writing TCP byte stream
+## contents.
+##
+## cid: The connection ID.
+##
+## direction: Controls what sides of the connection to record. The argument can
+## take one the four values:
+##
+## - ``CONTENTS_NONE``: Stop recording the connection's content.
+## - ``CONTENTS_ORIG``: Record the data sent by the connection
+## originator (often the client).
+## - ``CONTENTS_RESP``: Record the data sent by the connection
+## responder (often the server).
+## - ``CONTENTS_BOTH``: Record the data sent in both directions.
+## Results in the two directions being
+## intermixed in the file, in the order the
+## data was seen by Bro.
+##
+## f: The file handle of the file to write the contents to.
+##
+## Returns: Returns false if *id* does not point to an active connection and
+## true otherwise.
+##
+## .. note::
+##
+## The data recorded to the file reflects the byte stream, not the
+## contents of individual packets. Reordering and duplicates are
+## removed. If any data is missing, the recording stops at the
+## missing data; this can happen, e.g., due to an
+## :bro:id:`ack_above_hole` event.
+##
+## .. bro:see: get_contents_file set_record_packets
+function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_BOOL);
+
+ c->GetRootAnalyzer()->SetContentsFile(direction, f);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Returns the file handle of the contents file of a connection.
+##
+## cid: The connection ID.
+##
+## direction: Controls what sides of the connection to record. SEe
+## :bro:id:`set_contents_file` for possible values.
+##
+## Returns: The :bro:type:`file` handle for the contentents file of the
+## connection identified by *cid*. If the connection exists
+## but no contents file for *direction*, the function generates a
+## error and returns a file handle to ``stderr``.
+##
+## .. bro:see: set_contents_file set_record_packets
+function get_contents_file%(cid: conn_id, direction: count%): file
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0;
+
+ if ( f )
+ {
+ Ref(f);
+ return new Val(f);
+ }
+
+ // Return some sort of error value.
+ if ( ! c )
+ builtin_error("unknown connection id in get_contents_file()", cid);
+ else
+ builtin_error("no contents file for given direction");
+
+ return new Val(new BroFile(stderr, "-", "w"));
+ %}
+
+## Sets an individual inactivity timeout for a connection and thus
+## overrides the global inactivity timeout.
+##
+## cid: The connection ID.
+##
+## t: The new inactivity timeout for the connection identified by *cid*.
+##
+## Returns: The previous timeout interval.
+function set_inactivity_timeout%(cid: conn_id, t: interval%): interval
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_INTERVAL);
+
+ double old_timeout = c->InactivityTimeout();
+ c->SetInactivityTimeout(t);
+
+ return new Val(old_timeout, TYPE_INTERVAL);
+ %}
+
+## Returns the state of the given login (Telnet or Rlogin) connection.
+##
+## cid: The connection ID.
+##
+## Returns: False if the connection is not active or is not tagged as a
+## login analyzer. Otherwise the function returns the state, which can
+## be one of:
+##
+## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its
+## initial authentication dialog.
+## - ``OGIN_STATE_LOGGED_IN``: The analyzer believes the user has
+## successfully authenticated.
+## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further
+## processing of the connection.
+## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it
+## does not correctly know the state of the connection, and/or
+## the username associated with it.
+##
+## .. bro:see: set_login_state
+function get_login_state%(cid: conn_id%): count
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_BOOL);
+
+ Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login);
+ if ( ! la )
+ return new Val(0, TYPE_BOOL);
+
+ return new Val(int(static_cast(la)->LoginState()),
+ TYPE_COUNT);
+ %}
+
+## Sets the login state of a connection with a login analyzer.
+##
+## cid: The connection ID.
+##
+## new_state: The new state of the login analyzer. See
+## :bro:id:`get_login_state` for possible values.
+##
+## Returns: Returns false if *cid* is not an active connection
+## or does not tagged as login analyzer, and true otherwise.
+##
+## .. bro:see: get_login_state
+function set_login_state%(cid: conn_id, new_state: count%): bool
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_BOOL);
+
+ Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login);
+ if ( ! la )
+ return new Val(0, TYPE_BOOL);
+
+ static_cast(la)->SetLoginState(login_state(new_state));
+ return new Val(1, TYPE_BOOL);
+ %}
+
+%%{
+#include "TCP.h"
+%%}
+
+## Get the originator sequence number of a TCP connection. Sequence numbers
+## are absolute (i.e., they reflect the values seen directly in packet headers;
+## they are not relative to the beginning of the connection).
+##
+## cid: The connection ID.
+##
+## Returns: The highest sequence number sent by a connection's originator, or 0
+## if *cid* does not point to an active TCP connection.
+##
+## .. bro:see:: get_resp_seq
+function get_orig_seq%(cid: conn_id%): count
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_COUNT);
+
+ if ( c->ConnTransport() != TRANSPORT_TCP )
+ return new Val(0, TYPE_COUNT);
+
+ Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP);
+ if ( tc )
+ return new Val(static_cast(tc)->OrigSeq(),
+ TYPE_COUNT);
+ else
+ {
+ reporter->Error("connection does not have TCP analyzer");
+ return new Val(0, TYPE_COUNT);
+ }
+ %}
+
+## Get the responder sequence number of a TCP connection. Sequence numbers
+## are absolute (i.e., they reflect the values seen directly in packet headers;
+## they are not relative to the beginning of the connection).
+##
+## cid: The connection ID.
+##
+## Returns: The highest sequence number sent by a connection's responder, or 0
+## if *cid* does not point to an active TCP connection.
+##
+## .. bro:see:: get_orig_seq
+function get_resp_seq%(cid: conn_id%): count
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( ! c )
+ return new Val(0, TYPE_COUNT);
+
+ if ( c->ConnTransport() != TRANSPORT_TCP )
+ return new Val(0, TYPE_COUNT);
+
+ Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP);
+ if ( tc )
+ return new Val(static_cast(tc)->RespSeq(),
+ TYPE_COUNT);
+ else
+ {
+ reporter->Error("connection does not have TCP analyzer");
+ return new Val(0, TYPE_COUNT);
+ }
+ %}
+
+%%{
+#include "SMTP.h"
+%%}
+
+## Skips SMTP data until the next email in a connection.
+##
+## c: The SMTP connection.
+##
+## .. bro:see:: skip_http_entity_data
+function skip_smtp_data%(c: connection%): any
+ %{
+ Analyzer* sa = c->FindAnalyzer(AnalyzerTag::SMTP);
+ if ( sa )
+ static_cast(sa)->SkipData();
+ return 0;
+ %}
+
+## Enables all event handlers in a given group. One can tag event handlers with
+## the :bro:attr:`&group` attribute to logically group them together, e.g,
+## ``event foo() &group="bar"``. This function enables all event handlers that
+## belong to such a group.
+##
+## group: The group.
+##
+## .. bro:see:: disable_event_group
+function enable_event_group%(group: string%) : any
+ %{
+ event_registry->EnableGroup(group->CheckString(), true);
+ return 0;
+ %}
+
+## Disables all event handlers in a given group.
+##
+## group: The group.
+##
+## .. bro:see:: enable_event_group
+function disable_event_group%(group: string%) : any
+ %{
+ event_registry->EnableGroup(group->CheckString(), false);
+ return 0;
+ %}
+
+# ===========================================================================
+#
+# Files and Directories
+#
+# ===========================================================================
+
+## Opens a file for writing. If a file with the same name already exists, this
+## function overwrites it (as opposed to :bro:id:`open_for_append`).
+##
+## f: The path to the file.
+##
+## Returns: A :bro:type:`file` handle for subsequent operations.
+##
+## .. bro:see;: active_file open_for_append close write_file
+## get_file_name set_buf flush_all mkdir enable_raw_output
+function open%(f: string%): file
+ %{
+ const char* file = f->CheckString();
+
+ if ( streq(file, "-") )
+ return new Val(new BroFile(stdout, "-", "w"));
+ else
+ return new Val(new BroFile(file, "w"));
+ %}
+
+## Opens a file for writing or appending. If a file with the same name already
+## exists, this function appends to it (as opposed to :bro:id:`open`).
+##
+## f: The path to the file.
+##
+## Returns: A :bro:type:`file` handle for subsequent operations.
+##
+## .. bro:see;: active_file open close write_file
+## get_file_name set_buf flush_all mkdir enable_raw_output
+function open_for_append%(f: string%): file
+ %{
+ return new Val(new BroFile(f->CheckString(), "a"));
+ %}
+
+## Closes an open file and flushes any buffered content.
+## exists, this function appends to it (as opposed to :bro:id:`open`).
+##
+## f: A :bro:type:`file` handle to an open file.
+##
+## Returns: True on success.
+##
+## .. bro:see;: active_file open open_for_append write_file
+## get_file_name set_buf flush_all mkdir enable_raw_output
+function close%(f: file%): bool
+ %{
+ return new Val(f->Close(), TYPE_BOOL);
+ %}
+
+## Writes data to an open file.
+##
+## f: A :bro:type:`file` handle to an open file.
+##
+## data: The data to write to *f*.
+##
+## Returns: True on success.
+##
+## .. bro:see;: active_file open open_for_append close
+## get_file_name set_buf flush_all mkdir enable_raw_output
+function write_file%(f: file, data: string%): bool
+ %{
+ if ( ! f )
+ return new Val(0, TYPE_BOOL);
+
+ return new Val(f->Write((const char*) data->Bytes(), data->Len()),
+ TYPE_BOOL);
+ %}
+
+## Alters the buffering behavior of a file.
+##
+## f: A :bro:type:`file` handle to an open file.
+##
+## buffered: When true, *f* is fully buffered, i.e., bytes are saved in a
+## buffered until the block size has been reached. When
+## false, *f* is line buffered, i.e., bytes are saved up until a
+## newline occurs.
+##
+## .. bro:see;: active_file open open_for_append close
+## get_file_name write_file flush_all mkdir enable_raw_output
+function set_buf%(f: file, buffered: bool%): any
+ %{
+ f->SetBuf(buffered);
+ return new Val(0, TYPE_VOID);
+ %}
+
+## Flushes all open files to disk.
+##
+## Returns: True on success.
+##
+## .. bro:see;: active_file open open_for_append close
+## get_file_name write_file set_buf mkdir enable_raw_output
+function flush_all%(%): bool
+ %{
+ return new Val(fflush(0) == 0, TYPE_BOOL);
+ %}
+
+## Creates a new directory.
+##
+## f: The directory name.
+##
+## Returns: Returns true if the operation succeeds and false if the
+## creation fails or if *f* exists already.
+##
+## .. bro:see;: active_file open_for_append close write_file
+## get_file_name set_buf flush_all enable_raw_output
+function mkdir%(f: string%): bool
+ %{
+ const char* filename = f->CheckString();
+ if ( mkdir(filename, 0777) < 0 && errno != EEXIST )
+ {
+ builtin_error("cannot create directory", @ARG@[0]);
+ return new Val(0, TYPE_BOOL);
+ }
+ else
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Checks whether a given file is open.
+##
+## f: The file to check.
+##
+## Returns: True if *f* is an open :bro:type:`file`.
+##
+## .. todo:: Rename to ``is_open``.
+function active_file%(f: file%): bool
+ %{
+ return new Val(f->IsOpen(), TYPE_BOOL);
+ %}
+
+## Gets the filename associated with a file handle.
+##
+## f: The file handle to inquire the name for.
+##
+## Returns: The filename associated with *f*.
+##
+## .. bro:see:: open
+function get_file_name%(f: file%): string
+ %{
+ if ( ! f )
+ return new StringVal("");
+
+ return new StringVal(f->Name());
+ %}
+
+## Rotates a file.
+##
+## f: An open file handle.
+##
+## Returns: Rotations statistics which include the original file name, the name
+## after the rotation, and the time when *f* was opened/closed.
+##
+## .. bro:see:: rotate_file_by_name calc_next_rotate
+function rotate_file%(f: file%): rotate_info
+ %{
+ RecordVal* info = f->Rotate();
+ if ( info )
+ return info;
+
+ // Record indicating error.
+ info = new RecordVal(rotate_info);
+ info->Assign(0, new StringVal(""));
+ info->Assign(1, new StringVal(""));
+ info->Assign(2, new Val(0, TYPE_TIME));
+ info->Assign(3, new Val(0, TYPE_TIME));
+
+ return info;
+ %}
+
+## Rotates a file identified by its name.
+##
+## f: The name of the file to rotate
+##
+## Returns: Rotations statistics which include the original file name, the name
+## after the rotation, and the time when *f* was opened/closed.
+##
+## .. bro:see:: rotate_file calc_next_rotate
+function rotate_file_by_name%(f: string%): rotate_info
+ %{
+ RecordVal* info = new RecordVal(rotate_info);
+
+ bool is_pkt_dumper = false;
+ bool is_addl_pkt_dumper = false;
+
+ // Special case: one of current dump files.
+ if ( pkt_dumper && streq(pkt_dumper->FileName(), f->CheckString()) )
+ {
+ is_pkt_dumper = true;
+ pkt_dumper->Close();
+ }
+
+ if ( addl_pkt_dumper &&
+ streq(addl_pkt_dumper->FileName(), f->CheckString()) )
+ {
+ is_addl_pkt_dumper = true;
+ addl_pkt_dumper->Close();
+ }
+
+ FILE* file = rotate_file(f->CheckString(), info);
+ if ( ! file )
+ {
+ // Record indicating error.
+ info->Assign(0, new StringVal(""));
+ info->Assign(1, new StringVal(""));
+ info->Assign(2, new Val(0, TYPE_TIME));
+ info->Assign(3, new Val(0, TYPE_TIME));
+ return info;
+ }
+
+ fclose(file);
+
+ if ( is_pkt_dumper )
+ {
+ info->Assign(2, new Val(pkt_dumper->OpenTime(), TYPE_TIME));
+ pkt_dumper->Open();
+ }
+
+ if ( is_addl_pkt_dumper )
+ info->Assign(2, new Val(addl_pkt_dumper->OpenTime(), TYPE_TIME));
+
+ return info;
+ %}
+
+## Calculates the duration until the next time a file is to be rotated, based
+## on a given rotate interval.
+##
+## i: The rotate interval to base the calculation on.
+##
+## Returns: The duration until the next file rotation time.
+##
+## .. bro:see:: rotate_file rotate_file_by_name
+function calc_next_rotate%(i: interval%) : interval
+ %{
+ const char* base_time = log_rotate_base_time ?
+ log_rotate_base_time->AsString()->CheckString() : 0;
+ return new Val(calc_next_rotate(i, base_time), TYPE_INTERVAL);
+ %}
+
+## Returns the size of a given file.
+##
+## f: The name of the file whose size to lookup.
+##
+## Returns: The size of *f* in bytes.
+function file_size%(f: string%) : double
+ %{
+ struct stat s;
+
+ if ( stat(f->CheckString(), &s) < 0 )
+ return new Val(-1.0, TYPE_DOUBLE);
+
+ return new Val(double(s.st_size), TYPE_DOUBLE);
+ %}
+
+## Disables sending :bro:id:`print_hook` events to remote peers for a given
+## file. This function is equivalent to :bro:attr:`&disable_print_hook`. In a
+## distributed setup, communicating Bro instances generate the event
+## :bro:id:`print_hook` for each print statement and send it to the remote
+## side. When disabled for a particular file, these events will not be
+## propagated to other peers.
+##
+## f: The file to disable :bro:id:`print_hook` events for.
+##
+## .. bro:see:: enable_raw_output
+function disable_print_hook%(f: file%): any
+ %{
+ f->DisablePrintHook();
+ return 0;
+ %}
+
+## Prevents escaping of non-ASCII character when writing to a file.
+## This function is equivalent to :bro:attr:`&disable_print_hook`.
+##
+## f: The file to disable raw output for.
+##
+## .. bro:see:: disable_print_hook
+function enable_raw_output%(f: file%): any
+ %{
+ f->EnableRawOutput();
+ return 0;
+ %}
+
+# ===========================================================================
+#
+# Packet Filtering
+#
+# ===========================================================================
+
+## Precompiles a PCAP filter and binds it to a given identifier.
+##
+## id: The PCAP identifier to reference the filter *s* later on.
+##
+## s: The PCAP filter. See ``man tcpdump`` for valid expressions.
+##
+## Returns: True if *s* is valid and precompiles successfully.
+##
+## .. bro:see:: install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool
+ %{
+ bool success = true;
+
+ loop_over_list(pkt_srcs, i)
+ {
+ pkt_srcs[i]->ClearErrorMsg();
+
+ if ( ! pkt_srcs[i]->PrecompileFilter(id->ForceAsInt(),
+ s->CheckString()) )
+ {
+ reporter->Error("precompile_pcap_filter: %s",
+ pkt_srcs[i]->ErrorMsg());
+ success = false;
+ }
+ }
+
+ return new Val(success, TYPE_BOOL);
+ %}
+
+## Installs a PCAP filter that has been precompiled with
+## :bro:id:`precompile_pcap_filter`.
+##
+## id: The PCAP filter id of a precompiled filter.
+##
+## Returns: True if the filter associated with *id* has been installed
+## successfully.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+function install_pcap_filter%(id: PcapFilterID%): bool
+ %{
+ bool success = true;
+
+ loop_over_list(pkt_srcs, i)
+ {
+ pkt_srcs[i]->ClearErrorMsg();
+
+ if ( ! pkt_srcs[i]->SetFilter(id->ForceAsInt()) )
+ success = false;
+ }
+
+ return new Val(success, TYPE_BOOL);
+ %}
+
+## Returns a string representation of the last PCAP error.
+##
+## Returns: A descriptive error message of the PCAP function that failed.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+function pcap_error%(%): string
+ %{
+ loop_over_list(pkt_srcs, i)
+ {
+ const char* err = pkt_srcs[i]->ErrorMsg();
+ if ( *err )
+ return new StringVal(err);
+ }
+
+ return new StringVal("no error");
+ %}
+
+## Installs a filter to drop packets from a given IP source address with
+## a certain probability if none of a given set of TCP flags are set.
+##
+## ip: The IP address to drop.
+##
+## tcp_flags: If none of these TCP flags are set, drop packets from *ip* with
+## probability *prob*.
+##
+## prob: The probability [0.0, 1.0] used to drop packets from *ip*.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+##
+## .. todo:: The return value should be changed to any.
+function install_src_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
+ %{
+ sessions->GetPacketFilter()->AddSrc(ip, tcp_flags, prob);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Installs a filter to drop packets originating from a given subnet with
+## a certain probability if none of a given set of TCP flags are set.
+##
+## snet: The subnet to drop packets from.
+##
+## tcp_flags: If none of these TCP flags are set, drop packets from *snet* with
+## probability *prob*.
+##
+## prob: The probability [0.0, 1.0] used to drop packets from *snet*.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+##
+## .. todo:: The return value should be changed to any.
+function install_src_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool
+ %{
+ sessions->GetPacketFilter()->AddSrc(snet, tcp_flags, prob);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Removes a source address filter.
+##
+## ip: The IP address for which a source filter was previously installed.
+##
+## Returns: True on success.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+function uninstall_src_addr_filter%(ip: addr%) : bool
+ %{
+ return new Val(sessions->GetPacketFilter()->RemoveSrc(ip), TYPE_BOOL);
+ %}
+
+## Removes a source subnet filter.
+##
+## snet: The subnet for which a source filter was previously installed.
+##
+## Returns: True on success.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+function uninstall_src_net_filter%(snet: subnet%) : bool
+ %{
+ return new Val(sessions->GetPacketFilter()->RemoveSrc(snet), TYPE_BOOL);
+ %}
+
+## Installs a filter to drop packets destined to a given IP address with
+## a certain probability if none of a given set of TCP flags are set.
+##
+## ip: Drop packets to this IP address.
+##
+## tcp_flags: If none of these TCP flags are set, drop packets to *ip* with
+## probability *prob*.
+##
+## prob: The probability [0.0, 1.0] used to drop packets to *ip*.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+##
+## .. todo:: The return value should be changed to any.
+function install_dst_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
+ %{
+ sessions->GetPacketFilter()->AddDst(ip, tcp_flags, prob);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Installs a filter to drop packets destined to a given subnet with
+## a certain probability if none of a given set of TCP flags are set.
+##
+## snet: Drop packets to this subnet.
+##
+## tcp_flags: If none of these TCP flags are set, drop packets to *snet* with
+## probability *prob*.
+##
+## prob: The probability [0.0, 1.0] used to drop packets to *snet*.
+##
+## Returns: True (unconditionally).
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## uninstall_dst_addr_filter
+## uninstall_dst_net_filter
+## pcap_error
+##
+## .. todo:: The return value should be changed to any.
+function install_dst_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool
+ %{
+ sessions->GetPacketFilter()->AddDst(snet, tcp_flags, prob);
+ return new Val(1, TYPE_BOOL);
+ %}
+
+## Removes a destination address filter.
+##
+## ip: The IP address for which a destination filter was previously installed.
+##
+## Returns: True on success.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_net_filter
+## pcap_error
+function uninstall_dst_addr_filter%(ip: addr%) : bool
+ %{
+ return new Val(sessions->GetPacketFilter()->RemoveDst(ip), TYPE_BOOL);
+ %}
+
+## Removes a destination subnet filter.
+##
+## snet: The subnet for which a destination filter was previously installed.
+##
+## Returns: True on success.
+##
+## .. bro:see:: precompile_pcap_filter
+## install_pcap_filter
+## install_src_addr_filter
+## install_src_net_filter
+## uninstall_src_addr_filter
+## uninstall_src_net_filter
+## install_dst_addr_filter
+## install_dst_net_filter
+## uninstall_dst_addr_filter
+## pcap_error
+function uninstall_dst_net_filter%(snet: subnet%) : bool
+ %{
+ return new Val(sessions->GetPacketFilter()->RemoveDst(snet), TYPE_BOOL);
+ %}
+
+# ===========================================================================
+#
+# Communication
+#
+# ===========================================================================
+
+## Enables the communication system. By default, the communication is off until
+## explicitly enabled, and all other calls to communication-related functions
+## will be ignored until done so.
function enable_communication%(%): any
%{
if ( bro_start_network_time != 0.0 )
@@ -3690,8 +4837,649 @@ function enable_communication%(%): any
return 0;
%}
-## Returns the Bro version string
-function bro_version%(%): string
+## Flushes in-memory state tagged with the :bro:attr:`&persistent` attribute
+## to disk. The function writes the state to the file ``.state/state.bst`` in
+## the directory where Bro was started.
+##
+## Returns: True on success.
+##
+## .. bro:see:: rescan_state
+function checkpoint_state%(%) : bool
%{
- return new StringVal(bro_version());
+ return new Val(persistence_serializer->WriteState(true), TYPE_BOOL);
%}
+
+## Reads persistent state from the \texttt{.state} directory and populates the
+## in-memory data structures accordingly. This function is the dual to
+## :bro:id:`checkpoint_state`.
+##
+## Returns: True on success.
+##
+## .. bro:see:: checkpoint_state
+function rescan_state%(%) : bool
+ %{
+ return new Val(persistence_serializer->ReadAll(false, true), TYPE_BOOL);
+ %}
+
+## Writes the binary event stream generated by the core to a given file.
+## Use the ``-x `` command line switch to replay saved events.
+##
+## filename: The name of the file which stores the events.
+##
+## Returns: True if opening the target file succeeds.
+##
+## .. bro:see:: capture_state_updates
+function capture_events%(filename: string%) : bool
+ %{
+ if ( ! event_serializer )
+ event_serializer = new FileSerializer();
+ else
+ event_serializer->Close();
+
+ return new Val(event_serializer->Open(
+ (const char*) filename->CheckString()), TYPE_BOOL);
+ %}
+
+## Writes state updates generated by :bro:attr:`&synchronized` variables to a
+## file.
+##
+## filename: The name of the file which stores the state updates.
+##
+## Returns: True if opening the target file succeeds.
+##
+## .. bro:see:: capture_events
+function capture_state_updates%(filename: string%) : bool
+ %{
+ if ( ! state_serializer )
+ state_serializer = new FileSerializer();
+ else
+ state_serializer->Close();
+
+ return new Val(state_serializer->Open(
+ (const char*) filename->CheckString()), TYPE_BOOL);
+ %}
+
+## Establishes a connection to a remote Bro or Broccoli instance.
+##
+## ip: The IP address of the remote peer.
+##
+## port: The port of the remote peer.
+##
+## our_class: If an non-empty string, the remote (listening) peer checks it
+## against its class name in its peer table and terminates the
+## connection if they don't match.
+##
+## retry: If the connection fails, try to reconnect with the peer after this
+## time interval.
+##
+## ssl: If true, uses SSL to encrypt the session.
+##
+## Returns: A locally unique ID of the new peer.
+##
+## .. bro:see:: disconnect
+## listen
+## request_remote_events
+## request_remote_sync
+## request_remote_logs
+## request_remote_events
+## set_accept_state
+## set_compression_level
+## send_state
+## send_id
+function connect%(ip: addr, p: port, our_class: string, retry: interval, ssl: bool%) : count
+ %{
+ return new Val(uint32(remote_serializer->Connect(ip, p->Port(),
+ our_class->CheckString(), retry, ssl)),
+ TYPE_COUNT);
+ %}
+
+## Terminate the connection with a peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True on success.
+##
+## .. bro:see:: connect listen
+function disconnect%(p: event_peer%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->CloseConnection(id), TYPE_BOOL);
+ %}
+
+## Subscribes to all events from a remote peer whose names match a given
+## pattern.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## handlers: The pattern describing the events to request from peer *p*.
+##
+## Returns: True on success.
+##
+## .. bro:see:: request_remote_sync
+## request_remote_logs
+## set_accept_state
+function request_remote_events%(p: event_peer, handlers: pattern%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->RequestEvents(id, handlers),
+ TYPE_BOOL);
+ %}
+
+## Requests synchronization of IDs with a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## auth: If true, the local instance considers its current state authoritative
+## and sends it to *p* right after the handshake.
+##
+## Returns: True on success.
+##
+## .. bro:see:: request_remote_events
+## request_remote_logs
+## set_accept_state
+function request_remote_sync%(p: event_peer, auth: bool%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->RequestSync(id, auth), TYPE_BOOL);
+ %}
+
+## Requests logs from a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True on success.
+##
+## .. bro:see:: request_remote_events
+## request_remote_sync
+function request_remote_logs%(p: event_peer%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->RequestLogs(id), TYPE_BOOL);
+ %}
+
+## Sets a boolean flag whether Bro accepts state from a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True on success.
+##
+## .. bro:see:: request_remote_events
+## request_remote_sync
+## set_compression_level
+function set_accept_state%(p: event_peer, accept: bool%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->SetAcceptState(id, accept),
+ TYPE_BOOL);
+ %}
+
+## Sets the compression level of the session with a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## level: Allowed values are in the range *[0, 9]*, where 0 is the default and
+## means no compression.
+##
+## Returns: True on success.
+##
+## .. bro:see:: set_accept_state
+function set_compression_level%(p: event_peer, level: count%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->SetCompressionLevel(id, level),
+ TYPE_BOOL);
+ %}
+
+## Listens on address a given IP address and port for remote connections.
+##
+## ip: The IP address to bind to.
+##
+## p: The TCP port to listen to.
+##
+## ssl: If true, Bro uses SSL to encrypt the session.
+##
+## Returns: True on success.
+##
+## .. bro:see:: connect disconnect
+function listen%(ip: addr, p: port, ssl: bool %) : bool
+ %{
+ return new Val(remote_serializer->Listen(ip, p->Port(), ssl), TYPE_BOOL);
+ %}
+
+## Checks whether the last raised event came from a remote peer.
+##
+## Returns: True if the last raised event came from a remote peer.
+function is_remote_event%(%) : bool
+ %{
+ return new Val(mgr.CurrentSource() != SOURCE_LOCAL, TYPE_BOOL);
+ %}
+
+## Sends all persistent state to a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True on success.
+##
+## .. bro:see:: send_id send_ping send_current_packet send_capture_filter
+function send_state%(p: event_peer%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(persistence_serializer->SendState(id, true), TYPE_BOOL);
+ %}
+
+## Sends a global identifier to a remote peer, which them might install it
+## locally.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## id: The identifier to send.
+##
+## Returns: True on success.
+##
+## .. bro:see:: send_state send_ping send_current_packet send_capture_filter
+function send_id%(p: event_peer, id: string%) : bool
+ %{
+ RemoteSerializer::PeerID pid = p->AsRecordVal()->Lookup(0)->AsCount();
+
+ ID* i = global_scope()->Lookup(id->CheckString());
+ if ( ! i )
+ {
+ reporter->Error("send_id: no global id %s", id->CheckString());
+ return new Val(0, TYPE_BOOL);
+ }
+
+ SerialInfo info(remote_serializer);
+ return new Val(remote_serializer->SendID(&info, pid, *i), TYPE_BOOL);
+ %}
+
+## Gracefully finishes communication by first making sure that all remaining
+## data from parent and child has been sent out.
+##
+## Returns: True if the termination process has been started successfully.
+function terminate_communication%(%) : bool
+ %{
+ return new Val(remote_serializer->Terminate(), TYPE_BOOL);
+ %}
+
+## Signals a remote peer that the local Bro instance finished the initial
+## handshake.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True on success.
+function complete_handshake%(p: event_peer%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->CompleteHandshake(id), TYPE_BOOL);
+ %}
+
+## Sends a ping event to a remote peer. In combination with an event handler
+## for :bro:id:`remote_pong`, this function can be used to measure latency
+## between two peers.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## seq: A sequence number (also included by :bro:id:`remote_pong`).
+##
+## Returns: True if sending the ping succeeds.
+##
+## .. bro:see:: send_state send_id send_current_packet send_capture_filter
+function send_ping%(p: event_peer, seq: count%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->SendPing(id, seq), TYPE_BOOL);
+ %}
+
+## Sends the currently processed packet to a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## Returns: True if sending the packet succeeds.
+##
+## .. bro:see:: send_id send_state send_ping send_capture_filter
+## dump_packet dump_current_packet get_current_packet
+function send_current_packet%(p: event_peer%) : bool
+ %{
+ Packet pkt("");
+
+ if ( ! current_pktsrc ||
+ ! current_pktsrc->GetCurrentPacket(&pkt.hdr, &pkt.pkt) )
+ return new Val(0, TYPE_BOOL);
+
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+
+ pkt.time = pkt.hdr->ts.tv_sec + double(pkt.hdr->ts.tv_usec) / 1e6;
+ pkt.hdr_size = current_pktsrc->HdrSize();
+ pkt.link_type = current_pktsrc->LinkType();
+
+ SerialInfo info(remote_serializer);
+ return new Val(remote_serializer->SendPacket(&info, id, pkt), TYPE_BOOL);
+ %}
+
+## Returns the peer who generated the last event.
+##
+## Returns: The ID of the peer who genereated the last event.
+##
+## .. bro:see:: get_local_event_peer
+function get_event_peer%(%) : event_peer
+ %{
+ SourceID src = mgr.CurrentSource();
+
+ if ( src == SOURCE_LOCAL )
+ {
+ RecordVal* p = mgr.GetLocalPeerVal();
+ Ref(p);
+ return p;
+ }
+
+ if ( ! remote_serializer )
+ reporter->InternalError("remote_serializer not initialized");
+
+ Val* v = remote_serializer->GetPeerVal(src);
+ if ( ! v )
+ {
+ reporter->Error("peer %d does not exist anymore", int(src));
+ RecordVal* p = mgr.GetLocalPeerVal();
+ Ref(p);
+ return p;
+ }
+
+ return v;
+ %}
+
+## Returns the local peer ID.
+##
+## Returns: The peer ID of the local Bro instance.
+##
+## .. bro:see:: get_event_peer
+function get_local_event_peer%(%) : event_peer
+ %{
+ RecordVal* p = mgr.GetLocalPeerVal();
+ Ref(p);
+ return p;
+ %}
+
+## Sends a capture filter to a remote peer.
+##
+## p: The peer ID return from :bro:id:`connect`.
+##
+## s: The capture filter.
+##
+## Returns: True if sending the packet succeeds.
+##
+## .. bro:see:: send_id send_state send_ping send_current_packet
+function send_capture_filter%(p: event_peer, s: string%) : bool
+ %{
+ RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount();
+ return new Val(remote_serializer->SendCaptureFilter(id, s->CheckString()), TYPE_BOOL);
+ %}
+
+## Stops Bro's packet processing. This function is used to synchronize
+## distributed trace processing with communication enabled
+## (*pseudo-realtime* mode).
+##
+## .. bro:see: continue_processing suspend_state_updates resume_state_updates
+function suspend_processing%(%) : any
+ %{
+ net_suspend_processing();
+ return 0;
+ %}
+
+## Resumes Bro's packet processing.
+##
+## .. bro:see: suspend_processing suspend_state_updates resume_state_updates
+function continue_processing%(%) : any
+ %{
+ net_continue_processing();
+ return 0;
+ %}
+
+## Stops propagating :bro:attr:`&synchronized` accesses.
+##
+## .. bro:see: suspend_processing continue_processing resume_state_updates
+function suspend_state_updates%(%) : any
+ %{
+ if ( remote_serializer )
+ remote_serializer->SuspendStateUpdates();
+ return 0;
+ %}
+
+## Resumes propagating :bro:attr:`&synchronized` accesses.
+##
+## .. bro:see: suspend_processing continue_processing suspend_state_updates
+function resume_state_updates%(%) : any
+ %{
+ if ( remote_serializer )
+ remote_serializer->ResumeStateUpdates();
+ return 0;
+ %}
+
+# ===========================================================================
+#
+# Internal Functions
+#
+# ===========================================================================
+
+## Manually triggers the signature engine for a given connection.
+## This is an internal function.
+function match_signatures%(c: connection, pattern_type: int, s: string,
+ bol: bool, eol: bool,
+ from_orig: bool, clear: bool%) : bool
+ %{
+ if ( ! rule_matcher )
+ return new Val(0, TYPE_BOOL);
+
+ c->Match((Rule::PatternType) pattern_type, s->Bytes(), s->Len(),
+ from_orig, bol, eol, clear);
+
+ return new Val(1, TYPE_BOOL);
+ %}
+
+# ===========================================================================
+#
+# Deprecated Functions
+#
+# ===========================================================================
+
+%%{
+#include "Anon.h"
+%%}
+
+## Preserves the prefix of an IP address in anonymization.
+##
+## a: The address to preserve.
+##
+## width: The number of bits from the top that should remain intact.
+##
+## .. bro:see:: preserve_subnet anonymize_addr
+##
+## .. todo:: Currently dysfunctional.
+function preserve_prefix%(a: addr, width: count%): any
+ %{
+ AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
+ if ( ip_anon )
+ {
+#ifdef BROv6
+ if ( ! is_v4_addr(a) )
+ builtin_error("preserve_prefix() not supported for IPv6 addresses");
+ else
+ ip_anon->PreservePrefix(a[3], width);
+#else
+ ip_anon->PreservePrefix(a, width);
+#endif
+ }
+
+
+ return 0;
+ %}
+
+## Preserves the prefix of a subnet in anonymization.
+##
+## a: The subnet to preserve.
+##
+## width: The number of bits from the top that should remain intact.
+##
+## .. bro:see:: preserve_prefix anonymize_addr
+##
+## .. todo:: Currently dysfunctional.
+function preserve_subnet%(a: subnet%): any
+ %{
+ DEBUG_MSG("%s/%d\n", dotted_addr(a->AsAddr()), a->Width());
+ AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
+ if ( ip_anon )
+ {
+#ifdef BROv6
+ if ( ! is_v4_addr(a->AsAddr()) )
+ builtin_error("preserve_subnet() not supported for IPv6 addresses");
+ else
+ ip_anon->PreservePrefix(a->AsAddr()[3], a->Width());
+#else
+ ip_anon->PreservePrefix(a->AsAddr(), a->Width());
+#endif
+ }
+
+ return 0;
+ %}
+
+## Anonymizes an IP address.
+##
+## a: The address to anonymize.
+##
+## cl: The anonymization class, which can take on three different values:
+##
+## - ``ORIG_ADDR``: Tag *a* as an originator address.
+##
+## - ``RESP_ADDR``: Tag *a* as an responder address.
+##
+## - ``OTHER_ADDR``: Tag *a* as an arbitrary address.
+##
+## Returns: An anonymized version of *a*.
+##
+## .. bro:see:: preserve_prefix preserve_subnet
+##
+## .. todo:: Currently dysfunctional.
+function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr
+ %{
+ int anon_class = cl->InternalInt();
+ if ( anon_class < 0 || anon_class >= NUM_ADDR_ANONYMIZATION_CLASSES )
+ builtin_error("anonymize_addr(): invalid ip addr anonymization class");
+
+#ifdef BROv6
+ if ( ! is_v4_addr(a) )
+ {
+ builtin_error("anonymize_addr() not supported for IPv6 addresses");
+ return 0;
+ }
+ else
+ return new AddrVal(anonymize_ip(a[3],
+ (enum ip_addr_anonymization_class_t) anon_class));
+#else
+ return new AddrVal(anonymize_ip(a,
+ (enum ip_addr_anonymization_class_t) anon_class));
+#endif
+ %}
+
+## Deprecated. Will be removed.
+function active_connection%(id: conn_id%): bool
+ %{
+ Connection* c = sessions->FindConnection(id);
+ return new Val(c ? 1 : 0, TYPE_BOOL);
+ %}
+
+## Deprecated. Will be removed.
+function connection_record%(cid: conn_id%): connection
+ %{
+ Connection* c = sessions->FindConnection(cid);
+ if ( c )
+ return c->BuildConnVal();
+ else
+ {
+ // Hard to recover from this until we have union types ...
+ builtin_error("connection ID not a known connection (fatal)", cid);
+ exit(0);
+ return 0;
+ }
+ %}
+
+## Deprecated. Will be removed.
+function dump_config%(%) : bool
+ %{
+ return new Val(persistence_serializer->WriteConfig(true), TYPE_BOOL);
+ %}
+
+## Deprecated. Will be removed.
+function make_connection_persistent%(c: connection%) : bool
+ %{
+ c->MakePersistent();
+ return new Val(1, TYPE_BOOL);
+ %}
+
+%%{
+// Experimental code to add support for IDMEF XML output based on
+// notices. For now, we're implementing it as a builtin you can call on an
+// notices record.
+
+#ifdef USE_IDMEF
+extern "C" {
+#include
+}
+#endif
+
+#include
+
+char* port_to_string(PortVal* port)
+ {
+ char buf[256]; // to hold sprintf results on port numbers
+ snprintf(buf, sizeof(buf), "%u", port->Port());
+ return copy_string(buf);
+ }
+
+%%}
+
+## Deprecated. Will be removed.
+function generate_idmef%(src_ip: addr, src_port: port,
+ dst_ip: addr, dst_port: port%) : bool
+ %{
+#ifdef USE_IDMEF
+ xmlNodePtr message =
+ newIDMEF_Message(newAttribute("version","1.0"),
+ newAlert(newCreateTime(NULL),
+ newSource(
+ newNode(newAddress(
+ newAttribute("category","ipv4-addr"),
+ newSimpleElement("address",
+ copy_string(dotted_addr(src_ip))),
+ NULL), NULL),
+ newService(
+ newSimpleElement("port",
+ port_to_string(src_port)),
+ NULL), NULL),
+ newTarget(
+ newNode(newAddress(
+ newAttribute("category","ipv4-addr"),
+ newSimpleElement("address",
+ copy_string(dotted_addr(dst_ip))),
+ NULL), NULL),
+ newService(
+ newSimpleElement("port",
+ port_to_string(dst_port)),
+ NULL), NULL), NULL), NULL);
+
+ // if ( validateCurrentDoc() )
+ printCurrentMessage(stderr);
+ return new Val(1, TYPE_BOOL);
+#else
+ builtin_error("Bro was not configured for IDMEF support");
+ return new Val(0, TYPE_BOOL);
+#endif
+ %}
+
+## Deprecated. Will be removed.
+function bro_has_ipv6%(%) : bool
+ %{
+#ifdef BROv6
+ return new Val(1, TYPE_BOOL);
+#else
+ return new Val(0, TYPE_BOOL);
+#endif
+ %}
diff --git a/src/const.bif b/src/const.bif
index 96630e300b..bc960caeb6 100644
--- a/src/const.bif
+++ b/src/const.bif
@@ -1,4 +1,6 @@
-# Documentation and default values for these are located in policy/bro.init.
+##! Declaration of various scripting-layer constants that the Bro core uses
+##! internally. Documentation and default values for the scripting-layer
+##! variables themselves are found in :doc:`/scripts/base/init-bare`.
const ignore_keep_alive_rexmit: bool;
const skip_http_data: bool;
diff --git a/src/event.bif b/src/event.bif
index beceaaa6e3..001f0b84f1 100644
--- a/src/event.bif
+++ b/src/event.bif
@@ -1,448 +1,6012 @@
+##! The events that the C/C++ core of Bro can generate. This is mostly
+##! consisting of high-level network events that protocol analyzers detect,
+##! but there are also several general-utility events generated by internal
+##! Bro frameworks.
+
+#
+# Documentation conventions:
+#
+# - Use past tense for activity that has already occured.
+#
+# - List parameters with an empty line in between.
+#
+# - Within the description, reference other parameters of the same events
+# as *arg*.
+#
+# - Order:
+#
+# - Short initial sentence (which doesn't need to be a sentence),
+# starting with "Generated ..."
+#
+# - Description
+#
+# - Parameters
+#
+# - .. bro:see::
+#
+# - .. note::
+#
+# - .. todo::
+
+## Generated at Bro initialization time. The event engine generates this
+## event just before normal input processing begins. It can be used to execute
+## one-time initialization code at startup. At the time a handler runs, Bro will
+## have executed any global initializations and statements.
+##
+## .. bro:see:: bro_done
+##
+## .. note::
+##
+## When a ``bro_init`` handler executes, Bro has not yet seen any input packets
+## and therefore :bro:id:`network_time` is not initialized yet. An artifact
+## of that is that any timer installed in a ``bro_init`` handler will fire
+## immediately with the first packet. The standard way to work around that is to
+## ignore the first time the timer fires and immediately reschedule.
+##
event bro_init%(%);
+
+## Generated at Bro termination time. The event engine generates this event when
+## Bro is about to terminate, either due to having exhausted reading its input
+## trace file(s), receiving a termination signal, or because Bro was run without
+## a network input source and has finished executing any global statements.
+##
+## .. bro:see:: bro_init
+##
+## .. note::
+##
+## If Bro terminates due to an invocation of :bro:id:`exit`, then this event is
+## not generated.
event bro_done%(%);
+## Generated when an internal DNS lookup reduces the same result as last time.
+## Bro keeps an internal DNS cache for host names and IP addresses it has
+## already resolved. This event is generated when subsequent lookup returns
+## the same result as stored in the cache.
+##
+## dm: A record describing the new resolver result (which matches the old one).
+##
+## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified
event dns_mapping_valid%(dm: dns_mapping%);
+
+## Generated when an internal DNS lookup got no answer even though it had succeeded he
+## past. Bro keeps an internal DNS cache for host names and IP addresses it has
+## already resolved. This event is generated when a subsequent lookup does not
+## produce an answer even though we have already stored a result in the cache.
+##
+## dm: A record describing the old resolver result.
+##
+## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_valid
event dns_mapping_unverified%(dm: dns_mapping%);
+
+## Generated when an internal DNS lookup succeeed but an earlier attempt not. had
+## had succeeded he past. Bro keeps an internal DNS cache for host names and IP
+## addresses it has already resolved. This event is generated when a subsequent
+## lookup produces an answer for a query that was marked as failed in the cache.
+##
+## dm: A record describing the new resolver result.
+##
+## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_unverified
+## dns_mapping_valid
event dns_mapping_new_name%(dm: dns_mapping%);
+
+## Generated when an internal DNS lookup returned zero answers even though it
+## had succeeded he past. Bro keeps an internal DNS cache for host names and IP
+## addresses it has already resolved. This event is generated when for a subsequent
+## lookup we received answer that however was empty even though we have
+## already stored a result in the cache.
+##
+## dm: A record describing the old resolver result.
+##
+## .. bro:see:: dns_mapping_altered dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid
event dns_mapping_lost_name%(dm: dns_mapping%);
-event dns_mapping_name_changed%(old_dm: dns_mapping, new_dm: dns_mapping%);
+
+## Generated when an internal DNS lookup produced a different result than in
+## past. Bro keeps an internal DNS cache for host names and IP addresses it has
+## already resolved. This event is generated when a subsequent lookup returns
+## a different answer than we have stored in the cache.
+##
+## dm: A record describing the new resolver result.
+##
+## old_addrs: Addresses that used to be part of the returned set for the query
+## described by *dm*, but are not anymore.
+##
+## new_addrs: Addresses that did not use to be part of the returned set for the
+## query described by *dm*, but now are.
+##
+## .. bro:see:: dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid
event dns_mapping_altered%(dm: dns_mapping, old_addrs: addr_set, new_addrs: addr_set%);
+## Generated for every new connection. The event is raised with the first packet
+## of a previously unknown connection. Bro uses a flow-based definition of
+## "connection" here that includes not only TCP sessions but also UDP and ICMP
+## flows.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_status_update connection_timeout
+## expected_connection_seen new_connection_contents partial_connection
+##
+## .. note::
+##
+## Handling this event is potentially expensive. For example, during a SYN
+## flooding attack, every spoofed SYN packet will lead to a new
+## event.
event new_connection%(c: connection%);
+
+## Generated when reassembly starts for a TCP connection. The event is raised
+## at the moment when Bro's TCP analyzer enables stream reassembly for a
+## connection.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_status_update connection_timeout
+## expected_connection_seen new_connection partial_connection
event new_connection_contents%(c: connection%);
-event new_packet%(c: connection, p: pkt_hdr%);
+
+## Generated for an unsuccessful connection attempt. The event is raised when an
+## originator unsuccessfully attempted to establish a connection. "Unsuccessful"
+## is defined as at least :bro:id:`tcp_attempt_delay` seconds having elapsed since
+## the originator first sent a connection establishment packet to the destination
+## without seeing a reply.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_established
+## connection_external connection_finished connection_first_ACK
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_attempt%(c: connection%);
+
+## Generated for an established TCP connection. The event is raised when the
+## initial 3-way TCP handshake has successfully finished for a connection.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_external connection_finished connection_first_ACK
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_established%(c: connection%);
+
+## Generated for a new active TCP connection if Bro did not see the initial
+## handshake. The event is raised when Bro has observed traffic from each endpoint,
+## but the activity did not begin with the usual connection establishment.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_status_update connection_timeout
+## expected_connection_seen new_connection new_connection_contents
+##
event partial_connection%(c: connection%);
+
+## Generated when a previously inactive endpoint attempts to close a TCP connection
+## via a normal FIN handshake or an abort RST sequence. When the endpoint sent
+## one of these packets, Bro waits :bro:id:`tcp_partial_close_delay` prior
+## to generating the event, to give the other endpoint a chance to close the
+## connection normally.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_partial_close%(c: connection%);
+
+## Generated for a TCP connection that finished normally. The event is raised
+## when a regular FIN handshake from both endpoints was observed.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_first_ACK
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_finished%(c: connection%);
+
+## Generated when one endpoint of a TCP connection attempted to gracefully close
+## the connection, but the other endpoint is in the TCP_INACTIVE state. This can
+## happen due to split routing, in which Bro only sees one side of a connection.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_half_finished%(c: connection%);
+
+## Generated for a rejected TCP connection. The event is raised when an originator
+## attempted to setup a TCP connection but the responder replied with a RST packet
+## denying it.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
+##
+## c: The connection.
+##
+## .. note::
+##
+## If the responder does not respond at all, :bro:id:`connection_attempt` is
+## raised instead. If the responder initially accepts the connection but aborts
+## it later, Bro first generates :bro:id:`connection_established` and then
+## :bro:id:`connection_reset`.
event connection_rejected%(c: connection%);
+
+## Generated when an endpoint aborted a TCP connection. The event is raised
+## when one endpoint of an established TCP connection aborted by sending a RST
+## packet.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reused
+## connection_state_remove connection_status_update connection_timeout
+## expected_connection_seen new_connection new_connection_contents
+## partial_connection
event connection_reset%(c: connection%);
+
+## Generated for each still-open connection when Bro terminates.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection bro_done
event connection_pending%(c: connection%);
+
+## Generated when a connection's internal state is about to be removed from
+## memory. Bro generates this event reliably once for every connection when it
+## is about to delete the internal state. As such, the event is well-suited for
+## scrip-level cleanup that needs to be performed for every connection. The
+## ``connection_state_remove`` event is generated not only for TCP sessions but
+## also for UDP and ICMP flows.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection udp_inactivity_timeout
+## tcp_inactivity_timeout icmp_inactivity_timeout conn_stats
event connection_state_remove%(c: connection%);
+
+## Generated for a SYN packet. Bro raises this event for every SYN packet seen by
+## its TCP analyzer.
+##
+## c: The connection.
+##
+## pkt: Information extracted from the SYN packet.
+##
+## .. bro:see:: connection_EOF connection_attempt connection_established
+## connection_external connection_finished connection_first_ACK
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
+##
+## .. note::
+##
+## This event has quite low-level semantics and can potentially be expensive to
+## generate. It should only be used if one really needs the specific information
+## passed into the handler via the ``pkt`` argument. If not, handling one of the
+## other ``connection_*`` events is typically the better approach.
event connection_SYN_packet%(c: connection, pkt: SYN_packet%);
+
+## Generated for the first ACK packet seen for a TCP connection from
+## its *orginator*.
+##
+## c: The connection.
+##
+## pkt: Information extracted from the SYN packet.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
+##
+## .. note::
+##
+## This event has quite low-level semantics and should be used only rarely.
event connection_first_ACK%(c: connection%);
+
+## Generated when a TCP connection timed out. This event is raised when no activity
+## was seen for an interval of at least :bro:id:`tcp_connection_linger`, and
+## either one endpoint has already closed the connection or one side never
+## never became active.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_status_update expected_connection_seen
+## new_connection new_connection_contents partial_connection
+##
+## .. note::
+##
+## The precise semantics of this event can be unintuitive as it only
+## covers a subset of cases where a connection times out. Often, handling
+## :bro:id:`connection_state_remove` is the better option. That one will be
+## generated reliably when an interval of ``tcp_inactivity_timeout`` has passed
+## with out any activity seen (but also for all other ways a connection may
+## terminate).
event connection_timeout%(c: connection%);
+
+## Generated when a connection 4-tuple is reused. The event is raised when Bro
+## sees a new TCP session or UDP flow using a 4-tuple matching that of an earlier
+## connection it still consideres active.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_reused%(c: connection%);
+
+## Generated in regular intervals during the life time of a connection. The
+## events is raised each ``connection_status_update_interval`` seconds
+## and can be used to check conditions on a regular basis.
+##
+## c: The connection.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_status_update%(c: connection%);
+
+## Generated at the end of reassembled TCP connections. The TCP reassembler
+## raised the event once for each endpoint of a connection when it finished
+## reassembling the corresponding side of the communication.
+##
+## c: The connection.
+##
+## is_orig: True if the event is raised for the originator side.
+##
+## .. bro:see:: connection_SYN_packet connection_attempt connection_established
+## connection_external connection_finished connection_first_ACK
+## connection_half_finished connection_partial_close connection_pending
+## connection_rejected connection_reset connection_reused connection_state_remove
+## connection_status_update connection_timeout expected_connection_seen
+## new_connection new_connection_contents partial_connection
event connection_EOF%(c: connection, is_orig: bool%);
+
+## Generated for a new connection received from the communication subsystem. Remote
+## peers can inject packets into Bro's packet loop, for example via :doc:`Broccoli
+## `. The communication systems raises this event
+## with the first packet of a connection coming in this way.
event connection_external%(c: connection, tag: string%);
+
+## Generated when a connected is seen that has previously marked as being expected.
+## The function :bro:id:`expect_connection` tells Bro to expect a particular
+## connection to come up, and which analyzer to associate with it. Once the
+## first packet of such a connection is indeed seen, this event is raised.
+##
+## c: The connection.
+##
+## a: The analyzer that was scheduled for the connection with the
+## :bro:id:`expect_connection` call. When the event is raised, that
+## analyzer will already have been activated to process the connection. The
+## ``count`` is one of the ``ANALYZER_*`` constants, e.g., ``ANALYZER_HTTP``.
+##
+## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
+## connection_established connection_external connection_finished
+## connection_first_ACK connection_half_finished connection_partial_close
+## connection_pending connection_rejected connection_reset connection_reused
+## connection_state_remove connection_status_update connection_timeout
+## new_connection new_connection_contents partial_connection
+##
+## .. todo: We don't have a good way to document the automatically generated
+## ``ANALYZER_*`` constants right now.
event expected_connection_seen%(c: connection, a: count%);
+## Generated for every packet Bro sees. This is a very low-level and expensive
+## event that should be avoided when at all possible. Is's usually infeasible to
+## handle when processing even medium volumes of traffic in real-time. That
+## said, if you work from a trace and want to do some packet-level analysis,
+## it may come in handy.
+##
+## c: The connection the packet is part of.
+##
+## p: Informattion from the header of the packet that triggered the event.
+##
+## .. bro:see:: tcp_packet packet_contents
+event new_packet%(c: connection, p: pkt_hdr%);
+
+## Generated for every packet that has non-empty transport-layer payload. This is a
+## very low-level and expensive event that should be avoided when at all possible.
+## It's usually infeasible to handle when processing even medium volumes of
+## traffic in real-time. It's even worse than :bro:id:`new_packet`. That said, if
+## you work from a trace and want to do some packet-level analysis, it may come in
+## handy.
+##
+## c: The connection the packet is part of.
+##
+## contants: The raw transport-layer payload.
+##
+## .. bro:see:: new_packet tcp_packet
+event packet_contents%(c: connection, contents: string%);
+
+## Generated for every TCP packet. This is a very low-level and expensive event
+## that should be avoided when at all possible. It's usually infeasible to handle
+## when processing even medium volumes of traffic in real-time. It's slightly
+## better than :bro:id:`new_packet` because it affects only TCP, but not much. That
+## said, if you work from a trace and want to do some packet-level analysis, it may
+## come in handy.
+##
+## c: The connection the packet is part of.
+##
+## is_orig: True if the packet was sent by the connection's originator.
+##
+## flags: A string with the packet's TCP flags. In the string, each character
+## corresponds to one set flag, as follows: ``S`` -> SYN; ``F`` -> FIN;
+## ``R`` -> RST; ``A`` -> ACK; ``P`` -> PUSH.
+##
+## seq: The packet's TCP sequence number.
+##
+## ack: The packet's ACK number.
+##
+## len: The length of the TCP payload, as specified in the packet header.
+##
+## payload: The raw TCP payload. Note that this may less than *len* if the packet
+## was not fully captured.
+##
+## .. bro:see:: new_packet packet_contents tcp_option tcp_contents tcp_rexmit
+event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%);
+
+## Generated for each option found in a TCP header. Like many of the ``tcp_*``
+## events, this is a very low-level event and potentially expensive as it may
+## be raised very often.
+##
+## c: The connection the packet is part of.
+##
+## is_orig: True if the packet was sent by the connection's originator.
+##
+## opt: The numerical option number, as found in the TCP header.
+##
+## optlen: The length of the options value.
+##
+## .. bro:see:: tcp_packet tcp_contents tcp_rexmit
+##
+## .. note:: There is currently no way to get the actual option value, if any.
+event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%);
+
+## Generated for each chunk of reassembled TCP payload. When content delivery is
+## enabled for a TCP connection (via :bro:id:`tcp_content_delivery_ports_orig`,
+## :bro:id:`tcp_content_delivery_ports_resp`,
+## :bro:id:`tcp_content_deliver_all_orig`,
+## :bro:id:`tcp_content_deliver_all_resp`), this event is raised for each chunk
+## of in-order payload reconstructed from the packet stream. Note that this event
+## is potentially expensive if many connections carry signficant amounts of data as
+## then all that needs to be passed on to the scripting layer.
+##
+## c: The connection the payload is part of.
+##
+## is_orig: True if the packet was sent by the connection's originator.
+##
+## seq: The sequence number corresponding to the first byte of the payload
+## chunk.
+##
+## payload: The raw payload, which will be non-empty.
+##
+## .. bro:see:: tcp_packet tcp_option tcp_rexmit
+## tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp
+## tcp_content_deliver_all_resp tcp_content_deliver_all_orig
+##
+## .. note::
+##
+## The payload received by this event is the same that is also passed into
+## application-layer protocol analyzers internally. Subsequent invocations of
+## this event for the same connection receive non-overlapping in-order chunks
+## of its TCP payload stream. It is however undefined what size each chunk
+## has; while Bro passes the data on as soon as possible, specifics depend on
+## network-level effects such as latency, acknowledgements, reordering, etc.
+event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%);
+
+## Generated
+event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%);
+
+## Generated when Bro detects a TCP retransmission inconsistency. When
+## reassemling TCP stream, Bro buffers all payload until it seens the responder
+## acking it. If during time, the sender resends a chunk of payload but with
+## content than originally, this event will be raised.
+##
+## c: The connection showing the inconsistency.
+##
+## t1: The original payload.
+##
+## t2: The new payload.
+##
+## .. bro:see:: tcp_rexmit tcp_contents
+event rexmit_inconsistency%(c: connection, t1: string, t2: string%);
+
+## Generated when a TCP endpoint acknowledges payload that Bro did never see.
+##
+## c: The connection.
+##
+## .. bro:see:: content_gap
+##
+## .. note::
+##
+## Seeing an acknowledgment indicates that the responder of the connection
+## says it has received the corresponding data. If Bro did not, it must have
+## either missed one or more packets, or the responder's TCP stack is broken
+## (which isn't unheard of). In practice, one will always see a few of these
+## events in any larger volume of network traffic. If there are lots of them,
+## however, that typically means that there is a problem with the monitoring
+## infrastructure such as a tap dropping packets, split routing on the path, or
+## reordering at the tap.
+##
+## This event reports similar situations as :bro:id:`content_gap`, though their
+## specifics differ slightly. Often, however, both will be raised for the same
+## connection if some of its data is missing. We should eventually merge
+## the two.
+event ack_above_hole%(c: connection%);
+
+## Generated when Bro detects a gap in a reassembled TCP payload stream. This event
+## is raised when Bro, while reassemling a payload stream, determines that a chunk
+## of payload is missing (e.g., because the responder has already acknowledged it,
+## even though Bro didn't see it).
+##
+## c: The connection.
+##
+## is_orig: True if the gap is on the originator's side.
+##
+## seq: The sequence number where the gap starts.
+##
+## length: The number of bytes missing.
+##
+## .. bro:see:: ack_above_hole
+##
+## .. note::
+##
+## Content gaps tend to occur occasionally for various reasons, including broken
+## TCP stacks. If, however, one finds lots of them, that typically means that
+## there is a problem with the monitoring infrastructure such as a tap dropping
+## packets, split routing on the path, or reordering at the tap.
+##
+## This event reports similar situations as :bro:id:`ack_above_hole`, though
+## their specifics differ slightly. Often, however, both will be raised for
+## connection if some of its data is missing. We should eventually merge the
+## two.
+event content_gap%(c: connection, is_orig: bool, seq: count, length: count%);
+
+## Summarizes the amount of missing TCP payload at regular intervals. Internally,
+## Bro tracks (1) the number of :bro:id:`ack_above_hole` events, including the
+## numer of bytes missing; and (2) the total number of TCP acks seen, with the
+## total volume of bytes that have been acked. This event reports these statistics
+## in :bro:id:`gap_report_freq` intervals for the purpose of determining packet
+## loss.
+##
+## dt: The time that has past since the last ``gap_report`` interval.
+##
+## info: The gap statistics.
+##
+## .. bro:see:: content_gap ack_above_hole
+##
+## .. note::
+##
+## Bro comes with a script :doc:`/scripts/policy/misc/capture-loss` that uses
+## this event to estimate packet loss and report when a predefined threshold is
+## exceeded.
+event gap_report%(dt: interval, info: gap_info%);
+
+
+## Generated when a protocol analyzer confirms that a connection is indeed
+## using that protocol. Bro's dynamic protocol detection heuristically activates
+## analyzers as soon as it believe a connection *could* be using a particular
+## protocol. It is then left to the corresponding analyzer to verify whether that
+## is indeed the case; if so, this event will be generated.
+##
+## c: The connection.
+##
+## atype: The type of the analyzer confirming that its protocol is in
+## use. The value is one of the ``ANALYZER_*`` constants. For example,
+## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed
+## parsing an HTTP connection.
+##
+## aid: A unique integer ID identifying the specific *instance* of the
+## analyzer *atype* that is analyzing the connection ``c``. The ID can
+## be used to reference the analyzer when using builtin functions like
+## :bro:id:`disable_analyzer`.
+##
+## .. bro:see:: protocol_violation
+##
+## .. note::
+##
+## Bro's default scripts use this event to determine the ``service`` column of
+## :bro:type:`Conn::Info`: once confirmed, the protocol will be listed there
+## (and thus in ``conn.log``).
event protocol_confirmation%(c: connection, atype: count, aid: count%);
+
+## Generated when a protocol analyzer determines that a connection it is parsing
+## is not conforming to the protocol it expects. Bro's dynamic protocol detection
+## heuristically activates analyzers as soon as it believe a connection *could* be
+## using a particular protocol. It is then left to the corresponding analyzer to
+## verify whether that is indeed the case; if not, the analyzer will trigger this
+## event.
+##
+## c: The connection.
+##
+## atype: The type of the analyzer confirming that its protocol is in
+## use. The value is one of the ``ANALYZER_*`` constants. For example,
+## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed
+## parsing an HTTP connection.
+##
+## aid: A unique integer ID identifying the specific *instance* of the
+## analyzer *atype* that is analyzing the connection ``c``. The ID can
+## be used to reference the analyzer when using builtin functions like
+## :bro:id:`disable_analyzer`.
+##
+## .. bro:see:: protocol_confirmation
+##
+## .. note::
+##
+## Bro's default scripts use this event to disable an analyzer via
+## :bro:id:`disable_analyzer` if it's parsing the wrong protocol. That's however
+## a script-level decision and not done automatically by the event eninge.
event protocol_violation%(c: connection, atype: count, aid: count, reason: string%);
-event packet_contents%(c: connection, contents: string%);
-event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%);
-event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%);
-event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%);
-event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%);
+## Generated for each packet sent by a UDP flow's originator. This a potentially
+## expsensive event due to the volume of UDP traffic and should be used with care.
+##
+## u: The connection record for the corresponding UDP flow.
+##
+## .. bro:see:: udp_contents udp_reply udp_session_done
event udp_request%(u: connection%);
-event udp_reply%(u: connection%);
-event udp_contents%(u: connection, is_orig: bool, contents: string%);
-event udp_session_done%(u: connection%);
-event icmp_sent%(c: connection, icmp: icmp_conn%);
-event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%);
-event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%);
-event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
-event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
-event icmp_redirect%(c: connection, icmp: icmp_conn, a: addr%);
-event conn_stats%(c: connection, os: endpoint_stats, rs: endpoint_stats%);
-event conn_weird%(name: string, c: connection, addl: string%);
-event flow_weird%(name: string, src: addr, dst: addr%);
-event net_weird%(name: string%);
-event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%);
-event rexmit_inconsistency%(c: connection, t1: string, t2: string%);
-event ack_above_hole%(c: connection%);
-event content_gap%(c: connection, is_orig: bool, seq: count, length: count%);
-event gap_report%(dt: interval, info: gap_info%);
-event inconsistent_option%(c: connection%);
-event bad_option%(c: connection%);
-event bad_option_termination%(c: connection%);
+## Generated for each packet sent by a UDP flow's responder. This a potentially
+## expsensive event due to the volume of UDP traffic and should be used with care.
+##
+## u: The connection record for the corresponding UDP flow.
+##
+## .. bro:see:: udp_contents udp_request udp_session_done
+event udp_reply%(u: connection%);
+
+## Generated for UDP packets to pass on their payload. As the number of UDP
+## packets can be very large, this event is normally raised only for those on
+## ports configured in :bro:id:`udp_content_delivery_ports_orig` (for packets sent
+## by the flow's orgininator) or :bro:id:`udp_content_delivery_ports_resp` (for
+## packets sent by the flow's responder). However, delivery can be enabled for all
+## UDP request and reply packets by setting :bro:id:`udp_content_deliver_all_orig`
+## or :bro:id:`udp_content_deliver_all_resp`, respectively. Note that this event is
+## also raised for all matching UDP packets, including empty ones.
+##
+## u: The connection record for the corresponding UDP flow.
+##
+## is_orig: True if the event is raised for the originator side.
+##
+## .. bro:see:: udp_reply udp_request udp_session_done
+## udp_content_deliver_all_orig udp_content_deliver_all_resp
+## udp_content_delivery_ports_orig udp_content_delivery_ports_resp
+event udp_contents%(u: connection, is_orig: bool, contents: string%);
+
+## Generated when a UDP session for a supported protocol has finished. Some of
+## Bro's application-layer UDP analyzers flag the end of a session by raising this
+## event. Currently, the analyzers for DNS, NTP, Netbios, and Syslog support this.
+##
+## u: The connection record for the corresponding UDP flow.
+##
+## .. bro:see:: udp_contents udp_reply udp_request
+event udp_session_done%(u: connection%);
+
+## Generated for all ICMP messages that are not handled separetely with dedicated
+## ICMP events. Bro's ICMP analyzer handles a number of ICMP messages directly
+## with dedicated events. This handlers acts as a fallback for those it doesn't.
+## The *icmp* record provides more information about the message.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard
+## connection record *c*.
+##
+## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect
+## icmp_time_exceeded icmp_unreachable
+event icmp_sent%(c: connection, icmp: icmp_conn%);
+
+## Generated for ICMP *echo request* messages.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard
+## connection record *c*.
+##
+## id: The *echo request* identifier.
+##
+## seq: The *echo request* sequence number.
+##
+## payload: The message-specific data of the packet payload, i.e., everything after
+## the first 8 bytes of the ICMP header.
+##
+## .. bro:see:: icmp_echo_reply icmp_redirect icmp_sent
+## icmp_time_exceeded icmp_unreachable
+event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%);
+
+## Generated for ICMP *echo reply* messages.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard connection
+## record *c*.
+##
+## id: The *echo reply* identifier.
+##
+## seq: The *echo reply* sequence number.
+##
+## payload: The message-specific data of the packet payload, i.e., everything after
+## the first 8 bytes of the ICMP header.
+##
+## .. bro:see:: icmp_echo_request icmp_redirect icmp_sent
+## icmp_time_exceeded icmp_unreachable
+event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%);
+
+## Generated for ICMP *destination unreachable* messages.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard connection
+## record *c*.
+##
+## code: The ICMP code of the *unreachable* message.
+##
+## context: A record with specifics of the original packet that the message refers
+## to. *Unreachable* messages should include the original IP header from the packet
+## that triggered them, and Bro parses that into the *context* structure. Note
+## that if the *unreachable* includes only a partial IP header for some reason, no
+## fields of *context* will be filled out.
+##
+## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent
+## icmp_time_exceeded
+event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
+
+## Generated for ICMP *time exceeded* messages.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard connection
+## record *c*.
+##
+## code: The ICMP code of the *exceeded* message.
+##
+## context: A record with specifics of the original packet that the message refers
+## to. *Unreachable* messages should include the original IP header from the packet
+## that triggered them, and Bro parses that into the *context* structure. Note that
+## if the *exceeded* includes only a partial IP header for some reason, no fields
+## of *context* will be filled out.
+##
+## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent
+## icmp_unreachable
+event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
+
+## Generated for ICMP *redirect* messages.
+##
+## See `Wikipedia
+## `__ for more
+## information about the ICMP protocol.
+##
+## c: The connection record for the corresponding ICMP flow.
+##
+## icmp: Additional ICMP-specific information augmenting the standard connection
+## record *c*.
+##
+## a: The new destination address the message is redirecting to.
+##
+## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent
+## icmp_time_exceeded icmp_unreachable
+event icmp_redirect%(c: connection, icmp: icmp_conn, a: addr%);
+
+## Generated when a TCP connection terminated, passing on statistics about the
+## two endpoints. This event is always generated when Bro flushes the internal
+## connection state, independent of how a connection terminates.
+##
+## c: The connection.
+##
+## os: Statistics for the originator endpoint.
+##
+## rs: Statistics for the responder endpoint.
+##
+## .. bro:see:: connection_state_remove
+event conn_stats%(c: connection, os: endpoint_stats, rs: endpoint_stats%);
+
+## Generated for unexpected activity related to a specific connection. When
+## Bro's packet analysis encounters activity that does not conform to a protocol's
+## specification, it raises one of the ``*_weird`` events to report that. This
+## event is raised if the activity is tied directly to a specific connection.
+##
+## name: A unique name for the specific type of "weird" situation. Bro's default
+## scripts use this name in filtering policies that specify which "weirds" are
+## worth reporting.
+##
+## c: The corresponding connection.
+##
+## addl: Optional additional context further describing the situation.
+##
+## .. bro:see:: flow_weird net_weird
+##
+## .. note:: "Weird" activity is much more common in real-world network traffic
+## than one would intuitively expect. While in principle, any protocol violation
+## could be an attack attempt, it's much more likely that an endpoint's
+## implementation interprets an RFC quite liberally.
+event conn_weird%(name: string, c: connection, addl: string%);
+
+## Generated for unexpected activity related to a pair of hosts, but independent
+## of a specific connection. When Bro's packet analysis encounters activity that
+## does not conform to a protocol's specification, it raises one of the ``*_weird``
+## event to report that. This event is raised if the activity is related to a
+## pair of hosts, yet not to a specific connection between them.
+##
+## name: A unique name for the specific type of "weird" situation. Bro's default
+## scripts use this name in filtering policies that specify which "weirds" are
+## worth reporting.
+##
+## src: The source address corresponding to the activity.
+##
+## dst: The destination address corresponding to the activity.
+##
+## .. bro:see:: conn_weird net_weird
+##
+## .. note:: "Weird" activity is much more common in real-world network traffic
+## than one would intuitively expect. While in principle, any protocol violation
+## could be an attack attempt, it's much more likely that an endpoint's
+## implementation interprets an RFC quite liberally.
+event flow_weird%(name: string, src: addr, dst: addr%);
+
+## Generated for unexpected activity that is not tied to a specific connection
+## or pair of hosts. When Bro's packet analysis encounters activity that
+## does not conform to a protocol's specification, it raises one of the
+## ``*_weird`` event to report that. This event is raised if the activity is
+## not tied directly to a specific connection or pair of hosts.
+##
+## name: A unique name for the specific type of "weird" situation. Bro's default
+## scripts use this name in filtering policies that specify which "weirds" are
+## worth reporting.
+##
+## .. bro:see:: flow_weird
+##
+## .. note:: "Weird" activity is much more common in real-world network traffic
+## than one would intuitively expect. While in principle, any protocol violation
+## could be an attack attempt, it's much more likely that an endpoint's
+## implementation interprets an RFC quite liberally.
+event net_weird%(name: string%);
+
+## Generated regularly for the purpose of profiling Bro's processing. This event
+## is raised for every :bro:id:`load_sample_freq` packet. For these packets,
+## Bro records script-level functions executed during their processing as well as
+## further internal locations. By sampling the processing in this form, one can
+## understand where Bro spends its time.
+##
+## samples: A set with functions and locations seens during the processing of
+## the sampled packet.
+##
+## CPU: The CPU time spent on processing the sampled.
+##
+## dmem: The difference in memory usage caused by processing the sampled packet.
+event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%);
+
+## Generated for ARP requests.
+##
+## See `Wikipedia `__ for
+## more information about the ARP protocol.
+##
+## mac_src: The request's source MAC address.
+##
+## mac_dst: The request's destination MAC address.
+##
+## SPA: The sender protocol address.
+##
+## SHA: The sender hardware address.
+##
+## TPA: The target protocol address.
+##
+## THA: The target hardware address.
+##
+## .. bro:see:: arp_reply bad_arp
event arp_request%(mac_src: string, mac_dst: string, SPA: addr, SHA: string,
TPA: addr, THA: string%);
+
+## Generated for ARP replies.
+##
+## See `Wikipedia `__ for
+## more information about the ARP protocol.
+##
+## mac_src: The replies's source MAC address.
+##
+## mac_dst: The replies's destination MAC address.
+##
+## SPA: The sender protocol address.
+##
+## SHA: The sender hardware address.
+##
+## TPA: The target protocol address.
+##
+## THA: The target hardware address.
+##
+## .. bro:see:: arp_request bad_arp
event arp_reply%(mac_src: string, mac_dst: string, SPA: addr, SHA: string,
TPA: addr, THA: string%);
+
+## Generated for ARP packets that Bro cannot interpret. Examples are packets with
+## non-standard hardware address formats or hardware addresses that not match the
+## originator of the packet.
+##
+## SPA: The sender protocol address.
+##
+## SHA: The sender hardware address.
+##
+## TPA: The target protocol address.
+##
+## THA: The target hardware address.
+##
+## explanation: A short description of why the ARP packet is considered "bad".
+##
+## .. bro:see:: arp_reply arp_request
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event bad_arp%(SPA: addr, SHA: string, TPA: addr, THA: string, explanation: string%);
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive
+## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_handshake%(c: connection, is_orig: bool,
reserved: string, info_hash: string, peer_id: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_keep_alive%(c: connection, is_orig: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bittorrent_peer_choke%(c: connection, is_orig: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request
+## bittorrent_peer_unknown bittorrent_peer_weird
event bittorrent_peer_unchoke%(c: connection, is_orig: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_keep_alive
+## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_interested%(c: connection, is_orig: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_not_interested%(c: connection, is_orig: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_interested bittorrent_peer_keep_alive
+## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_have%(c: connection, is_orig: bool, piece_index: count%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_cancel bittorrent_peer_choke bittorrent_peer_handshake
+## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive
+## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_bitfield%(c: connection, is_orig: bool, bitfield: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_request%(c: connection, is_orig: bool, index: count,
begin: count, length: count%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_port
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_piece%(c: connection, is_orig: bool, index: count,
begin: count, piece_length: count%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bittorrent_peer_cancel%(c: connection, is_orig: bool, index: count,
begin: count, length: count%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown
+## bittorrent_peer_weird
event bittorrent_peer_port%(c: connection, is_orig: bool, listen_port: port%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_weird
event bittorrent_peer_unknown%(c: connection, is_orig: bool, message_id: count,
data: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown
event bittorrent_peer_weird%(c: connection, is_orig: bool, msg: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bt_tracker_request%(c: connection, uri: string,
headers: bt_tracker_headers%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bt_tracker_response%(c: connection, status: count,
headers: bt_tracker_headers,
peers: bittorrent_peer_set,
benc: bittorrent_benc_dir%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bt_tracker_response_not_ok%(c: connection, status: count,
headers: bt_tracker_headers%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the BitTorrent protocol.
+##
+## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke
+## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested
+## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece
+## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke
+## bittorrent_peer_unknown bittorrent_peer_weird
event bt_tracker_weird%(c: connection, is_orig: bool, msg: string%);
+## Generated for Finger requests.
+##
+## See `Wikipedia `__ for more
+## information about the Finger protocol.
+##
+## c: The connection.
+##
+## full: True if verbose information is requested (``/W`` switch).
+##
+## username: The request's user name.
+##
+## hostname: The request's host name.
+##
+## .. bro:see:: finger_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event finger_request%(c: connection, full: bool, username: string, hostname: string%);
+
+## Generated for Finger replies.
+##
+## See `Wikipedia `__ for more
+## information about the Finger protocol.
+##
+## c: The connection.
+##
+## reply_line: The reply as returned by the server
+##
+## .. bro:see:: finger_request
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event finger_reply%(c: connection, reply_line: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify
+## gnutella_not_establish gnutella_partial_binary_msg gnutella_signature_found
+##
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_text_msg%(c: connection, orig: bool, headers: string%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_establish gnutella_http_notify gnutella_not_establish
+## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_binary_msg%(c: connection, orig: bool, msg_type: count,
ttl: count, hops: count, msg_len: count,
payload: string, payload_len: count,
trunc: bool, complete: bool%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify
+## gnutella_not_establish gnutella_signature_found gnutella_text_msg
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_partial_binary_msg%(c: connection, orig: bool,
msg: string, len: count%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_binary_msg gnutella_http_notify gnutella_not_establish
+## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_establish%(c: connection%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify
+## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_not_establish%(c: connection%);
+
+## TODO.
+##
+## See `Wikipedia `__ for more
+## information about the Gnutella protocol.
+##
+## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_not_establish
+## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event gnutella_http_notify%(c: connection%);
+## Generated for Ident requests.
+##
+## See `Wikipedia `__ for more
+## information about the Ident protocol.
+##
+## c: The connection.
+##
+## lport: The request's local port.
+##
+## rport: The request's remote port.
+##
+## .. bro:see:: ident_error ident_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event ident_request%(c: connection, lport: port, rport: port%);
+
+## Generated for Ident replies.
+##
+## See `Wikipedia `__ for more
+## information about the Ident protocol.
+##
+## c: The connection.
+##
+## lport: The corresponding request's local port.
+##
+## rport: The corresponding request's remote port.
+##
+## user_id: The user id returned by the reply.
+##
+## system: The operating system returned by the reply.
+##
+## .. bro:see:: ident_error ident_request
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event ident_reply%(c: connection, lport: port, rport: port, user_id: string, system: string%);
+
+## Generated for Ident error replies.
+##
+## See `Wikipedia `__ for more
+## information about the Ident protocol.
+##
+## c: The connection.
+##
+## lport: The corresponding request's local port.
+##
+## rport: The corresponding request's remote port.
+##
+## line: The error description returned by the reply.
+##
+## .. bro:see:: ident_reply ident_request
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event ident_error%(c: connection, lport: port, rport: port, line: string%);
+## Generated for Telnet/Rlogin login failures. The *login* analyzer inspects
+## Telnet/Rlogin sessions to heuristically extract username and password
+## information as well as the text returned by the login server. This event is
+## raised if a login attempt appears to have been unsuccessful.
+##
+## c: The connection.
+##
+## user: The user name tried.
+##
+## client_user: For Telnet connections, this is an empty string, but for Rlogin
+## connections, it is the client name passed in the initial authentication
+## information (to check against .rhosts).
+##
+## password: The password tried.
+##
+## line: line is the line of text that led the analyzer to conclude that the
+## authentication had failed.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_input_line
+## login_output_line login_prompt login_success login_terminal direct_login_prompts
+## get_login_state login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs
+## login_timeouts set_login_state
+##
+## .. note:: The login analyzer depends on a set of script-level variables that
+## need to configured with patterns identifying login attempts. This configuration
+## has not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is
+## therefore not directly usable at the moment.
+##
+## .. todo: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_failure%(c: connection, user: string, client_user: string, password: string, line: string%);
+
+## Generated for successful Telnet/Rlogin logins. The *login* analyzer inspects
+## Telnet/Rlogin sessions to heuristically extract username and password
+## information as well as the text returned by the login server. This event is
+## raised if a login attempt appears to have been successful.
+##
+## c: The connection.
+##
+## user: The user name used.
+##
+## client_user: For Telnet connections, this is an empty string, but for Rlogin
+## connections, it is the client name passed in the initial authentication
+## information (to check against .rhosts).
+##
+## password: The password used.
+##
+## line: line is the line of text that led the analyzer to conclude that the
+## authentication had succeeded.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_failure
+## login_input_line login_output_line login_prompt login_terminal
+## direct_login_prompts get_login_state login_failure_msgs login_non_failure_msgs
+## login_prompts login_success_msgs login_timeouts set_login_state
+##
+## .. note:: The login analyzer depends on a set of script-level variables that
+## need to configured with patterns identifying login attempts. This configuration
+## has not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is
+## therefore not directly usable at the moment.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_success%(c: connection, user: string, client_user: string, password: string, line: string%);
+
+## Generated for lines of input on Telnet/Rlogin sessions. The line will have
+## control characters (such as in-band Telnet options) removed.
+##
+## c: The connection.
+##
+## line: The input line.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_failure
+## login_output_line login_prompt login_success login_terminal rsh_request
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_input_line%(c: connection, line: string%);
+
+## Generated for lines of output on Telnet/Rlogin sessions. The line will have
+## control characters (such as in-band Telnet options) removed.
+##
+## c: The connection.
+##
+## line: The ouput line.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_failure
+## login_input_line login_prompt login_success login_terminal rsh_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_output_line%(c: connection, line: string%);
+
+## Generated when tracking of Telnet/Rlogin authentication failed. As Bro's *login*
+## analyzer uses a number of heuristics to extract authentication information, it
+## may become confused. If it can no longer correctly track the authentication
+## dialog, it raised this event.
+##
+## c: The connection.
+##
+## msg: Gives the particular problem the heuristics detected (for example,
+## ``multiple_login_prompts`` means that the engine saw several login prompts in
+## a row, without the type-ahead from the client side presumed necessary to cause
+## them)
+##
+## line: The line of text that caused the heuristics to conclude they were
+## confused.
+##
+## .. bro:see:: login_confused_text login_display login_failure login_input_line login_output_line
+## login_prompt login_success login_terminal direct_login_prompts get_login_state
+## login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs
+## login_timeouts set_login_state
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_confused%(c: connection, msg: string, line: string%);
+
+## Generated after getting confused while tracking a Telnet/Rlogin authentication
+## dialog. The *login* analyzer generates this even for every line of user input
+## after it has reported :bro:id:`login_confused` for a connection.
+##
+## c: The connection.
+##
+## line: The line the user typed.
+##
+## .. bro:see:: login_confused login_display login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal direct_login_prompts
+## get_login_state login_failure_msgs login_non_failure_msgs login_prompts
+## login_success_msgs login_timeouts set_login_state
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_confused_text%(c: connection, line: string%);
+
+## Generated for clients transmitting a terminal type in an Telnet session. This
+## information is extracted out of environment variables sent as Telnet options.
+##
+## c: The connection.
+##
+## terminal: The TERM value transmitted.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_failure
+## login_input_line login_output_line login_prompt login_success
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_terminal%(c: connection, terminal: string%);
+
+## Generated for clients transmitting a X11 DISPLAY in a Telnet session. This
+## information is extracted out of environment variables sent as Telnet options.
+##
+## c: The connection.
+##
+## terminal: The DISPLAY transmitted.
+##
+## .. bro:see:: login_confused login_confused_text login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event login_display%(c: connection, display: string%);
-event login_prompt%(c: connection, prompt: string%);
-event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%);
-event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%);
-event excessive_line%(c: connection%);
+
+## Generated when a Telnet authentication has been successful. The Telnet protocol
+## includes options for negotiating authentication. When such an option is sent
+## from client to server and the server replies that it accepts the authentication,
+## then the event engine generates this event.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## name: The authenticated name.
+##
+## c: The connection.
+##
+## .. bro:see:: authentication_rejected authentication_skipped login_success
+##
+## .. note:: This event inspects the corresponding Telnet option while :bro:id:`login_success`
+## heuristically determines success by watching session data.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event authentication_accepted%(name: string, c: connection%);
+
+## Generated when a Telnet authentication has been unsuccessful. The Telnet
+## protocol includes options for negotiating authentication. When such an option
+## is sent from client to server and the server replies that it did not accept the
+## authentication, then the event engine generates this event.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## name: The attempted authentication name.
+##
+## c: The connection.
+##
+## .. bro:see:: authentication_accepted authentication_skipped login_failure
+##
+## .. note:: This event inspects the corresponding Telnet option while :bro:id:`login_success`
+## heuristically determines failure by watching session
+## data.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event authentication_rejected%(name: string, c: connection%);
+
+## Generated when for Telnet/Rlogin sessions when a pattern match indicates
+## that no authentication is performed.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: authentication_accepted authentication_rejected direct_login_prompts
+## get_login_state login_failure_msgs login_non_failure_msgs login_prompts
+## login_success_msgs login_timeouts set_login_state
+##
+## .. note:: The login analyzer depends on a set of script-level variables that
+## need to be configured with patterns identifying actvity. This configuration has
+## not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is therefore
+## not directly usable at the moment.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event authentication_skipped%(c: connection%);
+
+## Generated for clients transmitting a terminal prompt in a Telnet session. This
+## information is extracted out of environment variables sent as Telnet options.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## c: The connection.
+##
+## terminal: The TTYPROMPT transmitted.
+##
+## .. bro:see:: login_confused login_confused_text login_display login_failure
+## login_input_line login_output_line login_success login_terminal
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event login_prompt%(c: connection, prompt: string%);
+
+## Generated for Telnet sessions when encryption is activated. The Telnet protoco;
+## includes options for negotiating encryption. When such a series of options is
+## successfully negotiated, the event engine generates this event.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: authentication_accepted authentication_rejected authentication_skipped
+## login_confused login_confused_text login_display login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal
event activating_encryption%(c: connection%);
+## Generated for inconsistent Telnet options observed. Telnet options are specified
+## by the client and server stating which options they are willing to support
+## vs. which they are not, and then instructing one another which in fact they
+## should or should not use for the current connection. If the event engine sees
+## a peer violate either what the other peer has instructed it to do, or what it
+## itself offered in terms of options in the past, then the engine generates an
+## inconsistent_option event.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: bad_option bad_option_termination authentication_accepted
+## authentication_rejected authentication_skipped login_confused
+## login_confused_text login_display login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal
+event inconsistent_option%(c: connection%);
+
+## Generated for an ill-formed or unrecognized Telnet option.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: inconsistent_option bad_option_termination authentication_accepted
+## authentication_rejected authentication_skipped login_confused
+## login_confused_text login_display login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event bad_option%(c: connection%);
+
+## Generated for a Telnet option that's incorrectly terminated.
+##
+## See `Wikipedia `__ for more information
+## about the Telnet protocol.
+##
+## .. bro:see:: inconsistent_option bad_option authentication_accepted
+## authentication_rejected authentication_skipped login_confused
+## login_confused_text login_display login_failure login_input_line
+## login_output_line login_prompt login_success login_terminal
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event bad_option_termination%(c: connection%);
+
+## Generated for client side commands on an RSH connection.
+##
+## See `RFC 1258 `__ for more information about
+## the Rlogin/Rsh protocol.
+##
+## c: The connection.
+##
+## client_user: The client-side user name as sent in the initial protocol
+## handshake.
+##
+## client_user: The server-side user name as sent in the initial protocol
+## handshake.
+##
+## line: The command line sent in the request.
+##
+## new_session: True if this is the first command of the Rsh session.
+##
+## .. bro:see:: rsh_reply login_confused login_confused_text login_display
+## login_failure login_input_line login_output_line login_prompt login_success
+## login_terminal
+##
+## .. note: For historical reasons, these events are separate from the ``login_``
+## events. Ideally, they would all be handled uniquely.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%);
+
+## Generated for client side commands on an RSH connection.
+##
+## See `RFC 1258 `__ for more information about
+## the Rlogin/Rsh protocol.
+##
+## c: The connection.
+##
+## client_user: The client-side user name as sent in the initial protocol
+## handshake.
+##
+## client_user: The server-side user name as sent in the initial protocol
+## handshake.
+##
+## line: The command line sent in the request.
+##
+## new_session: True if this is the first command of the Rsh session.
+##
+## .. bro:see:: rsh_request login_confused login_confused_text login_display
+## login_failure login_input_line login_output_line login_prompt login_success
+## login_terminal
+##
+## .. note: For historical reasons, these events are separate from the ``login_``
+## events. Ideally, they would all be handled uniquely.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%);
+
+## Generated for client-side FTP commands.
+##
+## See `Wikipedia `__ for more
+## information about the FTP protocol.
+##
+## c: The connection.
+##
+## command: The FTP command issued by the client (without any arguments).
+##
+## arg: The arguments going with the command.
+##
+## .. bro:see:: ftp_reply fmt_ftp_port parse_eftp_port
+## parse_ftp_epsv parse_ftp_pasv parse_ftp_port
event ftp_request%(c: connection, command: string, arg: string%) &group="ftp";
+
+## Generated for server-side FTP replies.
+##
+## See `Wikipedia `__ for more
+## information about the FTP protocol.
+##
+## c: The connection.
+##
+## code: The numerical response code the server responded with.
+##
+## msg: The textual message of the response.
+##
+## cont_resp: True if the reply line is tagged as being continued to the next line.
+## If so, further events will be raised and a handler may want to reassemle the
+## pieces before processing the response any further.
+##
+## .. bro:see:: ftp_request fmt_ftp_port parse_eftp_port
+## parse_ftp_epsv parse_ftp_pasv parse_ftp_port
event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%) &group="ftp";
+## Generated for client-side SMTP commands.
+##
+## See `Wikipedia `__
+## for more information about the SMTP protocol.
+##
+## c: The connection.
+##
+## is_orig: True if the sender of the command is the originator of the TCP
+## connection. Note that this is not redundant: the SMTP ``TURN`` command allows
+## client and server to flip roles on established SMTP sessions, and hence a
+## "request" might still come from the TCP-level responder. In practice, however,
+## that will rarely happen as TURN is considered insecure and rarely used.
+##
+## command: The request's command, without any arguments.
+##
+## arg: The request command's arguments.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data
+## smtp_data smtp_reply
+##
+## .. note:: Bro does not support the newer ETRN extension yet.
event smtp_request%(c: connection, is_orig: bool, command: string, arg: string%) &group="smtp";
+
+## Generated for server-side SMTP commands.
+##
+## See `Wikipedia `__
+## for more information about the SMTP protocol.
+##
+## c: The connection.
+##
+## is_orig: True if the sender of the command is the originator of the TCP
+## connection. Note that this is not redundant: the SMTP ``TURN`` command
+## allows client and server to flip roles on established SMTP sessions,
+## and hence a "reply" might still come from the TCP-level originator. In
+## practice, however, that will rarely happen as TURN is considered insecure
+## and rarely used.
+##
+## code: The reply's numerical code.
+##
+## msg: The reply's textual description.
+##
+## cont_resp: True if the reply line is tagged as being continued to the next line.
+## If so, further events will be raised and a handler may want to reassemle the
+## pieces before processing the response any further.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data
+## smtp_data smtp_request
+##
+## .. note:: Bro doesn't support the newer ETRN extension yet.
event smtp_reply%(c: connection, is_orig: bool, code: count, cmd: string, msg: string, cont_resp: bool%) &group="smtp";
+
+## Generated for DATA transmitted on SMTP sessions. This event is raised for
+## subsequent chunks of raw data following the ``DATA`` SMTP command until the
+## corresponding end marker ``.`` is seen. A handler may want to reassembly
+## the pieces as they come in if stream-analysis is required.
+##
+## See `Wikipedia `__
+## for more information about the SMTP protocol.
+##
+## c: The connection.
+##
+## is_orig: True if the sender of the data is the originator of the TCP
+## connection.
+##
+## data: The raw data. Note that the size of each chunk is undefined and
+## depends on specifics of the underlying TCP connection.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data
+## smtp_reply smtp_request skip_smtp_data
+##
+## .. note:: This event received the unprocessed raw data. There is a separate
+## set ``mime_*`` events that strip out the outer MIME-layer of emails and provide
+## structured access to their content.
event smtp_data%(c: connection, is_orig: bool, data: string%) &group="smtp";
+
+## Generated for unexpected activity on SMTP sessions. The SMTP analyzer tracks the
+## state of SMTP sessions and reports commands and other activity with this event
+## that it sees even though it would not expect so at the current point of the
+## communication.
+##
+## See `Wikipedia `__
+## for more information about the SMTP protocol.
+##
+## c: The connection.
+##
+## is_orig: True if the sender of the unexpected activity is the originator of the
+## TCP connection.
+##
+## msg: A descriptive message of what was unexpected.
+##
+## detail: The actual SMTP line triggering the event.
+##
+## .. bro:see:: smtp_data smtp_request smtp_reply
event smtp_unexpected%(c: connection, is_orig: bool, msg: string, detail: string%) &group="smtp";
+## Generated when starting to parse a email MIME entity. MIME is a
+## protocol-independent data format for encoding text and files, along with
+## corresponding meta-data, for transmission. Bro raises this event when it begin
+## parsing a MIME entity extracted from an email protocol.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_content_hash mime_end_entity
+## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data
+## http_begin_entity
+##
+## .. note:: Bro also extracts MIME entities from HTTP session. For those, however,
+## it raises :bro:id:`http_begin_entity` instead.
event mime_begin_entity%(c: connection%);
-event mime_next_entity%(c: connection%);
+
+## Generated when finishing parsing an email MIME entity. MIME is a
+## protocol-independent data format for encoding text and files, along with
+## corresponding meta-data, for transmission. Bro raises this event when it
+## finished parsing a MIME entity extracted from an email protocol.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data
+## http_end_entity
+##
+## .. note:: Bro also extracts MIME entities from HTTP session. For those, however,
+## it raises :bro:id:`http_end_entity` instead.
event mime_end_entity%(c: connection%);
+
+## Generated for individual MIME headers extracted from email MIME
+## entities. MIME is a protocol-independent data format for encoding text and
+## files, along with corresponding meta-data, for transmission.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## h: The parsed MIME header.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_event mime_segment_data
+## http_header http_all_headers
+##
+## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however,
+## it raises :bro:id:`http_header` instead.
event mime_one_header%(c: connection, h: mime_header_rec%);
+
+## Generated for MIME headers extracted from email MIME entities, passing all
+## headers at once. MIME is a protocol-independent data format for encoding text
+## and files, along with corresponding meta-data, for transmission.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## hlist: A *table* containing all headers extracted from the current entity.
+## The table is indexed by the position of the header (1 for the first, 2 for the
+## second, etc.).
+##
+## .. bro:see:: mime_all_data mime_begin_entity mime_content_hash mime_end_entity
+## mime_entity_data mime_event mime_one_header mime_segment_data
+## http_header http_all_headers
+##
+## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however,
+## it raises :bro:id:`http_header` instead.
event mime_all_headers%(c: connection, hlist: mime_header_list%);
+
+## Generated for chunks of decoded MIME data from email MIME entities. MIME
+## is a protocol-independent data format for encoding text and files, along with
+## corresponding meta-data, for transmission. As Bro parses the data of an entity,
+## it raises a sequence of these events, each coming as soon as a new chunk of
+## data is available. In contrast, there is also :bro:id:`mime_entity_data`, which
+## passes all of an entities data at once in a single block. While the latter is
+## more convinient to handle, ``mime_segment_data`` is more efficient as Bro does
+## not need to buffer the data. Thus, if possible, this event should be prefered.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## length: The length of *data*.
+##
+## data: The raw data of one segment of the current entity.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_event mime_one_header http_entity_data
+## mime_segment_length mime_segment_overlap_length
+##
+## .. note:: Bro also extracts MIME data from HTTP sessions. For those, however, it
+## raises :bro:id:`http_entity_data` (sic!) instead.
event mime_segment_data%(c: connection, length: count, data: string%);
+
+## Generated for data decoded from an email MIME entity. This event delivers
+## the complete content of a single MIME entity. In contrast, there is also
+## :bro:id:`mime_segment_data`, which passes on a sequence of data chunks as
+## they. come in. While ``mime_entity_data`` is more convinient to handle,
+## ``mime_segment_data`` is more efficient as Bro does not need to buffer the data.
+## Thus, if possible, the latter should be prefered.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## length: The length of *data*.
+##
+## data: The raw data of the complete entity.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_event mime_one_header mime_segment_data
+##
+## .. note:: While Bro also decodes MIME entities extracted from HTTP
+## sessions, there's no corresponding event for that currently.
event mime_entity_data%(c: connection, length: count, data: string%);
+
+## Generated for passing on all data decoded from an single email MIME
+## message. If an email message has more than one MIME entity, this event
+## combines all their data into a single value for analysis. Note that because
+## of the potentially significant buffering necessary, using this event can be
+## expensive.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## length: The length of *data*.
+##
+## data: The raw data of all MIME entities concatenated.
+##
+## .. bro:see:: mime_all_headers mime_begin_entity mime_content_hash mime_end_entity
+## mime_entity_data mime_event mime_one_header mime_segment_data
+##
+## .. note:: While Bro also decodes MIME entities extracted from HTTP
+## sessions, there's no corresponding event for that currently.
event mime_all_data%(c: connection, length: count, data: string%);
+
+## Generated for errors found when decoding email MIME entities.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## event_type: A string describing the general category of the problem found (e.g.,
+## ``illegal format``).
+##
+## detail: Further more detailed description of the error.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash
+## mime_end_entity mime_entity_data mime_one_header mime_segment_data http_event
+##
+## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however,
+## it raises :bro:id:`http_event` instead.
event mime_event%(c: connection, event_type: string, detail: string%);
+
+## Generated for decoded MIME entities extracted from email meessage, passing on
+## their MD5 checksums. Bro computes the MD5 over the complete decoded data of
+## each MIME entity.
+##
+## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia
+## `__ for more information about the ARP
+## protocol.
+##
+## c: The connection.
+##
+## content_len: The length of entity being hashed.
+##
+## hash_value: The MD5 hash.
+##
+## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_end_entity
+## mime_entity_data mime_event mime_one_header mime_segment_data
+##
+## .. note:: While Bro also decodes MIME entities extracted from HTTP
+## sessions, there's no corresponding event for that currently.
event mime_content_hash%(c: connection, content_len: count, hash_value: string%);
-# Generated for each RPC request / reply *pair* (if there is no reply, the event
-# will be generated on timeout).
+## Generated for RPC request/reply *pairs*. The RPC analyzer associates request
+## and reply by their transactions identifiers and raise this event once both
+## have been seen. If there's not reply, the will still be generated eventually
+## on timeout. In that case, *status* will be set to :bro:enum:`RPC_TIMEOUT`.
+##
+## See `Wikipedia `__ for more information
+## about the ONC RPC protocol.
+## c: The connection.
+##
+## xid: The transaction identifier allowing to match requests with replies.
+##
+## prog: The remote program to call.
+##
+## ver: The version of the remote program to call.
+##
+## proc: The procedure of the remote program to call.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## start_time: Then time when the *call* was seen.
+##
+## call_len: The size of the *call_body* PDU.
+##
+## reply_len: The size of the *reply_body* PDU.
+##
+## .. bro:see:: rpc_call rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request
+## dce_rpc_response rpc_timeout
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event rpc_dialogue%(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count%);
-# Generated for each (correctly formed) RPC_CALL message received.
+
+## Generated for RPC *call* messages.
+##
+## See `Wikipedia `__ for more information
+## about the ONC RPC protocol.
+##
+## c: The connection.
+##
+## xid: The transaction identifier allowing to match requests with replies.
+##
+## prog: The remote program to call.
+##
+## ver: The version of the remote program to call.
+##
+## proc: The procedure of the remote program to call.
+##
+## call_len: The size of the *call_body* PDU.
+##
+## .. bro:see:: rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request
+## dce_rpc_response rpc_timeout
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event rpc_call%(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count%);
-# Generated for each (correctly formed) RPC_REPLY message received.
+
+## Generated for RPC *reply* messages.
+##
+## See `Wikipedia `__ for more information
+## about the ONC RPC protocol.
+##
+## c: The connection.
+##
+## xid: The transaction identifier allowing to match requests with replies.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## reply_len: The size of the *reply_body* PDU.
+##
+## .. bro:see:: rpc_call rpc_dialogue dce_rpc_bind dce_rpc_message dce_rpc_request
+## dce_rpc_response rpc_timeout
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event rpc_reply%(c: connection, xid: count, status: rpc_status, reply_len: count%);
+## Generated for Portmapper requests of type *null*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the service.
+##
+## r: The RPC connection.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit
+## pm_request_dump pm_request_getport pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_null%(r: connection%);
+
+## Generated for Portmapper request/reply dialogues of type *set*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the service.
+##
+## r: The RPC connection.
+##
+## m: The argument to the request.
+##
+## success: True if the request was successful, according to the corresponding
+## reply. If no reply was seen, this will be false once the request times out.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit
+## pm_request_dump pm_request_getport pm_request_null pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_set%(r: connection, m: pm_mapping, success: bool%);
+
+## Generated for Portmapper request/reply dialogues of type *unset*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the service.
+##
+## r: The RPC connection.
+##
+## m: The argument to the request.
+##
+## success: True if the request was successful, according to the corresponding
+## reply. If no reply was seen, this will be false once the request times out.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit
+## pm_request_dump pm_request_getport pm_request_null pm_request_set rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_unset%(r: connection, m: pm_mapping, success: bool%);
+
+## Generated for Portmapper request/reply dialogues of type *getport*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the service.
+##
+## r: The RPC connection.
+##
+## pr: The argument to the request.
+##
+## p: The port returned by the server.
+##
+## success: True if the request was successful, according to the corresponding
+## reply. If no reply was seen, this will be false once the request times out.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit
+## pm_request_dump pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_getport%(r: connection, pr: pm_port_request, p: port%);
+
+## Generated for Portmapper request/reply dialogues of type *dump*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the service.
+##
+## r: The RPC connection.
+##
+## m: The mappings returned by the server.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_dump%(r: connection, m: pm_mappings%);
+
+## Generated for Portmapper request/reply dialogues of type *callit*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## m: The argument to the request.
+##
+## p: The port value returned by the call.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_request_callit%(r: connection, call: pm_callit_request, p: port%);
+
+## Generated for failed Portmapper requests of type *null*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_null%(r: connection, status: rpc_status%);
+
+## Generated for failed Portmapper requests of type *set*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## m: The argument to the original request.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_set%(r: connection, status: rpc_status, m: pm_mapping%);
+
+## Generated for failed Portmapper requests of type *unset*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## m: The argument to the original request.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_unset%(r: connection, status: rpc_status, m: pm_mapping%);
+
+## Generated for failed Portmapper requests of type *getport*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## pr: The argument to the original request.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_null
+## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_getport%(r: connection, status: rpc_status, pr: pm_port_request%);
+
+## Generated for failed Portmapper requests of type *dump*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_getport pm_attempt_null
+## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_dump%(r: connection, status: rpc_status%);
+
+## Generated for failed Portmapper requests of type *callit*.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## status: The status of the reply, which should be one of the index values of
+## :bro:id:`RPC_status`.
+##
+## call: The argument to the original request.
+##
+## .. bro:see:: epm_map_response pm_attempt_dump pm_attempt_getport pm_attempt_null
+## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump
+## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_attempt_callit%(r: connection, status: rpc_status, call: pm_callit_request%);
+
+## Generated for Portmapper requests or replies that include an invalid port
+## number. Since ports are represented by unsigned 4-byte integers, they can stray
+## outside the allowed range of 0--65535 by being >= 65536. If so, this event is
+## generated.
+##
+## Portmapper is a service running on top of RPC. See `Wikipedia
+## `__ for more information about the
+## service.
+##
+## r: The RPC connection.
+##
+## bad_p: The invalid port value.
+##
+## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport
+## pm_attempt_null pm_attempt_set pm_attempt_unset pm_request_callit
+## pm_request_dump pm_request_getport pm_request_null pm_request_set
+## pm_request_unset rpc_call rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event pm_bad_port%(r: connection, bad_p: count%);
-# Events for the NFS analyzer. An event is generated if we have received a
-# Call (request) / Response pair (or in case of a time out). info$rpc_stat and
-# info$nfs_stat show whether the request was successful. The request record is
-# always filled out, however, the reply record(s) might not be set or might only
-# be partially set. See the comments for the record types in bro.init to see which
-# reply fields are set when.
+## Generated for NFSv3 request/reply dialogues of type *null*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_read nfs_proc_readdir nfs_proc_readlink
+## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_null%(c: connection, info: NFS3::info_t%);
-event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%);
+## Generated for NFSv3 request/reply dialogues of type *getattr*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## attr: The attributes returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status
+## rpc_call rpc_dialogue rpc_reply NFS3::mode2string
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_getattr%(c: connection, info: NFS3::info_t, fh: string, attrs: NFS3::fattr_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *lookup*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## req: The arguments passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status
+## rpc_call rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_lookup%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::lookup_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *read*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## req: The arguments passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_remove nfs_proc_rmdir
+## nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply
+## NFS3::return_data NFS3::return_data_first_only NFS3::return_data_max
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_read%(c: connection, info: NFS3::info_t, req: NFS3::readargs_t, rep: NFS3::read_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *readlink*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_readlink%(c: connection, info: NFS3::info_t, fh: string, rep: NFS3::readlink_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *write*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply NFS3::return_data NFS3::return_data_first_only
+## NFS3::return_data_max
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_write%(c: connection, info: NFS3::info_t, req: NFS3::writeargs_t, rep: NFS3::write_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *create*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status
+## rpc_call rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_create%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *mkdir*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status
+## rpc_call rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_mkdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *remove*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_remove%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *rmdir*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_write nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_rmdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%);
+
+## Generated for NFSv3 request/reply dialogues of type *readdir*. The event is
+## generated once we have either seen both the request and its corresponding reply,
+## or an unanswered request has timed out.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## fh: The file handle passed in the request.
+##
+## rep: The response returned in the reply. The values may not be valid if the
+## request was unsuccessful.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readlink
+## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_proc_readdir%(c: connection, info: NFS3::info_t, req: NFS3::readdirargs_t, rep: NFS3::readdir_reply_t%);
-# Generated for each NFS reply message we receive, giving just gives the status.
+## Generated for NFS3 request/reply dialogues of a type that Bro's NFS3 analyzer
+## does not implement.
+##
+## NFS is a service running on top of RPC. See `Wikipedia
+## `__ for more
+## information about the service.
+##
+## c: The RPC connection.
+##
+## info: Reports the status of the dialogue, along with some meta information.
+##
+## proc: The procedure called that Bro does not implement.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_null nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove
+## nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
+event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%);
+
+## Generated for each NFS3 reply message received, reporting just the
+## status included.
+##
+## info: Reports the status included in the reply.
+##
+## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir
+## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir
+## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write rpc_call
+## rpc_dialogue rpc_reply
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event nfs_reply_status%(n: connection, info: NFS3::info_t%);
+## Generated for all NTP messages. Different from many other of Bro's events, this
+## one is generated for both client-side and server-side messages.
+##
+## See `Wikipedia `__ for more
+## information about the NTP protocol.
+##
+## u: The connection record describing the corresponding UDP flow.
+##
+## msg: The parsed NTP message.
+##
+## excess: The raw bytes of any optional parts of the NTP packet. Bro does not
+## further parse any optional fields.
+##
+## .. bro:see:: ntp_session_timeout
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event ntp_message%(u: connection, msg: ntp_msg, excess: string%);
+## Generated for all NetBIOS SSN and DGM messages. Bro's NetBIOS analyzer processes
+## the NetBIOS session service running on TCP port 139, and (despite its name!) the
+## NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## msg_type: The general type of message, as defined in Section 4.3.1 of `RFC 1002
+## `__.
+##
+## data_len: The length of the message's payload.
+##
+## .. bro:see:: netbios_session_accepted netbios_session_keepalive
+## netbios_session_raw_message netbios_session_rejected netbios_session_request
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_message%(c: connection, is_orig: bool, msg_type: count, data_len: count%);
+
+## Generated for NetBIOS messages of type *session request*. Bro's NetBIOS analyzer
+## processes the NetBIOS session service running on TCP port 139, and (despite its
+## name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS
+## header.
+##
+## .. bro:see:: netbios_session_accepted netbios_session_keepalive
+## netbios_session_message netbios_session_raw_message netbios_session_rejected
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_request%(c: connection, msg: string%);
+
+## Generated for NetBIOS messages of type *positive session response*. Bro's
+## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139,
+## and (despite its name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS
+## header.
+##
+## .. bro:see:: netbios_session_keepalive netbios_session_message
+## netbios_session_raw_message netbios_session_rejected netbios_session_request
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_accepted%(c: connection, msg: string%);
+
+## Generated for NetBIOS messages of type *negative session response*. Bro's
+## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139,
+## and (despite its name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS
+## header.
+##
+## .. bro:see:: netbios_session_accepted netbios_session_keepalive
+## netbios_session_message netbios_session_raw_message netbios_session_request
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_rejected%(c: connection, msg: string%);
+
+## Generated for NetBIOS message of type *session message* that are not carrying
+## SMB payload.
+##
+## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139,
+## and (despite its name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS
+## header (i.e., the ``user_data``).
+##
+## .. bro:see:: netbios_session_accepted netbios_session_keepalive
+## netbios_session_message netbios_session_rejected netbios_session_request
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: This is an oddly named event. In fact, it's probably an odd event to
+## have to begin with.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_raw_message%(c: connection, is_orig: bool, msg: string%);
+
+## Generated for NetBIOS messages of type *retarget response*. Bro's NetBIOS
+## analyzer processes the NetBIOS session service running on TCP port 139, and
+## (despite its name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS header.
+##
+## .. bro:see:: netbios_session_accepted netbios_session_keepalive
+## netbios_session_message netbios_session_raw_message netbios_session_rejected
+## netbios_session_request decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo: This is an oddly named event.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_ret_arg_resp%(c: connection, msg: string%);
+
+## Generated for NetBIOS messages of type *keep-alive*. Bro's NetBIOS analyzer
+## processes the NetBIOS session service running on TCP port 139, and (despite its
+## name!) the NetBIOS datagram service on UDP port 138.
+##
+## See `Wikipedia `__ for more information
+## about NetBIOS. `RFC 1002 `__ describes
+## the packet format for NetBIOS over TCP/IP, which Bro parses.
+##
+## c: The connection, which may be a TCP or UDP, depending on the type of the
+## NetBIOS session.
+##
+## msg: The raw payload of the message sent, excluding the common NetBIOS header.
+##
+## .. bro:see:: netbios_session_accepted netbios_session_message
+## netbios_session_raw_message netbios_session_rejected netbios_session_request
+## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type
+##
+## .. note:: These days, NetBIOS is primarily used as a transport mechanism for
+## `SMB/CIFS `__. Bro's SMB
+## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event netbios_session_keepalive%(c: connection, msg: string%);
+## Generated for all SMB/CIFS messages.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## is_orig: True if the message was sent by the originator of the underlying
+## transport-level connection.
+##
+## cmd: A string mmenonic of the SMB command code.
+##
+## body_length: The length of the SMB message body, i.e. the data starting after
+## the SMB header.
+##
+## body: The raw SMB message body, i.e., the data starting after the SMB header.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error
+## smb_get_dfs_referral
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_message%(c: connection, hdr: smb_hdr, is_orig: bool, cmd: string, body_length: count, body: string%);
+
+## Generated for SMB/CIFS messages of type *tree connect andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## path: The ``path`` attribute specified in the message.
+##
+## service: The ``service`` attribute specified in the message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_tree_connect_andx%(c: connection, hdr: smb_hdr, path: string, service: string%);
+
+## Generated for SMB/CIFS messages of type *tree disconnect*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## path: The ``path`` attribute specified in the message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_tree_disconnect%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages of type *nt create andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## name: The ``name`` attribute specified in the message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_read_andx
+## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_nt_create_andx%(c: connection, hdr: smb_hdr, name: string%);
+
+## Generated for SMB/CIFS messages of type *nt transaction*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## trans: The parsed transaction header.
+##
+## data: The raw transaction data.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe
+## smb_com_trans_rap smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_transaction%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%);
+
+## Generated for SMB/CIFS messages of type *nt transaction 2*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## trans: The parsed transaction header.
+##
+## data: The raw transaction data.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe
+## smb_com_trans_rap smb_com_transaction smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_transaction2%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%);
+
+## Generated for SMB/CIFS messages of type *transaction mailslot*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## trans: The parsed transaction header.
+##
+## data: The raw transaction data.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_trans_mailslot%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%);
+
+## Generated for SMB/CIFS messages of type *transaction rap*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## trans: The parsed transaction header.
+##
+## data: The raw transaction data.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error
+## smb_get_dfs_referral smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_trans_rap%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%);
+
+## Generated for SMB/CIFS messages of type *transaction pipe*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## trans: The parsed transaction header.
+##
+## data: The raw transaction data.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_trans_pipe%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%);
+
+## Generated for SMB/CIFS messages of type *read andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## data: Always empty.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_read_andx%(c: connection, hdr: smb_hdr, data: string%);
+
+## Generated for SMB/CIFS messages of type *read andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## data: Always empty.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_tree_disconnect smb_error
+## smb_get_dfs_referral smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_write_andx%(c: connection, hdr: smb_hdr, data: string%);
+
+## Generated for SMB/CIFS messages of type *get dfs referral*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## max_referral_level: The ``max_referral_level`` attribute specified in the
+## message.
+##
+## file_name: The ``filene_name`` attribute specified in the message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_get_dfs_referral%(c: connection, hdr: smb_hdr, max_referral_level: count, file_name: string%);
+
+## Generated for SMB/CIFS messages of type *negotiate*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx
+## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction
+## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect
+## smb_com_write_andx smb_error smb_get_dfs_referral smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_negotiate%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages of type *negotiate response*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## dialect_index: The ``dialect`` indicated in the message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx
+## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction
+## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect
+## smb_com_write_andx smb_error smb_get_dfs_referral smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_negotiate_response%(c: connection, hdr: smb_hdr, dialect_index: count%);
+
+## Generated for SMB/CIFS messages of type *setup andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_setup_andx%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages of type *generic andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## .. bro:see:: smb_com_close smb_com_logoff_andx smb_com_negotiate
+## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx
+## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_generic_andx%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages of type *close*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## .. bro:see:: smb_com_generic_andx smb_com_logoff_andx smb_com_negotiate
+## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx
+## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_close%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages of type *logoff andx*.
+##
+## See `Wikipedia `__ for more
+## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both
+## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_negotiate
+## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx
+## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap
+## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx
+## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral
+## smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_com_logoff_andx%(c: connection, hdr: smb_hdr%);
+
+## Generated for SMB/CIFS messages that indicate an error. This event is triggered
+## by an SMB header including a status that signals an error.
+##
+## c: The connection.
+##
+## hdr: The parsed header of the SMB message.
+##
+## cmd: The SMB command code.
+##
+## cmd_str: A string mmenonic of the SMB command code.
+##
+## body: The raw SMB message body, i.e., the data starting after the SMB header.
+##
+## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx
+## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx
+## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot
+## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2
+## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx
+## smb_get_dfs_referral smb_message
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event smb_error%(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string%);
+## Generated for all DNS messages.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## is_orig: True if the message was sent by the originator of the connection.
+##
+## msg: The parsed DNS message header.
+##
+## len: The length of the message's raw representation (i.e, the DNS payload).
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_query_reply dns_rejected
+## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%) &group="dns";
+
+## Generated for DNS requests. For requests with multiple queries, this event
+## is raised once for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## query: The queried name.
+##
+## qtype: The queried resource record type.
+##
+## qclass: The queried resource record class.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns";
-event dns_full_request%(%) &group="dns";
+
+## Generated for DNS replies that reject a query. This event is raised if a DNS
+## reply either indicates failure via its status code or does not pass on any
+## answers to a query. Note that all of the event's paramaters are parsed out of
+## the reply; there's no stateful correlation with the query.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## query: The queried name.
+##
+## qtype: The queried resource record type.
+##
+## qclass: The queried resource record class.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns";
-event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns";
-event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr, astr: string%) &group="dns";
-event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
-event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
-event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
-event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%) &group="dns";
-event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
-event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
-event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%) &group="dns";
-event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%) &group="dns";
-event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
-event dns_EDNS%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
-event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%) &group="dns";
-event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%) &group="dns";
-
-# Generated at the end of processing a DNS packet.
-event dns_end%(c: connection, msg: dns_msg%) &group="dns";
+## Generated for DNS replies with an *ok* status code but no question section.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## query: The queried name.
+##
+## qtype: The queried resource record type.
+##
+## qclass: The queried resource record class.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_rejected
+## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_query_reply%(c: connection, msg: dns_msg, query: string,
qtype: count, qclass: count%) &group="dns";
-# Generated when a port 53 UDP message cannot be parsed as a DNS request.
+## Generated when the DNS analyzer processes what seems to be a non-DNS packets.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The raw DNS payload.
+##
+## .. note:: This event is deprecated and superseded by Bro's dynamic protocol
+## detection framework.
event non_dns_request%(c: connection, msg: string%) &group="dns";
+## Generated for DNS replies of type *A*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## a: The address returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply
+## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+##
+## .. note: This event is currently also raised for ``AAAA`` records. In that
+## case, the address *a* will correspond to the lower-order 4 bytes of the
+## IPv6 address. This will go away once IPv6 support is improved.
+##
+## .. todo: IPv6 handling is obviously very broken here ...
+event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns";
+
+## Generated for DNS replies of type *AAAA*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## a: The address returned by the reply.
+##
+## .. bro:see:: dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply
+## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
+## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
+## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
+## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+##
+## .. todo: Raising this event is not implemented currently, not even when
+## Bro's compiled IPv6 support. ``AAAA`` are currently always turned into
+## :bro:id:`dns_A_reply` events.
+event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr, astr: string%) &group="dns";
+
+## Generated for DNS replies of type *NS*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## name: The name returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
+
+## Generated for DNS replies of type *CNAME*. For replies with multiple answers,
+## an individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## name: The name returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply
+## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
+## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
+## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
+## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
+
+## Generated for DNS replies of type *PTR*. For replies with multiple answers,
+## an individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## name: The name returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_SOA_reply dns_SRV_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns";
+
+## Generated for DNS replies of type *CNAME*. For replies with multiple answers,
+## an individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## soa: The parsed SOA value
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SRV_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%) &group="dns";
+
+## Generated for DNS replies of type *WKS*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
+
+## Generated for DNS replies of type *HINFO*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## name: The name returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_MX_reply
+## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
+## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
+## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
+## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
+
+## Generated for DNS replies of type *MX*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## name: The name returned by the reply.
+##
+## preference: The preference for *name* specificed by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%) &group="dns";
+
+## Generated for DNS replies of type *TXT*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## str: The textual information returned by the reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%) &group="dns";
+
+## Generated for DNS replies of type *SRV*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The type-independent part of the parsed answer record.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns";
+
+## Generated for DNS replies of type *EDNS*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The parsed EDNS reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply
+## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
+## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
+## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
+## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
+## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%) &group="dns";
+
+## Generated for DNS replies of type *TSIG*. For replies with multiple answers, an
+## individual event of the corresponding type is raised for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## ans: The parsed TSIG reply.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TXT_reply dns_WKS_reply dns_end dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%) &group="dns";
+
+## Generated at the end of processing a DNS packet. This event is the last
+## ``dns_*`` event that will be raised for a DNS query/reply and signals that
+## all resource records have been passed on.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_full_request
+## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+event dns_end%(c: connection, msg: dns_msg%) &group="dns";
+
+## Generated for DHCP messages of type *discover*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## req_addr: The specific address requested by the client.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
+## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%);
+
+## Generated for DHCP messages of type *offer*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## mask: The subnet mask specified by the mesage.
+##
+## router: The list of routers specified by the message.
+##
+## lease: The least interval specificed by the message.
+##
+## serv_addr: The server address specified by the message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%);
+
+## Generated for DHCP messages of type *request*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## req_addr: The client address specified by the message.
+##
+## serv_addr: The server address specified by the message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr%);
+
+## Generated for DHCP messages of type *decline*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_decline%(c: connection, msg: dhcp_msg%);
+
+## Generated for DHCP messages of type *acknowledgment*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## mask: The subnet mask specified by the mesage.
+##
+## router: The list of routers specified by the message.
+##
+## lease: The least interval specificed by the message.
+##
+## serv_addr: The server address specified by the message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%);
+
+## Generated for DHCP messages of type *negative acknowledgment*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_nak%(c: connection, msg: dhcp_msg%);
+
+## Generated for DHCP messages of type *release*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_release%(c: connection, msg: dhcp_msg%);
+
+## Generated for DHCP messages of type *inform*.
+##
+## See `Wikipedia
+## `__ for more
+## information about the DHCP protocol.
+##
+## c: The connection record describing the underlying UDP flow..
+##
+## msg: The parsed type-indepedent part of the DHCP message.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected dns_request non_dns_request
+##
+## .. note: Bro does not support broadcast packets (as used by the DHCP protocol).
+## It treats broadcast addresses just like any other and associates packets into
+## transport-level flows in the same way as usual.
+##
+## .. todo:: Bro's current default configuration does not activate the protocol
+## analyzer that generates this event; the corresponding script has not yet
+## been ported to Bro 2.x. To still enable this event, one needs to add a
+## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature.
event dhcp_inform%(c: connection, msg: dhcp_msg%);
+## Generated for HTTP requests. Bro supports persistent and pipelined HTTP sessions
+## and raises corresponding events as it parses client/server dialogues. This event
+## is generated as soon as a request's initial line has been parsed, and before any
+## :bro:id:`http_header` events are raised.
+##
+## See `Wikipedia `__ for
+## more information about the HTTP protocol.
+##
+## c: The connection.
+##
+## method: The HTTP method extracted from the request (e.g., ``GET``, ``POST``).
+##
+## original_URI: The unprocessed URI as specified in the request.
+##
+## unescaped_URI: The URI with all percent-encodings decoded.
+##
+## version: The version number specified in the request (e.g., ``1.1``).
+##
+## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity
+## http_entity_data http_event http_header http_message_done http_reply http_stats
+## truncate_http_URI
event http_request%(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string%) &group="http-request";
+
+## Generated for HTTP replies. Bro supports persistent and pipelined HTTP sessions
+## and raises corresponding events as it parses client/server dialogues. This event
+## is generated as soon as a reply's initial line has been parsed, and before any
+## :bro:id:`http_header` events are raised.
+##
+## See `Wikipedia