diff --git a/scripts/base/frameworks/tunnels/main.bro b/scripts/base/frameworks/tunnels/main.bro index b40aa519f9..743098cd6d 100644 --- a/scripts/base/frameworks/tunnels/main.bro +++ b/scripts/base/frameworks/tunnels/main.bro @@ -27,7 +27,7 @@ export { ts: time &log; ## The unique identifier for the tunnel, which may correspond ## to a :bro:type:`connection`'s *uid* field for non-IP-in-IP tunnels. - uid: string &log &optional; + uid: string &log; ## The tunnel "connection" 4-tuple of endpoint addresses/ports. ## For an IP tunnel, the ports will be 0. id: conn_id &log; diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 59075de439..cc798ecdc5 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -190,7 +190,7 @@ export { tunnel_type: Tunnel::Type; ## A globally unique identifier that, for non-IP-in-IP tunnels, ## cross-references the *uid* field of :bro:type:`connection`. - uid: string &optional; + uid: string; } &log; } # end export module GLOBAL; diff --git a/src/Conn.cc b/src/Conn.cc index 6333f98f3e..0e34903bed 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -13,6 +13,7 @@ #include "Timer.h" #include "PIA.h" #include "binpac.h" +#include "Tunnels.h" void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer, int arg_do_expire) diff --git a/src/Sessions.cc b/src/Sessions.cc index fa6faba85c..d3d5d294bc 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -542,9 +542,23 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, fake_hdr.caplen = fake_hdr.len = caplen; fake_hdr.ts = hdr->ts; - EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(), - BifEnum::Tunnel::IP); - encapsulation.Add(ec); + IPPair tunnel_idx; + if ( ip_hdr->SrcAddr() < ip_hdr->DstAddr() ) + tunnel_idx = IPPair(ip_hdr->SrcAddr(), ip_hdr->DstAddr()); + else + tunnel_idx = IPPair(ip_hdr->DstAddr(), ip_hdr->SrcAddr()); + + IPTunnelMap::const_iterator it = ip_tunnels.find(tunnel_idx); + + if ( it == ip_tunnels.end() ) + { + EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(), + BifEnum::Tunnel::IP); + ip_tunnels[tunnel_idx] = ec; + encapsulation.Add(ec); + } + else + encapsulation.Add(it->second); DoNextPacket(t, &fake_hdr, inner_ip, data, 0, encapsulation); diff --git a/src/Sessions.h b/src/Sessions.h index fb76d29831..54ff74ded9 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -11,6 +11,8 @@ #include "PacketFilter.h" #include "Stats.h" #include "NetVar.h" +#include "Tunnels.h" +#include struct pcap_pkthdr; @@ -202,6 +204,9 @@ protected: PDict(Connection) udp_conns; PDict(Connection) icmp_conns; PDict(FragReassembler) fragments; + typedef pair IPPair; + typedef std::map IPTunnelMap; + IPTunnelMap ip_tunnels; ARP_Analyzer* arp_analyzer; diff --git a/src/Tunnels.h b/src/Tunnels.h index e6e3de6d76..b8d693ea59 100644 --- a/src/Tunnels.h +++ b/src/Tunnels.h @@ -13,6 +13,10 @@ class Connection; class EncapsulatingConn { public: + EncapsulatingConn() + : src_port(0), dst_port(0), type(BifEnum::Tunnel::NONE), uid(0) + {} + EncapsulatingConn(const IPAddr& s, const IPAddr& d, BifEnum::Tunnel::Type t) : src_addr(s), dst_addr(d), src_port(0), dst_port(0), type(t) @@ -36,7 +40,13 @@ public: friend bool operator==(const EncapsulatingConn& ec1, const EncapsulatingConn& ec2) { - return ec1.type == ec2.type && ec1.src_addr == ec2.src_addr && + if ( ec1.type != ec2.type ) + return false; + if ( ec1.type == BifEnum::Tunnel::IP ) + return ec1.uid == ec2.uid && + ((ec1.src_addr == ec2.src_addr && ec1.dst_addr == ec2.dst_addr) || + (ec1.src_addr == ec2.dst_addr && ec1.dst_addr == ec2.src_addr)); + return ec1.src_addr == ec2.src_addr && ec1.dst_addr == ec2.dst_addr && ec1.src_port == ec2.src_port && ec1.dst_port == ec2.dst_port && ec1.uid == ec2.uid; } diff --git a/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output b/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output new file mode 100644 index 0000000000..afb5837b23 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output @@ -0,0 +1,33 @@ +new_connection: tunnel + conn_id: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + encap: [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] +NEW_PACKET: + [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] diff --git a/testing/btest/Traces/tunnels/ping6-in-ipv4.pcap b/testing/btest/Traces/tunnels/ping6-in-ipv4.pcap new file mode 100644 index 0000000000..5e0995f80e Binary files /dev/null and b/testing/btest/Traces/tunnels/ping6-in-ipv4.pcap differ diff --git a/testing/btest/core/tunnels/ip-tunnel-uid.test b/testing/btest/core/tunnels/ip-tunnel-uid.test new file mode 100644 index 0000000000..f86fd126c9 --- /dev/null +++ b/testing/btest/core/tunnels/ip-tunnel-uid.test @@ -0,0 +1,33 @@ +# @TEST-EXEC: bro -b -r $TRACES/tunnels/ping6-in-ipv4.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: btest-diff output + +event new_connection(c: connection) + { + if ( c?$tunnel ) + { + print "new_connection: tunnel"; + print fmt(" conn_id: %s", c$id); + print fmt(" encap: %s", c$tunnel); + } + else + { + print "new_connection: no tunnel"; + } + } + +event tunnel_changed(c: connection, e: EncapsulatingConnVector) + { + print "tunnel_changed:"; + print fmt(" conn_id: %s", c$id); + if ( c?$tunnel ) + print fmt(" old: %s", c$tunnel); + print fmt(" new: %s", e); + } + +event new_packet(c: connection, p: pkt_hdr) + { + print "NEW_PACKET:"; + print fmt(" %s", c$id); + if ( c?$tunnel ) + print fmt(" %s", c$tunnel); + }