Improve handling of IPv6 Routing Type 0 headers.

- For RH0 headers with non-zero segments left, a "routing0_segleft"
  flow_weird event is raised (with a destination indicating the last
  address in the routing header), and an "rh0_segleft" event can also
  be handled if the other contents of the packet header are of interest.
  No further analysis is done as the complexity required to correctly
  identify destination endpoints of connections doesn't seem worth it
  as RH0 has been deprecated by RFC 5095.

- For RH0 headers without any segments left, a "routing0_header"
  flow_weird event is raised, but further analysis still occurs
  as normal.
This commit is contained in:
Jon Siwek 2012-03-28 13:49:28 -05:00
parent d889f14638
commit 256cd592a7
12 changed files with 93 additions and 4 deletions

View file

@ -305,6 +305,24 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next)
chain.push_back(p);
// RFC 5095 deprecates routing type 0 headers, so raise weirds for that
if ( current_type == IPPROTO_ROUTING &&
((const struct ip6_rthdr*)hdrs)->ip6r_type == 0 )
{
IPAddr src(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_src);
if ( ((const struct ip6_rthdr*)hdrs)->ip6r_segleft > 0 )
{
const in6_addr* a = (const in6_addr*)(hdrs+len-16);
reporter->Weird(src, *a, "routing0_segleft");
}
else
{
IPAddr dst(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_dst);
reporter->Weird(src, dst, "routing0_header");
}
}
hdrs += len;
length += len;
} while ( current_type != IPPROTO_FRAGMENT &&

View file

@ -171,6 +171,20 @@ public:
{ return IsFragment() ?
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
/**
* Returns whether the chain contains a routing type 0 extension header
* with nonzero segments left.
*/
bool RH0SegLeft() const
{
for ( size_t i = 0; i < chain.size(); ++i )
if ( chain[i]->Type() == IPPROTO_ROUTING &&
((const struct ip6_rthdr*)chain[i]->Data())->ip6r_type == 0 &&
((const struct ip6_rthdr*)chain[i]->Data())->ip6r_segleft > 0 )
return true;
return false;
}
/**
* Returns a vector of ip6_ext_hdr RecordVals that includes script-layer
* representation of all extension headers in the chain.
@ -343,6 +357,13 @@ public:
size_t NumHeaders() const
{ return ip4 ? 1 : ip6_hdrs->Size(); }
/**
* Returns true if this is an IPv6 header containing a routing type 0
* extension with nonzero segments left, else returns false.
*/
bool RH0SegLeft() const
{ return ip4 ? false : ip6_hdrs->RH0SegLeft(); }
/**
* Returns an ip_hdr or ip6_hdr_chain RecordVal.
*/

View file

@ -481,6 +481,22 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
return;
}
// Stop analyzing IPv6 packets that use routing type 0 headers with segments
// left since RH0 headers are deprecated by RFC 5095 and we'd have to make
// extra effort to get the destination in the connection/flow endpoint right
if ( ip_hdr->RH0SegLeft() )
{
dump_this_packet = 1;
if ( rh0_segleft )
{
val_list* vl = new val_list();
vl->append(ip_hdr->BuildPktHdrVal());
mgr.QueueEvent(rh0_segleft, vl);
}
Remove(f);
return;
}
int proto = ip_hdr->NextProto();
if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt) )

View file

@ -478,6 +478,14 @@ event ipv6_ext_headers%(c: connection, p: pkt_hdr%);
## .. bro:see:: new_packet tcp_packet ipv6_ext_headers
event esp_packet%(p: pkt_hdr%);
## Generated for any packets using an IPv6 Routing Type 0 extension header
## with non-zero segments left.
##
## p: Information from the header of the packet that triggered the event.
##
## .. bro:see:: new_packet tcp_packet ipv6_ext_headers
event rh0_segleft%(p: pkt_hdr%);
## Generated for every packet that has non-empty transport-layer payload. This is a
## very low-level and expensive event that should be avoided when at all possible.
## It's usually infeasible to handle when processing even medium volumes of

View file

@ -1 +1 @@
[ip=<uninitialized>, ip6=[class=0, flow=0, len=59, nxt=0, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=0, hopopts=[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]], dstopts=<uninitialized>, routing=<uninitialized>, fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>], [id=43, hopopts=<uninitialized>, dstopts=<uninitialized>, routing=[nxt=17, len=4, rtype=0, segleft=2, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A ^A\0x\0^A\02\0\0\0\0\0\0\0^B], fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>]]], tcp=<uninitialized>, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=<uninitialized>]
[ip=<uninitialized>, ip6=[class=0, flow=0, len=68, nxt=0, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=0, hopopts=[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]], dstopts=<uninitialized>, routing=<uninitialized>, fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>], [id=43, hopopts=<uninitialized>, dstopts=<uninitialized>, routing=[nxt=6, len=4, rtype=0, segleft=0, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A ^A\0x\0^A\02\0\0\0\0\0\0\0^B], fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>]]], tcp=[sport=30000/tcp, dport=80/tcp, seq=0, ack=0, hl=20, dl=0, flags=2, win=8192], udp=<uninitialized>, icmp=<uninitialized>]

View file

@ -0,0 +1,2 @@
flow_weird routing0_segleft from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:78:1:32::2
rh0 w/ segments left from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:4f8:4:7:2e0:81ff:fe52:9a6b

View file

@ -0,0 +1,2 @@
flow_weird routing0_header from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:4f8:4:7:2e0:81ff:fe52:9a6b
new_connection: [orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=30000/tcp, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=80/tcp]

Binary file not shown.

View file

@ -1,7 +1,7 @@
# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft.trace %INPUT >output
# @TEST-EXEC: btest-diff output
event ipv6_ext_headers(c: connection, p: pkt_hdr)
event rh0_segleft(p: pkt_hdr)
{
for ( h in p$ip6$exts )
if ( p$ip6$exts[h]$id == IPPROTO_ROUTING )

View file

@ -1,4 +1,4 @@
# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft0.trace %INPUT >output
# @TEST-EXEC: btest-diff output
# Just check that the event is raised correctly for a packet containing

View file

@ -0,0 +1,22 @@
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft0.trace %INPUT >segleft0.out
# @TEST-EXEC: btest-diff segleft0.out
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft.trace %INPUT >segleft.out
# @TEST-EXEC: btest-diff segleft.out
# This will be raised only by the packet with RH0 and segments left.
event rh0_segleft(p: pkt_hdr)
{
print fmt("rh0 w/ segments left from %s to %s", p$ip6$src, p$ip6$dst);
}
# This will be raised only by the packet with RH0 and no segments left.
event new_connection(c: connection)
{
print fmt("new_connection: %s", c$id);
}
# This will be raised by any packet with RH0 regardless of segments left.
event flow_weird(name: string, src: addr, dst: addr)
{
print fmt("flow_weird %s from %s to %s", name, src, dst);
}