Make Flow a separate, more flexible type in PACF.

This allows the use of wildcards, etc. in rules and removes the need
for a few entity types that were separate so far.
This commit is contained in:
Johanna Amann 2015-05-12 13:37:16 -07:00
parent a51ee45e05
commit ed65fdb6ba
6 changed files with 101 additions and 69 deletions

View file

@ -265,7 +265,7 @@ function entity_to_info(info: Info, e: Entity)
info$entity_type = fmt("%s", e$ty);
switch ( e$ty ) {
case ADDRESS, ORIGINATOR, RESPONDER:
case ADDRESS:
info$entity = fmt("%s", e$ip);
break;
@ -364,7 +364,13 @@ function drop_address(a: addr, t: interval, location: string &default="") : bool
function shunt_flow(f: flow_id, t: interval, location: string &default="") : bool
{
local e: Entity = [$ty=FLOW, $flow=f];
local flow = Pacf::Flow(
$src_h=addr_to_subnet(f$src_h),
$src_p=f$src_p,
$dst_h=addr_to_subnet(f$dst_h),
$dst_p=f$dst_p
);
local e: Entity = [$ty=FLOW, $flow=flow];
local r: Rule = [$ty=DROP, $target=MONITOR, $entity=e, $expire=t, $location=location];
local id = add_rule(r);

View file

@ -63,6 +63,26 @@ function openflow_flow_mod_pred(p: PluginState, r: Rule, m: OpenFlow::ofp_flow_m
return m;
}
function determine_dl_type(s: subnet): count
{
local pdl = OpenFlow::ETH_IPv4;
if ( is_v6_subnet(s) )
pdl = OpenFlow::ETH_IPv6;
return pdl;
}
function determine_proto(p: port): count
{
local proto = OpenFlow::IP_TCP;
if ( is_udp_port(p) )
proto = OpenFlow::IP_UDP;
else if ( is_icmp_port(p) )
proto = OpenFlow::IP_ICMP;
return proto;
}
function entity_to_match(p: PluginState, e: Entity): vector of OpenFlow::ofp_match
{
local v : vector of OpenFlow::ofp_match = vector();
@ -74,49 +94,34 @@ function entity_to_match(p: PluginState, e: Entity): vector of OpenFlow::ofp_mat
return openflow_match_pred(p, e, v);
}
if ( e$ty == MAC || e$ty == ORIGMAC || e$ty == DESTMAC )
if ( e$ty == MAC )
{
if ( e$ty == MAC || e$ty == ORIGMAC )
v[|v|] = OpenFlow::ofp_match(
$dl_src=e$mac
);
if ( e$ty == MAC || e$ty == DESTMAC )
v[|v|] = OpenFlow::ofp_match(
$dl_dst=e$mac
);
return openflow_match_pred(p, e, v);
}
if ( e$ty == MACFLOW )
{
v[|v|] = OpenFlow::ofp_match(
$dl_src=e$mac,
$dl_dst=e$dst_mac
);
v[|v|] = OpenFlow::ofp_match(
$dl_src=e$mac
);
v[|v|] = OpenFlow::ofp_match(
$dl_dst=e$mac
);
return openflow_match_pred(p, e, v);
}
local dl_type = OpenFlow::ETH_IPv4;
if ( e$ty == ADDRESS || e$ty == RESPONDER || e$ty == ORIGINATOR )
if ( e$ty == ADDRESS )
{
if ( is_v6_subnet(e$ip) )
dl_type = OpenFlow::ETH_IPv6;
if ( e$ty == ADDRESS || e$ty == ORIGINATOR )
v[|v|] = OpenFlow::ofp_match(
$dl_type=dl_type,
$nw_src=e$ip
);
v[|v|] = OpenFlow::ofp_match(
$dl_type=dl_type,
$nw_src=e$ip
);
if ( e$ty == ADDRESS || e$ty == RESPONDER )
v[|v|] = OpenFlow::ofp_match(
$dl_type=dl_type,
$nw_dst=e$ip
);
v[|v|] = OpenFlow::ofp_match(
$dl_type=dl_type,
$nw_dst=e$ip
);
return openflow_match_pred(p, e, v);
}
@ -125,22 +130,39 @@ function entity_to_match(p: PluginState, e: Entity): vector of OpenFlow::ofp_mat
if ( e$ty == FLOW )
{
if ( is_v6_addr(e$flow$src_h) )
dl_type = OpenFlow::ETH_IPv6;
local m = OpenFlow::ofp_match();
local f = e$flow;
if ( is_udp_port(e$flow$src_p) )
proto = OpenFlow::IP_UDP;
else if ( is_icmp_port(e$flow$src_p) )
proto = OpenFlow::IP_ICMP;
if ( f?$src_m )
m$dl_src=f$src_m;
if ( f?$dst_m )
m$dl_dst=f$dst_m;
v[|v|] = OpenFlow::ofp_match(
$dl_type=dl_type,
$nw_proto=proto,
$nw_src=addr_to_subnet(e$flow$src_h),
$tp_src=e$flow$src_p,
$nw_dst=addr_to_subnet(e$flow$dst_h),
$tp_dst=e$flow$dst_p
);
if ( f?$src_h )
{
m$dl_type = determine_dl_type(f$src_h);
m$nw_src = f$src_h;
}
if ( f?$dst_h )
{
m$dl_type = determine_dl_type(f$dst_h);
m$nw_dst = f$dst_h;
}
if ( f?$src_p )
{
m$nw_proto = determine_proto(f$src_p);
m$tp_src = f$src_p;
}
if ( f?$dst_p )
{
m$nw_proto = determine_proto(f$dst_p);
m$tp_dst = f$dst_p;
}
v[|v|] = m;
return openflow_match_pred(p, e, v);
}

View file

@ -5,24 +5,28 @@ 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.
FLOW, ##< All of a uni-directional flow's activity. Can contain wildcards.
MAC, ##< Activity involving a MAC address.
ORIGMAC, ##< Activity *from* a source MAC address.
DESTMAC, ##< Activity *to* a destination MAC adress.
MACFLOW ##< Activity involving a pair of MAC addresses.
};
## Type of a :bro:id:`Flow` for defining a flow.
type Flow: record {
src_h: subnet &optional; ##< The source IP address/subnet.
src_p: port &optional; ##< The source port number.
dst_h: subnet &optional; ##< The destination IP address/subnet.
dst_p: port &optional; ##< The desintation port number.
src_m: string &optional; ##< The source MAC address.
dst_m: string &optional; ##< The destination 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`/:bro:id:`ORIGMAC`/:bro:id:`DESTMAC`/:bro:id:`MACFLOW`.
dst_mac: string &optional; ##< Used with :bro:id:`MACFLOW`; specifies the destination for the flow.
flow: Flow &optional; ##< Used with :bro:id:`FLOW` .
ip: subnet &optional; ##< Used with bro:id:`ADDRESS`; can specifiy a CIDR subnet.
mac: string &optional; ##< Used with :bro:id:`MAC`.
};
## Target of :bro:id:`Rule` action.