Cool -- that did the trick.  This is really good stuff.

I decided to try using this against other bro events, besides just bro_init():

$ cat exec-test.bro
@load ./exec

event dns_message(c: connection, is_orig: bool, msg: dns_msg, len: count)
        {
        Exec::run("./hello", function(r: Exec::Result)
                {
                if ( ! r?$stdout )
                        {
                        print "nothing?!?";
                        return;
                        }

                for ( i in r$stdout )
                        {
                        print r$stdout[i];
                        }
                });
        }

./hello is just a hello world program.

So, when I test that, I see the following.

$ bro -r test.pcap exec-test.bro
Hello World
Hello World
Hello World
nothing?!?
ERROR: 1361476370.202590 no such index (Exec::results[Exec::name]) (././exec.bro, line 25)
[...]


This got me wondering -- why would exec-test.bro ever have a case where (! r?$stdout) is true, when I have a program that absolutely returns output every time it's run? (And then print out "nothing?!?")

For convenience:
# exec.bro
 21 event Exec::stdout_line(description: Input::EventDescription, tpe: Input::Event, s: string)
 22         {
 23         local name = sub(description$name, /_[^_]*$/, "");
 24
 25         if ( ! results[name]?$stdout )
 26                 results[name]$stdout = vector(s);
 27         else
 28                 results[name]$stdout[|results[name]$stdout|] = s;
 29         }


It's also worth noting that exec.bro really trashes the /tmp directory at this point.

# exec.bro
 94 function run(cmd: string, cb: function(r: Result))
 95         {
 96         local tmpfile = "/tmp/bro-exec-" + unique_id("");
 97         system(fmt("touch %s_done", tmpfile));
 98         system(fmt("touch %s_stdout", tmpfile));
 99         system(fmt("touch %s_stderr", tmpfile));
100         # Sleep for 1 sec before writing to the done file to avoid race conditions
101         # This makes sure that all of the data is read from
102         system(fmt("%s 2>>%s_stderr 1>> %s_stdout; echo \"exit_code:${?}\" > %s_done; sleep 1; echo \"done\" >> %s_done", cmd, tmpf
103
104         results[tmpfile] = [];
105         callbacks[tmpfile] = cb;
106
107         schedule 1msec { start_watching_files(tmpfile) };
108         }

That chunk of code probably needs something like this:

system(fmt("rm %s_done", tmpfile));
system(fmt("rm %s_stdout", tmpfile));
system(fmt("rm %s_stderr", tmpfile));

I'm just not sure where it should go.

-Chris

On Thu, Feb 21, 2013 at 4:54 PM, Seth Hall <seth@icir.org> wrote:

On Feb 21, 2013, at 4:47 PM, Chris Crawford <christopher.p.crawford@gmail.com> wrote:

> Is there another way to load the listen script?

Oh, I think it's because you're reading a packet capture.  When reading packets from a file you can't enable the communication framework.

Just try taking out the -r argument.  You should be able to just put frameworks/communication/listen on the command line too instead of the full file path.  Also, Bro won't terminate until you kill it.

  .Seth

--
Seth Hall
International Computer Science Institute
(Bro) because everyone has a network
http://www.bro-ids.org/