Merge remote-tracking branch 'origin/topic/jsiwek/skip-rh0-segleft'

* origin/topic/jsiwek/skip-rh0-segleft:
  Improve handling of IPv6 Routing Type 0 headers.

Closes #804.
This commit is contained in:
Robin Sommer 2012-03-28 15:11:11 -07:00
commit de7300f999
14 changed files with 111 additions and 5 deletions

17
CHANGES
View file

@ -1,4 +1,21 @@
2.0-184 | 2012-03-28 15:11:11 -0700
* Improve handling of IPv6 Routing Type 0 headers. (Jon Siwek)
- 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.
2.0-182 | 2012-03-28 15:01:57 -0700
* Remove dead tcp_checksum function from net_util. (Jon Siwek)

View file

@ -1 +1 @@
2.0-182
2.0-184

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);
}