Merge branch 'topic/script-reference' into topic/bif_cleanup

Conflicts:
	src/bro.bif
This commit is contained in:
Matthias Vallentin 2011-12-15 22:54:52 -08:00
commit 3ab03874b5
29 changed files with 10871 additions and 2604 deletions

View file

@ -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']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@ -217,3 +217,6 @@ man_pages = [
('index', 'bro', u'Bro Documentation',
[u'The Bro Project'], 1)
]
# -- Options for todo plugin --------------------------------------------
todo_include_todos=True

View file

@ -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

View file

@ -6,113 +6,621 @@ Types
The Bro scripting language supports the following built-in types.
.. TODO: add documentation
.. bro:type:: void
.. 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-with-NUL>" 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
<http://flex.sourceforge.net/manual/Patterns.html>`_. 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:: (&tracked)
.. TODO: needs documented or removed if it's not used anywhere.

View file

@ -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 <notice>`
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 <notice>`
(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 <cmp> <address-list>``
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`` ``<int-list>``
@ -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 <string>``
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
<http://www.gnu.org/software/flex/manual/html_chapter/flex_7.html>`_.
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.

View file

@ -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 )

View file

@ -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 <http://tracker.bro-ids.org/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,

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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="<not found>"]; # Sentinel.
const no_filter: Filter = [$name="<not found>"];
# 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;
}

View file

@ -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];
}

View file

@ -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.

View file

@ -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

View file

@ -1,3 +1,5 @@
##! Allows configuration of a pager email address to which notices can be sent.
@load ../main
module Notice;

View file

@ -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
@ -15,8 +15,8 @@ export {
## :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
## If an address from one of these networks is reported, we mark
## the entry with an addition quote symbol (that is, ">"). Many MUAs
## then highlight such lines differently.
global flag_nets: set[subnet] &redef;

View file

@ -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 )

View file

@ -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,22 +48,33 @@ 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;
## 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;
## These are shorthand ways of giving the uid and id to a notice. The
## 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 :bro:enum:`Notice::Type` of the notice.
## The type of the notice.
note: Type &log;
## The human readable message for the notice.
msg: string &log &optional;
@ -141,8 +151,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).
@ -163,8 +174,8 @@ export {
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],
@ -193,8 +204,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.
@ -207,14 +219,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
## :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
@ -231,30 +249,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);
}
@ -410,7 +453,8 @@ event notice(n: Notice::Info) &priority=-5
}
## This determines if a notice is being suppressed. It is only used
## internally as part of the mechanics for the global NOTICE function.
## 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 )

View file

@ -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);
}

View file

@ -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;

View file

@ -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,
};

View file

@ -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.

View file

@ -1,30 +1,36 @@
##! Script level signature support.
##! Script level signature support. See the
##! :doc:`signature documentation </signatures>` 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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
# Internal functions and types used by the logging framework.
##! Internal functions and types used by the logging framework.
module Log;

View file

@ -1,3 +1,11 @@
##! The reporter built-in functions allow for the scripting layer to
##! generate messages of varying severity. If no event handlers
##! exist for reporter messages, the messages are output to stderr.
##! If event handlers do exist, it's assumed they take care of determining
##! how/where to output the messages.
##!
##! See :doc:`/scripts/base/frameworks/reporter/main` for a convenient
##! reporter message logging framework.
module Reporter;
@ -5,6 +13,13 @@ module Reporter;
#include "NetVar.h"
%%}
## Generates an informational message.
##
## msg: The informational message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_info
function Reporter::info%(msg: string%): bool
%{
reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -13,6 +28,13 @@ function Reporter::info%(msg: string%): bool
return new Val(1, TYPE_BOOL);
%}
## Generates a message that warns of a potential problem.
##
## msg: The warning message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_warning
function Reporter::warning%(msg: string%): bool
%{
reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -21,6 +43,14 @@ function Reporter::warning%(msg: string%): bool
return new Val(1, TYPE_BOOL);
%}
## Generates a non-fatal error indicative of a definite problem that should
## be addressed. Program execution does not terminate.
##
## msg: The error message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_error
function Reporter::error%(msg: string%): bool
%{
reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -29,6 +59,11 @@ function Reporter::error%(msg: string%): bool
return new Val(1, TYPE_BOOL);
%}
## Generates a fatal error on stderr and terminates program execution.
##
## msg: The error message to report.
##
## Returns: Always true.
function Reporter::fatal%(msg: string%): bool
%{
reporter->PushLocation(frame->GetCall()->GetLocationInfo());

View file

@ -10,6 +10,14 @@ using namespace std;
%%}
## Concates all arguments into a single string. The function takes a variable
## number of arguments of type string and stiches them together.
##
## Returns: The concatenation of all (string) arguments.
##
## .. bro:see:: cat cat_sep cat_string_array cat_string_array_n
## fmt
## join_string_vec join_string_array
function string_cat%(...%): string
%{
int n = 0;
@ -73,18 +81,53 @@ BroString* cat_string_array_n(TableVal* tbl, int start, int end)
}
%%}
## Concatenates all elements in an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: The concatenation of all elements in *a*.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array_n
## fmt
## join_string_vec join_string_array
function cat_string_array%(a: string_array%): string
%{
TableVal* tbl = a->AsTableVal();
return new StringVal(cat_string_array_n(tbl, 1, a->AsTable()->Length()));
%}
## Concatenates a specific range of elements in an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## start: The array index of the first element of the range.
##
## end: The array index of the last element of the range.
##
## Returns: The concatenation of the range *[start, end]* in *a*.
##
## .. bro:see:: cat string_cat cat_string_array
## fmt
## join_string_vec join_string_array
function cat_string_array_n%(a: string_array, start: count, end: count%): string
%{
TableVal* tbl = a->AsTableVal();
return new StringVal(cat_string_array_n(tbl, start, end));
%}
## Joins all values in the given array of strings with a separator placed
## between each element.
##
## sep: The separator to place between each element.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: The concatenation of all elements in *a*, with *sep* placed
## between each element.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n
## fmt
## join_string_vec
function join_string_array%(sep: string, a: string_array%): string
%{
vector<const BroString*> vs;
@ -108,6 +151,45 @@ function join_string_array%(sep: string, a: string_array%): string
return new StringVal(concatenate(vs));
%}
## Joins all values in the given vector of strings with a separator placed
## between each element.
##
## sep: The separator to place between each element.
##
## a: The :bro:id:`string_vec` (``vector of string``).
##
## Returns: The concatenation of all elements in *a*, with *sep* placed
## between each element.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n
## fmt
## join_string_array
function join_string_vec%(vec: string_vec, sep: string%): string
%{
ODesc d;
VectorVal *v = vec->AsVectorVal();
for ( unsigned i = 0; i < v->Size(); ++i )
{
if ( i > 0 )
d.Add(sep->CheckString(), 0);
v->Lookup(i+1)->Describe(&d);
}
BroString* s = new BroString(1, d.TakeBytes(), d.Len());
s->SetUseFreeToDelete(true);
return new StringVal(s);
%}
## Sorts an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: A sorted copy of *a*.
##
## .. bro:see:: sort
function sort_string_array%(a: string_array%): string_array
%{
TableVal* tbl = a->AsTableVal();
@ -133,27 +215,26 @@ function sort_string_array%(a: string_array%): string_array
vs_to_string_array(vs, b, 1, n);
return b;
%}
function join_string_vec%(vec: string_vec, sep: string%): string
%{
ODesc d;
VectorVal *v = vec->AsVectorVal();
for ( unsigned i = 0; i < v->Size(); ++i )
{
if ( i > 0 )
d.Add(sep->CheckString(), 0);
v->Lookup(i+1)->Describe(&d);
}
BroString* s = new BroString(1, d.TakeBytes(), d.Len());
s->SetUseFreeToDelete(true);
return new StringVal(s);
%}
## Returns an edited version of a string that applies a special
## "backspace character" (usually ``\x08`` for backspace or ``\x7f`` for DEL).
## For ## example, ``edit("hello there", "e")`` returns ``"llo t"``.
##
## arg_s: The string to edit.
##
## arg_edit_char: A string of exactly one character that represents the
## "backspace character". If it is longer than one character Bro
## generates a run-time error and uses the first character in
## the string.
##
## Returns: An edited version of *arg_s* where *arg_edit_char* triggers the
## deletetion of the last character.
##
## .. bro:see:: clean
## to_string_literal
## escape_string
## strip
function edit%(arg_s: string, arg_edit_char: string%): string
%{
if ( arg_edit_char->Len() != 1 )
@ -184,11 +265,28 @@ function edit%(arg_s: string, arg_edit_char: string%): string
return new StringVal(new BroString(1, byte_vec(new_s), ind));
%}
## Returns the number of characters (bytes) in the given string. The
## length computation includes any embedded NULs, and also a trailing NUL,
## if any (which is why the function isn't called ``strlen``; to remind
## the user that Bro strings can include NULs).
##
## s: The string to compute the length for.
##
## Returns: The number of characters in *s*.
function byte_len%(s: string%): count
%{
return new Val(s->Len(), TYPE_COUNT);
%}
## Get a substring of from a string, given a starting position length.
##
## s: The string to obtain a substring from.
##
## start: The starting position of the substring in *s*
##
## n: The number of characters to extract, beginning at *start*.
##
## Returns: A substring of *s* of length *n* from position *start*.
function sub_bytes%(s: string, start: count, n: int%): string
%{
if ( start > 0 )
@ -368,42 +466,94 @@ Val* do_sub(StringVal* str_val, RE_Matcher* re, StringVal* repl, int do_all)
}
%%}
# Similar to split in awk.
## Splits a string into an array of strings according to a pattern.
##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## Returns: An array of strings where each element corresponds to a substring
## in *str* separated by *re*.
##
## .. bro:see:: split1 split_all split_n str_split
##
## .. note:: The returned table starts at index 1. Note that conceptually the
## return value is meant to be a vector and this might change in the
## future.
##
function split%(str: string, re: pattern%): string_array
%{
return do_split(str, re, 0, 0, 0);
%}
# split1(str, pattern, include_separator): table[count] of string
#
# Same as split, except that str is only split (if possible) at the
# earliest position and an array of two strings is returned.
# An array of one string is returned when str cannot be splitted.
## Splits a string *once* into a a two-element array of strings according to a
## pattern. This function is the same as :bro:id:`split`, but * is only split
## once (if possible) at the earliest position and an array of two strings is
## returned.
##
## str: The string to split.
##
## re: The pattern describing the separator to split *str* in two pieces.
##
## Returns: An array of strings with two elements in which the first represents
## the substring in *str* up to the first occurence of *re*, and the
## second everything after *re*. An array of one string is returned
## when *s* cannot be split.
##
## .. bro:see:: split split_all split_n str_split
function split1%(str: string, re: pattern%): string_array
%{
return do_split(str, re, 0, 0, 1);
%}
# Same as split, except that the array returned by split_all also
# includes parts of string that match the pattern in the array.
# For example, split_all("a-b--cd", /(\-)+/) returns {"a", "-", "b",
# "--", "cd"}: odd-indexed elements do not match the pattern
# and even-indexed ones do.
## Splits a string into an array of strings according to a pattern. This
## function is the same as :bro:id:`split`, except that the separators are
## returned as well. For example, ``split_all("a-b--cd", /(\-)+/)`` returns
## ``{"a", "-", "b", "--", "cd"}``: odd-indexed elements do not match the
## pattern and even-indexed ones do.
##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## Returns: An array of strings where each two successive elements correspond
## to a substring in *str* of the part not matching *re* (odd-indexed)
## and thei part that matches *re* (even-indexed).
##
## .. bro:see:: split split1 split_n str_split
function split_all%(str: string, re: pattern%): string_array
%{
return do_split(str, re, 0, 1, 0);
%}
## Splits a string a given number of times into an array of strings according
## to a pattern. This function is similar to :bro:id:`split1` and
## :bro:id:`split_all`, but with customizable behavior with respect to
## including separators in the result and the number of times to split.
##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## incl_sep: A flag indicating whether to include the separator matches in the
## result (as in :bro:id:`split_all`).
##
## max_num_sep: The number of times to split *str*.
##
## Returns: An array of strings where, if *incl_sep* is true, each two
## successive elements correspond to a substring in *str* of the part
## not matching *re* (odd-indexed) and the part that matches *re*
## (even-indexed).
##
## .. bro:see:: split split1 split_all str_split
function split_n%(str: string, re: pattern,
incl_sep: bool, max_num_sep: count%): string_array
%{
return do_split(str, re, 0, incl_sep, max_num_sep);
%}
## Deprecated. Will be removed.
# Reason: the parameter ``other`` does nothing.
function split_complete%(str: string,
re: pattern, other: string_set,
incl_sep: bool, max_num_sep: count%): string_array
@ -411,22 +561,65 @@ function split_complete%(str: string,
return do_split(str, re, other->AsTableVal(), incl_sep, max_num_sep);
%}
## Substitutes a given replacement string for the first occurrence of a pattern
## in a given string.
##
## str: The string to perform the substitution in.
##
## re: The pattern being replaced with *repl*.
##
## repl: The string that replacs *re*.
##
## Returns: A copy of *str* with the first occurence of *re* replaced with
## *repl*.
##
## .. bro:see:: gsub subst_string
function sub%(str: string, re: pattern, repl: string%): string
%{
return do_sub(str, re, repl, 0);
%}
## Substitutes a given replacement string for the all occurrences of a pattern
## in a given string.
##
## str: The string to perform the substitution in.
##
## re: The pattern being replaced with *repl*.
##
## repl: The string that replacs *re*.
##
## Returns: A copy of *str* with all occurences of *re* replaced with *repl*.
##
## .. bro:see:: sub subst_string
function gsub%(str: string, re: pattern, repl: string%): string
%{
return do_sub(str, re, repl, 1);
%}
## Lexicographically compares two string.
##
## s1: The first string.
##
## s2: The second string.
##
## Returns: An integer greater than, equal to, or less than 0 according as
## *s1* is greater than, equal to, or less than *s2*.
function strcmp%(s1: string, s2: string%): int
%{
return new Val(Bstr_cmp(s1->AsString(), s2->AsString()), TYPE_INT);
%}
# Returns 0 if $little is not found in $big.
## Locates the first occurrence of one string in another.
##
## big: The string to look in.
##
## little: The (smaller) string to find inside *big*.
##
## Returns: The location of *little* in *big* or 0 if *little* is not found in
## *big*.
##
## .. bro:see:: find_all find_last
function strstr%(big: string, little: string%): count
%{
return new Val(
@ -434,8 +627,17 @@ function strstr%(big: string, little: string%): count
TYPE_COUNT);
%}
# Substitute each (non-overlapping) appearance of $from in $s to $to,
# and return the resulting string.
## Substitutes each (non-overlapping) appearance of a string in another.
##
## s: The string in which to perform the substitution.
##
## from: The string to look for which is replaced with *to*.
##
## to: The string that replaces all occurrences of *from* in *s*.
##
## Returns: A copy of *s* where each occurrence of *from* is replaced with *to*.
##
## .. bro:see:: sub gsub
function subst_string%(s: string, from: string, to: string%): string
%{
const int little_len = from->Len();
@ -478,6 +680,15 @@ function subst_string%(s: string, from: string, to: string%): string
return new StringVal(concatenate(vs));
%}
## Replaces all uppercase letters in a string with their lowercase counterpart.
##
## str: The string to convert to lowercase letters.
##
## Returns: A copy of the given string with the uppercase letters (as indicated
## by ``isascii`` and \verb|isupper|``) folded to lowercase
## (via ``tolower``).
##
## .. bro:see:: to_upper is_ascii
function to_lower%(str: string%): string
%{
const u_char* s = str->Bytes();
@ -498,6 +709,15 @@ function to_lower%(str: string%): string
return new StringVal(new BroString(1, lower_s, n));
%}
## Replaces all lowercase letters in a string with their uppercase counterpart.
##
## str: The string to convert to uppercase letters.
##
## Returns: A copy of the given string with the lowercase letters (as indicated
## by ``isascii`` and \verb|islower|``) folded to uppercase
## (via ``toupper``).
##
## .. bro:see:: to_lower is_ascii
function to_upper%(str: string%): string
%{
const u_char* s = str->Bytes();
@ -518,18 +738,54 @@ function to_upper%(str: string%): string
return new StringVal(new BroString(1, upper_s, n));
%}
## Replaces non-printable characters in a string with escaped sequences. The
## mappings are:
##
## - ``NUL`` to ``\0``
## - ``DEL`` to ``^?``
## - values <= 26 to ``^[A-Z]``
## - values not in *[32, 126]** to ``%XX``
##
## If the string does not yet have a trailing NUL, one is added.
##
## str: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: to_string_literal escape_string
function clean%(str: string%): string
%{
char* s = str->AsString()->Render();
return new StringVal(new BroString(1, byte_vec(s), strlen(s)));
%}
## Replaces non-printable characters in a string with escaped sequences. The
## mappings are:
##
## - ``NUL`` to ``\0``
## - ``DEL`` to ``^?``
## - values <= 26 to ``^[A-Z]``
## - values not in *[32, 126]** to ``%XX``
##
## str: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: clean escape_string
function to_string_literal%(str: string%): string
%{
char* s = str->AsString()->Render(BroString::BRO_STRING_LITERAL);
return new StringVal(new BroString(1, byte_vec(s), strlen(s)));
%}
## Determines whether a given string contains only ASCII characters.
##
## str: The string to examine.
##
## Returns: False if any byte value of *str* is greater than 127, and true
## otherwise.
##
## .. bro:see:: to_upper to_lower
function is_ascii%(str: string%): bool
%{
int n = str->Len();
@ -542,7 +798,14 @@ function is_ascii%(str: string%): bool
return new Val(1, TYPE_BOOL);
%}
# Make printable version of string.
## Creates a printable version of a string. This function is the same as
## :bro:id:`clean` except that non-printable characters are removed.
##
## s: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: clean to_string_literal
function escape_string%(s: string%): string
%{
char* escstr = s->AsString()->Render();
@ -551,7 +814,12 @@ function escape_string%(s: string%): string
return val;
%}
# Returns an ASCII hexadecimal representation of a string.
## Returns an ASCII hexadecimal representation of a string.
##
## s: The string to convert to hex.
##
## Returns: A copy of *s* where each byte is replaced with the corresponding
## hex nibble.
function string_to_ascii_hex%(s: string%): string
%{
char* x = new char[s->Len() * 2 + 1];
@ -563,8 +831,15 @@ function string_to_ascii_hex%(s: string%): string
return new StringVal(new BroString(1, (u_char*) x, s->Len() * 2));
%}
function str_smith_waterman%(s1: string, s2: string, params: sw_params%)
: sw_substring_vec
## Uses the Smith Waterman algorithm to find similar/overlapping substrings.
## See `Wikipedia <http://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm>`_.
##
## s1: The first string.
##
## s2: The second string.
##
## Returns: The result of the Smit Waterman algorithm calculation.
function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_substring_vec
%{
SWParams sw_params(params->AsRecordVal()->Lookup(0)->AsCount(),
SWVariant(params->AsRecordVal()->Lookup(1)->AsCount()));
@ -578,6 +853,16 @@ function str_smith_waterman%(s1: string, s2: string, params: sw_params%)
return result;
%}
## Splits a string into substrings with the help of an index vector of cutting
## points.
##
## s: The string to split.
##
## idx: The index vector (``vector of count``) with the cutting points.
##
## Returns: A vector of strings.
##
## .. bro:see:: split split1 split_all split_n
function str_split%(s: string, idx: index_vec%): string_vec
%{
vector<Val*>* idx_v = idx->AsVector();
@ -606,6 +891,13 @@ function str_split%(s: string, idx: index_vec%): string_vec
return result_v;
%}
## Strips whitespace at both ends of a string.
##
## str: The string to strip the whitespace from.
##
## Returns: A copy of *str* with leading and trailing whitespace removed.
##
## .. bro:see:: sub gsub
function strip%(str: string%): string
%{
const u_char* s = str->Bytes();
@ -629,6 +921,14 @@ function strip%(str: string%): string
return new StringVal(new BroString(sp, (e - sp + 1), 1));
%}
## Generates a string of a given size and fills it with repetitions of a source
## string.
##
## len: The length of the output string.
##
## source: The string to concatenate repeatedly until *len* has been reached.
##
## Returns: A string of length *len* filled with *source*.
function string_fill%(len: int, source: string%): string
%{
const u_char* src = source->Bytes();
@ -643,10 +943,15 @@ function string_fill%(len: int, source: string%): string
return new StringVal(new BroString(1, byte_vec(dst), len));
%}
# Takes a string and escapes characters that would allow execution of commands
# at the shell level. Must be used before including strings in system() or
# similar calls.
#
## Takes a string and escapes characters that would allow execution of
## commands at the shell level. Must be used before including strings in
## :bro:id:`system` or similar calls.
##
## source: The string to escape.
##
## Returns: A shell-escaped version of *source*.
##
## .. bro:see:: system
function str_shell_escape%(source: string%): string
%{
unsigned j = 0;
@ -675,8 +980,15 @@ function str_shell_escape%(source: string%): string
return new StringVal(new BroString(1, dst, j));
%}
# Returns all occurrences of the given pattern in the given string (an empty
# empty set if none).
## Finds all occurrences of a pattern in a string.
##
## str: The string to inspect.
##
## re: The pattern to look for in *str*.
##
## Returns: The set of strings in *str* that match *re*, or the empty set.
##
## .. bro:see: find_last strstr
function find_all%(str: string, re: pattern%) : string_set
%{
TableVal* a = new TableVal(internal_type("string_set")->AsTableType());
@ -697,11 +1009,18 @@ function find_all%(str: string, re: pattern%) : string_set
return a;
%}
# Returns the last occurrence of the given pattern in the given string.
# If not found, returns an empty string. Note that this function returns
# the match that starts at the largest index in the string, which is
# not necessarily the longest match. For example, a pattern of /.*/
# will return the final character in the string.
## Finds the last occurrence of a pattern in a string. This function returns
## the match that starts at the largest index in the string, which is not
## necessarily the longest match. For example, a pattern of ``/.*/`` will
## return the final character in the string.
##
## str: The string to inspect.
##
## re: The pattern to look for in *str*.
##
## Returns: The last string in *str* that matches *re*, or the empty string.
##
## .. bro:see: find_all strstr
function find_last%(str: string, re: pattern%) : string
%{
const u_char* s = str->Bytes();
@ -717,10 +1036,16 @@ function find_last%(str: string, re: pattern%) : string
return new StringVal("");
%}
# Returns a hex dump for given input data. The hex dump renders
# 16 bytes per line, with hex on the left and ASCII (where printable)
# on the right. Based on Netdude's hex editor code.
#
## Returns a hex dump for given input data. The hex dump renders 16 bytes per
## line, with hex on the left and ASCII (where printable)
## on the right.
##
## data_str: The string to dump in hex format.
##
## .. bro:see:: string_to_ascii_hex bytestring_to_hexstr
##
## .. note:: Based on Netdude's hex editor code.
##
function hexdump%(data_str: string%) : string
%{