rescan_state()?

I’ve been trying to play with persistent variables with the following:

module PTEST;

global a = 4 &persistent;

event bro_init()
{
if ( rescan_state() )
print “Success!”;
print a;
}

event bro_done()
{
if ( checkpoint_state() )
print “Success!”;
}

event connection_state_remove(c: connection)
{
a = 5;
}

but the “print a” always prints “4” (regardless of how many times I run it), what am I missing? Any thoughts?

Bro is being run with bro -C -r test.pcap persistent.bro (from the same directory each time, and I can see the .state/state.bst file being created.

Thanks.

but the "print a" always prints "4" (regardless of how many times I run it), what am I missing? Any thoughts?

Not entirely sure, but an observation is that it does seem to work when handling "new_connection" and changing the value there instead. So maybe "connection_state_remove" is being raised as a result of reaching the end of the pcap and persistent state tracking/changes doesn't work as well when Bro is in the process of shutting down.

- Jon

Thanks for the feedback!

I found this: "Bro generates this event reliably once for every
connection when it is about to delete the internal state. As such, the
event is well-suited for script-level cleanup that needs to be
performed for every connection."

The oddities seem to exist around UDP, I split it up into
connection_finished and udp_session_done. The TCP stuff seems to
always work/get persisted and the UDP stuff never does.

The expanded script (for anybody interested):

module DF;

# IP -> DHH -> proto -> [0] = number of connections [1] = bytes transferred
global ip_to_connection_info: table[addr] of table[int] of
table[string] of vector of count &persistent &synchronized;

event bro_init()
    {
    if ( rescan_state() )
        print "Success!";
    print ip_to_connection_info;
    print "------";
    }

event bro_done()
    {
    if ( checkpoint_state() )
        print "Success!";
    print ip_to_connection_info;
    }

#event connection_state_remove(c: connection)
event connection_finished(c: connection)
    {
    local net_time = network_time();
    local date = to_int(strftime("%w%H", net_time));
    #local proto = fmt("%s", c$conn$proto);
    local proto = "tcp";
    local ip = c$id$orig_h;

    if ( ip !in ip_to_connection_info )
        {
        ip_to_connection_info[ip] = table();
        }
    if ( ip in ip_to_connection_info && date !in ip_to_connection_info[ip] )
        {
        ip_to_connection_info[ip][date] = table();
        }
    if ( ip in ip_to_connection_info && date in
ip_to_connection_info[ip] && proto !in ip_to_connection_info[ip][date]
)
        {
        ip_to_connection_info[ip][date][proto] = vector();
        ip_to_connection_info[ip][date][proto][0] = 1;
        ip_to_connection_info[ip][date][proto][1] = c$orig$num_bytes_ip;
        }
    else
        {
        ip_to_connection_info[ip][date][proto][0] =
ip_to_connection_info[ip][date][proto][0] + 1;
        ip_to_connection_info[ip][date][proto][1] =
ip_to_connection_info[ip][date][proto][1] + c$orig$num_bytes_ip;
        }
    print fmt("ips[%s][%d][%s][connections] = %d", ip, date, proto,
ip_to_connection_info[ip][date][proto][0]);
    print fmt("ips[%s][%d][%s][total_bytes] = %d", ip, date, proto,
ip_to_connection_info[ip][date][proto][1]);
    print "-------";
    }

event udp_session_done(u: connection)
    {
    local net_time = network_time();
    local date = to_int(strftime("%w%H", net_time));
    local proto = "udp";
    local ip = u$id$orig_h;
    if ( ip !in ip_to_connection_info )
        {
        ip_to_connection_info[ip] = table();
        }
    if ( ip in ip_to_connection_info && date !in ip_to_connection_info[ip] )
        {
        ip_to_connection_info[ip][date] = table();
        }
    if ( ip in ip_to_connection_info && date in
ip_to_connection_info[ip] && proto !in ip_to_connection_info[ip][date]
)
        {
        ip_to_connection_info[ip][date][proto] = vector();
        ip_to_connection_info[ip][date][proto][0] = 1;
        ip_to_connection_info[ip][date][proto][1] = u$orig$num_bytes_ip;
        }
    else
        {
        ip_to_connection_info[ip][date][proto][0] =
ip_to_connection_info[ip][date][proto][0] + 1;
        ip_to_connection_info[ip][date][proto][1] =
ip_to_connection_info[ip][date][proto][1] + u$orig$num_bytes_ip;
        }
    print fmt("ips[%s][%d][%s][connections] = %d", ip, date, proto,
ip_to_connection_info[ip][date][proto][0]);
    print fmt("ips[%s][%d][%s][total_bytes] = %d", ip, date, proto,
ip_to_connection_info[ip][date][proto][1]);
    print "-------";
    }

We're planning on removing the &persistent attribute before long too. It's not terribly safe to use if you want to keep data safe externally to the Bro process. Actually, we're hopefully going to be removing &synchronized too. Neither of those attributes give you the flexibility to define how to make things behave.

If/when we remove them we'll be sure that equivalent and better functionality will be made available, I just wanted to make sure you're aware that your script will need to be updated in the future.

  .Seth