diff --git a/scripts/base/frameworks/pacf/__load__.bro b/scripts/base/frameworks/pacf/__load__.bro new file mode 100644 index 0000000000..e2c97f6959 --- /dev/null +++ b/scripts/base/frameworks/pacf/__load__.bro @@ -0,0 +1,3 @@ +@load ./types +@load ./main +@load ./plugins diff --git a/scripts/base/frameworks/pacf/main.bro b/scripts/base/frameworks/pacf/main.bro new file mode 100644 index 0000000000..0e0d930fce --- /dev/null +++ b/scripts/base/frameworks/pacf/main.bro @@ -0,0 +1,477 @@ +##! Bro's packet aquisition and control framework. +##! +##! This plugin-based framework allows to control the traffic that Bro monitors +##! as well as, if having access to the forwarding path, the traffic the network +##! forwards. By default, the framework lets evyerthing through, to both Bro +##! itself as well as on the network. Scripts can then add rules to impose +##! restrictions on entities, such as specific connections or IP addresses. +##! +##! This framework has two API: a high-level and low-level. The high-levem API +##! provides convinience functions for a set of common operations. The +##! low-level API provides full flexibility. + +module Pacf; + +@load ./plugin +@load ./types + +export { + ## The framework's logging stream identifier. + redef enum Log::ID += { LOG }; + + # ### + # ### Generic functions. + # ### + + # Activates a plugin. + # + # plugin: The plugin to acticate. + # + # priority: The higher the priority, the earlier this plugin will be checked + # whether it supports an operation, relative to other plugins. + global activate: function(p: PluginState, priority: int); + + # ### + # ### High-level API. + # ### + + ## Stops all packets involving an IP address from being forwarded. + ## + ## a: The address to be dropped. + ## + ## t: How long to drop it, with 0 being indefinitly. + ## + ## location: An optional string describing where the drop was triggered. + ## + ## Returns: True if a plugin accepted the rule for carrying it out. + global drop_address: function(a: addr, t: interval, location: string &default="") : bool; + + ## Stops forwarding a uni-directional flow's packets to Bro. + ## + ## f: The flow to shunt. + ## + ## t: How long to leave the shunt in place, with 0 being indefinitly. + ## + ## location: An optional string describing where the shunt was triggered. + ## + ## Returns: True if a plugin accepted the rule for carrying it out. + global shunt_flow: function(f: flow_id, t: interval, location: string &default="") : bool; + + ## Removes all rules and notifications for an entity. + ## + ## e: The entity. Note that this will be directly to entities of existing + ## notifications and notifications, which must match exactly field by field. + global reset: function(e: Entity); + + ## Flushes all state. + global clear: function(); + + # ### + # ### Low-level API. + # ### + + ###### Manipulation of rules. + + ## Installs a rule. + ## + ## r: The rule to install. + ## + ## Returns: If succesful, returns an ID string unique to the rule that can later + ## be used to refer to it. If unsuccessful, returns an empty string. The ID is also + ## assigned to ``r$id``. Note that "successful" means "a plugin knew how to handle + ## the rule", it doesn't necessarily mean that it was indeed successfully put in + ## place, because that might happen asynchronously and thus fail only later. + global add_rule: function(r: Rule) : string; + + ## Removes a rule. + ## + ## id: The rule to remove, specified as the ID returned by :bro:id:`add_rule` . + ## + ## Returns: True if succesful, the relevant plugin indicated that ity knew how + ## to handle the removal. Note that again "success" means the plugin accepted the + ## removal. They might still fail to put it into effect, as that might happen + ## asynchronously and thus go wrong at that point. + global remove_rule: function(id: string) : bool; + + ###### Asynchronous feedback on rules. + + ## Confirms that a rule was put in place. + ## + ## r: The rule now in place. + ## + ## plugin: The name of the plugin that put it into place. + ## + ## msg: An optional informational message by the plugin. + global rule_added: event(r: Rule, p: PluginState, msg: string &default=""); + + ## Reports that a rule was removed due to a remove: function() call. + ## + ## r: The rule now removed. + ## + ## plugin: The name of the plugin that had the rule in place and now + ## removed it. + ## + ## msg: An optional informational message by the plugin. + global rule_removed: event(r: Rule, p: PluginState, msg: string &default=""); + + ## Reports that a rule was removed internally due to a timeout. + ## + ## r: The rule now removed. + ## + ## plugin: The name of the plugin that had the rule in place and now + ## removed it. + ## + ## msg: An optional informational message by the plugin. + global rule_timeout: event(r: Rule, p: PluginState); + + ## Reports an error when operating on a rule. + ## + ## r: The rule that encountered an error. + ## + ## plugin: The name of the plugin that reported the error. + ## + ## msg: An optional informational message by the plugin. + global rule_error: event(r: Rule, p: PluginState, msg: string &default=""); + + ## Installs a notification. + ## + ## n: The notification to install. + ## + ## Returns: If succesful, returns an ID string unique to the notification that can later + ## be used to refer to it. If unsuccessful, returns an empty string. The ID is also + ## assigned to ``r$id``. Note that "successful" means "a plugin knew how to handle + ## the notification", it doesn't necessarily mean that it was indeed successfully put in + ## place, because that might happen asynchronously and thus fail only later. + global add_notification: function(n: Notification) : string; + + ## Removes a notification. + ## + ## id: The notification to remove, specified as the ID returned by :bro:id:`add_notification` . + ## + ## Returns: True if succesful, the relevant plugin indicated that ity knew how + ## to handle the removal. Note that again "success" means the plugin accepted the + ## removal. They might still fail to put it into effect, as that might happen + ## asynchronously and thus go wrong at that point. + global remove_notification: function(id: string) : bool; + + ###### Asynchronous feedback on notifications. + + ## Confirms that a notification was put in place. + ## + ## n: The notification now in place. + ## + ## plugin: The name of the plugin that put it into place. + ## + ## msg: An optional informational message by the plugin. + global notification_added: event(n: Notification, p: PluginState, msg: string &default=""); + + ## Reports that a notification was removed due to a remove: function() call. + ## + ## n: The notification now removed. + ## + ## plugin: The name of the plugin that had the notification in place and now + ## removed it. + ## + ## msg: An optional informational message by the plugin. + global notification_removed: event(n: Notification, p: PluginState, msg: string &default=""); + + ## Reports that a notification was removed internally due to a timeout. + ## + ## n: The notification now removed. + ## + ## plugin: The name of the plugin that had the notification in place and now + ## removed it. + ## + ## msg: An optional informational message by the plugin. + global notification_timeout: event(n: Notification, p: PluginState); + + ## Reports an error when operating on a notification. + ## + ## n: The notification that encountered an error. + ## + ## plugin: The name of the plugin that reported the error. + ## + ## msg: An optional informational message by the plugin. + global notification_error: event(n: Notification, p: PluginState, msg: string &default=""); + + ## Type of an entry in the PACF log. + type InfoCategory: enum { + ## A log entry reflecting a framework message. + MESSAGE, + ## A log entry reflecting a framework message. + ERROR, + ## A log entry about about a rule. + RULE, + ## A log entry about about a notification. + NOTIFICATION + }; + + ## State of an entry in the PACF log. + type InfoState: enum { + REQUESTED, + SUCCEEDED, + FAILED, + REMOVED, + TIMEOUT, + }; + + ## The record type which contains column fields of the PACF log. + type Info: record { + ## Time at which the recorded activity occurred. + ts: time &log; + ## Type of the log entry. + category: InfoCategory &log &optional; + ## The command the log entry is about. + cmd: string &log &optional; + ## State the log entry reflects. + state: InfoState &log &optional; + ## String describing an action the entry is about. + action: string &log &optional; + ## The target type of the action. + target: TargetType &log &optional; + ## Type of the entity the log entry is about. + entity_type: string &log &optional; + ## String describing the entity the log entry is about. + entity: string &log &optional; + ## String with an additional message. + msg: string &log &optional; + ## Logcation where the underlying action was triggered. + location: string &log &optional; + ## Plugin triggering the log entry. + plugin: string &log &optional; + }; +} + +redef record Rule += { + ##< Internally set to the plugin handling the rule. + _plugin: PluginState &optional; +}; + +global plugins: vector of PluginState; +global rule_counter: count = 0; +global rules: table[string] of Rule; + +event bro_init() &priority=5 + { + Log::create_stream(Pacf::LOG, [$columns=Info]); + } + +function entity_to_info(info: Info, e: Entity) + { + info$entity_type = fmt("%s", e$ty); + + switch ( e$ty ) { + case ADDRESS, ORIGINATOR, RESPONDER: + info$entity = fmt("%s", e$ip); + break; + + case CONNECTION: + info$entity = fmt("%s/%d<->%s/%d", + e$conn$orig_h, e$conn$orig_p, + e$conn$resp_h, e$conn$resp_p); + break; + + case FLOW: + info$entity = fmt("%s/%d->%s/%d", + e$flow$src_h, e$flow$src_p, + e$flow$dst_h, e$flow$dst_p); + break; + + case MAC: + info$entity = e$mac; + break; + + default: + info$entity = ""; + break; + } + } + +function rule_to_info(info: Info, r: Rule) + { + info$action = fmt("%s", r$ty); + info$target = r$target; + + if ( r?$location ) + info$location = r$location; + + entity_to_info(info, r$entity); + } + +function log_msg(msg: string, p: PluginState) + { + Log::write(LOG, [$ts=network_time(), $category=MESSAGE, $msg=msg, $plugin=p$plugin$name(p)]); + } + +function log_error(msg: string, p: PluginState) + { + Log::write(LOG, [$ts=network_time(), $category=ERROR, $msg=msg, $plugin=p$plugin$name(p)]); + } + +function log_rule(r: Rule, cmd: string, state: InfoState, p: PluginState) + { + local info: Info = [$ts=network_time()]; + info$category = RULE; + info$cmd = cmd; + info$state = state; + info$plugin = p$plugin$name(p); + + rule_to_info(info, r); + + Log::write(LOG, info); + } + +function log_rule_error(r: Rule, msg: string, p: PluginState) + { + local info: Info = [$ts=network_time(), $category=ERROR, $msg=msg, $plugin=p$plugin$name(p)]; + rule_to_info(info, r); + Log::write(LOG, info); + } + +function log_rule_no_plugin(r: Rule, state: InfoState, msg: string) + { + local info: Info = [$ts=network_time()]; + info$category = RULE; + info$state = state; + info$msg = msg; + + rule_to_info(info, r); + + Log::write(LOG, info); + } + +function activate(p: PluginState, priority: int) + { + p$_priority = priority; + plugins[|plugins|] = p; + sort(plugins, function(p1: PluginState, p2: PluginState) : int { return p2$_priority - p1$_priority; }); + + log_msg(fmt("activated plugin with priority %d", priority), p); + } + +function drop_address(a: addr, t: interval, location: string &default="") : bool + { + local e: Entity = [$ty=ADDRESS, $ip=addr_to_subnet(a)]; + local r: Rule = [$ty=DROP, $target=FORWARD, $entity=e, $expire=t, $location=location]; + + local id = add_rule(r); + return |id| > 0; + } + +function shunt_flow(f: flow_id, t: interval, location: string &default="") : bool + { + local e: Entity = [$ty=FLOW, $flow=f]; + local r: Rule = [$ty=DROP, $target=MONITOR, $entity=e, $expire=t, $location=location]; + + local id = add_rule(r); + return |id| > 0; + } + +function reset(e: Entity) + { + print "Pacf::reset not implemented yet"; + } + +function clear() + { + print "Pacf::clear not implemented yet"; + } + +function add_rule(r: Rule) : string + { + r$id = fmt("%d", ++rule_counter); + + for ( i in plugins ) + { + local p = plugins[i]; + + if ( p$plugin$add_rule(p, r) ) + { + r$_plugin = p; + log_rule(r, "ADD", REQUESTED, p); + return r$id; + } + } + + log_rule_no_plugin(r, FAILED, "not supported"); + } + +function remove_rule(id: string) : bool + { + local r = rules[id]; + local p = r$_plugin; + + if ( ! p$plugin$remove_rule(r$_plugin, r) ) + { + log_rule_error(r, "remove failed", p); + return F; + } + + log_rule(r, "REMOVE", REQUESTED, p); + return T; + } + +event rule_expire(r: Rule, p: PluginState) + { + if ( r$id !in rules ) + # Remove already. + return; + + event rule_timeout(r, p); + remove_rule(r$id); + } + +event rule_added(r: Rule, p: PluginState, msg: string &default="") + { + log_rule(r, "ADD", SUCCEEDED, p); + + rules[r$id] = r; + + if ( r?$expire && ! p$plugin$can_expire ) + schedule r$expire { rule_expire(r, p) }; + } + +event rule_removed(r: Rule, p: PluginState, msg: string &default="") + { + delete rules[r$id]; + log_rule(r, "REMOVE", SUCCEEDED, p); + } + +event rule_timeout(r: Rule, p: PluginState) + { + delete rules[r$id]; + log_rule(r, "EXPIRE", TIMEOUT, p); + } + +event rule_error(r: Rule, p: PluginState, msg: string &default="") + { + log_rule_error(r, msg, p); + } + +function add_notification(n: Notification) : string + { + print "Pacf::add_notification not implemented yet"; + } + +function remove_notification(id: string) : bool + { + print "Pacf::remove_notification not implemented yet"; + } + +event notification_added(n: Notification, p: PluginState, msg: string &default="") + { + } + +event notification_removed(n: Notification, p: PluginState, msg: string &default="") + { + } + +event notification_timeout(n: Notification, p: PluginState) + { + } + +event notification_error(n: Notification, p: PluginState, msg: string &default="") + { + } + + diff --git a/scripts/base/frameworks/pacf/plugin.bro b/scripts/base/frameworks/pacf/plugin.bro new file mode 100644 index 0000000000..944705605f --- /dev/null +++ b/scripts/base/frameworks/pacf/plugin.bro @@ -0,0 +1,91 @@ + +module Pacf; + +@load ./types + +export { + ## State for a plugin instance. + type PluginState: record { + ## Table for a plugin to store custom, instance-specfific state. + config: table[string] of string &default=table(); + + ## Set internally. + _priority: int &default=+0; + }; + + # Definitioan of a plugin. + # + # Generally a plugin needs to implement only what it can support. By + # returning failure, it indicates that it can't support something and the + # the framework will then try another plugin, if available; or informn the + # that the operation failed. If a function isn't implemented by a plugin, + # that's considered an implicit failure to support the operation. + # + # If plugin accepts a rule operation, it *must* generate one of the reporting + # events ``rule_{added,remove,error}`` to signal if it indeed worked out; + # this is separate from accepting the operation because often a plugin + # will only know later (i.e., asynchrously) if that was an error for + # something it thought it could handle. The same applies to notifications, + # with the corresponding ``notification_*`` events. + type Plugin: record { + # Returns a descriptive name of the plugin instance, suitable for use in logging + # messages. Note that this function is not optional. + name: function(state: PluginState) : string; + + ## If true, plugin can expire rules/notifications itself. If false, + ## framework will manage rule expiration. + can_expire: bool; + + # One-time initialization functionl called when plugin gets registered, and + # befire any ther methods are called. + init: function(state: PluginState) &optional; + + # One-time finalization function called when a plugin is shutdown; no further + # functions will be called afterwords. + done: function(state: PluginState) &optional; + + # Implements the add_rule() operation. If the plugin accepts the rule, + # it returns true, false otherwise. The rule will already have its + # ``id`` field set, which the plugin may use for identification + # purposes. + add_rule: function(state: PluginState, r: Rule) : bool &optional; + + # Implements the remove_rule() operation. This will only be called for + # rules that the plugins has previously accepted with add_rule(). The + # ``id`` field will match that of the add_rule() call. Generally, + # a plugin that accepts an add_rule() should also accept the + # remove_rule(). + remove_rule: function(state: PluginState, r: Rule) : bool &optional; + + # Implements the add_notification() operation. If the plugin accepts the notification, + # it returns true, false otherwise. The notification will already have its + # ``id`` field set, which the plugin may use for identification + # purposes. + add_notification: function(state: PluginState, r: Notification) : bool &optional; + + # Implements the remove_notification() operation. This will only be called for + # notifications that the plugins has previously accepted with add_notification(). + # The ``id`` field will match that of the add_notification() call. Generally, + # a plugin that accepts an add_notification() should also accept the + # remove_notification(). + remove_notification: function(state: PluginState, r: Notification) : bool &optional; + + # A transaction groups a number of operations. The plugin can add them internally + # and postpone putting them into effect until committed. This allows to build a + # configuration of multiple rules at once, including replaying a previous state. + transaction_begin: function(state: PluginState) &optional; + transaction_end: function(state: PluginState) &optional; + }; + + # Table for a plugin to store instance-specific configuration information. + # + # Note, it would be nicer to pass the Plugin instance to all the below, instead + # of this state table. However Bro's type resolver has trouble with refering to a + # record type from inside itself. + redef record PluginState += { + ## The plugin that the state belongs to. (Defined separately + ## because of cyclic type dependency.) + plugin: Plugin &optional; + }; + +} diff --git a/scripts/base/frameworks/pacf/plugins/__load__.bro b/scripts/base/frameworks/pacf/plugins/__load__.bro new file mode 100644 index 0000000000..0b76aa2b74 --- /dev/null +++ b/scripts/base/frameworks/pacf/plugins/__load__.bro @@ -0,0 +1 @@ +@load ./debug diff --git a/scripts/base/frameworks/pacf/plugins/debug.bro b/scripts/base/frameworks/pacf/plugins/debug.bro new file mode 100644 index 0000000000..09fb87ef3f --- /dev/null +++ b/scripts/base/frameworks/pacf/plugins/debug.bro @@ -0,0 +1,119 @@ + +@load ../plugin + +module Pacf; + +export { + ## Instantiates a debug plugin for the PACF framework. The debug + ## plugin simply logs the operations it receives. + ## + ## do_something: If true, the plugin will claim it supports all operations; if + ## false, it will indicate it doesn't support any. + global create_debug: function(do_something: bool) : PluginState; +} + +function do_something(p: PluginState) : bool + { + return p$config["all"] == "1"; + } + +function debug_name(p: PluginState) : string + { + return fmt("Debug-%s", (do_something(p) ? "All" : "None")); + } + +function debug_log(p: PluginState, msg: string) + { + print fmt("pacf debug (%s): %s", debug_name(p), msg); + } + +function debug_init(p: PluginState) + { + debug_log(p, "init"); + } + +function debug_done(p: PluginState) + { + debug_log(p, "init"); + } + +function debug_add_rule(p: PluginState, r: Rule) : bool + { + local s = fmt("add_rule: %s", r); + debug_log(p, s); + + if ( do_something(p) ) + { + event Pacf::rule_added(r, p); + return T; + } + + return F; + } + +function debug_remove_rule(p: PluginState, r: Rule) : bool + { + local s = fmt("remove_rule: %s", r); + debug_log(p, s); + + event Pacf::rule_removed(r, p); + return T; + } + +function debug_add_notification(p: PluginState, r: Notification) : bool + { + local s = fmt("add_notification: %s", r); + debug_log(p, s); + + if ( do_something(p) ) + { + event Pacf::notification_added(r, p); + return T; + } + + return F; + } + +function debug_remove_notification(p: PluginState, r: Notification) : bool + { + local s = fmt("remove_notification: %s", r); + debug_log(p, s); + + return do_something(p); + } + +function debug_transaction_begin(p: PluginState) + { + debug_log(p, "transaction_begin"); + } + +function debug_transaction_end(p: PluginState) + { + debug_log(p, "transaction_end"); + } + +global debug_plugin = Plugin( + $name=debug_name, + $can_expire = F, + $init = debug_init, + $done = debug_done, + $add_rule = debug_add_rule, + $remove_rule = debug_remove_rule, + $add_notification = debug_add_notification, + $remove_notification = debug_remove_notification, + $transaction_begin = debug_transaction_begin, + $transaction_end = debug_transaction_end + ); + +function create_debug(do_something: bool) : PluginState + { + local p: PluginState = [$plugin=debug_plugin]; + + # FIXME: Why's the default not working? + p$config = table(); + p$config["all"] = (do_something ? "1" : "0"); + + return p; + } + + diff --git a/scripts/base/frameworks/pacf/types.bro b/scripts/base/frameworks/pacf/types.bro new file mode 100644 index 0000000000..8e3a3b999d --- /dev/null +++ b/scripts/base/frameworks/pacf/types.bro @@ -0,0 +1,122 @@ + +module Pacf; + +export { + ## Type of a :bro:id:`Entity` for defining an action. + type EntityType: enum { + ADDRESS, ##< Activity involving a specific IP address. + ORIGINATOR, ##< Activity *from* a source IP address. + RESPONDER, ##< Activity *to* a destination IP address. + CONNECTION, ##< All of a bi-directional connection's activity. + FLOW, ##< All of a uni-directional flow's activity. + MAC, ##< Activity involving a MAC address. + }; + + ## Type defining the enity an :bro:id:`Rule` is operating on. + type Entity: record { + ty: EntityType; ##< Type of entity. + conn: conn_id &optional; ##< Used with :bro:id:`CONNECTION` . + flow: flow_id &optional; ##< Used with :bro:id:`FLOW` . + ip: subnet &optional; ##< Used with :bro:id:`ORIGINATOR`/:bro:id:`RESPONDER`/:bro:id:`ADDRESS`; can specifiy a CIDR subnet. + mac: string &optional; ##< Used with :bro:id:`MAC` . + }; + + ## Target of :bro:id:`Rule` action. + type TargetType: enum { + FORWARD, #< Apply rule actively to traffic on forwarding path. + MONITOR, #< Apply rule passively to traffic sent to Bro for monitoring. + }; + + ## Type of rules that the framework supports. Each type lists the + ## :bro:id:`Rule` argument(s) it uses, if any. + ## + ## Plugins may extend this type to define their own. + type RuleType: enum { + ## Stop forwarding all packets matching entity. + ## + ## No arguments. + DROP, + + ## Begin rate-limiting flows matching entity. + ## + ## d: Percent of available bandwidth. + LIMIT, + + ## Begin modifying all packets matching entity. + ## + ## .. todo:: + ## Define arguments. + MODIFY, + + ## Begin redirecting all packets matching entity. + ## + ## .. todo:: + ## Define arguments. + REDIRECT, + + ## Begin sampling all flows matching entity. + ## + ## d: Probability to include a flow between 0 and 1. + SAMPLE, + + ## Whitelists all packets of an entity, meaning no restrictions will be applied. + ## While whitelisting is the default if no rule matches an this can type can be + ## used to override lower-priority rules that would otherwise take effect for the + ## entity. + WHITELIST, + }; + + ## A rule for the framework to put in place. Of all rules currently in + ## place, the first match will be taken, sorted by priority. All + ## further riles will be ignored. + type Rule: record { + ty: RuleType; ##< Type of rule. + target: TargetType; ##< Where to apply rule. + entity: Entity; ##< Entity to apply rule to. + expire: interval &optional; ##< Timeout after which to expire the rule. + priority: int &default=+0; ##< Priority if multiple rules match an entity (larger value is higher priority). + location: string &optional; ##< Optional string describing where/what installed the rule. + + i: int &optional; ##< Argument for rule types requiring an integer argument. + d: double &optional; ##< Argument for rule types requiring a double argument. + s: string &optional; ##< Argument for rule types requiring a string argument. + + id: string &default=""; ##< Internally determined unique ID for this rule. Will be set when added. + }; + + ## Type of notifications that the framework supports. Each type lists the + ## :bro:id:`Notification` argument(s) it uses, if any. + ## + ## Plugins may extend this type to define their own. + type NotificationType: enum { + ## Notify if threshold of packets has been reached by entity. + ## + ## i: Number of packets. + NUM_PACKETS, + + ## Notify if threshold of bytes has been reached by entity. + ## + ## i: Number of bytes. + NUM_BYTES, + }; + + ## A notification for the framework to raise when a condition has been reached. + ## Different than with rules, all matching conditions will be reported, not only + ## the first match. + type Notification: record { + ty: NotificationType; ##< Type of notification. + entity: Entity; ##< Entity to apply notification to. + expire: interval &optional; ##< Timeout after which to expire the notification. + src: string &optional; ##< Optional string describing where/what installed the notification. + + i: int; ##< Argument for notification types requiring an integer argument. + d: double; ##< Argument for notification types requiring a double argument. + s: string; ##< Argument for notification types requiring a string argument. + + id: string &default=""; ##< Internally determined unique ID for this notification. Will be set when added. + }; +} + + + + diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index cfe845eb4f..ba3bd35c7f 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -120,6 +120,18 @@ type conn_id: record { resp_p: port; ##< The responder's port number. } &log; +## The identifying 4-tuple of a uni-directional flow. +## +## .. note:: It's actually a 5-tuple: the transport-layer protocol is stored as +## part of the port values, `src_p` and `dst_p`, and can be extracted from +## them with :bro:id:`get_port_transport_proto`. +type flow_id : record { + src_h: addr; ##< The source IP address. + src_p: port; ##< The source port number. + dst_h: addr; ##< The destination IP address. + dst_p: port; ##< The desintation port number. +}; + ## Specifics about an ICMP conversation. ICMP events typically pass this in ## addition to :bro:type:`conn_id`. ## diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 2af8f3bc3d..c3e868e48f 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -37,6 +37,7 @@ @load base/frameworks/reporter @load base/frameworks/sumstats @load base/frameworks/tunnels +@load base/frameworks/pacf @load base/protocols/conn @load base/protocols/dhcp diff --git a/src/bro.bif b/src/bro.bif index e7be72410c..18f91b31df 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2366,6 +2366,19 @@ function to_subnet%(sn: string%): subnet return ret; %} +## Converts a :bro:type:`addr` to a :bro:type:`subnet`. +## +## a: The address to convert. +## +## Returns: The *sn* string as a :bro:type:`subnet`. +## +## .. bro:see:: to_subset +function addr_to_subnet%(a: addr%): subnet + %{ + int width = (a->AsAddr().GetFamily() == IPv4 ? 32 : 128); + return new SubNetVal(a->AsAddr(), width); + %} + ## Converts a :bro:type:`string` to a :bro:type:`double`. ## ## str: The :bro:type:`string` to convert.