diff --git a/src/Val.cc b/src/Val.cc index f7feb3bd31..643a6b158a 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1969,6 +1969,8 @@ void TableVal::CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe case element_removed: type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_REMOVED); break; + case element_expired: + type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_EXPIRED); } vl.append(type); @@ -2262,9 +2264,9 @@ void TableVal::DoExpire(double t) tbl->MakeRobustCookie(expire_cookie); } - HashKey* k = 0; - TableEntryVal* v = 0; - TableEntryVal* v_saved = 0; + HashKey* k = nullptr; + TableEntryVal* v = nullptr; + TableEntryVal* v_saved = nullptr; bool modified = false; for ( int i = 0; i < table_incremental_step && @@ -2281,10 +2283,11 @@ void TableVal::DoExpire(double t) else if ( v->ExpireAccessTime() + timeout < t ) { + Val* idx = nullptr; if ( expire_func ) { - Val* idx = RecoverIndex(k); - double secs = CallExpireFunc(idx); + idx = RecoverIndex(k); + double secs = CallExpireFunc(idx->Ref()); // It's possible that the user-provided // function modified or deleted the table @@ -2295,6 +2298,7 @@ void TableVal::DoExpire(double t) if ( ! v ) { // user-provided function deleted it v = v_saved; + Unref(idx); delete k; continue; } @@ -2304,6 +2308,7 @@ void TableVal::DoExpire(double t) // User doesn't want us to expire // this now. v->SetExpireAccess(network_time - timeout + secs); + Unref(idx); delete k; continue; } @@ -2312,13 +2317,20 @@ void TableVal::DoExpire(double t) if ( subnets ) { - Val* index = RecoverIndex(k); - if ( ! subnets->Remove(index) ) + if ( ! idx ) + idx = RecoverIndex(k); + if ( ! subnets->Remove(idx) ) reporter->InternalWarning("index not in prefix table"); - Unref(index); } tbl->RemoveEntry(k); + if ( change_func ) + { + if ( ! idx ) + idx = RecoverIndex(k); + CallChangeFunc(idx, v->Value(), element_expired); + } + Unref(idx); Unref(v->Value()); delete v; modified = true; diff --git a/src/Val.h b/src/Val.h index 18b9226e42..8d65468a5d 100644 --- a/src/Val.h +++ b/src/Val.h @@ -848,7 +848,7 @@ protected: double CallExpireFunc(Val *idx); // Enum for the different kinds of changes an &on_change handler can see - enum OnChangeType { element_new, element_changed, element_removed }; + enum OnChangeType { element_new, element_changed, element_removed, element_expired }; // Calls &change_func. Does not take ownership of values. (Refs if needed). void CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe); diff --git a/src/types.bif b/src/types.bif index bea4bd0f3d..876365459c 100644 --- a/src/types.bif +++ b/src/types.bif @@ -229,6 +229,7 @@ enum TableChange %{ TABLE_ELEMENT_NEW, TABLE_ELEMENT_CHANGED, TABLE_ELEMENT_REMOVED, + TABLE_ELEMENT_EXPIRED, %} module Reporter; diff --git a/testing/btest/Baseline/language.on_change_expire/output b/testing/btest/Baseline/language.on_change_expire/output new file mode 100644 index 0000000000..74399a5c6b --- /dev/null +++ b/testing/btest/Baseline/language.on_change_expire/output @@ -0,0 +1,91 @@ +change_function, a, 5, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.1, orig_p=17500/udp, resp_h=172.16.238.255, resp_p=17500/udp], 1, TABLE_ELEMENT_NEW +expired [orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp] +change_function, [orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.1, orig_p=17500/udp, resp_h=172.16.238.255, resp_p=17500/udp] +change_function, [orig_h=172.16.238.1, orig_p=17500/udp, resp_h=172.16.238.255, resp_p=17500/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp] +change_function, [orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp] +change_function, [orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp] +change_function, [orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 1, TABLE_ELEMENT_EXPIRED +expired a +change_function, a, 5, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp] +change_function, [orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp] +change_function, [orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 1, TABLE_ELEMENT_EXPIRED +change_function, [orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=45126/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +expired [orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp] +change_function, [orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=45126/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=45126/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +change_function, [orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=48621/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +expired [orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp] +change_function, [orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=48621/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=48621/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +expired [orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp] +change_function, [orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_EXPIRED +change_function, [orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=42269/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=56485/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=39723/udp, resp_h=172.16.238.2, resp_p=53/udp], 1, TABLE_ELEMENT_NEW +change_function, [orig_h=172.16.238.131, orig_p=123/udp, resp_h=69.50.219.51, resp_p=123/udp], 1, TABLE_ELEMENT_NEW diff --git a/testing/btest/language/on_change_expire.test b/testing/btest/language/on_change_expire.test new file mode 100644 index 0000000000..df748e67d2 --- /dev/null +++ b/testing/btest/language/on_change_expire.test @@ -0,0 +1,25 @@ +# @TEST-EXEC: zeek -C -r $TRACES/var-services-std-ports.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +function inform_me(s: table[string] of count, idx: string): interval + { + print fmt("expired %s", idx); + return 0secs; + } + +function change_function(t: table[string] of count, tpe: TableChange, idx: string, val: count) + { + print "change_function", idx, val, tpe; + } + +global s: table[string] of count &create_expire=1secs &expire_func=inform_me &on_change=change_function; + +event new_connection(c: connection) + { + s[fmt("%s", c$id)] = 1; + } + +event zeek_init() + { + s["a"] = 5; + }