diff --git a/scripts/base/frameworks/pacf/main.bro b/scripts/base/frameworks/pacf/main.bro index efb5cd60d0..93e835bc29 100644 --- a/scripts/base/frameworks/pacf/main.bro +++ b/scripts/base/frameworks/pacf/main.bro @@ -218,7 +218,8 @@ global plugins: vector of PluginState; global plugin_ids: table[count] of PluginState; global rule_counter: count = 1; global plugin_counter: count = 1; -global rules: table[string] of Rule; +global rules: table[string,count] of Rule; # Rules indexed by id and cid +global id_to_cids: table[string] of set[count]; # id to cid event bro_init() &priority=5 { @@ -394,42 +395,63 @@ function activate_impl(p: PluginState, priority: int) log_msg(fmt("activated plugin with priority %d", priority), p); } -function add_rule_impl(r: Rule) : string +function add_rule_impl(rule: Rule) : string { - r$cid = ++rule_counter; # numeric id that can be used by plugins for their rules. + rule$cid = ++rule_counter; # numeric id that can be used by plugins for their rules. - if ( ! r?$id || r$id == "" ) - r$id = cat(r$cid); + if ( ! rule?$id || rule$id == "" ) + rule$id = cat(rule$cid); + + local accepted = F; + local priority: int = +0; + local r = rule; for ( i in plugins ) { local p = plugins[i]; + # in this case, rule was accepted by earlier plugin and thus plugin has same + # priority. accept, but give out new rule id. + if ( accepted == T && p$_priority == priority ) + { + r = copy(rule); + r$cid = ++rule_counter; + } + else if ( accepted == T ) + # in this case, rule was accepted by earlier plugin and this plugin has a lower + # priority. Abort and do not send there... + break; + # set before, in case the plugins sends and regenerates the plugin record later. r$_plugin_id = p$_id; if ( p$plugin$add_rule(p, r) ) { + accepted = T; + priority = p$_priority; log_rule(r, "ADD", REQUESTED, p); - return r$id; } } + if ( accepted ) + return rule$id; + log_rule_no_plugin(r, FAILED, "not supported"); return ""; } -function remove_rule_impl(id: string) : bool +function remove_single_rule(id: string, cid: count) : bool { - if ( id !in rules ) + if ( [id,cid] !in rules ) { - Reporter::error(fmt("Rule %s does not exist in Pacf::remove_rule", id)); + Reporter::error(fmt("Rule %s -- %d does not exist in Pacf::remove_single_rule", id, cid)); return F; } - local r = rules[id]; + local r = rules[id,cid]; local p = plugin_ids[r$_plugin_id]; + # remove the respective rules from its plugins.. if ( ! p$plugin$remove_rule(p, r) ) { log_rule_error(r, "remove failed", p); @@ -440,21 +462,52 @@ function remove_rule_impl(id: string) : bool return T; } +function remove_rule_impl(id: string) : bool + { + if ( id !in id_to_cids ) + { + Reporter::error(fmt("Rule %s does not exist in Pacf::remove_rule", id)); + return F; + } + + local cids = id_to_cids[id]; + + local success = T; + for ( cid in cids ) + { + if ( [id,cid] !in rules ) + { + Reporter::error(fmt("Internal error in pacf::remove_rule - cid %d does not belong to rule %s", cid, id)); + delete cids[cid]; + next; + } + + if ( ! remove_single_rule(id, cid) ) + success = F; + } + + return success; + } + event rule_expire(r: Rule, p: PluginState) { - if ( r$id !in rules ) + if ( [r$id,r$cid] !in rules ) # Removed already. return; event rule_timeout(r, FlowInfo(), p); - remove_rule(r$id); + remove_single_rule(r$id, r$cid); } event rule_added(r: Rule, p: PluginState, msg: string &default="") { log_rule(r, "ADD", SUCCEEDED, p); - rules[r$id] = r; + rules[r$id,r$cid] = r; + if ( r$id !in id_to_cids ) + id_to_cids[r$id] = set(); + + add id_to_cids[r$id][r$cid]; if ( r?$expire && ! p$plugin$can_expire ) schedule r$expire { rule_expire(r, p) }; @@ -462,17 +515,31 @@ event rule_added(r: Rule, p: PluginState, msg: string &default="") event rule_removed(r: Rule, p: PluginState, msg: string &default="") { - delete rules[r$id]; + delete rules[r$id,r$cid]; + delete id_to_cids[r$id][r$cid]; + if ( |id_to_cids[r$id]| == 0 ) + delete id_to_cids[r$id]; + log_rule(r, "REMOVE", SUCCEEDED, p); } event rule_timeout(r: Rule, i: FlowInfo, p: PluginState) { - delete rules[r$id]; + delete rules[r$id,r$cid]; + delete id_to_cids[r$id][r$cid]; + if ( |id_to_cids[r$id]| == 0 ) + delete id_to_cids[r$id]; + log_rule(r, "EXPIRE", TIMEOUT, p); } event rule_error(r: Rule, p: PluginState, msg: string &default="") { log_rule_error(r, msg, p); + # errors can occur during deletion. Since this probably means we wo't hear + # from it again, let's just remove it if it exists... + delete rules[r$id,r$cid]; + delete id_to_cids[r$id][r$cid]; + if ( |id_to_cids[r$id]| == 0 ) + delete id_to_cids[r$id]; } diff --git a/testing/btest/Baseline/scripts.base.frameworks.pacf.multiple/pacf.log b/testing/btest/Baseline/scripts.base.frameworks.pacf.multiple/pacf.log new file mode 100644 index 0000000000..588c014285 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.pacf.multiple/pacf.log @@ -0,0 +1,36 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path pacf +#open 2015-06-02-19-34-04 +#fields ts category cmd state action target entity_type entity msg location plugin +#types time enum string enum string enum string string string string string +0.000000 Pacf::MESSAGE - - - - - - activated plugin with priority 10 - Debug-All +0.000000 Pacf::MESSAGE - - - - - - activated plugin with priority 10 - Openflow - OpenFlog Log Plugin - DPID 42 +0.000000 Pacf::MESSAGE - - - - - - activated plugin with priority 0 - Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::REQUESTED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722767.875996 Pacf::RULE ADD Pacf::SUCCEEDED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Openflow - OpenFlog Log Plugin - DPID 42 +1254722776.690444 Pacf::RULE REMOVE Pacf::REQUESTED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::REQUESTED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::REQUESTED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::REQUESTED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::SUCCEEDED Pacf::DROP Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::SUCCEEDED Pacf::WHITELIST Pacf::FORWARD Pacf::ADDRESS 10.10.1.4/32 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::SUCCEEDED Pacf::REDIRECT Pacf::FORWARD Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +1254722776.690444 Pacf::RULE REMOVE Pacf::SUCCEEDED Pacf::DROP Pacf::MONITOR Pacf::FLOW 10.10.1.4/32/1470->74.53.140.153/32/25 - (empty) Debug-All +#close 2015-06-02-19-34-04 diff --git a/testing/btest/scripts/base/frameworks/pacf/multiple.bro b/testing/btest/scripts/base/frameworks/pacf/multiple.bro new file mode 100644 index 0000000000..eda66b1a93 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/pacf/multiple.bro @@ -0,0 +1,24 @@ +# @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT +# @TEST-EXEC: btest-diff pacf.log + +@load base/frameworks/pacf + +event bro_init() + { + local pacf_debug = Pacf::create_debug(T); + local pacf_debug_2 = Pacf::create_debug(T); + local of_controller = OpenFlow::log_new(42); + local pacf_of = Pacf::create_openflow(of_controller); + Pacf::activate(pacf_debug, 10); + Pacf::activate(pacf_of, 10); + Pacf::activate(pacf_debug_2, 0); + } + +event connection_established(c: connection) + { + local id = c$id; + Pacf::shunt_flow([$src_h=id$orig_h, $src_p=id$orig_p, $dst_h=id$resp_h, $dst_p=id$resp_p], 30sec); + Pacf::drop_address(id$orig_h, 15sec); + Pacf::whitelist_address(id$orig_h, 15sec); + Pacf::redirect_flow([$src_h=id$orig_h, $src_p=id$orig_p, $dst_h=id$resp_h, $dst_p=id$resp_p], 5, 30sec); + }