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.