From eb9f686bb20fc1fe5021cd0b92eea3b5a147a1cd Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 2 Mar 2012 20:01:01 -0600 Subject: [PATCH 01/13] Add handling for IPv6 extension header chains (addresses #531) - The script-layer 'pkt_hdr' type is extended with a new 'ip6' field representing the full IPv6 header chain. - The 'new_packet' event is now raised for IPv6 packets (addresses #523) - A new event called 'ipv6_ext_header' is raised for any IPv6 packet containing extension headers. - A new event called 'esp_packet' is raised for any packets using ESP ('new_packet' and 'ipv6_ext_header' events provide connection info, but that info can't be provided here since the upper-layer payload is encrypted). - The 'unknown_protocol' weird is now raised more reliably when Bro sees a transport protocol or IPv6 extension header it can't handle. (addresses #522) Still need to do IPv6 fragment reassembly and needs more testing. --- scripts/base/init-bare.bro | 156 ++++++++++++++++++++- src/CMakeLists.txt | 1 + src/Frag.cc | 13 +- src/Frag.h | 5 +- src/IP.cc | 273 +++++++++++++++++++++++++++++++++++++ src/IP.h | 196 +++++++++++++++++++++++--- src/PacketSort.cc | 2 +- src/Sessions.cc | 151 ++++++++++---------- src/Sessions.h | 10 +- src/TCP.cc | 6 +- src/event.bif | 21 ++- 11 files changed, 724 insertions(+), 110 deletions(-) create mode 100644 src/IP.cc diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c4ae4b134a..91c6b7856d 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -939,11 +939,154 @@ const IPPROTO_IGMP = 2; ##< Group management protocol. const IPPROTO_IPIP = 4; ##< IP encapsulation in IP. const IPPROTO_TCP = 6; ##< TCP. const IPPROTO_UDP = 17; ##< User datagram protocol. +const IPPROTO_IPV6 = 41; ##< IPv6 header. const IPPROTO_RAW = 255; ##< Raw IP packet. -## Values extracted from an IP header. +# Definitions for IPv6 extension headers. +const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. +const IPPROTO_ROUTING = 43; ##< IPv6 routing header. +const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. +const IPPROTO_ESP = 50; ##< IPv6 encapsulating security payload header. +const IPPROTO_AH = 51; ##< IPv6 authentication header. +const IPPROTO_NONE = 59; ##< IPv6 no next header. +const IPPROTO_DSTOPTS = 60; ##< IPv6 destination options header. + +## Values extracted from an IPv6 header. ## -## .. bro:see:: pkt_hdr discarder_check_ip +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts ip6_routing +## ip6_fragment ip6_ah ip6_esp +type ip6_hdr: record { + class: count; ##< Traffic class. + flow: count; ##< Flow label. + len: count; ##< Payload length. + nxt: count; ##< Next header (RFC 1700 assigned number). + hlim: count; ##< Hop limit. + src: addr; ##< Source address. + dst: addr; ##< Destination address. +}; + +## Values extracted from an IPv6 extension header's (e.g. hop-by-hop or +## destination option headers) option field. +## +## .. bro:see:: ip6_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts +type ip6_option: record { + otype: count; ##< Option type. + len: count; ##< Option data length. + data: string; ##< Option data. +}; + +## Values extracted from an IPv6 Hop-by-Hop options extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain ip6_option +type ip6_hopopts: record { + ## Next header (RFC 1700 assigned number). + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## The TLV encoded options; + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Destination options extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain ip6_option +type ip6_dstopts: record { + ## Next header (RFC 1700 assigned number). + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## The TLV encoded options; + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Routing extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +type ip6_routing: record { + ## Next header (RFC 1700 assigned number). + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## Routing type. + rtype: count; + ## Segments left. + segleft: count; + ## Type-specific data. + data: string; +}; + +## Values extracted from an IPv6 Fragment extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +type ip6_fragment: record { + ## Next header (RFC 1700 assigned number). + nxt: count; + ## 8-bit reserved field. + rsv1: count; + ## Fragmentation offset. + offset: count; + ## 2-bit reserved field. + rsv2: count; + ## More fragments. + more: bool; + ## Fragment identification. + id: count; +}; + +## Values extracted from an IPv6 Authentication extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +type ip6_ah: record { + ## Next header (RFC 1700 assigned number). + nxt: count; + ## Length of header in 4-octet units, excluding first two units. + len: count; + ## Reserved field. + rsv: count; + ## Security Parameter Index. + spi: count; + ## Sequence number. + seq: count; + ## Authentication data. + data: string; +}; + +## Values extracted from an IPv6 ESP extension header. +## +## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +type ip6_esp: record { + ## Security Parameters Index. + spi: count; + ## Sequence number. + seq: count; +}; + +## An IPv6 header chain. +## +## .. bro:see:: pkt_hdr ip_hdr +type ip6_hdr_chain: record { + ## The main IPv6 header. + hdr: ip6_hdr; + ## Hop-by-hop option extension header. + hopopts: vector of ip6_hopopts; + ## Destination option extension headers. + dstopts: vector of ip6_dstopts; + ## Routing extension headers. + routing: vector of ip6_routing; + ## Fragment headers. + fragment: vector of ip6_fragment; + ## Authentication extension headers. + ah: vector of ip6_ah; + ## Encapsulating security payload headers. + esp: vector of ip6_esp; + + ## Order of extension headers identified by RFC 1700 assigned numbers. + ext_order: vector of count; +}; + +## Values extracted from an IPv4 header. +## +## .. bro:see:: pkt_hdr ip6_hdr discarder_check_ip type ip_hdr: record { hl: count; ##< Header length in bytes. tos: count; ##< Type of service. @@ -1000,10 +1143,11 @@ type icmp_hdr: record { ## ## .. bro:see:: new_packet type pkt_hdr: record { - ip: ip_hdr; ##< The IP header. - tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet. - udp: udp_hdr &optional; ##< The UDP header if a UDP packet. - icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet. + ip: ip_hdr &optional; ##< The IPv4 header if an IPv4 packet. + ip6: ip6_hdr_chain &optional; ##< The IPv6 header chain if an IPv6 packet. + tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet. + udp: udp_hdr &optional; ##< The UDP header if a UDP packet. + icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet. }; ## Definition of "secondary filters". A secondary filter is a BPF filter given as diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d51211f0d1..26807a184f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -330,6 +330,7 @@ set(bro_SRCS IntSet.cc InterConn.cc IOSource.cc + IP.cc IPAddr.cc IRC.cc List.cc diff --git a/src/Frag.cc b/src/Frag.cc index 21abc324f8..b5c5e371d4 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -27,7 +27,7 @@ void FragTimer::Dispatch(double t, int /* is_expire */) FragReassembler::FragReassembler(NetSessions* arg_s, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field, HashKey* k, double t) + HashKey* k, double t) : Reassembler(0, ip->DstAddr(), REASSEM_IP) { s = arg_s; @@ -41,7 +41,7 @@ FragReassembler::FragReassembler(NetSessions* arg_s, reassembled_pkt = 0; frag_size = 0; // flag meaning "not known" - AddFragment(t, ip, pkt, frag_field); + AddFragment(t, ip, pkt); if ( frag_timeout != 0.0 ) { @@ -60,8 +60,7 @@ FragReassembler::~FragReassembler() delete key; } -void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field) +void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) { const struct ip* ip4 = ip->IP4_Hdr(); @@ -72,16 +71,16 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, // attack. s->Weird("fragment_protocol_inconsistency", ip); - if ( frag_field & 0x4000 ) + if ( ip->DF() ) // Linux MTU discovery for UDP can do this, for example. s->Weird("fragment_with_DF", ip); - int offset = (ntohs(ip4->ip_off) & 0x1fff) * 8; + int offset = ip->FragOffset(); int len = ntohs(ip4->ip_len); int hdr_len = proto_hdr->ip_hl * 4; int upper_seq = offset + len - hdr_len; - if ( (frag_field & 0x2000) == 0 ) + if ( ! ip->MF() ) { // Last fragment. if ( frag_size == 0 ) diff --git a/src/Frag.h b/src/Frag.h index 92bf1b3bbd..4c9886faa2 100644 --- a/src/Frag.h +++ b/src/Frag.h @@ -20,11 +20,10 @@ typedef void (FragReassembler::*frag_timer_func)(double t); class FragReassembler : public Reassembler { public: FragReassembler(NetSessions* s, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field, HashKey* k, double t); + HashKey* k, double t); ~FragReassembler(); - void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field); + void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt); void Expire(double t); void DeleteTimer(); diff --git a/src/IP.cc b/src/IP.cc new file mode 100644 index 0000000000..826ae544f6 --- /dev/null +++ b/src/IP.cc @@ -0,0 +1,273 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IP.h" +#include "Type.h" +#include "Val.h" +#include "Var.h" + +static RecordType* ip_hdr_type = 0; +static RecordType* ip6_hdr_type = 0; +static RecordType* ip6_hdr_chain_type = 0; +static RecordType* ip6_option_type = 0; +static RecordType* ip6_hopopts_type = 0; +static RecordType* ip6_dstopts_type = 0; +static RecordType* ip6_routing_type = 0; +static RecordType* ip6_fragment_type = 0; +static RecordType* ip6_ah_type = 0; +static RecordType* ip6_esp_type = 0; + +static inline RecordType* hdrType(RecordType*& type, const char* name) + { + if ( ! type ) type = internal_type(name)->AsRecordType(); + return type; + } + +RecordVal* IPv6_Hdr::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr")); + const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; + rv->Assign(0, new Val(ntohl(ip6->ip6_flow) & 0x0ff00000, TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT)); + rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT)); + rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT)); + rv->Assign(5, new AddrVal(ip6->ip6_src)); + rv->Assign(6, new AddrVal(ip6->ip6_dst)); + return rv; + } + +static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) + { + VectorVal* vv = new VectorVal(new VectorType(ip6_option_type->Ref())); + while ( len > 0 ) + { + const struct ip6_opt* opt = (const struct ip6_opt*) data; + RecordVal* rv = new RecordVal(hdrType(ip6_option_type, "ip6_option")); + rv->Assign(0, new Val(opt->ip6o_type, TYPE_COUNT)); + rv->Assign(1, new Val(opt->ip6o_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, new StringVal( + new BroString(data + off, opt->ip6o_len - off, 1))); + data += opt->ip6o_len + off; + len -= opt->ip6o_len + off; + vv->Assign(vv->Size(), rv, 0); + } + return vv; + } + +RecordVal* IPv6_HopOpts::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts")); + const struct ip6_hbh* hbh = (const struct ip6_hbh*)data; + rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + return rv; + } + +RecordVal* IPv6_DstOpts::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts")); + const struct ip6_dest* dst = (const struct ip6_dest*)data; + rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + return rv; + } + +RecordVal* IPv6_Routing::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing")); + const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data; + rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT)); + rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT)); + rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT)); + uint16 off = 4 * sizeof(uint8); + rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1))); + return rv; + } + +RecordVal* IPv6_Fragment::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment")); + const struct ip6_frag* frag = (const struct ip6_frag*)data; + rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(frag->ip6f_offlg) & 0xfff8, TYPE_COUNT)); + rv->Assign(3, new Val(ntohs(frag->ip6f_offlg) & 0x0006, TYPE_COUNT)); + rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL)); + rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT)); + return rv; + } + +RecordVal* IPv6_AH::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah")); + rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT)); + rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT)); + rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT)); + uint16 off = 3 * sizeof(uint32); + rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1))); + return rv; + } + +RecordVal* IPv6_ESP::BuildRecordVal() const + { + RecordVal* rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp")); + const uint32* esp = (const uint32*)data; + rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT)); + return rv; + } + +RecordVal* IP_Hdr::BuildRecordVal() const + { + RecordVal* rval = 0; + + if ( ! ip_hdr_type ) + { + ip_hdr_type = internal_type("ip_hdr")->AsRecordType(); + ip6_hdr_type = internal_type("ip6_hdr")->AsRecordType(); + ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType(); + ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType(); + ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType(); + ip6_routing_type = internal_type("ip6_routing")->AsRecordType(); + ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType(); + ip6_ah_type = internal_type("ip6_ah")->AsRecordType(); + ip6_esp_type = internal_type("ip6_esp")->AsRecordType(); + } + + if ( ip4 ) + { + rval = new RecordVal(ip_hdr_type); + rval->Assign(0, new Val(ip4->ip_hl * 4, TYPE_COUNT)); + rval->Assign(1, new Val(ip4->ip_tos, TYPE_COUNT)); + rval->Assign(2, new Val(ntohs(ip4->ip_len), TYPE_COUNT)); + rval->Assign(3, new Val(ntohs(ip4->ip_id), TYPE_COUNT)); + rval->Assign(4, new Val(ip4->ip_ttl, TYPE_COUNT)); + rval->Assign(5, new Val(ip4->ip_p, TYPE_COUNT)); + rval->Assign(6, new AddrVal(ip4->ip_src.s_addr)); + rval->Assign(7, new AddrVal(ip4->ip_dst.s_addr)); + } + else + { + rval = new RecordVal(ip6_hdr_chain_type); + + VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref())); + VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref())); + VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref())); + VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref())); + VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref())); + VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref())); + VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT))); + + for ( size_t i = 1; i < ip6_hdrs->Size(); ++i ) + { + RecordVal* v = ((*ip6_hdrs)[i])->BuildRecordVal(); + uint8 type = ((*ip6_hdrs)[i])->Type(); + switch (type) { + case IPPROTO_HOPOPTS: + hopopts->Assign(hopopts->Size(), v, 0); + break; + case IPPROTO_ROUTING: + routing->Assign(routing->Size(), v, 0); + break; + case IPPROTO_DSTOPTS: + dstopts->Assign(dstopts->Size(), v, 0); + break; + case IPPROTO_FRAGMENT: + fragment->Assign(fragment->Size(), v, 0); + break; + case IPPROTO_AH: + ah->Assign(ah->Size(), v, 0); + break; + case IPPROTO_ESP: + esp->Assign(esp->Size(), v, 0); + break; + case IPPROTO_IPV6: + default: + reporter->InternalError("pkt_hdr assigned bad header %d", type); + break; + } + order->Assign(i, new Val(type, TYPE_COUNT), 0); + } + + rval->Assign(0, ((*ip6_hdrs)[0])->BuildRecordVal()); + rval->Assign(1, hopopts); + rval->Assign(2, dstopts); + rval->Assign(3, routing); + rval->Assign(4, fragment); + rval->Assign(5, ah); + rval->Assign(6, esp); + rval->Assign(7, order); + } + + return rval; + } + +static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d) + { + switch (type) { + case IPPROTO_IPV6: + return new IPv6_Hdr(d); + case IPPROTO_HOPOPTS: + return new IPv6_HopOpts(d); + case IPPROTO_ROUTING: + return new IPv6_Routing(d); + case IPPROTO_DSTOPTS: + return new IPv6_DstOpts(d); + case IPPROTO_FRAGMENT: + return new IPv6_Fragment(d); + case IPPROTO_AH: + return new IPv6_AH(d); + case IPPROTO_ESP: + return new IPv6_ESP(d); + default: + // should never get here if calls are protected by isIPv6ExtHeader() + reporter->InternalError("Unknown IPv6 header type: %d", type); + break; + } + // can't be reached + assert(false); + return 0; + } + +static inline bool isIPv6ExtHeader(uint8 type) + { + switch (type) { + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_DSTOPTS: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: + case IPPROTO_ESP: + return true; + default: + return false; + } + } + +IPv6_Hdr_Chain::IPv6_Hdr_Chain(const struct ip6_hdr* ip6) + { + length = 0; + uint8 current_type, next_type; + next_type = IPPROTO_IPV6; + const u_char* hdrs = (const u_char*) ip6; + + do + { + current_type = next_type; + chain.push_back(getIPv6Header(current_type, hdrs)); + next_type = chain[chain.size()-1]->NextHdr(); + uint16 len = chain[chain.size()-1]->Length(); + hdrs += len; + length += len; + } while ( current_type != IPPROTO_FRAGMENT && + current_type != IPPROTO_ESP && + isIPv6ExtHeader(next_type) ); + } diff --git a/src/IP.h b/src/IP.h index 36e8634912..09640f47b9 100644 --- a/src/IP.h +++ b/src/IP.h @@ -4,8 +4,139 @@ #define ip_h #include "config.h" +#include "net_util.h" #include "IPAddr.h" -#include +#include "Reporter.h" +#include "Val.h" +#include "Type.h" +#include +#include +#include +#include + +/** + * Base class for IPv6 header/extensions. + */ +class IPv6_Hdr { +public: + IPv6_Hdr() : type(0), data(0) {} + + /** + * Construct the main IPv6 header. + */ + IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {} + + /** + * Construct an IPv6 header or extension header from assigned type number. + */ + IPv6_Hdr(uint8 t, const u_char* d) : type(t), data(d) {} + + virtual ~IPv6_Hdr() {} + + /** + * Returns the assigned IPv6 extension header type number of the header + * that immediately follows this one. + */ + virtual uint8 NextHdr() const { return ((ip6_hdr*)data)->ip6_nxt; } + + /** + * Returns the length of the header in bytes. + */ + virtual uint16 Length() const { return 40; } + + /** + * Returns the RFC 1700 assigned number indicating the header type. + */ + uint8 Type() const { return type; } + + /** + * Returns the script-layer record representation of the header. + */ + virtual RecordVal* BuildRecordVal() const; + +protected: + uint8 type; + const u_char* data; +}; + +class IPv6_HopOpts : public IPv6_Hdr { +public: + IPv6_HopOpts(const u_char* d) : IPv6_Hdr(IPPROTO_HOPOPTS, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_DstOpts : public IPv6_Hdr { +public: + IPv6_DstOpts(const u_char* d) : IPv6_Hdr(IPPROTO_DSTOPTS, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_Routing : public IPv6_Hdr { +public: + IPv6_Routing(const u_char* d) : IPv6_Hdr(IPPROTO_ROUTING, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_Fragment : public IPv6_Hdr { +public: + IPv6_Fragment(const u_char* d) : IPv6_Hdr(IPPROTO_FRAGMENT, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + uint16 Length() const { return 8; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_AH : public IPv6_Hdr { +public: + IPv6_AH(const u_char* d) : IPv6_Hdr(IPPROTO_AH, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_ESP : public IPv6_Hdr { +public: + IPv6_ESP(const u_char* d) : IPv6_Hdr(IPPROTO_ESP, d) {} + uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + // encrypted payload begins after 8 bytes + uint16 Length() const { return 8; } + RecordVal* BuildRecordVal() const; +}; + +class IPv6_Hdr_Chain { +public: + /** + * Initializes the header chain from an IPv6 header structure. + */ + IPv6_Hdr_Chain(const struct ip6_hdr* ip6); + + ~IPv6_Hdr_Chain() + { for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; } + + /** + * Returns the number of headers in the chain. + */ + size_t Size() const { return chain.size(); } + + /** + * Returns the sum of the length of all headers in the chain in bytes. + */ + uint16 TotalLength() const { return length; } + + /** + * Accesses the header at the given location in the chain. + */ + const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; } + +protected: + vector chain; + uint16 length; // The summation of all header lengths in the chain in bytes. +}; class IP_Hdr { public: @@ -17,10 +148,12 @@ public: IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del) : ip4(0), ip6(arg_ip6), del(arg_del) { + ip6_hdrs = new IPv6_Hdr_Chain(ip6); } ~IP_Hdr() { + if ( ip6 ) delete ip6_hdrs; if ( del ) { if ( ip4 ) @@ -30,23 +163,23 @@ public: } } + //TODO: audit usages of this for correct IPv6 support or IPv4 assumptions const struct ip* IP4_Hdr() const { return ip4; } + const struct ip6_hdr* IP6_Hdr() const { return ip6; } IPAddr SrcAddr() const { return ip4 ? IPAddr(ip4->ip_src) : IPAddr(ip6->ip6_src); } + IPAddr DstAddr() const { return ip4 ? IPAddr(ip4->ip_dst) : IPAddr(ip6->ip6_dst); } - //TODO: needs adapting/replacement for IPv6 support - uint16 ID4() const { return ip4 ? ip4->ip_id : 0; } - const u_char* Payload() const { if ( ip4 ) return ((const u_char*) ip4) + ip4->ip_hl * 4; else - return ((const u_char*) ip6) + 40; + return ((const u_char*) ip6) + ip6_hdrs->TotalLength(); } uint16 PayloadLen() const @@ -54,33 +187,60 @@ public: if ( ip4 ) return ntohs(ip4->ip_len) - ip4->ip_hl * 4; else - return ntohs(ip6->ip6_plen); + return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength(); } uint16 TotalLen() const - { - if ( ip4 ) - return ntohs(ip4->ip_len); - else - return ntohs(ip6->ip6_plen) + 40; - } + { return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; } + + uint16 HdrLen() const + { return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); } + + uint8 LastHeader() const + { return ip4 ? IPPROTO_RAW : + ((*ip6_hdrs)[ip6_hdrs->Size()-1])->Type(); } - uint16 HdrLen() const { return ip4 ? ip4->ip_hl * 4 : 40; } unsigned char NextProto() const - { return ip4 ? ip4->ip_p : ip6->ip6_nxt; } + { return ip4 ? ip4->ip_p : + ((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); } + unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; } + + //TODO: check for IPv6 Fragment ext. header + bool IsFragment() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : false; } + + //TODO: check for IPv6 Fragment ext. header + uint16 FragOffset() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : 0; } + + //TODO: check for IPv6 Fragment ext. header uint16 FragField() const - { return ntohs(ip4 ? ip4->ip_off : 0); } + { return ip4 ? ntohs(ip4->ip_off) : 0; } + + //TODO: check for IPv6 Fragment ext. header + uint16 ID() const + { return ip4 ? ntohs(ip4->ip_id) : 0; } + + //TODO: check for IPv6 Fragment ext. header + int MF() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : 0; } + + // IPv6 has no "Don't Fragment" flag. int DF() const - { return ip4 ? ((ntohs(ip4->ip_off) & IP_DF) != 0) : 0; } - uint16 IP_ID() const - { return ip4 ? (ntohs(ip4->ip_id)) : 0; } + { return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; } + + size_t NumHeaders() const + { return ip4 ? 1 : ip6_hdrs->Size(); } + + RecordVal* BuildRecordVal() const; private: const struct ip* ip4; const struct ip6_hdr* ip6; bool del; + IPv6_Hdr_Chain* ip6_hdrs; }; #endif diff --git a/src/PacketSort.cc b/src/PacketSort.cc index d0e04a37ea..7bfdaba9a0 100644 --- a/src/PacketSort.cc +++ b/src/PacketSort.cc @@ -33,7 +33,7 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, if ( ip_hdr->NextProto() == IPPROTO_TCP && // Note: can't sort fragmented packets - (ip_hdr->FragField() & 0x3fff) == 0 ) + ( ! ip_hdr->IsFragment() ) ) { tcp_offset = hdr_size + ip_hdr->HdrLen(); if ( caplen >= tcp_offset + sizeof(struct tcphdr) ) diff --git a/src/Sessions.cc b/src/Sessions.cc index 04b877dfe0..e8cece9e46 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -332,7 +332,8 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* StringVal* cmd_val = new StringVal(sp->Event()->Filter()); args->append(cmd_val); - args->append(BuildHeader(ip)); + IP_Hdr ip_hdr(ip, false); + args->append(BuildHeader(&ip_hdr)); // ### Need to queue event here. try { @@ -400,18 +401,6 @@ int NetSessions::CheckConnectionTag(Connection* conn) return 1; } - -static bool looks_like_IPv4_packet(int len, const struct ip* ip_hdr) - { - if ( (unsigned int) len < sizeof(struct ip) ) - return false; - - if ( ip_hdr->ip_v == 4 && ntohs(ip_hdr->ip_len) == len ) - return true; - else - return false; - } - void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, const IP_Hdr* ip_hdr, const u_char* const pkt, int hdr_size) @@ -441,18 +430,9 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) ) return; - int proto = ip_hdr->NextProto(); - if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && - proto != IPPROTO_ICMP ) - { - dump_this_packet = 1; - return; - } - FragReassembler* f = 0; - uint32 frag_field = ip_hdr->FragField(); - if ( (frag_field & 0x3fff) != 0 ) + if ( ip_hdr->IsFragment() ) { dump_this_packet = 1; // always record fragments @@ -463,12 +443,12 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // Don't try to reassemble, that's doomed. // Discard all except the first fragment (which // is useful in analyzing header-only traces) - if ( (frag_field & 0x1fff) != 0 ) + if ( ip_hdr->FragOffset() != 0 ) return; } else { - f = NextFragment(t, ip_hdr, pkt + hdr_size, frag_field); + f = NextFragment(t, ip_hdr, pkt + hdr_size); const IP_Hdr* ih = f->ReassembledPkt(); if ( ! ih ) // It didn't reassemble into anything yet. @@ -485,21 +465,24 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; - uint32 min_hdr_len = (proto == IPPROTO_TCP) ? sizeof(struct tcphdr) : - (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); - - if ( len < min_hdr_len ) + if ( ip_hdr->LastHeader() == IPPROTO_ESP ) { - Weird("truncated_header", hdr, pkt); - if ( f ) - Remove(f); // ### + if ( esp_packet ) + { + val_list* vl = new val_list(); + vl->append(ip_hdr->BuildRecordVal()); + mgr.QueueEvent(esp_packet, vl); + } + Remove(f); + // Can't do more since upper-layer payloads are going to be encrypted return; } - if ( caplen < min_hdr_len ) + + int proto = ip_hdr->NextProto(); + + if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt) ) { - Weird("internally_truncated_header", hdr, pkt); - if ( f ) - Remove(f); // ### + Remove(f); return; } @@ -549,6 +532,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, default: Weird(fmt("unknown_protocol %d", proto), hdr, pkt); + Remove(f); return; } @@ -574,6 +558,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( consistent < 0 ) { delete h; + Remove(f); return; } @@ -592,10 +577,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } if ( ! conn ) + { delete h; - - if ( ! conn ) + Remove(f); return; + } int record_packet = 1; // whether to record the packet at all int record_content = 1; // whether to record its data @@ -603,8 +589,17 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, int is_orig = (id.src_addr == conn->OrigAddr()) && (id.src_port == conn->OrigPort()); - if ( new_packet && ip4 ) - conn->Event(new_packet, 0, BuildHeader(ip4)); + Val* pkt_hdr_val = 0; + + if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) + { + pkt_hdr_val = BuildHeader(ip_hdr); + conn->Event(new_packet, 0, pkt_hdr_val); + } + + if ( new_packet ) + conn->Event(new_packet, 0, + pkt_hdr_val ? pkt_hdr_val->Ref() : BuildHeader(ip_hdr)); conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data, record_packet, record_content, @@ -614,7 +609,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, { // Above we already recorded the fragment in its entirety. f->DeleteTimer(); - Remove(f); // ### + Remove(f); } else if ( record_packet ) @@ -630,10 +625,39 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } } -Val* NetSessions::BuildHeader(const struct ip* ip) +bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, + const struct pcap_pkthdr* h, const u_char* p) + { + uint32 min_hdr_len = 0; + switch ( proto ) { + case IPPROTO_TCP: + min_hdr_len = sizeof(struct tcphdr); + break; + case IPPROTO_UDP: + min_hdr_len = sizeof(struct udphdr); + break; + case IPPROTO_ICMP: + default: + min_hdr_len = ICMP_MINLEN; + break; + } + if ( len < min_hdr_len ) + { + Weird("truncated_header", h, p); + return true; + } + if ( caplen < min_hdr_len ) + { + Weird("internally_truncated_header", h, p); + return true; + } + return false; + } + + +Val* NetSessions::BuildHeader(const IP_Hdr* ip) { static RecordType* pkt_hdr_type = 0; - static RecordType* ip_hdr_type = 0; static RecordType* tcp_hdr_type = 0; static RecordType* udp_hdr_type = 0; static RecordType* icmp_hdr_type; @@ -641,7 +665,6 @@ Val* NetSessions::BuildHeader(const struct ip* ip) if ( ! pkt_hdr_type ) { pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType(); - ip_hdr_type = internal_type("ip_hdr")->AsRecordType(); tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType(); udp_hdr_type = internal_type("udp_hdr")->AsRecordType(); icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType(); @@ -649,26 +672,15 @@ Val* NetSessions::BuildHeader(const struct ip* ip) RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); - RecordVal* ip_hdr = new RecordVal(ip_hdr_type); - - int ip_hdr_len = ip->ip_hl * 4; - int ip_pkt_len = ntohs(ip->ip_len); - - ip_hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT)); - ip_hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT)); - ip_hdr->Assign(2, new Val(ip_pkt_len, TYPE_COUNT)); - ip_hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT)); - ip_hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT)); - ip_hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT)); - ip_hdr->Assign(6, new AddrVal(ip->ip_src.s_addr)); - ip_hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr)); - - pkt_hdr->Assign(0, ip_hdr); + if ( ip->IP4_Hdr() ) + pkt_hdr->Assign(0, ip->BuildRecordVal()); + else + pkt_hdr->Assign(1, ip->BuildRecordVal()); // L4 header. - const u_char* data = ((const u_char*) ip) + ip_hdr_len; + const u_char* data = ip->Payload(); - int proto = ip->ip_p; + int proto = ip->NextProto(); switch ( proto ) { case IPPROTO_TCP: { @@ -676,7 +688,7 @@ Val* NetSessions::BuildHeader(const struct ip* ip) RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type); int tcp_hdr_len = tp->th_off * 4; - int data_len = ip_pkt_len - ip_hdr_len - tcp_hdr_len; + int data_len = ip->PayloadLen() - tcp_hdr_len; tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); @@ -687,7 +699,7 @@ Val* NetSessions::BuildHeader(const struct ip* ip) tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); - pkt_hdr->Assign(1, tcp_hdr); + pkt_hdr->Assign(2, tcp_hdr); break; } @@ -700,7 +712,7 @@ Val* NetSessions::BuildHeader(const struct ip* ip) udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); - pkt_hdr->Assign(2, udp_hdr); + pkt_hdr->Assign(3, udp_hdr); break; } @@ -711,7 +723,7 @@ Val* NetSessions::BuildHeader(const struct ip* ip) icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); - pkt_hdr->Assign(3, icmp_hdr); + pkt_hdr->Assign(4, icmp_hdr); break; } @@ -725,9 +737,9 @@ Val* NetSessions::BuildHeader(const struct ip* ip) } FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt, uint32 frag_field) + const u_char* pkt) { - uint32 frag_id = ntohs(ip->ID4()); // we actually could skip conv. + uint32 frag_id = ip->ID(); ListVal* key = new ListVal(TYPE_ANY); key->Append(new AddrVal(ip->SrcAddr())); @@ -741,7 +753,7 @@ FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, FragReassembler* f = fragments.Lookup(h); if ( ! f ) { - f = new FragReassembler(this, ip, pkt, frag_field, h, t); + f = new FragReassembler(this, ip, pkt, h, t); fragments.Insert(h, f); Unref(key); return f; @@ -750,7 +762,7 @@ FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, delete h; Unref(key); - f->AddFragment(t, ip, pkt, frag_field); + f->AddFragment(t, ip, pkt); return f; } @@ -909,6 +921,7 @@ void NetSessions::Remove(Connection* c) void NetSessions::Remove(FragReassembler* f) { + if ( ! f ) return; HashKey* k = f->Key(); if ( ! k ) reporter->InternalError("fragment block not in dictionary"); diff --git a/src/Sessions.h b/src/Sessions.h index 0a6338899b..ac5fcacfb5 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -79,7 +79,7 @@ public: // Returns a reassembled packet, or nil if there are still // some missing fragments. FragReassembler* NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt, uint32 frag_field); + const u_char* pkt); int Get_OS_From_SYN(struct os_type* retval, uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS, @@ -193,7 +193,13 @@ protected: // Builds a record encapsulating a packet. This should be more // general, including the equivalent of a union of tcp/udp/icmp // headers . - Val* BuildHeader(const struct ip* ip); + Val* BuildHeader(const IP_Hdr* ip); + + // For a given protocol, checks whether the header's length as derived + // from lower-level headers or the length actually captured is less + // than that protocol's minimum header size. + bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, + const struct pcap_pkthdr* hdr, const u_char* pkt); CompositeHash* ch; PDict(Connection) tcp_conns; diff --git a/src/TCP.cc b/src/TCP.cc index 3315db79f3..57e4449bf8 100644 --- a/src/TCP.cc +++ b/src/TCP.cc @@ -1203,7 +1203,7 @@ RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip, if ( ip->HdrLen() > 20 ) quirks |= QUIRK_IPOPT; - if ( ip->IP_ID() == 0 ) + if ( ip->ID() == 0 ) quirks |= QUIRK_ZEROID; if ( tcp->th_seq == 0 ) @@ -1942,11 +1942,11 @@ int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, { if ( ++num_pkts == 1 ) { // First packet. - last_id = ntohs(ip->ID4()); + last_id = ip->ID(); return 0; } - int id = ntohs(ip->ID4()); + int id = ip->ID(); if ( id == last_id ) { diff --git a/src/event.bif b/src/event.bif index 1423750f29..1745139f11 100644 --- a/src/event.bif +++ b/src/event.bif @@ -454,11 +454,30 @@ event expected_connection_seen%(c: connection, a: count%); ## ## c: The connection the packet is part of. ## -## p: Informattion from the header of the packet that triggered the event. +## p: Information from the header of the packet that triggered the event. ## ## .. bro:see:: tcp_packet packet_contents event new_packet%(c: connection, p: pkt_hdr%); +## Generated for every IPv6 packet that contains extension headers. +## This is potentially an expensive event to handle if analysiing IPv6 traffic +## that happens to utilize extension headers frequently. +## +## c: The connection the packet is part of. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet tcp_packet packet_contents esp_packet +event ipv6_ext_headers%(c: connection, p: pkt_hdr%); + +## Generated for any packets using the IPv6 Encapsulating Security Payload (ESP) +## extension header. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet tcp_packet ipv6_ext_headers +event esp_packet%(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 From 9d590456b00628ba258cb0a3eedbe167dbeaf39c Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 6 Mar 2012 16:08:28 -0600 Subject: [PATCH 02/13] Add IPv6 fragment reassembly. --- src/Frag.cc | 57 +++++++++++++++---- src/Frag.h | 3 +- src/IP.cc | 27 ++++----- src/IP.h | 154 +++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 180 insertions(+), 61 deletions(-) diff --git a/src/Frag.cc b/src/Frag.cc index b5c5e371d4..cbdae92883 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -33,13 +33,23 @@ FragReassembler::FragReassembler(NetSessions* arg_s, s = arg_s; key = k; const struct ip* ip4 = ip->IP4_Hdr(); - proto_hdr_len = ip4->ip_hl * 4; - proto_hdr = (struct ip*) new u_char[64]; // max IP header + slop - // Don't do a structure copy - need to pick up options, too. - memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); + if ( ip4 ) + { + proto_hdr_len = ip4->ip_hl * 4; + proto_hdr = new u_char[64]; // max IP header + slop + // Don't do a structure copy - need to pick up options, too. + memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); + } + else + { + proto_hdr_len = ip->HdrLen() - 8; // minus length of fragment header + proto_hdr = new u_char[proto_hdr_len]; + memcpy(proto_hdr, ip->IP6_Hdr(), proto_hdr_len); + } reassembled_pkt = 0; frag_size = 0; // flag meaning "not known" + next_proto = ip->NextProto(); AddFragment(t, ip, pkt); @@ -64,22 +74,37 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) { const struct ip* ip4 = ip->IP4_Hdr(); - if ( ip4->ip_p != proto_hdr->ip_p || ip4->ip_hl != proto_hdr->ip_hl ) + if ( ip4 ) + { + if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p || + ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl ) // || ip4->ip_tos != proto_hdr->ip_tos // don't check TOS, there's at least one stack that actually // uses different values, and it's hard to see an associated // attack. s->Weird("fragment_protocol_inconsistency", ip); + } + else + { + if ( ip->NextProto() != next_proto || + ip->HdrLen() - 8 != proto_hdr_len ) + s->Weird("fragment_protocol_inconsistency", ip); + //TODO: more detailed unfrag header consistency checks? + } if ( ip->DF() ) // Linux MTU discovery for UDP can do this, for example. s->Weird("fragment_with_DF", ip); int offset = ip->FragOffset(); - int len = ntohs(ip4->ip_len); - int hdr_len = proto_hdr->ip_hl * 4; + int len = ip->TotalLen(); + int hdr_len = ip->HdrLen(); int upper_seq = offset + len - hdr_len; + if ( ! offset ) + // Make sure to use the first fragment header's next field. + next_proto = ip->NextProto(); + if ( ! ip->MF() ) { // Last fragment. @@ -192,8 +217,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) u_char* pkt = new u_char[n]; memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len); - struct ip* reassem4 = (struct ip*) pkt; - reassem4->ip_len = htons(frag_size + proto_hdr_len); + u_char* pkt_start = pkt; pkt += proto_hdr_len; @@ -213,7 +237,20 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) } delete reassembled_pkt; - reassembled_pkt = new IP_Hdr(reassem4, true); + + if ( ((const struct ip*)pkt_start)->ip_v == 4 ) + { + struct ip* reassem4 = (struct ip*) pkt_start; + reassem4->ip_len = htons(frag_size + proto_hdr_len); + reassembled_pkt = new IP_Hdr(reassem4, true); + } + else + { + struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; + reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); + const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto); + reassembled_pkt = new IP_Hdr(reassem6, true, chain); + } DeleteTimer(); } diff --git a/src/Frag.h b/src/Frag.h index 4c9886faa2..86cf3a9dd4 100644 --- a/src/Frag.h +++ b/src/Frag.h @@ -36,11 +36,12 @@ protected: void BlockInserted(DataBlock* start_block); void Overlap(const u_char* b1, const u_char* b2, int n); - struct ip* proto_hdr; + u_char* proto_hdr; IP_Hdr* reassembled_pkt; int proto_hdr_len; NetSessions* s; int frag_size; // size of fully reassembled fragment + uint16 next_proto; // first IPv6 fragment header's next proto field HashKey* key; FragTimer* expire_timer; diff --git a/src/IP.cc b/src/IP.cc index 826ae544f6..ce8514519a 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -26,7 +26,7 @@ RecordVal* IPv6_Hdr::BuildRecordVal() const { RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr")); const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; - rv->Assign(0, new Val(ntohl(ip6->ip6_flow) & 0x0ff00000, TYPE_COUNT)); + rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT)); rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT)); rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT)); rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT)); @@ -96,8 +96,8 @@ RecordVal* IPv6_Fragment::BuildRecordVal() const const struct ip6_frag* frag = (const struct ip6_frag*)data; rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT)); rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT)); - rv->Assign(2, new Val(ntohs(frag->ip6f_offlg) & 0xfff8, TYPE_COUNT)); - rv->Assign(3, new Val(ntohs(frag->ip6f_offlg) & 0x0006, TYPE_COUNT)); + rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT)); + rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT)); rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL)); rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT)); return rv; @@ -210,23 +210,24 @@ RecordVal* IP_Hdr::BuildRecordVal() const return rval; } -static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d) +static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d, + bool set_next = false, uint16 nxt = 0) { switch (type) { case IPPROTO_IPV6: - return new IPv6_Hdr(d); + return set_next ? new IPv6_Hdr(d, nxt) : new IPv6_Hdr(d); case IPPROTO_HOPOPTS: - return new IPv6_HopOpts(d); + return set_next ? new IPv6_HopOpts(d, nxt) : new IPv6_HopOpts(d); case IPPROTO_ROUTING: - return new IPv6_Routing(d); + return set_next ? new IPv6_Routing(d, nxt) : new IPv6_Routing(d); case IPPROTO_DSTOPTS: - return new IPv6_DstOpts(d); + return set_next ? new IPv6_DstOpts(d, nxt) : new IPv6_DstOpts(d); case IPPROTO_FRAGMENT: - return new IPv6_Fragment(d); + return set_next ? new IPv6_Fragment(d, nxt) : new IPv6_Fragment(d); case IPPROTO_AH: - return new IPv6_AH(d); + return set_next ? new IPv6_AH(d, nxt) : new IPv6_AH(d); case IPPROTO_ESP: - return new IPv6_ESP(d); + return new IPv6_ESP(d); // never able to set ESP header's next default: // should never get here if calls are protected by isIPv6ExtHeader() reporter->InternalError("Unknown IPv6 header type: %d", type); @@ -252,7 +253,7 @@ static inline bool isIPv6ExtHeader(uint8 type) } } -IPv6_Hdr_Chain::IPv6_Hdr_Chain(const struct ip6_hdr* ip6) +void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) { length = 0; uint8 current_type, next_type; @@ -262,7 +263,7 @@ IPv6_Hdr_Chain::IPv6_Hdr_Chain(const struct ip6_hdr* ip6) do { current_type = next_type; - chain.push_back(getIPv6Header(current_type, hdrs)); + chain.push_back(getIPv6Header(current_type, hdrs, set_next, next)); next_type = chain[chain.size()-1]->NextHdr(); uint16 len = chain[chain.size()-1]->Length(); hdrs += len; diff --git a/src/IP.h b/src/IP.h index 09640f47b9..be3d568375 100644 --- a/src/IP.h +++ b/src/IP.h @@ -26,6 +26,16 @@ public: */ IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {} + /** + * Construct the main IPv6 header, but replace the next protocol field + * if it points to a fragment. + */ + IPv6_Hdr(const u_char* d, uint16 nxt) : type(IPPROTO_IPV6), data(d) + { + if ( ((ip6_hdr*)data)->ip6_nxt == IPPROTO_FRAGMENT ) + ((ip6_hdr*)data)->ip6_nxt = nxt; + } + /** * Construct an IPv6 header or extension header from assigned type number. */ @@ -49,6 +59,11 @@ public: */ uint8 Type() const { return type; } + /** + * Returns pointer to the start of where header structure resides in memory. + */ + const u_char* Data() const { return data; } + /** * Returns the script-layer record representation of the header. */ @@ -59,50 +74,63 @@ protected: const u_char* data; }; -class IPv6_HopOpts : public IPv6_Hdr { +class IPv6_Ext : public IPv6_Hdr { public: - IPv6_HopOpts(const u_char* d) : IPv6_Hdr(IPPROTO_HOPOPTS, d) {} + IPv6_Ext(uint16 type, const u_char* d) : IPv6_Hdr(type, d) {} + IPv6_Ext(uint16 type, const u_char* d, uint16 nxt) : IPv6_Hdr(type, d) + { + if ( ((ip6_ext*)data)->ip6e_nxt == IPPROTO_FRAGMENT ) + ((ip6_ext*)data)->ip6e_nxt = nxt; + } uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + virtual uint16 Length() const = 0; + virtual RecordVal* BuildRecordVal() const = 0; +}; + +class IPv6_HopOpts : public IPv6_Ext { +public: + IPv6_HopOpts(const u_char* d) : IPv6_Ext(IPPROTO_HOPOPTS, d) {} + IPv6_HopOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_HOPOPTS, d, n) {} uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } RecordVal* BuildRecordVal() const; }; -class IPv6_DstOpts : public IPv6_Hdr { +class IPv6_DstOpts : public IPv6_Ext { public: - IPv6_DstOpts(const u_char* d) : IPv6_Hdr(IPPROTO_DSTOPTS, d) {} - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + IPv6_DstOpts(const u_char* d) : IPv6_Ext(IPPROTO_DSTOPTS, d) {} + IPv6_DstOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_DSTOPTS, d, n) {} uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } RecordVal* BuildRecordVal() const; }; -class IPv6_Routing : public IPv6_Hdr { +class IPv6_Routing : public IPv6_Ext { public: - IPv6_Routing(const u_char* d) : IPv6_Hdr(IPPROTO_ROUTING, d) {} - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + IPv6_Routing(const u_char* d) : IPv6_Ext(IPPROTO_ROUTING, d) {} + IPv6_Routing(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_ROUTING, d, n) {} uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } RecordVal* BuildRecordVal() const; }; -class IPv6_Fragment : public IPv6_Hdr { +class IPv6_Fragment : public IPv6_Ext { public: - IPv6_Fragment(const u_char* d) : IPv6_Hdr(IPPROTO_FRAGMENT, d) {} - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + IPv6_Fragment(const u_char* d) : IPv6_Ext(IPPROTO_FRAGMENT, d) {} + IPv6_Fragment(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_FRAGMENT, d, n) + {} uint16 Length() const { return 8; } RecordVal* BuildRecordVal() const; }; -class IPv6_AH : public IPv6_Hdr { +class IPv6_AH : public IPv6_Ext { public: - IPv6_AH(const u_char* d) : IPv6_Hdr(IPPROTO_AH, d) {} - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + IPv6_AH(const u_char* d) : IPv6_Ext(IPPROTO_AH, d) {} + IPv6_AH(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_AH, d, n) {} uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; } RecordVal* BuildRecordVal() const; }; -class IPv6_ESP : public IPv6_Hdr { +class IPv6_ESP : public IPv6_Ext { public: - IPv6_ESP(const u_char* d) : IPv6_Hdr(IPPROTO_ESP, d) {} - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } + IPv6_ESP(const u_char* d) : IPv6_Ext(IPPROTO_ESP, d) {} // encrypted payload begins after 8 bytes uint16 Length() const { return 8; } RecordVal* BuildRecordVal() const; @@ -113,7 +141,14 @@ public: /** * Initializes the header chain from an IPv6 header structure. */ - IPv6_Hdr_Chain(const struct ip6_hdr* ip6); + IPv6_Hdr_Chain(const struct ip6_hdr* ip6) { Init(ip6, false); } + + /** + * Initializes the header chain from an IPv6 header structure, and replaces + * the first next protocol pointer field that points to a fragment header. + */ + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next) + { Init(ip6, true, next); } ~IPv6_Hdr_Chain() { for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; } @@ -133,22 +168,73 @@ public: */ const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; } + /** + * Returns whether the header chain indicates a fragmented packet. + */ + bool IsFragment() const + { return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT; } + + /** + * Returns pointer to fragment header structure if the chain contains one. + */ + const struct ip6_frag* GetFragHdr() const + { return IsFragment() ? + (const struct ip6_frag*)chain[chain.size()-1]->Data(): 0; } + + /** + * If the header chain is a fragment, returns the offset in number of bytes + * relative to the start of the Fragmentable Part of the original packet. + */ + uint16 FragOffset() const + { return IsFragment() ? + (ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0; } + + /** + * If the header chain is a fragment, returns the identification field. + */ + uint32 ID() const + { return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; } + + /** + * If the header chain is a fragment, returns the M (more fragments) flag. + */ + int MF() const + { return IsFragment() ? + (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; } + protected: + void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0); + vector chain; uint16 length; // The summation of all header lengths in the chain in bytes. }; class IP_Hdr { public: + IP_Hdr(const u_char* p, bool arg_del) + : ip4(0), ip6(0), del(arg_del), ip6_hdrs(0) + { + if ( ((const struct ip*)p)->ip_v == 4 ) + ip4 = (const struct ip*)p; + else if ( ((const struct ip*)p)->ip_v == 6 ) + { + ip6 = (const struct ip6_hdr*)p; + ip6_hdrs = new IPv6_Hdr_Chain(ip6); + } + else if ( arg_del ) + delete [] p; + } + IP_Hdr(const struct ip* arg_ip4, bool arg_del) - : ip4(arg_ip4), ip6(0), del(arg_del) + : ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0) { } - IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del) - : ip4(0), ip6(arg_ip6), del(arg_del) + IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, + const IPv6_Hdr_Chain* c = 0) + : ip4(0), ip6(arg_ip6), del(arg_del), + ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6)) { - ip6_hdrs = new IPv6_Hdr_Chain(ip6); } ~IP_Hdr() @@ -190,7 +276,7 @@ public: return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength(); } - uint16 TotalLen() const + uint32 TotalLen() const { return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; } uint16 HdrLen() const @@ -207,25 +293,19 @@ public: unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; } - //TODO: check for IPv6 Fragment ext. header bool IsFragment() const - { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : false; } + { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : + ip6_hdrs->IsFragment(); } - //TODO: check for IPv6 Fragment ext. header uint16 FragOffset() const - { return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : 0; } + { return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : + ip6_hdrs->FragOffset(); } - //TODO: check for IPv6 Fragment ext. header - uint16 FragField() const - { return ip4 ? ntohs(ip4->ip_off) : 0; } + uint32 ID() const + { return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); } - //TODO: check for IPv6 Fragment ext. header - uint16 ID() const - { return ip4 ? ntohs(ip4->ip_id) : 0; } - - //TODO: check for IPv6 Fragment ext. header int MF() const - { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : 0; } + { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); } // IPv6 has no "Don't Fragment" flag. int DF() const @@ -240,7 +320,7 @@ private: const struct ip* ip4; const struct ip6_hdr* ip6; bool del; - IPv6_Hdr_Chain* ip6_hdrs; + const IPv6_Hdr_Chain* ip6_hdrs; }; #endif From 65307764f476c9f06804f26712b3adde3450ef8e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 7 Mar 2012 12:40:01 -0600 Subject: [PATCH 03/13] Fix some IPv6 header related bugs. - IPv6 payload length calculation didn't count main 40 byte IPv6 header. - Fix how IPv6 headers that use TLV options are built. - Fix ip6_hdr_chain$ext_order starting index at 1 instead of 0. --- src/IP.cc | 34 +++++++++++++++++++++++++--------- src/IP.h | 2 +- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/IP.cc b/src/IP.cc index ce8514519a..8a102e8542 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -38,18 +38,34 @@ RecordVal* IPv6_Hdr::BuildRecordVal() const static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) { - VectorVal* vv = new VectorVal(new VectorType(ip6_option_type->Ref())); + VectorVal* vv = new VectorVal(new VectorType( + hdrType(ip6_option_type, "ip6_option")->Ref())); + while ( len > 0 ) { const struct ip6_opt* opt = (const struct ip6_opt*) data; - RecordVal* rv = new RecordVal(hdrType(ip6_option_type, "ip6_option")); + RecordVal* rv = new RecordVal(ip6_option_type); rv->Assign(0, new Val(opt->ip6o_type, TYPE_COUNT)); - rv->Assign(1, new Val(opt->ip6o_len, TYPE_COUNT)); - uint16 off = 2 * sizeof(uint8); - rv->Assign(2, new StringVal( - new BroString(data + off, opt->ip6o_len - off, 1))); - data += opt->ip6o_len + off; - len -= opt->ip6o_len + off; + + if ( opt->ip6o_type == 0 ) + { + // Pad1 option + rv->Assign(1, new Val(0, TYPE_COUNT)); + rv->Assign(2, new StringVal("")); + data += sizeof(uint8); + len -= sizeof(uint8); + } + else + { + // PadN or other option + uint16 off = 2 * sizeof(uint8); + rv->Assign(1, new Val(opt->ip6o_len, TYPE_COUNT)); + rv->Assign(2, new StringVal( + new BroString(data + off, opt->ip6o_len, 1))); + data += opt->ip6o_len + off; + len -= opt->ip6o_len + off; + } + vv->Assign(vv->Size(), rv, 0); } return vv; @@ -194,7 +210,7 @@ RecordVal* IP_Hdr::BuildRecordVal() const reporter->InternalError("pkt_hdr assigned bad header %d", type); break; } - order->Assign(i, new Val(type, TYPE_COUNT), 0); + order->Assign(i-1, new Val(type, TYPE_COUNT), 0); } rval->Assign(0, ((*ip6_hdrs)[0])->BuildRecordVal()); diff --git a/src/IP.h b/src/IP.h index be3d568375..8918f9da5b 100644 --- a/src/IP.h +++ b/src/IP.h @@ -273,7 +273,7 @@ public: if ( ip4 ) return ntohs(ip4->ip_len) - ip4->ip_hl * 4; else - return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength(); + return ntohs(ip6->ip6_plen) + 40 - ip6_hdrs->TotalLength(); } uint32 TotalLen() const From 76ef36e048c5ccf6298da06b3aee63e5a2864720 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 7 Mar 2012 14:17:56 -0600 Subject: [PATCH 04/13] Add a few comments to IP.h --- src/IP.h | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/IP.h b/src/IP.h index 8918f9da5b..62391ca8fc 100644 --- a/src/IP.h +++ b/src/IP.h @@ -260,6 +260,10 @@ public: IPAddr DstAddr() const { return ip4 ? IPAddr(ip4->ip_dst) : IPAddr(ip6->ip6_dst); } + /** + * Returns a pointer to the payload of the IP packet, usually an + * upper-layer protocol. + */ const u_char* Payload() const { if ( ip4 ) @@ -268,6 +272,10 @@ public: return ((const u_char*) ip6) + ip6_hdrs->TotalLength(); } + /** + * Returns the length of the IP packet's payload (length of packet minus + * header length or, for IPv6, also minus length of all extension headers). + */ uint16 PayloadLen() const { if ( ip4 ) @@ -276,16 +284,30 @@ public: return ntohs(ip6->ip6_plen) + 40 - ip6_hdrs->TotalLength(); } + /** + * Returns the length of the IP packet (length of headers and payload). + */ uint32 TotalLen() const { return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; } + /** + * Returns length of IP packet header (includes extension headers for IPv6). + */ uint16 HdrLen() const { return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); } + /** + * For IPv6 header chains, returns the type of the last header in the chain. + */ uint8 LastHeader() const { return ip4 ? IPPROTO_RAW : ((*ip6_hdrs)[ip6_hdrs->Size()-1])->Type(); } + /** + * Returns the protocol type of the IP packet's payload, usually an + * upper-layer protocol. For IPv6, this returns the last (extension) + * header's Next Header value. + */ unsigned char NextProto() const { return ip4 ? ip4->ip_p : ((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); } @@ -297,23 +319,42 @@ public: { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : ip6_hdrs->IsFragment(); } + /** + * Returns the fragment packet's offset in relation to the original + * packet in bytes. + */ uint16 FragOffset() const { return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : ip6_hdrs->FragOffset(); } + /** + * Returns the fragment packet's identification field. + */ uint32 ID() const { return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); } + /** + * Returns whether a fragment packet's "More Fragments" field is set. + */ int MF() const { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); } - // IPv6 has no "Don't Fragment" flag. + /** + * Returns whether a fragment packet's "Don't Fragment" field is set. + * Note that IPv6 has no such field. + */ int DF() const { return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; } + /** + * Returns number of IP headers in packet (includes IPv6 extension headers). + */ size_t NumHeaders() const { return ip4 ? 1 : ip6_hdrs->Size(); } + /** + * Returns an ip_hdr or ip6_hdr_chain RecordVal. + */ RecordVal* BuildRecordVal() const; private: From 0b32c980bf6117d3149d4ce8d41aa46df11c27e4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 8 Mar 2012 13:12:04 -0600 Subject: [PATCH 05/13] Update PacketFilter/Discarder code for IP version independence. The signatures of script-layer functions 'discarder_check_ip', 'discarder_check_tcp', 'discarder_check_udp', and 'discarder_check_icmp' were changed to use the more general 'pkt_hdr' type as a parameter instead of individual header types. --- scripts/base/init-bare.bro | 21 ++-- src/Discard.cc | 83 ++-------------- src/Discard.h | 9 -- src/IP.cc | 84 +++++++++++++++- src/IP.h | 9 +- src/PacketFilter.cc | 7 +- src/Sessions.cc | 90 +---------------- src/Sessions.h | 5 - .../bifs.install_src_addr_filter/output | 8 ++ testing/btest/Baseline/core.discarder/output | 24 +++++ testing/btest/Traces/icmp-unreach.trace | Bin 0 -> 234 bytes .../btest/bifs/install_src_addr_filter.test | 13 +++ testing/btest/core/discarder.bro | 92 ++++++++++++++++++ 13 files changed, 251 insertions(+), 194 deletions(-) create mode 100644 testing/btest/Baseline/bifs.install_src_addr_filter/output create mode 100644 testing/btest/Baseline/core.discarder/output create mode 100644 testing/btest/Traces/icmp-unreach.trace create mode 100644 testing/btest/bifs/install_src_addr_filter.test create mode 100644 testing/btest/core/discarder.bro diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c007bd8262..a031080f0e 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -1167,7 +1167,7 @@ global discarder_maxlen = 128 &redef; ## analysis. If the function signals to discard a packet, no further processing ## will be performed on it. ## -## i: The IP header of the considered packet. +## p: The IP header of the considered packet. ## ## Returns: True if the packet should not be analyzed any further. ## @@ -1176,15 +1176,15 @@ global discarder_maxlen = 128 &redef; ## ## .. note:: This is very low-level functionality and potentially expensive. ## Avoid using it. -global discarder_check_ip: function(i: ip_hdr): bool; +global discarder_check_ip: function(p: pkt_hdr): bool; ## Function for skipping packets based on their TCP header. If defined, this ## function will be called for all TCP packets before Bro performs any further ## analysis. If the function signals to discard a packet, no further processing ## will be performed on it. ## -## i: The IP header of the considered packet. -## t: The TCP header. +## p: The IP and TCP headers of the considered packet. +## ## d: Up to :bro:see:`discarder_maxlen` bytes of the TCP payload. ## ## Returns: True if the packet should not be analyzed any further. @@ -1194,15 +1194,15 @@ global discarder_check_ip: function(i: ip_hdr): bool; ## ## .. note:: This is very low-level functionality and potentially expensive. ## Avoid using it. -global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool; +global discarder_check_tcp: function(p: pkt_hdr, d: string): bool; ## Function for skipping packets based on their UDP header. If defined, this ## function will be called for all UDP packets before Bro performs any further ## analysis. If the function signals to discard a packet, no further processing ## will be performed on it. ## -## i: The IP header of the considered packet. -## t: The UDP header. +## p: The IP and UDP headers of the considered packet. +## ## d: Up to :bro:see:`discarder_maxlen` bytes of the UDP payload. ## ## Returns: True if the packet should not be analyzed any further. @@ -1212,15 +1212,14 @@ global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool; ## ## .. note:: This is very low-level functionality and potentially expensive. ## Avoid using it. -global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool; +global discarder_check_udp: function(p: pkt_hdr, d: string): bool; ## Function for skipping packets based on their ICMP header. If defined, this ## function will be called for all ICMP packets before Bro performs any further ## analysis. If the function signals to discard a packet, no further processing ## will be performed on it. ## -## i: The IP header of the considered packet. -## ih: The ICMP header. +## p: The IP and ICMP headers of the considered packet. ## ## Returns: True if the packet should not be analyzed any further. ## @@ -1229,7 +1228,7 @@ global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool; ## ## .. note:: This is very low-level functionality and potentially expensive. ## Avoid using it. -global discarder_check_icmp: function(i: ip_hdr, ih: icmp_hdr): bool; +global discarder_check_icmp: function(p: pkt_hdr): bool; ## Bro's watchdog interval. const watchdog_interval = 10 sec &redef; diff --git a/src/Discard.cc b/src/Discard.cc index a71b810601..edfeea1408 100644 --- a/src/Discard.cc +++ b/src/Discard.cc @@ -10,11 +10,6 @@ Discarder::Discarder() { - ip_hdr = internal_type("ip_hdr")->AsRecordType(); - tcp_hdr = internal_type("tcp_hdr")->AsRecordType(); - udp_hdr = internal_type("udp_hdr")->AsRecordType(); - icmp_hdr = internal_type("icmp_hdr")->AsRecordType(); - check_ip = internal_func("discarder_check_ip"); check_tcp = internal_func("discarder_check_tcp"); check_udp = internal_func("discarder_check_udp"); @@ -36,12 +31,10 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) { int discard_packet = 0; - const struct ip* ip4 = ip->IP4_Hdr(); - if ( check_ip ) { val_list* args = new val_list; - args->append(BuildHeader(ip4)); + args->append(ip->BuildPktHdrVal()); try { @@ -59,19 +52,18 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) return discard_packet; } - int proto = ip4->ip_p; + int proto = ip->NextProto(); if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && proto != IPPROTO_ICMP ) // This is not a protocol we understand. return 0; // XXX shall we only check the first packet??? - uint32 frag_field = ntohs(ip4->ip_off); - if ( (frag_field & 0x3fff) != 0 ) + if ( ip->IsFragment() ) // Never check any fragment. return 0; - int ip_hdr_len = ip4->ip_hl * 4; + int ip_hdr_len = ip->HdrLen(); len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; @@ -87,7 +79,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) // Where the data starts - if this is a protocol we know about, // this gets advanced past the transport header. - const u_char* data = ((u_char*) ip4 + ip_hdr_len); + const u_char* data = ip->Payload(); if ( is_tcp ) { @@ -97,8 +89,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) int th_len = tp->th_off * 4; val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(tp, len)); + args->append(ip->BuildPktHdrVal()); args->append(BuildData(data, th_len, len, caplen)); try @@ -123,8 +114,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) int uh_len = sizeof (struct udphdr); val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(up)); + args->append(ip->BuildPktHdrVal()); args->append(BuildData(data, uh_len, len, caplen)); try @@ -148,8 +138,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) const struct icmp* ih = (const struct icmp*) data; val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(ih)); + args->append(ip->BuildPktHdrVal()); try { @@ -168,62 +157,6 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) return discard_packet; } -Val* Discarder::BuildHeader(const struct ip* ip) - { - RecordVal* hdr = new RecordVal(ip_hdr); - - hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT)); - hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT)); - hdr->Assign(2, new Val(ntohs(ip->ip_len), TYPE_COUNT)); - hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT)); - hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT)); - hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT)); - hdr->Assign(6, new AddrVal(ip->ip_src.s_addr)); - hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct tcphdr* tp, int tcp_len) - { - RecordVal* hdr = new RecordVal(tcp_hdr); - - hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); - hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); - hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); - hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); - - int tcp_hdr_len = tp->th_off * 4; - - hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); - hdr->Assign(5, new Val(tcp_len - tcp_hdr_len, TYPE_COUNT)); - - hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); - hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct udphdr* up) - { - RecordVal* hdr = new RecordVal(udp_hdr); - - hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); - hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); - hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct icmp* icmp) - { - RecordVal* hdr = new RecordVal(icmp_hdr); - - hdr->Assign(0, new Val(icmp->icmp_type, TYPE_COUNT)); - - return hdr; - } - Val* Discarder::BuildData(const u_char* data, int hdrlen, int len, int caplen) { len -= hdrlen; diff --git a/src/Discard.h b/src/Discard.h index 16f7a58e6e..f4daabefa7 100644 --- a/src/Discard.h +++ b/src/Discard.h @@ -25,17 +25,8 @@ public: int NextPacket(const IP_Hdr* ip, int len, int caplen); protected: - Val* BuildHeader(const struct ip* ip); - Val* BuildHeader(const struct tcphdr* tp, int tcp_len); - Val* BuildHeader(const struct udphdr* up); - Val* BuildHeader(const struct icmp* icmp); Val* BuildData(const u_char* data, int hdrlen, int len, int caplen); - RecordType* ip_hdr; - RecordType* tcp_hdr; - RecordType* udp_hdr; - RecordType* icmp_hdr; - Func* check_ip; Func* check_tcp; Func* check_udp; diff --git a/src/IP.cc b/src/IP.cc index 8a102e8542..77797ece8f 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -141,7 +141,7 @@ RecordVal* IPv6_ESP::BuildRecordVal() const return rv; } -RecordVal* IP_Hdr::BuildRecordVal() const +RecordVal* IP_Hdr::BuildIPHdrVal() const { RecordVal* rval = 0; @@ -226,6 +226,88 @@ RecordVal* IP_Hdr::BuildRecordVal() const return rval; } +RecordVal* IP_Hdr::BuildPktHdrVal() const + { + static RecordType* pkt_hdr_type = 0; + static RecordType* tcp_hdr_type = 0; + static RecordType* udp_hdr_type = 0; + static RecordType* icmp_hdr_type = 0; + + if ( ! pkt_hdr_type ) + { + pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType(); + tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType(); + udp_hdr_type = internal_type("udp_hdr")->AsRecordType(); + icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType(); + } + + RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); + + if ( ip4 ) + pkt_hdr->Assign(0, BuildIPHdrVal()); + else + pkt_hdr->Assign(1, BuildIPHdrVal()); + + // L4 header. + const u_char* data = Payload(); + + int proto = NextProto(); + switch ( proto ) { + case IPPROTO_TCP: + { + const struct tcphdr* tp = (const struct tcphdr*) data; + RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type); + + int tcp_hdr_len = tp->th_off * 4; + int data_len = PayloadLen() - tcp_hdr_len; + + tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); + tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); + tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); + tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); + tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); + tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT)); + tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); + tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); + + pkt_hdr->Assign(2, tcp_hdr); + break; + } + + case IPPROTO_UDP: + { + const struct udphdr* up = (const struct udphdr*) data; + RecordVal* udp_hdr = new RecordVal(udp_hdr_type); + + udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); + udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); + udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); + + pkt_hdr->Assign(3, udp_hdr); + break; + } + + case IPPROTO_ICMP: + { + const struct icmp* icmpp = (const struct icmp *) data; + RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); + + icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); + + pkt_hdr->Assign(4, icmp_hdr); + break; + } + + default: + { + // This is not a protocol we understand. + break; + } + } + + return pkt_hdr; + } + static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d, bool set_next = false, uint16 nxt = 0) { diff --git a/src/IP.h b/src/IP.h index 62391ca8fc..53fe1daf84 100644 --- a/src/IP.h +++ b/src/IP.h @@ -249,7 +249,6 @@ public: } } - //TODO: audit usages of this for correct IPv6 support or IPv4 assumptions const struct ip* IP4_Hdr() const { return ip4; } const struct ip6_hdr* IP6_Hdr() const { return ip6; } @@ -355,7 +354,13 @@ public: /** * Returns an ip_hdr or ip6_hdr_chain RecordVal. */ - RecordVal* BuildRecordVal() const; + RecordVal* BuildIPHdrVal() const; + + /** + * Returns a pkt_hdr RecordVal, which includes not only the IP header, but + * also upper-layer (tcp/udp/icmp) headers. + */ + RecordVal* BuildPktHdrVal() const; private: const struct ip* ip4; diff --git a/src/PacketFilter.cc b/src/PacketFilter.cc index 93a452482f..4fb3b1c8f7 100644 --- a/src/PacketFilter.cc +++ b/src/PacketFilter.cc @@ -71,9 +71,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags ) { // Caution! The packet sanity checks have not been performed yet - const struct ip* ip4 = ip.IP4_Hdr(); - - int ip_hdr_len = ip4->ip_hl * 4; + int ip_hdr_len = ip.HdrLen(); len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; @@ -82,8 +80,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, // Packet too short, will be dropped anyway. return false; - const struct tcphdr* tp = - (const struct tcphdr*) ((u_char*) ip4 + ip_hdr_len); + const struct tcphdr* tp = (const struct tcphdr*) ip.Payload(); if ( tp->th_flags & f.tcp_flags ) // At least one of the flags is set, so don't drop diff --git a/src/Sessions.cc b/src/Sessions.cc index e8cece9e46..b4115f5c16 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -333,7 +333,7 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* new StringVal(sp->Event()->Filter()); args->append(cmd_val); IP_Hdr ip_hdr(ip, false); - args->append(BuildHeader(&ip_hdr)); + args->append(ip_hdr.BuildPktHdrVal()); // ### Need to queue event here. try { @@ -470,7 +470,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( esp_packet ) { val_list* vl = new val_list(); - vl->append(ip_hdr->BuildRecordVal()); + vl->append(ip_hdr->BuildPktHdrVal()); mgr.QueueEvent(esp_packet, vl); } Remove(f); @@ -593,13 +593,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) { - pkt_hdr_val = BuildHeader(ip_hdr); + pkt_hdr_val = ip_hdr->BuildPktHdrVal(); conn->Event(new_packet, 0, pkt_hdr_val); } if ( new_packet ) conn->Event(new_packet, 0, - pkt_hdr_val ? pkt_hdr_val->Ref() : BuildHeader(ip_hdr)); + pkt_hdr_val ? pkt_hdr_val->Ref() : ip_hdr->BuildPktHdrVal()); conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data, record_packet, record_content, @@ -654,88 +654,6 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, return false; } - -Val* NetSessions::BuildHeader(const IP_Hdr* ip) - { - static RecordType* pkt_hdr_type = 0; - static RecordType* tcp_hdr_type = 0; - static RecordType* udp_hdr_type = 0; - static RecordType* icmp_hdr_type; - - if ( ! pkt_hdr_type ) - { - pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType(); - tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType(); - udp_hdr_type = internal_type("udp_hdr")->AsRecordType(); - icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType(); - } - - RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); - - if ( ip->IP4_Hdr() ) - pkt_hdr->Assign(0, ip->BuildRecordVal()); - else - pkt_hdr->Assign(1, ip->BuildRecordVal()); - - // L4 header. - const u_char* data = ip->Payload(); - - int proto = ip->NextProto(); - switch ( proto ) { - case IPPROTO_TCP: - { - const struct tcphdr* tp = (const struct tcphdr*) data; - RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type); - - int tcp_hdr_len = tp->th_off * 4; - int data_len = ip->PayloadLen() - tcp_hdr_len; - - tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); - tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); - tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); - tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); - tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); - tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT)); - tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); - tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); - - pkt_hdr->Assign(2, tcp_hdr); - break; - } - - case IPPROTO_UDP: - { - const struct udphdr* up = (const struct udphdr*) data; - RecordVal* udp_hdr = new RecordVal(udp_hdr_type); - - udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); - udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); - udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); - - pkt_hdr->Assign(3, udp_hdr); - break; - } - - case IPPROTO_ICMP: - { - const struct icmp* icmpp = (const struct icmp *) data; - RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); - - icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); - - pkt_hdr->Assign(4, icmp_hdr); - break; - } - - default: - { - // This is not a protocol we understand. - } - } - - return pkt_hdr; - } - FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, const u_char* pkt) { diff --git a/src/Sessions.h b/src/Sessions.h index ac5fcacfb5..06c6057dbf 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -190,11 +190,6 @@ protected: void Internal(const char* msg, const struct pcap_pkthdr* hdr, const u_char* pkt); - // Builds a record encapsulating a packet. This should be more - // general, including the equivalent of a union of tcp/udp/icmp - // headers . - Val* BuildHeader(const IP_Hdr* ip); - // For a given protocol, checks whether the header's length as derived // from lower-level headers or the length actually captured is less // than that protocol's minimum header size. diff --git a/testing/btest/Baseline/bifs.install_src_addr_filter/output b/testing/btest/Baseline/bifs.install_src_addr_filter/output new file mode 100644 index 0000000000..bf99083391 --- /dev/null +++ b/testing/btest/Baseline/bifs.install_src_addr_filter/output @@ -0,0 +1,8 @@ +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] diff --git a/testing/btest/Baseline/core.discarder/output b/testing/btest/Baseline/core.discarder/output new file mode 100644 index 0000000000..82b4b3e622 --- /dev/null +++ b/testing/btest/Baseline/core.discarder/output @@ -0,0 +1,24 @@ +################ IP Discarder ################ +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +################ TCP Discarder ################ +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +################ UDP Discarder ################ +[orig_h=fe80::217:f2ff:fed7:cf65, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp] +################ ICMP Discarder ################ +Discard icmp packet: [icmp_type=3] diff --git a/testing/btest/Traces/icmp-unreach.trace b/testing/btest/Traces/icmp-unreach.trace new file mode 100644 index 0000000000000000000000000000000000000000..60137bb6fe9a7c942ca6039b194277bb9e0bdca3 GIT binary patch literal 234 zcmca|c+)~A1{MYw`2U}Qff2|_v1ai$7Gh#J1Z0CSgXH7qvC0hGx0555aWJ?tFl^9} zV_;}t>?=R8f-wz<8JU@xcY_oHLh)|9+r10%N7iu{z) Y;sfGHQXF6@!vjtjVkS_rlOp-L0Av?6tN;K2 literal 0 HcmV?d00001 diff --git a/testing/btest/bifs/install_src_addr_filter.test b/testing/btest/bifs/install_src_addr_filter.test new file mode 100644 index 0000000000..5b387832de --- /dev/null +++ b/testing/btest/bifs/install_src_addr_filter.test @@ -0,0 +1,13 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +event bro_init() + { + install_src_addr_filter(141.142.220.118, TH_SYN, 100.0); + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$tcp && p$ip$src == 141.142.220.118 ) + print c$id; + } diff --git a/testing/btest/core/discarder.bro b/testing/btest/core/discarder.bro new file mode 100644 index 0000000000..9dfa9a2cea --- /dev/null +++ b/testing/btest/core/discarder.bro @@ -0,0 +1,92 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-ip.bro >output +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output +# @TEST-EXEC: bro -C -r $TRACES/icmp-unreach.trace discarder-icmp.bro >>output +# @TEST-EXEC: btest-diff output + +@TEST-START-FILE discarder-ip.bro + +event bro_init() + { + print "################ IP Discarder ################"; + } + +function discarder_check_ip(p: pkt_hdr): bool + { + if ( p?$ip && p$ip$src == 141.142.220.118 && p$ip$dst == 208.80.152.2 ) + return F; + return T; + } + + +event new_packet(c: connection, p: pkt_hdr) + { + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-tcp.bro + +event bro_init() + { + print "################ TCP Discarder ################"; + } + +function discarder_check_tcp(p: pkt_hdr, d: string): bool + { + if ( p$tcp$flags == TH_SYN ) + return F; + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$tcp ) + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-udp.bro + +event bro_init() + { + print "################ UDP Discarder ################"; + } + +function discarder_check_udp(p: pkt_hdr, d: string): bool + { + if ( p?$ip6 ) + return F; + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$udp ) + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-icmp.bro + +event bro_init() + { + print "################ ICMP Discarder ################"; + } + +function discarder_check_icmp(p: pkt_hdr): bool + { + print fmt("Discard icmp packet: %s", p$icmp); + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$icmp ) + print c$id; + } + +@TEST-END-FILE From e74cbbf77484528334e5137d73a1e041d9206590 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 12 Mar 2012 15:26:51 -0500 Subject: [PATCH 06/13] Add unit test for IPv6 fragment reassembly. --- testing/btest/Baseline/core.ipv6-frag/dns.log | 9 +++++++++ testing/btest/Baseline/core.ipv6-frag/output | 5 +++++ testing/btest/Traces/ipv6-fragmented-dns.trace | Bin 0 -> 4772 bytes testing/btest/core/ipv6-frag.test | 9 +++++++++ 4 files changed, 23 insertions(+) create mode 100644 testing/btest/Baseline/core.ipv6-frag/dns.log create mode 100644 testing/btest/Baseline/core.ipv6-frag/output create mode 100755 testing/btest/Traces/ipv6-fragmented-dns.trace create mode 100644 testing/btest/core/ipv6-frag.test diff --git a/testing/btest/Baseline/core.ipv6-frag/dns.log b/testing/btest/Baseline/core.ipv6-frag/dns.log new file mode 100644 index 0000000000..50c9684bac --- /dev/null +++ b/testing/btest/Baseline/core.ipv6-frag/dns.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z answers TTLs +#types time string addr port addr port enum count string count string count string count string bool bool bool bool bool count vector[string] vector[interval] +1331084278.438444 UWkUyAuUGXf 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR F T F T F 0 This TXT record should be ignored 1.000000 +1331084293.592245 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR F T F T F 0 This TXT record should be ignored 1.000000 diff --git a/testing/btest/Baseline/core.ipv6-frag/output b/testing/btest/Baseline/core.ipv6-frag/output new file mode 100644 index 0000000000..5020d94e8d --- /dev/null +++ b/testing/btest/Baseline/core.ipv6-frag/output @@ -0,0 +1,5 @@ +ip6=[hdr=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51850/udp, dport=53/udp, ulen=81] +ip6=[hdr=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=53/udp, dport=51850/udp, ulen=331] +ip6=[hdr=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[hdr=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[hdr=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] diff --git a/testing/btest/Traces/ipv6-fragmented-dns.trace b/testing/btest/Traces/ipv6-fragmented-dns.trace new file mode 100755 index 0000000000000000000000000000000000000000..9dda47a8a9f6a4b89c12c3b26577aad3f6effc86 GIT binary patch literal 4772 zcmca|c+)~A1{MYw`2U}Qff300wmZy!%?37xb|4#sZx|$b9Nl_EhuJ!3RomSJpa?^t zpo0PpHckwKr=zc0!hA-ijsoF zl$6Z8^mt<8#GJ~iB9_eL;!KXD)S~RvoYYF@)Ra;N1_6*hO#z_J1|SAG ztKb<7o)dQ2fuwQ$XOuBM7pyM@IV{~)O}Df zBqOs}AtWM1p(r&uzbHkaI3vF_Cq*GCRUtDyFTW@?MbxoaA+tmQs4A9 z1RRiNU;=uCfgy!KkgX^`CowMt7#o>I%=ty>Kv8%E925r!7f2n;foZ$tS@(qbmvVA4 zbO05BFqU)@L_|922Bwpsoz3$n0-XSI1(4)NO(zDVB@~dm4yJH1OaYn(!dMbYoDRW+ zBFMlU0CEdWBk2H5O{at52V{s#J7output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff dns.log + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$ip6 && p?$ udp ) + print fmt("ip6=%s, udp = %s", p$ip6, p$udp); + } From 79948c79741e005565ab0aa29006249014428905 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 13 Mar 2012 14:34:53 -0700 Subject: [PATCH 07/13] Merge remote-tracking branch 'origin/topic/jsiwek/ipv6-ext-headers' * origin/topic/jsiwek/ipv6-ext-headers: Update PacketFilter/Discarder code for IP version independence. Add a few comments to IP.h Fix some IPv6 header related bugs. Add IPv6 fragment reassembly. Add handling for IPv6 extension header chains (addresses #531) --- aux/broccoli | 2 +- scripts/base/init-bare.bro | 265 ++++++++++++++++++++----------------- src/Frag.cc | 10 +- src/IP.h | 16 +++ src/Sessions.cc | 9 +- 5 files changed, 175 insertions(+), 127 deletions(-) diff --git a/aux/broccoli b/aux/broccoli index 2602eb53e7..ca13601450 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 2602eb53e70d7f0afae8fac58d7636b9291974a4 +Subproject commit ca13601450803b48d70122609764e51252a0d86e diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index a031080f0e..98da9f331d 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -303,10 +303,10 @@ type gap_info: record { gap_bytes: count; ##< How many bytes were missing in the gaps. }; -## Deprecated. -## +## Deprecated. +## ## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere -## else. +## else. type packet: record { conn: connection; is_orig: bool; @@ -933,7 +933,7 @@ const ICMP_UNREACH_ADMIN_PROHIB = 13; ##< Adminstratively prohibited. # Definitions for access to packet headers. Currently only used for # discarders. # todo::these should go into an enum to make them autodoc'able -const IPPROTO_IP = 0; ##< Dummy for IP. +const IPPROTO_IP = 0; ##< Dummy for IP. [Robin] Rename to IPPROTO_IP4? const IPPROTO_ICMP = 1; ##< Control message protocol. const IPPROTO_IGMP = 2; ##< Group management protocol. const IPPROTO_IPIP = 4; ##< IP encapsulation in IP. @@ -943,6 +943,7 @@ const IPPROTO_IPV6 = 41; ##< IPv6 header. const IPPROTO_RAW = 255; ##< Raw IP packet. # Definitions for IPv6 extension headers. +# [Robin] Do we need a constant for unknown extensions? const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. const IPPROTO_ROUTING = 43; ##< IPv6 routing header. const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. @@ -959,7 +960,7 @@ type ip6_hdr: record { class: count; ##< Traffic class. flow: count; ##< Flow label. len: count; ##< Payload length. - nxt: count; ##< Next header (RFC 1700 assigned number). + nxt: count; ##< Next header (RFC 1700 assigned number). # [Robin] That's just the IPPROTO_* constant right. Then we should refer to them. hlim: count; ##< Hop limit. src: addr; ##< Source address. dst: addr; ##< Destination address. @@ -1037,7 +1038,7 @@ type ip6_fragment: record { ## ## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain type ip6_ah: record { - ## Next header (RFC 1700 assigned number). + ## Next header (RFC 1700 assigned number). # [Robin] Same as above. nxt: count; ## Length of header in 4-octet units, excluding first two units. len: count; @@ -1064,7 +1065,17 @@ type ip6_esp: record { ## An IPv6 header chain. ## ## .. bro:see:: pkt_hdr ip_hdr +# +# [Robin] How about turning ip6_hdr_chain and ip6_hdr around, making the latter +# the top-level record that then contains an ip6_hdr_chain instance. That way, the +# pkt_hdr record would have ip4_hdr and ip6_hdr members, which seems more natural. +# +# [Robin] What happens to unknown extension headers? We should keep them too so that +# one can at least identify what one can't analyze. type ip6_hdr_chain: record { + # [Robin] This looses the order of the headers (partially at least, even with ext_order I believe). + # Not sure how to do it differently, but can order be important for us? + ## The main IPv6 header. hdr: ip6_hdr; ## Hop-by-hop option extension header. @@ -1081,12 +1092,15 @@ type ip6_hdr_chain: record { esp: vector of ip6_esp; ## Order of extension headers identified by RFC 1700 assigned numbers. + # [Robin] I don't understand how this works. ext_order: vector of count; }; ## Values extracted from an IPv4 header. ## ## .. bro:see:: pkt_hdr ip6_hdr discarder_check_ip +## +# [Robin] Rename to ip4_hdr? type ip_hdr: record { hl: count; ##< Header length in bytes. tos: count; ##< Type of service. @@ -1142,6 +1156,9 @@ type icmp_hdr: record { ## A packet header, consisting of an IP header and transport-layer header. ## ## .. bro:see:: new_packet +# +# [Robin] Add flags saying whether it's v4/v6, tcp/udp/icmp? The day will come where +# we can't infer that from the connection anymore (tunnels). type pkt_hdr: record { ip: ip_hdr &optional; ##< The IPv4 header if an IPv4 packet. ip6: ip6_hdr_chain &optional; ##< The IPv6 header chain if an IPv6 packet. @@ -1459,7 +1476,7 @@ export { ## NFS file attributes. Field names are based on RFC 1813. ## - ## .. bro:see:: nfs_proc_getattr + ## .. bro:see:: nfs_proc_getattr type fattr_t: record { ftype: file_type_t; ##< File type. mode: count; ##< Mode @@ -1478,8 +1495,8 @@ export { }; ## NFS *readdir* arguments. - ## - ## .. bro:see:: nfs_proc_readdir + ## + ## .. bro:see:: nfs_proc_readdir type diropargs_t : record { dirfh: string; ##< The file handle of the directory. fname: string; ##< The name of the file we are interested in. @@ -1488,7 +1505,7 @@ export { ## NFS lookup reply. If the lookup failed, *dir_attr* may be set. If the lookup ## succeeded, *fh* is always set and *obj_attr* and *dir_attr* may be set. ## - ## .. bro:see:: nfs_proc_lookup + ## .. bro:see:: nfs_proc_lookup type lookup_reply_t: record { fh: string &optional; ##< File handle of object looked up. obj_attr: fattr_t &optional; ##< Optional attributes associated w/ file @@ -1505,7 +1522,7 @@ export { }; ## NFS *read* reply. If the lookup fails, *attr* may be set. If the lookup succeeds, - ## *attr* may be set and all other fields are set. + ## *attr* may be set and all other fields are set. type read_reply_t: record { attr: fattr_t &optional; ##< Attributes. size: count &optional; ##< Number of bytes read. @@ -1514,7 +1531,7 @@ export { }; ## NFS *readline* reply. If the request fails, *attr* may be set. If the request - ## succeeds, *attr* may be set and all other fields are set. + ## succeeds, *attr* may be set and all other fields are set. ## ## .. bro:see:: nfs_proc_readlink type readlink_reply_t: record { @@ -1524,7 +1541,7 @@ export { ## NFS *write* arguments. ## - ## .. bro:see:: nfs_proc_write + ## .. bro:see:: nfs_proc_write type writeargs_t: record { fh: string; ##< File handle to write to. offset: count; ##< Offset in file. @@ -1534,18 +1551,18 @@ export { }; ## NFS *wcc* attributes. - ## + ## ## .. bro:see:: NFS3::write_reply_t type wcc_attr_t: record { - size: count; ##< The dize. + size: count; ##< The dize. atime: time; ##< Access time. mtime: time; ##< Modification time. }; ## NFS *write* reply. If the request fails, *pre|post* attr may be set. If the - ## request succeeds, *pre|post* attr may be set and all other fields are set. + ## request succeeds, *pre|post* attr may be set and all other fields are set. ## - ## .. bro:see:: nfs_proc_write + ## .. bro:see:: nfs_proc_write type write_reply_t: record { preattr: wcc_attr_t &optional; ##< Pre operation attributes. postattr: fattr_t &optional; ##< Post operation attributes. @@ -1556,9 +1573,9 @@ export { ## NFS reply for *create*, *mkdir*, and *symlink*. If the proc ## failed, *dir_\*_attr* may be set. If the proc succeeded, *fh* and the *attr*'s - ## may be set. Note: no guarantee that *fh* is set after success. + ## may be set. Note: no guarantee that *fh* is set after success. ## - ## .. bro:see:: nfs_proc_create nfs_proc_mkdir + ## .. bro:see:: nfs_proc_create nfs_proc_mkdir type newobj_reply_t: record { fh: string &optional; ##< File handle of object created. obj_attr: fattr_t &optional; ##< Optional attributes associated w/ new object. @@ -1566,17 +1583,17 @@ export { dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir. }; - ## NFS reply for *remove*, *rmdir*. Corresponds to *wcc_data* in the spec. + ## NFS reply for *remove*, *rmdir*. Corresponds to *wcc_data* in the spec. ## - ## .. bro:see:: nfs_proc_remove nfs_proc_rmdir + ## .. bro:see:: nfs_proc_remove nfs_proc_rmdir type delobj_reply_t: record { dir_pre_attr: wcc_attr_t &optional; ##< Optional attributes associated w/ dir. dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir. }; ## NFS *readdir* arguments. Used for both *readdir* and *readdirplus*. - ## - ## .. bro:see:: nfs_proc_readdir + ## + ## .. bro:see:: nfs_proc_readdir type readdirargs_t: record { isplus: bool; ##< Is this a readdirplus request? dirfh: string; ##< The directory filehandle. @@ -1589,7 +1606,7 @@ export { ## NFS *direntry*. *fh* and *attr* are used for *readdirplus*. However, even ## for *readdirplus* they may not be filled out. ## - ## .. bro:see:: NFS3::direntry_vec_t NFS3::readdir_reply_t + ## .. bro:see:: NFS3::direntry_vec_t NFS3::readdir_reply_t type direntry_t: record { fileid: count; ##< E.g., inode number. fname: string; ##< Filename. @@ -1600,7 +1617,7 @@ export { ## Vector of NFS *direntry*. ## - ## .. bro:see:: NFS3::readdir_reply_t + ## .. bro:see:: NFS3::readdir_reply_t type direntry_vec_t: vector of direntry_t; ## NFS *readdir* reply. Used for *readdir* and *readdirplus*. If an is @@ -1631,7 +1648,7 @@ module GLOBAL; ## An NTP message. ## -## .. bro:see:: ntp_message +## .. bro:see:: ntp_message type ntp_msg: record { id: count; ##< Message ID. code: count; ##< Message code. @@ -1653,7 +1670,7 @@ global samba_cmds: table[count] of string &redef { return fmt("samba-unknown-%d", c); }; ## An SMB command header. -## +## ## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx ## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx ## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot @@ -1672,9 +1689,9 @@ type smb_hdr : record { }; ## An SMB transaction. -## +## ## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 +## smb_com_transaction smb_com_transaction2 type smb_trans : record { word_count: count; ##< TODO. total_param_count: count; ##< TODO. @@ -1688,7 +1705,7 @@ type smb_trans : record { param_offset: count; ##< TODO. data_count: count; ##< TODO. data_offset: count; ##< TODO. - setup_count: count; ##< TODO. + setup_count: count; ##< TODO. setup0: count; ##< TODO. setup1: count; ##< TODO. setup2: count; ##< TODO. @@ -1699,19 +1716,19 @@ type smb_trans : record { ## SMB transaction data. -## +## ## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 -## +## smb_com_transaction smb_com_transaction2 +## ## .. todo:: Should this really be a record type? type smb_trans_data : record { data : string; ##< The transaction's data. }; -## Deprecated. -## +## Deprecated. +## ## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere -## else. +## else. type smb_tree_connect : record { flags: count; password: string; @@ -1719,21 +1736,21 @@ type smb_tree_connect : record { service: string; }; -## Deprecated. -## +## Deprecated. +## ## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere -## else. +## else. type smb_negotiate : table[count] of string; ## A list of router addresses offered by a DHCP server. ## -## .. bro:see:: dhcp_ack dhcp_offer +## .. bro:see:: dhcp_ack dhcp_offer type dhcp_router_list: table[count] of addr; ## A DHCP message. ## ## .. bro:see:: dhcp_ack dhcp_decline dhcp_discover dhcp_inform dhcp_nak -## dhcp_offer dhcp_release dhcp_request +## dhcp_offer dhcp_release dhcp_request type dhcp_msg: record { op: count; ##< Message OP code. 1 = BOOTREQUEST, 2 = BOOTREPLY m_type: count; ##< The type of DHCP message. @@ -1770,7 +1787,7 @@ type dns_msg: record { ## A DNS SOA record. ## -## .. bro:see:: dns_SOA_reply +## .. bro:see:: dns_SOA_reply type dns_soa: record { mname: string; ##< Primary source of data for zone. rname: string; ##< Mailbox for responsible person. @@ -1783,7 +1800,7 @@ type dns_soa: record { ## An additional DNS EDNS record. ## -## .. bro:see:: dns_EDNS_addl +## .. bro:see:: dns_EDNS_addl type dns_edns_additional: record { query: string; ##< Query. qtype: count; ##< Query type. @@ -1798,7 +1815,7 @@ type dns_edns_additional: record { ## An additional DNS TSIG record. ## -## bro:see:: dns_TSIG_addl +## bro:see:: dns_TSIG_addl type dns_tsig_additional: record { query: string; ##< Query. qtype: count; ##< Query type. @@ -1812,9 +1829,9 @@ type dns_tsig_additional: record { }; # DNS answer types. -# +# # .. .. bro:see:: dns_answerr -# +# # todo::use enum to make them autodoc'able const DNS_QUERY = 0; ##< A query. This shouldn't occur, just for completeness. const DNS_ANS = 1; ##< An answer record. @@ -1828,7 +1845,7 @@ const DNS_ADDL = 3; ##< An additional record. ## dns_TXT_reply dns_WKS_reply type dns_answer: record { ## Answer type. One of :bro:see:`DNS_QUERY`, :bro:see:`DNS_ANS`, - ## :bro:see:`DNS_AUTH` and :bro:see:`DNS_ADDL`. + ## :bro:see:`DNS_AUTH` and :bro:see:`DNS_ADDL`. answer_type: count; query: string; ##< Query. qtype: count; ##< Query type. @@ -1848,27 +1865,27 @@ global dns_skip_auth: set[addr] &redef; ## .. bro:see:: dns_skip_all_addl dns_skip_auth global dns_skip_addl: set[addr] &redef; -## If true, all DNS AUTH records are skipped. +## If true, all DNS AUTH records are skipped. ## ## .. bro:see:: dns_skip_all_addl dns_skip_auth global dns_skip_all_auth = T &redef; -## If true, all DNS ADDL records are skipped. +## If true, all DNS ADDL records are skipped. ## ## .. bro:see:: dns_skip_all_auth dns_skip_addl global dns_skip_all_addl = T &redef; ## If a DNS request includes more than this many queries, assume it's non-DNS -## traffic and do not process it. Set to 0 to turn off this functionality. +## traffic and do not process it. Set to 0 to turn off this functionality. global dns_max_queries = 5; ## An X509 certificate. ## -## .. bro:see:: x509_certificate +## .. bro:see:: x509_certificate type X509: record { version: count; ##< Version number. serial: string; ##< Serial number. - subject: string; ##< Subject. + subject: string; ##< Subject. issuer: string; ##< Issuer. not_valid_before: time; ##< Timestamp before when certificate is not valid. not_valid_after: time; ##< Timestamp after when certificate is not valid. @@ -1876,7 +1893,7 @@ type X509: record { ## HTTP session statistics. ## -## .. bro:see:: http_stats +## .. bro:see:: http_stats type http_stats_rec: record { num_requests: count; ##< Number of requests. num_replies: count; ##< Number of replies. @@ -1886,7 +1903,7 @@ type http_stats_rec: record { ## HTTP message statistics. ## -## .. bro:see:: http_message_done +## .. bro:see:: http_message_done type http_message_stat: record { ## When the request/reply line was complete. start: time; @@ -1903,26 +1920,26 @@ type http_message_stat: record { }; ## Maximum number of HTTP entity data delivered to events. The amount of data -## can be limited for better performance, zero disables truncation. -## +## can be limited for better performance, zero disables truncation. +## ## .. bro:see:: http_entity_data skip_http_entity_data skip_http_data global http_entity_data_delivery_size = 1500 &redef; ## Skip HTTP data for performance considerations. The skipped -## portion will not go through TCP reassembly. -## +## portion will not go through TCP reassembly. +## ## .. bro:see:: http_entity_data skip_http_entity_data http_entity_data_delivery_size const skip_http_data = F &redef; ## Maximum length of HTTP URIs passed to events. Longer ones will be truncated ## to prevent over-long URIs (usually sent by worms) from slowing down event ## processing. A value of -1 means "do not truncate". -## +## ## .. bro:see:: http_request const truncate_http_URI = -1 &redef; -## IRC join information. -## +## IRC join information. +## ## .. bro:see:: irc_join_list type irc_join_info: record { nick: string; @@ -1933,13 +1950,13 @@ type irc_join_info: record { ## Set of IRC join information. ## -## .. bro:see:: irc_join_message +## .. bro:see:: irc_join_message type irc_join_list: set[irc_join_info]; -## Deprecated. -## +## Deprecated. +## ## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere -## else. +## else. global irc_servers : set[addr] &redef; ## Internal to the stepping stone detector. @@ -2003,7 +2020,7 @@ type backdoor_endp_stats: record { ## Description of a signature match. ## -## .. bro:see:: signature_match +## .. bro:see:: signature_match type signature_state: record { sig_id: string; ##< ID of the matching signature. conn: connection; ##< Matching connection. @@ -2011,10 +2028,10 @@ type signature_state: record { payload_size: count; ##< Payload size of the first matching packet of current endpoint. }; -# Deprecated. -# +# Deprecated. +# # .. todo:: This type is no longer used. Remove any reference of this from the -# core. +# core. type software_version: record { major: int; minor: int; @@ -2022,10 +2039,10 @@ type software_version: record { addl: string; }; -# Deprecated. -# +# Deprecated. +# # .. todo:: This type is no longer used. Remove any reference of this from the -# core. +# core. type software: record { name: string; version: software_version; @@ -2042,7 +2059,7 @@ type OS_version_inference: enum { ## Passive fingerprinting match. ## -## .. bro:see:: OS_version_found +## .. bro:see:: OS_version_found type OS_version: record { genre: string; ##< Linux, Windows, AIX, ... detail: string; ##< Lernel version or such. @@ -2052,20 +2069,20 @@ type OS_version: record { ## Defines for which subnets we should do passive fingerprinting. ## -## .. bro:see:: OS_version_found +## .. bro:see:: OS_version_found global generate_OS_version_event: set[subnet] &redef; # Type used to report load samples via :bro:see:`load_sample`. For now, it's a # set of names (event names, source file names, and perhaps ````, which were seen during the sample. +# number>``, which were seen during the sample. type load_sample_info: set[string]; ## ID for NetFlow header. This is primarily a means to sort together NetFlow -## headers and flow records at the script level. +## headers and flow records at the script level. type nfheader_id: record { ## Name of the NetFlow file (e.g., ``netflow.dat``) or the receiving socket address ## (e.g., ``127.0.0.1:5555``), or an explicit name if specified to - ## ``-y`` or ``-Y``. + ## ``-y`` or ``-Y``. rcvr_id: string; ## A serial number, ignoring any overflows. pdu_id: count; @@ -2073,7 +2090,7 @@ type nfheader_id: record { ## A NetFlow v5 header. ## -## .. bro:see:: netflow_v5_header +## .. bro:see:: netflow_v5_header type nf_v5_header: record { h_id: nfheader_id; ##< ID for sorting. cnt: count; ##< TODO. @@ -2089,7 +2106,7 @@ type nf_v5_header: record { ## A NetFlow v5 record. ## ## .. bro:see:: netflow_v5_record -type nf_v5_record: record { +type nf_v5_record: record { h_id: nfheader_id; ##< ID for sorting. id: conn_id; ##< Connection ID. nexthop: addr; ##< Address of next hop. @@ -2123,7 +2140,7 @@ type bittorrent_peer: record { }; ## A set of BitTorrent peers. -## +## ## .. bro:see:: bt_tracker_response type bittorrent_peer_set: set[bittorrent_peer]; @@ -2146,12 +2163,12 @@ type bittorrent_benc_dir: table[string] of bittorrent_benc_value; ## Header table type used by BitTorrent analyzer. ## ## .. bro:see:: bt_tracker_request bt_tracker_response -## bt_tracker_response_not_ok +## bt_tracker_response_not_ok type bt_tracker_headers: table[string] of string; @load base/event.bif -## BPF filter the user has set via the -f command line options. Empty if none. +## BPF filter the user has set via the -f command line options. Empty if none. const cmd_line_bpf_filter = "" &redef; ## Deprecated. @@ -2169,24 +2186,24 @@ const log_encryption_key = "" &redef; ## Write profiling info into this file in regular intervals. The easiest way to ## activate profiling is loading :doc:`/scripts/policy/misc/profiling`. ## -## .. bro:see:: profiling_interval expensive_profiling_multiple segment_profiling +## .. bro:see:: profiling_interval expensive_profiling_multiple segment_profiling global profiling_file: file &redef; ## Update interval for profiling (0 disables). The easiest way to activate ## profiling is loading :doc:`/scripts/policy/misc/profiling`. ## -## .. bro:see:: profiling_file expensive_profiling_multiple segment_profiling +## .. bro:see:: profiling_file expensive_profiling_multiple segment_profiling const profiling_interval = 0 secs &redef; ## Multiples of profiling_interval at which (more expensive) memory profiling is ## done (0 disables). ## -## .. bro:see:: profiling_interval profiling_file segment_profiling +## .. bro:see:: profiling_interval profiling_file segment_profiling const expensive_profiling_multiple = 0 &redef; ## If true, then write segment profiling information (very high volume!) ## in addition to profiling statistics. -## +## ## .. bro:see:: profiling_interval expensive_profiling_multiple profiling_file const segment_profiling = F &redef; @@ -2225,42 +2242,42 @@ global load_sample_freq = 20 &redef; ## Rate at which to generate :bro:see:`gap_report` events assessing to what degree ## the measurement process appears to exhibit loss. -## +## ## .. bro:see:: gap_report const gap_report_freq = 1.0 sec &redef; ## Whether we want :bro:see:`content_gap` and :bro:see:`gap_report` for partial ## connections. A connection is partial if it is missing a full handshake. Note ## that gap reports for partial connections might not be reliable. -## +## ## .. bro:see:: content_gap gap_report partial_connection const report_gaps_for_partial = F &redef; ## The CA certificate file to authorize remote Bros/Broccolis. -## +## ## .. bro:see:: ssl_private_key ssl_passphrase const ssl_ca_certificate = "" &redef; ## File containing our private key and our certificate. -## +## ## .. bro:see:: ssl_ca_certificate ssl_passphrase const ssl_private_key = "" &redef; ## The passphrase for our private key. Keeping this undefined ## causes Bro to prompt for the passphrase. -## +## ## .. bro:see:: ssl_private_key ssl_ca_certificate const ssl_passphrase = "" &redef; ## Default mode for Bro's user-space dynamic packet filter. If true, packets that -## aren't explicitly allowed through, are dropped from any further processing. -## +## aren't explicitly allowed through, are dropped from any further processing. +## ## .. note:: This is not the BPF packet filter but an additional dynamic filter -## that Bro optionally applies just before normal processing starts. -## -## .. bro:see:: install_dst_addr_filter install_dst_net_filter +## that Bro optionally applies just before normal processing starts. +## +## .. bro:see:: install_dst_addr_filter install_dst_net_filter ## install_src_addr_filter install_src_net_filter uninstall_dst_addr_filter -## uninstall_dst_net_filter uninstall_src_addr_filter uninstall_src_net_filter +## uninstall_dst_net_filter uninstall_src_addr_filter uninstall_src_net_filter const packet_filter_default = F &redef; ## Maximum size of regular expression groups for signature matching. @@ -2272,17 +2289,17 @@ const enable_syslog = F &redef; ## Description transmitted to remote communication peers for identification. const peer_description = "bro" &redef; -## If true, broadcast events received from one peer to all other peers. -## +## If true, broadcast events received from one peer to all other peers. +## ## .. bro:see:: forward_remote_state_changes ## ## .. note:: This option is only temporary and will disappear once we get a more ## sophisticated script-level communication framework. const forward_remote_events = F &redef; -## If true, broadcast state updates received from one peer to all other peers. -## -## .. bro:see:: forward_remote_events +## If true, broadcast state updates received from one peer to all other peers. +## +## .. bro:see:: forward_remote_events ## ## .. note:: This option is only temporary and will disappear once we get a more ## sophisticated script-level communication framework. @@ -2311,23 +2328,23 @@ const REMOTE_SRC_PARENT = 2; ##< Message from the parent process. const REMOTE_SRC_SCRIPT = 3; ##< Message from a policy script. ## Synchronize trace processing at a regular basis in pseudo-realtime mode. -## +## ## .. bro:see:: remote_trace_sync_peers const remote_trace_sync_interval = 0 secs &redef; ## Number of peers across which to synchronize trace processing in -## pseudo-realtime mode. -## +## pseudo-realtime mode. +## ## .. bro:see:: remote_trace_sync_interval const remote_trace_sync_peers = 0 &redef; ## Whether for :bro:attr:`&synchronized` state to send the old value as a -## consistency check. +## consistency check. const remote_check_sync_consistency = F &redef; ## Analyzer tags. The core automatically defines constants ## ``ANALYZER_*``, e.g., ``ANALYZER_HTTP``. -## +## ## .. bro:see:: dpd_config ## ## .. todo::We should autodoc these automaticallty generated constants. @@ -2345,7 +2362,7 @@ type dpd_protocol_config: record { ## This table defines the ports. ## ## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size -## dpd_match_only_beginning dpd_ignore_ports +## dpd_match_only_beginning dpd_ignore_ports const dpd_config: table[AnalyzerTag] of dpd_protocol_config = {} &redef; ## Reassemble the beginning of all TCP connections before doing @@ -2353,10 +2370,10 @@ const dpd_config: table[AnalyzerTag] of dpd_protocol_config = {} &redef; ## expensive of CPU cycles. ## ## .. bro:see:: dpd_config dpd_buffer_size -## dpd_match_only_beginning dpd_ignore_ports -## +## dpd_match_only_beginning dpd_ignore_ports +## ## .. note:: Despite the name, this option affects *all* signature matching, not -## only signatures used for dynamic protocol detection. +## only signatures used for dynamic protocol detection. const dpd_reassemble_first_packets = T &redef; ## Size of per-connection buffer used for dynamic protocol detection. For each @@ -2365,23 +2382,23 @@ const dpd_reassemble_first_packets = T &redef; ## already passed through (i.e., when a DPD signature matches only later). ## However, once the buffer is full, data is deleted and lost to analyzers that are ## activated afterwards. Then only analyzers that can deal with partial -## connections will be able to analyze the session. +## connections will be able to analyze the session. ## ## .. bro:see:: dpd_reassemble_first_packets dpd_config dpd_match_only_beginning -## dpd_ignore_ports +## dpd_ignore_ports const dpd_buffer_size = 1024 &redef; ## If true, stops signature matching if dpd_buffer_size has been reached. ## ## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size -## dpd_config dpd_ignore_ports -## +## dpd_config dpd_ignore_ports +## ## .. note:: Despite the name, this option affects *all* signature matching, not -## only signatures used for dynamic protocol detection. +## only signatures used for dynamic protocol detection. const dpd_match_only_beginning = T &redef; ## If true, don't consider any ports for deciding which protocol analyzer to -## use. If so, the value of :bro:see:`dpd_config` is ignored. +## use. If so, the value of :bro:see:`dpd_config` is ignored. ## ## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size ## dpd_match_only_beginning dpd_config @@ -2389,14 +2406,14 @@ const dpd_ignore_ports = F &redef; ## Ports which the core considers being likely used by servers. For ports in ## this set, is may heuristically decide to flip the direction of the -## connection if it misses the initial handshake. +## connection if it misses the initial handshake. const likely_server_ports: set[port] &redef; ## Deprated. Set of all ports for which we know an analyzer, built by -## :doc:`/scripts/base/frameworks/dpd/main`. +## :doc:`/scripts/base/frameworks/dpd/main`. ## ## .. todo::This should be defined by :doc:`/scripts/base/frameworks/dpd/main` -## itself we still need it. +## itself we still need it. global dpd_analyzer_ports: table[port] of set[AnalyzerTag]; ## Per-incident timer managers are drained after this amount of inactivity. @@ -2409,7 +2426,7 @@ const time_machine_profiling = F &redef; const check_for_unused_event_handlers = F &redef; # If true, dumps all invoked event handlers at startup. -# todo::Still used? +# todo::Still used? # const dump_used_event_handlers = F &redef; ## Deprecated. @@ -2425,7 +2442,7 @@ const trace_output_file = ""; ## of setting this to true is that we can write the packets out before we actually ## process them, which can be helpful for debugging in case the analysis triggers a ## crash. -## +## ## .. bro:see:: trace_output_file const record_all_packets = F &redef; @@ -2438,7 +2455,7 @@ const record_all_packets = F &redef; const ignore_keep_alive_rexmit = F &redef; ## Whether the analysis engine parses IP packets encapsulated in -## UDP tunnels. +## UDP tunnels. ## ## .. bro:see:: tunnel_port const parse_udp_tunnels = F &redef; @@ -2446,6 +2463,6 @@ const parse_udp_tunnels = F &redef; ## Number of bytes per packet to capture from live interfaces. const snaplen = 8192 &redef; -# Load the logging framework here because it uses fairly deep integration with +# Load the logging framework here because it uses fairly deep integration with # BiFs and script-land defined types. @load base/frameworks/logging diff --git a/src/Frag.cc b/src/Frag.cc index cbdae92883..68c5c108f1 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -32,10 +32,12 @@ FragReassembler::FragReassembler(NetSessions* arg_s, { s = arg_s; key = k; + + // [Robin] Can't we merge these two cases now? const struct ip* ip4 = ip->IP4_Hdr(); if ( ip4 ) { - proto_hdr_len = ip4->ip_hl * 4; + proto_hdr_len = ip4->ip_hl * 4; // [Robin] HdrLen? proto_hdr = new u_char[64]; // max IP header + slop // Don't do a structure copy - need to pick up options, too. memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); @@ -244,6 +246,12 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) reassem4->ip_len = htons(frag_size + proto_hdr_len); reassembled_pkt = new IP_Hdr(reassem4, true); } + + // [Robin] Please always check for IP version explicitly, like here + // do "if ... ip_v == 6", and then catch other values via + // weird/errors. Even of it shouldn't happen (because of earlier + // checks), it's better to be safe. I believe there are more places + // like this elsewhere, please check. else { struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; diff --git a/src/IP.h b/src/IP.h index 53fe1daf84..b876a2ac3b 100644 --- a/src/IP.h +++ b/src/IP.h @@ -14,6 +14,15 @@ #include #include +// [Robin] I'm concerced about the virtual methods here. These methods will +// be called *a lot* and that may add to some significant overhead I'm afraid +// (at least eventually as IPv6 is picking up). +// +// [Robin] Similar concern for the vector and ip6_hdrs data +// members: we're creating/allocating those for every IPv6 packet, right? +// +// Any idea how to avoid these? + /** * Base class for IPv6 header/extensions. */ @@ -32,6 +41,13 @@ public: */ IPv6_Hdr(const u_char* d, uint16 nxt) : type(IPPROTO_IPV6), data(d) { + // [Robin]. This looks potentially dangerous as it's changing + // the data passed in, which the caller may not realize. From + // quick look, it's only used from Frag.cc, so that may be + // ok. But could we guard against accidental use somehome? + // Like making this protected and then declare a friend; or a + // seperate method ChangeNext(). (I saw it's used by derived + // classes so not sure wehat works best.) if ( ((ip6_hdr*)data)->ip6_nxt == IPPROTO_FRAGMENT ) ((ip6_hdr*)data)->ip6_nxt = nxt; } diff --git a/src/Sessions.cc b/src/Sessions.cc index b4115f5c16..a5b054b933 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -430,6 +430,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) ) return; + // [Robin] dump_this_packet = 1 for non-ICMP/UDP/TCP removed here. Why? + FragReassembler* f = 0; if ( ip_hdr->IsFragment() ) @@ -465,6 +467,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; + // [Robin] Does ESP need to be the last header? if ( ip_hdr->LastHeader() == IPPROTO_ESP ) { if ( esp_packet ) @@ -474,7 +477,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, mgr.QueueEvent(esp_packet, vl); } Remove(f); - // Can't do more since upper-layer payloads are going to be encrypted + // Can't do more since upper-layer payloads are going to be encrypted. return; } @@ -486,6 +489,9 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, return; } + // [Robin] The Remove(f) used to be here, while it's now before every + // return statement. I'm not seeing why? + const u_char* data = ip_hdr->Payload(); ConnID id; @@ -594,6 +600,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) { pkt_hdr_val = ip_hdr->BuildPktHdrVal(); + // [Robin] This should be ipv6_ext_headers, right? conn->Event(new_packet, 0, pkt_hdr_val); } From 7af14ec1fe0ff4ed4088f127eeae2eeb79eac887 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 14 Mar 2012 10:00:48 -0500 Subject: [PATCH 08/13] Remove the default "tcp or udp or icmp" filter. In default mode, Bro would load the packet filter script framework which installs a filter that allows all packets, but in bare mode (the -b option), this old filter would not follow IPv6 protocol chains and thus filter out packets with extension headers. --- src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cc b/src/main.cc index 6313528980..f5a5b5282f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -837,7 +837,7 @@ int main(int argc, char** argv) if ( dns_type != DNS_PRIME ) net_init(interfaces, read_files, netflows, flow_files, - writefile, "tcp or udp or icmp", + writefile, "", secondary_path->Filter(), do_watchdog); BroFile::SetDefaultRotation(log_rotate_interval, log_max_size); From 5312a904ab2e1a242a03486b8ed2b59e2f274514 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 14 Mar 2012 10:31:08 -0500 Subject: [PATCH 09/13] Fix ipv6_ext_headers event and add routing0_data_to_addrs BIF. Also add unit tests for ipv6_ext_headers and esp_packet events. --- src/Sessions.cc | 2 +- src/bro.bif | 32 +++++ .../bifs.routing0_data_to_addrs/output | 4 + testing/btest/Baseline/core.ipv6_esp/output | 120 ++++++++++++++++++ .../Baseline/core.ipv6_ext_headers/output | 1 + .../btest/Traces/ext_hdr_hbh_routing.trace | Bin 0 -> 153 bytes testing/btest/Traces/ip6_esp.trace | Bin 0 -> 20210 bytes .../btest/bifs/routing0_data_to_addrs.test | 9 ++ testing/btest/core/ipv6_esp.test | 10 ++ testing/btest/core/ipv6_ext_headers.test | 10 ++ 10 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/bifs.routing0_data_to_addrs/output create mode 100644 testing/btest/Baseline/core.ipv6_esp/output create mode 100644 testing/btest/Baseline/core.ipv6_ext_headers/output create mode 100644 testing/btest/Traces/ext_hdr_hbh_routing.trace create mode 100644 testing/btest/Traces/ip6_esp.trace create mode 100644 testing/btest/bifs/routing0_data_to_addrs.test create mode 100644 testing/btest/core/ipv6_esp.test create mode 100644 testing/btest/core/ipv6_ext_headers.test diff --git a/src/Sessions.cc b/src/Sessions.cc index b4115f5c16..e70540b598 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -594,7 +594,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) { pkt_hdr_val = ip_hdr->BuildPktHdrVal(); - conn->Event(new_packet, 0, pkt_hdr_val); + conn->Event(ipv6_ext_headers, 0, pkt_hdr_val); } if ( new_packet ) diff --git a/src/bro.bif b/src/bro.bif index ff06288940..375a1c64c1 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2049,6 +2049,38 @@ function is_v6_addr%(a: addr%): bool # # =========================================================================== +## Converts the *data* field of :bro:type:`ip6_routing` records that have +## *rtype* of 0 into a set of addresses. +## +## s: The *data* field of an :bro:type:`ip6_routing` record that has +## an *rtype* of 0. +## +## Returns: The set of addresses contained in the routing header data. +function routing0_data_to_addrs%(s: string%): addr_set + %{ + BroType* index_type = base_type(TYPE_ADDR); + TypeList* set_index = new TypeList(index_type); + set_index->Append(index_type); + TableVal* tv = new TableVal(new SetType(set_index, 0)); + + int len = s->Len(); + const u_char* bytes = s->Bytes(); + bytes += 4; // go past 32-bit reserved field + len -= 4; + if ( ( len % 16 ) != 0 ) + reporter->Warning("Bad ip6_routing data length: %d", s->Len()); + + while ( len > 0 ) + { + IPAddr a(IPAddr::IPv6, (const uint32*) bytes, IPAddr::Network); + tv->Assign(new AddrVal(a), 0); + bytes += 16; + len -= 16; + } + + return tv; + %} + ## Converts a :bro:type:`addr` to a :bro:type:`index_vec`. ## ## a: The address to convert into a vector of counts. diff --git a/testing/btest/Baseline/bifs.routing0_data_to_addrs/output b/testing/btest/Baseline/bifs.routing0_data_to_addrs/output new file mode 100644 index 0000000000..7179bf8564 --- /dev/null +++ b/testing/btest/Baseline/bifs.routing0_data_to_addrs/output @@ -0,0 +1,4 @@ +{ +2001:78:1:32::1, +2001:78:1:32::2 +} diff --git a/testing/btest/Baseline/core.ipv6_esp/output b/testing/btest/Baseline/core.ipv6_esp/output new file mode 100644 index 0000000000..645b4c8c56 --- /dev/null +++ b/testing/btest/Baseline/core.ipv6_esp/output @@ -0,0 +1,120 @@ +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] diff --git a/testing/btest/Baseline/core.ipv6_ext_headers/output b/testing/btest/Baseline/core.ipv6_ext_headers/output new file mode 100644 index 0000000000..4cc9c706ae --- /dev/null +++ b/testing/btest/Baseline/core.ipv6_ext_headers/output @@ -0,0 +1 @@ +[ip=, ip6=[hdr=[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], hopopts=[[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]]], dstopts=[], 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=[], ah=[], esp=[], ext_order=[0, 43]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] diff --git a/testing/btest/Traces/ext_hdr_hbh_routing.trace b/testing/btest/Traces/ext_hdr_hbh_routing.trace new file mode 100644 index 0000000000000000000000000000000000000000..2a294ed58ea254aa88049e4287324bd05111eaf0 GIT binary patch literal 153 zcmca|c+)~A1{MYwaA0F#U<7jR?~eEPY-MC91hPT+KNvt%wcSksF{~LJ6c|~405!8S zJ!t&@FX;b&RQ{}NZ3afL(Sj@tOdu@^j0_b($jfgh8yN)nEXRP#nmY z40s(L;RP>gHKxO8up=oUL)MP z5A~q~2SO^f;(f8SkG&p&VpYp{gTog}f#sGc1Ii!*tNj~kqaQ_#A`j}G2W1=~t#a=z zr6|?P{~avOcJ16A3wg*t*@4gbcdLzHEFTN&9811FBTn8!BAX#=RO@0L>+|F?3+=0_ zS9Q;vI+vHU?;Xjl0CF%PoaBhNn^1GcY9iie((`Rd;f|@*&;80_odR2$1o}OgGAJ7t zp)p%t5KMV9iksz(M{bx#=b=-t&#L$i+?dF!lb1NODq|Li7OItsC;z}J-N~|MT|ynR zp09jyxxipWOK%mBXArBeWv6#tP?qFo)8)hxQN-Sa-q zZj$0R<>fjcXM&d;a=R&#ylHZmYq3%llk7zmWgZIg4KY^#54YSiwPcT4+@9Z;=V=F5 z$dyv{dPd4WwJe_CkPl&ntwbgTu;(5wIb#Nmyhw;W-!@`8ZjYd8{8jlbPA{iw_R)w_ zV?KTI1|Z+Xhtq69zTJd(xqO&Wq4g{`m8g+u?^u<5PUh>|p|UpFt^#_bU6OY=x)?lIQG ztV@;}Rr8~-EtQSa1m(5f!L~H9E0@uMFTMN4wobqljeGZ<9}AB^mJWS6a0C6or!V;>h*D@~M%chQ@oG%P=!pFfT!6 z0ZB3GP&}F*4N>6E@BJ|9BeL74FD@sU(ByxoLY}CF5A?O{^RFB2Z z4j?b7g_9ipcGLW?{gWihVQZb`FQ3yV@gM0o>NTENnnw@lY12JG{H}@nJTsU(rqb~b zAjfS+17!e9AoTd>hV-vB)apO3p-8|e4B$X`tdU6(-#rj!-c%*h==uJ|Um9D|Q|8&z zF4RfYkCUXfyfff2ZUKAU;z5P-ur1rM9`sU;b)4KE&XubY?<<;{M=mkCtYjay;Yc#k z85|j|bV!@DkG7iF;~r&6oB~pm2{=g+VGS~nviYu*D9^KnX`zlHHOh`sjEVLOoPeN& zP3=7^1l3E7Ey`m-+PWAn4E%DwLiS-(rF}`2`Tdt(hX-Dz794NZGhay^8d!R*WaW`n zGQUt_Az?iOq|)PXk|MzxKG#ak_rI5vj9NO5-49sBeay}D-HCrNerGcR&rNJfXsuB? zXvr?YY4pl0V_N}1m$gsOm2z~oWZ)*!zv=u9O1N(z!;w>rdy~<#`zB*3BggbD_2+VbCU zA>azz#YxTIT7&d7T5(KAUWO=6js5ggMnC(^>n;H)C%mM{u!efa(IByee#$9<(WQ;a zN|*PC9HnH_CiDW%V4^Jo7W^N$A0{87Qc3twImU3*kwv8KK33taB$9olB5gCi&*B_g zD>_V>8#n5*2?%VAU*#Mr*nz|YuKTGS+Tbs9sDT3J+etdMSl#n!uOs3 zw;WJU;!tt}F7J2p8eAi>Bgk1#T;8yNbG+HoP{{HX_v_+phw0Akq-09pMf@8xy|fo! zgY2v`(KVaQ-)39^(gJu%QDF@^%#T~o=ye{M^`#fRlSFr0Y_zu~nRPGdKV!kbC1OU+ zz!S0l?Ia*~z5M2MVHE6}wA$tx*ZH7%XXq6Zi=O{vxtPnw>&XqizF)-z>2=TTUV0LU zUjx!XcuCP<4bRnMQm_tZdg(vA;T&JQ9H@7jNcV{KL|f3^sT6QY>o^$HRpT9eZpc=Q}?- ztU=GqH@D8gpv>@_legA#xT@5*w|0)7zwODjhGU&1SD5znHeX+glW=H3^ppQjjwLe0lO|Pc|h1?lL*VQ5rk9G4dQQT?EEyiWoB$$gU zAMO0vuSl{1iy!Z~L`6I54xxMDw7Q=AJQM%3;EfQytcRh&e%l)o!<-;l&-WVeH6&;4X(8g+y%AfKD~_r)x5G z9MUCx?Z8@i<-a&!i3Lcd;3b8?8btiqR34qYNeD!)=b2jR!DuAa8ljAs`mz1D6gxGo zsrHjsV^08Tk}a9*8&c<7RFOiH8iJ_OcgD2!=}L(-wqHhPXS{t(gs~i`a3CBpfzJ|LZxnijTwp%y zl6RxF@*Z6?yWNLzOKR$+Z9rs*TCxZ==Qm2rV&|Wk(q)vp$48AOO$Ar|&)9JQ=@7i6 zD6oc~^Qnjrb($WL(aBK<6;q81I)9QnK8*AUt!oeYW+u$8#08{r@RFj!8gimBORb%Y zXe4$_+fX?6?NwD`0Bss=~#Ff5afagCx)z47GA3dno(qFMnC)B7I^Ac^&ZpX(YU)Xs`yXSiiz^V#cnQX4Z+;-QpGx zgFLVT9@E|zw2oU0zThsf=jlC6Cn~7kF;-nN9mOKOJc#%K8nzr}B*seEYTnu5x%ryL zJsK_UFV>TLNDq1Du{^7f4@j}#B}Iod^omxb=>~zfNm|7;2HZ6xoj-Y0&JpX;q0U#v zdkX6+)K?u_34r3{a>D}r7Z$2z?5c@f@rXJ}eA(jTJf~g_y(*}GYAT(GIT-ZtSUUW} zaq^m<7X=`7Uq%PT0!s|^_~!=s*BWK;AAgU60Hd&g10fLfMej@(gaAzy22xSc&@nKv zuyJtl@CgWsh)GDv$nQ~5Qc=^;($O<8GBLBTvaxe;a&hzU^6?7@-WNhZL=@E&ywYBs zYk9e^%H2Q-*spfaofkPb@a??8d<`Rrhsev39c4h&7Dy`%1n`UFa{1%;VZhWQ>1 zki!5k9V8G$0o6gEsWS_AyRy4nhOGO)^|K2YZe(eJoD(1iE>{*g5TvUE=#ZhQd3V&2 zIesCQ_@F-gA(S_p4#@ckFC9uCC`B94p+Hkj@2G3*G&5aHV;V<#A)r7HoTypB$KJltDR`kk4wpCPf46Ui53Cda>|1$Q zDs#!$)2eZd6M}rhtb?ux9MtIquP@nNp;^_Sh+guM8K`b@)!)w7^VGih@p4c(%c!lI9UyB%u?pK8sL*pAbtu_N1%$MYv>|eh#%x zV=QtQARqLAlN|AOQ$t4hb?|u4yaAUg`NTukzxwRDJHkK7MDuID>tjXfzo--r@x1U` zzP!;pIbatr2QNS^!j@wF1gkMxwrqR!I9+QGm7pdJL1-^)pOU8*7EN^>%rcwnoz^mk}{11 zhO}I z{(qV*S6#P@(^|e^+1Xw$YEfX+tlC^=zBk|I5_WJ~wmXY1da;DELV(7>VW$1suHJf_ znGZ_c`}K_v-PKvBEl~5tNmTC0r`y^oMsE! z?Iy0?-ScRD?B6L(uDbOGLDJ`<$|173&kB^V2@@3dW{Kx6!oS&(G8NpLSoQ@8yP_{7 zS;utCb7T_+MG^Nl?h$OLGOu5v7p~mHOjG~psR+rqfMy`yUoH=3vc_+N&=(n4a zZsMN=kLc^}dyrzC&{a5e>I(>aJUT^<4MF(2^4yViC%*<%!0v58$BmTgcS9P9t|?6p zQvNpk5OXE)$*&D1yr6xFHx{Jfr@}41m70|E1Tlk$_Y$?*M{?|y(g1nBALf7e=p_NL zhW@i}b&^YVdem08@^arLVoaUFK|h^)6;BrjgIGi?rWm*iq|EFD+&=R}pRH=iE1^rQpQxL!C( z5n&BnZeSCe6UNJPUfh6o+s*zqK7rHS=LBD@9B4gvXom;{NpzO7QY;v$6p{%v$Asq; z&&~xJMeZ}6_PA**dHMSeii*)Xho0}a?#wI|rs4fWV8b5H0HihDaFQay8a5~rsfk(R zk%}K4UhmQQ7Ru_5et+U$GdrVt5Z|eI=wlcE(N{M8&k?fk&<~S3&lBz&le!E>qkyUb zny~!f$Ro5bpb4uwo}J6Cd+blG$bFA^ii|S>sXn}*SoXkL4%xM#%^h@=6`nu zV&_;ZB!hiFtms((ofXb3N1NKdDKcVE6mH{x+RZ>vD_{LAk9AXd>HP4CA)&^)caKP) zj~;W2;+_~zWWlBe>ZYh*79hogmlOhP=zBs@t3o4=D28Kb&=T)KP#6?4o9>x2Us{`? z5FY%cSJKhVa*<{FQ_HTw>N^J3e)VMjuo~(Lze|#D3WGFQjrvOTV#$>pt4p$z5vbe} z?|4`PpS}g8OI>if`pB?`=`JitXC97j_rN{OVewW5_syyz%-sjtp}!cNeiSF1`);{# zG&IuxPVS`<@QWvZM^_ey$5m~Kr6*QYd`}vKfJE*&vz1F>-|=eTHmlEuNc$KwLpC6d zgqIWr)?mqRn};#>ArgbQE!b85Dkl@IT-=`!gV}x0^yN5DHuZ#Wkht7xhzbX;y`8~S zuu@#>hfj$Tu^=IXxyemmj{xO&3iOWCugk;DmhEK}Um4F3qmASMQWJPdQDF@)rrvMH zCmpjj=^H=9Y`<}6)=kLWHI(|0c=39dq}oFEM9Cqtr?x$uD64X{iQ6;HwbrQhg8JHM1@aa`m zNPKCw#BZnC&r(m$Rm&7H@-PpO9(;k*JVl2!EIo_FeNd7-S6N>kF-%01RL+4NWX__QS3oVat7RhfAPjZyEsEqcXXPAAu+_@x) zQeQY}9qRW%%qat;{X@5;|F`>Aguoj0&%TvB^5OwoK^OLyvDMhTeO>=TfiBQ6La|7E zP;z;L<5iJ@NfY&jwN*LCAAi+o!L(0aI*wrh5B4qUtmedr!PebJ0(I&pU;-KPmO($h z@D44~hcC5nQho`_Eb=`l2c#E+aFQaz8glrj`kTYYvNlOtqlH9+Ia?w5x)O7d*u@pI zmcP5y_y^CCj&>JG0^KEFmBe5KA7ZRxKS=aU@|_63N7Kg;bzZgt=0Id+qOZhBWqp7C z>e&JBdz1=5Y7Q?c60AYTZj+GN4$<1@Kn17JM3z1AAi~8n0QuK?;ESvC|2)x&kvjvGddLI}sv?`VS0gzh2 zOA3ZHNdJ29`4{KTxT<)|{7K_B$6BLcLzfh>Y6yz$GJa6(pj7BPMQc4DP(1Sc#G#Zh zzHeEAm7Tu42^BIUAo&Ng$YuP-1F=s$FiQdrNH?%$8mgm8)GGn$=2tjfeF&_9`%yS9 z)o*(e7R1NsUR9d|AqG8c-_2PU)-~M}hfB7Tby*fAg|cxSz*h>U>G7de#mFx=8{5gP zmo@Sly^Q0{R^}xOvdqs{m;MyrjsmhS*&4bs29Nt($Qi{g;7= z%&N#&6&d7+MYZ%#I8^0L#Iy4%GIy5%{@7w9$MPP?;T5!wRAtVcQ_`J z_V`lr_`Y_ufbDmNOxxz^My6^&>IN?<3akO+z1=V$1+Ii$?#FD|VujuNC_`o6O$j|q zgc+xPXN4nY6j*xvj2?0cD3~!wFngvqswCERN{wYGfy4ht!urKb)&OF6k8-6lo`>pF z`=R-*@+KLZ8bHbiFDWXl0hdBT%V!}=)37;eqoYli@>~4WXEDEF2qDhsWeXNsB_w=-9t}l)84pZJZgG;rO=DGxCPk^8sFLnwgg@hoh*trTovH?5x2p-`%)* zJQv=MBVn)fVRAA{nn4XpzqJyC+QZb*{N)@4(T_nl!Uh7Eld*v8Pbx}Tp3~>e5GfB~hVGt)OFs*g`$L>uPu4=`Ks!Mj`Hr`G2i&>5%9Eq!m zdbw(}|K7J^SO04S zLV%{S0I7G`x5`F@SdUZ1Jy*NLP-q8o8dS01qXYJ><|Y9hA~e+lNWF^=-Dp_$E51%y zxE7DpXCTKOUOHgkiW90sf~L~nQI~&z&dy7aXG?=mUbX|sVTG3t90+or0CZqz>VnGM z&K>R_x&k_afmEg4=hvM;4(B5{U0Gn?>gfoegFsW4)bFOlLEb#!2_aL&FuYd!0^~#j zIseuE0qm;+*tf!f>X4zSvUk*J@u;eO%}pC4XP@uv0&>vcr33b@!iNDJ3N*D_?QZ8T zar0NaQmXB2eHQ2aZXm}<6Hez2*tg;z0CcF(R8k=IE?=|xT>A)x!{7BnWn74QfE*Sr zIO%|WEBih`hXzeuyrYg-;{1CGkDugZ5UEKokh5U{CmpbFl~WJs(4ncNKF|plsmVJ@okJ_V4Fg+5N}Aai9Z6L4T(~7^K!)59qeN5q`l$ z3c)mZ&&-C_F_|T)l#=zaUT&I<{L;xb2<7Be)TZgk0KTlJdC0xUIqN=j&&Q@o9@IsD z=SQ7+jY5)&RoZ9_bgEXg{eGw_9?@ue(o1r-8{WUtsbc}O25;b`MZBG^!`$O08FF|i zimKo5B;!CvW%~&{oFD%ORkwx;@g%Xv#BcUXqujaHWiMlZWgv;`kz~%$-dA>Y7RDS@ zu!cHFAQoLgsP|b5=lGf8hn7)nRzOPwFD=sT^ss@ewHzfwdBSg-5C(6_y$(x>9H)=z zq%~}U9i2j2)Ej(g*aRsNyzPdV_vlO>jq8{78YYdtHk_(G=H`hwO=fhbM6!`;YHu7Q zs<6ijU}Xcef$-9TZ>LYpNKhsU7&1q^s?vPP(Pv(}`(kNACc=d#H@DmY1wE@7x#9=ZN!${3cw zZ*@k$rp=q41b4{tc>1v*k-sh^j@?x6FV%d!O9TgW-oi_Zd^_EGnIBJmQ3Q!urV^5q zveG@HXm5@eRxIJVCWeZtLkMrv#M7vdyp~Yd+qBGQov5A1hm-37Z`2RrC}&)3o1(t1ooc zueboMOd6bK0_yE_!+rs#R(iGTt{%~(r`2d1Z@bTwMLDSOy%qbFCwLg8h8xg2rNT*zc01i^ zc6+)S`BRI}m9@u^bndrzYa)mUQz~EE+5MulEK!OX`*Mid8-s_UviHTJ8pZk8@VGWH zrIfxYEYs2QEm0~|0* zN+0(uyceb_+bZy$yT^#fCe~k?%TMvov5CB0H);CQMu=#*IK?#ROqc3K;g{$sDxRcQ zf$#OCbHnKx1~7H@EcN-s0A0`woOFn=)QgI71*1SbX}U9)NJ`acwsw}7VKvNG(q7Mg zS0J~h|AZVIJO0%B<3G2Y!6aZhptacyvOvL)?_p6Rpuhf$WfPMZ#OmLN94!v$9Dc${ zhXhOI{H}ejj*qv0*sy(>%*HA%^2seW@%nl`(*8%P;9u2>nLNWPRm*X@k~0QV2Ujm{ zlOd8(759h`84SV(DywuWPtx3X5nYK~5`c~gUOF%=_1hOmud%kLtx+n|Ec>}Gtv3_v z*&{jrE|1rxPjO?Sv7eK>R|_rFZHY+ocz@ZJ{d-WJA)x%8z?#~|0q5fLssyT<_xqs+ zMqmf|T<+=zoX#BtmP*I-c;S15r)e!un41mE38hx{}#KSKiyhfRiM_$~Ro~8eBPa(Hf0xxDk+Pwwg)9a#^ow2=_S;R7jzGEl* zzn5s=Tqs3l7%lh_N&`A)ceIP=qPGGUax> zXt^V#ODcN`ZS)>Rvdb469Vm~HNQ7>eZ7uZTRdeI;RLKB3MtJE^VX2cB zh)SUFX|6yV<5Qd7`7rwpA6IquZv&czgb~-Q29-7bCSlGXO2#>~cklb2NG#;xEe zQ0&LNu1dwbAZTS^;<3+sq=SEwP#r=jlw&3RRV#@~x8MHsa`JgnnC^1q;A8pmqI5Yx zR|zj2IxH1$+P$#hCSPyo;O}e17&8MJ%k5to*7^RXXAD}}Z!GlOVm(74h9HF92V+R4 zr^W^?R_6@Pg!uCL`wX=pIYut32ZzCOyykdnfR1wpQKkrDYnv4Vm(QR(@oUp%*?&^Rpa1l;AL|CfgYK7F!$WRy!{d$p%*)^t- zM(bAu0Zbh`h{wbOthY~I+3GGS^Jq$=T5;gMdl~Fu+EF_%CVL&f8X~&LIod~L^F1#~ zsXI*L5uj6pmktS*T0m#PtDN@6uEH!6(*9 zm9%gQ;ePU@1&_}-ou%usmp*MDnfQ^ADDgY)?R{A|qpr%oIDL(?A8f1R%LLvpM5WW}x#9jxTiCsM82fKCNoIuuyyD(&a+-0QcJ;@-^S<@uzCa)NK)di(2^ zPorwn^ca~IA8(GEOeUd*H&C{}vOU~6;Q6p-nKidt+|;Exl8)N$Lt6R7)1+iEK?l&` zz)Ob;OReE>V#_wnX~dmMteCE2~7pH*T6eAnLefT8iQs{VMfnb%<88- zi)&w&<|TwO&0-2yn95sNS^3D|S+FPZ$68%L*Zd1k^9~J`y1che8GeZOh0s*t`~cs6 z_CA$dAMs9uL02i(k#~M?nKU>@3$-#&d{G?pE4XOVP*;YmI?Peq?akPm&kWTZGx)!% z&~e_8XzBsF=kU^@!%`u#2BMK$*6PlI9W*R4=aRjf9{VoQTPH8b+n3a9nU z33!QseG>+#2nm{cwthE}B`|ge82bu1>Coe!+g-03I1uDS2Z+GX)QUTbtbnoKxp3ek z0`^DzegYy0H1#czdY7wa1B|61{h#ymU!No7K#=@CAVP+wE&_A?E+SiCEMgp-M8H0X z&2vD60!?iPHh%6RvIEB2Xa7I{BkjMMN5J04p)DXng{JZXsdo|C17jIW;3NX}JEV*O j5gIggx%h4(2Vm?DFcvOfYrr0dmk}UBho+X@QS`q61hT$Z literal 0 HcmV?d00001 diff --git a/testing/btest/bifs/routing0_data_to_addrs.test b/testing/btest/bifs/routing0_data_to_addrs.test new file mode 100644 index 0000000000..f150ec2a35 --- /dev/null +++ b/testing/btest/bifs/routing0_data_to_addrs.test @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +event ipv6_ext_headers(c: connection, p: pkt_hdr) + { + for ( h in p$ip6$routing ) + if ( p$ip6$routing[h]$rtype == 0 ) + print routing0_data_to_addrs(p$ip6$routing[h]$data); + } diff --git a/testing/btest/core/ipv6_esp.test b/testing/btest/core/ipv6_esp.test new file mode 100644 index 0000000000..b606c23400 --- /dev/null +++ b/testing/btest/core/ipv6_esp.test @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -r $TRACES/ip6_esp.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the event is raised correctly for a packet containing +# ESP extension headers. + +event esp_packet(p: pkt_hdr) + { + print p; + } diff --git a/testing/btest/core/ipv6_ext_headers.test b/testing/btest/core/ipv6_ext_headers.test new file mode 100644 index 0000000000..170a67bc72 --- /dev/null +++ b/testing/btest/core/ipv6_ext_headers.test @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the event is raised correctly for a packet containing +# extension headers. + +event ipv6_ext_headers(c: connection, p: pkt_hdr) + { + print p; + } From 1c1d6570395432b9bfef8fb9ab1c27f02491f754 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 20 Mar 2012 15:38:37 -0500 Subject: [PATCH 10/13] Changes to IPv6 ext. header parsing (addresses #795). In response to feedback from Robin: - rename "ip_hdr" to "ip4_hdr" - pkt_hdr$ip6 is now of type "ip6_hdr" instead of "ip6_hdr_chain" - "ip6_hdr_chain" no longer contains an "ip6_hdr" field, instead it's the other way around, "ip6_hdr" contains an "ip6_hdr_chain" - other internal refactoring --- scripts/base/init-bare.bro | 108 ++++-- src/Frag.cc | 18 +- src/IP.cc | 345 +++++++++--------- src/IP.h | 190 +++++----- src/PacketSort.cc | 5 +- src/Sessions.cc | 16 + testing/btest/Baseline/core.ipv6-frag/output | 10 +- testing/btest/Baseline/core.ipv6_esp/output | 240 ++++++------ .../Baseline/core.ipv6_ext_headers/output | 2 +- .../btest/bifs/routing0_data_to_addrs.test | 6 +- 10 files changed, 491 insertions(+), 449 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 98da9f331d..42215839c0 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -934,6 +934,10 @@ const ICMP_UNREACH_ADMIN_PROHIB = 13; ##< Adminstratively prohibited. # discarders. # todo::these should go into an enum to make them autodoc'able const IPPROTO_IP = 0; ##< Dummy for IP. [Robin] Rename to IPPROTO_IP4? +# [Jon] I'd say leave it be or remove it because from +# IPPROTO_IPV4 can actually be the same as IPPROTO_IPIP (4)... +# IPPROTO_IP seems to be just for use with the socket API and not +# actually identifying protocol numbers in packet headers const IPPROTO_ICMP = 1; ##< Control message protocol. const IPPROTO_IGMP = 2; ##< Group management protocol. const IPPROTO_IPIP = 4; ##< IP encapsulation in IP. @@ -944,6 +948,13 @@ const IPPROTO_RAW = 255; ##< Raw IP packet. # Definitions for IPv6 extension headers. # [Robin] Do we need a constant for unknown extensions? +# [Jon] I don't think so, these constants are just conveniences to improve +# script readability, but they also identify the actual assigned protocol +# number of the header type. If the core were to actually pass to the +# script-layer a next-header value of something we don't know about yet, +# that value would be the actual value seen in the packet, not something +# we should make up. We could provide a "KNOWN_PROTOCOLS" set for +# convenience that one could check membership against. const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. const IPPROTO_ROUTING = 43; ##< IPv6 routing header. const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. @@ -952,20 +963,6 @@ const IPPROTO_AH = 51; ##< IPv6 authentication header. const IPPROTO_NONE = 59; ##< IPv6 no next header. const IPPROTO_DSTOPTS = 60; ##< IPv6 destination options header. -## Values extracted from an IPv6 header. -## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts ip6_routing -## ip6_fragment ip6_ah ip6_esp -type ip6_hdr: record { - class: count; ##< Traffic class. - flow: count; ##< Flow label. - len: count; ##< Payload length. - nxt: count; ##< Next header (RFC 1700 assigned number). # [Robin] That's just the IPPROTO_* constant right. Then we should refer to them. - hlim: count; ##< Hop limit. - src: addr; ##< Source address. - dst: addr; ##< Destination address. -}; - ## Values extracted from an IPv6 extension header's (e.g. hop-by-hop or ## destination option headers) option field. ## @@ -978,9 +975,10 @@ type ip6_option: record { ## Values extracted from an IPv6 Hop-by-Hop options extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain ip6_option +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option type ip6_hopopts: record { - ## Next header (RFC 1700 assigned number). + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. nxt: count; ## Length of header in 8-octet units, excluding first unit. len: count; @@ -990,9 +988,10 @@ type ip6_hopopts: record { ## Values extracted from an IPv6 Destination options extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain ip6_option +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option type ip6_dstopts: record { - ## Next header (RFC 1700 assigned number). + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. nxt: count; ## Length of header in 8-octet units, excluding first unit. len: count; @@ -1002,9 +1001,10 @@ type ip6_dstopts: record { ## Values extracted from an IPv6 Routing extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain type ip6_routing: record { - ## Next header (RFC 1700 assigned number). + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. nxt: count; ## Length of header in 8-octet units, excluding first unit. len: count; @@ -1018,9 +1018,10 @@ type ip6_routing: record { ## Values extracted from an IPv6 Fragment extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain type ip6_fragment: record { - ## Next header (RFC 1700 assigned number). + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. nxt: count; ## 8-bit reserved field. rsv1: count; @@ -1036,9 +1037,10 @@ type ip6_fragment: record { ## Values extracted from an IPv6 Authentication extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain type ip6_ah: record { - ## Next header (RFC 1700 assigned number). # [Robin] Same as above. + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. nxt: count; ## Length of header in 4-octet units, excluding first two units. len: count; @@ -1054,7 +1056,7 @@ type ip6_ah: record { ## Values extracted from an IPv6 ESP extension header. ## -## .. bro:see:: pkt_hdr ip_hdr ip6_hdr ip6_hdr_chain +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain type ip6_esp: record { ## Security Parameters Index. spi: count; @@ -1064,20 +1066,24 @@ type ip6_esp: record { ## An IPv6 header chain. ## -## .. bro:see:: pkt_hdr ip_hdr -# -# [Robin] How about turning ip6_hdr_chain and ip6_hdr around, making the latter -# the top-level record that then contains an ip6_hdr_chain instance. That way, the -# pkt_hdr record would have ip4_hdr and ip6_hdr members, which seems more natural. +## .. bro:see:: pkt_hdr ip4_hdr # # [Robin] What happens to unknown extension headers? We should keep them too so that # one can at least identify what one can't analyze. +# [Jon] Currently, they show up as "unknown_protocol" weirds and those packets +# are skipped before any "new_packet" or "ipv6_ext_headers" events are +# raised as those depend on a connection parameter which can't be +# created since we can't parse past unknown extension headers to get +# at the upper layer protocol. Does that seem reasonable for at +# being able to identify things that couldn't be analyzed? type ip6_hdr_chain: record { # [Robin] This looses the order of the headers (partially at least, even with ext_order I believe). # Not sure how to do it differently, but can order be important for us? + # [Jon] I do think order can be interesting as RFC 2460 specifies some + # ordering constraints, and I think I provide enough info in this + # record for one to reconstruct the order. Reread my new comments + # for the "ext_order" field below and see if you change your mind. - ## The main IPv6 header. - hdr: ip6_hdr; ## Hop-by-hop option extension header. hopopts: vector of ip6_hopopts; ## Destination option extension headers. @@ -1091,17 +1097,39 @@ type ip6_hdr_chain: record { ## Encapsulating security payload headers. esp: vector of ip6_esp; - ## Order of extension headers identified by RFC 1700 assigned numbers. - # [Robin] I don't understand how this works. + ## Order of extension headers as seen in the packet header. + ## The value at an index indicates the protocol number (RFC 1700 et seq., + ## IANA assigned number) of the header at that same position in the chain. + ## e.g. if :bro:id:`IPPROTO_DSTOPTS` is at index 0 and index 2 and + ## :bro:id:`IPPROTO_ROUTING` is at index 1, then the order of the headers + ## in the chain is the header at index 0 of *dstopts* followed by + ## the header at index 0 of *routing* and then the header at index 1 of + ## *dstopts* (tracking of duplicate header types to know where to + ## index into each vector would be up to the script following the chain). ext_order: vector of count; }; +## Values extracted from an IPv6 header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts +## ip6_routing ip6_fragment ip6_ah ip6_esp +type ip6_hdr: record { + class: count; ##< Traffic class. + flow: count; ##< Flow label. + len: count; ##< Payload length. + nxt: count; ##< Protocol number of the next header + ##< (RFC 1700 et seq., IANA assigned number), e.g. + ##< :bro:id:`IPPROTO_ICMP`. + hlim: count; ##< Hop limit. + src: addr; ##< Source address. + dst: addr; ##< Destination address. + exts: ip6_hdr_chain;##< Extension header chain. +}; + ## Values extracted from an IPv4 header. ## ## .. bro:see:: pkt_hdr ip6_hdr discarder_check_ip -## -# [Robin] Rename to ip4_hdr? -type ip_hdr: record { +type ip4_hdr: record { hl: count; ##< Header length in bytes. tos: count; ##< Type of service. len: count; ##< Total length. @@ -1159,9 +1187,11 @@ type icmp_hdr: record { # # [Robin] Add flags saying whether it's v4/v6, tcp/udp/icmp? The day will come where # we can't infer that from the connection anymore (tunnels). +# [Jon] I'm not sure what you mean, doesn't checking result of ?$ operator +# always work for finding out protocols involved? type pkt_hdr: record { - ip: ip_hdr &optional; ##< The IPv4 header if an IPv4 packet. - ip6: ip6_hdr_chain &optional; ##< The IPv6 header chain if an IPv6 packet. + ip: ip4_hdr &optional; ##< The IPv4 header if an IPv4 packet. + ip6: ip6_hdr &optional; ##< The IPv6 header if an IPv6 packet. tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet. udp: udp_hdr &optional; ##< The UDP header if a UDP packet. icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet. diff --git a/src/Frag.cc b/src/Frag.cc index 68c5c108f1..5fcad35560 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -34,10 +34,13 @@ FragReassembler::FragReassembler(NetSessions* arg_s, key = k; // [Robin] Can't we merge these two cases now? + // [Jon] I think we'll always have to check v4 versus v6 to get the correct + // proto_hdr_len unless IP_Hdr::HdrLen itself makes a special case for + // IPv6 fragments (but that seems more confusing to me) const struct ip* ip4 = ip->IP4_Hdr(); if ( ip4 ) { - proto_hdr_len = ip4->ip_hl * 4; // [Robin] HdrLen? + proto_hdr_len = ip->HdrLen(); proto_hdr = new u_char[64]; // max IP header + slop // Don't do a structure copy - need to pick up options, too. memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); @@ -247,12 +250,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) reassembled_pkt = new IP_Hdr(reassem4, true); } - // [Robin] Please always check for IP version explicitly, like here - // do "if ... ip_v == 6", and then catch other values via - // weird/errors. Even of it shouldn't happen (because of earlier - // checks), it's better to be safe. I believe there are more places - // like this elsewhere, please check. - else + else if ( ((const struct ip*)pkt_start)->ip_v == 6 ) { struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); @@ -260,6 +258,12 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) reassembled_pkt = new IP_Hdr(reassem6, true, chain); } + else + { + reporter->InternalError("bad IP version in fragment reassembly"); + } + + DeleteTimer(); } diff --git a/src/IP.cc b/src/IP.cc index 77797ece8f..9dcb372d3f 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -5,7 +5,7 @@ #include "Val.h" #include "Var.h" -static RecordType* ip_hdr_type = 0; +static RecordType* ip4_hdr_type = 0; static RecordType* ip6_hdr_type = 0; static RecordType* ip6_hdr_chain_type = 0; static RecordType* ip6_option_type = 0; @@ -22,20 +22,6 @@ static inline RecordType* hdrType(RecordType*& type, const char* name) return type; } -RecordVal* IPv6_Hdr::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr")); - const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; - rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT)); - rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT)); - rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT)); - rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT)); - rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT)); - rv->Assign(5, new AddrVal(ip6->ip6_src)); - rv->Assign(6, new AddrVal(ip6->ip6_dst)); - return rv; - } - static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) { VectorVal* vv = new VectorVal(new VectorType( @@ -71,73 +57,100 @@ static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) return vv; } -RecordVal* IPv6_HopOpts::BuildRecordVal() const +RecordVal* IPv6_Hdr::BuildRecordVal() const { - RecordVal* rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts")); - const struct ip6_hbh* hbh = (const struct ip6_hbh*)data; - rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT)); - rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT)); - uint16 off = 2 * sizeof(uint8); - rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); - return rv; + RecordVal* rv = 0; + + switch ( type ) { + case IPPROTO_IPV6: + { + rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr")); + const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; + rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT)); + rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT)); + rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT)); + rv->Assign(5, new AddrVal(ip6->ip6_src)); + rv->Assign(6, new AddrVal(ip6->ip6_dst)); + } + break; + + case IPPROTO_HOPOPTS: + { + rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts")); + const struct ip6_hbh* hbh = (const struct ip6_hbh*)data; + rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + + } + break; + + case IPPROTO_DSTOPTS: + { + rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts")); + const struct ip6_dest* dst = (const struct ip6_dest*)data; + rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + } + break; + + case IPPROTO_ROUTING: + { + rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing")); + const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data; + rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT)); + rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT)); + rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT)); + uint16 off = 4 * sizeof(uint8); + rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1))); + } + break; + + case IPPROTO_FRAGMENT: + { + rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment")); + const struct ip6_frag* frag = (const struct ip6_frag*)data; + rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT)); + rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT)); + rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT)); + rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL)); + rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT)); + } + break; + + case IPPROTO_AH: + { + rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah")); + rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT)); + rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT)); + rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT)); + uint16 off = 3 * sizeof(uint32); + rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1))); + } + break; + + case IPPROTO_ESP: + { + rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp")); + const uint32* esp = (const uint32*)data; + rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT)); + } + break; + + default: + break; } -RecordVal* IPv6_DstOpts::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts")); - const struct ip6_dest* dst = (const struct ip6_dest*)data; - rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT)); - rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT)); - uint16 off = 2 * sizeof(uint8); - rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); - return rv; - } - -RecordVal* IPv6_Routing::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing")); - const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data; - rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT)); - rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT)); - rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT)); - rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT)); - uint16 off = 4 * sizeof(uint8); - rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1))); - return rv; - } - -RecordVal* IPv6_Fragment::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment")); - const struct ip6_frag* frag = (const struct ip6_frag*)data; - rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT)); - rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT)); - rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT)); - rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT)); - rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL)); - rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT)); - return rv; - } - -RecordVal* IPv6_AH::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah")); - rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT)); - rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT)); - rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT)); - rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT)); - rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT)); - uint16 off = 3 * sizeof(uint32); - rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1))); - return rv; - } - -RecordVal* IPv6_ESP::BuildRecordVal() const - { - RecordVal* rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp")); - const uint32* esp = (const uint32*)data; - rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT)); - rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT)); return rv; } @@ -145,22 +158,9 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const { RecordVal* rval = 0; - if ( ! ip_hdr_type ) - { - ip_hdr_type = internal_type("ip_hdr")->AsRecordType(); - ip6_hdr_type = internal_type("ip6_hdr")->AsRecordType(); - ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType(); - ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType(); - ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType(); - ip6_routing_type = internal_type("ip6_routing")->AsRecordType(); - ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType(); - ip6_ah_type = internal_type("ip6_ah")->AsRecordType(); - ip6_esp_type = internal_type("ip6_esp")->AsRecordType(); - } - if ( ip4 ) { - rval = new RecordVal(ip_hdr_type); + rval = new RecordVal(hdrType(ip4_hdr_type, "ip4_hdr")); rval->Assign(0, new Val(ip4->ip_hl * 4, TYPE_COUNT)); rval->Assign(1, new Val(ip4->ip_tos, TYPE_COUNT)); rval->Assign(2, new Val(ntohs(ip4->ip_len), TYPE_COUNT)); @@ -172,55 +172,8 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const } else { - rval = new RecordVal(ip6_hdr_chain_type); - - VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref())); - VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref())); - VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref())); - VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref())); - VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref())); - VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref())); - VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT))); - - for ( size_t i = 1; i < ip6_hdrs->Size(); ++i ) - { - RecordVal* v = ((*ip6_hdrs)[i])->BuildRecordVal(); - uint8 type = ((*ip6_hdrs)[i])->Type(); - switch (type) { - case IPPROTO_HOPOPTS: - hopopts->Assign(hopopts->Size(), v, 0); - break; - case IPPROTO_ROUTING: - routing->Assign(routing->Size(), v, 0); - break; - case IPPROTO_DSTOPTS: - dstopts->Assign(dstopts->Size(), v, 0); - break; - case IPPROTO_FRAGMENT: - fragment->Assign(fragment->Size(), v, 0); - break; - case IPPROTO_AH: - ah->Assign(ah->Size(), v, 0); - break; - case IPPROTO_ESP: - esp->Assign(esp->Size(), v, 0); - break; - case IPPROTO_IPV6: - default: - reporter->InternalError("pkt_hdr assigned bad header %d", type); - break; - } - order->Assign(i-1, new Val(type, TYPE_COUNT), 0); - } - - rval->Assign(0, ((*ip6_hdrs)[0])->BuildRecordVal()); - rval->Assign(1, hopopts); - rval->Assign(2, dstopts); - rval->Assign(3, routing); - rval->Assign(4, fragment); - rval->Assign(5, ah); - rval->Assign(6, esp); - rval->Assign(7, order); + rval = ((*ip6_hdrs)[0])->BuildRecordVal(); + rval->Assign(7, ip6_hdrs->BuildRecordVal()); } return rval; @@ -308,34 +261,6 @@ RecordVal* IP_Hdr::BuildPktHdrVal() const return pkt_hdr; } -static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d, - bool set_next = false, uint16 nxt = 0) - { - switch (type) { - case IPPROTO_IPV6: - return set_next ? new IPv6_Hdr(d, nxt) : new IPv6_Hdr(d); - case IPPROTO_HOPOPTS: - return set_next ? new IPv6_HopOpts(d, nxt) : new IPv6_HopOpts(d); - case IPPROTO_ROUTING: - return set_next ? new IPv6_Routing(d, nxt) : new IPv6_Routing(d); - case IPPROTO_DSTOPTS: - return set_next ? new IPv6_DstOpts(d, nxt) : new IPv6_DstOpts(d); - case IPPROTO_FRAGMENT: - return set_next ? new IPv6_Fragment(d, nxt) : new IPv6_Fragment(d); - case IPPROTO_AH: - return set_next ? new IPv6_AH(d, nxt) : new IPv6_AH(d); - case IPPROTO_ESP: - return new IPv6_ESP(d); // never able to set ESP header's next - default: - // should never get here if calls are protected by isIPv6ExtHeader() - reporter->InternalError("Unknown IPv6 header type: %d", type); - break; - } - // can't be reached - assert(false); - return 0; - } - static inline bool isIPv6ExtHeader(uint8 type) { switch (type) { @@ -361,12 +286,86 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) do { current_type = next_type; - chain.push_back(getIPv6Header(current_type, hdrs, set_next, next)); - next_type = chain[chain.size()-1]->NextHdr(); - uint16 len = chain[chain.size()-1]->Length(); + IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs); + + next_type = p->NextHdr(); + uint16 len = p->Length(); + + if ( set_next && next_type == IPPROTO_FRAGMENT ) + { + p->ChangeNext(next); + next_type = next; + } + + chain.push_back(p); + hdrs += len; length += len; } while ( current_type != IPPROTO_FRAGMENT && current_type != IPPROTO_ESP && isIPv6ExtHeader(next_type) ); } + +RecordVal* IPv6_Hdr_Chain::BuildRecordVal() const + { + if ( ! ip6_hdr_chain_type ) + { + ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType(); + ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType(); + ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType(); + ip6_routing_type = internal_type("ip6_routing")->AsRecordType(); + ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType(); + ip6_ah_type = internal_type("ip6_ah")->AsRecordType(); + ip6_esp_type = internal_type("ip6_esp")->AsRecordType(); + } + + RecordVal* rval = new RecordVal(ip6_hdr_chain_type); + + VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref())); + VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref())); + VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref())); + VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref())); + VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref())); + VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref())); + VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT))); + + for ( size_t i = 1; i < chain.size(); ++i ) + { + RecordVal* v = chain[i]->BuildRecordVal(); + uint8 type = chain[i]->Type(); + switch (type) { + case IPPROTO_HOPOPTS: + hopopts->Assign(hopopts->Size(), v, 0); + break; + case IPPROTO_ROUTING: + routing->Assign(routing->Size(), v, 0); + break; + case IPPROTO_DSTOPTS: + dstopts->Assign(dstopts->Size(), v, 0); + break; + case IPPROTO_FRAGMENT: + fragment->Assign(fragment->Size(), v, 0); + break; + case IPPROTO_AH: + ah->Assign(ah->Size(), v, 0); + break; + case IPPROTO_ESP: + esp->Assign(esp->Size(), v, 0); + break; + case IPPROTO_IPV6: + default: + reporter->InternalError("pkt_hdr assigned bad header %d", type); + break; + } + order->Assign(i-1, new Val(type, TYPE_COUNT), 0); + } + + rval->Assign(0, hopopts); + rval->Assign(1, dstopts); + rval->Assign(2, routing); + rval->Assign(3, fragment); + rval->Assign(4, ah); + rval->Assign(5, esp); + rval->Assign(6, order); + return rval; + } diff --git a/src/IP.h b/src/IP.h index b876a2ac3b..5e5e3c0748 100644 --- a/src/IP.h +++ b/src/IP.h @@ -22,56 +22,94 @@ // members: we're creating/allocating those for every IPv6 packet, right? // // Any idea how to avoid these? +// +// [Jon] Seems fair enough to just remove the virtual method concern at this +// point by replacing the class hierarchy with some inline functions that +// do switch statements. I don't know what to do about the +// vector and ip6_hdrs data members being allocated for every +// IPv6 packet, maybe it's too early to try to optimize before we know +// the frequency at which extension headers appear in real IPv6 traffic? /** * Base class for IPv6 header/extensions. */ class IPv6_Hdr { public: - IPv6_Hdr() : type(0), data(0) {} - - /** - * Construct the main IPv6 header. - */ - IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {} - - /** - * Construct the main IPv6 header, but replace the next protocol field - * if it points to a fragment. - */ - IPv6_Hdr(const u_char* d, uint16 nxt) : type(IPPROTO_IPV6), data(d) - { - // [Robin]. This looks potentially dangerous as it's changing - // the data passed in, which the caller may not realize. From - // quick look, it's only used from Frag.cc, so that may be - // ok. But could we guard against accidental use somehome? - // Like making this protected and then declare a friend; or a - // seperate method ChangeNext(). (I saw it's used by derived - // classes so not sure wehat works best.) - if ( ((ip6_hdr*)data)->ip6_nxt == IPPROTO_FRAGMENT ) - ((ip6_hdr*)data)->ip6_nxt = nxt; - } - /** * Construct an IPv6 header or extension header from assigned type number. */ IPv6_Hdr(uint8 t, const u_char* d) : type(t), data(d) {} - virtual ~IPv6_Hdr() {} + /** + * Replace the value of the next protocol field. + */ + void ChangeNext(uint8 next_type) + { + switch ( type ) { + case IPPROTO_IPV6: + ((ip6_hdr*)data)->ip6_nxt = next_type; + break; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: + ((ip6_ext*)data)->ip6e_nxt = next_type; + break; + case IPPROTO_ESP: + default: + break; + } + } + + ~IPv6_Hdr() {} /** * Returns the assigned IPv6 extension header type number of the header * that immediately follows this one. */ - virtual uint8 NextHdr() const { return ((ip6_hdr*)data)->ip6_nxt; } + uint8 NextHdr() const + { + switch ( type ) { + case IPPROTO_IPV6: + return ((ip6_hdr*)data)->ip6_nxt; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: + return ((ip6_ext*)data)->ip6e_nxt; + case IPPROTO_ESP: + default: + return IPPROTO_NONE; + } + } /** * Returns the length of the header in bytes. */ - virtual uint16 Length() const { return 40; } + uint16 Length() const + { + switch ( type ) { + case IPPROTO_IPV6: + return 40; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + return 8 + 8 * ((ip6_ext*)data)->ip6e_len; + case IPPROTO_FRAGMENT: + return 8; + case IPPROTO_AH: + return 8 + 4 * ((ip6_ext*)data)->ip6e_len; + case IPPROTO_ESP: + return 8; //encrypted payload begins after 8 bytes + default: + return 0; + } + } /** - * Returns the RFC 1700 assigned number indicating the header type. + * Returns the RFC 1700 et seq. IANA assigned number for the header. */ uint8 Type() const { return type; } @@ -83,75 +121,13 @@ public: /** * Returns the script-layer record representation of the header. */ - virtual RecordVal* BuildRecordVal() const; + RecordVal* BuildRecordVal() const; protected: uint8 type; const u_char* data; }; -class IPv6_Ext : public IPv6_Hdr { -public: - IPv6_Ext(uint16 type, const u_char* d) : IPv6_Hdr(type, d) {} - IPv6_Ext(uint16 type, const u_char* d, uint16 nxt) : IPv6_Hdr(type, d) - { - if ( ((ip6_ext*)data)->ip6e_nxt == IPPROTO_FRAGMENT ) - ((ip6_ext*)data)->ip6e_nxt = nxt; - } - uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; } - virtual uint16 Length() const = 0; - virtual RecordVal* BuildRecordVal() const = 0; -}; - -class IPv6_HopOpts : public IPv6_Ext { -public: - IPv6_HopOpts(const u_char* d) : IPv6_Ext(IPPROTO_HOPOPTS, d) {} - IPv6_HopOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_HOPOPTS, d, n) {} - uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } - RecordVal* BuildRecordVal() const; -}; - -class IPv6_DstOpts : public IPv6_Ext { -public: - IPv6_DstOpts(const u_char* d) : IPv6_Ext(IPPROTO_DSTOPTS, d) {} - IPv6_DstOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_DSTOPTS, d, n) {} - uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } - RecordVal* BuildRecordVal() const; -}; - -class IPv6_Routing : public IPv6_Ext { -public: - IPv6_Routing(const u_char* d) : IPv6_Ext(IPPROTO_ROUTING, d) {} - IPv6_Routing(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_ROUTING, d, n) {} - uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; } - RecordVal* BuildRecordVal() const; -}; - -class IPv6_Fragment : public IPv6_Ext { -public: - IPv6_Fragment(const u_char* d) : IPv6_Ext(IPPROTO_FRAGMENT, d) {} - IPv6_Fragment(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_FRAGMENT, d, n) - {} - uint16 Length() const { return 8; } - RecordVal* BuildRecordVal() const; -}; - -class IPv6_AH : public IPv6_Ext { -public: - IPv6_AH(const u_char* d) : IPv6_Ext(IPPROTO_AH, d) {} - IPv6_AH(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_AH, d, n) {} - uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; } - RecordVal* BuildRecordVal() const; -}; - -class IPv6_ESP : public IPv6_Ext { -public: - IPv6_ESP(const u_char* d) : IPv6_Ext(IPPROTO_ESP, d) {} - // encrypted payload begins after 8 bytes - uint16 Length() const { return 8; } - RecordVal* BuildRecordVal() const; -}; - class IPv6_Hdr_Chain { public: /** @@ -159,13 +135,6 @@ public: */ IPv6_Hdr_Chain(const struct ip6_hdr* ip6) { Init(ip6, false); } - /** - * Initializes the header chain from an IPv6 header structure, and replaces - * the first next protocol pointer field that points to a fragment header. - */ - IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next) - { Init(ip6, true, next); } - ~IPv6_Hdr_Chain() { for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; } @@ -218,7 +187,24 @@ public: { return IsFragment() ? (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; } + /** + * Returns an ip6_hdr_chain RecordVal that includes script-layer + * representation of all extension headers in the chain. + */ + RecordVal* BuildRecordVal() const; + protected: + // for access to protected ctor that changes next header values that + // point to a fragment + friend class FragReassembler; + + /** + * Initializes the header chain from an IPv6 header structure, and replaces + * the first next protocol pointer field that points to a fragment header. + */ + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next) + { Init(ip6, true, next); } + void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0); vector chain; @@ -237,8 +223,12 @@ public: ip6 = (const struct ip6_hdr*)p; ip6_hdrs = new IPv6_Hdr_Chain(ip6); } - else if ( arg_del ) - delete [] p; + else + { + if ( arg_del ) + delete [] p; + reporter->InternalError("bad IP version in IP_Hdr ctor"); + } } IP_Hdr(const struct ip* arg_ip4, bool arg_del) diff --git a/src/PacketSort.cc b/src/PacketSort.cc index 7bfdaba9a0..aec7639f4a 100644 --- a/src/PacketSort.cc +++ b/src/PacketSort.cc @@ -28,8 +28,11 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, const struct ip* ip = (const struct ip*) (pkt + hdr_size); if ( ip->ip_v == 4 ) ip_hdr = new IP_Hdr(ip, false); - else + else if ( ip->ip_v == 6 ) ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false); + else + // weird will be generated later in NetSessions::NextPacket + return; if ( ip_hdr->NextProto() == IPPROTO_TCP && // Note: can't sort fragmented packets diff --git a/src/Sessions.cc b/src/Sessions.cc index 675cc240c6..9e91fdc304 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -431,6 +431,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, return; // [Robin] dump_this_packet = 1 for non-ICMP/UDP/TCP removed here. Why? + // [Jon] The default case of the "switch ( proto )" calls Weird() which + // should set dump_this_packet = 1. The old code also returned + // at this point for non-ICMP/UDP/TCP, but for IPv6 fragments + // we need to do the reassembly first before knowing for sure what + // upper-layer protocol it is. FragReassembler* f = 0; @@ -468,8 +473,12 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, caplen -= ip_hdr_len; // [Robin] Does ESP need to be the last header? + // [Jon] In terms of what we try to parse, yes, we can't go any further + // in parsing a header chain once we reach an ESP one since + // encrypted payload immediately follows. if ( ip_hdr->LastHeader() == IPPROTO_ESP ) { + dump_this_packet = 1; if ( esp_packet ) { val_list* vl = new val_list(); @@ -491,6 +500,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // [Robin] The Remove(f) used to be here, while it's now before every // return statement. I'm not seeing why? + // [Jon] That Remove(f) is still here above in the CheckHeaderTrunc() + // conditional that's just a refactoring of the old code. + // The reason why it's not done unconditionally after the reassembly + // is because doing that could cause the object that ip_hdr points + // to to be freed when we still need to use that below. + // I added Remove(f)'s before other "abnormal" return points that + // looked like they'd otherwise leak the memory. const u_char* data = ip_hdr->Payload(); diff --git a/testing/btest/Baseline/core.ipv6-frag/output b/testing/btest/Baseline/core.ipv6-frag/output index 5020d94e8d..80c1a2cc93 100644 --- a/testing/btest/Baseline/core.ipv6-frag/output +++ b/testing/btest/Baseline/core.ipv6-frag/output @@ -1,5 +1,5 @@ -ip6=[hdr=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51850/udp, dport=53/udp, ulen=81] -ip6=[hdr=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=53/udp, dport=51850/udp, ulen=331] -ip6=[hdr=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] -ip6=[hdr=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] -ip6=[hdr=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] +ip6=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51850/udp, dport=53/udp, ulen=81] +ip6=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=53/udp, dport=51850/udp, ulen=331] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] diff --git a/testing/btest/Baseline/core.ipv6_esp/output b/testing/btest/Baseline/core.ipv6_esp/output index 645b4c8c56..db27689364 100644 --- a/testing/btest/Baseline/core.ipv6_esp/output +++ b/testing/btest/Baseline/core.ipv6_esp/output @@ -1,120 +1,120 @@ -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=1]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=2]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=3]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=4]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=5]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=6]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=7]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=8]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=9]], ext_order=[50]], tcp=, udp=, icmp=] -[ip=, ip6=[hdr=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25], hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=10]], ext_order=[50]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] diff --git a/testing/btest/Baseline/core.ipv6_ext_headers/output b/testing/btest/Baseline/core.ipv6_ext_headers/output index 4cc9c706ae..9348cc41c8 100644 --- a/testing/btest/Baseline/core.ipv6_ext_headers/output +++ b/testing/btest/Baseline/core.ipv6_ext_headers/output @@ -1 +1 @@ -[ip=, ip6=[hdr=[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], hopopts=[[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]]], dstopts=[], 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=[], ah=[], esp=[], ext_order=[0, 43]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] +[ip=, 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=[hopopts=[[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]]], dstopts=[], 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=[], ah=[], esp=[], ext_order=[0, 43]]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] diff --git a/testing/btest/bifs/routing0_data_to_addrs.test b/testing/btest/bifs/routing0_data_to_addrs.test index f150ec2a35..eb6ebbc614 100644 --- a/testing/btest/bifs/routing0_data_to_addrs.test +++ b/testing/btest/bifs/routing0_data_to_addrs.test @@ -3,7 +3,7 @@ event ipv6_ext_headers(c: connection, p: pkt_hdr) { - for ( h in p$ip6$routing ) - if ( p$ip6$routing[h]$rtype == 0 ) - print routing0_data_to_addrs(p$ip6$routing[h]$data); + for ( h in p$ip6$exts$routing ) + if ( p$ip6$exts$routing[h]$rtype == 0 ) + print routing0_data_to_addrs(p$ip6$exts$routing[h]$data); } From c765f43fe3eb6fd4cb49b2b947654881a225e145 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 21 Mar 2012 10:32:39 -0500 Subject: [PATCH 11/13] Refactor script-layer IPv6 ext. header chain (addresses #795) This replaces the "ip6_hdr_chain" in the "ip6_hdr" record with a vector of "ip6_ext_hdr" to make it easier to traverse the chain. --- scripts/base/init-bare.bro | 70 ++--- src/IP.cc | 58 ++--- src/IP.h | 6 +- testing/btest/Baseline/core.ipv6-frag/output | 10 +- testing/btest/Baseline/core.ipv6_esp/output | 240 +++++++++--------- .../Baseline/core.ipv6_ext_headers/output | 2 +- .../btest/bifs/routing0_data_to_addrs.test | 7 +- 7 files changed, 185 insertions(+), 208 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 42215839c0..b3c997a750 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -1064,9 +1064,10 @@ type ip6_esp: record { seq: count; }; -## An IPv6 header chain. +## A general container for a more specific IPv6 extension header. ## -## .. bro:see:: pkt_hdr ip4_hdr +## .. bro:see:: pkt_hdr ip4_hdr ip6_hopopts ip6_dstopts ip6_routing ip6_fragment +## ip6_ah ip6_esp # # [Robin] What happens to unknown extension headers? We should keep them too so that # one can at least identify what one can't analyze. @@ -1076,37 +1077,22 @@ type ip6_esp: record { # created since we can't parse past unknown extension headers to get # at the upper layer protocol. Does that seem reasonable for at # being able to identify things that couldn't be analyzed? -type ip6_hdr_chain: record { - # [Robin] This looses the order of the headers (partially at least, even with ext_order I believe). - # Not sure how to do it differently, but can order be important for us? - # [Jon] I do think order can be interesting as RFC 2460 specifies some - # ordering constraints, and I think I provide enough info in this - # record for one to reconstruct the order. Reread my new comments - # for the "ext_order" field below and see if you change your mind. - +type ip6_ext_hdr: record { + ## The RFC 1700 et seq. IANA assigned number identifying the type of + ## the extension header. + id: count; ## Hop-by-hop option extension header. - hopopts: vector of ip6_hopopts; - ## Destination option extension headers. - dstopts: vector of ip6_dstopts; - ## Routing extension headers. - routing: vector of ip6_routing; - ## Fragment headers. - fragment: vector of ip6_fragment; - ## Authentication extension headers. - ah: vector of ip6_ah; - ## Encapsulating security payload headers. - esp: vector of ip6_esp; - - ## Order of extension headers as seen in the packet header. - ## The value at an index indicates the protocol number (RFC 1700 et seq., - ## IANA assigned number) of the header at that same position in the chain. - ## e.g. if :bro:id:`IPPROTO_DSTOPTS` is at index 0 and index 2 and - ## :bro:id:`IPPROTO_ROUTING` is at index 1, then the order of the headers - ## in the chain is the header at index 0 of *dstopts* followed by - ## the header at index 0 of *routing* and then the header at index 1 of - ## *dstopts* (tracking of duplicate header types to know where to - ## index into each vector would be up to the script following the chain). - ext_order: vector of count; + hopopts: ip6_hopopts &optional; + ## Destination option extension header. + dstopts: ip6_dstopts &optional; + ## Routing extension header. + routing: ip6_routing &optional; + ## Fragment header. + fragment: ip6_fragment &optional; + ## Authentication extension header. + ah: ip6_ah &optional; + ## Encapsulating security payload header. + esp: ip6_esp &optional; }; ## Values extracted from an IPv6 header. @@ -1114,16 +1100,16 @@ type ip6_hdr_chain: record { ## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts ## ip6_routing ip6_fragment ip6_ah ip6_esp type ip6_hdr: record { - class: count; ##< Traffic class. - flow: count; ##< Flow label. - len: count; ##< Payload length. - nxt: count; ##< Protocol number of the next header - ##< (RFC 1700 et seq., IANA assigned number), e.g. - ##< :bro:id:`IPPROTO_ICMP`. - hlim: count; ##< Hop limit. - src: addr; ##< Source address. - dst: addr; ##< Destination address. - exts: ip6_hdr_chain;##< Extension header chain. + class: count; ##< Traffic class. + flow: count; ##< Flow label. + len: count; ##< Payload length. + nxt: count; ##< Protocol number of the next header + ##< (RFC 1700 et seq., IANA assigned number) + ##< e.g. :bro:id:`IPPROTO_ICMP`. + hlim: count; ##< Hop limit. + src: addr; ##< Source address. + dst: addr; ##< Destination address. + exts: vector of ip6_ext_hdr; ##< Extension header chain. }; ## Values extracted from an IPv4 header. diff --git a/src/IP.cc b/src/IP.cc index 9dcb372d3f..d6d1df0c31 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -7,7 +7,7 @@ static RecordType* ip4_hdr_type = 0; static RecordType* ip6_hdr_type = 0; -static RecordType* ip6_hdr_chain_type = 0; +static RecordType* ip6_ext_hdr_type = 0; static RecordType* ip6_option_type = 0; static RecordType* ip6_hopopts_type = 0; static RecordType* ip6_dstopts_type = 0; @@ -57,7 +57,7 @@ static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) return vv; } -RecordVal* IPv6_Hdr::BuildRecordVal() const +RecordVal* IPv6_Hdr::BuildRecordVal(VectorVal* chain) const { RecordVal* rv = 0; @@ -73,6 +73,10 @@ RecordVal* IPv6_Hdr::BuildRecordVal() const rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT)); rv->Assign(5, new AddrVal(ip6->ip6_src)); rv->Assign(6, new AddrVal(ip6->ip6_dst)); + if ( ! chain ) + chain = new VectorVal(new VectorType( + hdrType(ip6_ext_hdr_type, "ip6_ext_hdr")->Ref())); + rv->Assign(7, chain); } break; @@ -172,8 +176,7 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const } else { - rval = ((*ip6_hdrs)[0])->BuildRecordVal(); - rval->Assign(7, ip6_hdrs->BuildRecordVal()); + rval = ((*ip6_hdrs)[0])->BuildRecordVal(ip6_hdrs->BuildVal()); } return rval; @@ -306,11 +309,11 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) isIPv6ExtHeader(next_type) ); } -RecordVal* IPv6_Hdr_Chain::BuildRecordVal() const +VectorVal* IPv6_Hdr_Chain::BuildVal() const { - if ( ! ip6_hdr_chain_type ) + if ( ! ip6_ext_hdr_type ) { - ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType(); + ip6_ext_hdr_type = internal_type("ip6_ext_hdr")->AsRecordType(); ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType(); ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType(); ip6_routing_type = internal_type("ip6_routing")->AsRecordType(); @@ -319,53 +322,40 @@ RecordVal* IPv6_Hdr_Chain::BuildRecordVal() const ip6_esp_type = internal_type("ip6_esp")->AsRecordType(); } - RecordVal* rval = new RecordVal(ip6_hdr_chain_type); - - VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref())); - VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref())); - VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref())); - VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref())); - VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref())); - VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref())); - VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT))); + VectorVal* rval = new VectorVal(new VectorType(ip6_ext_hdr_type->Ref())); for ( size_t i = 1; i < chain.size(); ++i ) { RecordVal* v = chain[i]->BuildRecordVal(); + RecordVal* ext_hdr = new RecordVal(ip6_ext_hdr_type); uint8 type = chain[i]->Type(); + ext_hdr->Assign(0, new Val(type, TYPE_COUNT)); + switch (type) { case IPPROTO_HOPOPTS: - hopopts->Assign(hopopts->Size(), v, 0); - break; - case IPPROTO_ROUTING: - routing->Assign(routing->Size(), v, 0); + ext_hdr->Assign(1, v); break; case IPPROTO_DSTOPTS: - dstopts->Assign(dstopts->Size(), v, 0); + ext_hdr->Assign(2, v); + break; + case IPPROTO_ROUTING: + ext_hdr->Assign(3, v); break; case IPPROTO_FRAGMENT: - fragment->Assign(fragment->Size(), v, 0); + ext_hdr->Assign(4, v); break; case IPPROTO_AH: - ah->Assign(ah->Size(), v, 0); + ext_hdr->Assign(5, v); break; case IPPROTO_ESP: - esp->Assign(esp->Size(), v, 0); + ext_hdr->Assign(6, v); break; - case IPPROTO_IPV6: default: - reporter->InternalError("pkt_hdr assigned bad header %d", type); + reporter->InternalError("IPv6_Hdr_Chain bad header %d", type); break; } - order->Assign(i-1, new Val(type, TYPE_COUNT), 0); + rval->Assign(rval->Size(), ext_hdr, 0); } - rval->Assign(0, hopopts); - rval->Assign(1, dstopts); - rval->Assign(2, routing); - rval->Assign(3, fragment); - rval->Assign(4, ah); - rval->Assign(5, esp); - rval->Assign(6, order); return rval; } diff --git a/src/IP.h b/src/IP.h index 5e5e3c0748..a989b04d76 100644 --- a/src/IP.h +++ b/src/IP.h @@ -121,7 +121,7 @@ public: /** * Returns the script-layer record representation of the header. */ - RecordVal* BuildRecordVal() const; + RecordVal* BuildRecordVal(VectorVal* chain = 0) const; protected: uint8 type; @@ -188,10 +188,10 @@ public: (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; } /** - * Returns an ip6_hdr_chain RecordVal that includes script-layer + * Returns a vector of ip6_ext_hdr RecordVals that includes script-layer * representation of all extension headers in the chain. */ - RecordVal* BuildRecordVal() const; + VectorVal* BuildVal() const; protected: // for access to protected ctor that changes next header values that diff --git a/testing/btest/Baseline/core.ipv6-frag/output b/testing/btest/Baseline/core.ipv6-frag/output index 80c1a2cc93..12dfc3a841 100644 --- a/testing/btest/Baseline/core.ipv6-frag/output +++ b/testing/btest/Baseline/core.ipv6-frag/output @@ -1,5 +1,5 @@ -ip6=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51850/udp, dport=53/udp, ulen=81] -ip6=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=53/udp, dport=51850/udp, ulen=331] -ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51851/udp, dport=53/udp, ulen=82] -ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=51851/udp, dport=53/udp, ulen=82] -ip6=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[], ext_order=[]]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] +ip6=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51850/udp, dport=53/udp, ulen=81] +ip6=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[]], udp = [sport=53/udp, dport=51850/udp, ulen=331] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] diff --git a/testing/btest/Baseline/core.ipv6_esp/output b/testing/btest/Baseline/core.ipv6_esp/output index db27689364..97a8434e7b 100644 --- a/testing/btest/Baseline/core.ipv6_esp/output +++ b/testing/btest/Baseline/core.ipv6_esp/output @@ -1,120 +1,120 @@ -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=10, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=11, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=12, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=13, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=20, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=21, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=22, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=1]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=2]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=3]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=4]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=5]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=6]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=7]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=8]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=9]], ext_order=[50]]], tcp=, udp=, icmp=] -[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[hopopts=[], dstopts=[], routing=[], fragment=[], ah=[], esp=[[spi=23, seq=10]], ext_order=[50]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=10]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=1]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=2]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=3]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=4]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=5]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=6]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=7]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=8]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=9]]]], tcp=, udp=, icmp=] +[ip=, ip6=[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=10]]]], tcp=, udp=, icmp=] diff --git a/testing/btest/Baseline/core.ipv6_ext_headers/output b/testing/btest/Baseline/core.ipv6_ext_headers/output index 9348cc41c8..a5a0caf7c6 100644 --- a/testing/btest/Baseline/core.ipv6_ext_headers/output +++ b/testing/btest/Baseline/core.ipv6_ext_headers/output @@ -1 +1 @@ -[ip=, 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=[hopopts=[[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]]], dstopts=[], 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=[], ah=[], esp=[], ext_order=[0, 43]]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] +[ip=, 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=, routing=, fragment=, ah=, esp=], [id=43, hopopts=, dstopts=, 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=, ah=, esp=]]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] diff --git a/testing/btest/bifs/routing0_data_to_addrs.test b/testing/btest/bifs/routing0_data_to_addrs.test index eb6ebbc614..4bf15cae87 100644 --- a/testing/btest/bifs/routing0_data_to_addrs.test +++ b/testing/btest/bifs/routing0_data_to_addrs.test @@ -3,7 +3,8 @@ event ipv6_ext_headers(c: connection, p: pkt_hdr) { - for ( h in p$ip6$exts$routing ) - if ( p$ip6$exts$routing[h]$rtype == 0 ) - print routing0_data_to_addrs(p$ip6$exts$routing[h]$data); + for ( h in p$ip6$exts ) + if ( p$ip6$exts[h]$id == IPPROTO_ROUTING ) + if ( p$ip6$exts[h]$routing$rtype == 0 ) + print routing0_data_to_addrs(p$ip6$exts[h]$routing$data); } From 4321f635acd4bd7f83899c3e4ec7cf2d4e3d1468 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Mar 2012 16:40:14 -0700 Subject: [PATCH 12/13] Removing remaining comments. Looks fine. --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- cmake | 2 +- scripts/base/init-bare.bro | 28 +--------------------------- src/Frag.cc | 4 ---- src/IP.h | 16 ---------------- src/Net.cc | 1 - src/Sessions.cc | 25 +++---------------------- 10 files changed, 9 insertions(+), 75 deletions(-) diff --git a/aux/binpac b/aux/binpac index 3034da8f08..dd1a3a95f0 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 3034da8f082b61157e234237993ffd7a95be6e62 +Subproject commit dd1a3a95f07082efcd5274b21104a038d523d132 diff --git a/aux/bro-aux b/aux/bro-aux index f53bcb2b49..a59b35bdad 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit f53bcb2b492cb0db3dd288384040abc2ab711767 +Subproject commit a59b35bdada8f70fb1a59bf7bb2976534c86d378 diff --git a/aux/broccoli b/aux/broccoli index a08ca90727..612e95ac62 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit a08ca90727c5c4b90aa8633106ec33a5cf7378d4 +Subproject commit 612e95ac62a06b32b2e9e627f30527012a89a12c diff --git a/aux/broctl b/aux/broctl index 954538514d..66e9e87bee 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 954538514d71983e7ef3f0e109960466096e1c1d +Subproject commit 66e9e87beebce983fa0f479b0284d5690b0290d4 diff --git a/cmake b/cmake index 2cc1055770..550ab2c8d9 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 2cc105577044a2d214124568f3f2496ed2ccbb34 +Subproject commit 550ab2c8d95b1d3e18e40a903152650e6c7a3c45 diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index b3c997a750..7b1b304405 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -933,11 +933,7 @@ const ICMP_UNREACH_ADMIN_PROHIB = 13; ##< Adminstratively prohibited. # Definitions for access to packet headers. Currently only used for # discarders. # todo::these should go into an enum to make them autodoc'able -const IPPROTO_IP = 0; ##< Dummy for IP. [Robin] Rename to IPPROTO_IP4? -# [Jon] I'd say leave it be or remove it because from -# IPPROTO_IPV4 can actually be the same as IPPROTO_IPIP (4)... -# IPPROTO_IP seems to be just for use with the socket API and not -# actually identifying protocol numbers in packet headers +const IPPROTO_IP = 0; ##< Dummy for IP. const IPPROTO_ICMP = 1; ##< Control message protocol. const IPPROTO_IGMP = 2; ##< Group management protocol. const IPPROTO_IPIP = 4; ##< IP encapsulation in IP. @@ -947,14 +943,6 @@ const IPPROTO_IPV6 = 41; ##< IPv6 header. const IPPROTO_RAW = 255; ##< Raw IP packet. # Definitions for IPv6 extension headers. -# [Robin] Do we need a constant for unknown extensions? -# [Jon] I don't think so, these constants are just conveniences to improve -# script readability, but they also identify the actual assigned protocol -# number of the header type. If the core were to actually pass to the -# script-layer a next-header value of something we don't know about yet, -# that value would be the actual value seen in the packet, not something -# we should make up. We could provide a "KNOWN_PROTOCOLS" set for -# convenience that one could check membership against. const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. const IPPROTO_ROUTING = 43; ##< IPv6 routing header. const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. @@ -1068,15 +1056,6 @@ type ip6_esp: record { ## ## .. bro:see:: pkt_hdr ip4_hdr ip6_hopopts ip6_dstopts ip6_routing ip6_fragment ## ip6_ah ip6_esp -# -# [Robin] What happens to unknown extension headers? We should keep them too so that -# one can at least identify what one can't analyze. -# [Jon] Currently, they show up as "unknown_protocol" weirds and those packets -# are skipped before any "new_packet" or "ipv6_ext_headers" events are -# raised as those depend on a connection parameter which can't be -# created since we can't parse past unknown extension headers to get -# at the upper layer protocol. Does that seem reasonable for at -# being able to identify things that couldn't be analyzed? type ip6_ext_hdr: record { ## The RFC 1700 et seq. IANA assigned number identifying the type of ## the extension header. @@ -1170,11 +1149,6 @@ type icmp_hdr: record { ## A packet header, consisting of an IP header and transport-layer header. ## ## .. bro:see:: new_packet -# -# [Robin] Add flags saying whether it's v4/v6, tcp/udp/icmp? The day will come where -# we can't infer that from the connection anymore (tunnels). -# [Jon] I'm not sure what you mean, doesn't checking result of ?$ operator -# always work for finding out protocols involved? type pkt_hdr: record { ip: ip4_hdr &optional; ##< The IPv4 header if an IPv4 packet. ip6: ip6_hdr &optional; ##< The IPv6 header if an IPv6 packet. diff --git a/src/Frag.cc b/src/Frag.cc index 5fcad35560..a744526921 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -33,10 +33,6 @@ FragReassembler::FragReassembler(NetSessions* arg_s, s = arg_s; key = k; - // [Robin] Can't we merge these two cases now? - // [Jon] I think we'll always have to check v4 versus v6 to get the correct - // proto_hdr_len unless IP_Hdr::HdrLen itself makes a special case for - // IPv6 fragments (but that seems more confusing to me) const struct ip* ip4 = ip->IP4_Hdr(); if ( ip4 ) { diff --git a/src/IP.h b/src/IP.h index a989b04d76..f3e8272080 100644 --- a/src/IP.h +++ b/src/IP.h @@ -14,22 +14,6 @@ #include #include -// [Robin] I'm concerced about the virtual methods here. These methods will -// be called *a lot* and that may add to some significant overhead I'm afraid -// (at least eventually as IPv6 is picking up). -// -// [Robin] Similar concern for the vector and ip6_hdrs data -// members: we're creating/allocating those for every IPv6 packet, right? -// -// Any idea how to avoid these? -// -// [Jon] Seems fair enough to just remove the virtual method concern at this -// point by replacing the class hierarchy with some inline functions that -// do switch statements. I don't know what to do about the -// vector and ip6_hdrs data members being allocated for every -// IPv6 packet, maybe it's too early to try to optimize before we know -// the frequency at which extension headers appear in real IPv6 traffic? - /** * Base class for IPv6 header/extensions. */ diff --git a/src/Net.cc b/src/Net.cc index c92545cb87..35c3b383f6 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -42,7 +42,6 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); PList(PktSrc) pkt_srcs; // FIXME: We should really merge PktDumper and PacketDumper. -// It's on my to-do [Robin]. PktDumper* pkt_dumper = 0; int reading_live = 0; diff --git a/src/Sessions.cc b/src/Sessions.cc index 9e91fdc304..4f31d29346 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -430,13 +430,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) ) return; - // [Robin] dump_this_packet = 1 for non-ICMP/UDP/TCP removed here. Why? - // [Jon] The default case of the "switch ( proto )" calls Weird() which - // should set dump_this_packet = 1. The old code also returned - // at this point for non-ICMP/UDP/TCP, but for IPv6 fragments - // we need to do the reassembly first before knowing for sure what - // upper-layer protocol it is. - FragReassembler* f = 0; if ( ip_hdr->IsFragment() ) @@ -472,10 +465,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; - // [Robin] Does ESP need to be the last header? - // [Jon] In terms of what we try to parse, yes, we can't go any further - // in parsing a header chain once we reach an ESP one since - // encrypted payload immediately follows. + // We stop building the chain when seeing IPPROTO_ESP so if it's + // there, it's always the last. if ( ip_hdr->LastHeader() == IPPROTO_ESP ) { dump_this_packet = 1; @@ -498,16 +489,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, return; } - // [Robin] The Remove(f) used to be here, while it's now before every - // return statement. I'm not seeing why? - // [Jon] That Remove(f) is still here above in the CheckHeaderTrunc() - // conditional that's just a refactoring of the old code. - // The reason why it's not done unconditionally after the reassembly - // is because doing that could cause the object that ip_hdr points - // to to be freed when we still need to use that below. - // I added Remove(f)'s before other "abnormal" return points that - // looked like they'd otherwise leak the memory. - const u_char* data = ip_hdr->Payload(); ConnID id; @@ -553,7 +534,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } default: - Weird(fmt("unknown_protocol %d", proto), hdr, pkt); + Weird(fmt("unknown_protocol_%d", proto), hdr, pkt); Remove(f); return; } From 30014ac92010bdf1dca6534303ecee8945c0e657 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Mar 2012 16:49:29 -0700 Subject: [PATCH 13/13] Cosmetics in preparation for merge. --- scripts/base/init-bare.bro | 16 ++++++++-------- src/Frag.cc | 2 +- src/IP.cc | 5 ++++- src/IP.h | 4 +++- src/PacketSort.cc | 2 +- src/Sessions.cc | 6 +++++- src/bro.bif | 1 + 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 7b1b304405..b9eca66d24 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -945,7 +945,7 @@ const IPPROTO_RAW = 255; ##< Raw IP packet. # Definitions for IPv6 extension headers. const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. const IPPROTO_ROUTING = 43; ##< IPv6 routing header. -const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. +const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. const IPPROTO_ESP = 50; ##< IPv6 encapsulating security payload header. const IPPROTO_AH = 51; ##< IPv6 authentication header. const IPPROTO_NONE = 59; ##< IPv6 no next header. @@ -1081,14 +1081,14 @@ type ip6_ext_hdr: record { type ip6_hdr: record { class: count; ##< Traffic class. flow: count; ##< Flow label. - len: count; ##< Payload length. - nxt: count; ##< Protocol number of the next header - ##< (RFC 1700 et seq., IANA assigned number) - ##< e.g. :bro:id:`IPPROTO_ICMP`. + len: count; ##< Payload length. + nxt: count; ##< Protocol number of the next header + ##< (RFC 1700 et seq., IANA assigned number) + ##< e.g. :bro:id:`IPPROTO_ICMP`. hlim: count; ##< Hop limit. - src: addr; ##< Source address. - dst: addr; ##< Destination address. - exts: vector of ip6_ext_hdr; ##< Extension header chain. + src: addr; ##< Source address. + dst: addr; ##< Destination address. + exts: vector of ip6_ext_hdr; ##< Extension header chain. }; ## Values extracted from an IPv4 header. diff --git a/src/Frag.cc b/src/Frag.cc index a744526921..9bd16a71c9 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -90,7 +90,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) if ( ip->NextProto() != next_proto || ip->HdrLen() - 8 != proto_hdr_len ) s->Weird("fragment_protocol_inconsistency", ip); - //TODO: more detailed unfrag header consistency checks? + // TODO: more detailed unfrag header consistency checks? } if ( ip->DF() ) diff --git a/src/IP.cc b/src/IP.cc index d6d1df0c31..4148c58a33 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -18,7 +18,9 @@ static RecordType* ip6_esp_type = 0; static inline RecordType* hdrType(RecordType*& type, const char* name) { - if ( ! type ) type = internal_type(name)->AsRecordType(); + if ( ! type ) + type = internal_type(name)->AsRecordType(); + return type; } @@ -54,6 +56,7 @@ static VectorVal* BuildOptionsVal(const u_char* data, uint16 len) vv->Assign(vv->Size(), rv, 0); } + return vv; } diff --git a/src/IP.h b/src/IP.h index f3e8272080..cb5bcf77c7 100644 --- a/src/IP.h +++ b/src/IP.h @@ -229,7 +229,9 @@ public: ~IP_Hdr() { - if ( ip6 ) delete ip6_hdrs; + if ( ip6 ) + delete ip6_hdrs; + if ( del ) { if ( ip4 ) diff --git a/src/PacketSort.cc b/src/PacketSort.cc index aec7639f4a..04c525c4d1 100644 --- a/src/PacketSort.cc +++ b/src/PacketSort.cc @@ -31,7 +31,7 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, else if ( ip->ip_v == 6 ) ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false); else - // weird will be generated later in NetSessions::NextPacket + // Weird will be generated later in NetSessions::NextPacket. return; if ( ip_hdr->NextProto() == IPPROTO_TCP && diff --git a/src/Sessions.cc b/src/Sessions.cc index 4f31d29346..f03b6d4c63 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -640,20 +640,24 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, min_hdr_len = sizeof(struct udphdr); break; case IPPROTO_ICMP: - default: min_hdr_len = ICMP_MINLEN; break; + default: + internal_error("unknown protocol"); } + if ( len < min_hdr_len ) { Weird("truncated_header", h, p); return true; } + if ( caplen < min_hdr_len ) { Weird("internally_truncated_header", h, p); return true; } + return false; } diff --git a/src/bro.bif b/src/bro.bif index 375a1c64c1..64ed7d1f2f 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2067,6 +2067,7 @@ function routing0_data_to_addrs%(s: string%): addr_set const u_char* bytes = s->Bytes(); bytes += 4; // go past 32-bit reserved field len -= 4; + if ( ( len % 16 ) != 0 ) reporter->Warning("Bad ip6_routing data length: %d", s->Len());