diff --git a/aux/btest b/aux/btest
index 35bb074c1c..9726c5b982 160000
--- a/aux/btest
+++ b/aux/btest
@@ -1 +1 @@
-Subproject commit 35bb074c1c5173e44689df680a24ba13fea39a11
+Subproject commit 9726c5b982ee0e3e730a15dcd65f49bdee3fe458
diff --git a/doc/conf.py.in b/doc/conf.py.in
index 8ca8d70a7a..e5e093d498 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -41,10 +41,10 @@ btest_tests="doc/sphinx"
# 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', 'sphinx.ext.todo', 'adapt-toc',
- 'rootedliteralinclude']
+extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
os.environ["BRO_SRC_ROOT"] = "@CMAKE_SOURCE_DIR@"
+os.environ["DOC_ROOT"] = "@CMAKE_SOURCE_DIR@/doc"
# Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@@ -83,7 +83,7 @@ today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = []
+exclude_patterns = [".#*"]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
diff --git a/doc/ext/rootedliteralinclude.py b/doc/ext/rootedliteralinclude.py
deleted file mode 100644
index 7b4aea5547..0000000000
--- a/doc/ext/rootedliteralinclude.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import os
-from sphinx.directives.code import LiteralInclude
-
-def setup(app):
- app.add_directive('rootedliteralinclude', RootedLiteralInclude)
-
-class RootedLiteralInclude(LiteralInclude):
- """
- Like ``.. literalinclude::``, but the argument is an absolute path
- which may contain environment variables which will be expanded when
- generating documents.
- """
-
- def run(self):
- document = self.state.document
- if not document.settings.file_insertion_enabled:
- return [document.reporter.warning('File insertion disabled',
- line=self.lineno)]
- env = document.settings.env
-
- expanded_arg = os.path.expandvars(self.arguments[0])
- sphinx_src_relation = os.path.relpath(expanded_arg, env.srcdir)
- self.arguments[0] = os.path.join(os.sep, sphinx_src_relation)
-
- return super(RootedLiteralInclude, self).run()
diff --git a/doc/index.rst b/doc/index.rst
index 5afbb022a1..2dee7a4fb2 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -9,8 +9,8 @@ Bro Documentation
:maxdepth: 2
intro/index.rst
- quickstart/index.rst
install/index.rst
+ quickstart/index.rst
using/index.rst
scripting/index.rst
frameworks/index.rst
diff --git a/doc/install/changes.rst b/doc/install/changes.rst
index 5a1bd97220..32cd6ad33e 100644
--- a/doc/install/changes.rst
+++ b/doc/install/changes.rst
@@ -1,7 +1,7 @@
-===========================================
-Comprehensive Version History (aka CHANGES)
-===========================================
+========================
+Detailed Version History
+========================
.. contents::
diff --git a/doc/quickstart/index.rst b/doc/quickstart/index.rst
index 89de40e948..e07e729a02 100644
--- a/doc/quickstart/index.rst
+++ b/doc/quickstart/index.rst
@@ -7,9 +7,6 @@ Quick Start Guide
.. contents::
-Installation
-============
-
Bro works on most modern, Unix-based systems and requires no custom
hardware. It can be downloaded in either pre-built binary package or
source code forms. See :ref:`installing-bro` for instructions on how to
diff --git a/doc/scripting/connection_record_01.bro b/doc/scripting/connection_record_01.bro
new file mode 100644
index 0000000000..9800fb0520
--- /dev/null
+++ b/doc/scripting/connection_record_01.bro
@@ -0,0 +1,6 @@
+@load base/protocols/conn
+
+event connection_state_remove(c: connection)
+ {
+ print c;
+ }
diff --git a/doc/scripting/connection_record_02.bro b/doc/scripting/connection_record_02.bro
new file mode 100644
index 0000000000..4459e47ef6
--- /dev/null
+++ b/doc/scripting/connection_record_02.bro
@@ -0,0 +1,7 @@
+@load base/protocols/conn
+@load base/protocols/dns
+
+event connection_state_remove(c: connection)
+ {
+ print c;
+ }
diff --git a/doc/scripting/data_struct_record_01.bro b/doc/scripting/data_struct_record_01.bro
new file mode 100644
index 0000000000..a80d30faae
--- /dev/null
+++ b/doc/scripting/data_struct_record_01.bro
@@ -0,0 +1,22 @@
+type Service: record {
+ name: string;
+ ports: set[port];
+ rfc: count;
+};
+
+function print_service(serv: Service): string
+ {
+ print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
+
+ for ( p in serv$ports )
+ print fmt(" port: %s", p);
+ }
+
+event bro_init()
+ {
+ local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
+ local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+
+ print_service(dns);
+ print_service(http);
+ }
diff --git a/testing/btest/doc/manual/data_struct_record_02.bro b/doc/scripting/data_struct_record_02.bro
similarity index 86%
rename from testing/btest/doc/manual/data_struct_record_02.bro
rename to doc/scripting/data_struct_record_02.bro
index e340bc5744..b10b3feac0 100644
--- a/testing/btest/doc/manual/data_struct_record_02.bro
+++ b/doc/scripting/data_struct_record_02.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
type Service: record {
name: string;
ports: set[port];
@@ -12,23 +9,20 @@ type System: record {
services: set[Service];
};
-
function print_service(serv: Service): string
{
print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
- for (p in serv$ports)
- {
+
+ for ( p in serv$ports )
print fmt(" port: %s", p);
- }
}
function print_system(sys: System): string
{
print fmt("System: %s", sys$name);
- for (s in sys$services)
- {
+
+ for ( s in sys$services )
print_service(s);
- }
}
event bro_init()
diff --git a/testing/btest/doc/manual/data_struct_set_declaration.bro b/doc/scripting/data_struct_set_declaration.bro
similarity index 79%
rename from testing/btest/doc/manual/data_struct_set_declaration.bro
rename to doc/scripting/data_struct_set_declaration.bro
index 269cb3d328..94d53c7b66 100644
--- a/testing/btest/doc/manual/data_struct_set_declaration.bro
+++ b/doc/scripting/data_struct_set_declaration.bro
@@ -1,10 +1,8 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local ssl_ports: set[port];
local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
+
# SSH
add ssl_ports[22/tcp];
# HTTPS
@@ -14,17 +12,11 @@ event bro_init()
# Check for SMTPS
if ( 587/tcp !in ssl_ports )
- {
add ssl_ports[587/tcp];
- }
for ( i in ssl_ports )
- {
print fmt("SSL Port: %s", i);
- }
for ( i in non_ssl_ports )
- {
print fmt("Non-SSL Port: %s", i);
- }
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/data_struct_table_complex.bro b/doc/scripting/data_struct_table_complex.bro
similarity index 88%
rename from testing/btest/doc/manual/data_struct_table_complex.bro
rename to doc/scripting/data_struct_table_complex.bro
index 4ecd51aace..d04cee5a16 100644
--- a/testing/btest/doc/manual/data_struct_table_complex.bro
+++ b/doc/scripting/data_struct_table_complex.bro
@@ -1,17 +1,13 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local samurai_flicks: table[string, string, count, string] of string;
+
samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru";
samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin";
samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri";
samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei";
for ( [d, s, y, a] in samurai_flicks )
- {
print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a);
- }
}
diff --git a/testing/btest/doc/manual/data_struct_table_declaration.bro b/doc/scripting/data_struct_table_declaration.bro
similarity index 77%
rename from testing/btest/doc/manual/data_struct_table_declaration.bro
rename to doc/scripting/data_struct_table_declaration.bro
index 36abd0db1b..ab637f4c25 100644
--- a/testing/btest/doc/manual/data_struct_table_declaration.bro
+++ b/doc/scripting/data_struct_table_declaration.bro
@@ -1,19 +1,13 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local ssl_services: table[string] of port;
+
ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp);
ssl_services["IMAPS"] = 993/tcp;
if ( "SMTPS" !in ssl_services )
- {
ssl_services["SMTPS"] = 587/tcp;
- }
for ( k in ssl_services )
- {
print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]);
- }
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/data_struct_vector.bro b/doc/scripting/data_struct_vector.bro
similarity index 67%
rename from testing/btest/doc/manual/data_struct_vector.bro
rename to doc/scripting/data_struct_vector.bro
index 99d0b4dc6d..0c93f6cd41 100644
--- a/testing/btest/doc/manual/data_struct_vector.bro
+++ b/doc/scripting/data_struct_vector.bro
@@ -1,10 +1,7 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local v: vector of count = vector(1, 2, 3, 4);
local w = vector(1, 2, 3, 4);
print v;
print w;
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/data_struct_vector_declaration.bro b/doc/scripting/data_struct_vector_declaration.bro
similarity index 83%
rename from testing/btest/doc/manual/data_struct_vector_declaration.bro
rename to doc/scripting/data_struct_vector_declaration.bro
index 06fe48aeec..d64754b97b 100644
--- a/testing/btest/doc/manual/data_struct_vector_declaration.bro
+++ b/doc/scripting/data_struct_vector_declaration.bro
@@ -1,16 +1,15 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local v1: vector of count;
local v2 = vector(1, 2, 3, 4);
+
v1[|v1|] = 1;
v1[|v1|] = 2;
v1[|v1|] = 3;
v1[|v1|] = 4;
+
print fmt("contents of v1: %s", v1);
print fmt("length of v1: %d", |v1|);
print fmt("contents of v1: %s", v2);
print fmt("length of v2: %d", |v2|);
- }
\ No newline at end of file
+ }
diff --git a/doc/scripting/data_struct_vector_iter.bro b/doc/scripting/data_struct_vector_iter.bro
new file mode 100644
index 0000000000..01a5ff4cd2
--- /dev/null
+++ b/doc/scripting/data_struct_vector_iter.bro
@@ -0,0 +1,7 @@
+event bro_init()
+ {
+ local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6);
+
+ for (i in addr_vector)
+ print mask_addr(addr_vector[i], 18);
+ }
diff --git a/doc/scripting/data_type_const.bro b/doc/scripting/data_type_const.bro
new file mode 100644
index 0000000000..fbfd79a21e
--- /dev/null
+++ b/doc/scripting/data_type_const.bro
@@ -0,0 +1,9 @@
+const port_list: table[port] of string &redef;
+
+redef port_list += { [6666/tcp] = "IRC"};
+redef port_list += { [80/tcp] = "WWW" };
+
+event bro_init()
+ {
+ print port_list;
+ }
diff --git a/testing/btest/doc/manual/data_type_const_simple.bro b/doc/scripting/data_type_const_simple.bro
similarity index 53%
rename from testing/btest/doc/manual/data_type_const_simple.bro
rename to doc/scripting/data_type_const_simple.bro
index e32f740614..4e843fc2ac 100644
--- a/testing/btest/doc/manual/data_type_const_simple.bro
+++ b/doc/scripting/data_type_const_simple.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro -b %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
@load base/protocols/http
redef HTTP::default_capture_password = T;
diff --git a/doc/scripting/data_type_declaration.bro b/doc/scripting/data_type_declaration.bro
new file mode 100644
index 0000000000..55b9d1cd1c
--- /dev/null
+++ b/doc/scripting/data_type_declaration.bro
@@ -0,0 +1,9 @@
+event bro_init()
+ {
+ local a: int;
+ a = 10;
+ local b = 10;
+
+ if ( a == b )
+ print fmt("A: %d, B: %d", a, b);
+ }
diff --git a/testing/btest/doc/manual/data_type_interval.bro b/doc/scripting/data_type_interval.bro
similarity index 80%
rename from testing/btest/doc/manual/data_type_interval.bro
rename to doc/scripting/data_type_interval.bro
index 869715b76c..491c0d129c 100644
--- a/testing/btest/doc/manual/data_type_interval.bro
+++ b/doc/scripting/data_type_interval.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
# Store the time the previous connection was established.
global last_connection_time: time;
@@ -8,13 +5,14 @@ global last_connection_time: time;
global connection_seen: bool = F;
event connection_established(c: connection)
- {
+ {
local net_time: time = network_time();
+
print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h);
- if (connection_seen)
- {
+
+ if ( connection_seen )
print fmt(" Time since last connection: %s", net_time - last_connection_time);
- }
+
last_connection_time = net_time;
connection_seen = T;
- }
\ No newline at end of file
+ }
diff --git a/doc/scripting/data_type_local.bro b/doc/scripting/data_type_local.bro
new file mode 100644
index 0000000000..dfd4eb0a2a
--- /dev/null
+++ b/doc/scripting/data_type_local.bro
@@ -0,0 +1,11 @@
+function add_two(i: count): count
+ {
+ local added_two = i+2;
+ print fmt("i + 2 = %d", added_two);
+ return added_two;
+ }
+
+event bro_init()
+ {
+ local test = add_two(10);
+ }
diff --git a/testing/btest/doc/manual/data_type_pattern_01.bro b/doc/scripting/data_type_pattern_01.bro
similarity index 73%
rename from testing/btest/doc/manual/data_type_pattern_01.bro
rename to doc/scripting/data_type_pattern_01.bro
index 09b92773a3..08378dd124 100644
--- a/testing/btest/doc/manual/data_type_pattern_01.bro
+++ b/doc/scripting/data_type_pattern_01.bro
@@ -1,14 +1,13 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local test_string = "The quick brown fox jumped over the lazy dog.";
local test_pattern = /quick|lazy/;
- if (test_pattern in test_string)
+ if ( test_pattern in test_string )
+ {
local results = split(test_string, test_pattern);
print results[1];
print results[2];
print results[3];
- }
\ No newline at end of file
+ }
+ }
diff --git a/testing/btest/doc/manual/data_type_pattern_02.bro b/doc/scripting/data_type_pattern_02.bro
similarity index 85%
rename from testing/btest/doc/manual/data_type_pattern_02.bro
rename to doc/scripting/data_type_pattern_02.bro
index f4621cfb90..071ed2b6c1 100644
--- a/testing/btest/doc/manual/data_type_pattern_02.bro
+++ b/doc/scripting/data_type_pattern_02.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
event bro_init()
{
local test_string = "equality";
@@ -11,4 +8,3 @@ event bro_init()
test_pattern = /equality/;
print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
}
-
diff --git a/doc/scripting/data_type_subnets.bro b/doc/scripting/data_type_subnets.bro
new file mode 100644
index 0000000000..1676033003
--- /dev/null
+++ b/doc/scripting/data_type_subnets.bro
@@ -0,0 +1,15 @@
+event bro_init()
+ {
+ local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20);
+ local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1);
+
+ for ( a in addresses )
+ {
+ for ( s in subnets )
+ {
+ if ( addresses[a] in subnets[s] )
+ print fmt("%s belongs to subnet %s", addresses[a], subnets[s]);
+ }
+ }
+
+ }
diff --git a/doc/scripting/data_type_time.bro b/doc/scripting/data_type_time.bro
new file mode 100644
index 0000000000..6d09878205
--- /dev/null
+++ b/doc/scripting/data_type_time.bro
@@ -0,0 +1,4 @@
+event connection_established(c: connection)
+ {
+ print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h);
+ }
diff --git a/doc/scripting/framework_logging_factorial_01.bro b/doc/scripting/framework_logging_factorial_01.bro
new file mode 100644
index 0000000000..e4a171ebb6
--- /dev/null
+++ b/doc/scripting/framework_logging_factorial_01.bro
@@ -0,0 +1,19 @@
+module Factor;
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+ else
+ return ( n * factorial(n - 1) );
+ }
+
+event bro_init()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+ for ( n in numbers )
+ print fmt("%d", factorial(numbers[n]));
+ }
+
+
diff --git a/testing/btest/doc/manual/framework_logging_factorial_02.bro b/doc/scripting/framework_logging_factorial_02.bro
similarity index 84%
rename from testing/btest/doc/manual/framework_logging_factorial_02.bro
rename to doc/scripting/framework_logging_factorial_02.bro
index 2a6fb10d1a..abdbea605b 100644
--- a/testing/btest/doc/manual/framework_logging_factorial_02.bro
+++ b/doc/scripting/framework_logging_factorial_02.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff factor.log
-
module Factor;
export {
@@ -15,13 +12,10 @@ export {
function factorial(n: count): count
{
if ( n == 0 )
- {
return 1;
- }
+
else
- {
return ( n * factorial(n - 1) );
- }
}
event bro_init()
@@ -33,8 +27,6 @@ event bro_done()
{
local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for ( n in numbers )
- {
Log::write( Factor::LOG, [$num=numbers[n],
$factorial_num=factorial(numbers[n])]);
- }
}
diff --git a/testing/btest/doc/manual/framework_logging_factorial_03.bro b/doc/scripting/framework_logging_factorial_03.bro
similarity index 77%
rename from testing/btest/doc/manual/framework_logging_factorial_03.bro
rename to doc/scripting/framework_logging_factorial_03.bro
index 967229bd94..c99cca2c1d 100644
--- a/testing/btest/doc/manual/framework_logging_factorial_03.bro
+++ b/doc/scripting/framework_logging_factorial_03.bro
@@ -1,7 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff factor-mod5.log
-# @TEST-EXEC: btest-diff factor-non5.log
-
module Factor;
export {
@@ -16,45 +12,34 @@ export {
function factorial(n: count): count
{
if ( n == 0 )
- {
return 1;
- }
+
else
- {
- return ( n * factorial(n - 1) );
- }
- }
-
-event bro_init()
- {
- Log::create_stream(LOG, [$columns=Info]);
+ return (n * factorial(n - 1));
}
event bro_done()
{
local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for ( n in numbers )
- {
Log::write( Factor::LOG, [$num=numbers[n],
$factorial_num=factorial(numbers[n])]);
- }
}
function mod5(id: Log::ID, path: string, rec: Factor::Info) : string
{
if ( rec$factorial_num % 5 == 0 )
- {
return "factor-mod5";
- }
+
else
- {
return "factor-non5";
- }
}
event bro_init()
{
+ Log::create_stream(LOG, [$columns=Info]);
+
local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
Log::add_filter(Factor::LOG, filter);
Log::remove_filter(Factor::LOG, "default");
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/framework_logging_factorial_04.bro b/doc/scripting/framework_logging_factorial_04.bro
similarity index 80%
rename from testing/btest/doc/manual/framework_logging_factorial_04.bro
rename to doc/scripting/framework_logging_factorial_04.bro
index 49aef83ffc..a563069c46 100644
--- a/testing/btest/doc/manual/framework_logging_factorial_04.bro
+++ b/doc/scripting/framework_logging_factorial_04.bro
@@ -1,7 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff factor-mod5.log
-# @TEST-EXEC: btest-diff factor-non5.log
-
module Factor;
export {
@@ -18,13 +14,10 @@ export {
function factorial(n: count): count
{
if ( n == 0 )
- {
return 1;
- }
+
else
- {
- return ( n * factorial(n - 1) );
- }
+ return (n * factorial(n - 1));
}
event bro_init()
@@ -36,22 +29,17 @@ event bro_done()
{
local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for ( n in numbers )
- {
Log::write( Factor::LOG, [$num=numbers[n],
$factorial_num=factorial(numbers[n])]);
- }
}
function mod5(id: Log::ID, path: string, rec: Factor::Info) : string
{
if ( rec$factorial_num % 5 == 0 )
- {
return "factor-mod5";
- }
+
else
- {
return "factor-non5";
- }
}
event bro_init()
@@ -59,4 +47,4 @@ event bro_init()
local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
Log::add_filter(Factor::LOG, filter);
Log::remove_filter(Factor::LOG, "default");
- }
\ No newline at end of file
+ }
diff --git a/doc/scripting/framework_notice_hook_01.bro b/doc/scripting/framework_notice_hook_01.bro
new file mode 100644
index 0000000000..7c4980a896
--- /dev/null
+++ b/doc/scripting/framework_notice_hook_01.bro
@@ -0,0 +1,7 @@
+@load policy/protocols/ssh/interesting-hostnames.bro
+
+hook Notice::policy(n: Notice::Info)
+ {
+ if ( n$note == SSH::Interesting_Hostname_Login )
+ add n$actions[Notice::ACTION_EMAIL];
+ }
diff --git a/doc/scripting/framework_notice_hook_suppression_01.bro b/doc/scripting/framework_notice_hook_suppression_01.bro
new file mode 100644
index 0000000000..93bb988e25
--- /dev/null
+++ b/doc/scripting/framework_notice_hook_suppression_01.bro
@@ -0,0 +1,7 @@
+@load policy/protocols/ssl/expiring-certs.bro
+
+hook Notice::policy(n: Notice::Info)
+ {
+ if ( n$note == SSL::Certificate_Expires_Soon )
+ n$suppress_for = 12hrs;
+ }
diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_01.bro b/doc/scripting/framework_notice_shortcuts_01.bro
similarity index 74%
rename from testing/btest/doc/manual/framework_notice_shortcuts_01.bro
rename to doc/scripting/framework_notice_shortcuts_01.bro
index d1d2f19312..cd51abd5b5 100644
--- a/testing/btest/doc/manual/framework_notice_shortcuts_01.bro
+++ b/doc/scripting/framework_notice_shortcuts_01.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
@load policy/protocols/ssh/interesting-hostnames.bro
@load base/protocols/ssh/
diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_02.bro b/doc/scripting/framework_notice_shortcuts_02.bro
similarity index 77%
rename from testing/btest/doc/manual/framework_notice_shortcuts_02.bro
rename to doc/scripting/framework_notice_shortcuts_02.bro
index 5d05fdc775..ac427ac8b7 100644
--- a/testing/btest/doc/manual/framework_notice_shortcuts_02.bro
+++ b/doc/scripting/framework_notice_shortcuts_02.bro
@@ -1,6 +1,3 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
@load policy/protocols/ssh/interesting-hostnames.bro
@load base/protocols/ssh/
diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst
index 0610589004..a9826d9b3f 100644
--- a/doc/scripting/index.rst
+++ b/doc/scripting/index.rst
@@ -1,6 +1,8 @@
.. _writing-scripts:
+.. contents::
+
===================
Writing Bro Scripts
===================
@@ -8,119 +10,120 @@ Writing Bro Scripts
Understanding Bro Scripts
=========================
-Bro includes an event queue driven scripting language that provides
+.. todo::
+
+ The MHR integration has changed significantly since the text was
+ written. We need to update it, however I'm actually not sure this
+ script is a good introductory example anymore unfortunately.
+ -Robin
+
+Bro includes an event-driven scripting language that provides
the primary means for an organization to extend and customize Bro's
-functionality. An overwhelming amount of the output generated by Bro
+functionality. Virtually all of the output generated by Bro
is, in fact, generated by Bro scripts. It's almost easier to consider
Bro to be an entity behind-the-scenes processing connections and
generating events while Bro's scripting language is the medium through
which we mere mortals can achieve communication. Bro scripts
effectively notify Bro that should there be an event of a type we
define, then let us have the information about the connection so we
-can perform some function on it. For example, the ssl.log file is
+can perform some function on it. For example, the ``ssl.log`` file is
generated by a Bro script that walks the entire certificate chain and
issues notifications if any of the steps along the certificate chain
are invalid. This entire process is setup by telling Bro that should
-it see a server or client issue an SSL HELLO message, we want to know
+it see a server or client issue an SSL ``HELLO`` message, we want to know
about the information about that connection.
-It's often easier to understand Bro's scripting language by looking at
-a complete script and breaking it down into its identifiable
-components. In this example, we'll take a look at how Bro queries the
-Team Cymru Malware hash registry for detected downloads via HTTP. Part
-of the Team Cymru Malware Hash registry includes the ability to do a
-host lookup on a domain with the format
-MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or
-sha1 hash of a file. Team Cymru also populates the TXT record of
+It's often the easiest to understand Bro's scripting language by
+looking at a complete script and breaking it down into its
+identifiable components. In this example, we'll take a look at how
+Bro queries the `Team Cymru Malware hash registry
+`_ for downloads via
+HTTP. Part of the Team Cymru Malware Hash registry includes the
+ability to do a host lookup on a domain with the format
+``MALWARE_HASH.malware.hash.cymru.com`` where ``MALWARE_HASH`` is the MD5 or
+SHA1 hash of a file. Team Cymru also populates the TXT record of
their DNS responses with both a "last seen" timestamp and a numerical
"detection rate". The important aspect to understand is Bro already
generates hashes for files it can parse from HTTP streams, but the
script ``detect-MHR.bro`` is responsible for generating the
appropriate DNS lookup and parsing the response.
-
-.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro
Visually, there are three distinct sections of the script. A base
level with no indentation followed by an indented and formatted
-section explaining the custom variables being set (export) and another
+section explaining the custom variables being provided (``export``) and another
indented and formatted section describing the instructions for a
-specific event (event log_http). Don't get discouraged if you don't
+specific event (``event log_http``). Don't get discouraged if you don't
understand every section of the script; we'll cover the basics of the
script and much more in following sections.
-.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro
:lines: 7-11
Lines 7 and 8 of the script process the ``__load__.bro`` script in the
respective directories being loaded. The ``@load`` directives are
often considered good practice or even just good manners when writing
-Bro scripts that might be distributed. While it's unlikely that in a
+Bro scripts to make sure they can be
+used on their own. While it's unlikely that in a
full production deployment of Bro these additional resources wouldn't
already be loaded, it's not a bad habit to try to get into as you get
more experienced with Bro scripting. If you're just starting out,
this level of granularity might not be entirely necessary though.
-.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro
:lines: 12-24
The export section redefines an enumerable constant that describes the
type of notice we will generate with the logging framework. Bro
allows for redefinable constants, which at first, might seem
-counter-intuitive. We'll get more indepth with constants in a later
+counter-intuitive. We'll get more in-depth with constants in a later
chapter, for now, think of them as variables that can only be altered
before Bro starts running. The notice type listed allows for the use
-of the NOTICE() function to generate notices of type
-Malware_Hash_Registry_Match as done in the next section. Notices
+of the :bro:id:`NOTICE` function to generate notices of type
+``Malware_Hash_Registry_Match`` as done in the next section. Notices
allow Bro to generate some kind of extra notification beyond its
default log types. Often times, this extra notification comes in the
form of an email generated and sent to a pre-configured address.
-.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro
:lines: 26-44
The workhorse of the script is contained in the event handler for
``log_http``. The ``log_http`` event is defined as an event-hook in
-the base/protocols/http/main.bro script and allows scripts to handle a
-connection as it is being passed to the logging framework. The event
-handler is passed an HTTP::Info data structure which will be referred
-to as "rec" in body of the event handler.
+the :doc:`scripts/base/protocols/http/main.bro` script and allows scripts
+to handle a connection as it is being passed to the logging framework.
+The event handler is passed an :bro:id:`HTTP::Info` data structure
+which will be referred to as ``rec`` in body of the event handler.
-An if statement is used to check for the existence of a data structure
-named "md5" nested within the rec data structure. Bro uses the "$" as
+An ``if`` statement is used to check for the existence of a data structure
+named ``md5`` nested within the ``rec`` data structure. Bro uses the ``$`` as
a deference operator and as such, and it is employed in this script to
-check if rec$md5 is present by including the "?" operator within the
-path. If the rec data structure includes a nested data structure
-named "md5", the statement is processed as true and a local variable
-named "hash_domain" is provisioned and given a format string based on
-the contents of rec$md5 to produce a valid DNS lookup.
+check if ``rec$md5`` is present by including the ``?`` operator within the
+path. If the ``rec`` data structure includes a nested data structure
+named ``md5``, the statement is processed as true and a local variable
+named ``hash_domain`` is provisioned and given a format string based on
+the contents of ``rec$md5`` to produce a valid DNS lookup.
-The rest of the script is contained within a when() block. In short,
-a when block is used when Bro needs to perform asynchronous actions,
-such a DNS lookup, to ensure that performance isn't effected. The
-when() block performs a DNS TXT lookup and stores the result in the
-local variable MHR_result. Effectively, processing for this event
-continues and upon receipt of the values returned by
-lookup_hostname_txt(), the when block is executed. The when block
-splits the string returned into two seperate values and checks to
-ensure an expected format. If the format is invalid, the script
-assumes that the hash wasn't found in the respository and processing
-is concluded. If the format is as expected and the detection rate is
-above the threshold set by MHR_threshold, two new local variables are
-created and used in the notice issued by NOTICE().
+The rest of the script is contained within a ``when`` block. In
+short, a ``when`` block is used when Bro needs to perform asynchronous
+actions, such a DNS lookup, to ensure that performance isn't effected.
+The ``when`` block performs a DNS TXT lookup and stores the result
+in the local variable ``MHR_result``. Effectively, processing for
+this event continues and upon receipt of the values returned by
+:bro:id:`lookup_hostname_txt`, the ``when`` block is executed. The
+``when`` block splits the string returned into two seperate values and
+checks to ensure an expected format. If the format is invalid, the
+script assumes that the hash wasn't found in the respository and
+processing is concluded. If the format is as expected and the
+detection rate is above the threshold set by ``MHR_threshold``, two
+new local variables are created and used in the notice issued by
+:bro:id:`NOTICE`.
In approximately 15 lines of actual code, Bro provides an amazing
utility that would be incredibly difficult to implement and deploy
with other products. In truth, claiming that Bro does this in 15
-lines is a misdirection; There is a truly massive number of things
+lines is a misdirection; there is a truly massive number of things
going on behind-the-scenes in Bro, but it is the inclusion of the
scripting language that gives analysts access to those underlying
layers in a succinct and well defined manner.
@@ -150,7 +153,7 @@ write scripts for Bro but for understanding Bro itself.
Gaining familiarity with the specific events generated by Bro is a big
step towards building a mind set for working with Bro scripts. The
majority of events generated by Bro are defined in the
-built-in-function files or .bif files which also act as the basis for
+built-in-function files or ``.bif`` files which also act as the basis for
online event documentation. These in-line comments are compiled into
an online documentation system using Broxygen. Whether starting a
script from scratch or reading and maintaining someone else's script,
@@ -161,31 +164,32 @@ This effort resulted in built-in-function files organized such that
each entry contains a descriptive event name, the arguments passed to
the event, and a concise explanation of the functions use.
-.. literalinclude:: ../../../../build/src/base/event.bif.bro
- :language: bro
- :linenos:
- :lines: 4124-4149
+.. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro
+ :lines: 29-54
-Above is a segment of the documentation for the event dns_request().
-It's organized such that the documentation, commentary, and list of
-arguments precede the actual event definition used by Bro. As Bro
-detects DNS requests being issued by an originator, it issues this
-event and any number of scripts then have access to the data Bro
-passes along with the event. In this example, Bro passes not only the
-message, the query, query type and query class for the DNS request,
-but also a then record used for the connection itself.
+Above is a segment of the documentation for the event
+:bro:id:`dns_request` (and the preceeding link points to the
+documentation generated out of that). It's organized such that the
+documentation, commentary, and list of arguments precede the actual
+event definition used by Bro. As Bro detects DNS requests being
+issued by an originator, it issues this event and any number of
+scripts then have access to the data Bro passes along with the event.
+In this example, Bro passes not only the message, the query, query
+type and query class for the DNS request, but also a then record used
+for the connection itself.
The Connection Record Data Type
===============================
Of all the events defined by Bro, an overwhelmingly large number of
-them are passed the connection record data type, in effect, making it
-the backbone of many scripting solutions. The connection record
-itself, as we will see in a moment, is a mass of nested data types
-used to track state on a connection through its lifetime. Let's walk
-through the process of selecting an appropriate event, generating some
-output to standard out and dissecting the connection record so as to
-get an overview of it. We will cover data types in more detail later.
+them are passed the :bro:id:`connection` record data type, in effect,
+making it the backbone of many scripting solutions. The connection
+record itself, as we will see in a moment, is a mass of nested data
+types used to track state on a connection through its lifetime. Let's
+walk through the process of selecting an appropriate event, generating
+some output to standard out and dissecting the connection record so as
+to get an overview of it. We will cover data types in more detail
+later.
While Bro is capable of packet level processing, its strengths lay in
the context of a connection between an originator and a responder. As
@@ -193,40 +197,42 @@ such, there are events defined for the primary parts of the connection
life-cycle as you'll see from the small selection of
connection-related events below.
-.. literalinclude:: ../../../../build/src/base/event.bif.bro
- :language: bro
- :linenos:
+.. todo::
+
+ Update the line numbers, this isn't pulling in the right events
+ anymore but I don't know which ones it were.
+
+.. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/event.bif.bro
:lines: 135-138,154,204-208,218,255-256,266,335-340,351
Of the events listed, the event that will give us the best insight
into the connection record data type will be
-connection_state_remove(). As detailed in the in-line documentation,
-Bro generates this event just before it decides to remove this event
-from memory, effectively forgetting about it. Let's take a look at a
-simple script that will output the connection record for a single
-connection.
+:bro:id:`connection_state_remove` . As detailed in the in-line
+documentation, Bro generates this event just before it decides to
+remove this event from memory, effectively forgetting about it. Let's
+take a look at a simple script, stored as
+``connection_record_01.bro``, that will output the connection record
+for a single connection.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_01.bro
- :language: bro
- :linenos:
- :lines: 4-9
+.. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro
-Again, we start with @load, this time importing the
-base/protocols/conn scripts which supply the tracking and logging of
-general information and state of connections. We handle the
-connection_state_remove() event and simply print the contents of the
-argument passed to it. For this example we're going to run Bro in
-"bare mode" which loads only the minimum number of scripts to retain
-operability and leaves the burden of loading required scripts to the
-script being run. While bare mode is a low level functionality
-incorporated into Bro, in this case, we're going to use it to
-demonstrate how different features of Bro add more and more layers of
-information about a connection. This will give us a chance to see the
-contents of the connection record without it being overly populated.
+Again, we start with ``@load``, this time importing the
+:doc:`scripts/base/protocols/conn` scripts which supply the tracking
+and logging of general information and state of connections. We
+handle the :bro:id:`connection_state_remove` event and simply print
+the contents of the argument passed to it. For this example we're
+going to run Bro in "bare mode" which loads only the minimum number of
+scripts to retain operability and leaves the burden of loading
+required scripts to the script being run. While bare mode is a low
+level functionality incorporated into Bro, in this case, we're going
+to use it to demonstrate how different features of Bro add more and
+more layers of information about a connection. This will give us a
+chance to see the contents of the connection record without it being
+overly populated.
.. btest:: connection-record-01
- @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_01.bro
+ @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_01.bro
As you can see from the output, the connection record is something of
a jumble when printed on its own. Regularly taking a peek at a
@@ -237,12 +243,12 @@ of reference for accessing data in a script.
Bro makes extensive use of nested data structures to store state and
information gleaned from the analysis of a connection as a complete
unit. To break down this collection of information, you will have to
-make use of use Bro's field delimiter the "$". For example, the
-originating host is referenced by c$id$orig_h which if given a
-narritive relates to "``orig_h`` which is a member of ``id`` which is
+make use of use Bro's field delimiter ``$``. For example, the
+originating host is referenced by ``c$id$orig_h`` which if given a
+narritive relates to ``orig_h`` which is a member of ``id`` which is
a member of the data structure referred to as ``c`` that was passed
into the event handler." Given that the responder port
-(``c$id$resp_p``) is 53/tcp, it's likely that Bro's base DNS scripts
+(``c$id$resp_p``) is ``53/tcp``, it's likely that Bro's base DNS scripts
can further populate the connection record. Let's load the
``base/protocols/dns`` scripts and check the output of our script.
@@ -250,30 +256,27 @@ Bro uses the dollar sign as its field delimiter and a direct
correlation exists between the output of the connection record and the
proper format of a dereferenced variable in scripts. In the output of
the script above, groups of information are collected between
-brackets, which would correspond to the $-delimiter in a Bro script.
+brackets, which would correspond to the ``$``-delimiter in a Bro script.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_02.bro
- :language: bro
- :linenos:
- :lines: 4-10
+.. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro
.. btest:: connection-record-02
- @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro
+ @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_02.bro
The addition of the ``base/protocols/dns`` scripts populates the
-dns=[] member of the connection record. While Bro is doing a massive
-amount of work in the background, it is in what is commonly called
-"script land" that details are being refined and decisions being made.
-Were we to continue running in "bare mode" we could slowly keep adding
-infrastructure through ``@load`` statements. For example, were we to
-``@load base/frameworks/logging``, Bro would generate a conn.log and
-dns.log for us in the current working directory. As mentioned above,
-including the appropriate ``@load`` statements is not only good
-practice, but can also help to indicate which functionalities are
-being used in a script. Take a second to run the script with the
-``-b`` flag and check the output when all of Bro's functionality is
-applied to the tracefile.
+``dns=[]`` member of the connection record. While Bro is doing a
+massive amount of work in the background, it is in what is commonly
+called "scriptland" that details are being refined and decisions
+being made. Were we to continue running in "bare mode" we could slowly
+keep adding infrastructure through ``@load`` statements. For example,
+were we to ``@load base/frameworks/logging``, Bro would generate a
+``conn.log`` and ``dns.log`` for us in the current working directory.
+As mentioned above, including the appropriate ``@load`` statements is
+not only good practice, but can also help to indicate which
+functionalities are being used in a script. Take a second to run the
+script without the ``-b`` flag and check the output when all of Bro's
+functionality is applied to the tracefile.
Data Types and Data Structures
==============================
@@ -281,20 +284,17 @@ Data Types and Data Structures
Scope
-----
-Before embarking on a exploration of Bro's native Data Types and Data
-Structures, it's important to have a good grasp of the different
+Before embarking on a exploration of Bro's native data types and data
+structures, it's important to have a good grasp of the different
levels of scope available in Bro and the appropriate times to use them
within a script. The declarations of variables in Bro come in two
forms. Variables can be declared with or without a definition in the
-form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively;
-each of which produce the same result if EXPRESSION evaluates to the
-same type as TYPE. The decision as to which type of declaration to
+form ``SCOPE name: TYPE`` or ``SCOPE name = EXPRESSION`` respectively;
+each of which produce the same result if ``EXPRESSION`` evaluates to the
+same type as ``TYPE``. The decision as to which type of declaration to
use is likely to be dictated by personal preference and readability.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_declaration.bro
- :language: bro
- :linenos:
- :lines: 4-14
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_declaration.bro
Global Variables
~~~~~~~~~~~~~~~~
@@ -309,79 +309,71 @@ intended result. When a global is declared in a script with a
namespace there are two possible outcomes. First, the variable is
available only within the context of the namespace. In this scenario,
other scripts within the same namespace will have access to the
-varaible declared while scripts using a different namespace or no
+variable declared while scripts using a different namespace or no
namespace altogether will not have access to the variable.
-Alternatively, if a global variable is declared within an ``export{}``
+Alternatively, if a global variable is declared within an ``export { ... }``
block that variable is available to any other script through the
naming convention of ``MODULE::variable_name``.
-The declaration below, is a taken from the ``known-hosts.bro`` script
-and declares a variable called "known_hosts"" as a global set of
-unique ip addresses(line 32) within the "Known" namespace (line 8) and
-exports it (line 10) for use outside of the "Known" namespace. Were
-we to want to use the "known_hosts" variable we'd be able to access it
-through ``Known::known_hosts``.
+The declaration below is taken from the
+:doc:`scripts/policy/protocols/conn/known-hosts.bro` script and
+declares a variable called ``known_hosts`` as a global set of unique
+IP addresses within the ``Known`` namespace and exports it for use
+outside of the ``Known`` namespace. Were we to want to use the
+``known_hosts`` variable we'd be able to access it through
+``Known::known_hosts``.
-.. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/conn/known-hosts.bro
:lines: 8-10, 32, 37
-The sample above also makes use of an export{} block. When the module
+The sample above also makes use of an ``export { ... }`` block. When the module
keyword is used in a script, the variables declared are said to be in
that module's "namespace". Where as a global variable can be accessed
by its name alone when it is not declared within a module, a global
variable declared within a module must be exported and then accessed
-via MODULE_NAME::VARIABLE_NAME. As in the example above, we would be
-able to access the "known_hosts" in a separate script variable via
-"Known::known_hosts" due to the fact that known_hosts was declared as
-a global variable within an export block under the "Known" namespace.
+via ``MODULE_NAME::VARIABLE_NAME``. As in the example above, we would be
+able to access the ``known_hosts`` in a separate script variable via
+``Known::known_hosts`` due to the fact that ``known_hosts`` was declared as
+a global variable within an export block under the ``Known`` namespace.
Constants
~~~~~~~~~
-Bro also makes use of constants which are denoted by the "const"
+Bro also makes use of constants, which are denoted by the ``const``
keyword. Unlike globals, constants can only be set or altered at
-parse time if the &redef attribute has been used. Afterwards (in
+parse time if the ``&redef`` attribute has been used. Afterwards (in
runtime) the constants are unalterable. In most cases, redefinable
constants are used in Bro scripts as containers for configuration
options. For example, the configuration option to log password
decrypted from HTTP streams is stored in
``HTTP::default_capture_password`` as shown in the stripped down
-excerpt from ``http/main.bro`` below.
+excerpt from :doc:`scripts/scripts/base/protocols/http/main.bro`
+below.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro
- :language: bro
- :linenos:
- :lines: 8-10,19,20,74
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro
+ :lines: 8-10,19,20,118
Because the constant was declared with the ``&redef`` attribute, if we
needed to turn this option on globally, we could do so by adding the
following line to our ``site/local.bro`` file before firing up Bro.
-
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const_simple.bro
- :language: bro
- :lines: 6
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_const_simple.bro
While the idea of a redefinable constant might be odd, the constraint
that constants can only be altered at parse-time remains even with the
-"&redef" attribute. In the code snippet below, a table of strings
+``&redef`` attribute. In the code snippet below, a table of strings
indexed by ports is declared as a constant before two values are added
-to the table through redef statements. The table is then printed in a
-bro_init() event. Were we to try to alter the table in an event
-handler, Bro would notify the user of an error and the script would
-fail.
+to the table through ``redef`` statements. The table is then printed
+in a :bro:id:`bro_init` event. Were we to try to alter the table in
+an event handler, Bro would notify the user of an error and the script
+would fail.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro
- :language: bro
- :linenos:
- :lines: 4-12
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_const.bro
.. btest:: data_type_const.bro
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_type_const.bro
+ @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_type_const.bro
Local Variables
~~~~~~~~~~~~~~~
@@ -392,26 +384,22 @@ its availability is restricted to the body of the event or function in
which it was declared. Local variables tend to be used for values
that are only needed within a specific scope and once the processing
of a script passes beyond that scope and no longer used, the variable
-is deleted. While it is possible for a function to return a locally
-scoped variable, in doing so it retuns the value instead of the
-variable. Bro maintains a difference between variables an example of
-which is illustrated below. The script executes the event handler
-"bro_init()" which in turn calls the function "add_two(i: count)" with
-an argument of 10. Once Bro enters the add_two function, it
-provisions a locally scoped variable called "added_two" to hold the
-value of i+2, in this case, 12. The add_two function then prints the
-value of the added_two variable and returns its value to the
-bro_init() event handler. At this point, the variable "added_two" has
-fallen out of scope and no longer exists while the value 12 is still
-in use and stored in the locally scoped variable "test". When Bro
-finishes processing the bro_init function, the variable called "test"
-is no longer in scope and, since there exist no other references to
-the value "12", the value is also deleted.
+is deleted. Bro maintains names of locals separately from globally
+visible ones, an example of which is illustrated below. The script
+executes the event handler :bro:id:`bro_init` which in turn calls the
+function ``add_two(i: count)`` with an argument of ``10``. Once Bro
+enters the ``add_two`` function, it provisions a locally scoped
+variable called ``added_two`` to hold the value of ``i+2``, in this
+case, ``12``. The ``add_two`` function then prints the value of the
+``added_two`` variable and returns its value to the ``bro_init`` event
+handler. At this point, the variable ``added_two`` has fallen out of
+scope and no longer exists while the value ``12`` still in use and
+stored in the locally scoped variable ``test``. When Bro finishes
+processing the ``bro_init`` function, the variable called ``test`` is
+no longer in scope and, since there exist no other references to the
+value ``12``, the value is also deleted.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_local.bro
- :language: bro
- :linenos:
- :lines: 4-14
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_local.bro
Data Structures
@@ -421,12 +409,12 @@ It's difficult to talk about Bro's data types in a practical manner
without first covering the data structures available in Bro. Some of
the more interesting characteristics of data types are revealed when
used inside of a data structure, but given that data structures are
-made up of data types, it devolved rather quickly into a
-"chicken-and-egg"" problem. As such, we'll introduce data types from
-bird's eye view before diving into data structures and from there a
+made up of data types, it devolves rather quickly into a
+"chicken-and-egg" problem. As such, we'll introduce data types from
+a bird's eye view before diving into data structures and from there a
more complete exploration of data types.
-The table below shows the atomic types used in Bro, of which, the
+The table below shows the atomic types used in Bro, of which the
first four should seem familiar if you have some scripting experience,
while the remaining six are less common in other languages. It should
come as no surprise that a scripting language for a Network Security
@@ -445,7 +433,7 @@ reinventing the wheel.
+-----------+-------------------------------------+
| bool | boolean (T/F) |
+-----------+-------------------------------------+
-| addr | ip address, ipv4 and ipv6 |
+| addr | IP address, IPv4 and IPv6 |
+-----------+-------------------------------------+
| port | transport layer port |
+-----------+-------------------------------------+
@@ -461,67 +449,58 @@ reinventing the wheel.
Sets
~~~~
-Sets in Bro are used to stored a unique elements of the same data
+Sets in Bro are used to store unique elements of the same data
type. In essence, you can think of them as "a unique set of integers"
-or "a unique set of ip addresses". While the declaration of a set may
+or "a unique set of IP addresses". While the declaration of a set may
differ based on the data type being collected, the set will always
contain unique elements and the elements in the set will always be of
the same data type. Such requirements make the set data type perfect
-for information that is already naturally unique such as ports or ip
+for information that is already naturally unique such as ports or IP
addresses. The code snippet below shows both an explicit and implicit
declaration of a locally scoped set.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro
- :language: bro
- :linenos:
- :lines: 6,7
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
+ :lines: 1-4,22
-As you can see, sets are declared using the format "SCOPE var_name:
-set[TYPE]". Adding and removing elements in a set is achieved using
-the add and delete statements. Once you have elements inserted into
+As you can see, sets are declared using the format ``SCOPE var_name:
+set[TYPE]``. Adding and removing elements in a set is achieved using
+the ``add`` and ``delete`` statements. Once you have elements inserted into
the set, it's likely that you'll need to either iterate over that set
or test for membership within the set, both of which are covered by
-the in operator. In the case of iterating over a set, combining the
-for statement and the in operator will allow you to sequentially
+the ``in`` operator. In the case of iterating over a set, combining the
+``for`` statement and the ``in`` operator will allow you to sequentially
process each element of the set as seen below.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro
- :language: bro
- :linenos:
- :lines: 21-29
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
+ :lines: 17-21
-Here, the for statement loops over the contents of the set storing
-each element in the temporary variable "i". With each iteration of
-the for loop, the next element is chosen. Since sets are not an
+Here, the ``for`` statement loops over the contents of the set storing
+each element in the temporary variable ``i``. With each iteration of
+the ``for`` loop, the next element is chosen. Since sets are not an
ordered data type, you cannot guarantee the order of the elements as
-the for loop processes.
+the ``for`` loop processes.
-To test for membership in a set the in statment can be combined with
-an if statement to return a true or false value. If the exact element
-in the condition is already in the set, the condition returns true and
-the body executes. The in statement can also be negated by the !
-operator to create the inverse of the condition. While line 16 of the
-code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports
-))" try to avoid using this construct; instead, negate the in operator
-itself. While the functionality is the same, using the "!in" is more
-efficient as well as a more natural construct which will aid in the
-readability of your script.
+To test for membership in a set the ``in`` statment can be combined
+with an ``if`` statement to return a true or false value. If the
+exact element in the condition is already in the set, the condition
+returns true and the body executes. The ``in`` statement can also be
+negated by the ``!`` operator to create the inverse of the condition.
+While we could rewrite the corresponding line below as ``if ( !(
+587/tcp in ssl_ports ))`` try to avoid using this construct; instead,
+negate the in operator itself. While the functionality is the same,
+using the ``!in`` is more efficient as well as a more natural construct
+which will aid in the readability of your script.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro
- :language: bro
- :linenos:
- :lines: 15-19
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
+ :lines: 13-15
You can see the full script and its output below.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro
- :language: bro
- :linenos:
- :lines: 4-21
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
.. btest:: data_struct_set_declaration
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
Tables
~~~~~~
@@ -529,33 +508,30 @@ Tables
A table in Bro is a mapping of a key to a value or yield. While the
values don't have to be unique, each key in the table must be unique
to preserve a one-to-one mapping of keys to values. In the example
-below, we've compiled a table of SSL enable services and their common
+below, we've compiled a table of SSL-enabled services and their common
ports. The explicit declaration and constructor for the table on
lines 3 and 4 lay out the data types of the keys (strings) and the
data types of the yields (ports) and then fill in some sample key and
-yeild pairs. Line 5 shows how to use a table accessor to insert one
-key-yield pair into the table. When using the in operator on a table,
+yield pairs. Line 5 shows how to use a table accessor to insert one
+key-yield pair into the table. When using the ``in`` operator on a table,
you are effectively working with the keys of the table. In the case
-of an inf statement, the in operator will check for membership among
+of an ``if`` statement, the ``in`` operator will check for membership among
the set of keys and return a true or false value. As seen on line 7,
-we are checking if "SMTPS" is not in the set of keys for the
+we are checking if ``SMTPS`` is not in the set of keys for the
ssl_services table and if the condition holds true, we add the
-key-yield pair to the table. Line 12 shows the use of a for statement
+key-yield pair to the table. Line 12 shows the use of a ``for`` statement
to iterate over each key currently in the table.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_declaration.bro
- :language: bro
- :linenos:
- :lines: 4-21
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_declaration.bro
.. btest:: data_struct_table_declaration
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_table_declaration.bro
Simple examples aside, tables can become extremely complex as the keys
and values for the table become more intricate. Tables can have keys
comprised of multiple data types and even a series of elements called
-a 'tuple'. The flexibility gained with the use of complex tables in
+a "tuple". The flexibility gained with the use of complex tables in
Bro implies a cost in complexity for the person writing the scripts
but pays off in effectiveness given the power of Bro as a network
security platform.
@@ -564,75 +540,67 @@ The script below shows a sample table of strings indexed by two
strings, a count, and a final string. With a tuple acting as an
aggregate key, the order is the important as a change in order would
result in a new key. Here, we're using the table to track the
-Director, Studio, year or release, and lead actor in a series of
-samurai flicks. It's important to note that in the case of the for
+director, studio, year or release, and lead actor in a series of
+samurai flicks. It's important to note that in the case of the ``for``
statement, it's an all or nothing kind of iteration. We cannot
-iterate over, say, the directors; We have to iterate with the exact
+iterate over, say, the directors; we have to iterate with the exact
format as the keys themselves. In this case, we need squared brackets
surrounding four temporary variables to act as a collection for our
iteration. While this is a contrived example, we could easily have
-had keys containin ip addresses(addr), ports(port) and even a string
+had keys containin IP addresses (``addr``), ports (``port``) and even a ``string``
calculated as the result of a reverse hostname lookup.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_complex.bro
- :language: bro
- :linenos:
- :lines: 4-21
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_complex.bro
.. btest:: data_struct_table_complex
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_complex.bro
+ @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_table_complex.bro
Vectors
~~~~~~~
If you're coming to Bro with a programming background, you may or may
-not be familiar with the Vector data type depending on your language
-of choice. On the surface, vectors perform much of the same
-functionality as arrays, but in truth they are more like associative
-arrays with zero indexed unsigned integers as the indecies. As such
-any time you need to sequentially store data of the same type, in Bro
-you'll have to reach for a vector. Vectors are a collection of
-objects, all of which are of the same data type, to which elements can
-be dynamically added or removed. Since Vectors use contiguous storage
-for their elements, the contents of a vector can be accessed through a
-zero indexed numerical offset.
+not be familiar with a vector data type depending on your language of
+choice. On the surface, vectors perform much of the same
+functionality as associative arrays with unsigned integers as their
+indices. They are however more efficient than that and they allow for
+ordered access. As such any time you need to sequentially store data of the
+same type, in Bro you should reach for a vector. Vectors are a
+collection of objects, all of which are of the same data type, to
+which elements can be dynamically added or removed. Since Vectors use
+contiguous storage for their elements, the contents of a vector can be
+accessed through a zero-indexed numerical offset.
The format for the declaration of a Vector follows the pattern of
-other declarations, namely, "SCOPE v: vector of T" where v is the name
-of your vector of T is the data type of its members. For example, the
-following snippet shows an explicit and implicit declaration of two
-locally scoped vectors. The script populates the first vector by
-inserting values at the end by placing the vector name between two
-vertical pipes to get the Vector's current length before printing the
-contents of both Vectors and their current lengths.
+other declarations, namely, ``SCOPE v: vector of T`` where ``v`` is
+the name of your vector, and ``T`` is the data type of its members.
+For example, the following snippet shows an explicit and implicit
+declaration of two locally scoped vectors. The script populates the
+first vector by inserting values at the end; it does that by placing
+the vector name between two vertical pipes to get the vector's current
+length before printing the contents of both Vectors and their current
+lengths.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_declaration.bro
- :language: bro
- :linenos:
- :lines: 4-16
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro
.. btest:: data_struct_vector_declaration
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro
In a lot of cases, storing elements in a vector is simply a precursor
to then iterating over them. Iterating over a vector is easy with the
-for keyword. The sample below iterates over a vector of IP addresses
-and for each IP address, masks that address with 18 bits. The for
-keyword is used to generate a locally scoped variable called "i" which
-will hold the index of the current element in the vector. Using i as
-an index to addr_vector we can access the current item in the vector
-with addr_vector[i].
+``for`` keyword. The sample below iterates over a vector of IP
+addresses and for each IP address, masks that address with 18 bits.
+The ``for`` keyword is used to generate a locally scoped variable
+called ``i`` which will hold the index of the current element in the
+vector. Using ``i`` as an index to addr_vector we can access the
+current item in the vector with ``addr_vector[i]``.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_iter.bro
- :language: bro
- :linenos:
- :lines: 4-12
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_iter.bro
.. btest:: data_struct_vector_iter
- @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro
+ @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_vector_iter.bro
Data Types Revisited
@@ -641,40 +609,40 @@ Data Types Revisited
addr
~~~~
-The addr, or address, data type manages to cover a surprisingly large
-amount of ground while remaining succinct. IPv4, IPv6 and even
-hostname constants are included in the addr data type. While IPv4
+The ``addr``, or address, data type manages to cover a surprisingly
+large amount of ground while remaining succinct. IPv4, IPv6 and even
+hostname constants are included in the ``addr`` data type. While IPv4
addresses use the default dotted quad formatting, IPv6 addresses use
-RFC 2373 defined notation with the addition of squared brackets
+the RFC 2373 defined notation with the addition of squared brackets
wrapping the entire address. When you venture into hostname
constants, Bro performs a little slight of hand for the benefit of the
user; a hostname constant is, in fact, a set of addresses. Bro will
issue a DNS request when it sees a hostname constant in use and return
a set whose elements are the answers to the DNS request. For example,
if you were to use ``local google = www.google.com;`` you would end up
-with a locally scoped set of addr elements that represent the current
-set of round robin DNS entries for google. At first blush, this seems
-trivial, but it is yet another example of Bro making the life of the
-common Bro scripter a little easier through abstraction applied in a
-practical manner.
+with a locally scoped ``set[addr]`` with elements that represent the
+current set of round robin DNS entries for google. At first blush,
+this seems trivial, but it is yet another example of Bro making the
+life of the common Bro scripter a little easier through abstraction
+applied in a practical manner. (Note however that these IP addresses
+will never get updated during Bro's processing, so often this
+mechanism most useful for addresses that are expected to remain
+static.).
port
~~~~
Transport layer port numbers in Bro are represented in the format of
-``unsigned integer/protocol name`` e.g. ``22/tcp`` or ``53/udp``. Bro
-supports TCP( /tcp ), UDP( /udp ) , ICMP( /icmp ) and UNKNOWN(
-/unknown ) as protocol designations. While ICMP doesn't have an
-actual port, Bro supports the concept of ICMP "ports" by using the
-ICMP message type and ICMP message code as the source and destination
-port respectively. Ports can be compared for equality using the == or
-!= operators and can even be compared for ordering. Bro gives the
-protocol designations the following "order": unknown < tcp < udp <
-icmp.
-
-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.
+``/``, e.g., ``22/tcp`` or
+``53/udp``. Bro supports TCP(``/tcp``), UDP(``/udp``),
+ICMP(``/icmp``) and UNKNOWN(``/unknown``) as protocol designations.
+While ICMP doesn't have an actual port, Bro supports the concept of
+ICMP "ports" by using the ICMP message type and ICMP message code as
+the source and destination port respectively. Ports can be compared
+for equality using the ``==`` or ``!=`` operators and can even be
+compared for ordering. Bro gives the protocol designations the
+following "order": ``unknown`` < ``tcp`` < ``udp`` < ``icmp``. For
+example ``65535/tcp`` is smaller than ``0/udp``.
subnet
~~~~~~
@@ -686,69 +654,64 @@ your scripts. The following example below uses a Bro script to
determine if a series of IP addresses are within a set of subnets
using a 20 bit subnet mask.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_subnets.bro
- :language: bro
- :linenos:
- :lines: 4-19
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_subnets.bro
Because this is a script that doesn't use any kind of network
-analysis, we can handle the event bro_init() which is always generated
-by Bro's core upon startup. On lines six and seven, two locally
-scoped vectors are created to hold our lists of subnets and IP
-addresses respectively. Then, using a set of nested for loops, we
-iterate over every subnet and every IP address and use an if statement
-to compare an IP address against a subnet using the in operator. The
-in operator returns true if the IP address falls within a given subnet
-based on the longest prefix match calculation. For example, 10.0.0.1
-in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24
-would return false. When we run the script, we get the output listing
-the IP address and the subnet in which it belongs.
+analysis, we can handle the event :bro:id:`bro_init` which is always
+generated by Bro's core upon startup. On lines six and seven, two
+locally scoped vectors are created to hold our lists of subnets and IP
+addresses respectively. Then, using a set of nested ``for`` loops, we
+iterate over every subnet and every IP address and use an ``if``
+statement to compare an IP address against a subnet using the ``in``
+operator. The ``in`` operator returns true if the IP address falls
+within a given subnet based on the longest prefix match calculation.
+For example, ``10.0.0.1 in 10.0.0.0/8`` would return true while
+``192.168.2.1 in 192.168.1.0/24`` would return false. When we run the
+script, we get the output listing the IP address and the subnet in
+which it belongs.
.. btest:: data_type_subnets
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_subnets.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_subnets.bro
time
~~~~
While there is currently no supported way to add a time constant in
Bro, two built-in functions exist to make use of the ``time`` data
-type. Both ``network_time()`` and ``current_time()`` return a
+type. Both :bro:id:`network_time` and :bro:id:`current_time` return a
``time`` data type but they each return a time based on different
-criteria. The ``current_time()`` function returns what is called the
+criteria. The ``current_time`` function returns what is called the
wall-clock time as defined by the operating system. However,
-``network_time()`` returns the timestamp of the last packet processed
+``network_time`` returns the timestamp of the last packet processed
be it from a live data stream or saved packet capture. Both functions
return the time in epoch seconds, meaning ``strftime`` must be used to
turn the output into human readable output. The script below makes
-use of the ``connection_established`` event handler to generate text
+use of the :bro:id:`connection_established` event handler to generate text
every time a SYN/ACK packet is seen responding to a SYN packet as part
of a TCP handshake. The text generated, is in the format of a
timestamp and an indication of who the originator and responder were.
We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to
produce a common date time formatted time stamp.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_time.bro
- :language: bro
- :linenos:
- :lines: 4-7
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_time.bro
When the script is executed we get an output showing the details of
established connections.
.. btest:: data_type_time
- @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro
+ @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_time.bro
interval
~~~~~~~~
The interval data type is another area in Bro where rational
-application of abstraction made perfect sense. As a data type, the
+application of abstraction makes perfect sense. As a data type, the
interval represents a relative time as denoted by a numeric constant
followed by a unit of time. For example, 2.2 seconds would be
``2.2sec`` and thirty-one days would be represented by ``31days``.
-Bro supports usec, msec, sec, min, hr, or day which represent
+Bro supports ``usec``, ``msec``, ``sec``, ``min``, ``hr``, or ``day`` which represent
microseconds, milliseconds, seconds, minutes, hours, and days
respectively. In fact, the interval data type allows for a surprising
amount of variation in its definitions. There can be a space between
@@ -768,10 +731,7 @@ operator. The script below amends the script started in the section
above to include a time delta value printed along with the connection
establishment report.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_interval.bro
- :language: bro
- :linenos:
- :lines: 4-20
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_interval.bro
This time, when we execute the script we see an additional line in the
output to display the time delta since the last fully established
@@ -779,7 +739,7 @@ connection.
.. btest:: data_type_interval
- @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro
+ @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_interval.bro
Pattern
@@ -789,35 +749,32 @@ Bro has support for fast text searching operations using regular
expressions and even goes so far as to declare a native data type for
the patterns used in regular expressions. A pattern constant is
created by enclosing text within the forward slash characters. Bro
-supports syntax very similar to the flex lexical analyzer syntax. The
+supports syntax very similar to the Flex lexical analyzer syntax. The
most common use of patterns in Bro you are likely to come across is
embedded matching using the ``in`` operator. Embedded matching
adheres to a strict format, requiring the regular expression or
pattern constant to be on the left side of the ``in`` operator and the
string against which it will be tested to be on the right.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_01.bro
- :language: bro
- :linenos:
- :lines: 4-13
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_01.bro
In the sample above, two local variables are declared to hold our
sample sentence and regular expression. Our regular expression in
this case will return true if the string contains either the word
-"quick" or the word "fox." The ``if`` statement on line six uses
+``quick`` or the word ``fox``. The ``if`` statement on line six uses
embedded matching and the ``in`` operator to check for the existence
of the pattern within the string. If the statement resolves to true,
-split is called to break the string into separate pieces. Split takes
-a string and a pattern as its arguments and returns a table of strings
-indexed by a count. Each element of the table will be the segments
-before and after any matches against the pattern but excluding the
-actual matches. In this case, our pattern matches twice, and results
-in a table with three entries. Lines 11 through 13 print the contents
-of the table in order.
+:bro:id:`split` is called to break the string into separate pieces.
+``Split`` takes a string and a pattern as its arguments and returns a
+table of strings indexed by a count. Each element of the table will
+be the segments before and after any matches against the pattern but
+excluding the actual matches. In this case, our pattern matches
+twice, and results in a table with three entries. Lines 11 through 13
+print the contents of the table in order.
.. btest:: data_type_pattern
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_01.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_01.bro
Patterns can also be used to compare strings using equality and
inequality operators through the ``==`` and ``!=`` operators
@@ -827,23 +784,20 @@ ternary conditional statements to illustrate the use of the ``==``
operators with patterns. On lines 5 and 8 the output is altered based
on the result of the comparison between the pattern and the string.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_02.bro
- :language: bro
- :linenos:
- :lines: 4-13
+.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_02.bro
.. btest:: data_type_pattern_02
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_02.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_02.bro
Record Data Type
-================
+----------------
-With Bro's support for a wide array of data types and data structures
-an obvious extension of is to include the ability to create custom
-data types consisting of the atomic types and ddata structures. To
+With Bro's support for a wide array of data types and data structures,
+an obvious extension is to include the ability to create custom
+data types composed of atomic types and further data structures. To
accomplish this, Bro introduces the ``record`` type and the ``type``
keyword. Similar to how you would define a new data structure in C
with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble
@@ -851,23 +805,18 @@ together new data types to suit the needs of your situation.
When combined with the ``type`` keyword, ``record`` can generate a
composite type. We have, in fact, already encountered a a complex
-example of the ``record`` data type in the earlier sections. The
-excerpt below shows the definition of the connection record data type
-as defined in the ``Conn`` module.
+example of the ``record`` data type in the earlier sections, the
+:bro:id:`connection` record passed to many events. Another one,
+:bro:id:`Conn::Info`, which corresponds to the fields logged into
+``conn.log``, is shown by the exerpt below.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro
:lines: 10-12,16,17,19,21,23,25,28,31,35,37,56,62,68,90,93,97,100,104,108,109,114
-While it might be surprising that Bro is tracking and passing around
-this much data for each connection, it shouldn't be too surprising,
-given our exploration of it earlier, that the connection record
-consists of a collection of atomic data types, simple data types and
-even another ``record``. Looking at the structure of the definition,
-a new collection of data types is being defined as a type called
-``Info``. Since this type definition is within the confines of an
-export block, what is defined is, in fact, ``Conn::Info``.
+Looking at the structure of the definition, a new collection of data
+types is being defined as a type called ``Info``. Since this type
+definition is within the confines of an export block, what is defined
+is, in fact, ``Conn::Info``.
The formatting for a declaration of a record type in Bro includes the
descriptive name of the type being defined and the seperate fields
@@ -875,38 +824,32 @@ that make up the record. The individual fields that make up the new
record are not limited in type or number as long as the name for each
field is unique.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro
- :language: bro
- :linenos:
- :lines: 4-25
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_01.bro
.. btest:: data_struct_record_01
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_01.bro
The sample above shows a simple type definition that includes a
string, a set of ports, and a count to define a service type. Also
included is a function to print each field of a record in a formatted
-fashion and a bro_init event handler to show some functionality of
-working with records. The defintions of the dns and http services are
-both done inline using squared brackets before being passed to the
-``print_service`` function. The ``print_service`` function makes use
-of the ``$`` dereference operator to access the fields within the
-newly defined Service record type.
+fashion and a :bro:id:`bro_init` event handler to show some
+functionality of working with records. The definitions of the DNS and
+HTTP services are both done inline using squared brackets before being
+passed to the ``print_service`` function. The ``print_service``
+function makes use of the ``$`` dereference operator to access the
+fields within the newly defined Service record type.
-As you saw in the definition for the connection record, other records
-are even valid as fields within another record. We can extend the
-example above to include another record that contains a Service
+As you saw in the definition for the ``Conn::Info`` record, other
+records are even valid as fields within another record. We can extend
+the example above to include another record that contains a Service
record.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro
- :language: bro
- :linenos:
- :lines: 4-25
+.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_02.bro
.. btest:: data_struct_record_02
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro
The example above includes a second record type in which a field is
used as the data type for a set. Records can be reapeatedly nested
@@ -917,9 +860,7 @@ It's also common to see a ``type`` used to simply alias a data
structure to a more descriptive name. The example below shows an
example of this from Bro's own type definitions file.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro
:lines: 12,19,26
The three lines above alias a type of data structure to a descriptive
@@ -930,8 +871,8 @@ consideration can lead to better readability of your code and thus
easier maintainability in the future.
-Logging Framework
-=================
+Custom Logging
+==============
Armed with a decent understanding of the data types and data
structures in Bro, exploring the various frameworks available is a
@@ -940,23 +881,24 @@ likely to have the most interaction is the Logging Framework.
Designed in such a way to so as to abstract much of the process of
creating a file and appending ordered and organized data into it, the
Logging Framework makes use of some potentially unfamiliar
-nomenclature. Specifically, Log streams, Filters and Writers are
+nomenclature. Specifically, Log Streams, Filters and Writers are
simply abstractions of the processes required to manage a high rate of
incoming logs while maintaining full operability. If you've seen Bro
-employed in an environment with a large connection, you know that logs
-are produced incredibly quickly; the ability to process a large set of
-data and write it to disk is due to the design of the Logging
-Framework.
+employed in an environment with a large number of connections, you
+know that logs are produced incredibly quickly; the ability to process
+a large set of data and write it to disk is due to the design of the
+Logging Framework.
-Data is written to a Log stream based on decision making processes in
-Bro's scriptland. Log streams correspond to a single log as defined
-by the set of name value pairs that make up its fields. That data can
+Data is written to a Log Stream based on decision making processes in
+Bro's scriptland. Log Streams correspond to a single log as defined
+by the set of name/value pairs that make up its fields. That data can
then be filtered, modified, or redirected with Logging Filters which,
by default, are set to log everything. Filters can be used to break
log files into subsets or duplicate that information to another
output. The final output of the data is defined by the writer. Bro's
default writer is simple tab separated ASCII files but Bro also
-includes support for DataSeries and Elasticsearch outputs as well as
+includes support for `DataSeries `_
+and `Elasticsearch `_ outputs as well as
additional writers currently in development. While these new terms
and ideas may give the impression that the Logging Framework is
difficult to work with, the actual learning curve is, in actuality,
@@ -964,11 +906,11 @@ not very steep at all. The abstraction built into the Logging
Framework makes it such that a vast majority of scripts needs not go
past the basics. In effect, writing to a log file is as simple as
defining the format of your data, letting Bro know that you wish to
-create a new log, and then calling the ``Log::write()`` method to
+create a new log, and then calling the :bro:id:`Log::write` method to
output log records.
-The Logging Framework is an are in Bro where, the more you see it used
-and the more you use it yourself, the more second nature the
+The Logging Framework is an area in Bro where, the more you see it
+used and the more you use it yourself, the more second nature the
boilerplate parts of the code will become. As such, let's work
through a contrived example of simply logging the digits 1 through 10
and their corresponding factorial to the default ASCII log writer.
@@ -977,64 +919,59 @@ desired output with ``print`` and ``fmt`` before attempting to dive
into the Logging Framework. Below is a script that defines a
factorial function to recursively calculate the factorial of a
unsigned integer passed as an argument to the function. Using
-``print`` and ``fmt`` we can ensure that Bro can perform these
+:bro:id:`print` :bro:id:`fmt` we can ensure that Bro can perform these
calculations correctly as well get an idea of the answers ourselves.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_01.bro
- :language: bro
- :linenos:
- :lines: 4-25
+.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro
-.. btest:: framework_logging_factorial_01
+.. btest:: framework_logging_factorial
- @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro
The output of the script aligns with what we expect so now it's time
to integrate the Logging Framework. As mentioned above we have to
-perform a few steps before we can issue the ``Log::write()`` method
-and produce a logfile. As we are working within a namespace and
-informing an outside entity of workings and data internal to the
-namespace, we use an ``export{}`` block. First we need to inform Bro
-that we are going to be adding another Log stream by adding a value to
-the ``Log::ID`` enumerable. In line 3 of the script, we append the
-value ``LOG`` to the Log::ID enumerable, however due to this being in
+perform a few steps before we can issue the :bro:id:`Log::write`
+method and produce a logfile. As we are working within a namespace
+and informing an outside entity of workings and data internal to the
+namespace, we use an ``export`` block. First we need to inform Bro
+that we are going to be adding another Log Stream by adding a value to
+the :bro:id:`Log::ID` enumerable. In line 3 of the script, we append the
+value ``LOG`` to the ``Log::ID`` enumerable, however due to this being in
an export block the value appended to ``Log::ID`` is actually
``Factor::Log``. Next, we need to define the name and value pairs
that make up the data of our logs and dictate its format. Lines 5
-through 9 define a new datatype called an Info record (actually,
+through 9 define a new datatype called an ``Info`` record (actually,
``Factor::Info``) with two fields, both unsigned integers. Each of the
fields in the ``Factor::Log`` record type include the ``&log``
attribute, indicating that these fields should be passed to the
-Logging Framework when ``Log::write()`` is called. Were there to be
+Logging Framework when ``Log::write`` is called. Were there to be
any name value pairs without the ``&log`` attribute, those fields
would simply be ignored during logging but remain available for the
lifespan of the variable. The next step is to create the logging
-stream with ``Log::create_stream()`` which takes a Log::ID and a
+stream with :bro:id:`Log::create_stream` which takes a Log::ID and a
record as its arguments. In this example, on line 28, we call the
-``Log::create_stream()`` method and pass ``Factor::LOG`` and the
+``Log::create_stream`` method and pass ``Factor::LOG`` and the
``Factor::Info`` record as arguments. From here on out, if we issue
-the ``Log::write()`` command with the correct Log::ID and a properly
+the ``Log::write`` command with the correct ``Log::ID`` and a properly
formatted ``Factor::Info`` record, a log entry will be generated.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro
- :language: bro
- :linenos:
- :lines: 4-40
+.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro
Now, if we run the new version of the script, instead of generating
logging information to stdout, no output is created. Instead the
-output is all in factor.log, properly formatted and organized.
+output is all in ``factor.log``, properly formatted and organized.
-.. btest:: framework_logging_factorial_02
+.. btest:: framework_logging_factorial-2
- @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_02/factor.log
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro
+ @TEST-EXEC: btest-rst-include factor.log
While the previous example is a simplistic one, it serves to
-demonstrate the small pieces of script that need to be in place in
+demonstrate the small pieces of script code hat need to be in place in
order to generate logs. For example, it's common to call
-``Log::create_stream()`` in ``bro_init()`` and while in a live
-example, determining when to call ``Log::write()`` would likely be
-done in an event handler, in this case we use ``bro_done()``.
+``Log::create_stream`` in :bro:id:`bro_init` and while in a live
+example, determining when to call ``Log::write`` would likely be
+done in an event handler, in this case we use :bro:id:`bro_done` .
If you've already spent time with a deployment of Bro, you've likely
had the opportunity to view, search through, or manipulate the logs
@@ -1042,7 +979,7 @@ produced by the Logging Framework. The log output from a default
installation of Bro is substantial to say the least, however, there
are times in which the way the Logging Framework by default isn't
ideal for the situation. This can range from needing to log more or
-less data with each call to ``Log::write()`` or even the need to split
+less data with each call to ``Log::write`` or even the need to split
log files based on arbitrary logic. In the later case, Filters come
into play along with the Logging Framework. Filters grant a level of
customization to Bro's scriptland, allowing the script writer to
@@ -1055,34 +992,33 @@ example we've been using, let's extend it so as to write any factorial
which is a factor of 5 to an alternate file, while writing the
remaining logs to factor.log.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_03.bro
- :language: bro
+.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro
+ :lines: 38-62
:linenos:
- :lines: 43-60
To dynamically alter the file in which a stream writes its logs a
filter can specify function returns a string to be used as the
-filename for the current call to ``Log::write()``. The definition for
-this function has to take as its parameters a Log::ID called id, a
-string called path and the appropriate record type for the logs called
-"rec". You can see the definition of ``mod5`` used in this example on
+filename for the current call to ``Log::write``. The definition for
+this function has to take as its parameters a ``Log::ID`` called id, a
+string called ``path`` and the appropriate record type for the logs called
+``rec``. You can see the definition of ``mod5`` used in this example on
line one conforms to that requirement. The function simply returns
-"factor-mod5" if the factorial is divisible evenly by 5, otherwise, it
-returns "factor-non5". In the additional ``bro_init()`` event
+``factor-mod5`` if the factorial is divisible evenly by 5, otherwise, it
+returns ``factor-non5``. In the additional ``bro_init`` event
handler, we define a locally scoped ``Log::Filter`` and assign it a
record that defines the ``name`` and ``path_func`` fields. We then
-call ``Log::add_filter()`` to add the filter to the ``Factor::LOG``
-Log::ID and call ``Log::remove_filter()`` to remove the ``default``
-filter for Factor::LOG. Had we not removed the ``default`` filter,
-we'd have ended up with three log files: factor-mod5.log with all the
-factorials that are a factors of 5, factor-non5.log with the
-factorials that are not factors of 5, and factor.log which would have
+call ``Log::add_filter`` to add the filter to the ``Factor::LOG``
+``Log::ID`` and call ``Log::remove_filter`` to remove the ``default``
+filter for ``Factor::LOG``. Had we not removed the ``default`` filter,
+we'd have ended up with three log files: ``factor-mod5.log`` with all the
+factorials that are a factors of 5, ``factor-non5.log`` with the
+factorials that are not factors of 5, and ``factor.log`` which would have
included all factorials.
-.. btest:: framework_logging_factorial_02
+.. btest:: framework_logging_factorial-3
- @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log
- @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log
+ @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro
+ @TEST-EXEC: btest-rst-include factor-mod5.log
The ability of Bro to generate easily customizable and extensible logs
which remain easily parsable is a big part of the reason Bro has
@@ -1112,34 +1048,31 @@ block and define the value to be passed to it, in this case the
``Factor::Info`` record. We then list the ``log_factor`` function as
the ``$ev`` field in the call to ``Log::create_stream``
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_04.bro
- :language: bro
- :linenos:
- :lines: 4-62
+.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_04.bro
-Notice Framework
-================
+Raising Notices
+===============
While Bro's Logging Framework provides an easy and systematic way to
generate logs, there still exists a need to indicate when a specific
behavior has been detected and a method to allow that detection to
come to someone's attention. To that end, the Notice Framework is in
place to allow script writers a codified means through which they can
-raise a notice and a system through which an operator can opt-in to
-receive the notice. Bro holds to the philosophy that it is up to the
-individual operator to indicate the behaviors in which they are
-interested and as such Bro ships with a large number of policy scripts
-which detect behavior that may be of interest but it does not presume
-to guess as to which behaviors are "action-able". In effect, Bro
-works to separate the act of detection and the responsibility of
+raise a notice, as well as a system through which an operator can
+opt-in to receive the notice. Bro holds to the philosophy that it is
+up to the individual operator to indicate the behaviors in which they
+are interested and as such Bro ships with a large number of policy
+scripts which detect behavior that may be of interest but it does not
+presume to guess as to which behaviors are "action-able". In effect,
+Bro works to separate the act of detection and the responsibility of
reporting. With the Notice Framework it's simple to raise a notice
for any behavior that is detected.
To raise a notice in Bro, you only need to indicate to Bro that you
-are provide a specific ``Notice::Type`` by exporting it and then make
-a call to ``NOTICE()`` supplying it with an appropriate
-``Notice::Info`` record. Often times the call to ``NOTICE()``
+are provide a specific :bro:id:`Notice::Type` by exporting it and then
+make a call to :bro:id:`NOTICE` supplying it with an appropriate
+:bro:id:`Notice::Info` record. Often times the call to ``NOTICE``
includes just the ``Notice::Type``, and a concise message. There are
however, significantly more options available when raising notices as
seen in the table below. The only field in the table below whose
@@ -1154,6 +1087,11 @@ that are commonly included, ``$identifier`` and ``$suppress_for`` are
built around the automated suppression feature of the Notice Framework
which we will cover shortly.
+.. todo::
+
+ Once the link to ``Notice::Info`` work I think we should take out
+ the table. That's too easy to get out of date.
+
+---------------------+------------------------------------------------------------------+----------------+----------------------------------------+
| Field | Type | Attributes | Use |
+=====================+==================================================================+================+========================================+
@@ -1204,16 +1142,14 @@ One of the default policy scripts raises a notice when an SSH login
has been heuristically detected and the originating hostname is one
that would raise suspicion. Effectively, the script attempts to
define a list of hosts from which you would never want to see SSH
-traffic originating, dns servers, mail servers, etc. To accomplish
-this, the script adhere's to the seperation of detection and reporting
-by detecting a behavior and raising a notice. Whether or not that
-notice is acted upon is decided by the local Notice Policy, but the
-script attempts to supply as much information as possible while
-staying concise.
+traffic originating, like DNS servers, mail servers, etc. To
+accomplish this, the script adhere's to the seperation of detection
+and reporting by detecting a behavior and raising a notice. Whether
+or not that notice is acted upon is decided by the local Notice
+Policy, but the script attempts to supply as much information as
+possible while staying concise.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro
:lines: 1-46
While much of the script relates to the actual detection, the parts
@@ -1221,51 +1157,51 @@ specific to the Notice Framework are actually quite interesting in
themselves. On line 12 the script's ``export`` block adds the value
``SSH::Interesting_Hostname_Login`` to the enumerable constant
``Notice::Type`` to indicate to the Bro core that a new type of notice
-is being defined. The script then calls ``NOTICE()`` and defines the
-``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also
-includes a ternary if statement that modifies the ``$msg`` text
-depending on whether the host is a local address and whether it is the
-client or the server. This use of ``fmt()`` and a ternary operators
-is a concise way to lend readability to the notices that are generated
-without the need for branching ``if`` statements that each raise a
-specific notice.
+is being defined. The script then calls ``NOTICE`` and defines the
+``$note``, ``$msg``, ``$sub`` and ``$conn`` fields of the
+:bro:id:`Notice::Info` record. Line 39 also includes a ternary if
+statement that modifies the ``$msg`` text depending on whether the
+host is a local address and whether it is the client or the server.
+This use of :bro:id:`fmt` and a ternary operators is a concise way to
+lend readability to the notices that are generated without the need
+for branching ``if`` statements that each raise a specific notice.
The opt-in system for notices is managed through writing
-``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its
-argument a ``Notice::Info`` record which will hold the same
-information your script provided in its call to ``NOTICE()``. With
+:bro:id:`Notice::policy` hooks. A ``Notice::policy`` hook takes as
+its argument a ``Notice::Info`` record which will hold the same
+information your script provided in its call to ``NOTICE``. With
access to the ``Notice::Info`` record for a specific notice you can
include logic such as in statements in the body of your hook to alter
-the Policy for handling notices on your system. Notice hooks are akin
-to functions and event handlers and share the same structure; You can
-even think of hooks as multi-bodied functions. You define the hook
-and Bro will take care of passing in the ``Notice::Info`` record. The
-simplest kind of ``Notice::policy`` hooks simply check the value of
-``$note`` in the ``Notice::Info`` record being passed into the hook
-and performing an action based on the answer. The hook below adds the
-``Notice::ACTION_EMAIL`` action for the
-SSH::Interesting_Hostname_Login notice raised in the
-interesting-hostnames.bro script.
+the policy for handling notices on your system. In Bro, hooks are
+akin to a mix of functions and event handlers: like functions, calls
+to them are synchronous (i.e., run to completion and return); but like
+events, they can have multiple bodies which will all execute. For
+defining a notice policy, you define a hook and Bro will take care of
+passing in the ``Notice::Info`` record. The simplest kind of
+``Notice::policy`` hooks simply check the value of ``$note`` in the
+``Notice::Info`` record being passed into the hook and performing an
+action based on the answer. The hook below adds the
+:bro:id:`Notice::ACTION_EMAIL` action for the
+``SSH::Interesting_Hostname_Login`` notice raised in the
+:doc:`scripts/policy/protocols/ssh/interesting-hostnames.bro` script.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_01.bro
- :language: bro
- :linenos:
- :lines: 6-12
+.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_01.bro
In the example above we've added ``Notice::ACTION_EMAIL`` to the
``n$actions`` set. This set, defined in the Notice Framework scripts,
-can only have entries from the Notice::Action type which is itself an
-enumerable that defines the values shown in the table below along with
-their corresponding meanings. The ``Notice::ACTION_LOG`` action
-writes the notice to the ``Notice::LOG`` logging stream which, in the
-default configuration, will write each notice to the notice.log file
-and take no further action. The ``Notice::ACTION_EMAIL`` action will
-send an email to the address or addresses defined in the
-``Notice::mail_dest`` variable with the particulars of the notice as
-the body of the email. The last action, ``Notice::ACTION_ALARM``
-sends the notice to the ``Notice::ALARM_LOG`` logging stream which is
-then rotated hourly and its contents emailed in readable ASCII to the
-addresses in ``Notice::mail_dest``.
+can only have entries from the :bro:id:`Notice::Action` type, which is
+itself an enumerable that defines the values shown in the table below
+along with their corresponding meanings. The
+:bro:id:`Notice::ACTION_LOG` action writes the notice to the
+``Notice::LOG`` logging stream which, in the default configuration,
+will write each notice to the ``notice.log`` file and take no further
+action. The :bro:id:`Notice::ACTION_EMAIL` action will send an email
+to the address or addresses defined in the :bro:id:`Notice::mail_dest`
+variable with the particulars of the notice as the body of the email.
+The last action, :bro:id:`Notice::ACTION_ALARM` sends the notice to
+the :bro:id:`Notice::ALARM_LOG` logging stream which is then rotated
+hourly and its contents emailed in readable ASCII to the addresses in
+``Notice::mail_dest``.
+--------------+-----------------------------------------------------+
| ACTION_NONE | Take no action |
@@ -1286,31 +1222,30 @@ identifier. An identifier is a unique string of information collected
from the connection relative to the behavior that has been observed by
Bro.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro
- :language: bro
- :linenos:
+.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro
:lines: 59-62
-In the ``expiring-certs.bro`` script which identifies when SSL
-certificates are set to expire and raises notices when it crosses a
-pre-defined threshold, the call to ``NOTICE()`` above also sets the
-``$identifier`` entry by concatenating the responder ip, port, and the
-hash of the certificate. The selection of responder ip, port and
-certificate hash fits perfectly into an appropriate identifier as it
-creates a unique identifier with which the suppression can be matched.
-Were we to take out any of the entities used for the identifier, for
-example the certificate hash, we could be setting our suppression too
-broadly, causing an analyst to miss a notice that should have been
-raised. Depending on the available data for the identifier, it can be
-useful to set the ``$suppress_for`` variable as well. The
-``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``,
-telling the Notice Framework to suppress the notice for 24 hours after
-the first notice is raised. Once that time limit has passed, another
-notice can be raised which will again set the ``1day`` suppression
-time. Suppressing for a specific amount of time has benefits beyond
-simply not filling up an analyst's email inbox; keeping the notice
-alerts timely and succinct helps avoid a case where an analyst might
-see the notice and, due to over exposure, ignore it.
+In the :doc:`scripts/policy/protocols/ssl/expiring-certs.bro` script
+which identifies when SSL certificates are set to expire and raises
+notices when it crosses a pre-defined threshold, the call to
+``NOTICE`` above also sets the ``$identifier`` entry by concatenating
+the responder IP, port, and the hash of the certificate. The
+selection of responder IP, port and certificate hash fits perfectly
+into an appropriate identifier as it creates a unique identifier with
+which the suppression can be matched. Were we to take out any of the
+entities used for the identifier, for example the certificate hash, we
+could be setting our suppression too broadly, causing an analyst to
+miss a notice that should have been raised. Depending on the
+available data for the identifier, it can be useful to set the
+``$suppress_for`` variable as well. The ``expiring-certs.bro`` script
+sets ``$suppress_for`` to ``1day``, telling the Notice Framework to
+suppress the notice for 24 hours after the first notice is raised.
+Once that time limit has passed, another notice can be raised which
+will again set the ``1day`` suppression time. Suppressing for a
+specific amount of time has benefits beyond simply not filling up an
+analyst's email inbox; keeping the notice alerts timely and succinct
+helps avoid a case where an analyst might see the notice and, due to
+over exposure, ignore it.
The ``$suppress_for`` variable can also be altered in a
``Notice::policy`` hook, allowing a deployment to better suit the
@@ -1319,10 +1254,7 @@ environment in which it is be run. Using the example of
``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for``
variable to a shorter time.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro
- :language: bro
- :linenos:
- :lines: 6-12
+.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_suppression_01.bro
While ``Notice::policy`` hooks allow you to build custom
predicate-based policies for a deployment, there are bound to be times
@@ -1333,11 +1265,11 @@ facilitate these types of decisions, the Notice Framework supports
Notice Policy shortcuts. These shortcuts are implemented through the
means of a group of data structures that map specific, pre-defined
details and actions to the effective name of a notice. Primarily
-implemented as a set or table of enumerables of ``Notice::Type``,
+implemented as a set or table of enumerables of :bro:id:`Notice::Type`,
Notice Policy shortcuts can be placed as a single directive in your
``local.bro`` file as a concise readable configuration. As these
variables are all constants, it bears mentioning that these variables
-are all set at parsetime before Bro is fully up and running and not
+are all set at parse-time before Bro is fully up and running and not
set dynamically.
+------------------------------------+-----------------------------------------------------+-------------------------------------+
@@ -1367,21 +1299,15 @@ suppression being applied to the Notice. The shortcut
``Notice::not_suppressed_types`` can be used to remove the configured
suppression from a notice while ``Notice::type_suppression_intervals``
can be used to alter the suppression interval defined by $suppress_for
-in the call to ``NOTICE()``.
+in the call to ``NOTICE``.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_01.bro
- :language: bro
- :linenos:
- :lines: 7-10
+.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_01.bro
The Notice Policy shortcut above adds the ``Notice::Types`` of
SSH::Interesting_Hostname_Login and SSH::Login to the
Notice::emailed_types set while the shortcut below alters the length
of time for which those notices will be suppressed.
-.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_02.bro
- :language: bro
- :linenos:
- :lines: 7-10
+.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_02.bro
diff --git a/testing/btest/doc/manual/using_bro_sandbox_01 b/doc/scripting/using_bro_sandbox_01
similarity index 100%
rename from testing/btest/doc/manual/using_bro_sandbox_01
rename to doc/scripting/using_bro_sandbox_01
diff --git a/testing/btest/doc/manual/using_bro_sandbox_02 b/doc/scripting/using_bro_sandbox_02
similarity index 100%
rename from testing/btest/doc/manual/using_bro_sandbox_02
rename to doc/scripting/using_bro_sandbox_02
diff --git a/doc/using/index.rst b/doc/using/index.rst
index c9226fadd2..1ad05d74f8 100644
--- a/doc/using/index.rst
+++ b/doc/using/index.rst
@@ -44,7 +44,8 @@ the Unix utility ``head`` and outputting the first lines of the file:
.. btest:: using_bro
- @TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log"
+ @TEST-EXEC: btest-rst-cmd bro -r $TRACES/wikipedia.trace
+ @TEST-EXEC: btest-rst-include -n 15 conn.log
As you can see, the header consists of lines prefixed by ``#`` and
includes information such as what separators are being used for
diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1
new file mode 100644
index 0000000000..869395d05e
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1
@@ -0,0 +1,11 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -b -r dns-session.trace connection_record_01.bro
+ [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={
+
+ }, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={
+
+ }], extract_orig=F, extract_resp=F]
+
diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1
new file mode 100644
index 0000000000..3de3ee79a6
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1
@@ -0,0 +1,17 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -b -r dns-session.trace connection_record_02.bro
+ [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={
+
+ }, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={
+
+ }], extract_orig=F, extract_resp=F, dns=, dns_state=[pending={
+ [34798] = [initialized=T, vals={
+
+ }, settings=[max_len=], top=1, bottom=1, size=0]
+ }, finished_answers={
+
+ }]]
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1
new file mode 100644
index 0000000000..5b8d702333
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1
@@ -0,0 +1,12 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_struct_record_01.bro
+ Service: dns(RFC1035)
+ port: 53/tcp
+ port: 53/udp
+ Service: http(RFC2616)
+ port: 80/tcp
+ port: 8080/tcp
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1
new file mode 100644
index 0000000000..b640862c49
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1
@@ -0,0 +1,13 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_struct_record_02.bro
+ System: morlock
+ Service: dns(RFC1035)
+ port: 53/tcp
+ port: 53/udp
+ Service: http(RFC2616)
+ port: 80/tcp
+ port: 8080/tcp
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1
new file mode 100644
index 0000000000..f22481364a
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1
@@ -0,0 +1,14 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_struct_set_declaration.bro
+ SSL Port: 993/tcp
+ SSL Port: 22/tcp
+ SSL Port: 587/tcp
+ SSL Port: 443/tcp
+ Non-SSL Port: 143/tcp
+ Non-SSL Port: 25/tcp
+ Non-SSL Port: 80/tcp
+ Non-SSL Port: 23/tcp
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1
new file mode 100644
index 0000000000..415d6b4436
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1
@@ -0,0 +1,10 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -b data_struct_table_complex.bro
+ Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai
+ Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai
+ Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai
+ Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1
new file mode 100644
index 0000000000..0b6efd6166
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1
@@ -0,0 +1,10 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_struct_table_declaration.bro
+ Service Name: IMAPS - Common Port: 993/tcp
+ Service Name: HTTPS - Common Port: 443/tcp
+ Service Name: SSH - Common Port: 22/tcp
+ Service Name: SMTPS - Common Port: 587/tcp
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1
new file mode 100644
index 0000000000..c282de7c49
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1
@@ -0,0 +1,10 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_struct_vector_declaration.bro
+ contents of v1: [1, 2, 3, 4]
+ length of v1: 4
+ contents of v1: [1, 2, 3, 4]
+ length of v2: 4
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1
new file mode 100644
index 0000000000..88634f57a6
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1
@@ -0,0 +1,9 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -b data_struct_vector_iter.bro
+ 1.2.0.0/18
+ 2.3.0.0/18
+ 3.4.0.0/18
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1
new file mode 100644
index 0000000000..48532cfb84
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1
@@ -0,0 +1,10 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -b data_type_const.bro
+ {
+ [6666/tcp] = IRC,
+ [80/tcp] = WWW
+ }
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1
new file mode 100644
index 0000000000..d200467611
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1
@@ -0,0 +1,23 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -r wikipedia.trace data_type_interval.bro
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 132.0 msecs 97.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 177.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 2.0 msecs 177.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 33.0 msecs 898.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 35.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
+ Time since last connection: 2.0 msecs 532.0 usecs
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2
+ Time since last connection: 7.0 msecs 866.0 usecs
+ 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128
+ Time since last connection: 817.0 msecs 703.0 usecs
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1
new file mode 100644
index 0000000000..e74a70e576
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1
@@ -0,0 +1,9 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_type_pattern_01.bro
+ The
+ brown fox jumped over the
+ dog.
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1
new file mode 100644
index 0000000000..3097c85bcd
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1
@@ -0,0 +1,8 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_type_pattern_02.bro
+ equality and /^?(equal)$?/ are not equal
+ equality and /^?(equality)$?/ are equal
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1
new file mode 100644
index 0000000000..92d18b84ba
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1
@@ -0,0 +1,10 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro data_type_subnets.bro
+ 172.16.4.56 belongs to subnet 172.16.0.0/20
+ 172.16.47.254 belongs to subnet 172.16.32.0/20
+ 172.16.22.45 belongs to subnet 172.16.16.0/20
+ 172.16.1.1 belongs to subnet 172.16.0.0/20
+
diff --git a/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1
new file mode 100644
index 0000000000..d83f819038
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1
@@ -0,0 +1,15 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -r wikipedia.trace data_type_time.bro
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J
+ 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2^J
+ 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128^J
+
diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1
new file mode 100644
index 0000000000..e7fd140e3c
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1
@@ -0,0 +1,29 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro framework_logging_factorial_02.bro
+
+.. code-block:: guess
+ :linenos:
+
+ #separator \x09
+ #set_separator ,
+ #empty_field (empty)
+ #unset_field -
+ #path factor
+ #open 2013-08-30-23-20-49
+ #fields num factorial_num
+ #types count count
+ 1 1
+ 2 2
+ 3 6
+ 4 24
+ 5 120
+ 6 720
+ 7 5040
+ 8 40320
+ 9 362880
+ 10 3628800
+ #close 2013-08-30-23-20-49
+
diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1
new file mode 100644
index 0000000000..f19018b16c
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1
@@ -0,0 +1,25 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro framework_logging_factorial_03.bro
+
+.. code-block:: guess
+ :linenos:
+
+ #separator \x09
+ #set_separator ,
+ #empty_field (empty)
+ #unset_field -
+ #path factor-mod5
+ #open 2013-08-30-23-20-49
+ #fields num factorial_num
+ #types count count
+ 5 120
+ 6 720
+ 7 5040
+ 8 40320
+ 9 362880
+ 10 3628800
+ #close 2013-08-30-23-20-49
+
diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1
new file mode 100644
index 0000000000..8a64a2da65
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1
@@ -0,0 +1,16 @@
+.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro framework_logging_factorial_01.bro
+ 1
+ 2
+ 6
+ 24
+ 120
+ 720
+ 5040
+ 40320
+ 362880
+ 3628800
+
diff --git a/testing/btest/doc/manual/connection_record_02.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest
similarity index 53%
rename from testing/btest/doc/manual/connection_record_02.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest
index 480e42af0b..43a6ebc554 100644
--- a/testing/btest/doc/manual/connection_record_02.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest
@@ -1,10 +1,11 @@
-# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- connection_record_02.bro
@load base/protocols/conn
@load base/protocols/dns
event connection_state_remove(c: connection)
- {
+ {
print c;
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest
new file mode 100644
index 0000000000..43a6ebc554
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- connection_record_02.bro
+
+@load base/protocols/conn
+@load base/protocols/dns
+
+event connection_state_remove(c: connection)
+ {
+ print c;
+ }
diff --git a/testing/btest/doc/manual/data_struct_record_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest
similarity index 53%
rename from testing/btest/doc/manual/data_struct_record_01.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest
index 25eb0b02a0..82f1b1f56c 100644
--- a/testing/btest/doc/manual/data_struct_record_01.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest
@@ -1,5 +1,6 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_record_01.bro
type Service: record {
name: string;
@@ -10,16 +11,16 @@ type Service: record {
function print_service(serv: Service): string
{
print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
- for (p in serv$ports)
- {
+
+ for ( p in serv$ports )
print fmt(" port: %s", p);
- }
}
event bro_init()
{
- local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
- local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+ local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
+ local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+
print_service(dns);
print_service(http);
}
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest
new file mode 100644
index 0000000000..05b5b9d50c
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest
@@ -0,0 +1,45 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_record_02.bro
+
+type Service: record {
+ name: string;
+ ports: set[port];
+ rfc: count;
+ };
+
+type System: record {
+ name: string;
+ services: set[Service];
+ };
+
+function print_service(serv: Service): string
+ {
+ print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
+
+ for ( p in serv$ports )
+ print fmt(" port: %s", p);
+ }
+
+function print_system(sys: System): string
+ {
+ print fmt("System: %s", sys$name);
+
+ for ( s in sys$services )
+ print_service(s);
+ }
+
+event bro_init()
+ {
+ local server01: System;
+ server01$name = "morlock";
+ add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]];
+ add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]];
+ print_system(server01);
+
+
+ # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
+ # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+ # print_service(dns);
+ # print_service(http);
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest
new file mode 100644
index 0000000000..b659563ac3
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+event bro_init()
+ {
+ local ssl_ports: set[port];
+ local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest
new file mode 100644
index 0000000000..5fa1f36475
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+ for ( i in ssl_ports )
+ print fmt("SSL Port: %s", i);
+
+ for ( i in non_ssl_ports )
+ print fmt("Non-SSL Port: %s", i);
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest
new file mode 100644
index 0000000000..48d33b52e5
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest
@@ -0,0 +1,7 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+ # Check for SMTPS
+ if ( 587/tcp !in ssl_ports )
+ add ssl_ports[587/tcp];
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest
new file mode 100644
index 0000000000..19ddfe81d5
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest
@@ -0,0 +1,26 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+event bro_init()
+ {
+ local ssl_ports: set[port];
+ local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
+
+ # SSH
+ add ssl_ports[22/tcp];
+ # HTTPS
+ add ssl_ports[443/tcp];
+ # IMAPS
+ add ssl_ports[993/tcp];
+
+ # Check for SMTPS
+ if ( 587/tcp !in ssl_ports )
+ add ssl_ports[587/tcp];
+
+ for ( i in ssl_ports )
+ print fmt("SSL Port: %s", i);
+
+ for ( i in non_ssl_ports )
+ print fmt("Non-SSL Port: %s", i);
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest
new file mode 100644
index 0000000000..a6a1d7a63a
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_table_complex.bro
+
+event bro_init()
+ {
+ local samurai_flicks: table[string, string, count, string] of string;
+
+ samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru";
+ samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin";
+ samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri";
+ samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei";
+
+ for ( [d, s, y, a] in samurai_flicks )
+ print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a);
+ }
+
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest
new file mode 100644
index 0000000000..79fe7660ae
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_table_declaration.bro
+
+event bro_init()
+ {
+ local ssl_services: table[string] of port;
+
+ ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp);
+ ssl_services["IMAPS"] = 993/tcp;
+
+ if ( "SMTPS" !in ssl_services )
+ ssl_services["SMTPS"] = 587/tcp;
+
+ for ( k in ssl_services )
+ print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]);
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest
new file mode 100644
index 0000000000..6b8a81a58f
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest
@@ -0,0 +1,19 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_vector_declaration.bro
+
+event bro_init()
+ {
+ local v1: vector of count;
+ local v2 = vector(1, 2, 3, 4);
+
+ v1[|v1|] = 1;
+ v1[|v1|] = 2;
+ v1[|v1|] = 3;
+ v1[|v1|] = 4;
+
+ print fmt("contents of v1: %s", v1);
+ print fmt("length of v1: %d", |v1|);
+ print fmt("contents of v1: %s", v2);
+ print fmt("length of v2: %d", |v2|);
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest
new file mode 100644
index 0000000000..a28522fb64
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_vector_iter.bro
+
+event bro_init()
+ {
+ local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6);
+
+ for (i in addr_vector)
+ print mask_addr(addr_vector[i], 18);
+ }
diff --git a/testing/btest/doc/manual/data_type_const.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest
similarity index 72%
rename from testing/btest/doc/manual/data_type_const.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest
index bdcc888945..a42efd2b72 100644
--- a/testing/btest/doc/manual/data_type_const.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest
@@ -1,5 +1,6 @@
-# @TEST-EXEC: bro -b %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_const.bro
const port_list: table[port] of string &redef;
@@ -9,4 +10,4 @@ redef port_list += { [80/tcp] = "WWW" };
event bro_init()
{
print port_list;
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest
new file mode 100644
index 0000000000..914f9dc0ec
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest
@@ -0,0 +1,8 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_const_simple.bro
+
+@load base/protocols/http
+
+redef HTTP::default_capture_password = T;
+
diff --git a/testing/btest/doc/manual/data_type_declaration.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest
similarity index 53%
rename from testing/btest/doc/manual/data_type_declaration.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest
index ba82e0da20..edd01615fc 100644
--- a/testing/btest/doc/manual/data_type_declaration.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest
@@ -1,5 +1,6 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_declaration.bro
event bro_init()
{
@@ -7,8 +8,6 @@ event bro_init()
a = 10;
local b = 10;
- if (a == b)
- {
+ if ( a == b )
print fmt("A: %d, B: %d", a, b);
- }
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest
new file mode 100644
index 0000000000..7954ed9ebe
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest
@@ -0,0 +1,22 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_interval.bro
+
+# Store the time the previous connection was established.
+global last_connection_time: time;
+
+# boolean value to indicate whether we have seen a previous connection.
+global connection_seen: bool = F;
+
+event connection_established(c: connection)
+ {
+ local net_time: time = network_time();
+
+ print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h);
+
+ if ( connection_seen )
+ print fmt(" Time since last connection: %s", net_time - last_connection_time);
+
+ last_connection_time = net_time;
+ connection_seen = T;
+ }
diff --git a/testing/btest/doc/manual/data_type_local.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest
similarity index 75%
rename from testing/btest/doc/manual/data_type_local.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest
index e589f39e9f..850ffeb905 100644
--- a/testing/btest/doc/manual/data_type_local.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest
@@ -1,5 +1,6 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_local.bro
function add_two(i: count): count
{
@@ -11,4 +12,4 @@ function add_two(i: count): count
event bro_init()
{
local test = add_two(10);
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest
new file mode 100644
index 0000000000..475fcd676e
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_pattern_01.bro
+
+event bro_init()
+ {
+ local test_string = "The quick brown fox jumped over the lazy dog.";
+ local test_pattern = /quick|lazy/;
+
+ if ( test_pattern in test_string )
+ {
+ local results = split(test_string, test_pattern);
+ print results[1];
+ print results[2];
+ print results[3];
+ }
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest
new file mode 100644
index 0000000000..915e8612be
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest
@@ -0,0 +1,14 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_pattern_02.bro
+
+event bro_init()
+ {
+ local test_string = "equality";
+
+ local test_pattern = /equal/;
+ print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
+
+ test_pattern = /equality/;
+ print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
+ }
diff --git a/testing/btest/doc/manual/data_type_subnets.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest
similarity index 63%
rename from testing/btest/doc/manual/data_type_subnets.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest
index b0d174069a..d2edfd5e9a 100644
--- a/testing/btest/doc/manual/data_type_subnets.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest
@@ -1,22 +1,19 @@
-# @TEST-EXEC: bro -b %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_subnets.bro
event bro_init()
{
local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20);
local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1);
- for (a in addresses)
+
+ for ( a in addresses )
{
- for (s in subnets)
+ for ( s in subnets )
{
- if (addresses[a] in subnets[s])
- {
+ if ( addresses[a] in subnets[s] )
print fmt("%s belongs to subnet %s", addresses[a], subnets[s]);
- }
}
}
}
-
-
-
diff --git a/testing/btest/doc/manual/data_type_time.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest
similarity index 66%
rename from testing/btest/doc/manual/data_type_time.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest
index 45bff4479e..960d4ac9bd 100644
--- a/testing/btest/doc/manual/data_type_time.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest
@@ -1,7 +1,8 @@
-# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_time.bro
event connection_established(c: connection)
- {
+ {
print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h);
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/framework_logging_factorial_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest
similarity index 73%
rename from testing/btest/doc/manual/framework_logging_factorial_01.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest
index 961ee584bc..7a18c86509 100644
--- a/testing/btest/doc/manual/framework_logging_factorial_01.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest
@@ -1,27 +1,23 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_01.bro
module Factor;
function factorial(n: count): count
{
if ( n == 0 )
- {
return 1;
- }
else
- {
return ( n * factorial(n - 1) );
- }
}
event bro_init()
{
local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
for ( n in numbers )
- {
print fmt("%d", factorial(numbers[n]));
- }
}
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest
new file mode 100644
index 0000000000..6966f7ea3c
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest
@@ -0,0 +1,36 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_02.bro
+
+module Factor;
+
+export {
+ redef enum Log::ID += { LOG };
+
+ type Info: record {
+ num: count &log;
+ factorial_num: count &log;
+ };
+ }
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+
+ else
+ return ( n * factorial(n - 1) );
+ }
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info]);
+ }
+
+event bro_done()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ for ( n in numbers )
+ Log::write( Factor::LOG, [$num=numbers[n],
+ $factorial_num=factorial(numbers[n])]);
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest
new file mode 100644
index 0000000000..c3c16f8d6a
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest
@@ -0,0 +1,12 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_03.bro
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info]);
+
+ local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
+ Log::add_filter(Factor::LOG, filter);
+ Log::remove_filter(Factor::LOG, "default");
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest
new file mode 100644
index 0000000000..dbedb8e689
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest
@@ -0,0 +1,54 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_04.bro
+
+module Factor;
+
+export {
+ redef enum Log::ID += { LOG };
+
+ type Info: record {
+ num: count &log;
+ factorial_num: count &log;
+ };
+
+ global log_factor: event(rec: Info);
+ }
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+
+ else
+ return (n * factorial(n - 1));
+ }
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info, $ev=log_factor]);
+ }
+
+event bro_done()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ for ( n in numbers )
+ Log::write( Factor::LOG, [$num=numbers[n],
+ $factorial_num=factorial(numbers[n])]);
+ }
+
+function mod5(id: Log::ID, path: string, rec: Factor::Info) : string
+ {
+ if ( rec$factorial_num % 5 == 0 )
+ return "factor-mod5";
+
+ else
+ return "factor-non5";
+ }
+
+event bro_init()
+ {
+ local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
+ Log::add_filter(Factor::LOG, filter);
+ Log::remove_filter(Factor::LOG, "default");
+ }
diff --git a/testing/btest/doc/manual/framework_notice_hook_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest
similarity index 71%
rename from testing/btest/doc/manual/framework_notice_hook_01.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest
index 3ec0bbff02..70f8c70247 100644
--- a/testing/btest/doc/manual/framework_notice_hook_01.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest
@@ -1,12 +1,11 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_hook_01.bro
@load policy/protocols/ssh/interesting-hostnames.bro
hook Notice::policy(n: Notice::Info)
{
if ( n$note == SSH::Interesting_Hostname_Login )
- {
add n$actions[Notice::ACTION_EMAIL];
- }
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest
similarity index 69%
rename from testing/btest/doc/manual/framework_notice_hook_suppression_01.bro
rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest
index 3d948f65b5..522bef5930 100644
--- a/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest
@@ -1,12 +1,11 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_hook_suppression_01.bro
@load policy/protocols/ssl/expiring-certs.bro
hook Notice::policy(n: Notice::Info)
{
if ( n$note == SSL::Certificate_Expires_Soon )
- {
n$suppress_for = 12hrs;
- }
}
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest
new file mode 100644
index 0000000000..95eed5f501
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest
@@ -0,0 +1,12 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_shortcuts_01.bro
+
+@load policy/protocols/ssh/interesting-hostnames.bro
+@load base/protocols/ssh/
+
+redef Notice::emailed_types += {
+ SSH::Interesting_Hostname_Login,
+ SSH::Login
+};
+
diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest
new file mode 100644
index 0000000000..8c12558d42
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_shortcuts_02.bro
+
+@load policy/protocols/ssh/interesting-hostnames.bro
+@load base/protocols/ssh/
+
+redef Notice::type_suppression_intervals += {
+ [SSH::Interesting_Hostname_Login] = 1day,
+ [SSH::Login] = 12hrs,
+};
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest
new file mode 100644
index 0000000000..088d5d2368
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest
@@ -0,0 +1,25 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- event.bif.bro
+
+## script-level cleanup that needs to be performed for every connection. This
+## event is generated not only for TCP sessions but also for UDP and ICMP
+## flows.
+##
+##
+global connection_external: event(c: connection , tag: string );
+
+
+## Generated when a UDP session for a supported protocol has finished. Some of
+## Bro's application-layer UDP analyzers flag the end of a session by raising
+## Generated when a connection is seen that is marked as being expected.
+
+
+global ipv6_ext_headers: event(c: connection , p: pkt_hdr );
+## their specifics differ slightly. Often, however, both will be raised for
+## the same connection if some of its data is missing. We should eventually
+## merge the two.
+global ack_above_hole: event(c: connection );
+
+
+##
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest
new file mode 100644
index 0000000000..c8e7eaab20
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest
@@ -0,0 +1,30 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- Bro_DNS.events.bif.bro
+
+## Generated for DNS requests. For requests with multiple queries, this event
+## is raised once for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS
+## sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## query: The queried name.
+##
+## qtype: The queried resource record type.
+##
+## qclass: The queried resource record class.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count );
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest
new file mode 100644
index 0000000000..7d23c68ae4
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest
@@ -0,0 +1,7 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- init-bare.bro
+
+type string_array: table[count] of string;
+type string_set: set[string];
+type addr_set: set[addr];
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest
new file mode 100644
index 0000000000..dc18745d57
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest
@@ -0,0 +1,28 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- main.bro
+
+module Conn;
+
+export {
+ ## The record type which contains column fields of the connection log.
+ type Info: record {
+ ts: time &log;
+ uid: string &log;
+ id: conn_id &log;
+ proto: transport_proto &log;
+ service: string &log &optional;
+ duration: interval &log &optional;
+ orig_bytes: count &log &optional;
+ resp_bytes: count &log &optional;
+ conn_state: string &log &optional;
+ local_orig: bool &log &optional;
+ missed_bytes: count &log &default=0;
+ history: string &log &optional;
+ orig_pkts: count &log &optional;
+ orig_ip_bytes: count &log &optional;
+ resp_pkts: count &log &optional;
+ resp_ip_bytes: count &log &optional;
+ tunnel_parents: set[string] &log;
+ };
+}
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest
new file mode 100644
index 0000000000..abe74112bd
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest
@@ -0,0 +1,10 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- main.bro
+
+module HTTP;
+
+export {
+ ## This setting changes if passwords used in Basic-Auth are captured or not.
+ const default_capture_password = F &redef;
+}
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest
new file mode 100644
index 0000000000..b73140fe8e
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest
@@ -0,0 +1,61 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+##! Detect file downloads that have hash values matching files in Team
+##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
+
+@load base/frameworks/files
+@load base/frameworks/notice
+@load frameworks/files/hash-all-files
+
+module TeamCymruMalwareHashRegistry;
+
+export {
+ redef enum Notice::Type += {
+ ## The hash value of a file transferred over HTTP matched in the
+ ## malware hash registry.
+ Match
+ };
+
+ ## File types to attempt matching against the Malware Hash Registry.
+ const match_file_types = /application\/x-dosexec/ |
+ /application\/vnd.ms-cab-compressed/ |
+ /application\/pdf/ |
+ /application\/x-shockwave-flash/ |
+ /application\/x-java-applet/ |
+ /application\/jar/ |
+ /video\/mp4/ &redef;
+
+ ## The malware hash registry runs each malware sample through several A/V engines.
+ ## Team Cymru returns a percentage to indicate how many A/V engines flagged the
+ ## sample as malicious. This threshold allows you to require a minimum detection
+ ## rate.
+ const notice_threshold = 10 &redef;
+}
+
+event file_hash(f: fa_file, kind: string, hash: string)
+ {
+ if ( kind=="sha1" && match_file_types in f$mime_type )
+ {
+ local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
+ when ( local MHR_result = lookup_hostname_txt(hash_domain) )
+ {
+ # Data is returned as " "
+ local MHR_answer = split1(MHR_result, / /);
+ if ( |MHR_answer| == 2 )
+ {
+ local mhr_first_detected = double_to_time(to_double(MHR_answer[1]));
+ local mhr_detect_rate = to_count(MHR_answer[2]);
+
+ local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected);
+ if ( mhr_detect_rate >= notice_threshold )
+ {
+ local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected);
+ local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash);
+ NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]);
+ }
+ }
+ }
+ }
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest
new file mode 100644
index 0000000000..51044b36d9
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+
+module TeamCymruMalwareHashRegistry;
+
+export {
+ redef enum Notice::Type += {
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest
new file mode 100644
index 0000000000..37de8b6ff7
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+ ## The hash value of a file transferred over HTTP matched in the
+ ## malware hash registry.
+ Match
+ };
+
+ ## File types to attempt matching against the Malware Hash Registry.
+ const match_file_types = /application\/x-dosexec/ |
+ /application\/vnd.ms-cab-compressed/ |
+ /application\/pdf/ |
+ /application\/x-shockwave-flash/ |
+ /application\/x-java-applet/ |
+ /application\/jar/ |
+ /video\/mp4/ &redef;
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest
new file mode 100644
index 0000000000..19e9d2ee54
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest
@@ -0,0 +1,23 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+ ## The malware hash registry runs each malware sample through several A/V engines.
+ ## Team Cymru returns a percentage to indicate how many A/V engines flagged the
+ ## sample as malicious. This threshold allows you to require a minimum detection
+ ## rate.
+ const notice_threshold = 10 &redef;
+}
+
+event file_hash(f: fa_file, kind: string, hash: string)
+ {
+ if ( kind=="sha1" && match_file_types in f$mime_type )
+ {
+ local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
+ when ( local MHR_result = lookup_hostname_txt(hash_domain) )
+ {
+ # Data is returned as " "
+ local MHR_answer = split1(MHR_result, / /);
+ if ( |MHR_answer| == 2 )
+ {
+ local mhr_first_detected = double_to_time(to_double(MHR_answer[1]));
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest
new file mode 100644
index 0000000000..9b0c50c3f4
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- known-hosts.bro
+
+module Known;
+
+export {
+ global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
+}
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest
new file mode 100644
index 0000000000..73eec1a1b9
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest
@@ -0,0 +1,50 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- interesting-hostnames.bro
+
+##! This script will generate a notice if an apparent SSH login originates
+##! or heads to a host with a reverse hostname that looks suspicious. By
+##! default, the regular expression to match "interesting" hostnames includes
+##! names that are typically used for infrastructure hosts like nameservers,
+##! mail servers, web servers and ftp servers.
+
+@load base/frameworks/notice
+
+module SSH;
+
+export {
+ redef enum Notice::Type += {
+ ## Generated if a login originates or responds with a host where the
+ ## reverse hostname lookup resolves to a name matched by the
+ ## :bro:id:`SSH::interesting_hostnames` regular expression.
+ Interesting_Hostname_Login,
+ };
+
+ ## Strange/bad host names to see successful SSH logins from or to.
+ const interesting_hostnames =
+ /^d?ns[0-9]*\./ |
+ /^smtp[0-9]*\./ |
+ /^mail[0-9]*\./ |
+ /^pop[0-9]*\./ |
+ /^imap[0-9]*\./ |
+ /^www[0-9]*\./ |
+ /^ftp[0-9]*\./ &redef;
+}
+
+event SSH::heuristic_successful_login(c: connection)
+ {
+ for ( host in set(c$id$orig_h, c$id$resp_h) )
+ {
+ when ( local hostname = lookup_addr(host) )
+ {
+ if ( interesting_hostnames in hostname )
+ {
+ NOTICE([$note=Interesting_Hostname_Login,
+ $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.",
+ Site::is_local_addr(host) ? "local" : "remote",
+ host == c$id$orig_h ? "client" : "server"),
+ $sub=hostname, $conn=c]);
+ }
+ }
+ }
+ }
diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest
new file mode 100644
index 0000000000..16e2552545
--- /dev/null
+++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest
@@ -0,0 +1,8 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- expiring-certs.bro
+
+ NOTICE([$note=Certificate_Expires_Soon,
+ $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after),
+ $conn=c, $suppress_for=1day,
+ $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]);
diff --git a/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst b/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst
deleted file mode 100644
index 6b59bf64a2..0000000000
--- a/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-.. code-block:: none
-
- # bro -r wikipedia.trace
-
-.. code-block:: none
-
- # cat http.log | bro-cut ts id.orig_h | head -5
- 1300475168.843894 141.142.220.118
- 1300475168.975800 141.142.220.118
- 1300475168.976327 141.142.220.118
- 1300475168.979160 141.142.220.118
- 1300475169.012666 141.142.220.118
-
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1
index 1512c0c8ef..8958f860f6 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1
@@ -1,12 +1,18 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
+
+ # bro -r wikipedia.trace
+
+.. code-block:: guess
+ :linenos:
- # bro -r wikipedia.trace && head -15 conn.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
- #open 2013-08-22-22-52-46
+ #open 2013-08-30-23-20-51
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents
#types time string addr port addr port enum string interval count count string bool count string count count count count table[string]
1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty)
@@ -16,4 +22,5 @@
1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty)
1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty)
1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty)
+ [...]
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2
index 13ddfbb931..b455b9a8e8 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration
141.142.220.202 5353 224.0.0.251 -
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3
index 8a35312c44..8492053976 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log
141.142.220.202 5353 224.0.0.251 5353 -
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4
index f171bab392..8070ca3039 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# bro-cut -d ts uid host uri < http.log
2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5
index 491930cbc1..7aa5ab7e5f 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# bro-cut -u ts uid host uri < http.log
2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6
index a2b2316257..a3d261eca3 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log
18-03-2011T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7
index bdbf0e20a0..5b991fd43b 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5
VW0XPVINV8a 734
diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8
index 67d0417de8..d5a53c234e 100644
--- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8
+++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8
@@ -1,4 +1,6 @@
.. code-block:: none
+ :linenos:
+ :emphasize-lines: 1,1
# cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a
VW0XPVINV8a 208.80.152.3 GET 304 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png
diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg
index da0487f5ef..d53c2d8799 100644
--- a/testing/btest/btest.cfg
+++ b/testing/btest/btest.cfg
@@ -16,6 +16,7 @@ BTEST_PATH=%(testbase)s/../../aux/btest
PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(testbase)s/../../aux/bro-aux/bro-cut:%(default_path)s:%(testbase)s/../../aux/btest/sphinx:%(default_path)s
TRACES=%(testbase)s/Traces
SCRIPTS=%(testbase)s/../scripts
+DOC_ROOT=%(testbase)s/../../doc
DIST=%(testbase)s/../..
BUILD=%(testbase)s/../../build
TEST_DIFF_CANONIFIER=%(testbase)s/../scripts/diff-canonifier
diff --git a/testing/btest/doc/manual/connection_record_01.bro b/testing/btest/doc/manual/connection_record_01.bro
deleted file mode 100644
index ffd2f82dcc..0000000000
--- a/testing/btest/doc/manual/connection_record_01.bro
+++ /dev/null
@@ -1,9 +0,0 @@
-# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
-@load base/protocols/conn
-
-event connection_state_remove(c: connection)
- {
- print c;
- }
\ No newline at end of file
diff --git a/testing/btest/doc/manual/data_struct_vector_iter.bro b/testing/btest/doc/manual/data_struct_vector_iter.bro
deleted file mode 100644
index 96574eab1b..0000000000
--- a/testing/btest/doc/manual/data_struct_vector_iter.bro
+++ /dev/null
@@ -1,12 +0,0 @@
-# @TEST-EXEC: bro %INPUT
-# @TEST-EXEC: btest-diff .stdout
-
-event bro_init()
- {
- local addr_vector: vector of addr = vector( 1.2.3.4, 2.3.4.5, 3.4.5.6);
-
- for (i in addr_vector)
- {
- print mask_addr(addr_vector[i], 18);
- }
- }
diff --git a/testing/btest/doc/sphinx/connection-record-01.btest b/testing/btest/doc/sphinx/connection-record-01.btest
new file mode 100644
index 0000000000..b379fb4fbe
--- /dev/null
+++ b/testing/btest/doc/sphinx/connection-record-01.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_01.bro
diff --git a/testing/btest/doc/sphinx/connection-record-02.btest b/testing/btest/doc/sphinx/connection-record-02.btest
new file mode 100644
index 0000000000..292503e12c
--- /dev/null
+++ b/testing/btest/doc/sphinx/connection-record-02.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_02.bro
diff --git a/testing/btest/doc/sphinx/data_struct_record_01.btest b/testing/btest/doc/sphinx/data_struct_record_01.btest
new file mode 100644
index 0000000000..ae52b9a24d
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_record_01.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_01.bro
diff --git a/testing/btest/doc/sphinx/data_struct_record_02.btest b/testing/btest/doc/sphinx/data_struct_record_02.btest
new file mode 100644
index 0000000000..d978224e3b
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_record_02.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro
diff --git a/testing/btest/doc/sphinx/data_struct_set_declaration.btest b/testing/btest/doc/sphinx/data_struct_set_declaration.btest
new file mode 100644
index 0000000000..2812479dff
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_set_declaration.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_set_declaration.bro
diff --git a/testing/btest/doc/sphinx/data_struct_table_complex.btest b/testing/btest/doc/sphinx/data_struct_table_complex.btest
new file mode 100644
index 0000000000..99117130f8
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_table_complex.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_table_complex.bro
diff --git a/testing/btest/doc/sphinx/data_struct_table_declaration.btest b/testing/btest/doc/sphinx/data_struct_table_declaration.btest
new file mode 100644
index 0000000000..ac83e84e45
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_table_declaration.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_table_declaration.bro
diff --git a/testing/btest/doc/sphinx/data_struct_vector_declaration.btest b/testing/btest/doc/sphinx/data_struct_vector_declaration.btest
new file mode 100644
index 0000000000..b017f84aed
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_vector_declaration.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro
diff --git a/testing/btest/doc/sphinx/data_struct_vector_iter.btest b/testing/btest/doc/sphinx/data_struct_vector_iter.btest
new file mode 100644
index 0000000000..f5e6c2a0ba
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_struct_vector_iter.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_vector_iter.bro
diff --git a/testing/btest/doc/sphinx/data_type_const.bro.btest b/testing/btest/doc/sphinx/data_type_const.bro.btest
new file mode 100644
index 0000000000..903fed3fbf
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_const.bro.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_type_const.bro
diff --git a/testing/btest/doc/sphinx/data_type_interval.btest b/testing/btest/doc/sphinx/data_type_interval.btest
new file mode 100644
index 0000000000..0c1baa1372
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_interval.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_interval.bro
diff --git a/testing/btest/doc/sphinx/data_type_pattern.btest b/testing/btest/doc/sphinx/data_type_pattern.btest
new file mode 100644
index 0000000000..30ba3c6fe0
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_pattern.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_01.bro
diff --git a/testing/btest/doc/sphinx/data_type_pattern_02.btest b/testing/btest/doc/sphinx/data_type_pattern_02.btest
new file mode 100644
index 0000000000..b197cef792
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_pattern_02.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_02.bro
diff --git a/testing/btest/doc/sphinx/data_type_subnets.btest b/testing/btest/doc/sphinx/data_type_subnets.btest
new file mode 100644
index 0000000000..c78fe8c71c
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_subnets.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_subnets.bro
diff --git a/testing/btest/doc/sphinx/data_type_time.btest b/testing/btest/doc/sphinx/data_type_time.btest
new file mode 100644
index 0000000000..29dee6002f
--- /dev/null
+++ b/testing/btest/doc/sphinx/data_type_time.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_time.bro
diff --git a/testing/btest/doc/sphinx/framework_logging_factorial-2.btest b/testing/btest/doc/sphinx/framework_logging_factorial-2.btest
new file mode 100644
index 0000000000..c0f1262217
--- /dev/null
+++ b/testing/btest/doc/sphinx/framework_logging_factorial-2.btest
@@ -0,0 +1,2 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro
+@TEST-EXEC: btest-rst-include factor.log
diff --git a/testing/btest/doc/sphinx/framework_logging_factorial-3.btest b/testing/btest/doc/sphinx/framework_logging_factorial-3.btest
new file mode 100644
index 0000000000..75f2054661
--- /dev/null
+++ b/testing/btest/doc/sphinx/framework_logging_factorial-3.btest
@@ -0,0 +1,2 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro
+@TEST-EXEC: btest-rst-include factor-mod5.log
diff --git a/testing/btest/doc/sphinx/framework_logging_factorial.btest b/testing/btest/doc/sphinx/framework_logging_factorial.btest
new file mode 100644
index 0000000000..798b821f87
--- /dev/null
+++ b/testing/btest/doc/sphinx/framework_logging_factorial.btest
@@ -0,0 +1 @@
+@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest
new file mode 100644
index 0000000000..43a6ebc554
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- connection_record_02.bro
+
+@load base/protocols/conn
+@load base/protocols/dns
+
+event connection_state_remove(c: connection)
+ {
+ print c;
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest
new file mode 100644
index 0000000000..43a6ebc554
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- connection_record_02.bro
+
+@load base/protocols/conn
+@load base/protocols/dns
+
+event connection_state_remove(c: connection)
+ {
+ print c;
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest
new file mode 100644
index 0000000000..82f1b1f56c
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest
@@ -0,0 +1,26 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_record_01.bro
+
+type Service: record {
+ name: string;
+ ports: set[port];
+ rfc: count;
+};
+
+function print_service(serv: Service): string
+ {
+ print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
+
+ for ( p in serv$ports )
+ print fmt(" port: %s", p);
+ }
+
+event bro_init()
+ {
+ local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
+ local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+
+ print_service(dns);
+ print_service(http);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest
new file mode 100644
index 0000000000..05b5b9d50c
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest
@@ -0,0 +1,45 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_record_02.bro
+
+type Service: record {
+ name: string;
+ ports: set[port];
+ rfc: count;
+ };
+
+type System: record {
+ name: string;
+ services: set[Service];
+ };
+
+function print_service(serv: Service): string
+ {
+ print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
+
+ for ( p in serv$ports )
+ print fmt(" port: %s", p);
+ }
+
+function print_system(sys: System): string
+ {
+ print fmt("System: %s", sys$name);
+
+ for ( s in sys$services )
+ print_service(s);
+ }
+
+event bro_init()
+ {
+ local server01: System;
+ server01$name = "morlock";
+ add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]];
+ add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]];
+ print_system(server01);
+
+
+ # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
+ # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
+ # print_service(dns);
+ # print_service(http);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest
new file mode 100644
index 0000000000..b659563ac3
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+event bro_init()
+ {
+ local ssl_ports: set[port];
+ local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest
new file mode 100644
index 0000000000..5fa1f36475
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+ for ( i in ssl_ports )
+ print fmt("SSL Port: %s", i);
+
+ for ( i in non_ssl_ports )
+ print fmt("Non-SSL Port: %s", i);
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest
new file mode 100644
index 0000000000..48d33b52e5
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest
@@ -0,0 +1,7 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+ # Check for SMTPS
+ if ( 587/tcp !in ssl_ports )
+ add ssl_ports[587/tcp];
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest
new file mode 100644
index 0000000000..19ddfe81d5
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest
@@ -0,0 +1,26 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_set_declaration.bro
+
+event bro_init()
+ {
+ local ssl_ports: set[port];
+ local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
+
+ # SSH
+ add ssl_ports[22/tcp];
+ # HTTPS
+ add ssl_ports[443/tcp];
+ # IMAPS
+ add ssl_ports[993/tcp];
+
+ # Check for SMTPS
+ if ( 587/tcp !in ssl_ports )
+ add ssl_ports[587/tcp];
+
+ for ( i in ssl_ports )
+ print fmt("SSL Port: %s", i);
+
+ for ( i in non_ssl_ports )
+ print fmt("Non-SSL Port: %s", i);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest
new file mode 100644
index 0000000000..a6a1d7a63a
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_table_complex.bro
+
+event bro_init()
+ {
+ local samurai_flicks: table[string, string, count, string] of string;
+
+ samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru";
+ samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin";
+ samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri";
+ samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei";
+
+ for ( [d, s, y, a] in samurai_flicks )
+ print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a);
+ }
+
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest
new file mode 100644
index 0000000000..79fe7660ae
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_table_declaration.bro
+
+event bro_init()
+ {
+ local ssl_services: table[string] of port;
+
+ ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp);
+ ssl_services["IMAPS"] = 993/tcp;
+
+ if ( "SMTPS" !in ssl_services )
+ ssl_services["SMTPS"] = 587/tcp;
+
+ for ( k in ssl_services )
+ print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest
new file mode 100644
index 0000000000..6b8a81a58f
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest
@@ -0,0 +1,19 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_vector_declaration.bro
+
+event bro_init()
+ {
+ local v1: vector of count;
+ local v2 = vector(1, 2, 3, 4);
+
+ v1[|v1|] = 1;
+ v1[|v1|] = 2;
+ v1[|v1|] = 3;
+ v1[|v1|] = 4;
+
+ print fmt("contents of v1: %s", v1);
+ print fmt("length of v1: %d", |v1|);
+ print fmt("contents of v1: %s", v2);
+ print fmt("length of v2: %d", |v2|);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest
new file mode 100644
index 0000000000..a28522fb64
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_struct_vector_iter.bro
+
+event bro_init()
+ {
+ local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6);
+
+ for (i in addr_vector)
+ print mask_addr(addr_vector[i], 18);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest
new file mode 100644
index 0000000000..a42efd2b72
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest
@@ -0,0 +1,13 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_const.bro
+
+const port_list: table[port] of string &redef;
+
+redef port_list += { [6666/tcp] = "IRC"};
+redef port_list += { [80/tcp] = "WWW" };
+
+event bro_init()
+ {
+ print port_list;
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest
new file mode 100644
index 0000000000..914f9dc0ec
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest
@@ -0,0 +1,8 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_const_simple.bro
+
+@load base/protocols/http
+
+redef HTTP::default_capture_password = T;
+
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest
new file mode 100644
index 0000000000..edd01615fc
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest
@@ -0,0 +1,13 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_declaration.bro
+
+event bro_init()
+ {
+ local a: int;
+ a = 10;
+ local b = 10;
+
+ if ( a == b )
+ print fmt("A: %d, B: %d", a, b);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest
new file mode 100644
index 0000000000..7954ed9ebe
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest
@@ -0,0 +1,22 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_interval.bro
+
+# Store the time the previous connection was established.
+global last_connection_time: time;
+
+# boolean value to indicate whether we have seen a previous connection.
+global connection_seen: bool = F;
+
+event connection_established(c: connection)
+ {
+ local net_time: time = network_time();
+
+ print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h);
+
+ if ( connection_seen )
+ print fmt(" Time since last connection: %s", net_time - last_connection_time);
+
+ last_connection_time = net_time;
+ connection_seen = T;
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest
new file mode 100644
index 0000000000..850ffeb905
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest
@@ -0,0 +1,15 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_local.bro
+
+function add_two(i: count): count
+ {
+ local added_two = i+2;
+ print fmt("i + 2 = %d", added_two);
+ return added_two;
+ }
+
+event bro_init()
+ {
+ local test = add_two(10);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest
new file mode 100644
index 0000000000..475fcd676e
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_pattern_01.bro
+
+event bro_init()
+ {
+ local test_string = "The quick brown fox jumped over the lazy dog.";
+ local test_pattern = /quick|lazy/;
+
+ if ( test_pattern in test_string )
+ {
+ local results = split(test_string, test_pattern);
+ print results[1];
+ print results[2];
+ print results[3];
+ }
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest
new file mode 100644
index 0000000000..915e8612be
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest
@@ -0,0 +1,14 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_pattern_02.bro
+
+event bro_init()
+ {
+ local test_string = "equality";
+
+ local test_pattern = /equal/;
+ print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
+
+ test_pattern = /equality/;
+ print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest
new file mode 100644
index 0000000000..d2edfd5e9a
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest
@@ -0,0 +1,19 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_subnets.bro
+
+event bro_init()
+ {
+ local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20);
+ local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1);
+
+ for ( a in addresses )
+ {
+ for ( s in subnets )
+ {
+ if ( addresses[a] in subnets[s] )
+ print fmt("%s belongs to subnet %s", addresses[a], subnets[s]);
+ }
+ }
+
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest
new file mode 100644
index 0000000000..960d4ac9bd
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest
@@ -0,0 +1,8 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- data_type_time.bro
+
+event connection_established(c: connection)
+ {
+ print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest
new file mode 100644
index 0000000000..7a18c86509
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest
@@ -0,0 +1,23 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_01.bro
+
+module Factor;
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+ else
+ return ( n * factorial(n - 1) );
+ }
+
+event bro_init()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+ for ( n in numbers )
+ print fmt("%d", factorial(numbers[n]));
+ }
+
+
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest
new file mode 100644
index 0000000000..6966f7ea3c
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest
@@ -0,0 +1,36 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_02.bro
+
+module Factor;
+
+export {
+ redef enum Log::ID += { LOG };
+
+ type Info: record {
+ num: count &log;
+ factorial_num: count &log;
+ };
+ }
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+
+ else
+ return ( n * factorial(n - 1) );
+ }
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info]);
+ }
+
+event bro_done()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ for ( n in numbers )
+ Log::write( Factor::LOG, [$num=numbers[n],
+ $factorial_num=factorial(numbers[n])]);
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest
new file mode 100644
index 0000000000..c3c16f8d6a
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest
@@ -0,0 +1,12 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_03.bro
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info]);
+
+ local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
+ Log::add_filter(Factor::LOG, filter);
+ Log::remove_filter(Factor::LOG, "default");
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest
new file mode 100644
index 0000000000..dbedb8e689
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest
@@ -0,0 +1,54 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_logging_factorial_04.bro
+
+module Factor;
+
+export {
+ redef enum Log::ID += { LOG };
+
+ type Info: record {
+ num: count &log;
+ factorial_num: count &log;
+ };
+
+ global log_factor: event(rec: Info);
+ }
+
+function factorial(n: count): count
+ {
+ if ( n == 0 )
+ return 1;
+
+ else
+ return (n * factorial(n - 1));
+ }
+
+event bro_init()
+ {
+ Log::create_stream(LOG, [$columns=Info, $ev=log_factor]);
+ }
+
+event bro_done()
+ {
+ local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ for ( n in numbers )
+ Log::write( Factor::LOG, [$num=numbers[n],
+ $factorial_num=factorial(numbers[n])]);
+ }
+
+function mod5(id: Log::ID, path: string, rec: Factor::Info) : string
+ {
+ if ( rec$factorial_num % 5 == 0 )
+ return "factor-mod5";
+
+ else
+ return "factor-non5";
+ }
+
+event bro_init()
+ {
+ local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
+ Log::add_filter(Factor::LOG, filter);
+ Log::remove_filter(Factor::LOG, "default");
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest
new file mode 100644
index 0000000000..70f8c70247
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_hook_01.bro
+
+@load policy/protocols/ssh/interesting-hostnames.bro
+
+hook Notice::policy(n: Notice::Info)
+ {
+ if ( n$note == SSH::Interesting_Hostname_Login )
+ add n$actions[Notice::ACTION_EMAIL];
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest
new file mode 100644
index 0000000000..522bef5930
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_hook_suppression_01.bro
+
+@load policy/protocols/ssl/expiring-certs.bro
+
+hook Notice::policy(n: Notice::Info)
+ {
+ if ( n$note == SSL::Certificate_Expires_Soon )
+ n$suppress_for = 12hrs;
+ }
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest
new file mode 100644
index 0000000000..95eed5f501
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest
@@ -0,0 +1,12 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_shortcuts_01.bro
+
+@load policy/protocols/ssh/interesting-hostnames.bro
+@load base/protocols/ssh/
+
+redef Notice::emailed_types += {
+ SSH::Interesting_Hostname_Login,
+ SSH::Login
+};
+
diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest
new file mode 100644
index 0000000000..8c12558d42
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest
@@ -0,0 +1,11 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- framework_notice_shortcuts_02.bro
+
+@load policy/protocols/ssh/interesting-hostnames.bro
+@load base/protocols/ssh/
+
+redef Notice::type_suppression_intervals += {
+ [SSH::Interesting_Hostname_Login] = 1day,
+ [SSH::Login] = 12hrs,
+};
diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest
new file mode 100644
index 0000000000..088d5d2368
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest
@@ -0,0 +1,25 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- event.bif.bro
+
+## script-level cleanup that needs to be performed for every connection. This
+## event is generated not only for TCP sessions but also for UDP and ICMP
+## flows.
+##
+##
+global connection_external: event(c: connection , tag: string );
+
+
+## Generated when a UDP session for a supported protocol has finished. Some of
+## Bro's application-layer UDP analyzers flag the end of a session by raising
+## Generated when a connection is seen that is marked as being expected.
+
+
+global ipv6_ext_headers: event(c: connection , p: pkt_hdr );
+## their specifics differ slightly. Often, however, both will be raised for
+## the same connection if some of its data is missing. We should eventually
+## merge the two.
+global ack_above_hole: event(c: connection );
+
+
+##
diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest
new file mode 100644
index 0000000000..c8e7eaab20
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest
@@ -0,0 +1,30 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- Bro_DNS.events.bif.bro
+
+## Generated for DNS requests. For requests with multiple queries, this event
+## is raised once for each.
+##
+## See `Wikipedia `__ for more
+## information about the DNS protocol. Bro analyzes both UDP and TCP DNS
+## sessions.
+##
+## c: The connection, which may be UDP or TCP depending on the type of the
+## transport-layer session being analyzed.
+##
+## msg: The parsed DNS message header.
+##
+## query: The queried name.
+##
+## qtype: The queried resource record type.
+##
+## qclass: The queried resource record class.
+##
+## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
+## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
+## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
+## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
+## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
+## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
+## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
+global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count );
diff --git a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest
new file mode 100644
index 0000000000..7d23c68ae4
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest
@@ -0,0 +1,7 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- init-bare.bro
+
+type string_array: table[count] of string;
+type string_set: set[string];
+type addr_set: set[addr];
diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest
new file mode 100644
index 0000000000..dc18745d57
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest
@@ -0,0 +1,28 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- main.bro
+
+module Conn;
+
+export {
+ ## The record type which contains column fields of the connection log.
+ type Info: record {
+ ts: time &log;
+ uid: string &log;
+ id: conn_id &log;
+ proto: transport_proto &log;
+ service: string &log &optional;
+ duration: interval &log &optional;
+ orig_bytes: count &log &optional;
+ resp_bytes: count &log &optional;
+ conn_state: string &log &optional;
+ local_orig: bool &log &optional;
+ missed_bytes: count &log &default=0;
+ history: string &log &optional;
+ orig_pkts: count &log &optional;
+ orig_ip_bytes: count &log &optional;
+ resp_pkts: count &log &optional;
+ resp_ip_bytes: count &log &optional;
+ tunnel_parents: set[string] &log;
+ };
+}
diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest
new file mode 100644
index 0000000000..abe74112bd
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest
@@ -0,0 +1,10 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- main.bro
+
+module HTTP;
+
+export {
+ ## This setting changes if passwords used in Basic-Auth are captured or not.
+ const default_capture_password = F &redef;
+}
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest
new file mode 100644
index 0000000000..b73140fe8e
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest
@@ -0,0 +1,61 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+##! Detect file downloads that have hash values matching files in Team
+##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
+
+@load base/frameworks/files
+@load base/frameworks/notice
+@load frameworks/files/hash-all-files
+
+module TeamCymruMalwareHashRegistry;
+
+export {
+ redef enum Notice::Type += {
+ ## The hash value of a file transferred over HTTP matched in the
+ ## malware hash registry.
+ Match
+ };
+
+ ## File types to attempt matching against the Malware Hash Registry.
+ const match_file_types = /application\/x-dosexec/ |
+ /application\/vnd.ms-cab-compressed/ |
+ /application\/pdf/ |
+ /application\/x-shockwave-flash/ |
+ /application\/x-java-applet/ |
+ /application\/jar/ |
+ /video\/mp4/ &redef;
+
+ ## The malware hash registry runs each malware sample through several A/V engines.
+ ## Team Cymru returns a percentage to indicate how many A/V engines flagged the
+ ## sample as malicious. This threshold allows you to require a minimum detection
+ ## rate.
+ const notice_threshold = 10 &redef;
+}
+
+event file_hash(f: fa_file, kind: string, hash: string)
+ {
+ if ( kind=="sha1" && match_file_types in f$mime_type )
+ {
+ local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
+ when ( local MHR_result = lookup_hostname_txt(hash_domain) )
+ {
+ # Data is returned as " "
+ local MHR_answer = split1(MHR_result, / /);
+ if ( |MHR_answer| == 2 )
+ {
+ local mhr_first_detected = double_to_time(to_double(MHR_answer[1]));
+ local mhr_detect_rate = to_count(MHR_answer[2]);
+
+ local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected);
+ if ( mhr_detect_rate >= notice_threshold )
+ {
+ local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected);
+ local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash);
+ NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]);
+ }
+ }
+ }
+ }
+ }
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest
new file mode 100644
index 0000000000..51044b36d9
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+
+module TeamCymruMalwareHashRegistry;
+
+export {
+ redef enum Notice::Type += {
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest
new file mode 100644
index 0000000000..37de8b6ff7
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest
@@ -0,0 +1,17 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+ ## The hash value of a file transferred over HTTP matched in the
+ ## malware hash registry.
+ Match
+ };
+
+ ## File types to attempt matching against the Malware Hash Registry.
+ const match_file_types = /application\/x-dosexec/ |
+ /application\/vnd.ms-cab-compressed/ |
+ /application\/pdf/ |
+ /application\/x-shockwave-flash/ |
+ /application\/x-java-applet/ |
+ /application\/jar/ |
+ /video\/mp4/ &redef;
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest
new file mode 100644
index 0000000000..19e9d2ee54
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest
@@ -0,0 +1,23 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- detect-MHR.bro
+
+ ## The malware hash registry runs each malware sample through several A/V engines.
+ ## Team Cymru returns a percentage to indicate how many A/V engines flagged the
+ ## sample as malicious. This threshold allows you to require a minimum detection
+ ## rate.
+ const notice_threshold = 10 &redef;
+}
+
+event file_hash(f: fa_file, kind: string, hash: string)
+ {
+ if ( kind=="sha1" && match_file_types in f$mime_type )
+ {
+ local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
+ when ( local MHR_result = lookup_hostname_txt(hash_domain) )
+ {
+ # Data is returned as " "
+ local MHR_answer = split1(MHR_result, / /);
+ if ( |MHR_answer| == 2 )
+ {
+ local mhr_first_detected = double_to_time(to_double(MHR_answer[1]));
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest
new file mode 100644
index 0000000000..9b0c50c3f4
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest
@@ -0,0 +1,9 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- known-hosts.bro
+
+module Known;
+
+export {
+ global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
+}
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest
new file mode 100644
index 0000000000..73eec1a1b9
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest
@@ -0,0 +1,50 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- interesting-hostnames.bro
+
+##! This script will generate a notice if an apparent SSH login originates
+##! or heads to a host with a reverse hostname that looks suspicious. By
+##! default, the regular expression to match "interesting" hostnames includes
+##! names that are typically used for infrastructure hosts like nameservers,
+##! mail servers, web servers and ftp servers.
+
+@load base/frameworks/notice
+
+module SSH;
+
+export {
+ redef enum Notice::Type += {
+ ## Generated if a login originates or responds with a host where the
+ ## reverse hostname lookup resolves to a name matched by the
+ ## :bro:id:`SSH::interesting_hostnames` regular expression.
+ Interesting_Hostname_Login,
+ };
+
+ ## Strange/bad host names to see successful SSH logins from or to.
+ const interesting_hostnames =
+ /^d?ns[0-9]*\./ |
+ /^smtp[0-9]*\./ |
+ /^mail[0-9]*\./ |
+ /^pop[0-9]*\./ |
+ /^imap[0-9]*\./ |
+ /^www[0-9]*\./ |
+ /^ftp[0-9]*\./ &redef;
+}
+
+event SSH::heuristic_successful_login(c: connection)
+ {
+ for ( host in set(c$id$orig_h, c$id$resp_h) )
+ {
+ when ( local hostname = lookup_addr(host) )
+ {
+ if ( interesting_hostnames in hostname )
+ {
+ NOTICE([$note=Interesting_Hostname_Login,
+ $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.",
+ Site::is_local_addr(host) ? "local" : "remote",
+ host == c$id$orig_h ? "client" : "server"),
+ $sub=hostname, $conn=c]);
+ }
+ }
+ }
+ }
diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest
new file mode 100644
index 0000000000..16e2552545
--- /dev/null
+++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest
@@ -0,0 +1,8 @@
+# @TEST-EXEC: btest-diff %INPUT
+
+-- expiring-certs.bro
+
+ NOTICE([$note=Certificate_Expires_Soon,
+ $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after),
+ $conn=c, $suppress_for=1day,
+ $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]);
diff --git a/testing/btest/doc/sphinx/using_bro.btest b/testing/btest/doc/sphinx/using_bro.btest
index 3551104043..233f415942 100644
--- a/testing/btest/doc/sphinx/using_bro.btest
+++ b/testing/btest/doc/sphinx/using_bro.btest
@@ -1 +1,2 @@
-@TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log"
+@TEST-EXEC: btest-rst-cmd bro -r $TRACES/wikipedia.trace
+@TEST-EXEC: btest-rst-include -n 15 conn.log
diff --git a/testing/scripts/rst-filter b/testing/scripts/rst-filter
index b06d5efd5e..a62646508e 100755
--- a/testing/scripts/rst-filter
+++ b/testing/scripts/rst-filter
@@ -2,4 +2,5 @@
#
# Filters the output of btest-rst-cmd.
-sed "s#${TRACES}/\{0,1\}##g"
+sed "s#${TRACES}/\{0,1\}##g" | \
+sed 's#/[^ ]*/doc/\([^/]*/\)*##g'