Fixes for IPv6 truncation and ICMP/ICMP6 analysis.

- Add more guards against trying to analyze captured packets with a
  truncated IPv6 static header or extension header chain.

- Add back in the ICMP payload tracking for ICMP "connections".

- Fix 'icmp_context' record construction.  Some field assignments
  were mismatched for ICMP and ICMP6.  Source and destination
  addresses were set incorrectly for context packets that don't
  contain a full IP header.  Some fields for ICMP6 weren't filled out.

- Changed ICMP Time Exceeded packets to raise the 'icmp_time_exceeded'
  event instead of 'icmp_error_message'.

- Add unit tests for truncation and the main types of ICMP/ICMP6
  that have specific events.

- Documentation clarifications.
This commit is contained in:
Jon Siwek 2012-04-11 16:27:31 -05:00
parent 27ba3118c1
commit 51bad73e1e
39 changed files with 422 additions and 52 deletions

View file

@ -102,11 +102,13 @@ type icmp_conn: record {
## .. bro:see:: icmp_time_exceeded icmp_unreachable ## .. bro:see:: icmp_time_exceeded icmp_unreachable
type icmp_context: record { type icmp_context: record {
id: conn_id; ##< The packet's 4-tuple. id: conn_id; ##< The packet's 4-tuple.
len: count; ##< The lenght of the packet's IP header. len: count; ##< The length of the IP packet (headers + payload).
proto: count; ##< The packet's transport-layer protocol. proto: count; ##< The packet's transport-layer protocol.
frag_offset: count; ##< The packet's fragementation offset. frag_offset: count; ##< The packet's fragementation offset.
## True if the packet's IP header is fully included in the context. If that is not ## True if the packet's IP header is not fully included in the context
## the case, the other fields will all be set to null values. ## or if there is not enough of the transport header to determine source
## and destination ports. If that is the cast, the appropriate fields
## of this record will be set to null values.
bad_hdr_len: bool; bad_hdr_len: bool;
bad_checksum: bool; ##< True if the packet's IP checksum is not correct. bad_checksum: bool; ##< True if the packet's IP checksum is not correct.
MF: bool; ##< True if the packets *more fragements* flag is set. MF: bool; ##< True if the packets *more fragements* flag is set.

View file

@ -150,7 +150,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt)
void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n) void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n)
{ {
IP_Hdr proto_h(proto_hdr, false); IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
if ( memcmp((const void*) b1, (const void*) b2, n) ) if ( memcmp((const void*) b1, (const void*) b2, n) )
s->Weird("fragment_inconsistency", &proto_h); s->Weird("fragment_inconsistency", &proto_h);
@ -182,7 +182,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
// can happen for benign reasons when we're // can happen for benign reasons when we're
// intermingling parts of two fragmented packets. // intermingling parts of two fragmented packets.
IP_Hdr proto_h(proto_hdr, false); IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
s->Weird("fragment_size_inconsistency", &proto_h); s->Weird("fragment_size_inconsistency", &proto_h);
// We decide to analyze the contiguous portion now. // We decide to analyze the contiguous portion now.
@ -196,7 +196,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
else if ( last_block->upper > frag_size ) else if ( last_block->upper > frag_size )
{ {
IP_Hdr proto_h(proto_hdr, false); IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
s->Weird("fragment_size_inconsistency", &proto_h); s->Weird("fragment_size_inconsistency", &proto_h);
frag_size = last_block->upper; frag_size = last_block->upper;
} }
@ -250,8 +250,8 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
{ {
struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start;
reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40);
const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto); const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n);
reassembled_pkt = new IP_Hdr(reassem6, true, chain); reassembled_pkt = new IP_Hdr(reassem6, true, n, chain);
} }
else else

View file

@ -93,6 +93,12 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
caplen -= 8; caplen -= 8;
len -= 8; len -= 8;
int& len_stat = is_orig ? request_len : reply_len;
if ( len_stat < 0 )
len_stat = len;
else
len_stat += len;
if ( ip->NextProto() == IPPROTO_ICMP ) if ( ip->NextProto() == IPPROTO_ICMP )
NextICMP4(current_timestamp, icmpp, len, caplen, data, ip); NextICMP4(current_timestamp, icmpp, len, caplen, data, ip);
else else
@ -286,13 +292,12 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
IPAddr src_addr, dst_addr; IPAddr src_addr, dst_addr;
uint32 src_port, dst_port; uint32 src_port, dst_port;
if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) if ( len < (int)sizeof(struct ip) || ip_hdr_len > uint32(len) )
{ {
// We don't have an entire IP header. // We don't have an entire IP header.
bad_hdr_len = 1; bad_hdr_len = 1;
ip_len = frag_offset = 0; ip_len = frag_offset = 0;
DF = MF = bad_checksum = 0; DF = MF = bad_checksum = 0;
src_addr = dst_addr = 0;
src_port = dst_port = 0; src_port = dst_port = 0;
} }
@ -331,9 +336,9 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
iprec->Assign(0, id_val); iprec->Assign(0, id_val);
iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
iprec->Assign(2, new Val(proto, TYPE_COUNT)); iprec->Assign(2, new Val(proto, TYPE_COUNT));
iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); iprec->Assign(3, new Val(frag_offset, TYPE_COUNT));
iprec->Assign(4, new Val(bad_checksum, TYPE_BOOL)); iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL));
iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL));
iprec->Assign(6, new Val(MF, TYPE_BOOL)); iprec->Assign(6, new Val(MF, TYPE_BOOL));
iprec->Assign(7, new Val(DF, TYPE_BOOL)); iprec->Assign(7, new Val(DF, TYPE_BOOL));
@ -342,32 +347,33 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
{ {
const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false); int DF = 0, MF = 0, bad_hdr_len = 0;
const IP_Hdr* ip_hdr = &ip_hdr_data;
int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0;
TransportProto proto = TRANSPORT_UNKNOWN; TransportProto proto = TRANSPORT_UNKNOWN;
uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40
IPAddr src_addr; IPAddr src_addr;
IPAddr dst_addr; IPAddr dst_addr;
uint32 ip_len, frag_offset = 0; uint32 ip_len, frag_offset = 0;
uint32 src_port, dst_port; uint32 src_port, dst_port;
if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) // XXX What's the 2nd part doing? if ( len < (int)sizeof(struct ip6_hdr) )
{ {
bad_hdr_len = 1; bad_hdr_len = 1;
ip_len = 0; ip_len = 0;
src_addr = dst_addr = 0;
src_port = dst_port = 0; src_port = dst_port = 0;
} }
else else
{ {
ip_len = ip_hdr->TotalLen(); const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false, len);
const IP_Hdr* ip_hdr = &ip_hdr_data;
ip_len = ip_hdr->TotalLen();
src_addr = ip_hdr->SrcAddr(); src_addr = ip_hdr->SrcAddr();
dst_addr = ip_hdr->DstAddr(); dst_addr = ip_hdr->DstAddr();
frag_offset = ip_hdr->FragOffset();
MF = ip_hdr->MF();
DF = ip_hdr->DF();
if ( uint32(len) >= ip_hdr_len + 4 ) if ( uint32(len) >= uint32(ip_hdr->HdrLen() + 4) )
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
else else
{ {
@ -388,17 +394,13 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
iprec->Assign(0, id_val); iprec->Assign(0, id_val);
iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
iprec->Assign(2, new Val(proto, TYPE_COUNT));
//if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more iprec->Assign(3, new Val(frag_offset, TYPE_COUNT));
iprec->Assign(2, new Val(58, TYPE_COUNT)); iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL));
// bad_checksum is always false since IPv6 layer doesn't have a checksum
iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); iprec->Assign(5, new Val(0, TYPE_BOOL));
iprec->Assign(6, new Val(MF, TYPE_BOOL));
// The following are not available for IPv6. iprec->Assign(7, new Val(DF, TYPE_BOOL));
iprec->Assign(4, new Val(0, TYPE_BOOL)); // bad_checksum
iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); // frag_offset
iprec->Assign(6, new Val(0, TYPE_BOOL)); // MF
iprec->Assign(7, new Val(1, TYPE_BOOL)); // DF
return iprec; return iprec;
} }
@ -608,7 +610,7 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
break; break;
case ICMP_TIMXCEED: case ICMP_TIMXCEED:
f = icmp_error_message; f = icmp_time_exceeded;
break; break;
} }

View file

@ -419,20 +419,35 @@ static inline bool isIPv6ExtHeader(uint8 type)
} }
} }
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len,
bool set_next, uint16 next)
{ {
length = 0; length = 0;
uint8 current_type, next_type; uint8 current_type, next_type;
next_type = IPPROTO_IPV6; next_type = IPPROTO_IPV6;
const u_char* hdrs = (const u_char*) ip6; const u_char* hdrs = (const u_char*) ip6;
if ( total_len < (int)sizeof(struct ip6_hdr) )
reporter->InternalError("IPv6_HdrChain::Init with truncated IP header");
do do
{ {
// We can't determine a given header's length if there's less than
// two bytes of data available (2nd byte of extension headers is length)
if ( total_len < 2 ) return;
current_type = next_type; current_type = next_type;
IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs); IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs);
next_type = p->NextHdr(); next_type = p->NextHdr();
uint16 len = p->Length(); uint16 cur_len = p->Length();
// If this header is truncated, don't add it to chain, don't go further
if ( cur_len > total_len )
{
delete p;
return;
}
if ( set_next && next_type == IPPROTO_FRAGMENT ) if ( set_next && next_type == IPPROTO_FRAGMENT )
{ {
@ -444,16 +459,17 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next)
// Check for routing headers and remember final destination address. // Check for routing headers and remember final destination address.
if ( current_type == IPPROTO_ROUTING ) if ( current_type == IPPROTO_ROUTING )
ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, len); ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, cur_len);
#ifdef ENABLE_MOBILE_IPV6 #ifdef ENABLE_MOBILE_IPV6
// Only Mobile IPv6 has a destination option we care about right now. // Only Mobile IPv6 has a destination option we care about right now.
if ( current_type == IPPROTO_DSTOPTS ) if ( current_type == IPPROTO_DSTOPTS )
ProcessDstOpts((const struct ip6_dest*) hdrs, len); ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len);
#endif #endif
hdrs += len; hdrs += cur_len;
length += len; length += cur_len;
total_len -= cur_len;
} while ( current_type != IPPROTO_FRAGMENT && } while ( current_type != IPPROTO_FRAGMENT &&
current_type != IPPROTO_ESP && current_type != IPPROTO_ESP &&
#ifdef ENABLE_MOBILE_IPV6 #ifdef ENABLE_MOBILE_IPV6

View file

@ -142,12 +142,12 @@ public:
/** /**
* Initializes the header chain from an IPv6 header structure. * 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, int len) :
#ifdef ENABLE_MOBILE_IPV6 #ifdef ENABLE_MOBILE_IPV6
homeAddr(0), homeAddr(0),
#endif #endif
finalDst(0) finalDst(0)
{ Init(ip6, false); } { Init(ip6, len, false); }
~IPv6_Hdr_Chain() ~IPv6_Hdr_Chain()
{ {
@ -250,14 +250,20 @@ protected:
* Initializes the header chain from an IPv6 header structure, and replaces * Initializes the header chain from an IPv6 header structure, and replaces
* the first next protocol pointer field that points to a fragment header. * the first next protocol pointer field that points to a fragment header.
*/ */
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next) : IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next, int len) :
#ifdef ENABLE_MOBILE_IPV6 #ifdef ENABLE_MOBILE_IPV6
homeAddr(0), homeAddr(0),
#endif #endif
finalDst(0) finalDst(0)
{ Init(ip6, true, next); } { Init(ip6, len, true, next); }
void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0); /**
* Initializes the header chain from an IPv6 header structure of a given
* length, possibly setting the first next protocol pointer field that
* points to a fragment header.
*/
void Init(const struct ip6_hdr* ip6, int total_len, bool set_next,
uint16 next = 0);
/** /**
* Process a routing header and allocate/remember the final destination * Process a routing header and allocate/remember the final destination
@ -294,9 +300,21 @@ protected:
IPAddr* finalDst; IPAddr* finalDst;
}; };
/**
* A class that wraps either an IPv4 or IPv6 packet and abstracts methods
* for inquiring about common features between the two.
*/
class IP_Hdr { class IP_Hdr {
public: public:
IP_Hdr(const u_char* p, bool arg_del) /**
* Attempts to construct the header from some blob of data based on IP
* version number. Caller must have already checked that the header
* is not truncated.
* @param p pointer to memory containing an IPv4 or IPv6 packet.
* @param arg_del whether to take ownership of \a p pointer's memory.
* @param len the length of data, in bytes, pointed to by \a p.
*/
IP_Hdr(const u_char* p, bool arg_del, int len)
: ip4(0), ip6(0), del(arg_del), ip6_hdrs(0) : ip4(0), ip6(0), del(arg_del), ip6_hdrs(0)
{ {
if ( ((const struct ip*)p)->ip_v == 4 ) if ( ((const struct ip*)p)->ip_v == 4 )
@ -304,7 +322,7 @@ public:
else if ( ((const struct ip*)p)->ip_v == 6 ) else if ( ((const struct ip*)p)->ip_v == 6 )
{ {
ip6 = (const struct ip6_hdr*)p; ip6 = (const struct ip6_hdr*)p;
ip6_hdrs = new IPv6_Hdr_Chain(ip6); ip6_hdrs = new IPv6_Hdr_Chain(ip6, len);
} }
else else
{ {
@ -314,18 +332,38 @@ public:
} }
} }
/**
* Construct the header wrapper from an IPv4 packet. Caller must have
* already checked that the header is not truncated.
* @param arg_ip4 pointer to memory containing an IPv4 packet.
* @param arg_del whether to take ownership of \a arg_ip4 pointer's memory.
*/
IP_Hdr(const struct ip* arg_ip4, bool arg_del) IP_Hdr(const struct ip* arg_ip4, bool arg_del)
: ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0) : ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0)
{ {
} }
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, /**
* Construct the header wrapper from an IPv6 packet. Caller must have
* already checked that the static IPv6 header is not truncated. If
* the packet contains extension headers and they are truncated, that can
* be checked afterwards by comparing \a len with \a TotalLen. E.g.
* NetSessions::DoNextPacket does this to skip truncated packets.
* @param arg_ip6 pointer to memory containing an IPv6 packet.
* @param arg_del whether to take ownership of \a arg_ip6 pointer's memory.
* @param len the packet's length in bytes.
* @param c an already-constructed header chain to take ownership of.
*/
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len,
const IPv6_Hdr_Chain* c = 0) const IPv6_Hdr_Chain* c = 0)
: ip4(0), ip6(arg_ip6), del(arg_del), : ip4(0), ip6(arg_ip6), del(arg_del),
ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6)) ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len))
{ {
} }
/**
* Destructor.
*/
~IP_Hdr() ~IP_Hdr()
{ {
if ( ip6 ) if ( ip6 )
@ -340,8 +378,14 @@ public:
} }
} }
/**
* If an IPv4 packet is wrapped, return a pointer to it, else null.
*/
const struct ip* IP4_Hdr() const { return ip4; } const struct ip* IP4_Hdr() const { return ip4; }
/**
* If an IPv6 packet is wrapped, return a pointer to it, else null.
*/
const struct ip6_hdr* IP6_Hdr() const { return ip6; } const struct ip6_hdr* IP6_Hdr() const { return ip6; }
/** /**
@ -441,9 +485,15 @@ public:
{ return ip4 ? ip4->ip_p : { return ip4 ? ip4->ip_p :
((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); } ((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); }
/**
* Returns the IPv4 Time to Live or IPv6 Hop Limit field.
*/
unsigned char TTL() const unsigned char TTL() const
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; } { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
/**
* Returns whether the IP header indicates this packet is a fragment.
*/
bool IsFragment() const bool IsFragment() const
{ return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 :
ip6_hdrs->IsFragment(); } ip6_hdrs->IsFragment(); }

View file

@ -28,8 +28,8 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src,
const struct ip* ip = (const struct ip*) (pkt + hdr_size); const struct ip* ip = (const struct ip*) (pkt + hdr_size);
if ( ip->ip_v == 4 ) if ( ip->ip_v == 4 )
ip_hdr = new IP_Hdr(ip, false); ip_hdr = new IP_Hdr(ip, false);
else if ( ip->ip_v == 6 ) else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) )
ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false); ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size);
else else
// Weird will be generated later in NetSessions::NextPacket. // Weird will be generated later in NetSessions::NextPacket.
return; return;

View file

@ -281,7 +281,12 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
else if ( ip->ip_v == 6 ) else if ( ip->ip_v == 6 )
{ {
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false); if ( caplen < sizeof(struct ip6_hdr) )
{
Weird("truncated_IP", hdr, pkt);
return;
}
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen);
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size); DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
} }

View file

@ -0,0 +1,12 @@
icmp_unreachable (code=0)
conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=0, v6=F]
icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F]
icmp_unreachable (code=0)
conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=20, v6=F]
icmp_context: [id=[orig_h=10.0.0.2, orig_p=0/unknown, resp_h=10.0.0.1, resp_p=0/unknown], len=20, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F]
icmp_unreachable (code=3)
conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp]
icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F]
icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]

View file

@ -0,0 +1,20 @@
icmp_unreachable (code=3)
conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp]
icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F]
icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_time_exceeded (code=0)
conn_id: [orig_h=10.0.0.1, orig_p=11/icmp, resp_h=10.0.0.2, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=11, icode=0, len=32, v6=F]
icmp_context: [id=[orig_h=10.0.0.2, orig_p=30000/udp, resp_h=10.0.0.1, resp_p=13000/udp], len=32, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_echo_request (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567)
conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F]
icmp_echo_reply (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567)
conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F]
icmp_echo_request (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567)
conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F]
icmp_echo_reply (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567)
conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp]
icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F]

View file

@ -0,0 +1,16 @@
icmp_unreachable (code=0)
conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=0, v6=T]
icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F]
icmp_unreachable (code=0)
conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=40, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F]
icmp_unreachable (code=0)
conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_unreachable (code=0)
conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=48, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F]

View file

@ -0,0 +1,55 @@
icmp_unreachable (code=0)
conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_packet_too_big (code=0)
conn_id: [orig_h=fe80::dead, orig_p=2/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=2, icode=0, len=52, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_time_exceeded (code=0)
conn_id: [orig_h=fe80::dead, orig_p=3/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=3, icode=0, len=52, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_parameter_problem (code=0)
conn_id: [orig_h=fe80::dead, orig_p=4/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=4, icode=0, len=52, v6=T]
icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F]
icmp_echo_request (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_reply (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_request (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_reply (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_request (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_reply (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_request (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_echo_reply (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi)
conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp]
icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T]
icmp_redirect (tgt=fe80::cafe, dest=fe80::babe)
conn_id: [orig_h=fe80::dead, orig_p=137/icmp, resp_h=fe80::beef, resp_p=0/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=137, icode=0, len=32, v6=T]
icmp_router_advertisement (hop_limit=0, managed=F, rlifetime=1800, reachable=0.000000, retrans=0.000000)
conn_id: [orig_h=fe80::dead, orig_p=134/icmp, resp_h=fe80::beef, resp_p=133/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=134, icode=0, len=8, v6=T]
icmp_neighbor_advertisement (tgt=fe80::babe)
conn_id: [orig_h=fe80::dead, orig_p=136/icmp, resp_h=fe80::beef, resp_p=135/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=136, icode=0, len=16, v6=T]
icmp_router_solicitation
conn_id: [orig_h=fe80::dead, orig_p=133/icmp, resp_h=fe80::beef, resp_p=134/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=133, icode=0, len=0, v6=T]
icmp_neighbor_solicitation (tgt=fe80::babe)
conn_id: [orig_h=fe80::dead, orig_p=135/icmp, resp_h=fe80::beef, resp_p=136/icmp]
icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=135, icode=0, len=16, v6=T]

View file

@ -0,0 +1,3 @@
1334160095.895421 weird: truncated_IP
1334156241.519125 weird: truncated_IP
1334094648.590126 weird: truncated_IP

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,7 +1,7 @@
# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-ip.bro >output # @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-tcp.bro >>output
# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.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: bro -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output
# @TEST-EXEC: btest-diff output # @TEST-EXEC: btest-diff output
@TEST-START-FILE discarder-ip.bro @TEST-START-FILE discarder-ip.bro

View file

@ -0,0 +1,14 @@
# These tests all check that IPv6 context packet construction for ICMP6 works.
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-no-context.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-ip.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1
# @TEST-EXEC: btest-diff output
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_unreachable (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}

View file

@ -0,0 +1,44 @@
# These tests all check that ICMP6 events get raised with correct arguments.
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-timeexceeded.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-ping.pcap %INPUT >>output 2>&1
# @TEST-EXEC: btest-diff output
event icmp_sent(c: connection, icmp: icmp_conn)
{
print "icmp_sent";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
{
print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
{
print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_unreachable (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_time_exceeded (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}

View file

@ -0,0 +1,15 @@
# These tests all check that IPv6 context packet construction for ICMP6 works.
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-no-context.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-trunc.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext.pcap %INPUT >>output 2>&1
# @TEST-EXEC: btest-diff output
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_unreachable (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}

View file

@ -0,0 +1,110 @@
# These tests all check that ICMP6 events get raised with correct arguments.
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-toobig.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-timeexceeded.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-paramprob.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-ping.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-redirect.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-advert.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-advert.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-solicit.pcap %INPUT >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-solicit.pcap %INPUT >>output 2>&1
# @TEST-EXEC: btest-diff output
event icmp_sent(c: connection, icmp: icmp_conn)
{
print "icmp_sent";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
{
print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
{
print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_unreachable (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_packet_too_big (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_time_exceeded (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_parameter_problem (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr)
{
print "icmp_redirect (tgt=" + fmt("%s", tgt) + ", dest=" + fmt("%s", dest) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
{
print "icmp_error_message (code=" + fmt("%d", code) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
print " icmp_context: " + fmt("%s", context);
}
event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr)
{
print "icmp_neighbor_solicitation (tgt=" + fmt("%s", tgt) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr)
{
print "icmp_neighbor_advertisement (tgt=" + fmt("%s", tgt) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_router_solicitation(c: connection, icmp: icmp_conn)
{
print "icmp_router_solicitation";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}
event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval)
{
print "icmp_router_advertisement (hop_limit=" + fmt("%d", hop_limit) + ", managed=" + fmt("%s", managed) + ", rlifetime=" + fmt("%d", router_lifetime) + ", reachable=" + fmt("%f", reachable_time) + ", retrans=" + fmt("%f", retrans_timer) + ")";
print " conn_id: " + fmt("%s", c$id);
print " icmp_conn: " + fmt("%s", icmp);
}

View file

@ -0,0 +1,6 @@
# Truncated IP packet's should not be analyzed, and generate truncated_IP weird
# @TEST-EXEC: bro -b -r $TRACES/trunc/ip4-trunc.pcap >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-trunc.pcap >>output 2>&1
# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-ext-trunc.pcap >>output 2>&1
# @TEST-EXEC: btest-diff output