Merge remote-tracking branch 'origin/master' into topic/bernhard/input-logging-commmon-functions

Conflicts:
	src/input/readers/Ascii.cc
This commit is contained in:
Bernhard Amann 2013-01-11 09:48:53 -08:00
commit 1b0bb5063a
66 changed files with 2367 additions and 564 deletions

84
CHANGES
View file

@ -1,4 +1,88 @@
2.1-271 | 2013-01-08 10:18:57 -0800
* Change substring index notation to use a colon. String slice
notation is now written as `s[1:2]`. Addresses #422. (Jon Siwek)
2.1-268 | 2013-01-07 09:43:44 -0800
* Fix memory leak in OpaqueType::DoUnserialize. (Jon Siwek)
2.1-265 | 2012-12-20 17:38:42 -0800
* Add array-style index accessor for strings. Addresses #422. (Jon
Siwek)
The index expression can take up to two indices for the start and
end index of the substring to return (e.g. "mystring[1,3]").
Negative indices are allowed, with -1 representing the last
character in the string. The indexing is not cyclic -- if the
starting index is >= the length of the string an empty string is
returned, and if the ending index is >= the length of the string
then it's interpreted as the last index of the string. Assigning
to substrings accessed like this isn't allowed.
2.1-263 | 2012-12-20 16:22:09 -0800
* Bro's language now has a new set of types "opaque of X". (Matthias
Vallentin)
Opaque values can be passed around like other values but they can
only be manipulated with BiF functions, not with other operators.
Currently, the following opaque types are supported:
- opaque of md5
- opaque of sha1
- opaque of sha256
- opaquey of entropy.
They go along with the corrsponding BiF functions md5_*, sha1_*,
sha256_*, and entropy_*, respectively. Note that these functions
have changed their signatures to work with opaques types rather
than global state as it was before.
2.1-240 | 2012-12-20 15:21:07 -0800
* Improve error for invalid use of types as values. Addresses #923.
(Jon Siwek)
2.1-238 | 2012-12-20 15:11:25 -0800
* Finish implementation of script-layer switch statement. Addresses
#754. (Jon Siwek)
They behave like C-style switches except case labels can be
comprised of multiple literal constants delimited by commas. Only
atomic types are allowed for now. Case label bodies that don't
execute a "return" or "break" statement will fall through to
subsequent cases. A default case label is allowed.
* Fix a case where c$resp$size is misrepresented. Addresses #730.
(Jon Siwek)
2.1-234 | 2012-12-20 12:12:19 -0800
* Fix return value of hook calls that have no handlers. For this
case, the return value is always true. (Jon Siwek)
* Fix to_port() BIF for port strings with a port number of zero.
(Jon Siwek)
2.1-231 | 2012-12-14 14:51:35 -0800
* Make const variables actually constant. Both local and global
variables declared with "const" could be modified, but now
expressions that would modify them generate an error message at
parse-time. Addresses #922. (Jon Siwek)
2.1-229 | 2012-12-14 14:46:12 -0800
* Fix memory leak in ASCII reader when encoutering errors in input.
(Bernhard Amann)
* Improvements for the "bad checksums" detector to make it detect
bad TCP checksums. (Seth Hall)
2.1-223 | 2012-12-12 14:25:15 -0800 2.1-223 | 2012-12-12 14:25:15 -0800
* Trick for parallelizing input framework unit tests. Instead of * Trick for parallelizing input framework unit tests. Instead of

30
NEWS
View file

@ -24,6 +24,33 @@ New Functionality
- The ASCII writer can now output CSV files on a per filter basis. - The ASCII writer can now output CSV files on a per filter basis.
- Bro's language now has a working "switch" statement that generally
behaves like C-style switches except case labels can be comprised of
multiple literal constants delimited by commas. Only atomic types
are allowed for now. Case label bodies that don't execute a
"return" or "break" statement will fall through to subsequent cases.
A default case label is allowed.
- Bro's language now has a new set of types "opaque of X". Opaque
values can be passed around like other values but they can only be
manipulated with BiF functions, not with other operators. Currently,
the following opaque types are supported:
- opaque of md5
- opaque of sha1
- opaque of sha256
- opaquey of entropy.
They go along with the corrsponding BiF functions md5_*, sha1_*,
sha256_*, and entropy_*, respectively. Note that these functions
have changed their signatures to work with opaques types rather
than global state as it was before.
- Strings now support the subscript operator to extract individual
characters and substrings (e.g., s[4], s[1,5]). The index expression
can take up to two indices for the start and end index of the
substring to return (e.g. "mystring[1,3]").
Changed Functionality Changed Functionality
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -37,6 +64,9 @@ Changed Functionality
make_connection_persistent(), generate_idmef(), make_connection_persistent(), generate_idmef(),
split_complete() split_complete()
- md5_*, sha1_*, sha256_*, and entropy_* have all changed
their signatures to work with opaque types (see above).
- Removed a now unused argument from "do_split" helper function. - Removed a now unused argument from "do_split" helper function.
- "this" is no longer a reserved keyword. - "this" is no longer a reserved keyword.

View file

@ -1 +1 @@
2.1-223 2.1-271

@ -1 +1 @@
Subproject commit 06682dbb15d26d2688bdc9ad76efec17d38dc80f Subproject commit 073404dd29dc6e90ff0e4eb8bc836f8adbf3931e

@ -1 +1 @@
Subproject commit f4d6a2af15404dc1349d12d2ad21a3eebcb2ff1e Subproject commit 2bf6b37177b895329173acac2bb98f38a8783bc1

@ -1 +1 @@
Subproject commit d83e10c5f76cbfdf81c843575351fbc7b544fc93 Subproject commit 3585dc9a7afe20d70cb77fc2472cc6bce3850b67

View file

@ -21,12 +21,10 @@ redef Cluster::manager2worker_events += /Notice::begin_suppression/;
redef Cluster::worker2manager_events += /Notice::cluster_notice/; redef Cluster::worker2manager_events += /Notice::cluster_notice/;
@if ( Cluster::local_node_type() != Cluster::MANAGER ) @if ( Cluster::local_node_type() != Cluster::MANAGER )
# The notice policy is completely handled by the manager and shouldn't be # The notice policy is completely handled by the manager and shouldn't be
# done by workers or proxies to save time for packet processing. # done by workers or proxies to save time for packet processing.
event bro_init() &priority=11 redef Notice::policy = table();
{
Notice::policy = table();
}
event Notice::begin_suppression(n: Notice::Info) event Notice::begin_suppression(n: Notice::Info)
{ {

View file

@ -14,7 +14,8 @@ export {
} }
# Keep track of how many bad checksums have been seen. # Keep track of how many bad checksums have been seen.
global bad_checksums = 0; global bad_ip_checksums = 0;
global bad_tcp_checksums = 0;
# Track to see if this script is done so that messages aren't created multiple times. # Track to see if this script is done so that messages aren't created multiple times.
global done = F; global done = F;
@ -25,10 +26,19 @@ event ChecksumOffloading::check()
return; return;
local pkts_recvd = net_stats()$pkts_recvd; local pkts_recvd = net_stats()$pkts_recvd;
if ( (bad_checksums*1.0 / net_stats()$pkts_recvd*1.0) > 0.05 ) local bad_ip_checksum_pct = (pkts_recvd != 0) ? (bad_ip_checksums*1.0 / pkts_recvd*1.0) : 0;
local bad_tcp_checksum_pct = (pkts_recvd != 0) ? (bad_tcp_checksums*1.0 / pkts_recvd*1.0) : 0;
if ( bad_ip_checksum_pct > 0.05 || bad_tcp_checksum_pct > 0.05 )
{ {
local packet_src = reading_traces() ? "trace file likely has" : "interface is likely receiving"; local packet_src = reading_traces() ? "trace file likely has" : "interface is likely receiving";
local message = fmt("Your %s invalid IP checksums, most likely from NIC checksum offloading.", packet_src); local bad_checksum_msg = (bad_ip_checksum_pct > 0.0) ? "IP" : "";
if ( bad_tcp_checksum_pct > 0.0 )
{
if ( |bad_checksum_msg| > 0 )
bad_checksum_msg += " and ";
bad_checksum_msg += "TCP";
}
local message = fmt("Your %s invalid %s checksums, most likely from NIC checksum offloading.", packet_src, bad_checksum_msg);
Reporter::warning(message); Reporter::warning(message);
done = T; done = T;
} }
@ -48,7 +58,13 @@ event bro_init()
event net_weird(name: string) event net_weird(name: string)
{ {
if ( name == "bad_IP_checksum" ) if ( name == "bad_IP_checksum" )
++bad_checksums; ++bad_ip_checksums;
}
event conn_weird(name: string, c: connection, addl: string)
{
if ( name == "bad_TCP_checksum" )
++bad_tcp_checksums;
} }
event bro_done() event bro_done()

View file

@ -13,16 +13,16 @@ export {
redef record Info += { redef record Info += {
## MD5 sum for a file transferred over HTTP calculated from the ## MD5 sum for a file transferred over HTTP calculated from the
## response body. ## response body.
md5: string &log &optional; md5: string &log &optional;
## This value can be set per-transfer to determine per request ## This value can be set per-transfer to determine per request
## if a file should have an MD5 sum generated. It must be ## if a file should have an MD5 sum generated. It must be
## set to T at the time of or before the first chunk of body data. ## set to T at the time of or before the first chunk of body data.
calc_md5: bool &default=F; calc_md5: bool &default=F;
## Indicates if an MD5 sum is being calculated for the current ## Indicates if an MD5 sum is being calculated for the current
## request/response pair. ## request/response pair.
calculating_md5: bool &default=F; md5_handle: opaque of md5 &optional;
}; };
## Generate MD5 sums for these filetypes. ## Generate MD5 sums for these filetypes.
@ -41,13 +41,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
if ( c$http$calc_md5 || if ( c$http$calc_md5 ||
(c$http?$mime_type && generate_md5 in c$http$mime_type) ) (c$http?$mime_type && generate_md5 in c$http$mime_type) )
{ {
c$http$calculating_md5 = T; c$http$md5_handle = md5_hash_init();
md5_hash_init(c$id);
} }
} }
if ( c$http$calculating_md5 ) if ( c$http?$md5_handle )
md5_hash_update(c$id, data); md5_hash_update(c$http$md5_handle, data);
} }
## In the event of a content gap during a file transfer, detect the state for ## In the event of a content gap during a file transfer, detect the state for
@ -55,11 +54,11 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
## incorrect anyway. ## incorrect anyway.
event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5 event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5
{ {
if ( is_orig || ! c?$http || ! c$http$calculating_md5 ) return; if ( is_orig || ! c?$http || ! c$http?$md5_handle ) return;
set_state(c, F, is_orig); set_state(c, F, is_orig);
c$http$calculating_md5 = F; md5_hash_finish(c$http$md5_handle); # Ignore return value.
md5_hash_finish(c$id); delete c$http$md5_handle;
} }
## When the file finishes downloading, finish the hash and generate a notice. ## When the file finishes downloading, finish the hash and generate a notice.
@ -67,11 +66,11 @@ event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &
{ {
if ( is_orig || ! c?$http ) return; if ( is_orig || ! c?$http ) return;
if ( c$http$calculating_md5 ) if ( c$http?$md5_handle )
{ {
local url = build_url_http(c$http); local url = build_url_http(c$http);
c$http$calculating_md5 = F; c$http$md5 = md5_hash_finish(c$http$md5_handle);
c$http$md5 = md5_hash_finish(c$id); delete c$http$md5_handle;
NOTICE([$note=MD5, $msg=fmt("%s %s %s", c$id$orig_h, c$http$md5, url), NOTICE([$note=MD5, $msg=fmt("%s %s %s", c$id$orig_h, c$http$md5, url),
$sub=c$http$md5, $conn=c, $URL=url]); $sub=c$http$md5, $conn=c, $URL=url]);
@ -82,11 +81,12 @@ event connection_state_remove(c: connection) &priority=-5
{ {
if ( c?$http_state && if ( c?$http_state &&
c$http_state$current_response in c$http_state$pending && c$http_state$current_response in c$http_state$pending &&
c$http_state$pending[c$http_state$current_response]$calculating_md5 ) c$http_state$pending[c$http_state$current_response]?$md5_handle )
{ {
# The MD5 sum isn't going to be saved anywhere since the entire # The MD5 sum isn't going to be saved anywhere since the entire
# body wouldn't have been seen anyway and we'd just be giving an # body wouldn't have been seen anyway and we'd just be giving an
# incorrect MD5 sum. # incorrect MD5 sum.
md5_hash_finish(c$id); md5_hash_finish(c$http$md5_handle);
delete c$http$md5_handle;
} }
} }

View file

@ -16,33 +16,33 @@ export {
type EntityInfo: record { type EntityInfo: record {
## This is the timestamp of when the MIME content transfer began. ## This is the timestamp of when the MIME content transfer began.
ts: time &log; ts: time &log;
uid: string &log; uid: string &log;
id: conn_id &log; id: conn_id &log;
## A count to represent the depth of this message transaction in a ## A count to represent the depth of this message transaction in a
## single connection where multiple messages were transferred. ## single connection where multiple messages were transferred.
trans_depth: count &log; trans_depth: count &log;
## The filename seen in the Content-Disposition header. ## The filename seen in the Content-Disposition header.
filename: string &log &optional; filename: string &log &optional;
## Track how many bytes of the MIME encoded file have been seen. ## Track how many bytes of the MIME encoded file have been seen.
content_len: count &log &default=0; content_len: count &log &default=0;
## The mime type of the entity discovered through magic bytes identification. ## The mime type of the entity discovered through magic bytes identification.
mime_type: string &log &optional; mime_type: string &log &optional;
## The calculated MD5 sum for the MIME entity. ## The calculated MD5 sum for the MIME entity.
md5: string &log &optional; md5: string &log &optional;
## Optionally calculate the file's MD5 sum. Must be set prior to the ## Optionally calculate the file's MD5 sum. Must be set prior to the
## first data chunk being see in an event. ## first data chunk being see in an event.
calc_md5: bool &default=F; calc_md5: bool &default=F;
## This boolean value indicates if an MD5 sum is being calculated ## This boolean value indicates if an MD5 sum is being calculated
## for the current file transfer. ## for the current file transfer.
calculating_md5: bool &default=F; md5_handle: opaque of md5 &optional;
## Optionally write the file to disk. Must be set prior to first ## Optionally write the file to disk. Must be set prior to first
## data chunk being seen in an event. ## data chunk being seen in an event.
extract_file: bool &default=F; extract_file: bool &default=F;
## Store the file handle here for the file currently being extracted. ## Store the file handle here for the file currently being extracted.
extraction_file: file &log &optional; extraction_file: file &log &optional;
}; };
redef record Info += { redef record Info += {
@ -126,18 +126,16 @@ event mime_segment_data(c: connection, length: count, data: string) &priority=-5
if ( c$smtp$current_entity$content_len == 0 ) if ( c$smtp$current_entity$content_len == 0 )
{ {
if ( generate_md5 in c$smtp$current_entity$mime_type && ! never_calc_md5 ) local entity = c$smtp$current_entity;
c$smtp$current_entity$calc_md5 = T; if ( generate_md5 in entity$mime_type && ! never_calc_md5 )
entity$calc_md5 = T;
if ( c$smtp$current_entity$calc_md5 ) if ( entity$calc_md5 )
{ entity$md5_handle = md5_hash_init();
c$smtp$current_entity$calculating_md5 = T;
md5_hash_init(c$id);
}
} }
if ( c$smtp$current_entity$calculating_md5 ) if ( c$smtp$current_entity?$md5_handle )
md5_hash_update(c$id, data); md5_hash_update(entity$md5_handle, data);
} }
## In the event of a content gap during the MIME transfer, detect the state for ## In the event of a content gap during the MIME transfer, detect the state for
@ -147,10 +145,11 @@ event content_gap(c: connection, is_orig: bool, seq: count, length: count) &prio
{ {
if ( is_orig || ! c?$smtp || ! c$smtp?$current_entity ) return; if ( is_orig || ! c?$smtp || ! c$smtp?$current_entity ) return;
if ( c$smtp$current_entity$calculating_md5 ) local entity = c$smtp$current_entity;
if ( entity?$md5_handle )
{ {
c$smtp$current_entity$calculating_md5 = F; md5_hash_finish(entity$md5_handle);
md5_hash_finish(c$id); delete entity$md5_handle;
} }
} }
@ -161,12 +160,14 @@ event mime_end_entity(c: connection) &priority=-3
if ( ! c?$smtp || ! c$smtp?$current_entity ) if ( ! c?$smtp || ! c$smtp?$current_entity )
return; return;
if ( c$smtp$current_entity$calculating_md5 ) local entity = c$smtp$current_entity;
if ( entity?$md5_handle )
{ {
c$smtp$current_entity$md5 = md5_hash_finish(c$id); entity$md5 = md5_hash_finish(entity$md5_handle);
delete entity$md5_handle;
NOTICE([$note=MD5, $msg=fmt("Calculated a hash for a MIME entity from %s", c$id$orig_h), NOTICE([$note=MD5, $msg=fmt("Calculated a hash for a MIME entity from %s", c$id$orig_h),
$sub=c$smtp$current_entity$md5, $conn=c]); $sub=entity$md5, $conn=c]);
} }
} }
@ -177,6 +178,10 @@ event mime_one_header(c: connection, h: mime_header_rec)
if ( h$name == "CONTENT-DISPOSITION" && if ( h$name == "CONTENT-DISPOSITION" &&
/[fF][iI][lL][eE][nN][aA][mM][eE]/ in h$value ) /[fF][iI][lL][eE][nN][aA][mM][eE]/ in h$value )
c$smtp$current_entity$filename = extract_filename_from_content_disposition(h$value); c$smtp$current_entity$filename = extract_filename_from_content_disposition(h$value);
if ( h$name == "CONTENT-TYPE" &&
/[nN][aA][mM][eE][:blank:]*=/ in h$value )
c$smtp$current_entity$filename = extract_filename_from_content_disposition(h$value);
} }
event mime_end_entity(c: connection) &priority=-5 event mime_end_entity(c: connection) &priority=-5

View file

@ -19,7 +19,7 @@ function generate_extraction_filename(prefix: string, c: connection, suffix: str
## the filename. ## the filename.
function extract_filename_from_content_disposition(data: string): string function extract_filename_from_content_disposition(data: string): string
{ {
local filename = sub(data, /^.*[fF][iI][lL][eE][nN][aA][mM][eE][[:blank:]]*=[[:blank:]]*/, ""); local filename = sub(data, /^.*[nN][aA][mM][eE][[:blank:]]*=[[:blank:]]*/, "");
# Remove quotes around the filename if they are there. # Remove quotes around the filename if they are there.
if ( /^\"/ in filename ) if ( /^\"/ in filename )
filename = split_n(filename, /\"/, F, 2)[2]; filename = split_n(filename, /\"/, F, 2)[2];

View file

@ -28,7 +28,7 @@ event signature_match(state: signature_state, msg: string, data: string) &priori
if ( /^webapp-/ !in state$sig_id ) return; if ( /^webapp-/ !in state$sig_id ) return;
local c = state$conn; local c = state$conn;
local si = Software::Info; local si: Software::Info;
si = [$name=msg, $unparsed_version=msg, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=WEB_APPLICATION]; si = [$name=msg, $unparsed_version=msg, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=WEB_APPLICATION];
si$url = build_url_http(c$http); si$url = build_url_http(c$http);
if ( c$id$resp_h in Software::tracked && if ( c$id$resp_h in Software::tracked &&

View file

@ -361,6 +361,7 @@ set(bro_SRCS
NetVar.cc NetVar.cc
NetbiosSSN.cc NetbiosSSN.cc
Obj.cc Obj.cc
OpaqueVal.cc
OSFinger.cc OSFinger.cc
PacketFilter.cc PacketFilter.cc
PacketSort.cc PacketSort.cc

View file

@ -229,10 +229,15 @@ bool Expr::DoUnserialize(UnserialInfo* info)
} }
NameExpr::NameExpr(ID* arg_id) : Expr(EXPR_NAME) NameExpr::NameExpr(ID* arg_id, bool const_init) : Expr(EXPR_NAME)
{ {
id = arg_id; id = arg_id;
SetType(id->Type()->Ref()); in_const_init = const_init;
if ( id->AsType() )
SetType(new TypeType(id->AsType()));
else
SetType(id->Type()->Ref());
EventHandler* h = event_registry->Lookup(id->Name()); EventHandler* h = event_registry->Lookup(id->Name());
if ( h ) if ( h )
@ -287,6 +292,9 @@ Expr* NameExpr::MakeLvalue()
if ( id->AsType() ) if ( id->AsType() )
ExprError("Type name is not an lvalue"); ExprError("Type name is not an lvalue");
if ( id->IsConst() && ! in_const_init )
ExprError("const is not a modifiable lvalue");
return new RefExpr(this); return new RefExpr(this);
} }
@ -337,9 +345,11 @@ bool NameExpr::DoSerialize(SerialInfo* info) const
// Write out just the name of the function if requested. // Write out just the name of the function if requested.
if ( info->globals_as_names && id->IsGlobal() ) if ( info->globals_as_names && id->IsGlobal() )
return SERIALIZE('n') && SERIALIZE(id->Name()); return SERIALIZE('n') && SERIALIZE(id->Name()) &&
SERIALIZE(in_const_init);
else else
return SERIALIZE('f') && id->Serialize(info); return SERIALIZE('f') && id->Serialize(info) &&
SERIALIZE(in_const_init);
} }
bool NameExpr::DoUnserialize(UnserialInfo* info) bool NameExpr::DoUnserialize(UnserialInfo* info)
@ -370,6 +380,9 @@ bool NameExpr::DoUnserialize(UnserialInfo* info)
if ( ! id ) if ( ! id )
return false; return false;
if ( ! UNSERIALIZE(&in_const_init) )
return false;
return true; return true;
} }
@ -2788,22 +2801,43 @@ bool AssignExpr::DoUnserialize(UnserialInfo* info)
return UNSERIALIZE(&is_init); return UNSERIALIZE(&is_init);
} }
IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2) IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2, bool is_slice)
: BinaryExpr(EXPR_INDEX, arg_op1, arg_op2) : BinaryExpr(EXPR_INDEX, arg_op1, arg_op2)
{ {
if ( IsError() ) if ( IsError() )
return; return;
if ( is_slice )
{
if ( ! IsString(op1->Type()->Tag()) )
ExprError("slice notation indexing only supported for strings currently");
}
else if ( IsString(op1->Type()->Tag()) )
{
if ( arg_op2->Exprs().length() != 1 )
ExprError("invalid string index expression");
}
if ( IsError() )
return;
int match_type = op1->Type()->MatchesIndex(arg_op2); int match_type = op1->Type()->MatchesIndex(arg_op2);
if ( match_type == DOES_NOT_MATCH_INDEX ) if ( match_type == DOES_NOT_MATCH_INDEX )
SetError("not an index type"); SetError("not an index type");
else if ( ! op1->Type()->YieldType() ) else if ( ! op1->Type()->YieldType() )
{
if ( IsString(op1->Type()->Tag()) &&
match_type == MATCHES_INDEX_SCALAR )
SetType(base_type(TYPE_STRING));
else
// It's a set - so indexing it yields void. We don't // It's a set - so indexing it yields void. We don't
// directly generate an error message, though, since this // directly generate an error message, though, since this
// expression might be part of an add/delete statement, // expression might be part of an add/delete statement,
// rather than yielding a value. // rather than yielding a value.
SetType(base_type(TYPE_VOID)); SetType(base_type(TYPE_VOID));
}
else if ( match_type == MATCHES_INDEX_SCALAR ) else if ( match_type == MATCHES_INDEX_SCALAR )
SetType(op1->Type()->YieldType()->Ref()); SetType(op1->Type()->YieldType()->Ref());
@ -2879,6 +2913,9 @@ void IndexExpr::Delete(Frame* f)
Expr* IndexExpr::MakeLvalue() Expr* IndexExpr::MakeLvalue()
{ {
if ( IsString(op1->Type()->Tag()) )
ExprError("cannot assign to string index expression");
return new RefExpr(this); return new RefExpr(this);
} }
@ -2952,10 +2989,37 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const
Val* v = 0; Val* v = 0;
if ( v1->Type()->Tag() == TYPE_VECTOR ) switch ( v1->Type()->Tag() ) {
case TYPE_VECTOR:
v = v1->AsVectorVal()->Lookup(v2); v = v1->AsVectorVal()->Lookup(v2);
else break;
case TYPE_TABLE:
v = v1->AsTableVal()->Lookup(v2); v = v1->AsTableVal()->Lookup(v2);
break;
case TYPE_STRING:
{
const ListVal* lv = v2->AsListVal();
const BroString* s = v1->AsString();
int len = s->Len();
bro_int_t first = lv->Index(0)->AsInt();
bro_int_t last = lv->Length() > 1 ? lv->Index(1)->AsInt() : first;
if ( first < 0 )
first += len;
if ( last < 0 )
last += len;
BroString* substring = s->GetSubstring(first, last - first + 1);
return new StringVal(substring ? substring : new BroString(""));
}
default:
Error("type cannot be indexed");
break;
}
if ( v ) if ( v )
return v->Ref(); return v->Ref();
@ -2982,14 +3046,25 @@ void IndexExpr::Assign(Frame* f, Val* v, Opcode op)
return; return;
} }
if ( v1->Type()->Tag() == TYPE_VECTOR ) switch ( v1->Type()->Tag() ) {
{ case TYPE_VECTOR:
if ( ! v1->AsVectorVal()->Assign(v2, v, this, op) ) if ( ! v1->AsVectorVal()->Assign(v2, v, this, op) )
Internal("assignment failed"); Internal("assignment failed");
} break;
else if ( ! v1->AsTableVal()->Assign(v2, v, op) ) case TYPE_TABLE:
Internal("assignment failed"); if ( ! v1->AsTableVal()->Assign(v2, v, op) )
Internal("assignment failed");
break;
case TYPE_STRING:
Internal("assignment via string index accessor not allowed");
break;
default:
Internal("bad index expression type in assignment");
break;
}
Unref(v1); Unref(v1);
Unref(v2); Unref(v2);

View file

@ -198,7 +198,7 @@ protected:
class NameExpr : public Expr { class NameExpr : public Expr {
public: public:
NameExpr(ID* id); NameExpr(ID* id, bool const_init = false);
~NameExpr(); ~NameExpr();
ID* Id() const { return id; } ID* Id() const { return id; }
@ -220,6 +220,7 @@ protected:
DECLARE_SERIAL(NameExpr); DECLARE_SERIAL(NameExpr);
ID* id; ID* id;
bool in_const_init;
}; };
class ConstExpr : public Expr { class ConstExpr : public Expr {
@ -645,7 +646,7 @@ protected:
class IndexExpr : public BinaryExpr { class IndexExpr : public BinaryExpr {
public: public:
IndexExpr(Expr* op1, ListExpr* op2); IndexExpr(Expr* op1, ListExpr* op2, bool is_slice = false);
int CanAdd() const; int CanAdd() const;
int CanDel() const; int CanDel() const;

View file

@ -282,13 +282,14 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const
#ifdef PROFILE_BRO_FUNCTIONS #ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Function: %s\n", id->Name()); DEBUG_MSG("Function: %s\n", id->Name());
#endif #endif
if ( ! bodies.size() ) if ( ! bodies.size() )
{ {
// Can only happen for events and hooks. // Can only happen for events and hooks.
assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK); assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK);
loop_over_list(*args, i) loop_over_list(*args, i)
Unref((*args)[i]); Unref((*args)[i]);
return 0 ;
return Flavor() == FUNC_FLAVOR_HOOK ? new Val(true, TYPE_BOOL) : 0;
} }
SegmentProfiler(segment_logger, location); SegmentProfiler(segment_logger, location);

501
src/OpaqueVal.cc Normal file
View file

@ -0,0 +1,501 @@
#include "OpaqueVal.h"
#include "Reporter.h"
#include "Serializer.h"
bool HashVal::IsValid() const
{
return valid;
}
bool HashVal::Init()
{
if ( valid )
return false;
valid = DoInit();
return valid;
}
StringVal* HashVal::Get()
{
if ( ! valid )
return new StringVal("");
StringVal* result = DoGet();
valid = false;
return result;
}
bool HashVal::Feed(const void* data, size_t size)
{
if ( valid )
return DoFeed(data, size);
reporter->InternalError("invalid opaque hash value");
return false;
}
bool HashVal::DoInit()
{
assert(! "missing implementation of DoInit()");
return false;
}
bool HashVal::DoFeed(const void*, size_t)
{
assert(! "missing implementation of DoFeed()");
return false;
}
StringVal* HashVal::DoGet()
{
assert(! "missing implementation of DoGet()");
return new StringVal("");
}
HashVal::HashVal(OpaqueType* t) : OpaqueVal(t)
{
valid = false;
}
IMPLEMENT_SERIAL(HashVal, SER_HASH_VAL);
bool HashVal::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_HASH_VAL, OpaqueVal);
return SERIALIZE(valid);
}
bool HashVal::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(OpaqueVal);
return UNSERIALIZE(&valid);
}
void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH])
{
MD5_CTX h;
md5_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
md5_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
md5_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
md5_final(&h, result);
}
void MD5Val::hmac(val_list& vlist,
u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH])
{
digest(vlist, result);
for ( int i = 0; i < MD5_DIGEST_LENGTH; ++i )
result[i] ^= key[i];
MD5(result, MD5_DIGEST_LENGTH, result);
}
bool MD5Val::DoInit()
{
assert(! IsValid());
md5_init(&ctx);
return true;
}
bool MD5Val::DoFeed(const void* data, size_t size)
{
if ( ! IsValid() )
return false;
md5_update(&ctx, data, size);
return true;
}
StringVal* MD5Val::DoGet()
{
if ( ! IsValid() )
return new StringVal("");
u_char digest[MD5_DIGEST_LENGTH];
md5_final(&ctx, digest);
return new StringVal(md5_digest_print(digest));
}
IMPLEMENT_SERIAL(MD5Val, SER_MD5_VAL);
bool MD5Val::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_MD5_VAL, HashVal);
if ( ! IsValid() )
return true;
if ( ! (SERIALIZE(ctx.A) &&
SERIALIZE(ctx.B) &&
SERIALIZE(ctx.C) &&
SERIALIZE(ctx.D) &&
SERIALIZE(ctx.Nl) &&
SERIALIZE(ctx.Nh)) )
return false;
for ( int i = 0; i < MD5_LBLOCK; ++i )
{
if ( ! SERIALIZE(ctx.data[i]) )
return false;
}
if ( ! SERIALIZE(ctx.num) )
return false;
return true;
}
bool MD5Val::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(HashVal);
if ( ! IsValid() )
return true;
if ( ! (UNSERIALIZE(&ctx.A) &&
UNSERIALIZE(&ctx.B) &&
UNSERIALIZE(&ctx.C) &&
UNSERIALIZE(&ctx.D) &&
UNSERIALIZE(&ctx.Nl) &&
UNSERIALIZE(&ctx.Nh)) )
return false;
for ( int i = 0; i < MD5_LBLOCK; ++i )
{
if ( ! UNSERIALIZE(&ctx.data[i]) )
return false;
}
if ( ! UNSERIALIZE(&ctx.num) )
return false;
return true;
}
void SHA1Val::digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH])
{
SHA_CTX h;
sha1_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha1_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha1_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha1_final(&h, result);
}
bool SHA1Val::DoInit()
{
assert(! IsValid());
sha1_init(&ctx);
return true;
}
bool SHA1Val::DoFeed(const void* data, size_t size)
{
if ( ! IsValid() )
return false;
sha1_update(&ctx, data, size);
return true;
}
StringVal* SHA1Val::DoGet()
{
if ( ! IsValid() )
return new StringVal("");
u_char digest[SHA_DIGEST_LENGTH];
sha1_final(&ctx, digest);
return new StringVal(sha1_digest_print(digest));
}
IMPLEMENT_SERIAL(SHA1Val, SER_SHA1_VAL);
bool SHA1Val::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_SHA1_VAL, HashVal);
if ( ! IsValid() )
return true;
if ( ! (SERIALIZE(ctx.h0) &&
SERIALIZE(ctx.h1) &&
SERIALIZE(ctx.h2) &&
SERIALIZE(ctx.h3) &&
SERIALIZE(ctx.h4) &&
SERIALIZE(ctx.Nl) &&
SERIALIZE(ctx.Nh)) )
return false;
for ( int i = 0; i < SHA_LBLOCK; ++i )
{
if ( ! SERIALIZE(ctx.data[i]) )
return false;
}
if ( ! SERIALIZE(ctx.num) )
return false;
return true;
}
bool SHA1Val::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(HashVal);
if ( ! IsValid() )
return true;
if ( ! (UNSERIALIZE(&ctx.h0) &&
UNSERIALIZE(&ctx.h1) &&
UNSERIALIZE(&ctx.h2) &&
UNSERIALIZE(&ctx.h3) &&
UNSERIALIZE(&ctx.h4) &&
UNSERIALIZE(&ctx.Nl) &&
UNSERIALIZE(&ctx.Nh)) )
return false;
for ( int i = 0; i < SHA_LBLOCK; ++i )
{
if ( ! UNSERIALIZE(&ctx.data[i]) )
return false;
}
if ( ! UNSERIALIZE(&ctx.num) )
return false;
return true;
}
void SHA256Val::digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH])
{
SHA256_CTX h;
sha256_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha256_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha256_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha256_final(&h, result);
}
bool SHA256Val::DoInit()
{
assert( ! IsValid() );
sha256_init(&ctx);
return true;
}
bool SHA256Val::DoFeed(const void* data, size_t size)
{
if ( ! IsValid() )
return false;
sha256_update(&ctx, data, size);
return true;
}
StringVal* SHA256Val::DoGet()
{
if ( ! IsValid() )
return new StringVal("");
u_char digest[SHA256_DIGEST_LENGTH];
sha256_final(&ctx, digest);
return new StringVal(sha256_digest_print(digest));
}
IMPLEMENT_SERIAL(SHA256Val, SER_SHA256_VAL);
bool SHA256Val::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_SHA256_VAL, HashVal);
if ( ! IsValid() )
return true;
for ( int i = 0; i < 8; ++i )
{
if ( ! SERIALIZE(ctx.h[i]) )
return false;
}
if ( ! (SERIALIZE(ctx.Nl) &&
SERIALIZE(ctx.Nh)) )
return false;
for ( int i = 0; i < SHA_LBLOCK; ++i )
{
if ( ! SERIALIZE(ctx.data[i]) )
return false;
}
if ( ! (SERIALIZE(ctx.num) &&
SERIALIZE(ctx.md_len)) )
return false;
return true;
}
bool SHA256Val::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(HashVal);
if ( ! IsValid() )
return true;
for ( int i = 0; i < 8; ++i )
{
if ( ! UNSERIALIZE(&ctx.h[i]) )
return false;
}
if ( ! (UNSERIALIZE(&ctx.Nl) &&
UNSERIALIZE(&ctx.Nh)) )
return false;
for ( int i = 0; i < SHA_LBLOCK; ++i )
{
if ( ! UNSERIALIZE(&ctx.data[i]) )
return false;
}
if ( ! (UNSERIALIZE(&ctx.num) &&
UNSERIALIZE(&ctx.md_len)) )
return false;
return true;
}
bool EntropyVal::Feed(const void* data, size_t size)
{
state.add(data, size);
return true;
}
bool EntropyVal::Get(double *r_ent, double *r_chisq, double *r_mean,
double *r_montepicalc, double *r_scc)
{
state.end(r_ent, r_chisq, r_mean, r_montepicalc, r_scc);
return true;
}
IMPLEMENT_SERIAL(EntropyVal, SER_ENTROPY_VAL);
bool EntropyVal::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_ENTROPY_VAL, OpaqueVal);
for ( int i = 0; i < 256; ++i )
{
if ( ! SERIALIZE(state.ccount[i]) )
return false;
}
if ( ! (SERIALIZE(state.totalc) &&
SERIALIZE(state.mp) &&
SERIALIZE(state.sccfirst)) )
return false;
for ( int i = 0; i < RT_MONTEN; ++i )
{
if ( ! SERIALIZE(state.monte[i]) )
return false;
}
if ( ! (SERIALIZE(state.inmont) &&
SERIALIZE(state.mcount) &&
SERIALIZE(state.cexp) &&
SERIALIZE(state.montex) &&
SERIALIZE(state.montey) &&
SERIALIZE(state.montepi) &&
SERIALIZE(state.sccu0) &&
SERIALIZE(state.scclast) &&
SERIALIZE(state.scct1) &&
SERIALIZE(state.scct2) &&
SERIALIZE(state.scct3)) )
return false;
return true;
}
bool EntropyVal::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(OpaqueVal);
for ( int i = 0; i < 256; ++i )
{
if ( ! UNSERIALIZE(&state.ccount[i]) )
return false;
}
if ( ! (UNSERIALIZE(&state.totalc) &&
UNSERIALIZE(&state.mp) &&
UNSERIALIZE(&state.sccfirst)) )
return false;
for ( int i = 0; i < RT_MONTEN; ++i )
{
if ( ! UNSERIALIZE(&state.monte[i]) )
return false;
}
if ( ! (UNSERIALIZE(&state.inmont) &&
UNSERIALIZE(&state.mcount) &&
UNSERIALIZE(&state.cexp) &&
UNSERIALIZE(&state.montex) &&
UNSERIALIZE(&state.montey) &&
UNSERIALIZE(&state.montepi) &&
UNSERIALIZE(&state.sccu0) &&
UNSERIALIZE(&state.scclast) &&
UNSERIALIZE(&state.scct1) &&
UNSERIALIZE(&state.scct2) &&
UNSERIALIZE(&state.scct3)) )
return false;
return true;
}

110
src/OpaqueVal.h Normal file
View file

@ -0,0 +1,110 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef OPAQUEVAL_H
#define OPAQUEVAL_H
#include "RandTest.h"
#include "Val.h"
#include "digest.h"
class HashVal : public OpaqueVal {
public:
virtual bool IsValid() const;
virtual bool Init();
virtual bool Feed(const void* data, size_t size);
virtual StringVal* Get();
protected:
HashVal() { };
HashVal(OpaqueType* t);
virtual bool DoInit();
virtual bool DoFeed(const void* data, size_t size);
virtual StringVal* DoGet();
DECLARE_SERIAL(HashVal);
private:
// This flag exists because Get() can only be called once.
bool valid;
};
class MD5Val : public HashVal {
public:
static void digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]);
static void hmac(val_list& vlist,
u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH]);
MD5Val() : HashVal(new OpaqueType("md5")) { }
protected:
friend class Val;
virtual bool DoInit() /* override */;
virtual bool DoFeed(const void* data, size_t size) /* override */;
virtual StringVal* DoGet() /* override */;
DECLARE_SERIAL(MD5Val);
private:
MD5_CTX ctx;
};
class SHA1Val : public HashVal {
public:
static void digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH]);
SHA1Val() : HashVal(new OpaqueType("sha1")) { }
protected:
friend class Val;
virtual bool DoInit() /* override */;
virtual bool DoFeed(const void* data, size_t size) /* override */;
virtual StringVal* DoGet() /* override */;
DECLARE_SERIAL(SHA1Val);
private:
SHA_CTX ctx;
};
class SHA256Val : public HashVal {
public:
static void digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH]);
SHA256Val() : HashVal(new OpaqueType("sha256")) { }
protected:
friend class Val;
virtual bool DoInit() /* override */;
virtual bool DoFeed(const void* data, size_t size) /* override */;
virtual StringVal* DoGet() /* override */;
DECLARE_SERIAL(SHA256Val);
private:
SHA256_CTX ctx;
};
class EntropyVal : public OpaqueVal {
public:
EntropyVal() : OpaqueVal(new OpaqueType("entropy")) { }
bool Feed(const void* data, size_t size);
bool Get(double *r_ent, double *r_chisq, double *r_mean,
double *r_montepicalc, double *r_scc);
protected:
friend class Val;
EntropyVal(OpaqueType* t);
DECLARE_SERIAL(EntropyVal);
private:
RandTest state;
};
#endif

View file

@ -12,7 +12,18 @@
Modified for Bro by Seth Hall - July 2010 Modified for Bro by Seth Hall - July 2010
*/ */
#include <RandTest.h> #include <math.h>
#include "RandTest.h"
#define log2of10 3.32192809488736234787
/* RT_LOG2 -- Calculate log to the base 2 */
static double rt_log2(double x)
{
return log2of10 * log10(x);
}
// RT_INCIRC = pow(pow(256.0, (double) (RT_MONTEN / 2)) - 1, 2.0);
#define RT_INCIRC 281474943156225.0
RandTest::RandTest() RandTest::RandTest()
{ {
@ -28,9 +39,9 @@ RandTest::RandTest()
} }
} }
void RandTest::add(void *buf, int bufl) void RandTest::add(const void *buf, int bufl)
{ {
unsigned char *bp = (unsigned char*)buf; const unsigned char *bp = static_cast<const unsigned char*>(buf);
int oc; int oc;
while (bufl-- > 0) while (bufl-- > 0)
@ -78,8 +89,8 @@ void RandTest::add(void *buf, int bufl)
} }
} }
void RandTest::end(double *r_ent, double *r_chisq, void RandTest::end(double* r_ent, double* r_chisq,
double *r_mean, double *r_montepicalc, double *r_scc) double* r_mean, double* r_montepicalc, double* r_scc)
{ {
int i; int i;
double ent, chisq, scc, datasum; double ent, chisq, scc, datasum;

View file

@ -1,34 +1,33 @@
#include <math.h> #ifndef RANDTEST_H
#define RANDTEST_H
#define log2of10 3.32192809488736234787 #include "util.h"
/* RT_LOG2 -- Calculate log to the base 2 */
static double rt_log2(double x)
{
return log2of10 * log10(x);
}
#define RT_MONTEN 6 /* Bytes used as Monte Carlo #define RT_MONTEN 6 /* Bytes used as Monte Carlo
co-ordinates. This should be no more co-ordinates. This should be no more
bits than the mantissa of your "double" bits than the mantissa of your "double"
floating point type. */ floating point type. */
class EntropyVal;
// RT_INCIRC = pow(pow(256.0, (double) (RT_MONTEN / 2)) - 1, 2.0);
#define RT_INCIRC 281474943156225.0
class RandTest { class RandTest {
public: public:
RandTest(); RandTest();
void add(void *buf, int bufl); void add(const void* buf, int bufl);
void end(double *r_ent, double *r_chisq, double *r_mean, void end(double* r_ent, double* r_chisq, double* r_mean,
double *r_montepicalc, double *r_scc); double* r_montepicalc, double* r_scc);
private: private:
long ccount[256]; /* Bins to count occurrences of values */ friend class EntropyVal;
long totalc; /* Total bytes counted */
int64 ccount[256]; /* Bins to count occurrences of values */
int64 totalc; /* Total bytes counted */
int mp; int mp;
int sccfirst; int sccfirst;
unsigned int monte[RT_MONTEN]; unsigned int monte[RT_MONTEN];
long inmont, mcount; int64 inmont, mcount;
double cexp, montex, montey, montepi, double cexp, montex, montey, montepi,
sccu0, scclast, scct1, scct2, scct3; sccu0, scclast, scct1, scct2, scct3;
}; };
#endif

View file

@ -98,6 +98,12 @@ SERIAL_VAL(RECORD_VAL, 10)
SERIAL_VAL(ENUM_VAL, 11) SERIAL_VAL(ENUM_VAL, 11)
SERIAL_VAL(VECTOR_VAL, 12) SERIAL_VAL(VECTOR_VAL, 12)
SERIAL_VAL(MUTABLE_VAL, 13) SERIAL_VAL(MUTABLE_VAL, 13)
SERIAL_VAL(OPAQUE_VAL, 14)
SERIAL_VAL(HASH_VAL, 15)
SERIAL_VAL(MD5_VAL, 16)
SERIAL_VAL(SHA1_VAL, 17)
SERIAL_VAL(SHA256_VAL, 18)
SERIAL_VAL(ENTROPY_VAL, 19)
#define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR) #define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR)
SERIAL_EXPR(EXPR, 1) SERIAL_EXPR(EXPR, 1)
@ -178,6 +184,7 @@ SERIAL_TYPE(SUBNET_TYPE, 8)
SERIAL_TYPE(FILE_TYPE, 9) SERIAL_TYPE(FILE_TYPE, 9)
SERIAL_TYPE(ENUM_TYPE, 10) SERIAL_TYPE(ENUM_TYPE, 10)
SERIAL_TYPE(VECTOR_TYPE, 11) SERIAL_TYPE(VECTOR_TYPE, 11)
SERIAL_TYPE(OPAQUE_TYPE, 12)
SERIAL_CONST2(ATTRIBUTES) SERIAL_CONST2(ATTRIBUTES)
SERIAL_CONST2(EVENT_HANDLER) SERIAL_CONST2(EVENT_HANDLER)

View file

@ -592,6 +592,21 @@ Case::~Case()
void Case::Describe(ODesc* d) const void Case::Describe(ODesc* d) const
{ {
if ( ! Cases() )
{
if ( ! d->IsBinary() )
d->Add("default:");
d->AddCount(0);
d->PushIndent();
Body()->AccessStats(d);
Body()->Describe(d);
d->PopIndent();
return;
}
const expr_list& e = Cases()->Exprs(); const expr_list& e = Cases()->Exprs();
if ( ! d->IsBinary() ) if ( ! d->IsBinary() )
@ -658,13 +673,64 @@ bool Case::DoUnserialize(UnserialInfo* info)
return this->s != 0; return this->s != 0;
} }
SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) : static void int_del_func(void* v)
ExprStmt(STMT_SWITCH, index)
{ {
cases = arg_cases; delete (int*) v;
}
//### need to loop over cases and make sure their type matches void SwitchStmt::Init()
//### the index, and they're constant and not redundant {
TypeList* t = new TypeList();
t->Append(e->Type()->Ref());
comp_hash = new CompositeHash(t);
Unref(t);
case_label_map.SetDeleteFunc(int_del_func);
}
SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) :
ExprStmt(STMT_SWITCH, index), cases(arg_cases), default_case_idx(-1)
{
Init();
if ( ! is_atomic_type(e->Type()) )
e->Error("switch expression must be of an atomic type");
loop_over_list(*cases, i)
{
const Case* c = (*cases)[i];
const ListExpr* le = c->Cases();
if ( le )
{
if ( ! le->Type()->AsTypeList()->AllMatch(e->Type(), false) )
{
le->Error("case expression type differs from switch type", e);
continue;
}
const expr_list& exprs = le->Exprs();
loop_over_list(exprs, j)
{
if ( ! exprs[j]->IsConst() )
exprs[j]->Error("case label expression isn't constant");
else
{
if ( ! AddCaseLabelMapping(exprs[j]->ExprVal(), i) )
exprs[j]->Error("duplicate case label");
}
}
}
else
{
if ( default_case_idx != -1 )
c->Error("multiple default labels", (*cases)[default_case_idx]);
else
default_case_idx = i;
}
}
} }
SwitchStmt::~SwitchStmt() SwitchStmt::~SwitchStmt()
@ -673,12 +739,80 @@ SwitchStmt::~SwitchStmt()
Unref((*cases)[i]); Unref((*cases)[i]);
delete cases; delete cases;
delete comp_hash;
} }
Val* SwitchStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */) const bool SwitchStmt::AddCaseLabelMapping(const Val* v, int idx)
{ {
printf("switch statement not implemented\n"); HashKey* hk = comp_hash->ComputeHash(v, 1);
return 0;
if ( ! hk )
{
reporter->PushLocation(e->GetLocationInfo());
reporter->InternalError("switch expression type mismatch (%s/%s)",
type_name(v->Type()->Tag()), type_name(e->Type()->Tag()));
}
int* label_idx = case_label_map.Lookup(hk);
if ( label_idx )
{
delete hk;
return false;
}
case_label_map.Insert(hk, new int(idx));
return true;
}
int SwitchStmt::FindCaseLabelMatch(const Val* v) const
{
HashKey* hk = comp_hash->ComputeHash(v, 1);
if ( ! hk )
{
reporter->PushLocation(e->GetLocationInfo());
reporter->InternalError("switch expression type mismatch (%s/%s)",
type_name(v->Type()->Tag()), type_name(e->Type()->Tag()));
}
int* label_idx = case_label_map.Lookup(hk);
delete hk;
if ( ! label_idx )
return default_case_idx;
else
return *label_idx;
}
Val* SwitchStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
{
Val* rval = 0;
int matching_label_idx = FindCaseLabelMatch(v);
if ( matching_label_idx == -1 )
return 0;
for ( int i = matching_label_idx; i < cases->length(); ++i )
{
const Case* c = (*cases)[i];
flow = FLOW_NEXT;
rval = c->Body()->Exec(f, flow);
if ( flow == FLOW_BREAK )
{
flow = FLOW_NEXT;
break;
}
if ( flow == FLOW_RETURN )
break;
}
return rval;
} }
Stmt* SwitchStmt::DoSimplify() Stmt* SwitchStmt::DoSimplify()
@ -697,7 +831,13 @@ Stmt* SwitchStmt::DoSimplify()
} }
if ( e->IsConst() ) if ( e->IsConst() )
{ // ### go through cases and pull out the one it matches {
// Could possibly remove all case labels before the one
// that will match, but may be tricky to tell if any
// subsequent ones can also be removed since it depends
// on the evaluation of the body executing a break/return
// statement. Then still need a way to bypass the lookup
// DoExec for it to be beneficial.
if ( ! optimize ) if ( ! optimize )
Warn("constant in switch"); Warn("constant in switch");
} }
@ -770,6 +910,9 @@ bool SwitchStmt::DoSerialize(SerialInfo* info) const
if ( ! (*cases)[i]->Serialize(info) ) if ( ! (*cases)[i]->Serialize(info) )
return false; return false;
if ( ! SERIALIZE(default_case_idx) )
return false;
return true; return true;
} }
@ -777,6 +920,8 @@ bool SwitchStmt::DoUnserialize(UnserialInfo* info)
{ {
DO_UNSERIALIZE(ExprStmt); DO_UNSERIALIZE(ExprStmt);
Init();
int len; int len;
if ( ! UNSERIALIZE(&len) ) if ( ! UNSERIALIZE(&len) )
return false; return false;
@ -790,6 +935,25 @@ bool SwitchStmt::DoUnserialize(UnserialInfo* info)
cases->append(c); cases->append(c);
} }
if ( ! UNSERIALIZE(&default_case_idx) )
return false;
loop_over_list(*cases, i)
{
const ListExpr* le = (*cases)[i]->Cases();
if ( ! le )
continue;
const expr_list& exprs = le->Exprs();
loop_over_list(exprs, j)
{
if ( ! AddCaseLabelMapping(exprs[j]->ExprVal(), i) )
return false;
}
}
return true; return true;
} }

View file

@ -17,6 +17,8 @@
class StmtList; class StmtList;
class ForStmt; class ForStmt;
declare(PDict, int);
class Stmt : public BroObj { class Stmt : public BroObj {
public: public:
BroStmtTag Tag() const { return tag; } BroStmtTag Tag() const { return tag; }
@ -187,7 +189,8 @@ protected:
class Case : public BroObj { class Case : public BroObj {
public: public:
Case(ListExpr* c, Stmt* arg_s) { cases = c; s = arg_s; } Case(ListExpr* c, Stmt* arg_s) :
cases(simplify_expr_list(c,SIMPLIFY_GENERAL)), s(arg_s) { }
~Case(); ~Case();
const ListExpr* Cases() const { return cases; } const ListExpr* Cases() const { return cases; }
@ -226,7 +229,7 @@ public:
protected: protected:
friend class Stmt; friend class Stmt;
SwitchStmt() { cases = 0; } SwitchStmt() { cases = 0; default_case_idx = -1; comp_hash = 0; }
Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const; Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const;
Stmt* DoSimplify(); Stmt* DoSimplify();
@ -234,7 +237,23 @@ protected:
DECLARE_SERIAL(SwitchStmt); DECLARE_SERIAL(SwitchStmt);
// Initialize composite hash and case label map.
void Init();
// Adds an entry in case_label_map for the given value to associate it
// with the given index in the cases list. If the entry already exists,
// returns false, else returns true.
bool AddCaseLabelMapping(const Val* v, int idx);
// Returns index of a case label that's equal to the value, or
// default_case_idx if no case label matches (which may be -1 if there's
// no default label).
int FindCaseLabelMatch(const Val* v) const;
case_list* cases; case_list* cases;
int default_case_idx;
CompositeHash* comp_hash;
PDict(int) case_label_map;
}; };
class AddStmt : public ExprStmt { class AddStmt : public ExprStmt {

View file

@ -382,7 +382,7 @@ void TCP_Analyzer::ProcessFIN(double t, TCP_Endpoint* endpoint,
endpoint->FIN_seq = base_seq - endpoint->StartSeq() + seq_len; endpoint->FIN_seq = base_seq - endpoint->StartSeq() + seq_len;
} }
bool TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint, void TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint,
const IP_Hdr* ip, uint32 base_seq, const IP_Hdr* ip, uint32 base_seq,
int len, int& seq_len) int len, int& seq_len)
{ {
@ -406,11 +406,9 @@ bool TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint,
} }
PacketWithRST(); PacketWithRST();
return true;
} }
int TCP_Analyzer::ProcessFlags(double t, void TCP_Analyzer::ProcessFlags(double t,
const IP_Hdr* ip, const struct tcphdr* tp, const IP_Hdr* ip, const struct tcphdr* tp,
uint32 tcp_hdr_len, int len, int& seq_len, uint32 tcp_hdr_len, int len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer, TCP_Endpoint* endpoint, TCP_Endpoint* peer,
@ -425,14 +423,11 @@ int TCP_Analyzer::ProcessFlags(double t,
if ( flags.FIN() ) if ( flags.FIN() )
ProcessFIN(t, endpoint, seq_len, base_seq); ProcessFIN(t, endpoint, seq_len, base_seq);
if ( flags.RST() && if ( flags.RST() )
! ProcessRST(t, endpoint, ip, base_seq, len, seq_len) ) ProcessRST(t, endpoint, ip, base_seq, len, seq_len);
return 0;
if ( flags.ACK() ) if ( flags.ACK() )
ProcessACK(endpoint, peer, ack_seq, is_orig, flags); ProcessACK(endpoint, peer, ack_seq, is_orig, flags);
return 1;
} }
void TCP_Analyzer::TransitionFromInactive(double t, TCP_Endpoint* endpoint, void TCP_Analyzer::TransitionFromInactive(double t, TCP_Endpoint* endpoint,
@ -825,10 +820,27 @@ void TCP_Analyzer::UpdateClosedState(double t, TCP_Endpoint* endpoint,
} }
} }
void TCP_Analyzer::UpdateResetState(int len, TCP_Flags flags) void TCP_Analyzer::UpdateResetState(int len, TCP_Flags flags,
TCP_Endpoint* endpoint, uint32 base_seq,
uint32 last_seq)
{ {
if ( flags.SYN() ) if ( flags.SYN() )
{
Weird("SYN_after_reset"); Weird("SYN_after_reset");
if ( endpoint->prev_state == TCP_ENDPOINT_INACTIVE )
{
// Seq. numbers were initialized by a RST packet from this endpoint,
// but now that a SYN is seen from it, that could mean the earlier
// RST was spoofed/injected, so re-initialize. This mostly just
// helps prevent misrepresentations of payload sizes that are based
// on bad initial sequence values.
endpoint->InitStartSeq(base_seq);
endpoint->InitAckSeq(base_seq);
endpoint->InitLastSeq(last_seq);
}
}
if ( flags.FIN() ) if ( flags.FIN() )
Weird("FIN_after_reset"); Weird("FIN_after_reset");
@ -871,7 +883,7 @@ void TCP_Analyzer::UpdateStateMachine(double t,
break; break;
case TCP_ENDPOINT_RESET: case TCP_ENDPOINT_RESET:
UpdateResetState(len, flags); UpdateResetState(len, flags, endpoint, base_seq, last_seq);
break; break;
} }
} }
@ -996,10 +1008,8 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
int seq_len = len; // length in terms of sequence space int seq_len = len; // length in terms of sequence space
if ( ! ProcessFlags(t, ip, tp, tcp_hdr_len, len, seq_len, ProcessFlags(t, ip, tp, tcp_hdr_len, len, seq_len, endpoint, peer, base_seq,
endpoint, peer, base_seq, ack_seq, ack_seq, orig_addr, is_orig, flags);
orig_addr, is_orig, flags) )
return;
uint32 last_seq = base_seq + seq_len; uint32 last_seq = base_seq + seq_len;

View file

@ -135,13 +135,13 @@ protected:
void ProcessFIN(double t, TCP_Endpoint* endpoint, int& seq_len, void ProcessFIN(double t, TCP_Endpoint* endpoint, int& seq_len,
uint32 base_seq); uint32 base_seq);
bool ProcessRST(double t, TCP_Endpoint* endpoint, const IP_Hdr* ip, void ProcessRST(double t, TCP_Endpoint* endpoint, const IP_Hdr* ip,
uint32 base_seq, int len, int& seq_len); uint32 base_seq, int len, int& seq_len);
void ProcessACK(TCP_Endpoint* endpoint, TCP_Endpoint* peer, void ProcessACK(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 ack_seq, int is_orig, TCP_Flags flags); uint32 ack_seq, int is_orig, TCP_Flags flags);
int ProcessFlags(double t, const IP_Hdr* ip, const struct tcphdr* tp, void ProcessFlags(double t, const IP_Hdr* ip, const struct tcphdr* tp,
uint32 tcp_hdr_len, int len, int& seq_len, uint32 tcp_hdr_len, int len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer, TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq, uint32 base_seq, uint32 ack_seq,
@ -186,7 +186,8 @@ protected:
int delta_last, TCP_Flags flags, int delta_last, TCP_Flags flags,
int& do_close); int& do_close);
void UpdateResetState(int len, TCP_Flags flags); void UpdateResetState(int len, TCP_Flags flags, TCP_Endpoint* endpoint,
uint32 base_seq, uint32 last_seq);
void GeneratePacketEvent(TCP_Endpoint* endpoint, TCP_Endpoint* peer, void GeneratePacketEvent(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq, uint32 base_seq, uint32 ack_seq,

View file

@ -30,6 +30,7 @@ const char* type_name(TypeTag t)
"table", "union", "record", "types", "table", "union", "record", "types",
"func", "func",
"file", "file",
"opaque",
"vector", "vector",
"type", "type",
"error", "error",
@ -96,6 +97,7 @@ BroType::BroType(TypeTag t, bool arg_base_type)
case TYPE_LIST: case TYPE_LIST:
case TYPE_FUNC: case TYPE_FUNC:
case TYPE_FILE: case TYPE_FILE:
case TYPE_OPAQUE:
case TYPE_VECTOR: case TYPE_VECTOR:
case TYPE_TYPE: case TYPE_TYPE:
internal_tag = TYPE_INTERNAL_OTHER; internal_tag = TYPE_INTERNAL_OTHER;
@ -114,8 +116,17 @@ BroType::~BroType()
delete [] type_id; delete [] type_id;
} }
int BroType::MatchesIndex(ListExpr*& /* index */) const int BroType::MatchesIndex(ListExpr*& index) const
{ {
if ( Tag() == TYPE_STRING )
{
if ( index->Exprs().length() != 1 && index->Exprs().length() != 2 )
return DOES_NOT_MATCH_INDEX;
if ( check_and_promote_exprs_to_type(index, ::base_type(TYPE_INT)) )
return MATCHES_INDEX_SCALAR;
}
return DOES_NOT_MATCH_INDEX; return DOES_NOT_MATCH_INDEX;
} }
@ -1262,6 +1273,42 @@ bool FileType::DoUnserialize(UnserialInfo* info)
return yield != 0; return yield != 0;
} }
OpaqueType::OpaqueType(const string& arg_name) : BroType(TYPE_OPAQUE)
{
name = arg_name;
}
void OpaqueType::Describe(ODesc* d) const
{
if ( d->IsReadable() )
d->AddSP("opaque of");
else
d->Add(int(Tag()));
d->Add(name.c_str());
}
IMPLEMENT_SERIAL(OpaqueType, SER_OPAQUE_TYPE);
bool OpaqueType::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_OPAQUE_TYPE, BroType);
return SERIALIZE(name);
}
bool OpaqueType::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(BroType);
char const* n;
if ( ! UNSERIALIZE_STR(&n, 0) )
return false;
name = n;
delete [] n;
return true;
}
EnumType::EnumType(const string& arg_name) EnumType::EnumType(const string& arg_name)
: BroType(TYPE_ENUM) : BroType(TYPE_ENUM)
{ {
@ -1716,6 +1763,13 @@ int same_type(const BroType* t1, const BroType* t2, int is_init)
case TYPE_FILE: case TYPE_FILE:
return same_type(t1->YieldType(), t2->YieldType(), is_init); return same_type(t1->YieldType(), t2->YieldType(), is_init);
case TYPE_OPAQUE:
{
const OpaqueType* ot1 = (const OpaqueType*) t1;
const OpaqueType* ot2 = (const OpaqueType*) t2;
return ot1->Name() == ot2->Name() ? 1 : 0;
}
case TYPE_TYPE: case TYPE_TYPE:
return same_type(t1, t2, is_init); return same_type(t1, t2, is_init);
@ -1805,6 +1859,7 @@ int is_assignable(BroType* t)
case TYPE_VECTOR: case TYPE_VECTOR:
case TYPE_FILE: case TYPE_FILE:
case TYPE_OPAQUE:
case TYPE_TABLE: case TYPE_TABLE:
case TYPE_TYPE: case TYPE_TYPE:
return 1; return 1;
@ -2190,3 +2245,18 @@ BroType* init_type(Expr* init)
return new SetType(t->AsTypeList(), 0); return new SetType(t->AsTypeList(), 0);
} }
bool is_atomic_type(const BroType* t)
{
switch ( t->InternalType() ) {
case TYPE_INTERNAL_INT:
case TYPE_INTERNAL_UNSIGNED:
case TYPE_INTERNAL_DOUBLE:
case TYPE_INTERNAL_STRING:
case TYPE_INTERNAL_ADDR:
case TYPE_INTERNAL_SUBNET:
return true;
default:
return false;
}
}

View file

@ -29,6 +29,7 @@ typedef enum {
TYPE_LIST, TYPE_LIST,
TYPE_FUNC, TYPE_FUNC,
TYPE_FILE, TYPE_FILE,
TYPE_OPAQUE,
TYPE_VECTOR, TYPE_VECTOR,
TYPE_TYPE, TYPE_TYPE,
TYPE_ERROR TYPE_ERROR
@ -499,6 +500,23 @@ protected:
BroType* yield; BroType* yield;
}; };
class OpaqueType : public BroType {
public:
OpaqueType(const string& name);
virtual ~OpaqueType() { };
const string& Name() const { return name; }
void Describe(ODesc* d) const;
protected:
OpaqueType() { }
DECLARE_SERIAL(OpaqueType)
string name;
};
class EnumType : public BroType { class EnumType : public BroType {
public: public:
EnumType(const string& arg_name); EnumType(const string& arg_name);
@ -625,6 +643,9 @@ BroType* merge_type_list(ListExpr* elements);
// Given an expression, infer its type when used for an initialization. // Given an expression, infer its type when used for an initialization.
extern BroType* init_type(Expr* init); extern BroType* init_type(Expr* init);
// Returns true if argument is an atomic type.
bool is_atomic_type(const BroType* t);
// True if the given type tag corresponds to an integral type. // True if the given type tag corresponds to an integral type.
#define IsIntegral(t) (t == TYPE_INT || t == TYPE_COUNT || t == TYPE_COUNTER) #define IsIntegral(t) (t == TYPE_INT || t == TYPE_COUNT || t == TYPE_COUNTER)

View file

@ -3114,6 +3114,27 @@ void VectorVal::ValDescribe(ODesc* d) const
d->Add("]"); d->Add("]");
} }
OpaqueVal::OpaqueVal(OpaqueType* t) : Val(t)
{
}
OpaqueVal::~OpaqueVal()
{
}
IMPLEMENT_SERIAL(OpaqueVal, SER_OPAQUE_VAL);
bool OpaqueVal::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_OPAQUE_VAL, Val);
return true;
}
bool OpaqueVal::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(Val);
return true;
}
Val* check_and_promote(Val* v, const BroType* t, int is_init) Val* check_and_promote(Val* v, const BroType* t, int is_init)
{ {
@ -3209,17 +3230,7 @@ int same_val(const Val* /* v1 */, const Val* /* v2 */)
bool is_atomic_val(const Val* v) bool is_atomic_val(const Val* v)
{ {
switch ( v->Type()->InternalType() ) { return is_atomic_type(v->Type());
case TYPE_INTERNAL_INT:
case TYPE_INTERNAL_UNSIGNED:
case TYPE_INTERNAL_DOUBLE:
case TYPE_INTERNAL_STRING:
case TYPE_INTERNAL_ADDR:
case TYPE_INTERNAL_SUBNET:
return true;
default:
return false;
}
} }
int same_atomic_val(const Val* v1, const Val* v2) int same_atomic_val(const Val* v1, const Val* v2)

View file

@ -1013,6 +1013,20 @@ protected:
VectorType* vector_type; VectorType* vector_type;
}; };
// Base class for values with types that are managed completely internally,
// with no further script-level operators provided (other than bif
// functions). See OpaqueVal.h for derived classes.
class OpaqueVal : public Val {
public:
OpaqueVal(OpaqueType* t);
virtual ~OpaqueVal();
protected:
friend class Val;
OpaqueVal() { }
DECLARE_SERIAL(OpaqueVal);
};
// Checks the given value for consistency with the given type. If an // Checks the given value for consistency with the given type. If an
// exact match, returns it. If promotable, returns the promoted version, // exact match, returns it. If promotable, returns the promoted version,

View file

@ -210,7 +210,6 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
// defined. // defined.
Func* f = new BroFunc(id, 0, 0, 0, 0); Func* f = new BroFunc(id, 0, 0, 0, 0);
id->SetVal(new Val(f)); id->SetVal(new Val(f));
id->SetConst();
} }
} }
@ -233,8 +232,9 @@ Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init,
Ref(id); Ref(id);
Expr* name_expr = new NameExpr(id, dt == VAR_CONST);
Stmt* stmt = Stmt* stmt =
new ExprStmt(new AssignExpr(new NameExpr(id), init, 0, 0, new ExprStmt(new AssignExpr(name_expr, init, 0, 0,
id->Attrs() ? id->Attrs()->Attrs() : 0 )); id->Attrs() ? id->Attrs()->Attrs() : 0 ));
stmt->SetLocationInfo(init->GetLocationInfo()); stmt->SetLocationInfo(init->GetLocationInfo());

View file

@ -530,82 +530,7 @@ function piped_exec%(program: string, to_write: string%): bool
%} %}
%%{ %%{
static void hash_md5_val(val_list& vlist, unsigned char digest[16]) #include "OpaqueVal.h"
{
MD5_CTX h;
md5_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
md5_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
md5_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
md5_final(&h, digest);
}
static void hmac_md5_val(val_list& vlist, unsigned char digest[16])
{
hash_md5_val(vlist, digest);
for ( int i = 0; i < 16; ++i )
digest[i] = digest[i] ^ shared_hmac_md5_key[i];
MD5(digest, 16, digest);
}
static void hash_sha1_val(val_list& vlist, unsigned char digest[20])
{
SHA_CTX h;
sha1_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha1_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha1_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha1_final(&h, digest);
}
static void hash_sha256_val(val_list& vlist, unsigned char digest[32])
{
SHA256_CTX h;
sha256_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha256_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha256_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha256_final(&h, digest);
}
%%} %%}
## Computes the MD5 hash value of the provided list of arguments. ## Computes the MD5 hash value of the provided list of arguments.
@ -623,8 +548,8 @@ static void hash_sha256_val(val_list& vlist, unsigned char digest[32])
## friends. ## friends.
function md5_hash%(...%): string function md5_hash%(...%): string
%{ %{
unsigned char digest[16]; unsigned char digest[MD5_DIGEST_LENGTH];
hash_md5_val(@ARG@, digest); MD5Val::digest(@ARG@, digest);
return new StringVal(md5_digest_print(digest)); return new StringVal(md5_digest_print(digest));
%} %}
@ -643,8 +568,8 @@ function md5_hash%(...%): string
## friends. ## friends.
function sha1_hash%(...%): string function sha1_hash%(...%): string
%{ %{
unsigned char digest[20]; unsigned char digest[SHA_DIGEST_LENGTH];
hash_sha1_val(@ARG@, digest); SHA1Val::digest(@ARG@, digest);
return new StringVal(sha1_digest_print(digest)); return new StringVal(sha1_digest_print(digest));
%} %}
@ -663,8 +588,8 @@ function sha1_hash%(...%): string
## friends. ## friends.
function sha256_hash%(...%): string function sha256_hash%(...%): string
%{ %{
unsigned char digest[32]; unsigned char digest[SHA256_DIGEST_LENGTH];
hash_sha256_val(@ARG@, digest); SHA256Val::digest(@ARG@, digest);
return new StringVal(sha256_digest_print(digest)); return new StringVal(sha256_digest_print(digest));
%} %}
@ -679,288 +604,183 @@ function sha256_hash%(...%): string
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hmac%(...%): string function md5_hmac%(...%): string
%{ %{
unsigned char digest[16]; unsigned char hmac[MD5_DIGEST_LENGTH];
hmac_md5_val(@ARG@, digest); MD5Val::hmac(@ARG@, shared_hmac_md5_key, hmac);
return new StringVal(md5_digest_print(digest)); return new StringVal(md5_digest_print(hmac));
%} %}
%%{ ## Constructs an MD5 handle to enable incremental hash computation. You can
static map<BroString, MD5_CTX> md5_states; ## feed data to the returned opaque value with :bro:id:`md5_hash_update` and
static map<BroString, SHA_CTX> sha1_states; ## eventually need to call :bro:id:`md5_hash_finish` to finish the computation
static map<BroString, SHA256_CTX> sha256_states; ## and get the hash digest as result.
BroString* convert_index_to_string(Val* index)
{
ODesc d;
index->Describe(&d);
BroString* s = new BroString(1, d.TakeBytes(), d.Len());
s->SetUseFreeToDelete(1);
return s;
}
%%}
## Initializes MD5 state to enable incremental hash computation. After
## initializing the MD5 state with this function, you can feed data to
## :bro:id:`md5_hash_update` and finally need to call :bro:id:`md5_hash_finish`
## to finish the computation and get the final hash value.
## ##
## For example, when computing incremental MD5 values of transferred files in ## For example, when computing incremental MD5 values of transferred files in
## multiple concurrent HTTP connections, one would call ``md5_hash_init(c$id)`` ## multiple concurrent HTTP connections, one keeps an optional handle in the
## once before invoking ``md5_hash_update(c$id, some_more_data)`` in the ## HTTP session record. Then, one would call
## ``c$http$md5_handle = md5_hash_init()`` once before invoking
## ``md5_hash_update(c$http$md5_handle, some_more_data)`` in the
## :bro:id:`http_entity_data` event handler. When all data has arrived, a call ## :bro:id:`http_entity_data` event handler. When all data has arrived, a call
## to :bro:id:`md5_hash_finish` returns the final hash value. ## to :bro:id:`md5_hash_finish` returns the final hash value.
## ##
## index: The unique identifier to associate with this hash computation. ## Returns: The opaque handle associated with this hash computation.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_init%(index: any%): bool function md5_hash_init%(%): opaque of md5
%{ %{
BroString* s = convert_index_to_string(index); HashVal* digest = new MD5Val();
int status = 0; digest->Init();
return digest;
if ( md5_states.count(*s) < 1 )
{
MD5_CTX h;
md5_init(&h);
md5_states[*s] = h;
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Initializes SHA1 state to enable incremental hash computation. After ## Constructs an SHA1 handle to enable incremental hash computation. You can
## initializing the SHA1 state with this function, you can feed data to ## feed data to the returned opaque value with :bro:id:`sha1_hash_update` and
## :bro:id:`sha1_hash_update` and finally need to call ## finally need to call :bro:id:`sha1_hash_finish` to finish the computation
## :bro:id:`sha1_hash_finish` to finish the computation and get the final hash ## and get the hash digest as result.
## value.
## ##
## For example, when computing incremental SHA1 values of transferred files in ## For example, when computing incremental SHA1 values of transferred files in
## multiple concurrent HTTP connections, one would call ``sha1_hash_init(c$id)`` ## multiple concurrent HTTP connections, one keeps an optional handle in the
## once before invoking ``sha1_hash_update(c$id, some_more_data)`` in the ## HTTP session record. Then, one would call
## ``c$http$sha1_handle = sha1_hash_init()`` ## once before invoking
## ``sha1_hash_update(c$http$sha1_handle, some_more_data)`` in the
## :bro:id:`http_entity_data` event handler. When all data has arrived, a call ## :bro:id:`http_entity_data` event handler. When all data has arrived, a call
## to :bro:id:`sha1_hash_finish` returns the final hash value. ## to :bro:id:`sha1_hash_finish` returns the final hash value.
## ##
## index: The unique identifier to associate with this hash computation. ## Returns: The opaque handle associated with this hash computation.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_init%(index: any%): bool function sha1_hash_init%(%): opaque of sha1
%{ %{
BroString* s = convert_index_to_string(index); HashVal* digest = new SHA1Val();
int status = 0; digest->Init();
return digest;
if ( sha1_states.count(*s) < 1 )
{
SHA_CTX h;
sha1_init(&h);
sha1_states[*s] = h;
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Initializes SHA256 state to enable incremental hash computation. After ## Constructs an SHA256 handle to enable incremental hash computation. You can
## initializing the SHA256 state with this function, you can feed data to ## feed data to the returned opaque value with :bro:id:`sha256_hash_update` and
## :bro:id:`sha256_hash_update` and finally need to call ## finally need to call :bro:id:`sha256_hash_finish` to finish the computation
## :bro:id:`sha256_hash_finish` to finish the computation and get the final hash ## and get the hash digest as result.
## value.
## ##
## For example, when computing incremental SHA256 values of transferred files in ## For example, when computing incremental SHA256 values of transferred files in
## multiple concurrent HTTP connections, one would call ## multiple concurrent HTTP connections, one keeps an optional handle in the
## ``sha256_hash_init(c$id)`` once before invoking ## HTTP session record. Then, one would call
## ``sha256_hash_update(c$id, some_more_data)`` in the ## ``c$http$sha256_handle = sha256_hash_init()`` ## once before invoking
## ``sha256_hash_update(c$http$sha256_handle, some_more_data)`` in the
## :bro:id:`http_entity_data` event handler. When all data has arrived, a call ## :bro:id:`http_entity_data` event handler. When all data has arrived, a call
## to :bro:id:`sha256_hash_finish` returns the final hash value. ## to :bro:id:`sha256_hash_finish` returns the final hash value.
## ##
## index: The unique identifier to associate with this hash computation. ## Returns: The opaque handle associated with this hash computation.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_update sha256_hash_finish
function sha256_hash_init%(index: any%): bool function sha256_hash_init%(%): opaque of sha256
%{ %{
BroString* s = convert_index_to_string(index); HashVal* digest = new SHA256Val();
int status = 0; digest->Init();
return digest;
if ( sha256_states.count(*s) < 1 )
{
SHA256_CTX h;
sha256_init(&h);
sha256_states[*s] = h;
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Update the MD5 value associated with a given index. It is required to ## Updates the MD5 value associated with a given index. It is required to
## call :bro:id:`md5_hash_init` once before calling this ## call :bro:id:`md5_hash_init` once before calling this
## function. ## function.
## ##
## index: The unique identifier to associate with this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## data: The data to add to the hash computation. ## data: The data to add to the hash computation.
## ##
## Returns: True on success.
##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_update%(index: any, data: string%): bool function md5_hash_update%(handle: opaque of md5, data: string%): bool
%{ %{
BroString* s = convert_index_to_string(index); bool rc = static_cast<HashVal*>(handle)->Feed(data->Bytes(), data->Len());
int status = 0; return new Val(rc, TYPE_BOOL);
if ( md5_states.count(*s) > 0 )
{
md5_update(&md5_states[*s], data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Update the SHA1 value associated with a given index. It is required to ## Updates the SHA1 value associated with a given index. It is required to
## call :bro:id:`sha1_hash_init` once before calling this ## call :bro:id:`sha1_hash_init` once before calling this
## function. ## function.
## ##
## index: The unique identifier to associate with this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## data: The data to add to the hash computation. ## data: The data to add to the hash computation.
## ##
## Returns: True on success.
##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_update%(index: any, data: string%): bool function sha1_hash_update%(handle: opaque of sha1, data: string%): bool
%{ %{
BroString* s = convert_index_to_string(index); bool rc = static_cast<HashVal*>(handle)->Feed(data->Bytes(), data->Len());
int status = 0; return new Val(rc, TYPE_BOOL);
if ( sha1_states.count(*s) > 0 )
{
sha1_update(&sha1_states[*s], data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Update the SHA256 value associated with a given index. It is required to ## Updates the SHA256 value associated with a given index. It is required to
## call :bro:id:`sha256_hash_init` once before calling this ## call :bro:id:`sha256_hash_init` once before calling this
## function. ## function.
## ##
## index: The unique identifier to associate with this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## data: The data to add to the hash computation. ## data: The data to add to the hash computation.
## ##
## Returns: True on success.
##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_finish
function sha256_hash_update%(index: any, data: string%): bool function sha256_hash_update%(handle: opaque of sha256, data: string%): bool
%{ %{
BroString* s = convert_index_to_string(index); bool rc = static_cast<HashVal*>(handle)->Feed(data->Bytes(), data->Len());
int status = 0; return new Val(rc, TYPE_BOOL);
if ( sha256_states.count(*s) > 0 )
{
sha256_update(&sha256_states[*s], data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Returns the final MD5 digest of an incremental hash computation. ## Returns the final MD5 digest of an incremental hash computation.
## ##
## index: The unique identifier of this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## Returns: The hash value associated with the computation at *index*. ## Returns: The hash value associated with the computation of *handle*.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_finish%(index: any%): string function md5_hash_finish%(handle: opaque of md5%): string
%{ %{
BroString* s = convert_index_to_string(index); return static_cast<HashVal*>(handle)->Get();
StringVal* printable_digest;
if ( md5_states.count(*s) > 0 )
{
unsigned char digest[16];
md5_final(&md5_states[*s], digest);
md5_states.erase(*s);
printable_digest = new StringVal(md5_digest_print(digest));
}
else
printable_digest = new StringVal("");
delete s;
return printable_digest;
%} %}
## Returns the final SHA1 digest of an incremental hash computation. ## Returns the final SHA1 digest of an incremental hash computation.
## ##
## index: The unique identifier of this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## Returns: The hash value associated with the computation at *index*. ## Returns: The hash value associated with the computation of *handle*.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update ## sha1_hash sha1_hash_init sha1_hash_update
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish ## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_finish%(index: any%): string function sha1_hash_finish%(handle: opaque of sha1%): string
%{ %{
BroString* s = convert_index_to_string(index); return static_cast<HashVal*>(handle)->Get();
StringVal* printable_digest;
if ( sha1_states.count(*s) > 0 )
{
unsigned char digest[20];
sha1_final(&sha1_states[*s], digest);
sha1_states.erase(*s);
printable_digest = new StringVal(sha1_digest_print(digest));
}
else
printable_digest = new StringVal("");
delete s;
return printable_digest;
%} %}
## Returns the final SHA256 digest of an incremental hash computation. ## Returns the final SHA256 digest of an incremental hash computation.
## ##
## index: The unique identifier of this hash computation. ## handle: The opaque handle associated with this hash computation.
## ##
## Returns: The hash value associated with the computation at *index*. ## Returns: The hash value associated with the computation of *handle*.
## ##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish ## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update ## sha256_hash sha256_hash_init sha256_hash_update
function sha256_hash_finish%(index: any%): string function sha256_hash_finish%(handle: opaque of sha256%): string
%{ %{
BroString* s = convert_index_to_string(index); return static_cast<HashVal*>(handle)->Get();
StringVal* printable_digest;
if ( sha256_states.count(*s) > 0 )
{
unsigned char digest[32];
sha256_final(&sha256_states[*s], digest);
sha256_states.erase(*s);
printable_digest = new StringVal(sha256_digest_print(digest));
}
else
printable_digest = new StringVal("");
delete s;
return printable_digest;
%} %}
## Generates a random number. ## Generates a random number.
@ -1058,11 +878,6 @@ function identify_data%(data: string, return_mime: bool%): string
return new StringVal(descr); return new StringVal(descr);
%} %}
%%{
#include <RandTest.h>
static map<BroString, RandTest*> entropy_states;
%%}
## Performs an entropy test on the given data. ## Performs an entropy test on the given data.
## See http://www.fourmilab.ch/random. ## See http://www.fourmilab.ch/random.
## ##
@ -1107,13 +922,11 @@ function find_entropy%(data: string%): entropy_test_result
%{ %{
double montepi, scc, ent, mean, chisq; double montepi, scc, ent, mean, chisq;
montepi = scc = ent = mean = chisq = 0.0; montepi = scc = ent = mean = chisq = 0.0;
EntropyVal e;
e.Feed(data->Bytes(), data->Len());
e.Get(&ent, &chisq, &mean, &montepi, &scc);
RecordVal* ent_result = new RecordVal(entropy_test_result); RecordVal* ent_result = new RecordVal(entropy_test_result);
RandTest *rt = new RandTest();
rt->add((char*) data->Bytes(), data->Len());
rt->end(&ent, &chisq, &mean, &montepi, &scc);
delete rt;
ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
@ -1124,85 +937,52 @@ function find_entropy%(data: string%): entropy_test_result
## Initializes data structures for incremental entropy calculation. ## Initializes data structures for incremental entropy calculation.
## ##
## index: An arbitrary unique value per distinct computation. ## Returns: An opaque handle to be used in subsequent operations.
##
## Returns: True on success.
## ##
## .. bro:see:: find_entropy entropy_test_add entropy_test_finish ## .. bro:see:: find_entropy entropy_test_add entropy_test_finish
function entropy_test_init%(index: any%): bool function entropy_test_init%(%): opaque of entropy
%{ %{
BroString* s = convert_index_to_string(index); return new EntropyVal();
int status = 0;
if ( entropy_states.count(*s) < 1 )
{
entropy_states[*s] = new RandTest();
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%} %}
## Adds data to an incremental entropy calculation. Before using this function, ## Adds data to an incremental entropy calculation.
## one needs to invoke :bro:id:`entropy_test_init`. ##
## handle: The opaque handle representing the entropy calculation state.
## ##
## data: The data to add to the entropy calculation. ## data: The data to add to the entropy calculation.
## ##
## index: An arbitrary unique value that identifies a particular entropy
## computation.
##
## Returns: True on success. ## Returns: True on success.
## ##
## .. bro:see:: find_entropy entropy_test_add entropy_test_finish ## .. bro:see:: find_entropy entropy_test_add entropy_test_finish
function entropy_test_add%(index: any, data: string%): bool function entropy_test_add%(handle: opaque of entropy, data: string%): bool
%{ %{
BroString* s = convert_index_to_string(index); bool status = static_cast<EntropyVal*>(handle)->Feed(data->Bytes(),
int status = 0; data->Len());
if ( entropy_states.count(*s) > 0 )
{
entropy_states[*s]->add((char*) data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL); return new Val(status, TYPE_BOOL);
%} %}
## Finishes an incremental entropy calculation. Before using this function, ## Finishes an incremental entropy calculation. Before using this function,
## one needs to initialize the computation with :bro:id:`entropy_test_init` and ## one needs to obtain an opaque handle with :bro:id:`entropy_test_init` and
## add data to it via :bro:id:`entropy_test_add`. ## add data to it via :bro:id:`entropy_test_add`.
## ##
## index: An arbitrary unique value that identifies a particular entropy ## handle: The opaque handle representing the entropy calculation state.
## computation.
## ##
## Returns: The result of the entropy test. See :bro:id:`find_entropy` for a ## Returns: The result of the entropy test. See :bro:id:`find_entropy` for a
## description of the individual components. ## description of the individual components.
## ##
## .. bro:see:: find_entropy entropy_test_init entropy_test_add ## .. bro:see:: find_entropy entropy_test_init entropy_test_add
function entropy_test_finish%(index: any%): entropy_test_result function entropy_test_finish%(handle: opaque of entropy%): entropy_test_result
%{ %{
BroString* s = convert_index_to_string(index);
double montepi, scc, ent, mean, chisq; double montepi, scc, ent, mean, chisq;
montepi = scc = ent = mean = chisq = 0.0; montepi = scc = ent = mean = chisq = 0.0;
static_cast<EntropyVal*>(handle)->Get(&ent, &chisq, &mean, &montepi, &scc);
RecordVal* ent_result = new RecordVal(entropy_test_result); RecordVal* ent_result = new RecordVal(entropy_test_result);
if ( entropy_states.count(*s) > 0 )
{
RandTest *rt = entropy_states[*s];
rt->end(&ent, &chisq, &mean, &montepi, &scc);
entropy_states.erase(*s);
delete rt;
}
ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); ent_result->Assign(0, new Val(ent, TYPE_DOUBLE));
ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE));
ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); ent_result->Assign(2, new Val(mean, TYPE_DOUBLE));
ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE));
ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); ent_result->Assign(4, new Val(scc, TYPE_DOUBLE));
delete s;
return ent_result; return ent_result;
%} %}
@ -2684,8 +2464,9 @@ function to_port%(s: string%): port
if ( s->Len() < 10 ) if ( s->Len() < 10 )
{ {
char* slash; char* slash;
errno = 0;
port = strtol(s->CheckString(), &slash, 10); port = strtol(s->CheckString(), &slash, 10);
if ( port ) if ( ! errno )
{ {
++slash; ++slash;
if ( streq(slash, "tcp") ) if ( streq(slash, "tcp") )

View file

@ -74,7 +74,9 @@ HEX [0-9a-fA-F]+
"set" return check_c_mode(TOK_SET); "set" return check_c_mode(TOK_SET);
"table" return check_c_mode(TOK_TABLE); "table" return check_c_mode(TOK_TABLE);
"vector" return check_c_mode(TOK_VECTOR); "vector" return check_c_mode(TOK_VECTOR);
"module" return check_c_mode(TOK_MODULE); "of" return check_c_mode(TOK_OF);
"opaque" return check_c_mode(TOK_OPAQUE);
"module" return check_c_mode(TOK_MODULE);
"@ARG@" return TOK_ARG; "@ARG@" return TOK_ARG;
"@ARGS@" return TOK_ARGS; "@ARGS@" return TOK_ARGS;

View file

@ -269,15 +269,15 @@ void print_event_c_body(FILE *fp)
%token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG
%token TOK_BOOL %token TOK_BOOL
%token TOK_FUNCTION TOK_EVENT TOK_CONST TOK_ENUM %token TOK_FUNCTION TOK_EVENT TOK_CONST TOK_ENUM TOK_OF
%token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_TABLE TOK_MODULE %token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_OPAQUE TOK_TABLE TOK_MODULE
%token TOK_ARGS TOK_ARG TOK_ARGC %token TOK_ARGS TOK_ARG TOK_ARGC
%token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT %token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT
%token TOK_ATOM TOK_INT TOK_C_TOKEN %token TOK_ATOM TOK_INT TOK_C_TOKEN
%left ',' ':' %left ',' ':'
%type <str> TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR TOK_INT opt_ws %type <str> TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR TOK_INT opt_ws type
%type <val> TOK_ATOM TOK_BOOL %type <val> TOK_ATOM TOK_BOOL
%union { %union {
@ -584,7 +584,17 @@ args_1: args_1 ',' opt_ws arg opt_ws
{ /* empty */ } { /* empty */ }
; ;
arg: TOK_ID opt_ws ':' opt_ws TOK_ID // TODO: Migrate all other compound types to this rule. Once the BiF language
// can parse all regular Bro types, we can throw out the unnecessary
// boilerplate typedefs for addr_set, string_set, etc.
type:
TOK_OPAQUE opt_ws TOK_OF opt_ws TOK_ID
{ $$ = concat("opaque of ", $5); }
| TOK_ID
{ $$ = $1; }
;
arg: TOK_ID opt_ws ':' opt_ws type
{ args.push_back(new BuiltinFuncArg($1, $5)); } { args.push_back(new BuiltinFuncArg($1, $5)); }
| TOK_VAR_ARG | TOK_VAR_ARG
{ {
@ -594,7 +604,7 @@ arg: TOK_ID opt_ws ':' opt_ws TOK_ID
} }
; ;
return_type: ':' opt_ws TOK_ID opt_ws return_type: ':' opt_ws type opt_ws
{ {
BuiltinFuncArg* ret = new BuiltinFuncArg("", $3); BuiltinFuncArg* ret = new BuiltinFuncArg("", $3);
ret->PrintBro(fp_bro_init); ret->PrintBro(fp_bro_init);

View file

@ -213,8 +213,6 @@ bool Ascii::GetLine(string& str)
return false; return false;
} }
// read the entire file and send appropriate thingies back to InputMgr // read the entire file and send appropriate thingies back to InputMgr
bool Ascii::DoUpdate() bool Ascii::DoUpdate()
{ {

View file

@ -11,7 +11,7 @@
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR %token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR
%token TOK_FUNCTION TOK_GLOBAL TOK_HOOK TOK_ID TOK_IF TOK_INT %token TOK_FUNCTION TOK_GLOBAL TOK_HOOK TOK_ID TOK_IF TOK_INT
%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE %token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE
%token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT %token TOK_NEXT TOK_OF TOK_OPAQUE TOK_PATTERN TOK_PATTERN_TEXT
%token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF %token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF
%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET %token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET
%token TOK_STRING TOK_SUBNET TOK_SWITCH TOK_TABLE %token TOK_STRING TOK_SUBNET TOK_SWITCH TOK_TABLE
@ -418,6 +418,14 @@ expr:
$$ = new IndexExpr($1, $3); $$ = new IndexExpr($1, $3);
} }
| expr '[' expr ':' expr ']'
{
set_location(@1, @6);
ListExpr* le = new ListExpr($3);
le->Append($5);
$$ = new IndexExpr($1, le, true);
}
| expr '$' TOK_ID | expr '$' TOK_ID
{ {
set_location(@1, @3); set_location(@1, @3);
@ -899,6 +907,12 @@ type:
$$ = new FileType(base_type(TYPE_STRING)); $$ = new FileType(base_type(TYPE_STRING));
} }
| TOK_OPAQUE TOK_OF TOK_ID
{
set_location(@1, @3);
$$ = new OpaqueType($3);
}
| resolve_id | resolve_id
{ {
if ( ! $1 || ! ($$ = $1->AsType()) ) if ( ! $1 || ! ($$ = $1->AsType()) )

View file

@ -298,6 +298,7 @@ local return TOK_LOCAL;
module return TOK_MODULE; module return TOK_MODULE;
next return TOK_NEXT; next return TOK_NEXT;
of return TOK_OF; of return TOK_OF;
opaque return TOK_OPAQUE;
pattern return TOK_PATTERN; pattern return TOK_PATTERN;
port return TOK_PORT; port return TOK_PORT;
print return TOK_PRINT; print return TOK_PRINT;

View file

@ -1,6 +1,9 @@
123/tcp 123/tcp
123/udp 123/udp
123/icmp 123/icmp
0/tcp
0/udp
0/icmp
0/unknown 0/unknown
256/tcp 256/tcp
256/udp 256/udp

View file

@ -0,0 +1,3 @@
[orig_h=1.2.0.2, orig_p=2527/tcp, resp_h=1.2.0.3, resp_p=6649/tcp]
orig:, [size=175, state=1, num_pkts=4, num_bytes_ip=395, flow_label=0]
resp:, [size=0, state=6, num_pkts=5, num_bytes_ip=236, flow_label=0]

View file

@ -0,0 +1,4 @@
acbd18db4cc2f85cedef654fccc4a4d8
0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
[entropy=0.918296, chi_square=423.666667, mean=108.0, monte_carlo_pi=nan, serial_correlation=-0.5]

View file

@ -0,0 +1,4 @@
acbd18db4cc2f85cedef654fccc4a4d8
0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
[entropy=0.918296, chi_square=423.666667, mean=108.0, monte_carlo_pi=nan, serial_correlation=-0.5]

View file

@ -0,0 +1,13 @@
error in ./invalid.bro, line 15: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 16: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 17: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 17: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 18: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 19: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 20: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 22: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 25: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 26: const is not a modifiable lvalue (baz)
error in ./invalid.bro, line 27: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 28: const is not a modifiable lvalue (baz)
error in ./invalid.bro, line 33: const is not a modifiable lvalue (foo)

View file

@ -0,0 +1,10 @@
40
enter f, 10
exit f, 110
enter f, 9
exit f, 109
enter f, 7
exit f, 107
foo, 10
bar, 9
baz, 7

View file

@ -3,6 +3,7 @@ myhook return F
myhook return T myhook return T
myhook, &priority=5, [a=37, b=goobye world] myhook, &priority=5, [a=37, b=goobye world]
F F
T
myhook3, 8 myhook3, 8
T T
myhook4, 2 myhook4, 2

View file

@ -0,0 +1,13 @@
1
12
123456
0123456789
8
789
9
9
9
2
1

View file

@ -0,0 +1 @@
done

View file

@ -0,0 +1 @@
error in /home/jsiwek/bro/testing/btest/.tmp/language.type-type-error/type-type-error.bro, line 13: not a record (r$a)

View file

@ -56,20 +56,20 @@ ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes
1300475167096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 73 0 0 1300475167096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 73 0 0
1300475167097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0 0 0 S0 F 0 D 1 199 0 0 1300475167097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0 0 0 S0 F 0 D 1 199 0 0
1300475167099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0 0 0 S0 F 0 D 1 179 0 0 1300475167099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0 0 0 S0 F 0 D 1 179 0 0
1300475168853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 435 0 89 SHR F 0 Cd 0 0 1 117 1300475168853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 435 38 89 SF F 0 Dd 1 66 1 117
1300475168854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 420 0 99 SHR F 0 Cd 0 0 1 127 1300475168854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 420 52 99 SF F 0 Dd 1 80 1 127
1300475168854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 391 0 183 SHR F 0 Cd 0 0 1 211 1300475168854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 391 38 183 SF F 0 Dd 1 66 1 211
1300475168857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 317 0 89 SHR F 0 Cd 0 0 1 117 1300475168857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 317 38 89 SF F 0 Dd 1 66 1 117
1300475168858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 343 0 99 SHR F 0 Cd 0 0 1 127 1300475168858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 343 52 99 SF F 0 Dd 1 80 1 127
1300475168858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 375 0 183 SHR F 0 Cd 0 0 1 211 1300475168858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 375 38 183 SF F 0 Dd 1 66 1 211
1300475168891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 339 0 89 SHR F 0 Cd 0 0 1 117 1300475168891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 339 38 89 SF F 0 Dd 1 66 1 117
1300475168892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 334 0 99 SHR F 0 Cd 0 0 1 127 1300475168892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 334 52 99 SF F 0 Dd 1 80 1 127
1300475168892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 420 0 183 SHR F 0 Cd 0 0 1 211 1300475168892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 420 38 183 SF F 0 Dd 1 66 1 211
1300475168893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 384 0 89 SHR F 0 Cd 0 0 1 117 1300475168893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 384 38 89 SF F 0 Dd 1 66 1 117
1300475168894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 316 0 99 SHR F 0 Cd 0 0 1 127 1300475168894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 316 52 99 SF F 0 Dd 1 80 1 127
1300475168894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 422 0 183 SHR F 0 Cd 0 0 1 211 1300475168894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 422 38 183 SF F 0 Dd 1 66 1 211
1300475168901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 402 0 131 SHR F 0 Cd 0 0 1 159 1300475168901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 402 36 131 SF F 0 Dd 1 64 1 159
1300475168902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 374 0 198 SHR F 0 Cd 0 0 1 226 1300475168902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 374 36 198 SF F 0 Dd 1 64 1 226
1300475169899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 85 0 0 1300475169899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 85 0 0
1300475170862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2613016 350 0 S0 F 0 D 7 546 0 0 1300475170862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2613016 350 0 S0 F 0 D 7 546 0 0
1300475171675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 100096 66 0 S0 F 0 D 2 162 0 0 1300475171675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 100096 66 0 S0 F 0 D 2 162 0 0
@ -77,13 +77,13 @@ ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes
1300475173116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 99801 66 0 S0 F 0 D 2 162 0 0 1300475173116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 99801 66 0 S0 F 0 D 2 162 0 0
1300475173117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 99848 66 0 S0 F 0 D 2 122 0 0 1300475173117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 99848 66 0 S0 F 0 D 2 122 0 0
1300475173153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0 0 0 S0 F 0 D 1 78 0 0 1300475173153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0 0 0 S0 F 0 D 1 78 0 0
1300475168859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp 215893 1130 734 S1 F 1130 ShACad 4 216 4 950 1300475168859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp http 215893 1130 734 S1 F 0 ShADad 6 1450 4 950
1300475168652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 61328 0 350 OTH F 0 CdA 1 52 1 402 1300475168652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 61328 463 350 OTH F 0 DdA 2 567 1 402
1300475168895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp 227283 1178 734 S1 F 1178 ShACad 4 216 4 950 1300475168895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp http 227283 1178 734 S1 F 0 ShADad 6 1498 4 950
1300475168902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp 120040 534 412 S1 F 534 ShACad 3 164 3 576 1300475168902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp http 120040 534 412 S1 F 0 ShADad 4 750 3 576
1300475168892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp 229603 1148 734 S1 F 1148 ShACad 4 216 4 950 1300475168892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp http 229603 1148 734 S1 F 0 ShADad 6 1468 4 950
1300475168855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp 218501 1171 733 S1 F 1171 ShACad 4 216 4 949 1300475168855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp http 218501 1171 733 S1 F 0 ShADad 6 1491 4 949
1300475168892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp 220960 1137 733 S1 F 1137 ShACad 4 216 4 949 1300475168892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp http 220960 1137 733 S1 F 0 ShADad 6 1457 4 949
1300475169780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0 0 0 OTH F 0 h 0 0 1 48 1300475169780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0 0 0 OTH F 0 h 0 0 1 48
1300475168724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp 119904 525 232 S1 F 525 ShACad 3 164 3 396 1300475168724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp http 119904 525 232 S1 F 0 ShADad 4 741 3 396
1300475168855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp 219720 1125 734 S1 F 1125 ShACad 4 216 4 950 1300475168855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp http 219720 1125 734 S1 F 0 ShADad 6 1445 4 950

View file

@ -56,20 +56,20 @@ ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes
1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 73 0 0 1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 73 0 0
1300475167.097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0.000000 0 0 S0 F 0 D 1 199 0 0 1300475167.097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0.000000 0 0 S0 F 0 D 1 199 0 0
1300475167.099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0.000000 0 0 S0 F 0 D 1 179 0 0 1300475167.099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0.000000 0 0 S0 F 0 D 1 179 0 0
1300475168.853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 0 89 SHR F 0 Cd 0 0 1 117 1300475168.853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF F 0 Dd 1 66 1 117
1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 0 99 SHR F 0 Cd 0 0 1 127 1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF F 0 Dd 1 80 1 127
1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 0 183 SHR F 0 Cd 0 0 1 211 1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF F 0 Dd 1 66 1 211
1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 0 89 SHR F 0 Cd 0 0 1 117 1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF F 0 Dd 1 66 1 117
1300475168.858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 0 99 SHR F 0 Cd 0 0 1 127 1300475168.858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 52 99 SF F 0 Dd 1 80 1 127
1300475168.858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 0 183 SHR F 0 Cd 0 0 1 211 1300475168.858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 38 183 SF F 0 Dd 1 66 1 211
1300475168.891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 0 89 SHR F 0 Cd 0 0 1 117 1300475168.891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 38 89 SF F 0 Dd 1 66 1 117
1300475168.892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 0 99 SHR F 0 Cd 0 0 1 127 1300475168.892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 52 99 SF F 0 Dd 1 80 1 127
1300475168.892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 0 183 SHR F 0 Cd 0 0 1 211 1300475168.892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 38 183 SF F 0 Dd 1 66 1 211
1300475168.893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 0 89 SHR F 0 Cd 0 0 1 117 1300475168.893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 38 89 SF F 0 Dd 1 66 1 117
1300475168.894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 0 99 SHR F 0 Cd 0 0 1 127 1300475168.894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 52 99 SF F 0 Dd 1 80 1 127
1300475168.894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 0 183 SHR F 0 Cd 0 0 1 211 1300475168.894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 38 183 SF F 0 Dd 1 66 1 211
1300475168.901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 0 131 SHR F 0 Cd 0 0 1 159 1300475168.901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 36 131 SF F 0 Dd 1 64 1 159
1300475168.902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 0 198 SHR F 0 Cd 0 0 1 226 1300475168.902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 36 198 SF F 0 Dd 1 64 1 226
1300475169.899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 85 0 0 1300475169.899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 85 0 0
1300475170.862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2.613017 350 0 S0 F 0 D 7 546 0 0 1300475170.862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2.613017 350 0 S0 F 0 D 7 546 0 0
1300475171.675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 0.100096 66 0 S0 F 0 D 2 162 0 0 1300475171.675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 0.100096 66 0 S0 F 0 D 2 162 0 0
@ -77,13 +77,13 @@ ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes
1300475173.116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 0.099801 66 0 S0 F 0 D 2 162 0 0 1300475173.116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 0.099801 66 0 S0 F 0 D 2 162 0 0
1300475173.117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 0.099849 66 0 S0 F 0 D 2 122 0 0 1300475173.117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 0.099849 66 0 S0 F 0 D 2 122 0 0
1300475173.153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0.000000 0 0 S0 F 0 D 1 78 0 0 1300475173.153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0.000000 0 0 S0 F 0 D 1 78 0 0
1300475168.859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp 0.215893 1130 734 S1 F 1130 ShACad 4 216 4 950 1300475168.859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp http 0.215893 1130 734 S1 F 0 ShADad 6 1450 4 950
1300475168.652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 0.061329 0 350 OTH F 0 CdA 1 52 1 402 1300475168.652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 0.061329 463 350 OTH F 0 DdA 2 567 1 402
1300475168.895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp 0.227284 1178 734 S1 F 1178 ShACad 4 216 4 950 1300475168.895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp http 0.227284 1178 734 S1 F 0 ShADad 6 1498 4 950
1300475168.902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp 0.120041 534 412 S1 F 534 ShACad 3 164 3 576 1300475168.902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp http 0.120041 534 412 S1 F 0 ShADad 4 750 3 576
1300475168.892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp 0.229603 1148 734 S1 F 1148 ShACad 4 216 4 950 1300475168.892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp http 0.229603 1148 734 S1 F 0 ShADad 6 1468 4 950
1300475168.855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp 0.218501 1171 733 S1 F 1171 ShACad 4 216 4 949 1300475168.855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp http 0.218501 1171 733 S1 F 0 ShADad 6 1491 4 949
1300475168.892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp 0.220961 1137 733 S1 F 1137 ShACad 4 216 4 949 1300475168.892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp http 0.220961 1137 733 S1 F 0 ShADad 6 1457 4 949
1300475169.780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0.000000 0 0 OTH F 0 h 0 0 1 48 1300475169.780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0.000000 0 0 OTH F 0 h 0 0 1 48
1300475168.724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp 0.119905 525 232 S1 F 525 ShACad 3 164 3 396 1300475168.724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp http 0.119905 525 232 S1 F 0 ShADad 4 741 3 396
1300475168.855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp 0.219720 1125 734 S1 F 1125 ShACad 4 216 4 950 1300475168.855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp http 0.219720 1125 734 S1 F 0 ShADad 6 1445 4 950

View file

@ -65,17 +65,17 @@
# Extent, type='http' # Extent, type='http'
ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file
1300475168.843894 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 0 0 0 304 Not Modified 0 1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475168.975800 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475168.976327 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475168.979160 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.918358 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.012666 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.952307 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.012730 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.952296 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.014860 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.954820 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.022665 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 0 0 0 304 Not Modified 0 1300475168.962687 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.036294 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.975934 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.036798 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.976436 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.039923 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475168.979264 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.074793 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475169.014619 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.074938 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475169.014593 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0
1300475169.075065 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 0 0 0 304 Not Modified 0 1300475169.014927 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0

Binary file not shown.

Binary file not shown.

View file

@ -5,20 +5,14 @@
event bro_init() event bro_init()
{ {
local a = "dh3Hie02uh^s#Sdf9L3frd243h$d78r2G4cM6*Q05d(7rh46f!0|4-f"; local a = "dh3Hie02uh^s#Sdf9L3frd243h$d78r2G4cM6*Q05d(7rh46f!0|4-f";
if ( entropy_test_init(1) != T ) local handle = entropy_test_init();
if ( ! entropy_test_add(handle, a) )
exit(1); exit(1);
print entropy_test_finish(handle);
if ( entropy_test_add(1, a) != T )
exit(1);
print entropy_test_finish(1);
local b = "0011000aaabbbbcccc000011111000000000aaaabbbbcccc0000000"; local b = "0011000aaabbbbcccc000011111000000000aaaabbbbcccc0000000";
if ( entropy_test_init(2) != T ) handle = entropy_test_init();
if ( ! entropy_test_add(handle, b) )
exit(1); exit(1);
print entropy_test_finish(handle);
if ( entropy_test_add(2, b) != T )
exit(1);
print entropy_test_finish(2);
} }

View file

@ -4,16 +4,16 @@
print md5_hash("one"); print md5_hash("one");
print md5_hash("one", "two", "three"); print md5_hash("one", "two", "three");
md5_hash_init("a"); local a = md5_hash_init();
md5_hash_init("b"); local b = md5_hash_init();
md5_hash_update("a", "one"); md5_hash_update(a, "one");
md5_hash_update("b", "one"); md5_hash_update(b, "one");
md5_hash_update("b", "two"); md5_hash_update(b, "two");
md5_hash_update("b", "three"); md5_hash_update(b, "three");
print md5_hash_finish("a"); print md5_hash_finish(a);
print md5_hash_finish("b"); print md5_hash_finish(b);
print md5_hmac("one"); print md5_hmac("one");
print md5_hmac("one", "two", "three"); print md5_hmac("one", "two", "three");

View file

@ -4,13 +4,13 @@
print sha1_hash("one"); print sha1_hash("one");
print sha1_hash("one", "two", "three"); print sha1_hash("one", "two", "three");
sha1_hash_init("a"); local a = sha1_hash_init();
sha1_hash_init("b"); local b = sha1_hash_init();
sha1_hash_update("a", "one"); sha1_hash_update(a, "one");
sha1_hash_update("b", "one"); sha1_hash_update(b, "one");
sha1_hash_update("b", "two"); sha1_hash_update(b, "two");
sha1_hash_update("b", "three"); sha1_hash_update(b, "three");
print sha1_hash_finish("a"); print sha1_hash_finish(a);
print sha1_hash_finish("b"); print sha1_hash_finish(b);

View file

@ -4,13 +4,13 @@
print sha256_hash("one"); print sha256_hash("one");
print sha256_hash("one", "two", "three"); print sha256_hash("one", "two", "three");
sha256_hash_init("a"); local a = sha256_hash_init();
sha256_hash_init("b"); local b = sha256_hash_init();
sha256_hash_update("a", "one"); sha256_hash_update(a, "one");
sha256_hash_update("b", "one"); sha256_hash_update(b, "one");
sha256_hash_update("b", "two"); sha256_hash_update(b, "two");
sha256_hash_update("b", "three"); sha256_hash_update(b, "three");
print sha256_hash_finish("a"); print sha256_hash_finish(a);
print sha256_hash_finish("b"); print sha256_hash_finish(b);

View file

@ -7,6 +7,9 @@ event bro_init()
print to_port("123/tcp"); print to_port("123/tcp");
print to_port("123/udp"); print to_port("123/udp");
print to_port("123/icmp"); print to_port("123/icmp");
print to_port("0/tcp");
print to_port("0/udp");
print to_port("0/icmp");
print to_port("not a port"); print to_port("not a port");
local a: transport_proto = tcp; local a: transport_proto = tcp;

View file

@ -0,0 +1,26 @@
# Needs perftools support.
#
# @TEST-GROUP: leaks
#
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
#
# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -b -r $TRACES/wikipedia.trace %INPUT
event new_connection(c: connection)
{
local s = "0123456789";
print s[1];
print s[1:2];
print s[1:6];
print s[0:20];
print s[-2];
print s[-3:1];
print s[-1:10];
print s[-1:0];
print s[-1:5];
print s[20:23];
print s[-20:23];
print s[0:5][2];
print s[0:5][1:3][0];
}

View file

@ -0,0 +1,289 @@
# Needs perftools support.
#
# @TEST-GROUP: leaks
#
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
#
# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -b -r $TRACES/wikipedia.trace %INPUT
type MyEnum: enum {
RED,
GREEN,
BLUE,
PINK,
};
function switch_bool(v: bool): string
{
switch (v) {
case T:
return "true";
case F:
return "false";
}
return "n/a";
}
function switch_int(v: int): string
{
switch (v) {
case +1:
return "one";
case +2:
return "two";
case -3:
return "minus three";
}
return "n/a";
}
function switch_enum(v: MyEnum): string
{
switch (v) {
case RED:
return "red";
case GREEN:
return "green";
case BLUE:
return "blue";
}
return "n/a";
}
function switch_count(v: count): string
{
switch (v) {
case 1:
return "1";
case 2:
return "2";
case 3:
return "3";
}
return "n/a";
}
function switch_port(v: port): string
{
switch (v) {
case 22/tcp:
return "ssh";
case 53/udp:
return "dns";
case 0/icmp:
return "echo";
}
return "n/a";
}
function switch_double(v: double): string
{
switch (v) {
case 1.1:
return "1.1";
case 2.2:
return "2.2";
case 3.3:
return "3.3";
}
return "n/a";
}
function switch_interval(v: interval): string
{
switch (v) {
case 1sec:
return "1sec";
case 2day:
return "2day";
case 3min:
return "3min";
}
return "n/a";
}
function switch_string(v: string): string
{
switch (v) {
case "one":
return "first";
case "two":
return "second";
case "three":
return "third";
}
return "n/a";
}
function switch_addr(v: addr): string
{
switch (v) {
case 1.2.3.4:
return "ipv4";
case [fe80::1]:
return "ipv6";
case 0.0.0.0:
return "unspec";
}
return "n/a";
}
function switch_subnet(v: subnet): string
{
switch (v) {
case 1.2.3.0/24:
return "1.2.3.0/24";
case [fe80::0]/96:
return "[fe80::0]";
case 192.168.0.0/16:
return "192.168.0.0/16";
}
return "n/a";
}
function switch_empty(v: count): string
{
switch ( v ) {
}
return "n/a";
}
function switch_break(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "test";
case 2:
rval += "testing";
break;
case 3:
rval += "tested";
}
return rval + "return";
}
function switch_default(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "1";
case 2:
rval += "2";
case 3:
rval += "3";
default:
rval += "d";
}
return rval + "r";
}
function switch_default_placement(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "1";
default:
rval += "d";
case 2:
rval += "2";
break;
case 3:
rval += "3";
}
return rval + "r";
}
function switch_case_list(v: count): string
{
switch ( v ) {
case 1, 2:
return "1,2";
case 3, 4, 5:
return "3,4,5";
case 6, 7, 8, 9:
return "6,7,8,9";
}
return "n/a";
}
function test_switch(actual: string, expect: string)
{
if ( actual != expect )
print fmt("%s != %s", actual, expect);
}
event new_connection(c: connection)
{
test_switch( switch_bool(T) , "true" );
test_switch( switch_bool(F) , "false" );
test_switch( switch_int(+1) , "one" );
test_switch( switch_int(+2) , "two" );
test_switch( switch_int(-3) , "minus three" );
test_switch( switch_int(40) , "n/a" );
test_switch( switch_enum(RED) , "red" );
test_switch( switch_enum(BLUE) , "blue" );
test_switch( switch_enum(GREEN) , "green" );
test_switch( switch_enum(PINK) , "n/a" );
test_switch( switch_count(1) , "1" );
test_switch( switch_count(2) , "2" );
test_switch( switch_count(3) , "3" );
test_switch( switch_count(100) , "n/a" );
test_switch( switch_port(22/tcp) , "ssh" );
test_switch( switch_port(53/udp) , "dns" );
test_switch( switch_port(0/icmp) , "echo" );
test_switch( switch_port(1000/tcp) , "n/a" );
test_switch( switch_double(1.1) , "1.1" );
test_switch( switch_double(2.2) , "2.2" );
test_switch( switch_double(3.3) , "3.3" );
test_switch( switch_interval(1sec) , "1sec" );
test_switch( switch_interval(2day) , "2day" );
test_switch( switch_interval(3min) , "3min" );
test_switch( switch_string("one") , "first" );
test_switch( switch_string("two") , "second" );
test_switch( switch_string("three") , "third" );
test_switch( switch_addr(1.2.3.4) , "ipv4" );
test_switch( switch_addr([fe80::1]) , "ipv6" );
test_switch( switch_addr(0.0.0.0) , "unspec" );
test_switch( switch_subnet(1.2.3.4/24) , "1.2.3.0/24" );
test_switch( switch_subnet([fe80::1]/96) , "[fe80::0]" );
test_switch( switch_subnet(192.168.1.100/16) , "192.168.0.0/16" );
test_switch( switch_empty(2) , "n/a" );
test_switch( switch_break(1) , "testtestingreturn" );
test_switch( switch_break(2) , "testingreturn" );
test_switch( switch_break(3) , "testedreturn" );
test_switch( switch_default(1) , "123dr" );
test_switch( switch_default(2) , "23dr" );
test_switch( switch_default(3) , "3dr" );
test_switch( switch_default(4) , "dr" );
test_switch( switch_default_placement(1) , "1d2r" );
test_switch( switch_default_placement(2) , "2r" );
test_switch( switch_default_placement(3) , "3r" );
test_switch( switch_default_placement(4) , "d2r" );
local v = vector(0,1,2,3,4,5,6,7,9,10);
local expect: string;
for ( i in v )
{
switch ( v[i] ) {
case 1, 2:
expect = "1,2";
break;
case 3, 4, 5:
expect = "3,4,5";
break;
case 6, 7, 8, 9:
expect = "6,7,8,9";
break;
default:
expect = "n/a";
break;
}
test_switch( switch_case_list(v[i]) , expect );
}
print "done";
}

View file

@ -0,0 +1,12 @@
# @TEST-EXEC: bro -b -r $TRACES/tcp/rst-inject-rae.trace %INPUT
# @TEST-EXEC: btest-diff .stdout
# Mostly just checking that c$resp$size isn't huge due to the injected
# RST packet being used to initialize sequence number in TCP analyzer.
event connection_state_remove(c: connection)
{
print c$id;
print "orig:", c$orig;
print "resp:", c$resp;
}

View file

@ -0,0 +1,77 @@
#
# @TEST-EXEC: bro -r $TRACES/empty.trace write.bro
# @TEST-EXEC: bro read.bro
# @TEST-EXEC: btest-diff expected.log
# @TEST-EXEC: btest-diff output.log
# @TEST-EXEC: cmp output.log expected.log
@TEST-START-FILE read.bro
global md5_handle: opaque of md5 &persistent &synchronized;
global sha1_handle: opaque of sha1 &persistent &synchronized;
global sha256_handle: opaque of sha256 &persistent &synchronized;
global entropy_handle: opaque of entropy &persistent &synchronized;
event bro_done()
{
local out = open("output.log");
# Finish incremental operations started by a previous Bro.
if ( md5_hash_update(md5_handle, "oo") )
print out, md5_hash_finish(md5_handle);
else
print out, "md5_hash_update() failed";
if ( sha1_hash_update(sha1_handle, "oo") )
print out, sha1_hash_finish(sha1_handle);
else
print out, "sha1_hash_update() failed";
if ( sha256_hash_update(sha256_handle, "oo") )
print out, sha256_hash_finish(sha256_handle);
else
print out, "sha256_hash_update() failed";
if ( entropy_test_add(entropy_handle, "oo") )
print out, entropy_test_finish(entropy_handle);
else
print out, "entropy_test_add() failed";
}
@TEST-END-FILE
@TEST-START-FILE write.bro
global md5_handle: opaque of md5 &persistent &synchronized;
global sha1_handle: opaque of sha1 &persistent &synchronized;
global sha256_handle: opaque of sha256 &persistent &synchronized;
global entropy_handle: opaque of entropy &persistent &synchronized;
event bro_init()
{
local out = open("expected.log");
print out, md5_hash("foo");
print out, sha1_hash("foo");
print out, sha256_hash("foo");
print out, find_entropy("foo");
# Begin incremental operations. Our goal is to feed the data string "foo" to
# the computation, but split into "f" and "oo" in two instances..
md5_handle = md5_hash_init();
if ( ! md5_hash_update(md5_handle, "f") )
print out, "md5_hash_update() failed";
sha1_handle = sha1_hash_init();
if ( ! sha1_hash_update(sha1_handle, "f") )
print out, "sha1_hash_update() failed";
sha256_handle = sha256_hash_init();
if ( ! sha256_hash_update(sha256_handle, "f") )
print out, "sha256_hash_update() failed";
entropy_handle = entropy_test_init();
if ( ! entropy_test_add(entropy_handle, "f") )
print out, "entropy_test_add() failed";
}
@TEST-END-FILE

View file

@ -0,0 +1,79 @@
# @TEST-EXEC: bro -b valid.bro 2>valid.stderr 1>valid.stdout
# @TEST-EXEC: btest-diff valid.stderr
# @TEST-EXEC: btest-diff valid.stdout
# @TEST-EXEC-FAIL: bro -b invalid.bro 2>invalid.stderr 1>invalid.stdout
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff invalid.stderr
# @TEST-EXEC: btest-diff invalid.stdout
@TEST-START-FILE valid.bro
# First some simple code that should be valid and error-free.
function f(c: count)
{
print "enter f", c;
c = c + 100;
print "exit f", c;
}
const foo = 0 &redef;
redef foo = 10;
const bar = 9;
event bro_init()
{
const baz = 7;
local i = foo;
i = i + bar + 2;
i = i + baz + 11;
++i;
print i;
--i;
f(foo);
f(bar);
f(baz);
print "foo", foo;
print "bar", bar;
print "baz", baz;
}
@TEST-END-FILE
@TEST-START-FILE invalid.bro
# Now some const assignments that should generate errors at parse-time.
const foo = 0 &redef;
redef foo = 10;
const bar = 9;
event bro_init()
{
const baz = 7;
local s = 0;
print "nope";
foo = 100;
foo = bar;
foo = bar = baz;
foo = s;
++foo;
s = foo = bar;
if ( foo = 0 )
print "nope";
bar = 1 + 1;
baz = s;
++bar;
--baz;
print "foo", foo;
print "bar", bar;
print "baz", baz;
print "foo=foo", foo = foo;
}
@TEST-END-FILE

View file

@ -0,0 +1,17 @@
# @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: btest-diff out
local s = "0123456789";
print s[1];
print s[1:2];
print s[1:6];
print s[0:20];
print s[-2];
print s[-3:-1];
print s[-1:-10];
print s[-1:0];
print s[-1:5];
print s[20:23];
print s[-20:23];
print s[0:5][2];
print s[0:5][1:3][0];

View file

@ -0,0 +1,284 @@
# @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: btest-diff out
type MyEnum: enum {
RED,
GREEN,
BLUE,
PINK,
};
function switch_bool(v: bool): string
{
switch (v) {
case T:
return "true";
case F:
return "false";
}
return "n/a";
}
function switch_int(v: int): string
{
switch (v) {
case +1:
return "one";
case +2:
return "two";
case -3:
return "minus three";
}
return "n/a";
}
function switch_enum(v: MyEnum): string
{
switch (v) {
case RED:
return "red";
case GREEN:
return "green";
case BLUE:
return "blue";
}
return "n/a";
}
function switch_count(v: count): string
{
switch (v) {
case 1:
return "1";
case 2:
return "2";
case 3:
return "3";
}
return "n/a";
}
function switch_port(v: port): string
{
switch (v) {
case 22/tcp:
return "ssh";
case 53/udp:
return "dns";
case 0/icmp:
return "echo";
}
return "n/a";
}
function switch_double(v: double): string
{
switch (v) {
case 1.1:
return "1.1";
case 2.2:
return "2.2";
case 3.3:
return "3.3";
}
return "n/a";
}
function switch_interval(v: interval): string
{
switch (v) {
case 1sec:
return "1sec";
case 2day:
return "2day";
case 3min:
return "3min";
}
return "n/a";
}
function switch_string(v: string): string
{
switch (v) {
case "one":
return "first";
case "two":
return "second";
case "three":
return "third";
}
return "n/a";
}
function switch_addr(v: addr): string
{
switch (v) {
case 1.2.3.4:
return "ipv4";
case [fe80::1]:
return "ipv6";
case 0.0.0.0:
return "unspec";
}
return "n/a";
}
function switch_subnet(v: subnet): string
{
switch (v) {
case 1.2.3.0/24:
return "1.2.3.0/24";
case [fe80::0]/96:
return "[fe80::0]";
case 192.168.0.0/16:
return "192.168.0.0/16";
}
return "n/a";
}
function switch_empty(v: count): string
{
switch ( v ) {
}
return "n/a";
}
function switch_break(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "test";
case 2:
rval += "testing";
break;
case 3:
rval += "tested";
}
return rval + "return";
}
function switch_default(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "1";
case 2:
rval += "2";
case 3:
rval += "3";
default:
rval += "d";
}
return rval + "r";
}
function switch_default_placement(v: count): string
{
local rval = "";
switch ( v ) {
case 1:
rval += "1";
default:
rval += "d";
case 2:
rval += "2";
break;
case 3:
rval += "3";
}
return rval + "r";
}
function switch_case_list(v: count): string
{
switch ( v ) {
case 1, 2:
return "1,2";
case 3, 4, 5:
return "3,4,5";
case 6, 7, 8, 9:
return "6,7,8,9";
}
return "n/a";
}
function test_switch(actual: string, expect: string)
{
if ( actual != expect )
print fmt("%s != %s", actual, expect);
}
event bro_init()
{
test_switch( switch_bool(T) , "true" );
test_switch( switch_bool(F) , "false" );
test_switch( switch_int(+1) , "one" );
test_switch( switch_int(+2) , "two" );
test_switch( switch_int(-3) , "minus three" );
test_switch( switch_int(40) , "n/a" );
test_switch( switch_enum(RED) , "red" );
test_switch( switch_enum(BLUE) , "blue" );
test_switch( switch_enum(GREEN) , "green" );
test_switch( switch_enum(PINK) , "n/a" );
test_switch( switch_count(1) , "1" );
test_switch( switch_count(2) , "2" );
test_switch( switch_count(3) , "3" );
test_switch( switch_count(100) , "n/a" );
test_switch( switch_port(22/tcp) , "ssh" );
test_switch( switch_port(53/udp) , "dns" );
test_switch( switch_port(0/icmp) , "echo" );
test_switch( switch_port(1000/tcp) , "n/a" );
test_switch( switch_double(1.1) , "1.1" );
test_switch( switch_double(2.2) , "2.2" );
test_switch( switch_double(3.3) , "3.3" );
test_switch( switch_interval(1sec) , "1sec" );
test_switch( switch_interval(2day) , "2day" );
test_switch( switch_interval(3min) , "3min" );
test_switch( switch_string("one") , "first" );
test_switch( switch_string("two") , "second" );
test_switch( switch_string("three") , "third" );
test_switch( switch_addr(1.2.3.4) , "ipv4" );
test_switch( switch_addr([fe80::1]) , "ipv6" );
test_switch( switch_addr(0.0.0.0) , "unspec" );
test_switch( switch_subnet(1.2.3.4/24) , "1.2.3.0/24" );
test_switch( switch_subnet([fe80::1]/96) , "[fe80::0]" );
test_switch( switch_subnet(192.168.1.100/16) , "192.168.0.0/16" );
test_switch( switch_empty(2) , "n/a" );
test_switch( switch_break(1) , "testtestingreturn" );
test_switch( switch_break(2) , "testingreturn" );
test_switch( switch_break(3) , "testedreturn" );
test_switch( switch_default(1) , "123dr" );
test_switch( switch_default(2) , "23dr" );
test_switch( switch_default(3) , "3dr" );
test_switch( switch_default(4) , "dr" );
test_switch( switch_default_placement(1) , "1d2r" );
test_switch( switch_default_placement(2) , "2r" );
test_switch( switch_default_placement(3) , "3r" );
test_switch( switch_default_placement(4) , "d2r" );
local v = vector(0,1,2,3,4,5,6,7,9,10);
local expect: string;
for ( i in v )
{
switch ( v[i] ) {
case 1, 2:
expect = "1,2";
break;
case 3, 4, 5:
expect = "3,4,5";
break;
case 6, 7, 8, 9:
expect = "6,7,8,9";
break;
default:
expect = "n/a";
break;
}
test_switch( switch_case_list(v[i]) , expect );
}
print "done";
}

View file

@ -0,0 +1,14 @@
# @TEST-EXEC-FAIL: bro -b %INPUT
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr
type r: record {
a: string;
};
event bro_init()
{
# This should generate a parse error indicating that the type identifier
# is incorrectly used in an expression expecting a real value and not
# a value of type TypeType.
print r$a;
}