Contents
# ADD THIS TO bro.init policy # Types for bif-test. We will access these types # from C++ # We need to define them in bro.init, because the type definition # (from the .bro) must be parsed for each Zeek run # Add to bro.init type test_record : record { a: count; }; type test_set : set[count]; type test_table : table[count] of count; type test_vector: vector of count; module XYZ; export { # this needs to be in an export block! type barbar: record { bar: count; }; const the_answer = 23 &redef; const the_time_diff = 10 sec &redef; global mydt = 42msec; } # switch back to the global module namespace module GLOBAL; type foobar : record { bar: count; foo: count; }; global dummy = "global"; const constdummy = "i am const" &redef; const fb1 : foobar = [ $bar=1, $foo=2 ]; global fb2: foobar = [ $bar=3, $foo=4 ];
# ADD THIS TO const.bif # Const declarations for bif test const XYZ::the_answer : count; const XYZ::the_time_diff : interval; const constdummy: string; const fb1: foobar; # ERROR: dummy is defined as non-const global: const dummy : string;
# ADD THIS TO types.bif
# type declartion for policy <--> C++ interaction
type test_record: record;
type test_set: set;
type test_table: table;
type test_vector: vector;
# Set a module name
module FOO;
# The enum type "status" and all the enumerators (s1..s3) will
# be in the FOO namespace.
enum status %{
s1 = 1,
s2 = 2,
s3 = 3,
%}
# We can also use a fully qualified name
# However, this does *not* work for enums.
type XYZ::barbar : record;
# GLOBAL is a special built-in pseudo-module that represents
# no module, the global namespace
module GLOBAL;
type foobar : record;
# ADD THIS TO event.bif # Events for demonstrating C++ <--> policy interaction event bif_test_event%(msg: string, s: FOO::status, fb: foobar%); event FOO::bif_test_event%(dt: interval%);
# bif-test.bro @load bif-test-xyz @load bif-test-foo event bro_init() { local e : FOO::status; e = FOO::s2; print "In bro.init "; print fmt("e=%s", e); gmm_doit("called from file bif-test.bro"); XYZ::gmm_doit("called from file bif-test.bro (with fully qualified name)"); FOO::gmm_doit("called from file bif-test.bro (with fully qualified name)"); # call the bif that will then generate bif_test_event and FOO::bif_test_event do_bif_test(); # show how the interaction with C++ works local fb: foobar = [ $bar = 999, $foo=888 ]; interaction(12, -4, fb, e); print fmt("Now let's check the new value of the global fb2"); print fmt(" %s", fb2); print "----"; } event bif_test_event(msg: string, s: FOO::status, fb: foobar) { print fmt("bif_test_event: %s, %s, %s", msg, s, fb); }
# bif-test-foo.bro module FOO; event bro_init() { print "bif-test-foo.bro: in bro_init"; gmm_doit("called from file bif-test-foo.bro"); print "----"; } event FOO::bif_test_event(dt: interval) { print fmt("event FOO:bif_test_event: dt=%.6f", dt); }
# bif-test-xyz.bro module XYZ; event bro_init() { print "bif-test-xyz.bro: in bro_init"; gmm_doit("called from file bif-test-xzy.bro"); print "----"; }
# ADD THIS TO THE END OF bro.bif
# demonstrating C++ policy interaction and namespaces:
#
# using a module definition
module FOO;
function gmm_doit%(msg: string%): any
%{
cout << "FOO::gmm_doit(): ";
cout << msg->CheckString();
cout << "\n";
return 0;
%}
# switching back to using the global namespace
module GLOBAL;
function gmm_doit%(msg: string%): any
%{
cout << "gmm_doit(): ";
cout << msg->CheckString();
cout << "\n";
return 0;
%}
# we can also use a fully qualified identifier.
function XYZ::gmm_doit%(msg: string%): any
%{
cout << "XYZ::gmm_doit(): ";
cout << msg->CheckString();
cout << "\n";
return 0;
%}
#
# This demonstrates how to "generate" or raise an event from a bif
# (or more general: from the C++ layer)
function do_bif_test%(%): any
%{
// Check whether there's an event handler defined.
// This currently lives in the global namespace for backwards comaptability
// eventually bif_test_event will be in a namespace of its own
if (bif_test_event)
{
// Now lets pack the arguments together and dispatch the event
val_list *vl = new val_list;
vl->append(new StringVal("Hello, World!"));
// Assigning FOO::s2 to the enum
// We can use BifTypePtr::Enum::FOO::status thanks to the
// type status: record; declaration in types.bif
// BifTypePtr::Enum::FOO::status if an EnumType*, see Type.h
// EnumVal (and other Vals) is defined in Val.{cc|h}
vl->append(new EnumVal((BifEnum::FOO::s2), BifTypePtr::Enum::FOO::status));
// Now we need to put something into the record:
RecordVal* fb = new RecordVal(BifTypePtr::Record::foobar);
fb->Assign(0, new Val(123, TYPE_COUNT)); // assign 123 to the first field (bar)
// We can also use the field's name. You should use this if you are
// accessing fields that have been extended with +=
int offset_of_foo = BifTypePtr::Record::foobar->FieldOffset("foo");
if (offset_of_foo < 0)
reporter->InternalError("Field foo does not exist in record type");
fb->Assign(offset_of_foo, new Val(456, TYPE_COUNT));
vl->append(fb);
mgr.QueueEvent(bif_test_event, vl);
}
// Now raising an event with a module/namespace qualifier
// We need the global namespace qualifier :: at the beginning, because
// there this function is in the BifFunc namespace and there is a
// BifFunc::FOO namespace.
if (::FOO::bif_test_event)
{
val_list *vl = new val_list;
vl->append(new IntervalVal(42.23, Milliseconds));
mgr.QueueEvent(::FOO::bif_test_event, vl);
}
return 0;
%}
#
# This function demonstrates how we can access arguments, consts and
# globals from a bif.
# Note: you always have to use fully qualified type, const and variable names
# even if the bif function is in the same namespace than the
# access type.
# bif_type.def shows how Zeek bif-types are translated to c-types.
# You can also look at the generated <NAME>.bif.func_def files, this
# shows you how the bif arguments are translated into c types
# See also Val.h and Type.h
function interaction%(a: count, b: int, fb: foobar, s: FOO::status %) : any
%{
printf("builtin function interaction: arguments:\n");
printf("\ta = %"PRIu64"\n", a); // a is a bro_uint_t, which is 64bit
printf("\tb = %"PRId64"\n", b); // a is a bro_int_t, which is 64bit
bro_uint_t fb_bar, fb_foo;
// fb is a Val *
// fb->AsRecordVal()->Lookup(i) looks up field i and returns the associated Val*
fb_bar = fb->AsRecordVal()->Lookup(0)->AsCount();
fb_foo = fb->AsRecordVal()->Lookup(1)->AsCount();
printf("\tfb = [$bar=%"PRIu64", $foo=%"PRIu64"]\n", fb_bar, fb_foo);
// s is a generic Val *
// s->AsEnum() returns an int (not a bro_int_t)
printf("\ts = %d\n", s->AsEnum());
printf("Now accessing constants\n");
printf("\tXYZ::the_answer = %"PRIu64"\n", BifConst::XYZ::the_answer); // a bro_uint_t
printf("\tXYZ::the_time_diff = %.6f\n", BifConst::XYZ::the_time_diff); // a double
printf("\tconstdummy = \"%s\"\n", BifConst::constdummy->CheckString());
fb_bar = BifConst::fb1->AsRecordVal()->Lookup(0)->AsCount();
fb_foo = BifConst::fb1->AsRecordVal()->Lookup(1)->AsCount();
printf("\tfb1 = [$bar=%"PRIu64", $foo=%"PRIu64"]\n", fb_bar, fb_foo);
printf("Now accessing globals\n");
printf("\tXYZ::mydt = %.6f\n", internal_val("XYZ::mydt")->AsInterval()); // a double
printf("\tdummy = \"%s\"\n", internal_val("dummy")->AsStringVal()->CheckString());
RecordVal *fb2 = internal_val("fb2")->AsRecordVal();
fb_bar = fb2->Lookup(0)->AsCount();
fb_foo = fb2->Lookup(1)->AsCount();
printf("\tfb2 = [$bar=%"PRIu64", $foo=%"PRIu64"]\n", fb_bar, fb_foo);
// We now want to modify fb
fb2->Assign(0, new Val(31337, TYPE_COUNT));
return 0;
%}
© 2014 The Bro Project.
