From ea2ce67c5f2e7d80097b6264bb2c4db8faf9d2b5 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 18 May 2015 14:30:32 -0400 Subject: [PATCH 01/26] Fixes an issue with missing zlib headers on deflated HTTP content. - Includes a test. --- src/analyzer/protocol/zip/ZIP.cc | 82 ++++++++++++------ .../http.log | 11 +++ .../Traces/http/missing-zlib-header.pcap | Bin 0 -> 14844 bytes .../protocols/http/missing-zlib-header.bro | 6 ++ 4 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.http.missing-zlib-header/http.log create mode 100644 testing/btest/Traces/http/missing-zlib-header.pcap create mode 100644 testing/btest/scripts/base/protocols/http/missing-zlib-header.bro diff --git a/src/analyzer/protocol/zip/ZIP.cc b/src/analyzer/protocol/zip/ZIP.cc index 132515f29a..e71ba438b7 100644 --- a/src/analyzer/protocol/zip/ZIP.cc +++ b/src/analyzer/protocol/zip/ZIP.cc @@ -22,10 +22,9 @@ ZIP_Analyzer::ZIP_Analyzer(Connection* conn, bool orig, Method arg_method) zip->next_in = 0; zip->avail_in = 0; - // "15" here means maximum compression. "32" is a gross overload - // hack that means "check it for whether it's a gzip file". Sheesh. - zip_status = inflateInit2(zip, 15 + 32); - if ( zip_status != Z_OK ) + // "32" is a gross overload hack that means "check it + // for whether it's a gzip file". Sheesh. + if ( inflateInit2(zip, MAX_WBITS+32) != Z_OK ) { Weird("inflate_init_failed"); delete zip; @@ -54,40 +53,69 @@ void ZIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) return; static unsigned int unzip_size = 4096; - Bytef unzipbuf[unzip_size]; + int allow_restart = 1; + u_char *unzipbuf = new u_char[unzip_size]; + if ( unzipbuf == NULL ) + { + Weird("failed_to_allocate_deflate_buffer"); + return; + } zip->next_in = (Bytef*) data; zip->avail_in = len; - do + Bytef *orig_in = zip->next_in; + size_t nread = zip->avail_in; + + for(;;) { - zip->next_out = unzipbuf; + zip->next_out = (Bytef *)unzipbuf; zip->avail_out = unzip_size; zip_status = inflate(zip, Z_SYNC_FLUSH); + if ( zip_status == Z_STREAM_END || + zip_status == Z_OK ) + { + allow_restart = 0; - if ( zip_status != Z_STREAM_END && - zip_status != Z_OK && - zip_status != Z_BUF_ERROR ) + int have = unzip_size - zip->avail_out; + if ( have ) + ForwardStream(have, unzipbuf, IsOrig()); + + if ( zip_status == Z_STREAM_END ) + { + inflateEnd(zip); + delete unzipbuf; + return; + } + + if ( zip->avail_in == 0 ) + { + delete unzipbuf; + return; + } + } + else if ( allow_restart && zip_status == Z_DATA_ERROR ) + { + // Some servers seem to not generate zlib headers, + // so this is an attempt to fix and continue anyway. + inflateEnd(zip); + if ( inflateInit2(zip, -MAX_WBITS) != Z_OK ) + { + delete unzipbuf; + return; + } + + zip->next_in = orig_in; + zip->avail_in = nread; + allow_restart = 0; + continue; + } + else { Weird("inflate_failed"); - inflateEnd(zip); - break; + delete unzipbuf; + return; } - - int have = unzip_size - zip->avail_out; - if ( have ) - ForwardStream(have, unzipbuf, IsOrig()); - - if ( zip_status == Z_STREAM_END ) - { - inflateEnd(zip); - delete zip; - zip = 0; - break; - } - - zip_status = Z_OK; } - while ( zip->avail_out == 0 ); } diff --git a/testing/btest/Baseline/scripts.base.protocols.http.missing-zlib-header/http.log b/testing/btest/Baseline/scripts.base.protocols.http.missing-zlib-header/http.log new file mode 100644 index 0000000000..c4c96b7fb9 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.missing-zlib-header/http.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2015-05-12-16-26-53 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string set[enum] string string set[string] vector[string] vector[string] vector[string] vector[string] +1232039472.314927 CXWv6p3arKYeMETxOg 237.244.174.255 1905 79.218.110.244 80 1 GET ads1.msn.com /library/dap.js http://zone.msn.com/en/root/default.htm Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727) 0 13249 200 OK - - - (empty) - - - - - FBcNS3RwceOxW15xg text/plain +1232039472.446194 CXWv6p3arKYeMETxOg 237.244.174.255 1905 79.218.110.244 80 2 GET ads1.msn.com /library/dap.js http://zone.msn.com/en/root/default.htm Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727) 0 13249 200 OK - - - (empty) - - - - - FDWU85N0DpedJPh93 text/plain +#close 2015-05-12-16-26-53 diff --git a/testing/btest/Traces/http/missing-zlib-header.pcap b/testing/btest/Traces/http/missing-zlib-header.pcap new file mode 100644 index 0000000000000000000000000000000000000000..66406a9a4022f112bf4873b462bb30d4fe4f862f GIT binary patch literal 14844 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 literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/http/missing-zlib-header.bro b/testing/btest/scripts/base/protocols/http/missing-zlib-header.bro new file mode 100644 index 0000000000..25923f70da --- /dev/null +++ b/testing/btest/scripts/base/protocols/http/missing-zlib-header.bro @@ -0,0 +1,6 @@ +# This tests an issue where some web servers don't +# include an appropriate ZLIB header on deflated +# content. +# +# @TEST-EXEC: bro -r $TRACES/http/missing-zlib-header.pcap %INPUT +# @TEST-EXEC: btest-diff http.log From 08822e0dd43df88fcbe719c0092a2787cfc1e339 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 22 May 2015 11:46:50 -0500 Subject: [PATCH 02/26] Allow '<' and '>' in MIME multipart boundaries. The spec doesn't actually seem to permit these, but Seth had a (private) pcap showing them used in the wild (and the HTTP/MIME analyzer failed to parse content as a result). --- src/analyzer/protocol/http/HTTP.cc | 7 +++- src/analyzer/protocol/mime/MIME.cc | 66 +++++++++++++++--------------- src/analyzer/protocol/mime/MIME.h | 7 ++-- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/analyzer/protocol/http/HTTP.cc b/src/analyzer/protocol/http/HTTP.cc index f60d1372ac..ff72c6f350 100644 --- a/src/analyzer/protocol/http/HTTP.cc +++ b/src/analyzer/protocol/http/HTTP.cc @@ -1025,8 +1025,11 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) } else { - ProtocolViolation("not a http reply line"); - reply_state = EXPECT_REPLY_NOTHING; + if ( line != end_of_line ) + { + ProtocolViolation("not a http reply line"); + reply_state = EXPECT_REPLY_NOTHING; + } } break; diff --git a/src/analyzer/protocol/mime/MIME.cc b/src/analyzer/protocol/mime/MIME.cc index a1759d97d0..17630f0501 100644 --- a/src/analyzer/protocol/mime/MIME.cc +++ b/src/analyzer/protocol/mime/MIME.cc @@ -246,11 +246,16 @@ int MIME_get_field_name(int len, const char* data, data_chunk_t* name) } // See RFC 2045, page 12. -int MIME_is_tspecial (char ch) +int MIME_is_tspecial (char ch, bool is_boundary = false) { - return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' || - ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || - ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='; + if ( is_boundary ) + return ch == '(' || ch == ')' || ch == '@' || + ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || + ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='; + else + return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' || + ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || + ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='; } int MIME_is_field_name_char (char ch) @@ -258,26 +263,27 @@ int MIME_is_field_name_char (char ch) return ch >= 33 && ch <= 126 && ch != ':'; } -int MIME_is_token_char (char ch) +int MIME_is_token_char (char ch, bool is_boundary = false) { - return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch); + return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch, is_boundary); } // See RFC 2045, page 12. // A token is composed of characters that are not SPACE, CTLs or tspecials -int MIME_get_token(int len, const char* data, data_chunk_t* token) +int MIME_get_token(int len, const char* data, data_chunk_t* token, + bool is_boundary) { int i = MIME_skip_lws_comments(len, data); while ( i < len ) { int j; - if ( MIME_is_token_char(data[i]) ) + if ( MIME_is_token_char(data[i], is_boundary) ) { token->data = (data + i); for ( j = i; j < len; ++j ) { - if ( ! MIME_is_token_char(data[j]) ) + if ( ! MIME_is_token_char(data[j], is_boundary) ) break; } @@ -359,7 +365,7 @@ int MIME_get_quoted_string(int len, const char* data, data_chunk_t* str) return -1; } -int MIME_get_value(int len, const char* data, BroString*& buf) +int MIME_get_value(int len, const char* data, BroString*& buf, bool is_boundary) { int offset = MIME_skip_lws_comments(len, data); @@ -380,7 +386,7 @@ int MIME_get_value(int len, const char* data, BroString*& buf) else { data_chunk_t str; - int end = MIME_get_token(len, data, &str); + int end = MIME_get_token(len, data, &str, is_boundary); if ( end < 0 ) return -1; @@ -863,8 +869,22 @@ int MIME_Entity::ParseFieldParameters(int len, const char* data) len -= offset; BroString* val = 0; - // token or quoted-string - offset = MIME_get_value(len, data, val); + + if ( current_field_type == MIME_CONTENT_TYPE && + content_type == CONTENT_TYPE_MULTIPART && + strcasecmp_n(attr, "boundary") == 0 ) + { + // token or quoted-string (and some lenience for characters + // not explicitly allowed by the RFC, but encountered in the wild) + offset = MIME_get_value(len, data, val, true); + data_chunk_t vd = get_data_chunk(val); + multipart_boundary = new BroString((const u_char*)vd.data, + vd.length, 1); + } + else + // token or quoted-string + offset = MIME_get_value(len, data, val); + if ( offset < 0 ) { IllegalFormat("value not found in parameter specification"); @@ -874,8 +894,6 @@ int MIME_Entity::ParseFieldParameters(int len, const char* data) data += offset; len -= offset; - - ParseParameter(attr, get_data_chunk(val)); delete val; } @@ -920,24 +938,6 @@ void MIME_Entity::ParseContentEncoding(data_chunk_t encoding_mechanism) content_encoding = i; } -void MIME_Entity::ParseParameter(data_chunk_t attr, data_chunk_t val) - { - switch ( current_field_type ) { - case MIME_CONTENT_TYPE: - if ( content_type == CONTENT_TYPE_MULTIPART && - strcasecmp_n(attr, "boundary") == 0 ) - multipart_boundary = new BroString((const u_char*)val.data, val.length, 1); - break; - - case MIME_CONTENT_TRANSFER_ENCODING: - break; - - default: - break; - } - } - - int MIME_Entity::CheckBoundaryDelimiter(int len, const char* data) { if ( ! multipart_boundary ) diff --git a/src/analyzer/protocol/mime/MIME.h b/src/analyzer/protocol/mime/MIME.h index a3ee45d071..46c96658fb 100644 --- a/src/analyzer/protocol/mime/MIME.h +++ b/src/analyzer/protocol/mime/MIME.h @@ -117,7 +117,6 @@ protected: void ParseContentType(data_chunk_t type, data_chunk_t sub_type); void ParseContentEncoding(data_chunk_t encoding_mechanism); - void ParseParameter(data_chunk_t attr, data_chunk_t val); void BeginBody(); void NewDataLine(int len, const char* data, int trailing_CRLF); @@ -275,9 +274,11 @@ extern int MIME_count_leading_lws(int len, const char* data); extern int MIME_count_trailing_lws(int len, const char* data); extern int MIME_skip_comments(int len, const char* data); extern int MIME_skip_lws_comments(int len, const char* data); -extern int MIME_get_token(int len, const char* data, data_chunk_t* token); +extern int MIME_get_token(int len, const char* data, data_chunk_t* token, + bool is_boundary = false); extern int MIME_get_slash_token_pair(int len, const char* data, data_chunk_t* first, data_chunk_t* second); -extern int MIME_get_value(int len, const char* data, BroString*& buf); +extern int MIME_get_value(int len, const char* data, BroString*& buf, + bool is_boundary = false); extern int MIME_get_field_name(int len, const char* data, data_chunk_t* name); extern BroString* MIME_decode_quoted_pairs(data_chunk_t buf); From b386b2ba5122ac4d51f586f15a1793621fa1a5ad Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Thu, 28 May 2015 12:11:06 +0200 Subject: [PATCH 03/26] BIT-1314: Add detection for Quantum Insert attacks TCP_Reassembler can now keep a history of old TCP segments using the `tcp_max_old_segments` option. A value of zero will disable it. An overlapping segment with different data can indicate a possible TCP injection attack. The rexmit_inconsistency event will fire if this is the case. --- src/NetVar.cc | 2 + src/NetVar.h | 1 + src/Reassem.cc | 70 +++++++++++++++++++- src/Reassem.h | 12 ++++ src/analyzer/protocol/tcp/TCP_Reassembler.cc | 3 + 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/NetVar.cc b/src/NetVar.cc index 123e947701..dc049005bb 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -49,6 +49,7 @@ double tcp_partial_close_delay; int tcp_max_initial_window; int tcp_max_above_hole_without_any_acks; int tcp_excessive_data_without_further_acks; +int tcp_max_old_segments; RecordType* socks_address; @@ -354,6 +355,7 @@ void init_net_var() opt_internal_int("tcp_max_above_hole_without_any_acks"); tcp_excessive_data_without_further_acks = opt_internal_int("tcp_excessive_data_without_further_acks"); + tcp_max_old_segments = opt_internal_int("tcp_max_old_segments"); socks_address = internal_type("SOCKS::Address")->AsRecordType(); diff --git a/src/NetVar.h b/src/NetVar.h index bf2d9a5712..efadaaad6d 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -52,6 +52,7 @@ extern double tcp_reset_delay; extern int tcp_max_initial_window; extern int tcp_max_above_hole_without_any_acks; extern int tcp_excessive_data_without_further_acks; +extern int tcp_max_old_segments; extern RecordType* socks_address; diff --git a/src/Reassem.cc b/src/Reassem.cc index 8bf965427b..bf2ed5df02 100644 --- a/src/Reassem.cc +++ b/src/Reassem.cc @@ -34,12 +34,38 @@ uint64 Reassembler::total_size = 0; Reassembler::Reassembler(uint64 init_seq) { blocks = last_block = 0; + old_blocks = last_old_block = 0; + total_old_blocks = max_old_blocks = 0; trim_seq = last_reassem_seq = init_seq; } Reassembler::~Reassembler() { ClearBlocks(); + ClearOldBlocks(); + } + +void Reassembler::CheckOverlap(DataBlock *head, DataBlock *tail, + uint64 seq, uint64 len, const u_char* data) + { + if ( ! head || ! tail ) + return; + + if ( seq_between(seq, head->seq, tail->upper) ) + { + for ( DataBlock* b = head; b; b = b->next ) + { + if ( seq_between(seq, b->seq, b->upper) ) + { + uint64 overlap_start = seq; + uint64 overlap_offset = overlap_start - b->seq; + uint64 new_b_len = len; + uint64 b_len = b->upper - overlap_start; + uint64 overlap_len = min(new_b_len, b_len); + Overlap(&b->block[overlap_offset], data, overlap_len); + } + } + } } void Reassembler::NewBlock(double t, uint64 seq, uint64 len, const u_char* data) @@ -49,6 +75,9 @@ void Reassembler::NewBlock(double t, uint64 seq, uint64 len, const u_char* data) uint64 upper_seq = seq + len; + CheckOverlap( blocks, last_block, seq, len, data ); + CheckOverlap( old_blocks, last_old_block, seq, len, data ); + if ( upper_seq <= trim_seq ) // Old data, don't do any work for it. return; @@ -119,7 +148,33 @@ uint64 Reassembler::TrimToSeq(uint64 seq) num_missing += seq - blocks->upper; } - delete blocks; + if (max_old_blocks) + { + blocks->next = 0; + if (last_old_block) + { + blocks->prev = last_old_block; + last_old_block->next = blocks; + } + else + { + blocks->prev = 0; + old_blocks = blocks; + } + + last_old_block = blocks; + total_old_blocks++; + + while (old_blocks && total_old_blocks > max_old_blocks) + { + DataBlock* next = old_blocks->next; + delete old_blocks; + old_blocks = next; + total_old_blocks--; + } + } + else + delete blocks; blocks = b; } @@ -156,6 +211,19 @@ void Reassembler::ClearBlocks() last_block = 0; } +void Reassembler::ClearOldBlocks() + { + while ( old_blocks ) + { + DataBlock* b = old_blocks->next; + delete old_blocks; + old_blocks = b; + } + + last_old_block = 0; + } + + uint64 Reassembler::TotalSize() const { uint64 size = 0; diff --git a/src/Reassem.h b/src/Reassem.h index 39617f7816..e55c809990 100644 --- a/src/Reassem.h +++ b/src/Reassem.h @@ -36,6 +36,7 @@ public: // Delete all held blocks. void ClearBlocks(); + void ClearOldBlocks(); int HasBlocks() const { return blocks != 0; } uint64 LastReassemSeq() const { return last_reassem_seq; } @@ -50,6 +51,8 @@ public: // Sum over all data buffered in some reassembler. static uint64 TotalMemoryAllocation() { return total_size; } + void SetMaxOldBlocks(uint32 count) { max_old_blocks = count; } + protected: Reassembler() { } @@ -65,10 +68,19 @@ protected: DataBlock* AddAndCheck(DataBlock* b, uint64 seq, uint64 upper, const u_char* data); + void CheckOverlap(DataBlock *head, DataBlock *tail, + uint64 seq, uint64 len, const u_char* data); + DataBlock* blocks; DataBlock* last_block; + + DataBlock* old_blocks; + DataBlock* last_old_block; + uint64 last_reassem_seq; uint64 trim_seq; // how far we've trimmed + uint32 max_old_blocks; + uint32 total_old_blocks; static uint64 total_size; }; diff --git a/src/analyzer/protocol/tcp/TCP_Reassembler.cc b/src/analyzer/protocol/tcp/TCP_Reassembler.cc index 16bb9cc56d..bbcd9cb43a 100644 --- a/src/analyzer/protocol/tcp/TCP_Reassembler.cc +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.cc @@ -42,6 +42,9 @@ TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer, seq_to_skip = 0; in_delivery = false; + if ( tcp_max_old_segments ) + SetMaxOldBlocks(tcp_max_old_segments); + if ( tcp_contents ) { // Val dst_port_val(ntohs(Conn()->RespPort()), TYPE_PORT); From 2aa214d8358fe583bd56920545e2057565ab6500 Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Thu, 28 May 2015 12:12:22 +0200 Subject: [PATCH 04/26] BIT-1314: Added QI test for rexmit_inconsistency --- .../Baseline/core.tcp.quantum-insert/.stdout | 4 ++++ .../tcp/qi_internet_SYNACK_curl_jsonip.pcap | Bin 0 -> 1718 bytes testing/btest/core/tcp/quantum-insert.bro | 12 ++++++++++++ 3 files changed, 16 insertions(+) create mode 100644 testing/btest/Baseline/core.tcp.quantum-insert/.stdout create mode 100644 testing/btest/Traces/tcp/qi_internet_SYNACK_curl_jsonip.pcap create mode 100644 testing/btest/core/tcp/quantum-insert.bro diff --git a/testing/btest/Baseline/core.tcp.quantum-insert/.stdout b/testing/btest/Baseline/core.tcp.quantum-insert/.stdout new file mode 100644 index 0000000000..3f2c5fad1b --- /dev/null +++ b/testing/btest/Baseline/core.tcp.quantum-insert/.stdout @@ -0,0 +1,4 @@ +----- rexmit_inconsistency ----- +1429652006.683290 c: [orig_h=178.200.100.200, orig_p=39976/tcp, resp_h=96.126.98.124, resp_p=80/tcp] +1429652006.683290 t1: HTTP/1.1 200 OK\x0d\x0aContent-Length: 5\x0d\x0a\x0d\x0aBANG! +1429652006.683290 t2: HTTP/1.1 200 OK\x0d\x0aServer: nginx/1.4.4\x0d\x0aDate: diff --git a/testing/btest/Traces/tcp/qi_internet_SYNACK_curl_jsonip.pcap b/testing/btest/Traces/tcp/qi_internet_SYNACK_curl_jsonip.pcap new file mode 100644 index 0000000000000000000000000000000000000000..d906d9cac9dbccaface027bfe7feeeff22f9c742 GIT binary patch literal 1718 zcmah}O>7fK6rOc{u%}%JsA{7Us=-1KPZKP1q&)yPi}s2Xf`pI|qLq3Jszh&Xih7B9=mGkkS9a_*q$@pn)^GNE z-+SLT^Xr4Viy_iU>d&i-gb47mdwF>F$3lc0gEa=}S$P!;lg)46sfNR3jF9xw_i2*u zzH#O5qx_>!FU-wf>nE8#sdFp1xf)87WrL7VXV*`H&>0dsI*1^I>5JsR1m+R_=J^OY z0&5H(*RN4SKL7>DaQDeLB4Y)Txz>N_>!nLj;n~e?pRulYeDuyxnC`lvI*1HaHX-sq z-$uwNfMT@qR;OI#z3pLu_cK7hywH;-96qXZMPx+$?rDTzW3}djlX#Lb5OGWLwTQiG z^2w7{#PP8#Q`kf{n^EF&T%@xucchU5H$9Ez%1%j1$_Z7Dv3?_w8kWlDDbqS*N|w#d zIX6Ef5A9_oW3GAQG^A!`jsjXt9@NWc``p;e54EE8k~y^-p^^-DmO%P32xmyxG`5K?c94aQ<@dQzl^ zEYpMLq@&y{ctwp3VXe`TW8*uq;QPIF1GRp>jkEpcYU^z0%b-?uVQZS?_qWa#5%(T! zLaaHq$yw^!c63%{M|%tN<%J%y`a{M?1nsY*s}OPdcoSk!f7Od1$G?;}alAL#;CL9P zTI>2WCD&n?7=bYp;p$o+a`cv7%dwZNI(@Ai+eSXaoeFm}W)=+dbC6$^Rgr$Adt77L zG9O@xIGfTPP$)jc;;NQNYU(f>pUSR_l|5_2X5F?+Mo#w(%T&-f`&q82J1+M=EPE%U zlt{CVZn`JHzhh?3${S_@EL;T3@_Y@-2xH z=oZH+Nh76_bw-+Y3}^uy`iA@z_lj2D)fgNqw3V6^>A9$3N401?nUcYRavTDFqXSWW z&MJG5QT)X~G~-x1;l1d2wx%cr?yVn==y{RG>WAXtmz2PjRExG7rGIuD^`|d``WG)e z-<^T0b@B?Tjt?sD-f8kuyE}K(+_}9~`TNiJq~+W3nZ6kJv{zZ0u zlL2;>2D`6(Za%v|U()qEKgce<_Cbx^<^a3jkzEze&aUGPc8`JGVL|AkkSk*zdw=)6 Rw>Fq#bQGB$?D&7C{{eG_ Date: Fri, 22 May 2015 16:43:03 -0400 Subject: [PATCH 05/26] Refactor to make bro use a common Packet object. Do a better job of parsing layer 2 and keeping track of layer 3 proto. Add support for raw packet event, including Layer2 headers. --- aux/plugins | 2 +- scripts/base/init-bare.bro | 27 +++ src/CMakeLists.txt | 1 + src/Conn.cc | 8 +- src/Conn.h | 4 +- src/IP.cc | 31 ++- src/IP.h | 7 +- src/L2.cc | 104 +++++++++ src/L2.h | 38 +++ src/Net.cc | 17 +- src/Net.h | 7 +- src/Packet.h | 88 +++++++ src/RemoteSerializer.cc | 8 +- src/Serializer.cc | 61 ++--- src/Serializer.h | 58 ----- src/Sessions.cc | 220 ++++++++---------- src/Sessions.h | 30 +-- src/analyzer/protocol/arp/ARP.cc | 24 +- src/analyzer/protocol/arp/ARP.h | 6 +- src/bro.bif | 67 +++--- src/event.bif | 19 +- src/iosource/PktDumper.h | 16 +- src/iosource/PktSrc.cc | 138 +++++++---- src/iosource/PktSrc.h | 32 +-- src/iosource/pcap/Dumper.cc | 5 +- src/iosource/pcap/Source.cc | 5 +- src/types.bif | 12 + testing/btest/Baseline/core.raw_packet/output | 48 ++++ testing/btest/Traces/icmp_dot1q.trace | Bin 0 -> 1710 bytes testing/btest/Traces/raw_packets.trace | Bin 0 -> 6641 bytes testing/btest/core/raw_packet.bro | 9 + .../btest/plugins/pktdumper-plugin/src/Foo.cc | 4 +- .../btest/plugins/pktsrc-plugin/src/Foo.cc | 9 +- testing/btest/plugins/pktsrc-plugin/src/Foo.h | 1 - 34 files changed, 677 insertions(+), 429 deletions(-) create mode 100644 src/L2.cc create mode 100644 src/L2.h create mode 100644 src/Packet.h create mode 100644 testing/btest/Baseline/core.raw_packet/output create mode 100644 testing/btest/Traces/icmp_dot1q.trace create mode 100644 testing/btest/Traces/raw_packets.trace create mode 100644 testing/btest/core/raw_packet.bro diff --git a/aux/plugins b/aux/plugins index 475beed1e9..b6359657a7 160000 --- a/aux/plugins +++ b/aux/plugins @@ -1 +1 @@ -Subproject commit 475beed1e9688f572ee60c196e07c0fa72e1ed9f +Subproject commit b6359657a7ad053c6bb4de392d8c17cdd80b88b6 diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 23f4fd43dd..49df5d12be 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -740,6 +740,7 @@ type pcap_packet: record { caplen: count; ##< The number of bytes captured (<= *len*). len: count; ##< The length of the packet in bytes, including link-level header. data: string; ##< The payload of the packet, including link-level header. + link_type: link_encap; ##< L2 link encapsulation type }; ## GeoIP location information. @@ -1495,6 +1496,32 @@ type pkt_hdr: record { icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet. }; +## Values extracted from the layer 2 header. +## +## .. bro:see:: pkt_hdr +type l2_hdr: record { + encap: link_encap; ##< L2 link encapsulation + len: count; ##< Total frame length on wire + cap_len: count; ##< Captured length + src: string &optional; ##< L2 source (if ethernet) + dst: string &optional; ##< L2 destination (if ethernet) + vlan: count &optional; ##< Outermost VLAN tag if any (and ethernet) + eth_type: count &optional; ##< Innermost Ethertype (if ethernet) + proto: layer3_proto; ##< L3 proto +}; + +## A raw packet header, consisting of L2 header and everything in pkt_hdr above. +## +## .. bro:see:: raw_packet pkt_hdr +type raw_pkt_hdr: record { + l2: l2_hdr; ##< Layer 3 and above header + 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. +}; + ## A Teredo origin indication header. See :rfc:`4380` for more information ## about the Teredo protocol. ## diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bdbd3839ce..59b9f8d1b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -297,6 +297,7 @@ set(bro_SRCS IntSet.cc IP.cc IPAddr.cc + L2.cc List.cc Reporter.cc NFA.cc diff --git a/src/Conn.cc b/src/Conn.cc index 96e71ca52d..5c1a58a7b1 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -241,12 +241,8 @@ void Connection::NextPacket(double t, int is_orig, const u_char*& data, int& record_packet, int& record_content, // arguments for reproducing packets - const struct pcap_pkthdr* hdr, - const u_char* const pkt, - int hdr_size) + const Packet *pkt) { - current_hdr = hdr; - current_hdr_size = hdr_size; current_timestamp = t; current_pkt = pkt; @@ -264,8 +260,6 @@ void Connection::NextPacket(double t, int is_orig, else last_time = t; - current_hdr = 0; - current_hdr_size = 0; current_timestamp = 0; current_pkt = 0; } diff --git a/src/Conn.h b/src/Conn.h index 20e60d2617..62a1aa9613 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -86,9 +86,7 @@ public: const u_char*& data, int& record_packet, int& record_content, // arguments for reproducing packets - const struct pcap_pkthdr* hdr, - const u_char* const pkt, - int hdr_size); + const Packet *pkt); HashKey* Key() const { return key; } void ClearKey() { key = 0; } diff --git a/src/IP.cc b/src/IP.cc index 783c08da39..97db1bb93d 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -325,26 +325,33 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const } 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(); + } + RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); + return BuildPktHdrVal(pkt_hdr, 0); +} + +RecordVal* IP_Hdr::BuildPktHdrVal(RecordVal* pkt_hdr, int sindex) const + { + static RecordType* tcp_hdr_type = 0; + static RecordType* udp_hdr_type = 0; + static RecordType* icmp_hdr_type = 0; + + if ( ! tcp_hdr_type ) + { 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()); + pkt_hdr->Assign(sindex + 0, BuildIPHdrVal()); else - pkt_hdr->Assign(1, BuildIPHdrVal()); + pkt_hdr->Assign(sindex + 1, BuildIPHdrVal()); // L4 header. const u_char* data = Payload(); @@ -368,7 +375,7 @@ RecordVal* IP_Hdr::BuildPktHdrVal() const 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); + pkt_hdr->Assign(sindex + 2, tcp_hdr); break; } @@ -381,7 +388,7 @@ RecordVal* IP_Hdr::BuildPktHdrVal() const 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); + pkt_hdr->Assign(sindex + 3, udp_hdr); break; } @@ -392,7 +399,7 @@ RecordVal* IP_Hdr::BuildPktHdrVal() const icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); - pkt_hdr->Assign(4, icmp_hdr); + pkt_hdr->Assign(sindex + 4, icmp_hdr); break; } diff --git a/src/IP.h b/src/IP.h index b91c9130e4..bfd3ce8a41 100644 --- a/src/IP.h +++ b/src/IP.h @@ -574,8 +574,13 @@ public: */ RecordVal* BuildPktHdrVal() const; -private: + /** + * Same as above, but simply add our values into the record at the + * specified starting index. + */ + RecordVal* BuildPktHdrVal(RecordVal* pkt_hdr, int sindex) const; +private: const struct ip* ip4; const struct ip6_hdr* ip6; bool del; diff --git a/src/L2.cc b/src/L2.cc new file mode 100644 index 0000000000..9b277e9e9e --- /dev/null +++ b/src/L2.cc @@ -0,0 +1,104 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "L2.h" +#include "IP.h" +#include "Type.h" +#include "Val.h" +#include "Var.h" +#include "NetVar.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NET_ETHERNET_H +#include +#elif defined(HAVE_SYS_ETHERNET_H) +#include +#elif defined(HAVE_NETINET_IF_ETHER_H) +#include +#elif defined(HAVE_NET_ETHERTYPES_H) +#include +#endif +} + + +Val *L2_Hdr::fmt_eui48(const u_char *mac) const + { + char buf[20]; + snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return new StringVal(buf); + } + +RecordVal* L2_Hdr::BuildPktHdrVal() const + { + static RecordType* l2_hdr_type = 0; + static RecordType* raw_pkt_hdr_type = 0; + + if ( ! raw_pkt_hdr_type ) + { + raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType(); + l2_hdr_type = internal_type("l2_hdr")->AsRecordType(); + } + + RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type); + RecordVal* l2_hdr = new RecordVal(l2_hdr_type); + int is_ethernet = ( pkt->link_type == DLT_EN10MB ) ? 1 : 0; + int l3 = BifEnum::layer3_proto::l3_unknown; + if ( pkt->l3_proto == AF_INET ) + l3 = BifEnum::layer3_proto::l3_ipv4; + else if ( pkt->l3_proto == AF_INET6 ) + l3 = BifEnum::layer3_proto::l3_ipv6; + + // l2_hdr layout: + // encap: link_encap; ##< L2 link encapsulation + // len: count; ##< Total frame length on wire + // cap_len: count; ##< Captured length + // src: string &optional; ##< L2 source (if ethernet) + // dst: string &optional; ##< L2 destination (if ethernet) + // vlan: count &optional; ##< VLAN tag if any (and ethernet) + // ethertype: count &optional; ##< If ethernet + // proto: layer3_proto; ##< L3 proto + if ( is_ethernet ) + { + // Ethernet header layout is: + // dst[6bytes] src[6bytes] ethertype[2bytes]... + l2_hdr->Assign(0, new EnumVal(BifEnum::link_encap::link_ethernet, BifType::Enum::link_encap)); + l2_hdr->Assign(3, fmt_eui48(pkt->data + 6)); // src + l2_hdr->Assign(4, fmt_eui48(pkt->data)); // dst + if ( pkt->vlan ) + l2_hdr->Assign(5, new Val(pkt->vlan, TYPE_COUNT)); + l2_hdr->Assign(6, new Val(pkt->eth_type, TYPE_COUNT)); + if ( pkt->eth_type == ETHERTYPE_ARP || pkt->eth_type == ETHERTYPE_REVARP ) + { + // We also identify ARP for L3 over ethernet + l3 = BifEnum::layer3_proto::l3_arp; + } + } + else + { + l2_hdr->Assign(0, new EnumVal(BifEnum::link_encap::link_unknown, BifType::Enum::link_encap)); + } + l2_hdr->Assign(1, new Val(pkt->len, TYPE_COUNT)); + l2_hdr->Assign(2, new Val(pkt->cap_len, TYPE_COUNT)); + l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto)); + pkt_hdr->Assign(0, l2_hdr); + + if ( pkt->l3_proto == AF_INET ) + { + IP_Hdr ip_hdr((const struct ip*)(pkt->data + pkt->hdr_size), false); + return ip_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + else if ( pkt->l3_proto == AF_INET6 ) + { + IP_Hdr ip6_hdr((const struct ip6_hdr*)(pkt->data + pkt->hdr_size), false, pkt->cap_len); + return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + else + return pkt_hdr; + } + diff --git a/src/L2.h b/src/L2.h new file mode 100644 index 0000000000..588e9fb445 --- /dev/null +++ b/src/L2.h @@ -0,0 +1,38 @@ +#ifndef l2_h +#define l2_h + +#include "config.h" +#include "net_util.h" +#include "IP.h" +#include "Reporter.h" +#include "Val.h" +#include "Type.h" +#include "Packet.h" +#include + +/** + * A class that wraps an L2 packet. + */ +class L2_Hdr { +public: + L2_Hdr(const Packet *arg_pkt) + : pkt(arg_pkt) + { + } + + ~L2_Hdr() + { + } + + /** + * Returns a raw_pkt_hdr RecordVal, which includes L2 and also + * everything in IP_Hdr (i.e. IP4/6 + tcp/udp/icmp) + */ + RecordVal* BuildPktHdrVal() const; + +private: + Val *fmt_eui48(const u_char *mac) const; + const Packet *pkt; +}; + +#endif diff --git a/src/Net.cc b/src/Net.cc index af542cb1a6..4237b9f54d 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -62,10 +62,8 @@ double bro_start_network_time; // timestamp of first packet double last_watchdog_proc_time = 0.0; // value of above during last watchdog bool terminating = false; // whether we're done reading and finishing up -const struct pcap_pkthdr* current_hdr = 0; -const u_char* current_pkt = 0; +const Packet *current_pkt = 0; int current_dispatched = 0; -int current_hdr_size = 0; double current_timestamp = 0.0; iosource::PktSrc* current_pktsrc = 0; iosource::IOSource* current_iosrc = 0; @@ -109,7 +107,7 @@ RETSIGTYPE watchdog(int /* signo */) int frac_pst = int((processing_start_time - int_pst) * 1e6); - if ( current_hdr ) + if ( current_pkt ) { if ( ! pkt_dumper ) { @@ -127,10 +125,7 @@ RETSIGTYPE watchdog(int /* signo */) if ( pkt_dumper ) { - iosource::PktDumper::Packet p; - p.hdr = current_hdr; - p.data = current_pkt; - pkt_dumper->Dump(&p); + pkt_dumper->Dump(current_pkt); } } @@ -240,9 +235,7 @@ void expire_timers(iosource::PktSrc* src_ps) max_timer_expires - current_dispatched); } -void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr, - const u_char* pkt, int hdr_size, - iosource::PktSrc* src_ps) +void net_packet_dispatch(double t, const Packet* pkt, iosource::PktSrc* src_ps) { if ( ! bro_start_network_time ) bro_start_network_time = t; @@ -278,7 +271,7 @@ void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr, } } - sessions->DispatchPacket(t, hdr, pkt, hdr_size, src_ps); + sessions->DispatchPacket(t, pkt, src_ps); mgr.Drain(); if ( sp ) diff --git a/src/Net.h b/src/Net.h index 2e466f8c7f..d19bd9083c 100644 --- a/src/Net.h +++ b/src/Net.h @@ -19,8 +19,7 @@ extern void net_get_final_stats(); extern void net_finish(int drain_events); extern void net_delete(); // Reclaim all memory, etc. extern void net_update_time(double new_network_time); -extern void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr, - const u_char* pkt, int hdr_size, +extern void net_packet_dispatch(double t, const Packet* pkt, iosource::PktSrc* src_ps); extern void expire_timers(iosource::PktSrc* src_ps = 0); extern void termination_signal(); @@ -74,10 +73,8 @@ extern bool using_communication; // Snaplen passed to libpcap. extern int snaplen; -extern const struct pcap_pkthdr* current_hdr; -extern const u_char* current_pkt; +extern const Packet* current_pkt; extern int current_dispatched; -extern int current_hdr_size; extern double current_timestamp; extern iosource::PktSrc* current_pktsrc; extern iosource::IOSource* current_iosrc; diff --git a/src/Packet.h b/src/Packet.h new file mode 100644 index 0000000000..05c826ec5f --- /dev/null +++ b/src/Packet.h @@ -0,0 +1,88 @@ +#ifndef packet_h +#define packet_h + +#include "Desc.h" +#include "IP.h" + +// A link-layer packet. +// +// Note that for serialization we don't use much of the support provided by +// the serialization framework. Serialize/Unserialize do all the work by +// themselves. In particular, Packets aren't derived from SerialObj. They are +// completely seperate and self-contained entities, and we don't need any of +// the sophisticated features like object caching. + +class Packet { +public: + Packet() + { + } + // Construct and initialize from packet data. + Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, + uint32 arg_len, const u_char *arg_data, int arg_free = false, + std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, + int arg_l3_proto = -1) + { + Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag, + arg_hdrsize, arg_l3_proto); + } + + ~Packet() + { + if ( free ) + delete [] data; + } + + // Initialize with data from pointer + void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, + uint32 arg_len, const u_char *arg_data, int arg_free = false, + std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, + int arg_l3_proto = -1) + { + link_type = arg_link_type; + ts = *arg_ts; + cap_len = arg_caplen; + len = arg_len; + free = arg_free; + if ( free ) + { + data = new u_char [cap_len]; + memcpy(const_cast(data), arg_data, cap_len); + } + else + data = arg_data; + hdr_size = arg_hdrsize; + l3_proto = arg_l3_proto; + tag = arg_tag; + time = ts.tv_sec + double(ts.tv_usec) / 1e6; + eth_type = 0; + vlan = 0; + } + + const IP_Hdr IP() const + { return IP_Hdr((struct ip *) (data + hdr_size), true); } + + void Describe(ODesc* d) const; + + bool Serialize(SerialInfo* info) const; + static Packet* Unserialize(UnserialInfo* info); + + std::string tag; // Used in serialization + double time; // Timestamp reconstituted as float + + struct timeval ts; // Capture timestamp + const u_char* data; // Packet data. + uint32 link_type; // pcap link_type (DLT_EN10MB, DLT_RAW, etc) + uint32 cap_len; // Captured packet length + uint32 len; // Actual length on wire + uint32 hdr_size; // Layer 2 header size + uint32 l3_proto; // Layer 3 protocol identified (if any) + uint32 eth_type; // If L2==ethernet, innermost ethertype field + uint32 vlan; // (Outermost) VLan tag if any, else 0 + +private: + // should we delete associated packet memory upon destruction. + bool free; +}; + +#endif // packet_h diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index d359c1ea5d..44ec678a0f 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -1453,7 +1453,7 @@ void RemoteSerializer::Process() if ( packets.length() ) { BufferedPacket* bp = packets[0]; - Packet* p = bp->p; + const Packet* p = bp->p; // FIXME: The following chunk of code is copied from // net_packet_dispatch(). We should change that function @@ -1465,14 +1465,12 @@ void RemoteSerializer::Process() current_dispatched = tmgr->Advance(network_time, max_timer_expires); - current_hdr = p->hdr; - current_pkt = p->pkt; + current_pkt = p; current_pktsrc = 0; current_iosrc = this; - sessions->NextPacket(p->time, p->hdr, p->pkt, p->hdr_size); + sessions->NextPacket(p->time, p); mgr.Drain(); - current_hdr = 0; // done with these current_pkt = 0; current_iosrc = 0; diff --git a/src/Serializer.cc b/src/Serializer.cc index 7306b0ded0..54266de1d0 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1133,12 +1133,14 @@ void Packet::Describe(ODesc* d) const bool Packet::Serialize(SerialInfo* info) const { - return SERIALIZE(uint32(hdr->ts.tv_sec)) && - SERIALIZE(uint32(hdr->ts.tv_usec)) && - SERIALIZE(uint32(hdr->len)) && - SERIALIZE(link_type) && - info->s->Write(tag.c_str(), 0, "tag") && - info->s->Write((const char*) pkt, hdr->caplen, "data"); + return SERIALIZE(uint32(ts.tv_sec)) && + SERIALIZE(uint32(ts.tv_usec)) && + SERIALIZE(uint32(len)) && + SERIALIZE(uint32(link_type)) && + SERIALIZE(uint32(hdr_size)) && + SERIALIZE(uint32(l3_proto)) && + info->s->Write(tag.c_str(), tag.length(), "tag") && + info->s->Write((const char*)data, cap_len, "data"); } static BroFile* profiling_output = 0; @@ -1149,49 +1151,31 @@ static iosource::PktDumper* dump = 0; Packet* Packet::Unserialize(UnserialInfo* info) { - Packet* p = new Packet("", true); - pcap_pkthdr* hdr = new pcap_pkthdr; + struct timeval ts; + uint32 len, link_type, hdr_size, l3_proto; - uint32 tv_sec, tv_usec, len; - - if ( ! (UNSERIALIZE(&tv_sec) && - UNSERIALIZE(&tv_usec) && + if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) && + UNSERIALIZE((uint32 *)&ts.tv_usec) && UNSERIALIZE(&len) && - UNSERIALIZE(&p->link_type)) ) - { - delete p; - delete hdr; + UNSERIALIZE(&link_type) && + UNSERIALIZE(&hdr_size) && + UNSERIALIZE(&l3_proto)) ) return 0; - } - - hdr->ts.tv_sec = tv_sec; - hdr->ts.tv_usec = tv_usec; - hdr->len = len; char* tag; if ( ! info->s->Read((char**) &tag, 0, "tag") ) - { - delete p; - delete hdr; return 0; - } - char* pkt; + const u_char* pkt; int caplen; if ( ! info->s->Read((char**) &pkt, &caplen, "data") ) { - delete p; - delete hdr; delete [] tag; return 0; } - hdr->caplen = uint32(caplen); - p->hdr = hdr; - p->pkt = (u_char*) pkt; - p->tag = tag; - p->hdr_size = iosource::PktSrc::GetLinkHeaderSize(p->link_type); - + Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, + std::string(tag), hdr_size, l3_proto); delete [] tag; // For the global timer manager, we take the global network_time as the @@ -1199,7 +1183,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) if ( p->tag == "" ) p->time = timer_mgr->Time(); else - p->time = p->hdr->ts.tv_sec + double(p->hdr->ts.tv_usec) / 1e6; + p->time = p->ts.tv_sec + double(p->ts.tv_usec) / 1e6; if ( time_machine_profiling ) { @@ -1208,7 +1192,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) new BroFile("tm-prof.packets.log", "w"); profiling_output->Write(fmt("%.6f %s %d\n", current_time(), - (p->tag != "" ? p->tag.c_str() : "-"), hdr->len)); + (p->tag != "" ? p->tag.c_str() : "-"), p->len)); } #ifdef DEBUG @@ -1219,10 +1203,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) if ( dump ) { - iosource::PktDumper::Packet dp; - dp.hdr = p->hdr; - dp.data = p->pkt; - dump->Dump(&dp); + dump->Dump(p); } } #endif diff --git a/src/Serializer.h b/src/Serializer.h index 558dce2086..43a9943cc5 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -378,64 +378,6 @@ protected: }; - -// A link-layer packet. -// -// Eventually we should use something like this consistently throughout Bro, -// replacing the current packet arguments in functions like *::NextPacket(). -// Before doing this, though, we should consider provisioning for packet -// formats other than just libpcap by designing a more abstract interface. -// -// Note that for serialization we don't use much of the support provided by -// the serialization framework. Serialize/Unserialize do all the work by -// themselves. In particular, Packets aren't derived from SerialObj. They are -// completely seperate and self-contained entities, and we don't need any of -// the sophisticated features like object caching. - -class Packet { -public: - // Argument is whether we should delete associatd memory upon - // destruction. - Packet(TimerMgr::Tag arg_tag, bool arg_free = false) - { - time = 0.0; - hdr = 0; - pkt = 0; - hdr_size = 0; - free = arg_free; - tag = arg_tag; - link_type = 0; - } - - ~Packet() - { - if ( free ) - { - delete hdr; - delete [] pkt; - } - } - - const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (pkt + hdr_size), true); } - - void Describe(ODesc* d) const; - - bool Serialize(SerialInfo* info) const; - static Packet* Unserialize(UnserialInfo* info); - - const struct pcap_pkthdr* hdr; - const u_char* pkt; - TimerMgr::Tag tag; - uint32 link_type; - - double time; - int hdr_size; - -private: - bool free; -}; - extern FileSerializer* event_serializer; extern FileSerializer* state_serializer; diff --git a/src/Sessions.cc b/src/Sessions.cc index 086216e93d..e1c9e29c16 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -15,6 +15,7 @@ #include "Sessions.h" #include "Reporter.h" #include "OSFinger.h" +#include "L2.h" #include "analyzer/protocol/icmp/ICMP.h" #include "analyzer/protocol/udp/UDP.h" @@ -165,98 +166,85 @@ void NetSessions::Done() { } -void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* pkt, int hdr_size, +void NetSessions::DispatchPacket(double t, const Packet* pkt, iosource::PktSrc* src_ps) { - const struct ip* ip_hdr = 0; - const u_char* ip_data = 0; - int proto = 0; - - if ( hdr->caplen >= hdr_size + sizeof(struct ip) ) - { - ip_hdr = reinterpret_cast(pkt + hdr_size); - if ( hdr->caplen >= unsigned(hdr_size + (ip_hdr->ip_hl << 2)) ) - ip_data = pkt + hdr_size + (ip_hdr->ip_hl << 2); - } - - if ( encap_hdr_size > 0 && ip_data ) - // Blanket encapsulation - hdr_size += encap_hdr_size; - - NextPacket(t, hdr, pkt, hdr_size); + NextPacket(t, pkt); } -void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* const pkt, int hdr_size) +void NetSessions::NextPacket(double t, const Packet* pkt) + { + ProcNextPacket(t, pkt); + if ( raw_packet ) + { + val_list* vl = new val_list(); + L2_Hdr l2_hdr(pkt); + vl->append(l2_hdr.BuildPktHdrVal()); + mgr.QueueEvent(raw_packet, vl); + } + } + +void NetSessions::ProcNextPacket(double t, const Packet *pkt) { SegmentProfiler(segment_logger, "processing-packet"); if ( pkt_profiler ) - pkt_profiler->ProfilePkt(t, hdr->caplen); + pkt_profiler->ProfilePkt(t, pkt->cap_len); ++num_packets_processed; dump_this_packet = 0; if ( record_all_packets ) - DumpPacket(hdr, pkt); + DumpPacket(pkt); - // ### The following isn't really correct. What we *should* - // do is understanding the different link layers in order to - // find the network-layer protocol ID. That's a big - // portability pain, though, unless we just assume everything's - // Ethernet .... not great, given the potential need to deal - // with PPP or FDDI (for some older traces). So instead - // we look to see if what we have is consistent with an - // IPv4 packet. If not, it's either ARP or IPv6 or weird. - - if ( hdr_size > static_cast(hdr->caplen) ) + if ( pkt->hdr_size > pkt->cap_len ) { - Weird("truncated_link_frame", hdr, pkt); + Weird("truncated_link_frame", pkt); return; } - uint32 caplen = hdr->caplen - hdr_size; - if ( caplen < sizeof(struct ip) ) - { - Weird("truncated_IP", hdr, pkt); - return; - } + uint32 caplen = pkt->cap_len - pkt->hdr_size; - const struct ip* ip = (const struct ip*) (pkt + hdr_size); - - if ( ip->ip_v == 4 ) + if ( pkt->l3_proto == AF_INET ) { - IP_Hdr ip_hdr(ip, false); - DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0); - } - - else if ( ip->ip_v == 6 ) - { - if ( caplen < sizeof(struct ip6_hdr) ) + if ( caplen < sizeof(struct ip) ) { - Weird("truncated_IP", hdr, pkt); + Weird("truncated_IP", pkt); return; } - IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen); - DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0); + const struct ip* ip = (const struct ip*) (pkt->data + pkt->hdr_size); + IP_Hdr ip_hdr(ip, false); + DoNextPacket(t, pkt, &ip_hdr, 0); } - else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt, hdr_size) ) + else if ( pkt->l3_proto == AF_INET6 ) + { + if ( caplen < sizeof(struct ip6_hdr) ) + { + Weird("truncated_IP", pkt); + return; + } + + IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt->data + pkt->hdr_size), false, caplen); + DoNextPacket(t, pkt, &ip_hdr, 0); + } + + else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt) ) { if ( arp_analyzer ) - arp_analyzer->NextPacket(t, hdr, pkt, hdr_size); + arp_analyzer->NextPacket(t, pkt); } else { - Weird("unknown_packet_type", hdr, pkt); + Weird("unknown_packet_type", pkt); return; } + if ( dump_this_packet && ! record_all_packets ) - DumpPacket(hdr, pkt); + DumpPacket(pkt); } int NetSessions::CheckConnectionTag(Connection* conn) @@ -337,26 +325,25 @@ static unsigned int gre_header_len(uint16 flags) return len; } -void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, - const IP_Hdr* ip_hdr, const u_char* const pkt, - int hdr_size, const EncapsulationStack* encapsulation) +void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr, + const EncapsulationStack* encapsulation) { - uint32 caplen = hdr->caplen - hdr_size; + uint32 caplen = pkt->cap_len - pkt->hdr_size; const struct ip* ip4 = ip_hdr->IP4_Hdr(); uint32 len = ip_hdr->TotalLen(); if ( len == 0 ) { // TCP segmentation offloading can zero out the ip_len field. - Weird("ip_hdr_len_zero", hdr, pkt, encapsulation); + Weird("ip_hdr_len_zero", pkt, encapsulation); // Cope with the zero'd out ip_len field by using the caplen. - len = hdr->caplen - hdr_size; + len = pkt->cap_len - pkt->hdr_size; } - if ( hdr->len < len + hdr_size ) + if ( pkt->len < len + pkt->hdr_size ) { - Weird("truncated_IP", hdr, pkt, encapsulation); + Weird("truncated_IP", pkt, encapsulation); return; } @@ -368,7 +355,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( ! ignore_checksums && ip4 && ones_complement_checksum((void*) ip4, ip_hdr_len, 0) != 0xffff ) { - Weird("bad_IP_checksum", hdr, pkt, encapsulation); + Weird("bad_IP_checksum", pkt, encapsulation); return; } @@ -393,7 +380,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } else { - f = NextFragment(t, ip_hdr, pkt + hdr_size); + f = NextFragment(t, ip_hdr, pkt->data + pkt->hdr_size); const IP_Hdr* ih = f->ReassembledPkt(); if ( ! ih ) // It didn't reassemble into anything yet. @@ -437,7 +424,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff ) { - Weird("bad_MH_checksum", hdr, pkt, encapsulation); + Weird("bad_MH_checksum", pkt, encapsulation); return; } @@ -449,7 +436,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } if ( ip_hdr->NextProto() != IPPROTO_NONE ) - Weird("mobility_piggyback", hdr, pkt, encapsulation); + Weird("mobility_piggyback", pkt, encapsulation); return; } @@ -457,7 +444,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, int proto = ip_hdr->NextProto(); - if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt, encapsulation) ) + if ( CheckHeaderTrunc(proto, len, caplen, pkt, encapsulation) ) return; const u_char* data = ip_hdr->Payload(); @@ -664,7 +651,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, else it->second.second = network_time; - DoNextInnerPacket(t, hdr, inner, encapsulation, + DoNextInnerPacket(t, pkt, inner, encapsulation, ip_tunnels[tunnel_idx].first); return; @@ -677,13 +664,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // not sure the reason for the No Next header in the packet. if ( ! ( encapsulation && encapsulation->LastType() == BifEnum::Tunnel::TEREDO ) ) - Weird("ipv6_no_next", hdr, pkt); + Weird("ipv6_no_next", pkt); return; } default: - Weird(fmt("unknown_protocol_%d", proto), hdr, pkt, encapsulation); + Weird(fmt("unknown_protocol_%d", proto), pkt, encapsulation); return; } @@ -756,8 +743,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* 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, - hdr, pkt, hdr_size); + record_packet, record_content, pkt); if ( f ) { @@ -772,40 +758,52 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, else { - int hdr_len = data - pkt; - DumpPacket(hdr, pkt, hdr_len); // just save the header + int hdr_len = data - pkt->data; + DumpPacket(pkt, hdr_len); // just save the header } } } -void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, +void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, const IP_Hdr* inner, const EncapsulationStack* prev, const EncapsulatingConn& ec) { - struct pcap_pkthdr fake_hdr; - fake_hdr.caplen = fake_hdr.len = inner->TotalLen(); + uint32 caplen, len; + caplen = len = inner->TotalLen(); - if ( hdr ) - fake_hdr.ts = hdr->ts; + struct timeval ts; + int link_type, l3_proto; + + if ( pkt ) + ts = pkt->ts; else { - fake_hdr.ts.tv_sec = (time_t) network_time; - fake_hdr.ts.tv_usec = (suseconds_t) - ((network_time - (double)fake_hdr.ts.tv_sec) * 1000000); + ts.tv_sec = (time_t) network_time; + ts.tv_usec = (suseconds_t) + ((network_time - (double)ts.tv_sec) * 1000000); } - const u_char* pkt = 0; + const u_char* data = 0; if ( inner->IP4_Hdr() ) - pkt = (const u_char*) inner->IP4_Hdr(); + { + data = (const u_char*) inner->IP4_Hdr(); + l3_proto = AF_INET; + } else - pkt = (const u_char*) inner->IP6_Hdr(); + { + data = (const u_char*) inner->IP6_Hdr(); + l3_proto = AF_INET6; + } EncapsulationStack* outer = prev ? new EncapsulationStack(*prev) : new EncapsulationStack(); outer->Add(ec); - DoNextPacket(t, &fake_hdr, inner, pkt, 0, outer); + // Construct fake packet for DoNextPacket + Packet p; + p.Init(DLT_RAW, &ts, caplen, len, data, false, "", 0, l3_proto); + DoNextPacket(t, &p, inner, outer); delete inner; delete outer; @@ -843,8 +841,7 @@ int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto, } bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, - const struct pcap_pkthdr* h, - const u_char* p, const EncapsulationStack* encap) + const Packet* p, const EncapsulationStack* encap) { uint32 min_hdr_len = 0; switch ( proto ) { @@ -876,13 +873,13 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, if ( len < min_hdr_len ) { - Weird("truncated_header", h, p, encap); + Weird("truncated_header", p, encap); return true; } if ( caplen < min_hdr_len ) { - Weird("internally_truncated_header", h, p, encap); + Weird("internally_truncated_header", p, encap); return true; } @@ -1387,45 +1384,26 @@ void NetSessions::ExpireTimerMgrs() } } -void NetSessions::DumpPacket(const struct pcap_pkthdr* hdr, - const u_char* pkt, int len) +void NetSessions::DumpPacket(const Packet *pkt, int len) { if ( ! pkt_dumper ) return; - if ( len == 0 ) + if ( len != 0 ) { - iosource::PktDumper::Packet p; - p.hdr = hdr; - p.data = pkt; - pkt_dumper->Dump(&p); - } - - else - { - struct pcap_pkthdr h = *hdr; - h.caplen = len; - if ( h.caplen > hdr->caplen ) + if ( (uint32)len > pkt->cap_len ) reporter->InternalError("bad modified caplen"); - - iosource::PktDumper::Packet p; - p.hdr = &h; - p.data = pkt; - pkt_dumper->Dump(&p); + else + const_cast(pkt)->cap_len = len; } + + pkt_dumper->Dump(pkt); } -void NetSessions::Internal(const char* msg, const struct pcap_pkthdr* hdr, - const u_char* pkt) +void NetSessions::Weird(const char* name, const Packet* pkt, + const EncapsulationStack* encap) { - DumpPacket(hdr, pkt); - reporter->InternalError("%s", msg); - } - -void NetSessions::Weird(const char* name, const struct pcap_pkthdr* hdr, - const u_char* pkt, const EncapsulationStack* encap) - { - if ( hdr ) + if ( pkt ) dump_this_packet = 1; if ( encap && encap->LastType() != BifEnum::Tunnel::NONE ) diff --git a/src/Sessions.h b/src/Sessions.h index c46c092263..51539c42ef 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -15,8 +15,6 @@ #include -struct pcap_pkthdr; - class EncapsulationStack; class Connection; class OSFingerprint; @@ -71,8 +69,7 @@ public: // Main entry point for packet processing. Dispatches the packet // either through NextPacket(), optionally employing the packet // sorter first. - void DispatchPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* const pkt, int hdr_size, + void DispatchPacket(double t, const Packet* pkt, iosource::PktSrc* src_ps); void Done(); // call to drain events before destructing @@ -106,8 +103,8 @@ public: void GetStats(SessionStats& s) const; - void Weird(const char* name, const struct pcap_pkthdr* hdr, - const u_char* pkt, const EncapsulationStack* encap = 0); + void Weird(const char* name, const Packet* pkt, + const EncapsulationStack* encap = 0); void Weird(const char* name, const IP_Hdr* ip, const EncapsulationStack* encap = 0); @@ -133,9 +130,8 @@ public: icmp_conns.Length(); } - void DoNextPacket(double t, const struct pcap_pkthdr* hdr, - const IP_Hdr* ip_hdr, const u_char* const pkt, - int hdr_size, const EncapsulationStack* encapsulation); + void DoNextPacket(double t, const Packet *pkt, const IP_Hdr* ip_hdr, + const EncapsulationStack* encapsulation); /** * Wrapper that recurses on DoNextPacket for encapsulated IP packets. @@ -151,7 +147,7 @@ public: * the most-recently found depth of encapsulation. * @param ec The most-recently found depth of encapsulation. */ - void DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, + void DoNextInnerPacket(double t, const Packet *pkt, const IP_Hdr* inner, const EncapsulationStack* prev, const EncapsulatingConn& ec); @@ -218,24 +214,20 @@ protected: TransportProto transport_proto, uint8 tcp_flags, bool& flip_roles); - void NextPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* const pkt, int hdr_size); + void NextPacket(double t, const Packet* pkt); + + void ProcNextPacket(double t, const Packet *pkt); // Record the given packet (if a dumper is active). If len=0 // then the whole packet is recorded, otherwise just the first // len bytes. - void DumpPacket(const struct pcap_pkthdr* hdr, const u_char* pkt, - int len=0); - - void Internal(const char* msg, const struct pcap_pkthdr* hdr, - const u_char* pkt); + void DumpPacket(const Packet *pkt, int len=0); // 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, - const EncapsulationStack* encap); + const Packet *pkt, const EncapsulationStack* encap); CompositeHash* ch; PDict(Connection) tcp_conns; diff --git a/src/analyzer/protocol/arp/ARP.cc b/src/analyzer/protocol/arp/ARP.cc index b3ef5383ce..862bd742ee 100644 --- a/src/analyzer/protocol/arp/ARP.cc +++ b/src/analyzer/protocol/arp/ARP.cc @@ -19,10 +19,14 @@ ARP_Analyzer::~ARP_Analyzer() { } -bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) +// Assume pkt->hdr_size indicates size of the Layer 2 header. +bool ARP_Analyzer::IsARP(const Packet* pkt) { + if ( pkt->hdr_size < 2 ) + return false; + unsigned short network_protocol = - *(unsigned short*) (pkt + hdr_size - 2); + *(unsigned short*) (pkt->data + pkt->hdr_size - 2); switch ( ntohs(network_protocol) ) { case ETHERTYPE_ARP: @@ -93,16 +97,16 @@ bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) #endif -void ARP_Analyzer::NextPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* const pkt, int hdr_size) +void ARP_Analyzer::NextPacket(double t, const Packet* pkt) { + const u_char *data = pkt->data; // Check whether the packet is OK ("inspired" in tcpdump's print-arp.c). const struct arp_pkthdr* ah = - (const struct arp_pkthdr*) (pkt + hdr_size); + (const struct arp_pkthdr*) (data + pkt->hdr_size); // Check the size. - int min_length = (ar_tpa(ah) - (char*) (pkt + hdr_size)) + ah->ar_pln; - int real_length = hdr->caplen - hdr_size; + int min_length = (ar_tpa(ah) - (char*) (data + pkt->hdr_size)) + ah->ar_pln; + int real_length = pkt->cap_len - pkt->hdr_size; if ( min_length > real_length ) { Corrupted("truncated_ARP"); @@ -158,7 +162,7 @@ void ARP_Analyzer::NextPacket(double t, const struct pcap_pkthdr* hdr, // Check MAC src address = ARP sender MAC address. - if ( memcmp((const char*) (pkt+6), ar_sha(ah), ah->ar_hln) ) + if ( memcmp((const char*) (data+6), ar_sha(ah), ah->ar_hln) ) { BadARP(ah, "weird-arp-sha"); return; @@ -167,12 +171,12 @@ void ARP_Analyzer::NextPacket(double t, const struct pcap_pkthdr* hdr, // Check the code is supported. switch ( ntohs(ah->ar_op) ) { case ARPOP_REQUEST: - RREvent(arp_request, pkt+6, pkt, + RREvent(arp_request, data+6, data, ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); break; case ARPOP_REPLY: - RREvent(arp_reply, pkt+6, pkt, + RREvent(arp_reply, data+6, data, ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); break; diff --git a/src/analyzer/protocol/arp/ARP.h b/src/analyzer/protocol/arp/ARP.h index ad771b8db9..9f7142c846 100644 --- a/src/analyzer/protocol/arp/ARP.h +++ b/src/analyzer/protocol/arp/ARP.h @@ -24,6 +24,7 @@ #endif #include "NetVar.h" +#include "Packet.h" extern "C" { #include @@ -36,8 +37,7 @@ public: ARP_Analyzer(); virtual ~ARP_Analyzer(); - void NextPacket(double t, const struct pcap_pkthdr* hdr, - const u_char* const pkt, int hdr_size); + void NextPacket(double t, const Packet* pkt); void Describe(ODesc* d) const; void RREvent(EventHandlerPtr e, const u_char* src, const u_char* dst, @@ -45,7 +45,7 @@ public: const char* tpa, const char* tha); // Whether a packet is of interest for ARP analysis. - static bool IsARP(const u_char* pkt, int hdr_size); + static bool IsARP(const Packet *pkt); protected: AddrVal* ConstructAddrVal(const void* addr); diff --git a/src/bro.bif b/src/bro.bif index 037b236cc0..4eb1f89041 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -20,6 +20,7 @@ #include "Reporter.h" #include "IPAddr.h" #include "util.h" +#include "Packet.h" #include "file_analysis/Manager.h" #include "iosource/Manager.h" @@ -3238,11 +3239,10 @@ const char* conn_id_string(Val* c) ## .. bro:see:: dump_packet get_current_packet send_current_packet function dump_current_packet%(file_name: string%) : bool %{ - const struct pcap_pkthdr* hdr; - const u_char* pkt; + const Packet* pkt; if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&hdr, &pkt) ) + ! current_pktsrc->GetCurrentPacket(&pkt) ) return new Val(0, TYPE_BOOL); if ( ! addl_pkt_dumper ) @@ -3250,13 +3250,10 @@ function dump_current_packet%(file_name: string%) : bool if ( addl_pkt_dumper ) { - iosource::PktDumper::Packet p; - p.hdr = hdr; - p.data = pkt; - addl_pkt_dumper->Dump(&p); + addl_pkt_dumper->Dump(pkt); } - return new Val(! addl_pkt_dumper->IsError(), TYPE_BOOL); + return new Val( !!addl_pkt_dumper && ! addl_pkt_dumper->IsError(), TYPE_BOOL); %} ## Returns the currently processed PCAP packet. @@ -3267,26 +3264,27 @@ function dump_current_packet%(file_name: string%) : bool ## .. bro:see:: dump_current_packet dump_packet send_current_packet function get_current_packet%(%) : pcap_packet %{ - const struct pcap_pkthdr* hdr; - const u_char* data; + const Packet* p; RecordVal* pkt = new RecordVal(pcap_packet); if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&hdr, &data) ) + ! current_pktsrc->GetCurrentPacket(&p) ) { pkt->Assign(0, new Val(0, TYPE_COUNT)); pkt->Assign(1, new Val(0, TYPE_COUNT)); pkt->Assign(2, new Val(0, TYPE_COUNT)); pkt->Assign(3, new Val(0, TYPE_COUNT)); pkt->Assign(4, new StringVal("")); + pkt->Assign(5, new EnumVal(BifEnum::link_encap::link_unknown, BifType::Enum::link_encap)); return pkt; } - pkt->Assign(0, new Val(uint32(hdr->ts.tv_sec), TYPE_COUNT)); - pkt->Assign(1, new Val(uint32(hdr->ts.tv_usec), TYPE_COUNT)); - pkt->Assign(2, new Val(hdr->caplen, TYPE_COUNT)); - pkt->Assign(3, new Val(hdr->len, TYPE_COUNT)); - pkt->Assign(4, new StringVal(hdr->caplen, (const char*) data)); + pkt->Assign(0, new Val(uint32(p->ts.tv_sec), TYPE_COUNT)); + pkt->Assign(1, new Val(uint32(p->ts.tv_usec), TYPE_COUNT)); + pkt->Assign(2, new Val(p->cap_len, TYPE_COUNT)); + pkt->Assign(3, new Val(p->len, TYPE_COUNT)); + pkt->Assign(4, new StringVal(p->cap_len, (const char*)p->data)); + pkt->Assign(5, new EnumVal(p->link_type, BifType::Enum::link_encap)); return pkt; %} @@ -3302,26 +3300,29 @@ function get_current_packet%(%) : pcap_packet ## .. bro:see:: get_current_packet dump_current_packet send_current_packet function dump_packet%(pkt: pcap_packet, file_name: string%) : bool %{ - struct pcap_pkthdr hdr; - const val_list* pkt_vl = pkt->AsRecord(); - - hdr.ts.tv_sec = (*pkt_vl)[0]->AsCount(); - hdr.ts.tv_usec = (*pkt_vl)[1]->AsCount(); - hdr.caplen = (*pkt_vl)[2]->AsCount(); - hdr.len = (*pkt_vl)[3]->AsCount(); - if ( ! addl_pkt_dumper ) addl_pkt_dumper = iosource_mgr->OpenPktDumper(file_name->CheckString(), true); if ( addl_pkt_dumper ) { - iosource::PktDumper::Packet p; - p.hdr = &hdr; - p.data = (*pkt_vl)[4]->AsString()->Bytes(); + struct timeval ts; + uint32 caplen, len, link_type; + u_char *data; + + const val_list* pkt_vl = pkt->AsRecord(); + + ts.tv_sec = (*pkt_vl)[0]->AsCount(); + ts.tv_usec = (*pkt_vl)[1]->AsCount(); + caplen = (*pkt_vl)[2]->AsCount(); + len = (*pkt_vl)[3]->AsCount(); + data = (*pkt_vl)[4]->AsString()->Bytes(); + link_type = (*pkt_vl)[5]->AsEnum(); + Packet p(link_type, &ts, caplen, len, data, true); + addl_pkt_dumper->Dump(&p); } - return new Val(addl_pkt_dumper->IsError(), TYPE_BOOL); + return new Val(!!addl_pkt_dumper && !addl_pkt_dumper->IsError(), TYPE_BOOL); %} %%{ @@ -4800,20 +4801,16 @@ function send_ping%(p: event_peer, seq: count%) : bool ## dump_packet dump_current_packet get_current_packet function send_current_packet%(p: event_peer%) : bool %{ - Packet pkt(""); + const Packet* pkt; if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&pkt.hdr, &pkt.pkt) ) + ! current_pktsrc->GetCurrentPacket(&pkt) ) return new Val(0, TYPE_BOOL); RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - pkt.time = pkt.hdr->ts.tv_sec + double(pkt.hdr->ts.tv_usec) / 1e6; - pkt.hdr_size = current_pktsrc->HdrSize(); - pkt.link_type = current_pktsrc->LinkType(); - SerialInfo info(remote_serializer); - return new Val(remote_serializer->SendPacket(&info, id, pkt), TYPE_BOOL); + return new Val(remote_serializer->SendPacket(&info, id, *pkt), TYPE_BOOL); %} ## Returns the peer who generated the last event. diff --git a/src/event.bif b/src/event.bif index 6531bef6d8..3e4454c627 100644 --- a/src/event.bif +++ b/src/event.bif @@ -225,11 +225,20 @@ event udp_session_done%(u: connection%); ## ``ANALYZER_*`` constants right now. event scheduled_analyzer_applied%(c: connection, a: Analyzer::Tag%); -## Generated for every packet Bro sees. 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 traffic in real-time. That -## said, if you work from a trace and want to do some packet-level analysis, -## it may come in handy. +## Generated for every packet Bro sees that has a valid link layer header. This +## is a very very low-level and expensive event that should be avoided when at +## all possible. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet packet_contents +event raw_packet%(p: raw_pkt_hdr%); + +## Generated for almost every packet Bro sees. 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 traffic in +## real-time. That said, if you work from a trace and want to do some +## packet-level analysis, it may come in handy. ## ## c: The connection the packet is part of. ## diff --git a/src/iosource/PktDumper.h b/src/iosource/PktDumper.h index 56555c247a..dcfda2030b 100644 --- a/src/iosource/PktDumper.h +++ b/src/iosource/PktDumper.h @@ -3,6 +3,7 @@ #ifndef IOSOURCE_PKTSRC_PKTDUMPER_H #define IOSOURCE_PKTSRC_PKTDUMPER_H +#include "Packet.h" #include "IOSource.h" namespace iosource { @@ -12,21 +13,6 @@ namespace iosource { */ class PktDumper { public: - /** - * Structure describing a packet. - */ - struct Packet { - /** - * The pcap header associated with the packet. - */ - const struct pcap_pkthdr* hdr; - - /** - * The full content of the packet. - */ - const unsigned char* data; - }; - /** * Constructor. */ diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 5612c32e51..cb451088f5 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -147,7 +147,7 @@ void PktSrc::Info(const std::string& msg) void PktSrc::Weird(const std::string& msg, const Packet* p) { - sessions->Weird(msg.c_str(), p->hdr, p->data, 0); + sessions->Weird(msg.c_str(), p, 0); } void PktSrc::InternalError(const std::string& msg) @@ -197,20 +197,20 @@ double PktSrc::CheckPseudoTime() if ( remote_trace_sync_interval ) { - if ( next_sync_point == 0 || current_packet.ts >= next_sync_point ) + if ( next_sync_point == 0 || current_packet.time >= next_sync_point ) { int n = remote_serializer->SendSyncPoint(); next_sync_point = first_timestamp + n * remote_trace_sync_interval; remote_serializer->Log(RemoteSerializer::LogInfo, fmt("stopping at packet %.6f, next sync-point at %.6f", - current_packet.ts, next_sync_point)); + current_packet.time, next_sync_point)); return 0; } } - double pseudo_time = current_packet.ts - first_timestamp; + double pseudo_time = current_packet.time - first_timestamp; double ct = (current_time(true) - first_wallclock) * pseudo_realtime; return pseudo_time <= ct ? bro_start_time + pseudo_time : 0; @@ -261,7 +261,7 @@ double PktSrc::NextTimestamp(double* local_network_time) return -1.0; } - return current_packet.ts; + return current_packet.time; } void PktSrc::Process() @@ -272,20 +272,21 @@ void PktSrc::Process() if ( ! ExtractNextPacketInternal() ) return; - int pkt_hdr_size = props.hdr_size; - // Unfortunately some packets on the link might have MPLS labels // while others don't. That means we need to ask the link-layer if // labels are in place. bool have_mpls = false; + int l3_proto = 0; int protocol = 0; const u_char* data = current_packet.data; + current_packet.link_type = props.link_type; switch ( props.link_type ) { case DLT_NULL: { protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; + data += GetLinkHeaderSize(props.link_type); // From the Wireshark Wiki: "AF_INET6, unfortunately, has // different values in {NetBSD,OpenBSD,BSD/OS}, @@ -294,16 +295,14 @@ void PktSrc::Process() // as the AF_ value." As we may be reading traces captured on // platforms other than what we're running on, we accept them // all here. - if ( protocol != AF_INET - && protocol != AF_INET6 - && protocol != 24 - && protocol != 28 - && protocol != 30 ) + if ( protocol == 24 || protocol == 28 || protocol == 30 ) + protocol = AF_INET6; + if ( protocol != AF_INET && protocol != AF_INET6 ) { Weird("non_ip_packet_in_null_transport", ¤t_packet); goto done; } - + l3_proto = protocol; break; } @@ -311,7 +310,8 @@ void PktSrc::Process() { // Get protocol being carried from the ethernet frame. protocol = (data[12] << 8) + data[13]; - + data += GetLinkHeaderSize(props.link_type); + current_packet.eth_type = protocol; switch ( protocol ) { // MPLS carried over the ethernet frame. @@ -319,39 +319,43 @@ void PktSrc::Process() // Remove the data link layer and denote a // header size of zero before the IP header. have_mpls = true; - data += GetLinkHeaderSize(props.link_type); - pkt_hdr_size = 0; break; // VLAN carried over the ethernet frame. + // 802.1q / 802.1ad case 0x8100: - data += GetLinkHeaderSize(props.link_type); + case 0x9100: + current_packet.vlan = ((data[0] << 8) + data[1]) & 0xfff; + protocol = ((data[2] << 8) + data[3]); + data += 4; // Skip the vlan header // Check for MPLS in VLAN. - if ( ((data[2] << 8) + data[3]) == 0x8847 ) + if ( protocol == 0x8847 ) + { have_mpls = true; + break; + } - data += 4; // Skip the vlan header - pkt_hdr_size = 0; - - // Check for 802.1ah (Q-in-Q) containing IP. - // Only do a second layer of vlan tag - // stripping because there is no - // specification that allows for deeper - // nesting. - if ( ((data[2] << 8) + data[3]) == 0x0800 ) - data += 4; + // Check for double-tagged (802.1ad) + if ( protocol == 0x8100 || protocol == 0x9100 ) + { + protocol = ((data[2] << 8) + data[3]); + data += 4; // Skip the vlan header + } + current_packet.eth_type = protocol; break; // PPPoE carried over the ethernet frame. case 0x8864: - data += GetLinkHeaderSize(props.link_type); protocol = (data[6] << 8) + data[7]; data += 8; // Skip the PPPoE session and PPP header - pkt_hdr_size = 0; - if ( protocol != 0x0021 && protocol != 0x0057 ) + if ( protocol == 0x0021 ) + l3_proto = AF_INET; + else if ( protocol == 0x0057 ) + l3_proto = AF_INET6; + else { // Neither IPv4 nor IPv6. Weird("non_ip_packet_in_pppoe_encapsulation", ¤t_packet); @@ -360,6 +364,14 @@ void PktSrc::Process() break; } + // Normal path to determine Layer 3 protocol: + if ( !have_mpls && !l3_proto ) + { + if ( protocol == 0x800 ) + l3_proto = AF_INET; + else if ( protocol == 0x86dd ) + l3_proto = AF_INET6; + } break; } @@ -367,17 +379,19 @@ void PktSrc::Process() { // Get PPP protocol. protocol = (data[2] << 8) + data[3]; + data += GetLinkHeaderSize(props.link_type); if ( protocol == 0x0281 ) { // MPLS Unicast. Remove the data link layer and // denote a header size of zero before the IP header. have_mpls = true; - data += GetLinkHeaderSize(props.link_type); - pkt_hdr_size = 0; } - - else if ( protocol != 0x0021 && protocol != 0x0057 ) + else if ( protocol == 0x0021 ) + l3_proto = AF_INET; + else if ( protocol == 0x0057 ) + l3_proto = AF_INET6; + else { // Neither IPv4 nor IPv6. Weird("non_ip_packet_in_ppp_encapsulation", ¤t_packet); @@ -385,6 +399,14 @@ void PktSrc::Process() } break; } + default: + { + // Assume we're pointing at IP. Just figure out which version. + data += GetLinkHeaderSize(props.link_type); + const struct ip* ip = (const struct ip *)data; + l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; + break; + } } if ( have_mpls ) @@ -396,19 +418,53 @@ void PktSrc::Process() { end_of_stack = *(data + 2) & 0x01; data += 4; + if ( data >= current_packet.data + current_packet.cap_len ) + { + Weird("no_mpls_payload", ¤t_packet); + goto done; + } } + + // We assume that what remains is IP + if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) + { + Weird("no_ip_in_mpls_payload", ¤t_packet); + goto done; + } + const struct ip* ip = (const struct ip *)data; + l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; } + else if ( encap_hdr_size ) + { + // Blanket encapsulation + // We assume that what remains is IP + data += encap_hdr_size; + if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) + { + Weird("no_ip_left_after_encap", ¤t_packet); + goto done; + } + const struct ip* ip = (const struct ip *)data; + l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; + } + + // We've now determined (a) AF_INET (IPv4) vs (b) AF_INET6 (IPv6) vs + // (c) AF_UNSPEC (0 == anything else) + current_packet.l3_proto = l3_proto; + + // Calculate how much header we've used up. + current_packet.hdr_size = data - current_packet.data; if ( pseudo_realtime ) { current_pseudo = CheckPseudoTime(); - net_packet_dispatch(current_pseudo, current_packet.hdr, data, pkt_hdr_size, this); + net_packet_dispatch(current_pseudo, ¤t_packet, this); if ( ! first_wallclock ) first_wallclock = current_time(true); } else - net_packet_dispatch(current_packet.ts, current_packet.hdr, data, pkt_hdr_size, this); + net_packet_dispatch(current_packet.time, ¤t_packet, this); done: have_packet = 0; @@ -440,8 +496,9 @@ bool PktSrc::ExtractNextPacketInternal() if ( ExtractNextPacket(¤t_packet) ) { + current_packet.l3_proto = AF_UNSPEC; if ( ! first_timestamp ) - first_timestamp = current_packet.ts; + first_timestamp = current_packet.time; SetIdle(false); have_packet = true; @@ -524,12 +581,11 @@ bool PktSrc::ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_ch return pcap_offline_filter(code->GetProgram(), hdr, pkt); } -bool PktSrc::GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt) +bool PktSrc::GetCurrentPacket(const Packet** pkt) { if ( ! have_packet ) return false; - *hdr = current_packet.hdr; - *pkt = current_packet.data; + *pkt = ¤t_packet; return true; } diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index 2400219fd0..0f20bb3a0a 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -6,6 +6,7 @@ #include "IOSource.h" #include "BPF_Program.h" #include "Dict.h" +#include "Packet.h" declare(PDict,BPF_Program); @@ -165,14 +166,12 @@ public: /** * Returns the packet currently being processed, if available. * - * @param hdr A pointer to pass the header of the current packet back. - * * @param pkt A pointer to pass the content of the current packet * back. * * @return True if the current packet is available, or false if not. */ - bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt); + bool GetCurrentPacket(const Packet** hdr); // PacketSource interace for derived classes to override. @@ -225,6 +224,13 @@ public: */ static int GetLinkHeaderSize(int link_type); + /** + * Return the pcap link encapsulation type we started with. + * + * @return DLT_EN10MB (etc.) + */ + int GetLinkEncap(void); + protected: friend class Manager; @@ -274,26 +280,6 @@ protected: Properties(); }; - /** - * Structure describing a packet. - */ - struct Packet { - /** - * Time associated with the packet. - */ - double ts; - - /** - * The pcap header associated with the packet. - */ - const struct ::pcap_pkthdr* hdr; - - /** - * The full content of the packet. - */ - const u_char* data; - }; - /** * Called from the implementations of \a Open() to signal that the * source has been successully opened. diff --git a/src/iosource/pcap/Dumper.cc b/src/iosource/pcap/Dumper.cc index 5d0b5e599b..e924e882a1 100644 --- a/src/iosource/pcap/Dumper.cc +++ b/src/iosource/pcap/Dumper.cc @@ -101,7 +101,10 @@ bool PcapDumper::Dump(const Packet* pkt) if ( ! dumper ) return false; - pcap_dump((u_char*) dumper, pkt->hdr, pkt->data); + // Reconstitute the pcap_pkthdr + const struct pcap_pkthdr phdr = { + .ts = pkt->ts, .caplen = pkt->cap_len, .len = pkt->len }; + pcap_dump((u_char*) dumper, &phdr, pkt->data); return true; } diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 7645903c2a..45e8c89298 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -167,9 +167,8 @@ bool PcapSource::ExtractNextPacket(Packet* pkt) return false; } - pkt->ts = current_hdr.ts.tv_sec + double(current_hdr.ts.tv_usec) / 1e6; - pkt->hdr = ¤t_hdr; - pkt->data = last_data = data; + last_data = data; + pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) { diff --git a/src/types.bif b/src/types.bif index 180112dd8c..18a204d2b8 100644 --- a/src/types.bif +++ b/src/types.bif @@ -184,6 +184,18 @@ type EncapsulatingConn: record; module GLOBAL; +enum link_encap %{ + link_ethernet, + link_unknown, +%} + +enum layer3_proto %{ + l3_ipv4, + l3_ipv6, + l3_arp, + l3_unknown, +%} + type gtpv1_hdr: record; type gtp_create_pdp_ctx_request_elements: record; type gtp_create_pdp_ctx_response_elements: record; diff --git a/testing/btest/Baseline/core.raw_packet/output b/testing/btest/Baseline/core.raw_packet/output new file mode 100644 index 0000000000..314fbea931 --- /dev/null +++ b/testing/btest/Baseline/core.raw_packet/output @@ -0,0 +1,48 @@ +[l2=[encap=link_ethernet, len=215, cap_len=215, src=e8:de:27:ff:c0:78, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=201, id=0, ttl=64, p=17, src=192.168.1.1, dst=255.255.255.255], ip6=, tcp=, udp=[sport=40190/udp, dport=7437/udp, ulen=181], icmp=] +[l2=[encap=link_ethernet, len=68, cap_len=68, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=54, id=52261, ttl=64, p=6, src=192.168.1.103, dst=64.4.23.176], ip6=, tcp=[sport=65493/tcp, dport=40031/tcp, seq=2642773190, ack=2891276360, hl=32, dl=2, flags=24, win=4096], udp=, icmp=] +[l2=[encap=link_ethernet, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=l3_unknown], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=78, cap_len=78, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=64, id=32575, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=65170/udp, dport=53/udp, ulen=44], icmp=] +[l2=[encap=link_ethernet, len=78, cap_len=78, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=64, id=55466, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=53129/udp, dport=53/udp, ulen=44], icmp=] +[l2=[encap=link_ethernet, len=92, cap_len=92, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=78, id=32240, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=53129/udp, dport=53/udp, ulen=58], icmp=] +[l2=[encap=link_ethernet, len=85, cap_len=85, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=71, id=53895, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=57932/udp, dport=53/udp, ulen=51], icmp=] +[l2=[encap=link_ethernet, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=l3_unknown], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=307, cap_len=307, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=293, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=273], icmp=] +[l2=[encap=link_ethernet, len=316, cap_len=316, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=302, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=282], icmp=] +[l2=[encap=link_ethernet, len=379, cap_len=379, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=365, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=345], icmp=] +[l2=[encap=link_ethernet, len=371, cap_len=371, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=357, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=337], icmp=] +[l2=[encap=link_ethernet, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=l3_unknown], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=355, cap_len=355, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=341, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=321], icmp=] +[l2=[encap=link_ethernet, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=387, cap_len=387, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=373, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=353], icmp=] +[l2=[encap=link_ethernet, len=316, cap_len=316, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=302, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=282], icmp=] +[l2=[encap=link_ethernet, len=375, cap_len=375, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=361, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=341], icmp=] +[l2=[encap=link_ethernet, len=369, cap_len=369, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=355, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=335], icmp=] +[l2=[encap=link_ethernet, len=316, cap_len=316, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=302, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=282], icmp=] +[l2=[encap=link_ethernet, len=371, cap_len=371, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=357, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=337], icmp=] +[l2=[encap=link_ethernet, len=381, cap_len=381, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=367, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=347], icmp=] +[l2=[encap=link_ethernet, len=215, cap_len=215, src=e8:de:27:ff:c0:78, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=201, id=0, ttl=64, p=17, src=192.168.1.1, dst=255.255.255.255], ip6=, tcp=, udp=[sport=40190/udp, dport=7437/udp, ulen=181], icmp=] +[l2=[encap=link_ethernet, len=98, cap_len=98, src=00:50:56:3e:93:6b, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=84, id=29257, ttl=64, p=1, src=192.168.1.104, dst=192.168.1.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=98, cap_len=98, src=e8:de:27:ff:c0:78, dst=00:50:56:3e:93:6b, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=84, id=3684, ttl=64, p=1, src=192.168.1.1, dst=192.168.1.104], ip6=, tcp=, udp=, icmp=[icmp_type=0]] +[l2=[encap=link_ethernet, len=112, cap_len=112, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=98, id=56893, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176031, ack=445274592, hl=32, dl=46, flags=24, win=4096], udp=, icmp=] +[l2=[encap=link_ethernet, len=66, cap_len=66, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=52, id=22643, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176077, ack=445274652, hl=32, dl=0, flags=16, win=4094], udp=, icmp=] +[l2=[encap=link_ethernet, len=112, cap_len=112, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=98, id=85, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176077, ack=445274652, hl=32, dl=46, flags=24, win=4096], udp=, icmp=] +[l2=[encap=link_ethernet, len=97, cap_len=97, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=83, id=28558, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176123, ack=445274652, hl=32, dl=31, flags=24, win=4096], udp=, icmp=] +[l2=[encap=link_ethernet, len=66, cap_len=66, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=52, id=36529, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176154, ack=445274652, hl=32, dl=0, flags=17, win=4096], udp=, icmp=] +[l2=[encap=link_ethernet, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=l3_unknown], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:19:06:ea:b8:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:18:73:de:57:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:18:73:de:57:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:19:06:ea:b8:c1, dst=00:18:73:de:57:c1, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=5, ttl=255, p=1, src=192.168.123.2, dst=192.168.123.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:19:06:ea:b8:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=64, cap_len=64, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2054, proto=l3_arp], ip=, ip6=, tcp=, udp=, icmp=] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=6, ttl=255, p=1, src=192.168.123.2, dst=192.168.123.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:19:06:ea:b8:c1, dst=00:18:73:de:57:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=6, ttl=255, p=1, src=192.168.123.1, dst=192.168.123.2], ip6=, tcp=, udp=, icmp=[icmp_type=0]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=7, ttl=255, p=1, src=192.168.123.2, dst=192.168.123.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:19:06:ea:b8:c1, dst=00:18:73:de:57:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=7, ttl=255, p=1, src=192.168.123.1, dst=192.168.123.2], ip6=, tcp=, udp=, icmp=[icmp_type=0]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=8, ttl=255, p=1, src=192.168.123.2, dst=192.168.123.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:19:06:ea:b8:c1, dst=00:18:73:de:57:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=8, ttl=255, p=1, src=192.168.123.1, dst=192.168.123.2], ip6=, tcp=, udp=, icmp=[icmp_type=0]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:18:73:de:57:c1, dst=00:19:06:ea:b8:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=9, ttl=255, p=1, src=192.168.123.2, dst=192.168.123.1], ip6=, tcp=, udp=, icmp=[icmp_type=8]] +[l2=[encap=link_ethernet, len=118, cap_len=118, src=00:19:06:ea:b8:c1, dst=00:18:73:de:57:c1, vlan=123, eth_type=2048, proto=l3_ipv4], ip=[hl=20, tos=0, len=100, id=9, ttl=255, p=1, src=192.168.123.1, dst=192.168.123.2], ip6=, tcp=, udp=, icmp=[icmp_type=0]] diff --git a/testing/btest/Traces/icmp_dot1q.trace b/testing/btest/Traces/icmp_dot1q.trace new file mode 100644 index 0000000000000000000000000000000000000000..7c73c6266267385853ddd06a4cb418e62d082d2d GIT binary patch literal 1710 zcmb`Htxp3n7>C~;<2aIq1;;F)5DWqV!N(>b!66YC1mPbb12IK{Apy4l!GR)~Lrsvt zHtZZ&f+7KjKp*c%dhPB?Ce~hV={4)`o<8rpy>=dM1IU3MaSWjFp?bQzHU2mT6`a!@ z^MGRb-E5rz)S?hn1Yr&WS$n>(Dfte~a6@WP-rHv;Z{qNMC!NP@m=Yv;K`IO%FEQ_T zvXJJ><|#<>B*o1~d8KKSC%g1{Kb+@HC)<=)m^U?FfFoR_Tasi4`-4q@eHccwYNJf2 zC9VkSH>{s_9YLK@nDV`U7{$@S`^H#YmdDywK5b+?9{zeROT!S_Lk|G5q7a= zx#*w?sg)-e2X^1OT^I`O!aKz__HCbEPsA=(Ef;NcF~l9~$wd{rJ)v;BFcjK_cZ$6w gi^AO(qwHeEa?wH;^2hGU#l^Bk;dWstvdCA%>V!Z literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/raw_packets.trace b/testing/btest/Traces/raw_packets.trace new file mode 100644 index 0000000000000000000000000000000000000000..4fc64c429b2b785c735386adfb5f3db1aab16677 GIT binary patch literal 6641 zcmds63v5$m6#g&kN+}c=55dW#A_E!R?RLF=T|m1h+Z^rKI&h%K?d|PW*xK3$8z5m( zlz>PAgaiY`7#|S?1p*j(L>{8SfF?Me5=24-qedhsFdp-qdpovL7y}x&c$3rh-roOw z=X~G!&wuZ~hJBmg>p~Qy`LHSpq2Q$9!nE>SUO|q*ceEzyxNv%S)9yMI$s^V~WBbSKms}kgc~)J)dQ>*~?RHl1F)fqnMtQTdFrQjC7IQc`jdV`%{;$GqW+b zV5n$aB7b9UxX%Slv*80J$%XsSx`butmY$q;cJ$&S;PcFHUC9{mhep-!ZT4JChGl0bz!@R+ z5vmiMPQZCXh@PWQgol_BH6D=k_>%8X($WXf#<3lNKEh7dp>e6RJUIAW^8aODY zQt)}*p321Fj9Gp$LGab!ZxnhjI^UM}1p z1ZXj_+vZ+G?{)t~dFPg{Ner}j?<<8Y3PIW*@VV%4P^1}^Q0)u5c)vfvD~1RGtfP?0 zzWLorIpCnhV2wMx0I`O;o3YLoLniv!*G}zk!BTs?o)8^mbit6q9}ZR}0z`ESUB>|A z6A~X`(bwTO)g%pqMU&?jDVg}}@);^6p;Sbv0Ewh?2)PPwfdjscIu0Y3&U%=UCtzel z9YyqzF&agt&TDFvslsBXQh_3(Ncw6h;81@yH8pM;(6yRMnlQv>cNFGVXw$R>4o67_ zOht{lz+UFyw3&KKdZxh;F^1Dw7)GPc$;v6nqjT&wN2$G-)7J2HG+!x>)!}c&_M9w7 zq20!5t3n|^myw~fWTxwk=5+8X4bSjYy3*@vsx@jG0EGQsKNs-%LN0NpM-cI18K(^f zU4D+Q_RNF}WqG9&^GZ3b$L|Yfn9><-d5ITeWV9`922VBW@-jdThdnNiF)~h*-k_)5 z0&k>Q#>CKOgPWywZl~L6;ax6croeGA*cvrb_>C%oi~;)4Vkk_HQ20a?g~?kkcOZrB z&Gytz_A<^YdqFO|S1{ zazq%2#UXH%wu6)hH%i8fn|EX`WndfI7r8EAu!7n~-ii)Gxn0JJfiqGFQeTlMP0 zuF9iNsLAUf6k3c};fPobQDX6xY$p?|xxRs!9A8b1&nq=VH!p}e(!*!m=HMfU*Pa+< zF{wb02VUi`a~&uNuJRT)V>TL`@LXeX@ifarMVk#y6K!G{)~GkRU2eT8PU}(opkyvr zUeSYY~lZgGH~4*E4SWpkyxpn4a*!kE;daJCMs(J*C#; z_VCr!9^Na6t=}Lfu`25qv?=a(wdz2&_?naBj zXI}^+{%$TBe}g7@(d0q(y?fnKrQF6pl$Nlu5j{46$9rc)%F*M%k$3e78SUQ^?Xh)6 zT?ZCzdwc5?$Kib`+t)L{r+9}dSMN}6&RfytihlOEJrzseNBnJjm4t_E&|)$w^DROA zwYa<5iqQ?DrHlZ-4-gSyRLZD7Fq#aW@K7zC*|co(^6>R}Q)hfRY}cw^Uzv)42LbTj h6fW6>fD3Qj0XSI#OzKU#9*PD;kNtjD#^pZ>{{n^9b({bI literal 0 HcmV?d00001 diff --git a/testing/btest/core/raw_packet.bro b/testing/btest/core/raw_packet.bro new file mode 100644 index 0000000000..cb1ee94b0f --- /dev/null +++ b/testing/btest/core/raw_packet.bro @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -b -r $TRACES/raw_packets.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/icmp_dot1q.trace %INPUT >>output +# @TEST-EXEC: btest-diff output + +event raw_packet(p: raw_pkt_hdr) + { + print p; + } + diff --git a/testing/btest/plugins/pktdumper-plugin/src/Foo.cc b/testing/btest/plugins/pktdumper-plugin/src/Foo.cc index fdd364b034..c68eec809a 100644 --- a/testing/btest/plugins/pktdumper-plugin/src/Foo.cc +++ b/testing/btest/plugins/pktdumper-plugin/src/Foo.cc @@ -29,8 +29,8 @@ void Foo::Close() bool Foo::Dump(const Packet* pkt) { - double t = double(pkt->hdr->ts.tv_sec) + double(pkt->hdr->ts.tv_usec) / 1e6; - fprintf(stdout, "Dumping to %s: %.6f len %u\n", props.path.c_str(), t, (unsigned int)pkt->hdr->len); + double t = double(pkt->ts.tv_sec) + double(pkt->ts.tv_usec) / 1e6; + fprintf(stdout, "Dumping to %s: %.6f len %u\n", props.path.c_str(), t, (unsigned int)pkt->len); return true; } diff --git a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc index b08bc51d72..afd5621d0f 100644 --- a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc +++ b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc @@ -45,12 +45,9 @@ bool Foo::ExtractNextPacket(Packet* pkt) return false; } - hdr.ts.tv_sec = 1409193037; - hdr.ts.tv_usec = 0; - hdr.caplen = hdr.len = packet.size(); - pkt->ts = hdr.ts.tv_sec; - pkt->hdr = &hdr; - pkt->data = (const u_char *)packet.c_str(); + struct timeval ts = { 1409193037, 0 }; + pkt->Init(props.link_type, &ts, packet.size(), packet.size(), + (const u_char *)packet.c_str()); return true; } diff --git a/testing/btest/plugins/pktsrc-plugin/src/Foo.h b/testing/btest/plugins/pktsrc-plugin/src/Foo.h index 902ac0e37a..922b300b61 100644 --- a/testing/btest/plugins/pktsrc-plugin/src/Foo.h +++ b/testing/btest/plugins/pktsrc-plugin/src/Foo.h @@ -26,7 +26,6 @@ protected: private: Properties props; string packet; - struct pcap_pkthdr hdr; }; } From 72fca3ee26301a168b709a7558d4d941aaa61611 Mon Sep 17 00:00:00 2001 From: Jeff Barber Date: Thu, 28 May 2015 16:58:23 -0400 Subject: [PATCH 06/26] Make enums work for non-C++11 config --- src/L2.cc | 12 ++++++------ src/bro.bif | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/L2.cc b/src/L2.cc index 9b277e9e9e..33865071dc 100644 --- a/src/L2.cc +++ b/src/L2.cc @@ -48,11 +48,11 @@ RecordVal* L2_Hdr::BuildPktHdrVal() const RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type); RecordVal* l2_hdr = new RecordVal(l2_hdr_type); int is_ethernet = ( pkt->link_type == DLT_EN10MB ) ? 1 : 0; - int l3 = BifEnum::layer3_proto::l3_unknown; + int l3 = BifEnum::l3_unknown; if ( pkt->l3_proto == AF_INET ) - l3 = BifEnum::layer3_proto::l3_ipv4; + l3 = BifEnum::l3_ipv4; else if ( pkt->l3_proto == AF_INET6 ) - l3 = BifEnum::layer3_proto::l3_ipv6; + l3 = BifEnum::l3_ipv6; // l2_hdr layout: // encap: link_encap; ##< L2 link encapsulation @@ -67,7 +67,7 @@ RecordVal* L2_Hdr::BuildPktHdrVal() const { // Ethernet header layout is: // dst[6bytes] src[6bytes] ethertype[2bytes]... - l2_hdr->Assign(0, new EnumVal(BifEnum::link_encap::link_ethernet, BifType::Enum::link_encap)); + l2_hdr->Assign(0, new EnumVal(BifEnum::link_ethernet, BifType::Enum::link_encap)); l2_hdr->Assign(3, fmt_eui48(pkt->data + 6)); // src l2_hdr->Assign(4, fmt_eui48(pkt->data)); // dst if ( pkt->vlan ) @@ -76,12 +76,12 @@ RecordVal* L2_Hdr::BuildPktHdrVal() const if ( pkt->eth_type == ETHERTYPE_ARP || pkt->eth_type == ETHERTYPE_REVARP ) { // We also identify ARP for L3 over ethernet - l3 = BifEnum::layer3_proto::l3_arp; + l3 = BifEnum::l3_arp; } } else { - l2_hdr->Assign(0, new EnumVal(BifEnum::link_encap::link_unknown, BifType::Enum::link_encap)); + l2_hdr->Assign(0, new EnumVal(BifEnum::link_unknown, BifType::Enum::link_encap)); } l2_hdr->Assign(1, new Val(pkt->len, TYPE_COUNT)); l2_hdr->Assign(2, new Val(pkt->cap_len, TYPE_COUNT)); diff --git a/src/bro.bif b/src/bro.bif index 4eb1f89041..af42a9bd5f 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -3275,7 +3275,7 @@ function get_current_packet%(%) : pcap_packet pkt->Assign(2, new Val(0, TYPE_COUNT)); pkt->Assign(3, new Val(0, TYPE_COUNT)); pkt->Assign(4, new StringVal("")); - pkt->Assign(5, new EnumVal(BifEnum::link_encap::link_unknown, BifType::Enum::link_encap)); + pkt->Assign(5, new EnumVal(BifEnum::link_unknown, BifType::Enum::link_encap)); return pkt; } From 97ab422e173c805d09c356084f4940fe1ba5bb71 Mon Sep 17 00:00:00 2001 From: Jeff Barber Date: Mon, 1 Jun 2015 10:34:28 -0400 Subject: [PATCH 07/26] Packet::IP()-created IP_Hdr should not free --- src/Packet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Packet.h b/src/Packet.h index 05c826ec5f..0f3077eeec 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -60,7 +60,7 @@ public: } const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (data + hdr_size), true); } + { return IP_Hdr((struct ip *) (data + hdr_size), false); } void Describe(ODesc* d) const; From 49ece39cb6ca566ab72acf446abfa63b58fed082 Mon Sep 17 00:00:00 2001 From: Jeff Barber Date: Tue, 2 Jun 2015 16:35:23 -0400 Subject: [PATCH 08/26] One more tinker to Packet -- ensure no uninitialized values --- src/Packet.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Packet.h b/src/Packet.h index 0f3077eeec..838aebfc96 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -16,6 +16,8 @@ class Packet { public: Packet() { + struct timeval ts = {0, 0}; + Init(0, &ts, 0, 0, 0); } // Construct and initialize from packet data. Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, From 5d30be20838730dc2604aa7d1491414cbc56c826 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 3 Jul 2015 08:40:22 -0700 Subject: [PATCH 09/26] A set of tests exercising IP defragmentation and TCP reassembly. --- testing/btest/Baseline/core.reassembly/output | 32 ++++++++++++++++++ testing/btest/Traces/ipv4/fragmented-1.pcap | Bin 0 -> 620 bytes testing/btest/Traces/ipv4/fragmented-2.pcap | Bin 0 -> 342 bytes testing/btest/Traces/ipv4/fragmented-3.pcap | Bin 0 -> 7674 bytes testing/btest/Traces/ipv4/fragmented-4.pcap | Bin 0 -> 477 bytes testing/btest/Traces/tcp/reassembly.pcap | Bin 0 -> 43248 bytes testing/btest/core/reassembly.bro | 26 ++++++++++++++ 7 files changed, 58 insertions(+) create mode 100644 testing/btest/Baseline/core.reassembly/output create mode 100644 testing/btest/Traces/ipv4/fragmented-1.pcap create mode 100644 testing/btest/Traces/ipv4/fragmented-2.pcap create mode 100644 testing/btest/Traces/ipv4/fragmented-3.pcap create mode 100644 testing/btest/Traces/ipv4/fragmented-4.pcap create mode 100644 testing/btest/Traces/tcp/reassembly.pcap create mode 100644 testing/btest/core/reassembly.bro diff --git a/testing/btest/Baseline/core.reassembly/output b/testing/btest/Baseline/core.reassembly/output new file mode 100644 index 0000000000..79922b43c4 --- /dev/null +++ b/testing/btest/Baseline/core.reassembly/output @@ -0,0 +1,32 @@ +---------------------- +flow weird, excessively_small_fragment, 164.1.123.163, 164.1.123.61 +flow weird, fragment_size_inconsistency, 164.1.123.163, 164.1.123.61 +flow weird, fragment_inconsistency, 164.1.123.163, 164.1.123.61 +flow weird, fragment_inconsistency, 164.1.123.163, 164.1.123.61 +flow weird, dns_unmatched_msg, 164.1.123.163, 164.1.123.61 +---------------------- +flow weird, excessively_small_fragment, 164.1.123.163, 164.1.123.61 +flow weird, excessively_small_fragment, 164.1.123.163, 164.1.123.61 +flow weird, fragment_overlap, 164.1.123.163, 164.1.123.61 +---------------------- +flow weird, fragment_with_DF, 210.54.213.247, 131.243.1.10 +flow weird, fragment_with_DF, 210.54.213.247, 131.243.1.10 +flow weird, fragment_with_DF, 210.54.213.247, 131.243.1.10 +flow weird, fragment_with_DF, 210.54.213.247, 131.243.1.10 +flow weird, fragment_with_DF, 210.54.213.247, 131.243.1.10 +---------------------- +flow weird, excessively_small_fragment, 128.32.46.142, 10.0.0.1 +flow weird, excessively_small_fragment, 128.32.46.142, 10.0.0.1 +flow weird, fragment_inconsistency, 128.32.46.142, 10.0.0.1 +---------------------- +net_weird, truncated_IP +net_weird, truncated_IP +net_weird, truncated_IP +net_weird, truncated_IP +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], nlkmlpjfjjnoomfnqmdqgrdsgpefslhjrdjghsshrmosrkosidknnieiggpmnggelfhlkflfqojpjrsmeqghklmjlkdskjollmensjiqosemknoehellhlsspjfjpddfgqkemghskqosrksmkpsdomfoghllfokilshsisgpjhjoosidirlnmespjhdogdidoemejrnjjrookfrmiqllllqhlqfgolfqssfjrhrjhgfkpdnigiilrmnespjspeqjfedjhrkisjdhoofqdfeqnmihrelmildkngirkqorjslhmglripdojfedjjngjnpikoliqhdipgpshenekqiphmrsqmemghklodqnqoeggfkdqngrfollhjmddjreeghdqflohgrhqhelqsmdghgihpifpnikrddpmdfejhrhgfdfdlepmmhlhrnrslepqgmkopmdfogpoljeepqoemisfeksdeddiplnkfjddjioqhojlnmlirehidipdhqlddssssgpgikieeldsmfrkidpldsngdkidkoshkrofnonrrehghlmgmqshkedgpkpgjjkoneigsfjdlgjsngepfkndqoefqmsssrgegspromqepdpdeglmmegjljlmljeeorhhfmrohjeregpfshqjsqkekrihjdpfdjflgspepqjrqfemsjffmjfkhejdkrokmgdrhojgmgjpldjeiphroeheipolfmshoglkfnllfnhlflhlpddjflekhiqilefjpfqepdrrdokkjiekmelkhdpjlqjdlnfjemqdrksirdnjlrhrdijgqjhdqlidpfdisgrmnlfnsdlishlpfkshhglpdiqhpgmhpjdrpednjljfsqknsiqpfeqhlphgqdphflglpmqfkkhdjeodkelinkfpmfedidhphldmqjqggrljlhriehqqemeimkjhoqnsrdgengmgjokpeiijgrseppeoiflngggomdfjkndpqedhgnkiqlodkpjfkqoifidjmrdhhmglledkomllhpehdfjfdspmklkjdnhkdgpgqephfdfdrfplmepoegsekmrnikknelnprdpslmfkhghhooknieksjjhdeelidikndedijqqhfmphdondndpehmfoqelqigdpgioeljhedhfoeqlinriemqjigerkphgepqmiiidqlhriqioimpglonlsgomeloipndiihqqfiekkeriokrsjlmsjqiehqsrqkhdjlddjrrllirqkidqiggdrjpjirssgqepnqmhigfsqlekiqdddllnsjmroiofkieqnghddpjnhdjkfloilheljofddrkherkrieeoijrlfghiikmhpfdhekdjloejlmpperkgrhomedpfOOOOOOOOOOOOOOOOOOOOOOOOOOOO, nlkmlpjfjjnoomfnqmdqgrdsgpefslhjrdjghsshrmosrkosidknnieiggpmnggelfhlkflfqojpjrsmeqghklmjlkdskjollmensjiqosemknoehellhlsspjfjpddfgqkemghskqosrksmkpsdomfoghllfokilshsisgpjhjoosidirlnmespjhdogdidoemejrnjjrookfrmiqllllqhlqfgolfqssfjrhrjhgfkpdnigiilrmnespjspeqjfedjhrkisjdhoofqdfeqnmihrelmildkngirkqorjslhmglripdojfedjjngjnpikoliqhdipgpshenekqiphmrsqmemghklodqnqoeggfkdqngrfollhjmddjreeghdqflohgrhqhelqsmdghgihpifpnikrddpmdfejhrhgfdfdlepmmhlhrnrslepqgmkopmdfogpoljeepqoemisfeksdeddiplnkfjddjioqhojlnmlirehidipdhqlddssssgpgikieeldsmfrkidpldsngdkidkoshkrofnonrrehghlmgmqshkedgpkpgjjkoneigsfjdlgjsngepfkndqoefqmsssrgegspromqepdpdeglmmegjljlmljeeorhhfmrohjeregpfshqjsqkekrihjdpfdjflgspepqjrqfemsjffmjfkhejdkrokmgdrhojgmgjpldjeiphroeheipolfmshoglkfnllfnhlflhlpddjflekhiqilefjpfqepdrrdokkjiekmelkhdpjlqjdlnfjemqdrksirdnjlrhrdijgqjhdqlidpfdisgrmnlfnsdlishlpfkshhglpdiqhpgmhpjdrpednjljfsqknsiqpfeqhlphgqdphflglpmqfkkhdjeodkelinkfpmfedidhphldmqjqggrljlhriehqqemeimkjhoqnsrdgengmgjokpeiijgrseppeoiflngggomdfjkndpqedhgnkiqlodkpjfkqoifidjmrdhhmglledkomllhpehdfjfdspmklkjdnhkdgpgqephfdfdrfplmepoegsekmrnikknelnprdpslmfkhghhooknieksjjhdeelidikndedijqqhfmphdondndpehmfoqelqigdpgioeljhedhfoeqlinriemqjigerkphgepqmiiidqlhriqioimpglonlsgomeloipndiihqqfiekkeriokrsjlmsjqiehqsrqkhdjlddjrrllirqkidqiggdrjpjirssgqepnqmhigfsqlekiqdddllnsjmroiofkieqnghddpjnhdjkfloilheljofddrkherkrieeoijrlfghiikmhpfdhekdjloejlmpperkgrhomedpfqkrodjdmrqfpiodgphidfliidlhd +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], dgphrodofqhq, orgmmpelofil +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], lenhfdqhqfgs, dfpqssidkpdg +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], nlkmlpjfjjnoomfnqmdqgrdsgpefslhjrdjghsshrmosrkosidknnieiggpmnggelfhlkflfqojpjrsmeqghklmjlkdskjollmensjiqosemknoehellhlsspjfjpddfgqkemghskqosrksmkpsdomfoghllfokilshsisgpjhjoosidirlnmespjhdogdidoemejrnjjrookfrmiqllllqhlqfgolfqssfjrhrjhgfkpdnigiilrmnespjspeqjfedjhrkisjdhoofqdfeqnmihrelmildkngirkqorjslhmglripdojfedjjngjnpikoliqhdipgpshenekqiphmrsqmemghklodqnqoeggfkdqngrfollhjmddjreeghdqflohgrhqhelqsmdghgihpifpnikrddpmdfejhrhgfdfdlepmmhlhrnrslepqgmkopmdfogpoljeepqoemisfeksdeddiplnkfjddjioqhojlnmlirehidipdhqlddssssgpgikieeldsmfrkidpldsngdkidkoshkrofnonrrehghlmgmqshkedgpkpgjjkoneigsfjdlgjsngepfkndqoefqmsssrgegspromqepdpdeglmmegjljlmljeeorhhfmrohjeregpfshqjsqkekrihjdpfdjflgspepqjrqfemsjffmjfkhejdkrokmgdrhojgmgjpldjeiphroeheipolfmshoglkfnllfnhlflhlpddjflekhiqilefjpfqepdrrdokkjiekmelkhdpjlqjdlnfjemqdrksirdnjlrhrdijgqjhdqlidpfdisgrmnlfnsdlishlpfkshhglpdiqhpgmhpjdrpednjljfsqknsiqpfeqhlphgqdphflglpmqfkkhdjeodkelinkfpmfedidhphldmqjqggrljlhriehqqemeimkjhoqnsrdgengmgjokpeiijgrseppeoiflngggomdfjkndpqedhgnkiqlodkpjfkqoifidjmrdhhmglledkomllhpehdfjfdspmklkjdnhkdgpgqephfdfdrfplmepoegsekmrnikknelnprdpslmfkhghhooknieksjjhdeelidikndedijqqhfmphdondndpehmfoqelqigdpgioeljhedhfoeqlinriemqjigerkphgepqmiiidqlhriqioimpglonlsgomeloipndiihqqfiekkeriokrsjlmsjqiehqsrqkhdjlddjrrllirqkidqiggdrjpjirssgqepnqmhigfsqlekiqdddllnsjmroiofkieqnghddpjnhdjkfloilheljofddrkherkrieeoijrlfghiikmhpfdhekdjloejlmpperkgrhomedpfOOOOOOOOOOOOOOOOOOOOOOOOOOOO, nlkmlpjfjjnoomfnqmdqgrdsgpefslhjrdjghsshrmosrkosidknnieiggpmnggelfhlkflfqojpjrsmeqghklmjlkdskjollmensjiqosemknoehellhlsspjfjpddfgqkemghskqosrksmkpsdomfoghllfokilshsisgpjhjoosidirlnmespjhdogdidoemejrnjjrookfrmiqllllqhlqfgolfqssfjrhrjhgfkpdnigiilrmnespjspeqjfedjhrkisjdhoofqdfeqnmihrelmildkngirkqorjslhmglripdojfedjjngjnpikoliqhdipgpshenekqiphmrsqmemghklodqnqoeggfkdqngrfollhjmddjreeghdqflohgrhqhelqsmdghgihpifpnikrddpmdfejhrhgfdfdlepmmhlhrnrslepqgmkopmdfogpoljeepqoemisfeksdeddiplnkfjddjioqhojlnmlirehidipdhqlddssssgpgikieeldsmfrkidpldsngdkidkoshkrofnonrrehghlmgmqshkedgpkpgjjkoneigsfjdlgjsngepfkndqoefqmsssrgegspromqepdpdeglmmegjljlmljeeorhhfmrohjeregpfshqjsqkekrihjdpfdjflgspepqjrqfemsjffmjfkhejdkrokmgdrhojgmgjpldjeiphroeheipolfmshoglkfnllfnhlflhlpddjflekhiqilefjpfqepdrrdokkjiekmelkhdpjlqjdlnfjemqdrksirdnjlrhrdijgqjhdqlidpfdisgrmnlfnsdlishlpfkshhglpdiqhpgmhpjdrpednjljfsqknsiqpfeqhlphgqdphflglpmqfkkhdjeodkelinkfpmfedidhphldmqjqggrljlhriehqqemeimkjhoqnsrdgengmgjokpeiijgrseppeoiflngggomdfjkndpqedhgnkiqlodkpjfkqoifidjmrdhhmglledkomllhpehdfjfdspmklkjdnhkdgpgqephfdfdrfplmepoegsekmrnikknelnprdpslmfkhghhooknieksjjhdeelidikndedijqqhfmphdondndpehmfoqelqigdpgioeljhedhfoeqlinriemqjigerkphgepqmiiidqlhriqioimpglonlsgomeloipndiihqqfiekkeriokrsjlmsjqiehqsrqkhdjlddjrrllirqkidqiggdrjpjirssgqepnqmhigfsqlekiqdddllnsjmroiofkieqnghddpjnhdjkfloilheljofddrkherkrieeoijrlfghiikmhpfdhekdjloejlmpperkgrhomedpfqkrodjdmrqfpiodgphidfliislrr +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], iokgedlsdkjkiefgmeqkfjoh, ggdeolssksemrhedoledddml +net_weird, truncated_IP +rexmit_inconsistency, [orig_h=63.193.213.194, orig_p=2564/tcp, resp_h=128.3.97.175, resp_p=80/tcp], OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO HTTP/1.1\x0d\x0aHost: 127.0.0.1\x0d\x0aContent-Type: text/xml\x0d\x0aContent-length: 1\x0d\x0a\x0d\x0aO\x0d\x0aYh=wuMu{|KZQ6@biIo5;j44JZu47-n@ad}3g85VYz-F{@<1 v9I83A<$+wOnasox1oS=#qq~yP1>$4LE6A>7vvV8axl0uFsLzn zQebcpl=`%Uv3fBO+cH!$bTSC-e*{vD3P5H(0Gc%oC=9|FW_2)pVqkL+wCX}Jt7N|% PsyVdffn52QNA%x9+NG6L}Nd^+ox_7gJOU0*x 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 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/ipv4/fragmented-4.pcap b/testing/btest/Traces/ipv4/fragmented-4.pcap new file mode 100644 index 0000000000000000000000000000000000000000..ddcef18f1880a8cb94010d826014901648f6581f GIT binary patch literal 477 zcmca|c+)~A1{MYwxWLZ9zzF1QyL827>PsF5Gaws;88%#aA}k0YIT&087&I6d92owy zecH0-K`4z@Pv$a=ye6>$O=5$Yq^D|>rl+T0o|%_dqF-ED zT#}k=Y^0x@3p2?W=o}EnaFZ%fjPpMmGdIkn6us1nRD1no?Uc+S?PRMME|?KPK$Rej zVT23NTg?C29({xvp`Tlvn3Alo2Xz#j4)XR34=qZ`&-c|1FV6Ni^2~Jf2@LVX41V;0 Yg9iU$0hkTYfXf009OM80+jtll08SNvbN~PV literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tcp/reassembly.pcap b/testing/btest/Traces/tcp/reassembly.pcap new file mode 100644 index 0000000000000000000000000000000000000000..f387c3fbba81126ed2b6fb7162f4d5a1691bc06c GIT binary patch literal 43248 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 N{@mn!yoC4h-vR!6%3=Tj literal 0 HcmV?d00001 diff --git a/testing/btest/core/reassembly.bro b/testing/btest/core/reassembly.bro new file mode 100644 index 0000000000..cb04ace71b --- /dev/null +++ b/testing/btest/core/reassembly.bro @@ -0,0 +1,26 @@ +# @TEST-EXEC: bro -C -r $TRACES/ipv4/fragmented-1.pcap %INPUT >>output +# @TEST-EXEC: bro -C -r $TRACES/ipv4/fragmented-2.pcap %INPUT >>output +# @TEST-EXEC: bro -C -r $TRACES/ipv4/fragmented-3.pcap %INPUT >>output +# @TEST-EXEC: bro -C -r $TRACES/ipv4/fragmented-4.pcap %INPUT >>output +# @TEST-EXEC: bro -C -r $TRACES/tcp/reassembly.pcap %INPUT >>output +# @TEST-EXEC: btest-diff output + +event bro_init() + { + print "----------------------"; + } + +event flow_weird(name: string, src: addr, dst: addr) + { + print "flow weird", name, src, dst; + } + +event net_weird(name: string) + { + print "net_weird", name; + } + +event rexmit_inconsistency(c: connection, t1: string, t2: string) + { + print "rexmit_inconsistency", c$id, t1, t2 ; + } From de3932bc425fe13564a541ae95fd1dd3cefcf718 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 3 Jul 2015 09:04:45 -0700 Subject: [PATCH 10/26] A bit more cleanup for the new overlap detection. --- CHANGES | 7 ++++++- VERSION | 2 +- src/Reassem.cc | 35 ++++++++++++++++------------------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index 7e1feb2cfe..3f64d91489 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.4-19 | 2015-07-03 09:04:54 -0700 + + * A set of tests exercising IP defragmentation and TCP reassembly. + (Robin Sommer) + 2.4-17 | 2015-06-28 13:02:41 -0700 * BIT-1314: Add detection for Quantum Insert attacks. The TCP @@ -6,7 +11,7 @@ tcp_max_old_segments option. An overlapping segment with different data will then generate an rexmit_inconsistency event. The default for tcp_max_old_segments is zero, which disabled any additional - buffering. (Yun Zheng Hu) + buffering. (Yun Zheng Hu/Robin Sommer) 2.4-14 | 2015-06-28 12:30:12 -0700 diff --git a/VERSION b/VERSION index 3ad6a68544..040781c5ce 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4-17 +2.4-19 diff --git a/src/Reassem.cc b/src/Reassem.cc index eb6a6a6c0d..bfac7f7a07 100644 --- a/src/Reassem.cc +++ b/src/Reassem.cc @@ -51,35 +51,34 @@ void Reassembler::CheckOverlap(DataBlock *head, DataBlock *tail, if ( ! head || ! tail ) return; - uint64 orig_seq = seq; - uint64 orig_upper = seq + len; - const u_char* orig_data = data; + uint64 upper = (seq + len); for ( DataBlock* b = head; b; b = b->next ) { - uint64 seq = orig_seq; - uint64 upper = orig_upper; - const u_char* data = orig_data; + uint64 nseq = seq; + uint64 nupper = upper; + const u_char* ndata = data; - if ( upper <= b->seq ) + if ( nupper <= b->seq ) continue; - if ( seq >= b->upper ) + if ( nseq >= b->upper ) continue; - if ( seq < b->seq ) + if ( nseq < b->seq ) { - data += (b->seq - seq); - seq = b->seq; + ndata += (b->seq - seq); + nseq = b->seq; } - if ( upper > b->upper ) - upper = b->upper; + if ( nupper > b->upper ) + nupper = b->upper; + + uint64 overlap_offset = (nseq - b->seq); + uint64 overlap_len = (nupper - nseq); - uint64 overlap_offset = seq - b->seq; - uint64 overlap_len = upper - seq; if ( overlap_len ) - Overlap(&b->block[overlap_offset], data, overlap_len); + Overlap(&b->block[overlap_offset], ndata, overlap_len); } } @@ -304,7 +303,7 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, uint64 seq, uint64 upper, return new_b; } - // The blocks overlap, complain. + // The blocks overlap. if ( seq < b->seq ) { // The new block has a prefix that comes before b. @@ -325,8 +324,6 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, uint64 seq, uint64 upper, uint64 b_len = b->upper - overlap_start; uint64 overlap_len = min(new_b_len, b_len); -// Overlap(&b->block[overlap_offset], data, overlap_len); - if ( overlap_len < new_b_len ) { // Recurse to resolve remainder of the new data. From 85b433b13f528de2366f6160dde5fe5899c42007 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 3 Jul 2015 10:40:21 -0700 Subject: [PATCH 11/26] Adding a weird for when truncated packets lead TCP reassembly to ignore content. (Private test suite has a bunch of test cases.) --- CHANGES | 5 +++++ VERSION | 2 +- src/analyzer/protocol/tcp/TCP_Endpoint.cc | 11 ++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 3f64d91489..8ec7593749 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.4-20 | 2015-07-03 10:40:21 -0700 + + * Adding a weird for when truncated packets lead TCP reassembly to + ignore content. (Robin Sommer) + 2.4-19 | 2015-07-03 09:04:54 -0700 * A set of tests exercising IP defragmentation and TCP reassembly. diff --git a/VERSION b/VERSION index 040781c5ce..748c727101 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4-19 +2.4-20 diff --git a/src/analyzer/protocol/tcp/TCP_Endpoint.cc b/src/analyzer/protocol/tcp/TCP_Endpoint.cc index 2e8d6e593b..846eb6d9d1 100644 --- a/src/analyzer/protocol/tcp/TCP_Endpoint.cc +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.cc @@ -201,13 +201,18 @@ int TCP_Endpoint::DataSent(double t, uint64 seq, int len, int caplen, { int status = 0; - if ( contents_processor && caplen >= len ) - status = contents_processor->DataSent(t, seq, len, data); + if ( contents_processor ) + { + if ( caplen >= len ) + status = contents_processor->DataSent(t, seq, len, data); + else + TCP()->Weird("truncated_tcp_payload"); + } if ( caplen <= 0 ) return status; - if ( contents_file && ! contents_processor && + if ( contents_file && ! contents_processor && seq + len > contents_start_seq ) { int64 under_seq = contents_start_seq - seq; From 8d8dc890ddd550942cc3ebb3336d96a5a6337e0b Mon Sep 17 00:00:00 2001 From: Justin Azoff Date: Fri, 10 Jul 2015 08:35:18 -0400 Subject: [PATCH 12/26] Correct perl package name on freebsd Based on feedback on IRC, the correct package name is 'perl5', not 'perl' --- doc/install/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/install.rst b/doc/install/install.rst index ab3f6cafc8..03b77fba8c 100644 --- a/doc/install/install.rst +++ b/doc/install/install.rst @@ -67,7 +67,7 @@ To install the required dependencies, you can use: .. console:: - sudo pkg install bash cmake swig bison python perl py27-sqlite3 + sudo pkg install bash cmake swig bison python perl5 py27-sqlite3 Note that in older versions of FreeBSD, you might have to use the "pkg_add -r" command instead of "pkg install". From 31dda4116959241e1334023762038cb6ebef5970 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 10 Jul 2015 07:15:40 -0700 Subject: [PATCH 13/26] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- aux/btest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aux/bro-aux b/aux/bro-aux index 6d6679506d..7eb2c58993 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 6d6679506d8762ddbba16f0b34f7ad253e3aac45 +Subproject commit 7eb2c589939eaedb8ccbefef73531f891edbd5d9 diff --git a/aux/btest b/aux/btest index 0e2da116a5..a89cd0fda0 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 0e2da116a5e29baacaecc6daac7bc4bc9ff387c5 +Subproject commit a89cd0fda0f17f69b96c935959cae89145b92927 From 8fb708b9b2fe43802169e37701dc0a64396f9053 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 13 Jul 2015 22:13:10 -0700 Subject: [PATCH 14/26] Adding an environemtn variable to btest.cfg for external scripts. --- testing/external/subdir-btest.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/external/subdir-btest.cfg b/testing/external/subdir-btest.cfg index b2b36bf84f..4315ade850 100644 --- a/testing/external/subdir-btest.cfg +++ b/testing/external/subdir-btest.cfg @@ -15,6 +15,7 @@ TEST_DIFF_CANONIFIER=%(testbase)s/../../scripts/diff-canonifier-external TEST_DIFF_BRIEF=1 TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts +SCRIPTS_LOCAL=%(testbase)s/scripts DIST=%(testbase)s/../../.. BUILD=%(testbase)s/../../../build BRO_PROFILER_FILE=%(testbase)s/.tmp/script-coverage.XXXXXX From 0d9869a2aae66a907db11bc4890be98a13da78ce Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Wed, 15 Jul 2015 09:14:36 -0700 Subject: [PATCH 15/26] (Hopefully) fix race condition between trace and intel file. --- .../scripts/policy/frameworks/intel/seen/certs.bro | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testing/btest/scripts/policy/frameworks/intel/seen/certs.bro b/testing/btest/scripts/policy/frameworks/intel/seen/certs.bro index afddc6b2d9..2ab4c6a50a 100644 --- a/testing/btest/scripts/policy/frameworks/intel/seen/certs.bro +++ b/testing/btest/scripts/policy/frameworks/intel/seen/certs.bro @@ -16,3 +16,13 @@ www.dresdner-privat.de Intel::DOMAIN source1 test entry http://some-data-distrib redef Intel::read_files += { "intel.dat" }; +event bro_init() + { + suspend_processing(); + } + +event Input::end_of_data(name: string, source: string) + { + continue_processing(); + } + From 924549bd4d7011e9b075d614ddcfa98d2e873ef2 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 15 Jul 2015 13:31:49 -0700 Subject: [PATCH 16/26] Updating submodule(s). [nomail] --- CHANGES | 4 ++++ VERSION | 2 +- aux/broker | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index a1953c959c..cea967fbae 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.4-27 | 2015-07-15 13:31:49 -0700 + + * Fix race condition in intel test. (Johanna Amann) + 2.4-24 | 2015-07-14 08:04:11 -0700 * Correct Perl package name on FreeBSD in documentation.(Justin Azoff) diff --git a/VERSION b/VERSION index 8be05d8e74..37158a481a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4-24 +2.4-27 diff --git a/aux/broker b/aux/broker index f303cdbc60..d25efc7d5f 160000 --- a/aux/broker +++ b/aux/broker @@ -1 +1 @@ -Subproject commit f303cdbc60ad6eef35ebcd1473ee85b3123f5ef1 +Subproject commit d25efc7d5f495c30294b11180c1857477078f2d6 From 5f072688056ddab87dd8871a695d8fa3054e3dfc Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Thu, 16 Jul 2015 16:39:21 -0700 Subject: [PATCH 17/26] Small changes to iana tls registry. --- scripts/base/protocols/ssl/consts.bro | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index 05559ee5d0..7a95d63cc6 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -120,9 +120,9 @@ export { [18] = "signed_certificate_timestamp", [19] = "client_certificate_type", [20] = "server_certificate_type", - [21] = "padding", # temporary till 2015-03-12 + [21] = "padding", # temporary till 2016-03-12 [22] = "encrypt_then_mac", - [23] = "extended_master_secret", # temporary till 2015-09-26 + [23] = "extended_master_secret", [35] = "SessionTicket TLS", [40] = "extended_random", [13172] = "next_protocol_negotiation", @@ -169,7 +169,8 @@ export { [256] = "ffdhe2048", [257] = "ffdhe3072", [258] = "ffdhe4096", - [259] = "ffdhe8192", + [259] = "ffdhe6144", + [260] = "ffdhe8192", [0xFF01] = "arbitrary_explicit_prime_curves", [0xFF02] = "arbitrary_explicit_char2_curves" } &default=function(i: count):string { return fmt("unknown-%d", i); }; From 86440e44fcae2c9c45fcc93e32e6eb95edc8610e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 17 Jul 2015 13:59:12 -0700 Subject: [PATCH 18/26] Adding more cross-checks for IP. This prevents a few more packets from reaching raw_events(), see baseline update for the corresponding test. --- src/iosource/PktSrc.cc | 57 ++++++++++++++++--- testing/btest/Baseline/core.raw_packet/output | 4 -- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 9ab6372af4..08af764506 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -289,8 +289,7 @@ void PktSrc::Process() // labels are in place. bool have_mpls = false; - int l3_proto = 0; - int protocol = 0; + int l3_proto = AF_UNSPEC; const u_char* data = current_packet.data; current_packet.link_type = props.link_type; @@ -298,7 +297,7 @@ void PktSrc::Process() switch ( props.link_type ) { case DLT_NULL: { - protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; + int protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; data += GetLinkHeaderSize(props.link_type); // From the Wireshark Wiki: "AF_INET6, unfortunately, has @@ -324,7 +323,7 @@ void PktSrc::Process() case DLT_EN10MB: { // Get protocol being carried from the ethernet frame. - protocol = (data[12] << 8) + data[13]; + int protocol = (data[12] << 8) + data[13]; data += GetLinkHeaderSize(props.link_type); current_packet.eth_type = protocol; @@ -375,6 +374,7 @@ void PktSrc::Process() Weird("non_ip_packet_in_pppoe_encapsulation", ¤t_packet); goto done; } + break; } @@ -385,6 +385,14 @@ void PktSrc::Process() l3_proto = AF_INET; else if ( protocol == 0x86dd ) l3_proto = AF_INET6; + else if ( protocol == 0x0806 || protocol == 0x8035 ) + l3_proto = AF_UNSPEC; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet_in_ethernet", ¤t_packet); + goto done; + } } break; @@ -393,7 +401,7 @@ void PktSrc::Process() case DLT_PPP_SERIAL: { // Get PPP protocol. - protocol = (data[2] << 8) + data[3]; + int protocol = (data[2] << 8) + data[3]; data += GetLinkHeaderSize(props.link_type); if ( protocol == 0x0281 ) @@ -420,7 +428,18 @@ void PktSrc::Process() // Assume we're pointing at IP. Just figure out which version. data += GetLinkHeaderSize(props.link_type); const struct ip* ip = (const struct ip *)data; - l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; + + if ( ip->ip_v == 4 ) + l3_proto = AF_INET; + else if ( ip->ip_v == 6 ) + l3_proto = AF_INET6; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet", ¤t_packet); + goto done; + } + break; } } @@ -450,7 +469,17 @@ void PktSrc::Process() } const struct ip* ip = (const struct ip *)data; - l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; + + if ( ip->ip_v == 4 ) + l3_proto = AF_INET; + else if ( ip->ip_v == 6 ) + l3_proto = AF_INET6; + else + { + // Neither IPv4 nor IPv6. + Weird("no_ip_in_mpls_payload", ¤t_packet); + goto done; + } } else if ( encap_hdr_size ) @@ -464,11 +493,23 @@ void PktSrc::Process() } const struct ip* ip = (const struct ip *)data; - l3_proto = ( ip->ip_v == 4 ) ? AF_INET : AF_INET6; + + if ( ip->ip_v == 4 ) + l3_proto = AF_INET; + else if ( ip->ip_v == 6 ) + l3_proto = AF_INET6; + else + { + // Neither IPv4 nor IPv6. + Weird("no_ip_in_encap", ¤t_packet); + goto done; + } + } // We've now determined (a) AF_INET (IPv4) vs (b) AF_INET6 (IPv6) vs // (c) AF_UNSPEC (0 == anything else) + assert(l3_proto == AF_INET || l3_proto == AF_INET6 || l3_proto == AF_UNSPEC); current_packet.l3_proto = l3_proto; // Calculate how much header we've used up. diff --git a/testing/btest/Baseline/core.raw_packet/output b/testing/btest/Baseline/core.raw_packet/output index a84f124f71..eeca545bf6 100644 --- a/testing/btest/Baseline/core.raw_packet/output +++ b/testing/btest/Baseline/core.raw_packet/output @@ -1,18 +1,15 @@ [l2=[encap=LINK_ETHERNET, len=215, cap_len=215, src=e8:de:27:ff:c0:78, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=201, id=0, ttl=64, p=17, src=192.168.1.1, dst=255.255.255.255], ip6=, tcp=, udp=[sport=40190/udp, dport=7437/udp, ulen=181], icmp=] [l2=[encap=LINK_ETHERNET, len=68, cap_len=68, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=54, id=52261, ttl=64, p=6, src=192.168.1.103, dst=64.4.23.176], ip6=, tcp=[sport=65493/tcp, dport=40031/tcp, seq=2642773190, ack=2891276360, hl=32, dl=2, flags=24, win=4096], udp=, icmp=] -[l2=[encap=LINK_ETHERNET, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=L3_UNKNOWN], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=78, cap_len=78, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=64, id=32575, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=65170/udp, dport=53/udp, ulen=44], icmp=] [l2=[encap=LINK_ETHERNET, len=78, cap_len=78, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=64, id=55466, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=53129/udp, dport=53/udp, ulen=44], icmp=] [l2=[encap=LINK_ETHERNET, len=92, cap_len=92, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=78, id=32240, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=53129/udp, dport=53/udp, ulen=58], icmp=] [l2=[encap=LINK_ETHERNET, len=85, cap_len=85, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=71, id=53895, ttl=64, p=17, src=192.168.1.103, dst=192.168.1.1], ip6=, tcp=, udp=[sport=57932/udp, dport=53/udp, ulen=51], icmp=] -[l2=[encap=LINK_ETHERNET, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=L3_UNKNOWN], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=307, cap_len=307, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=293, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=273], icmp=] [l2=[encap=LINK_ETHERNET, len=316, cap_len=316, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=302, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=282], icmp=] [l2=[encap=LINK_ETHERNET, len=379, cap_len=379, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=365, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=345], icmp=] [l2=[encap=LINK_ETHERNET, len=371, cap_len=371, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=357, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=337], icmp=] -[l2=[encap=LINK_ETHERNET, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=L3_UNKNOWN], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=355, cap_len=355, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=341, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=321], icmp=] [l2=[encap=LINK_ETHERNET, len=42, cap_len=42, src=00:50:56:3e:93:6b, dst=ff:ff:ff:ff:ff:ff, vlan=, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=387, cap_len=387, src=e8:de:27:ff:c0:78, dst=01:00:5e:7f:ff:fa, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=373, id=0, ttl=4, p=17, src=192.168.1.1, dst=239.255.255.250], ip6=, tcp=, udp=[sport=45335/udp, dport=1900/udp, ulen=353], icmp=] @@ -30,7 +27,6 @@ [l2=[encap=LINK_ETHERNET, len=112, cap_len=112, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=98, id=85, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176077, ack=445274652, hl=32, dl=46, flags=24, win=4096], udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=97, cap_len=97, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=83, id=28558, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176123, ack=445274652, hl=32, dl=31, flags=24, win=4096], udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=66, cap_len=66, src=60:f8:1d:c9:8c:fa, dst=e8:de:27:ff:c0:78, vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=52, id=36529, ttl=64, p=6, src=192.168.1.103, dst=74.125.21.138], ip6=, tcp=[sport=49171/tcp, dport=443/tcp, seq=3725176154, ack=445274652, hl=32, dl=0, flags=17, win=4096], udp=, icmp=] -[l2=[encap=LINK_ETHERNET, len=60, cap_len=60, src=e8:de:27:ff:c0:77, dst=01:80:c2:00:00:00, vlan=, eth_type=38, proto=L3_UNKNOWN], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=64, cap_len=64, src=00:19:06:ea:b8:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=64, cap_len=64, src=00:18:73:de:57:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] [l2=[encap=LINK_ETHERNET, len=64, cap_len=64, src=00:18:73:de:57:c1, dst=ff:ff:ff:ff:ff:ff, vlan=123, eth_type=2054, proto=L3_ARP], ip=, ip6=, tcp=, udp=, icmp=] From 64a478dbd50c08ff5006811ad4935c7017f4f88e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 17 Jul 2015 14:22:50 -0700 Subject: [PATCH 19/26] Determining final L3 layer protocol right inside PktSrc. --- src/Packet.h | 14 +++++++--- src/Serializer.cc | 2 +- src/Sessions.cc | 12 ++++----- src/analyzer/protocol/arp/ARP.cc | 19 ------------- src/analyzer/protocol/arp/ARP.h | 3 --- src/iosource/PktSrc.cc | 46 ++++++++++++++++---------------- 6 files changed, 41 insertions(+), 55 deletions(-) diff --git a/src/Packet.h b/src/Packet.h index 0177b1fc14..f1dd233be5 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -3,6 +3,14 @@ #include "Desc.h" #include "IP.h" +#include "NetVar.h" + +enum Layer3Proto { + L3_UNKNOWN = -1, + L3_IPV4 = 1, + L3_IPV6 = 2, + L3_ARP = 3, +}; // A link-layer packet. // @@ -26,7 +34,7 @@ public: Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, uint32 arg_len, const u_char *arg_data, int arg_free = false, std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - int arg_l3_proto = -1) + Layer3Proto arg_l3_proto = L3_UNKNOWN) { Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag, arg_hdrsize, arg_l3_proto); @@ -45,7 +53,7 @@ public: void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, uint32 arg_len, const u_char *arg_data, int arg_free = false, std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - int arg_l3_proto = -1) + Layer3Proto arg_l3_proto = L3_UNKNOWN) { link_type = arg_link_type; ts = *arg_ts; @@ -86,7 +94,7 @@ public: uint32 cap_len; /// Captured packet length uint32 len; /// Actual length on wire uint32 hdr_size; /// Layer 2 header size - uint32 l3_proto; /// Layer 3 protocol identified (if any) + Layer3Proto l3_proto; /// Layer 3 protocol identified (if any) uint32 eth_type; /// If L2==ethernet, innermost ethertype field uint32 vlan; /// (Outermost) VLan tag if any, else 0 diff --git a/src/Serializer.cc b/src/Serializer.cc index 54266de1d0..d45e572611 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1175,7 +1175,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) } Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, - std::string(tag), hdr_size, l3_proto); + std::string(tag), hdr_size, (Layer3Proto) l3_proto); delete [] tag; // For the global timer manager, we take the global network_time as the diff --git a/src/Sessions.cc b/src/Sessions.cc index 7574bc647b..db1944634a 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -206,7 +206,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt) uint32 caplen = pkt->cap_len - pkt->hdr_size; - if ( pkt->l3_proto == AF_INET ) + if ( pkt->l3_proto == L3_IPV4 ) { if ( caplen < sizeof(struct ip) ) { @@ -219,7 +219,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt) DoNextPacket(t, pkt, &ip_hdr, 0); } - else if ( pkt->l3_proto == AF_INET6 ) + else if ( pkt->l3_proto == L3_IPV6 ) { if ( caplen < sizeof(struct ip6_hdr) ) { @@ -231,7 +231,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt) DoNextPacket(t, pkt, &ip_hdr, 0); } - else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt) ) + else if ( pkt->l3_proto == L3_ARP ) { if ( arp_analyzer ) arp_analyzer->NextPacket(t, pkt); @@ -774,7 +774,7 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, struct timeval ts; int link_type; - int l3_proto; + Layer3Proto l3_proto; if ( pkt ) ts = pkt->ts; @@ -790,12 +790,12 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, if ( inner->IP4_Hdr() ) { data = (const u_char*) inner->IP4_Hdr(); - l3_proto = AF_INET; + l3_proto = L3_IPV4; } else { data = (const u_char*) inner->IP6_Hdr(); - l3_proto = AF_INET6; + l3_proto = L3_IPV6; } EncapsulationStack* outer = prev ? diff --git a/src/analyzer/protocol/arp/ARP.cc b/src/analyzer/protocol/arp/ARP.cc index ebe18dc599..5cbb25451b 100644 --- a/src/analyzer/protocol/arp/ARP.cc +++ b/src/analyzer/protocol/arp/ARP.cc @@ -19,25 +19,6 @@ ARP_Analyzer::~ARP_Analyzer() { } -// Assumes pkt->hdr_size indicates size of the Layer 2 header. -bool ARP_Analyzer::IsARP(const Packet* pkt) - { - if ( pkt->hdr_size < 2 ) - return false; - - unsigned short network_protocol = - *(unsigned short*) (pkt->data + pkt->hdr_size - 2); - - switch ( ntohs(network_protocol) ) { - case ETHERTYPE_ARP: - case ETHERTYPE_REVARP: - return true; - default: - return false; - } - } - - // Argh! FreeBSD and Linux have almost completely different net/if_arp.h . // ... and on Solaris we are missing half of the ARPOP codes, so define // them here as necessary: diff --git a/src/analyzer/protocol/arp/ARP.h b/src/analyzer/protocol/arp/ARP.h index 9f7142c846..d0b035ef24 100644 --- a/src/analyzer/protocol/arp/ARP.h +++ b/src/analyzer/protocol/arp/ARP.h @@ -44,9 +44,6 @@ public: const char* spa, const char* sha, const char* tpa, const char* tha); - // Whether a packet is of interest for ARP analysis. - static bool IsARP(const Packet *pkt); - protected: AddrVal* ConstructAddrVal(const void* addr); StringVal* EthAddrToStr(const u_char* addr); diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 08af764506..e22f8da6dd 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -289,7 +289,7 @@ void PktSrc::Process() // labels are in place. bool have_mpls = false; - int l3_proto = AF_UNSPEC; + Layer3Proto l3_proto = L3_UNKNOWN; const u_char* data = current_packet.data; current_packet.link_type = props.link_type; @@ -307,16 +307,17 @@ void PktSrc::Process() // as the AF_ value." As we may be reading traces captured on // platforms other than what we're running on, we accept them // all here. - if ( protocol == 24 || protocol == 28 || protocol == 30 ) - protocol = AF_INET6; - if ( protocol != AF_INET && protocol != AF_INET6 ) + if ( protocol == AF_INET ) + l3_proto = L3_IPV4; + else if ( protocol == 24 || protocol == 28 || protocol == 30 ) + l3_proto = L3_IPV6; + else { Weird("non_ip_packet_in_null_transport", ¤t_packet); goto done; } - l3_proto = protocol; break; } @@ -365,9 +366,9 @@ void PktSrc::Process() data += 8; // Skip the PPPoE session and PPP header if ( protocol == 0x0021 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( protocol == 0x0057 ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else { // Neither IPv4 nor IPv6. @@ -379,14 +380,14 @@ void PktSrc::Process() } // Normal path to determine Layer 3 protocol. - if ( ! have_mpls && ! l3_proto ) + if ( ! have_mpls && l3_proto == L3_UNKNOWN ) { if ( protocol == 0x800 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( protocol == 0x86dd ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else if ( protocol == 0x0806 || protocol == 0x8035 ) - l3_proto = AF_UNSPEC; + l3_proto = L3_ARP; else { // Neither IPv4 nor IPv6. @@ -411,9 +412,9 @@ void PktSrc::Process() have_mpls = true; } else if ( protocol == 0x0021 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( protocol == 0x0057 ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else { // Neither IPv4 nor IPv6. @@ -430,9 +431,9 @@ void PktSrc::Process() const struct ip* ip = (const struct ip *)data; if ( ip->ip_v == 4 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( ip->ip_v == 6 ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else { // Neither IPv4 nor IPv6. @@ -471,9 +472,9 @@ void PktSrc::Process() const struct ip* ip = (const struct ip *)data; if ( ip->ip_v == 4 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( ip->ip_v == 6 ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else { // Neither IPv4 nor IPv6. @@ -495,9 +496,9 @@ void PktSrc::Process() const struct ip* ip = (const struct ip *)data; if ( ip->ip_v == 4 ) - l3_proto = AF_INET; + l3_proto = L3_IPV4; else if ( ip->ip_v == 6 ) - l3_proto = AF_INET6; + l3_proto = L3_IPV6; else { // Neither IPv4 nor IPv6. @@ -507,9 +508,8 @@ void PktSrc::Process() } - // We've now determined (a) AF_INET (IPv4) vs (b) AF_INET6 (IPv6) vs - // (c) AF_UNSPEC (0 == anything else) - assert(l3_proto == AF_INET || l3_proto == AF_INET6 || l3_proto == AF_UNSPEC); + // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs + // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else) current_packet.l3_proto = l3_proto; // Calculate how much header we've used up. @@ -556,7 +556,7 @@ bool PktSrc::ExtractNextPacketInternal() if ( ExtractNextPacket(¤t_packet) ) { - current_packet.l3_proto = AF_UNSPEC; + current_packet.l3_proto = L3_UNKNOWN; if ( ! first_timestamp ) first_timestamp = current_packet.time; From c72d191ab5c960be94c9f516aa94ec214f54b0c7 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 20 Jul 2015 11:45:28 -0700 Subject: [PATCH 20/26] Refactoring L2 parsing code to reside in the Packet class. That way it can be reused more easily. This also avoid having to change the serialization structure for packets, which is a problem as external sources of packets (via Broccoli) wouldn't have the new attributes available to send. Also moving Packet.{h,cc} and Layer2.{h,cc} into iosource/, and removing header size from properties that packet sources have to provide, as we can now compute that easily from the link type. Plus some more cleanup. --- CHANGES | 8 + VERSION | 4 + src/CMakeLists.txt | 1 - src/Packet.h | 106 ------- src/RemoteSerializer.cc | 2 +- src/Serializer.cc | 12 +- src/Sessions.cc | 12 +- src/Sessions.h | 4 - src/analyzer/protocol/arp/ARP.h | 3 +- src/bro.bif | 2 +- src/event.bif | 12 +- src/iosource/CMakeLists.txt | 2 + src/iosource/PktSrc.cc | 284 +----------------- src/iosource/PktSrc.h | 23 -- src/iosource/pcap/Dumper.cc | 2 +- src/iosource/pcap/Source.cc | 2 +- .../btest/plugins/pktsrc-plugin/src/Foo.cc | 1 - 17 files changed, 43 insertions(+), 437 deletions(-) delete mode 100644 src/Packet.h diff --git a/CHANGES b/CHANGES index aefe5d7929..7902f9ea7f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,12 @@ +<<<<<<< HEAD +======= +2.4-39 | 2015-07-20 15:30:35 -0700 + + * Refactoring layer 2 parsing code to reside in the Packet class, + plus further layer 2 cleanup. (Robin Sommer) + +>>>>>>> c7602ac... Cleanup 2.4-32 | 2015-07-16 17:21:29 -0700 * Refactor code to use a common Packet type throught. (Jeff Barber) diff --git a/VERSION b/VERSION index 1116eda970..c281ab1728 100644 --- a/VERSION +++ b/VERSION @@ -1 +1,5 @@ +<<<<<<< HEAD 2.4-32 +======= +2.4-39 +>>>>>>> c7602ac... Cleanup diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f28d5d695..bdbd3839ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -297,7 +297,6 @@ set(bro_SRCS IntSet.cc IP.cc IPAddr.cc - Layer2.cc List.cc Reporter.cc NFA.cc diff --git a/src/Packet.h b/src/Packet.h deleted file mode 100644 index f1dd233be5..0000000000 --- a/src/Packet.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef packet_h -#define packet_h - -#include "Desc.h" -#include "IP.h" -#include "NetVar.h" - -enum Layer3Proto { - L3_UNKNOWN = -1, - L3_IPV4 = 1, - L3_IPV6 = 2, - L3_ARP = 3, -}; - -// A link-layer packet. -// -// Note that for serialization we don't use much of the support provided by -// the serialization framework. Serialize/Unserialize do all the work by -// themselves. In particular, Packets aren't derived from SerialObj. They are -// completely seperate and self-contained entities, and we don't need any of -// the sophisticated features like object caching. - -class Packet { -public: - Packet() - { - struct timeval ts = {0, 0}; - Init(0, &ts, 0, 0, 0); - } - // Construct and initialize from packet data. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - Layer3Proto arg_l3_proto = L3_UNKNOWN) - { - Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag, - arg_hdrsize, arg_l3_proto); - } - - ~Packet() - { - if ( free ) - delete [] data; - } - - // Initialize with data from pointer. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - Layer3Proto arg_l3_proto = L3_UNKNOWN) - { - link_type = arg_link_type; - ts = *arg_ts; - cap_len = arg_caplen; - len = arg_len; - free = arg_free; - - if ( free ) - { - data = new u_char[cap_len]; - memcpy(const_cast(data), arg_data, cap_len); - } - else - data = arg_data; - - hdr_size = arg_hdrsize; - l3_proto = arg_l3_proto; - tag = arg_tag; - time = ts.tv_sec + double(ts.tv_usec) / 1e6; - eth_type = 0; - vlan = 0; - } - - const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (data + hdr_size), false); } - - void Describe(ODesc* d) const; - - bool Serialize(SerialInfo* info) const; - static Packet* Unserialize(UnserialInfo* info); - - std::string tag; /// Used in serialization - double time; /// Timestamp reconstituted as float - - struct timeval ts; /// Capture timestamp - const u_char* data; /// Packet data. - uint32 link_type; /// pcap link_type (DLT_EN10MB, DLT_RAW, etc) - uint32 cap_len; /// Captured packet length - uint32 len; /// Actual length on wire - uint32 hdr_size; /// Layer 2 header size - Layer3Proto l3_proto; /// Layer 3 protocol identified (if any) - uint32 eth_type; /// If L2==ethernet, innermost ethertype field - uint32 vlan; /// (Outermost) VLan tag if any, else 0 - -private: - // should we delete associated packet memory upon destruction. - bool free; -}; - -#endif // packet_h diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 3c0dec4f20..44ec678a0f 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -200,7 +200,7 @@ extern "C" { // Gets incremented each time there's an incompatible change // to the communication internals. -static const unsigned short PROTOCOL_VERSION = 0x08; +static const unsigned short PROTOCOL_VERSION = 0x07; static const char MSG_NONE = 0x00; static const char MSG_VERSION = 0x01; diff --git a/src/Serializer.cc b/src/Serializer.cc index d45e572611..554e8b36b6 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1136,9 +1136,7 @@ bool Packet::Serialize(SerialInfo* info) const return SERIALIZE(uint32(ts.tv_sec)) && SERIALIZE(uint32(ts.tv_usec)) && SERIALIZE(uint32(len)) && - SERIALIZE(uint32(link_type)) && - SERIALIZE(uint32(hdr_size)) && - SERIALIZE(uint32(l3_proto)) && + SERIALIZE(link_type) && info->s->Write(tag.c_str(), tag.length(), "tag") && info->s->Write((const char*)data, cap_len, "data"); } @@ -1152,14 +1150,12 @@ static iosource::PktDumper* dump = 0; Packet* Packet::Unserialize(UnserialInfo* info) { struct timeval ts; - uint32 len, link_type, hdr_size, l3_proto; + uint32 len, link_type; if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) && UNSERIALIZE((uint32 *)&ts.tv_usec) && UNSERIALIZE(&len) && - UNSERIALIZE(&link_type) && - UNSERIALIZE(&hdr_size) && - UNSERIALIZE(&l3_proto)) ) + UNSERIALIZE(&link_type)) ) return 0; char* tag; @@ -1175,7 +1171,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) } Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, - std::string(tag), hdr_size, (Layer3Proto) l3_proto); + std::string(tag)); delete [] tag; // For the global timer manager, we take the global network_time as the diff --git a/src/Sessions.cc b/src/Sessions.cc index db1944634a..19f4f6104f 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -15,7 +15,7 @@ #include "Sessions.h" #include "Reporter.h" #include "OSFinger.h" -#include "Layer2.h" +#include "iosource/Layer2.h" #include "analyzer/protocol/icmp/ICMP.h" #include "analyzer/protocol/udp/UDP.h" @@ -169,11 +169,8 @@ void NetSessions::Done() void NetSessions::DispatchPacket(double t, const Packet* pkt, iosource::PktSrc* src_ps) { - NextPacket(t, pkt); - } + SegmentProfiler(segment_logger, "dispatching-packet"); -void NetSessions::NextPacket(double t, const Packet* pkt) - { if ( raw_packet ) { val_list* vl = new val_list(); @@ -185,9 +182,6 @@ void NetSessions::NextPacket(double t, const Packet* pkt) ProcNextPacket(t, pkt); } -void NetSessions::ProcNextPacket(double t, const Packet *pkt) - { - SegmentProfiler(segment_logger, "processing-packet"); if ( pkt_profiler ) pkt_profiler->ProfilePkt(t, pkt->cap_len); @@ -804,7 +798,7 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, // Construct fake packet for DoNextPacket Packet p; - p.Init(DLT_RAW, &ts, caplen, len, data, false, "", 0, l3_proto); + p.Init(DLT_RAW, &ts, caplen, len, data, false, ""); DoNextPacket(t, &p, inner, outer); delete inner; diff --git a/src/Sessions.h b/src/Sessions.h index 51539c42ef..6561b555e7 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -214,10 +214,6 @@ protected: TransportProto transport_proto, uint8 tcp_flags, bool& flip_roles); - void NextPacket(double t, const Packet* pkt); - - void ProcNextPacket(double t, const Packet *pkt); - // Record the given packet (if a dumper is active). If len=0 // then the whole packet is recorded, otherwise just the first // len bytes. diff --git a/src/analyzer/protocol/arp/ARP.h b/src/analyzer/protocol/arp/ARP.h index d0b035ef24..1778f5e200 100644 --- a/src/analyzer/protocol/arp/ARP.h +++ b/src/analyzer/protocol/arp/ARP.h @@ -24,7 +24,8 @@ #endif #include "NetVar.h" -#include "Packet.h" + +class Packet; extern "C" { #include diff --git a/src/bro.bif b/src/bro.bif index 9d3a2c42a8..629abe7735 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -20,9 +20,9 @@ #include "Reporter.h" #include "IPAddr.h" #include "util.h" -#include "Packet.h" #include "file_analysis/Manager.h" #include "iosource/Manager.h" +#include "iosource/Packet.h" using namespace std; diff --git a/src/event.bif b/src/event.bif index 7ba6fc2e1e..456de20b3a 100644 --- a/src/event.bif +++ b/src/event.bif @@ -225,21 +225,21 @@ event udp_session_done%(u: connection%); ## ``ANALYZER_*`` constants right now. event scheduled_analyzer_applied%(c: connection, a: Analyzer::Tag%); -## Generated for every packet Bro sees that has a valid link-layer header. This +## Generated for every packet Bro sees that have a valid link-layer header. This ## is a very 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 traffic in real-time. That said, if you work from a trace and want to do some -## packet-level analysis, it may come in handy. +## packet-level analysis, it may come in handy. ## ## p: Information from the header of the packet that triggered the event. ## ## .. bro:see:: new_packet packet_contents event raw_packet%(p: raw_pkt_hdr%); -## Generated for all packets that make it into Bro's connection processing . In -## contrast to :bro:id:`raw_packet` this filters out some packets that, e.g., don't -## pass certain sanity checks. -## +## Generated for all packets that make it into Bro's connection processing. In +## contrast to :bro:id:`raw_packet` this filters out some more packets that don't +## pass certain sanity checks. +## ## 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 traffic in real-time. That said, if you work from a trace and want to do some diff --git a/src/iosource/CMakeLists.txt b/src/iosource/CMakeLists.txt index a36667aee7..b08e62334a 100644 --- a/src/iosource/CMakeLists.txt +++ b/src/iosource/CMakeLists.txt @@ -11,7 +11,9 @@ add_subdirectory(pcap) set(iosource_SRCS BPF_Program.cc Component.cc + Layer2.cc Manager.cc + Packet.cc PktDumper.cc PktSrc.cc ) diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index e22f8da6dd..8012f79f1b 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -17,7 +17,6 @@ PktSrc::Properties::Properties() { selectable_fd = -1; link_type = -1; - hdr_size = -1; netmask = NETMASK_UNKNOWN; is_live = false; } @@ -67,11 +66,6 @@ bool PktSrc::IsError() const return ErrorMsg(); } -int PktSrc::HdrSize() const - { - return IsOpen() ? props.hdr_size : -1; - } - int PktSrc::SnapLen() const { return snaplen; // That's a global. Change? @@ -98,7 +92,7 @@ double PktSrc::CurrentPacketWallClock() void PktSrc::Opened(const Properties& arg_props) { - if ( arg_props.hdr_size < 0 ) + if ( Packet::GetLinkHeaderSize(arg_props.link_type) < 0 ) { char buf[512]; safe_snprintf(buf, sizeof(buf), @@ -160,33 +154,6 @@ void PktSrc::ContinueAfterSuspend() current_wallclock = current_time(true); } -int PktSrc::GetLinkHeaderSize(int link_type) - { - switch ( link_type ) { - case DLT_NULL: - return 4; - - case DLT_EN10MB: - return 14; - - case DLT_FDDI: - return 13 + 8; // fddi_header + LLC - -#ifdef DLT_LINUX_SLL - case DLT_LINUX_SLL: - return 16; -#endif - - case DLT_PPP_SERIAL: // PPP_SERIAL - return 4; - - case DLT_RAW: - return 0; - } - - return -1; - } - double PktSrc::CheckPseudoTime() { if ( ! IsOpen() ) @@ -284,249 +251,20 @@ void PktSrc::Process() if ( ! ExtractNextPacketInternal() ) return; - // Unfortunately some packets on the link might have MPLS labels - // while others don't. That means we need to ask the link-layer if - // labels are in place. - bool have_mpls = false; - - Layer3Proto l3_proto = L3_UNKNOWN; - const u_char* data = current_packet.data; - - current_packet.link_type = props.link_type; - - switch ( props.link_type ) { - case DLT_NULL: + if ( current_packet.Layer2Valid() ) { - int protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; - data += GetLinkHeaderSize(props.link_type); + if ( pseudo_realtime ) + { + current_pseudo = CheckPseudoTime(); + net_packet_dispatch(current_pseudo, ¤t_packet, this); + if ( ! first_wallclock ) + first_wallclock = current_time(true); + } - // From the Wireshark Wiki: "AF_INET6, unfortunately, has - // different values in {NetBSD,OpenBSD,BSD/OS}, - // {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6 - // packet might have a link-layer header with 24, 28, or 30 - // as the AF_ value." As we may be reading traces captured on - // platforms other than what we're running on, we accept them - // all here. - - if ( protocol == AF_INET ) - l3_proto = L3_IPV4; - else if ( protocol == 24 || protocol == 28 || protocol == 30 ) - l3_proto = L3_IPV6; else - { - Weird("non_ip_packet_in_null_transport", ¤t_packet); - goto done; - } - - break; + net_packet_dispatch(current_packet.time, ¤t_packet, this); } - case DLT_EN10MB: - { - // Get protocol being carried from the ethernet frame. - int protocol = (data[12] << 8) + data[13]; - data += GetLinkHeaderSize(props.link_type); - current_packet.eth_type = protocol; - - switch ( protocol ) - { - // MPLS carried over the ethernet frame. - case 0x8847: - have_mpls = true; - break; - - // VLAN carried over the ethernet frame. - // 802.1q / 802.1ad - case 0x8100: - case 0x9100: - current_packet.vlan = ((data[0] << 8) + data[1]) & 0xfff; - protocol = ((data[2] << 8) + data[3]); - data += 4; // Skip the vlan header - - // Check for MPLS in VLAN. - if ( protocol == 0x8847 ) - { - have_mpls = true; - break; - } - - // Check for double-tagged (802.1ad) - if ( protocol == 0x8100 || protocol == 0x9100 ) - { - protocol = ((data[2] << 8) + data[3]); - data += 4; // Skip the vlan header - } - - current_packet.eth_type = protocol; - break; - - // PPPoE carried over the ethernet frame. - case 0x8864: - protocol = (data[6] << 8) + data[7]; - data += 8; // Skip the PPPoE session and PPP header - - if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_pppoe_encapsulation", ¤t_packet); - goto done; - } - - break; - } - - // Normal path to determine Layer 3 protocol. - if ( ! have_mpls && l3_proto == L3_UNKNOWN ) - { - if ( protocol == 0x800 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x86dd ) - l3_proto = L3_IPV6; - else if ( protocol == 0x0806 || protocol == 0x8035 ) - l3_proto = L3_ARP; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ethernet", ¤t_packet); - goto done; - } - } - - break; - } - - case DLT_PPP_SERIAL: - { - // Get PPP protocol. - int protocol = (data[2] << 8) + data[3]; - data += GetLinkHeaderSize(props.link_type); - - if ( protocol == 0x0281 ) - { - // MPLS Unicast. Remove the data link layer and - // denote a header size of zero before the IP header. - have_mpls = true; - } - else if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ppp_encapsulation", ¤t_packet); - goto done; - } - break; - } - - default: - { - // Assume we're pointing at IP. Just figure out which version. - data += GetLinkHeaderSize(props.link_type); - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet", ¤t_packet); - goto done; - } - - break; - } - } - - if ( have_mpls ) - { - // Skip the MPLS label stack. - bool end_of_stack = false; - - while ( ! end_of_stack ) - { - end_of_stack = *(data + 2) & 0x01; - data += 4; - - if ( data >= current_packet.data + current_packet.cap_len ) - { - Weird("no_mpls_payload", ¤t_packet); - goto done; - } - } - - // We assume that what remains is IP - if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) - { - Weird("no_ip_in_mpls_payload", ¤t_packet); - goto done; - } - - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_mpls_payload", ¤t_packet); - goto done; - } - } - - else if ( encap_hdr_size ) - { - // Blanket encapsulation. We assume that what remains is IP. - data += encap_hdr_size; - if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) - { - Weird("no_ip_left_after_encap", ¤t_packet); - goto done; - } - - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_encap", ¤t_packet); - goto done; - } - - } - - // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs - // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else) - current_packet.l3_proto = l3_proto; - - // Calculate how much header we've used up. - current_packet.hdr_size = (data - current_packet.data); - - if ( pseudo_realtime ) - { - current_pseudo = CheckPseudoTime(); - net_packet_dispatch(current_pseudo, ¤t_packet, this); - if ( ! first_wallclock ) - first_wallclock = current_time(true); - } - - else - net_packet_dispatch(current_packet.time, ¤t_packet, this); - -done: have_packet = 0; DoneWithPacket(); } @@ -556,8 +294,6 @@ bool PktSrc::ExtractNextPacketInternal() if ( ExtractNextPacket(¤t_packet) ) { - current_packet.l3_proto = L3_UNKNOWN; - if ( ! first_timestamp ) first_timestamp = current_packet.time; diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index 0f20bb3a0a..bf4c811dca 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -215,22 +215,6 @@ public: */ virtual void Statistics(Stats* stats) = 0; - /** - * Helper method to return the header size for a given link tyoe. - * - * @param link_type The link tyoe. - * - * @return The header size in bytes. - */ - static int GetLinkHeaderSize(int link_type); - - /** - * Return the pcap link encapsulation type we started with. - * - * @return DLT_EN10MB (etc.) - */ - int GetLinkEncap(void); - protected: friend class Manager; @@ -258,13 +242,6 @@ protected: */ int link_type; - /** - * The size of the link-layer header for packets from this - * source. \a GetLinkHeaderSize() may be used to derive this - * value. - */ - int hdr_size; - /** * Returns the netmask associated with the source, or \c * NETMASK_UNKNOWN if unknown. diff --git a/src/iosource/pcap/Dumper.cc b/src/iosource/pcap/Dumper.cc index e6909f32b1..5bea6231f7 100644 --- a/src/iosource/pcap/Dumper.cc +++ b/src/iosource/pcap/Dumper.cc @@ -79,7 +79,7 @@ void PcapDumper::Open() } props.open_time = network_time; - props.hdr_size = PktSrc::GetLinkHeaderSize(pcap_datalink(pd)); + props.hdr_size = Packet::GetLinkHeaderSize(pcap_datalink(pd)); Opened(props); } diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 45e8c89298..bebe02c018 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -5,6 +5,7 @@ #include "config.h" #include "Source.h" +#include "iosource/Packet.h" #ifdef HAVE_PCAP_INT_H #include @@ -274,7 +275,6 @@ void PcapSource::SetHdrSize() char errbuf[PCAP_ERRBUF_SIZE]; props.link_type = pcap_datalink(pd); - props.hdr_size = GetLinkHeaderSize(props.link_type); } iosource::PktSrc* PcapSource::Instantiate(const std::string& path, bool is_live) diff --git a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc index afd5621d0f..af752a20bf 100644 --- a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc +++ b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc @@ -17,7 +17,6 @@ Foo::Foo(const std::string& path, bool is_live) props.path = path; props.selectable_fd = open("/bin/sh", O_RDONLY); // any fd is fine. props.link_type = DLT_RAW; - props.hdr_size = 0; props.netmask = 0; props.is_live = 0; } From fcf8cef949e3cbea440656e5459fdf13bb95bdb7 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 20 Jul 2015 14:51:37 -0700 Subject: [PATCH 21/26] Updating submodule(s). [nomail] --- CHANGES | 3 --- VERSION | 4 ---- aux/plugins | 2 +- src/Sessions.cc | 2 +- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 7902f9ea7f..ea22a725ee 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,9 @@ -<<<<<<< HEAD -======= 2.4-39 | 2015-07-20 15:30:35 -0700 * Refactoring layer 2 parsing code to reside in the Packet class, plus further layer 2 cleanup. (Robin Sommer) ->>>>>>> c7602ac... Cleanup 2.4-32 | 2015-07-16 17:21:29 -0700 * Refactor code to use a common Packet type throught. (Jeff Barber) diff --git a/VERSION b/VERSION index c281ab1728..134135de59 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1 @@ -<<<<<<< HEAD -2.4-32 -======= 2.4-39 ->>>>>>> c7602ac... Cleanup diff --git a/aux/plugins b/aux/plugins index f2f4e0a52c..98ad8a5b97 160000 --- a/aux/plugins +++ b/aux/plugins @@ -1 +1 @@ -Subproject commit f2f4e0a52c65d4ba4eb2673555e9e8f9e424cd41 +Subproject commit 98ad8a5b97f601a3ec9a773d87582438212b8290 diff --git a/src/Sessions.cc b/src/Sessions.cc index 19f4f6104f..0d4e42e534 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -576,7 +576,7 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 ) { - Weird("non_ip_packet_in_egre", ip_hdr, encapsulation); + Weird("non_ip_packet_in_encap", ip_hdr, encapsulation); return; } From f69edd1437584a581e6192f59d97b37a9d961015 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 20 Jul 2015 16:49:03 -0700 Subject: [PATCH 22/26] Adding missing files. --- src/iosource/Layer2.cc | 117 ++++++++++++++++++ src/iosource/Layer2.h | 33 +++++ src/iosource/Packet.cc | 270 +++++++++++++++++++++++++++++++++++++++++ src/iosource/Packet.h | 136 +++++++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 src/iosource/Layer2.cc create mode 100644 src/iosource/Layer2.h create mode 100644 src/iosource/Packet.cc create mode 100644 src/iosource/Packet.h diff --git a/src/iosource/Layer2.cc b/src/iosource/Layer2.cc new file mode 100644 index 0000000000..b7e8c508f3 --- /dev/null +++ b/src/iosource/Layer2.cc @@ -0,0 +1,117 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IP.h" +#include "Type.h" +#include "Val.h" +#include "Var.h" +#include "NetVar.h" +#include "iosource/Layer2.h" +#include "iosource/Packet.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NET_ETHERNET_H +#include +#elif defined(HAVE_SYS_ETHERNET_H) +#include +#elif defined(HAVE_NETINET_IF_ETHER_H) +#include +#elif defined(HAVE_NET_ETHERTYPES_H) +#include +#endif +} + + +Val *L2_Hdr::fmt_eui48(const u_char *mac) const + { + char buf[20]; + snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return new StringVal(buf); + } + +RecordVal* L2_Hdr::BuildPktHdrVal() const + { + static RecordType* l2_hdr_type = 0; + static RecordType* raw_pkt_hdr_type = 0; + + if ( ! raw_pkt_hdr_type ) + { + raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType(); + l2_hdr_type = internal_type("l2_hdr")->AsRecordType(); + } + + RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type); + RecordVal* l2_hdr = new RecordVal(l2_hdr_type); + + int is_ethernet = (pkt->link_type == DLT_EN10MB) ? 1 : 0; + + int l3 = BifEnum::L3_UNKNOWN; + + if ( pkt->l3_proto == L3_IPV4 ) + l3 = BifEnum::L3_IPV4; + + else if ( pkt->l3_proto == L3_IPV6 ) + l3 = BifEnum::L3_IPV6; + + else if ( pkt->l3_proto == L3_ARP ) + l3 = BifEnum::L3_ARP; + + // l2_hdr layout: + // encap: link_encap; ##< L2 link encapsulation + // len: count; ##< Total frame length on wire + // cap_len: count; ##< Captured length + // src: string &optional; ##< L2 source (if ethernet) + // dst: string &optional; ##< L2 destination (if ethernet) + // vlan: count &optional; ##< VLAN tag if any (and ethernet) + // ethertype: count &optional; ##< If ethernet + // proto: layer3_proto; ##< L3 proto + + if ( is_ethernet ) + { + // Ethernet header layout is: + // dst[6bytes] src[6bytes] ethertype[2bytes]... + l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_ETHERNET, BifType::Enum::link_encap)); + l2_hdr->Assign(3, fmt_eui48(pkt->data + 6)); // src + l2_hdr->Assign(4, fmt_eui48(pkt->data)); // dst + + if ( pkt->vlan ) + l2_hdr->Assign(5, new Val(pkt->vlan, TYPE_COUNT)); + + l2_hdr->Assign(6, new Val(pkt->eth_type, TYPE_COUNT)); + + if ( pkt->eth_type == ETHERTYPE_ARP || pkt->eth_type == ETHERTYPE_REVARP ) + // We also identify ARP for L3 over ethernet + l3 = BifEnum::L3_ARP; + } + else + l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_UNKNOWN, BifType::Enum::link_encap)); + + l2_hdr->Assign(1, new Val(pkt->len, TYPE_COUNT)); + l2_hdr->Assign(2, new Val(pkt->cap_len, TYPE_COUNT)); + + l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto)); + + pkt_hdr->Assign(0, l2_hdr); + + if ( pkt->l3_proto == L3_IPV4 ) + { + IP_Hdr ip_hdr((const struct ip*)(pkt->data + pkt->hdr_size), false); + return ip_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + + else if ( pkt->l3_proto == L3_IPV6 ) + { + IP_Hdr ip6_hdr((const struct ip6_hdr*)(pkt->data + pkt->hdr_size), false, pkt->cap_len); + return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + + else + return pkt_hdr; + } + diff --git a/src/iosource/Layer2.h b/src/iosource/Layer2.h new file mode 100644 index 0000000000..7152836ffc --- /dev/null +++ b/src/iosource/Layer2.h @@ -0,0 +1,33 @@ +#ifndef l2_h +#define l2_h + +#include "config.h" +#include "net_util.h" +#include "IP.h" +#include "Reporter.h" +#include "Val.h" +#include "Type.h" +#include + +class Packet; + +/** + * A class that wraps an L2 packet. + */ +class L2_Hdr { +public: + L2_Hdr(const Packet *arg_pkt) : pkt(arg_pkt) { } + ~L2_Hdr() { } + + /** + * Returns a raw_pkt_hdr RecordVal, which includes L2 and also + * everything in IP_Hdr (i.e. IP4/6 + tcp/udp/icmp) + */ + RecordVal* BuildPktHdrVal() const; + +private: + Val *fmt_eui48(const u_char *mac) const; + const Packet *pkt; +}; + +#endif diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc new file mode 100644 index 0000000000..41e5e31a8e --- /dev/null +++ b/src/iosource/Packet.cc @@ -0,0 +1,270 @@ + +#include "Packet.h" +#include "Sessions.h" + +void Packet::Weird(const char* name) + { + sessions->Weird(name, this); + l2_valid = false; + } + +int Packet::GetLinkHeaderSize(int link_type) + { + switch ( link_type ) { + case DLT_NULL: + return 4; + + case DLT_EN10MB: + return 14; + + case DLT_FDDI: + return 13 + 8; // fddi_header + LLC + +#ifdef DLT_LINUX_SLL + case DLT_LINUX_SLL: + return 16; +#endif + + case DLT_PPP_SERIAL: // PPP_SERIAL + return 4; + + case DLT_RAW: + return 0; + } + + return -1; + } + +void Packet::ProcessLayer2() + { + l2_valid = true; + + // Unfortunately some packets on the link might have MPLS labels + // while others don't. That means we need to ask the link-layer if + // labels are in place. + bool have_mpls = false; + + const u_char* pdata = data; + + switch ( link_type ) { + case DLT_NULL: + { + int protocol = (pdata[3] << 24) + (pdata[2] << 16) + (pdata[1] << 8) + pdata[0]; + pdata += GetLinkHeaderSize(link_type); + + // From the Wireshark Wiki: "AF_INET6, unfortunately, has + // different values in {NetBSD,OpenBSD,BSD/OS}, + // {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6 + // packet might have a link-layer header with 24, 28, or 30 + // as the AF_ value." As we may be reading traces captured on + // platforms other than what we're running on, we accept them + // all here. + + if ( protocol == AF_INET ) + l3_proto = L3_IPV4; + else if ( protocol == 24 || protocol == 28 || protocol == 30 ) + l3_proto = L3_IPV6; + else + { + Weird("non_ip_packet_in_null_transport"); + return; + } + + break; + } + + case DLT_EN10MB: + { + // Get protocol being carried from the ethernet frame. + int protocol = (pdata[12] << 8) + pdata[13]; + pdata += GetLinkHeaderSize(link_type); + eth_type = protocol; + + switch ( protocol ) + { + // MPLS carried over the ethernet frame. + case 0x8847: + have_mpls = true; + break; + + // VLAN carried over the ethernet frame. + // 802.1q / 802.1ad + case 0x8100: + case 0x9100: + vlan = ((pdata[0] << 8) + pdata[1]) & 0xfff; + protocol = ((pdata[2] << 8) + pdata[3]); + pdata += 4; // Skip the vlan header + + // Check for MPLS in VLAN. + if ( protocol == 0x8847 ) + { + have_mpls = true; + break; + } + + // Check for double-tagged (802.1ad) + if ( protocol == 0x8100 || protocol == 0x9100 ) + { + protocol = ((pdata[2] << 8) + pdata[3]); + pdata += 4; // Skip the vlan header + } + + eth_type = protocol; + break; + + // PPPoE carried over the ethernet frame. + case 0x8864: + protocol = (pdata[6] << 8) + pdata[7]; + pdata += 8; // Skip the PPPoE session and PPP header + + if ( protocol == 0x0021 ) + l3_proto = L3_IPV4; + else if ( protocol == 0x0057 ) + l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet_in_pppoe_encapsulation"); + return; + } + + break; + } + + // Normal path to determine Layer 3 protocol. + if ( ! have_mpls && l3_proto == L3_UNKNOWN ) + { + if ( protocol == 0x800 ) + l3_proto = L3_IPV4; + else if ( protocol == 0x86dd ) + l3_proto = L3_IPV6; + else if ( protocol == 0x0806 || protocol == 0x8035 ) + l3_proto = L3_ARP; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet_in_ethernet"); + return; + } + } + + break; + } + + case DLT_PPP_SERIAL: + { + // Get PPP protocol. + int protocol = (pdata[2] << 8) + pdata[3]; + pdata += GetLinkHeaderSize(link_type); + + if ( protocol == 0x0281 ) + { + // MPLS Unicast. Remove the pdata link layer and + // denote a header size of zero before the IP header. + have_mpls = true; + } + else if ( protocol == 0x0021 ) + l3_proto = L3_IPV4; + else if ( protocol == 0x0057 ) + l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet_in_ppp_encapsulation"); + return; + } + break; + } + + default: + { + // Assume we're pointing at IP. Just figure out which version. + pdata += GetLinkHeaderSize(link_type); + const struct ip* ip = (const struct ip *)pdata; + + if ( ip->ip_v == 4 ) + l3_proto = L3_IPV4; + else if ( ip->ip_v == 6 ) + l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + Weird("non_ip_packet"); + return; + } + + break; + } + } + + if ( have_mpls ) + { + // Skip the MPLS label stack. + bool end_of_stack = false; + + while ( ! end_of_stack ) + { + end_of_stack = *(pdata + 2) & 0x01; + pdata += 4; + + if ( pdata >= pdata + cap_len ) + { + Weird("no_mpls_payload"); + return; + } + } + + // We assume that what remains is IP + if ( pdata + sizeof(struct ip) >= data + cap_len ) + { + Weird("no_ip_in_mpls_payload"); + return; + } + + const struct ip* ip = (const struct ip *)pdata; + + if ( ip->ip_v == 4 ) + l3_proto = L3_IPV4; + else if ( ip->ip_v == 6 ) + l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + Weird("no_ip_in_mpls_payload"); + return; + } + } + + else if ( encap_hdr_size ) + { + // Blanket encapsulation. We assume that what remains is IP. + pdata += encap_hdr_size; + if ( pdata + sizeof(struct ip) >= data + cap_len ) + { + Weird("no_ip_left_after_encap"); + return; + } + + const struct ip* ip = (const struct ip *)pdata; + + if ( ip->ip_v == 4 ) + l3_proto = L3_IPV4; + else if ( ip->ip_v == 6 ) + l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + Weird("no_ip_in_encap"); + return; + } + + } + + // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs + // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else) + l3_proto = l3_proto; + + // Calculate how much header we've used up. + hdr_size = (pdata - data); +} + diff --git a/src/iosource/Packet.h b/src/iosource/Packet.h new file mode 100644 index 0000000000..f4f4c01709 --- /dev/null +++ b/src/iosource/Packet.h @@ -0,0 +1,136 @@ +#ifndef packet_h +#define packet_h + +#include "Desc.h" +#include "IP.h" +#include "NetVar.h" + +enum Layer3Proto { + L3_UNKNOWN = -1, + L3_IPV4 = 1, + L3_IPV6 = 2, + L3_ARP = 3, +}; + +// A link-layer packet. +// +// Note that for serialization we don't use much of the support provided by +// the serialization framework. Serialize/Unserialize do all the work by +// themselves. In particular, Packets aren't derived from SerialObj. They are +// completely seperate and self-contained entities, and we don't need any of +// the sophisticated features like object caching. + +class Packet { +public: + Packet() + { + struct timeval ts = {0, 0}; + Init(0, &ts, 0, 0, 0); + } + // Construct and initialize from packet data. + // + // arg_free: If true makes an internal copy of the *data*. If false, + // stores just a pointer to *data*, which must remain valid. + Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, + uint32 arg_len, const u_char *arg_data, int arg_free = false, + std::string arg_tag = std::string("")) + { + Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag); + } + + ~Packet() + { + if ( free ) + delete [] data; + } + + // Initialize with data from pointer. + // + // arg_free: If true makes an internal copy of the *data*. If false, + // stores just a pointer to *data*, which must remain valid. + void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, + uint32 arg_len, const u_char *arg_data, int arg_free = false, + std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0) + { + link_type = arg_link_type; + ts = *arg_ts; + cap_len = arg_caplen; + len = arg_len; + free = arg_free; + + if ( free ) + { + data = new u_char[cap_len]; + memcpy(const_cast(data), arg_data, cap_len); + } + else + data = arg_data; + + hdr_size = arg_hdrsize; + l3_proto = L3_UNKNOWN; + tag = arg_tag; + time = ts.tv_sec + double(ts.tv_usec) / 1e6; + eth_type = 0; + vlan = 0; + + l2_valid = false; + + if ( data ) + ProcessLayer2(); + } + + const IP_Hdr IP() const + { return IP_Hdr((struct ip *) (data + hdr_size), false); } + + // Returns true if parsing the Layer 2 fields failed, including when + // no data was passed into the constructor in the first place. + bool Layer2Valid() + { + return l2_valid; + } + + void Describe(ODesc* d) const; + + /** + * Helper method to return the header size for a given link tyoe. + * + * @param link_type The link tyoe. + * + * @return The header size in bytes, or -1 if not known. + */ + static int GetLinkHeaderSize(int link_type); + + bool Serialize(SerialInfo* info) const; + static Packet* Unserialize(UnserialInfo* info); + + // These are passed in through the constructor. + std::string tag; /// Used in serialization + double time; /// Timestamp reconstituted as float + struct timeval ts; /// Capture timestamp + const u_char* data; /// Packet data. + uint32 len; /// Actual length on wire + uint32 cap_len; /// Captured packet length + uint32 link_type; /// pcap link_type (DLT_EN10MB, DLT_RAW, etc) + + // These are computed from Layer 2 data. These fields are only valid if + // Layer2Valid() returns true. + uint32 hdr_size; /// Layer 2 header size + Layer3Proto l3_proto; /// Layer 3 protocol identified (if any) + uint32 eth_type; /// If L2==ethernet, innermost ethertype field + uint32 vlan; /// (Outermost) VLan tag if any, else 0 + +private: + // Calculate layer 2 attributes. Sets + void ProcessLayer2(); + + // Wrapper to generate a packet-level weird. + void Weird(const char* name); + + // should we delete associated packet memory upon destruction. + bool free; + + // True if L2 processing succeeded. + bool l2_valid; +}; + +#endif // packet_h From f97b2b180c4e1b8154345fcb8f1ded7f1602d567 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 21 Jul 2015 07:37:04 -0700 Subject: [PATCH 23/26] Moving the remaining code from Layer2.* into Packet.* and documenting the Packet API. Plus, some more cleanup, including removing a legacy option time_machine_profiling. --- src/Net.cc | 2 +- src/NetVar.cc | 3 - src/NetVar.h | 2 - src/Serializer.cc | 84 --------------- src/Sessions.cc | 10 +- src/Sessions.h | 7 +- src/iosource/CMakeLists.txt | 1 - src/iosource/Layer2.cc | 117 -------------------- src/iosource/Layer2.h | 33 ------ src/iosource/Packet.cc | 209 +++++++++++++++++++++++++++++++++++- src/iosource/Packet.h | 208 +++++++++++++++++++++++------------ 11 files changed, 350 insertions(+), 326 deletions(-) delete mode 100644 src/iosource/Layer2.cc delete mode 100644 src/iosource/Layer2.h diff --git a/src/Net.cc b/src/Net.cc index c63d706ef4..2a368c47ef 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -270,7 +270,7 @@ void net_packet_dispatch(double t, const Packet* pkt, iosource::PktSrc* src_ps) } } - sessions->DispatchPacket(t, pkt, src_ps); + sessions->NextPacket(t, pkt); mgr.Drain(); if ( sp ) diff --git a/src/NetVar.cc b/src/NetVar.cc index dc049005bb..5585cf8211 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -226,8 +226,6 @@ int suppress_local_output; double timer_mgr_inactivity_timeout; -int time_machine_profiling; - StringVal* trace_output_file; int record_all_packets; @@ -522,7 +520,6 @@ void init_net_var() timer_mgr_inactivity_timeout = opt_internal_double("timer_mgr_inactivity_timeout"); - time_machine_profiling = opt_internal_int("time_machine_profiling"); script_id = internal_type("script_id")->AsRecordType(); id_table = internal_type("id_table")->AsTableType(); diff --git a/src/NetVar.h b/src/NetVar.h index efadaaad6d..97018121f9 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -230,8 +230,6 @@ extern int suppress_local_output; extern double timer_mgr_inactivity_timeout; -extern int time_machine_profiling; - extern StringVal* trace_output_file; extern int record_all_packets; diff --git a/src/Serializer.cc b/src/Serializer.cc index 554e8b36b6..49e57c0216 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1122,87 +1122,3 @@ void EventPlayer::Process() ne_time = 0; } - -void Packet::Describe(ODesc* d) const - { - const IP_Hdr ip = IP(); - d->Add(ip.SrcAddr()); - d->Add("->"); - d->Add(ip.DstAddr()); - } - -bool Packet::Serialize(SerialInfo* info) const - { - return SERIALIZE(uint32(ts.tv_sec)) && - SERIALIZE(uint32(ts.tv_usec)) && - SERIALIZE(uint32(len)) && - SERIALIZE(link_type) && - info->s->Write(tag.c_str(), tag.length(), "tag") && - info->s->Write((const char*)data, cap_len, "data"); - } - -static BroFile* profiling_output = 0; - -#ifdef DEBUG -static iosource::PktDumper* dump = 0; -#endif - -Packet* Packet::Unserialize(UnserialInfo* info) - { - struct timeval ts; - uint32 len, link_type; - - if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) && - UNSERIALIZE((uint32 *)&ts.tv_usec) && - UNSERIALIZE(&len) && - UNSERIALIZE(&link_type)) ) - return 0; - - char* tag; - if ( ! info->s->Read((char**) &tag, 0, "tag") ) - return 0; - - const u_char* pkt; - int caplen; - if ( ! info->s->Read((char**) &pkt, &caplen, "data") ) - { - delete [] tag; - return 0; - } - - Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, - std::string(tag)); - delete [] tag; - - // For the global timer manager, we take the global network_time as the - // packet's timestamp for feeding it into our packet loop. - if ( p->tag == "" ) - p->time = timer_mgr->Time(); - else - p->time = p->ts.tv_sec + double(p->ts.tv_usec) / 1e6; - - if ( time_machine_profiling ) - { - if ( ! profiling_output ) - profiling_output = - new BroFile("tm-prof.packets.log", "w"); - - profiling_output->Write(fmt("%.6f %s %d\n", current_time(), - (p->tag != "" ? p->tag.c_str() : "-"), p->len)); - } - -#ifdef DEBUG - if ( debug_logger.IsEnabled(DBG_TM) ) - { - if ( ! dump ) - dump = iosource_mgr->OpenPktDumper("tm.pcap", true); - - if ( dump ) - { - dump->Dump(p); - } - } -#endif - - return p; - } diff --git a/src/Sessions.cc b/src/Sessions.cc index 0d4e42e534..7b7974bfce 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -15,7 +15,6 @@ #include "Sessions.h" #include "Reporter.h" #include "OSFinger.h" -#include "iosource/Layer2.h" #include "analyzer/protocol/icmp/ICMP.h" #include "analyzer/protocol/udp/UDP.h" @@ -166,22 +165,17 @@ void NetSessions::Done() { } -void NetSessions::DispatchPacket(double t, const Packet* pkt, - iosource::PktSrc* src_ps) +void NetSessions::NextPacket(double t, const Packet* pkt) { SegmentProfiler(segment_logger, "dispatching-packet"); if ( raw_packet ) { val_list* vl = new val_list(); - L2_Hdr l2_hdr(pkt); - vl->append(l2_hdr.BuildPktHdrVal()); + vl->append(pkt->BuildPktHdrVal()); mgr.QueueEvent(raw_packet, vl); } - ProcNextPacket(t, pkt); - } - if ( pkt_profiler ) pkt_profiler->ProfilePkt(t, pkt->cap_len); diff --git a/src/Sessions.h b/src/Sessions.h index 6561b555e7..1780bbdb24 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -66,11 +66,8 @@ public: NetSessions(); ~NetSessions(); - // Main entry point for packet processing. Dispatches the packet - // either through NextPacket(), optionally employing the packet - // sorter first. - void DispatchPacket(double t, const Packet* pkt, - iosource::PktSrc* src_ps); + // Main entry point for packet processing. + void NextPacket(double t, const Packet* pkt); void Done(); // call to drain events before destructing diff --git a/src/iosource/CMakeLists.txt b/src/iosource/CMakeLists.txt index b08e62334a..b1de9bddaf 100644 --- a/src/iosource/CMakeLists.txt +++ b/src/iosource/CMakeLists.txt @@ -11,7 +11,6 @@ add_subdirectory(pcap) set(iosource_SRCS BPF_Program.cc Component.cc - Layer2.cc Manager.cc Packet.cc PktDumper.cc diff --git a/src/iosource/Layer2.cc b/src/iosource/Layer2.cc deleted file mode 100644 index b7e8c508f3..0000000000 --- a/src/iosource/Layer2.cc +++ /dev/null @@ -1,117 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "IP.h" -#include "Type.h" -#include "Val.h" -#include "Var.h" -#include "NetVar.h" -#include "iosource/Layer2.h" -#include "iosource/Packet.h" - -extern "C" { -#include -#include -#include -#include -#include -#include -#ifdef HAVE_NET_ETHERNET_H -#include -#elif defined(HAVE_SYS_ETHERNET_H) -#include -#elif defined(HAVE_NETINET_IF_ETHER_H) -#include -#elif defined(HAVE_NET_ETHERTYPES_H) -#include -#endif -} - - -Val *L2_Hdr::fmt_eui48(const u_char *mac) const - { - char buf[20]; - snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return new StringVal(buf); - } - -RecordVal* L2_Hdr::BuildPktHdrVal() const - { - static RecordType* l2_hdr_type = 0; - static RecordType* raw_pkt_hdr_type = 0; - - if ( ! raw_pkt_hdr_type ) - { - raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType(); - l2_hdr_type = internal_type("l2_hdr")->AsRecordType(); - } - - RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type); - RecordVal* l2_hdr = new RecordVal(l2_hdr_type); - - int is_ethernet = (pkt->link_type == DLT_EN10MB) ? 1 : 0; - - int l3 = BifEnum::L3_UNKNOWN; - - if ( pkt->l3_proto == L3_IPV4 ) - l3 = BifEnum::L3_IPV4; - - else if ( pkt->l3_proto == L3_IPV6 ) - l3 = BifEnum::L3_IPV6; - - else if ( pkt->l3_proto == L3_ARP ) - l3 = BifEnum::L3_ARP; - - // l2_hdr layout: - // encap: link_encap; ##< L2 link encapsulation - // len: count; ##< Total frame length on wire - // cap_len: count; ##< Captured length - // src: string &optional; ##< L2 source (if ethernet) - // dst: string &optional; ##< L2 destination (if ethernet) - // vlan: count &optional; ##< VLAN tag if any (and ethernet) - // ethertype: count &optional; ##< If ethernet - // proto: layer3_proto; ##< L3 proto - - if ( is_ethernet ) - { - // Ethernet header layout is: - // dst[6bytes] src[6bytes] ethertype[2bytes]... - l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_ETHERNET, BifType::Enum::link_encap)); - l2_hdr->Assign(3, fmt_eui48(pkt->data + 6)); // src - l2_hdr->Assign(4, fmt_eui48(pkt->data)); // dst - - if ( pkt->vlan ) - l2_hdr->Assign(5, new Val(pkt->vlan, TYPE_COUNT)); - - l2_hdr->Assign(6, new Val(pkt->eth_type, TYPE_COUNT)); - - if ( pkt->eth_type == ETHERTYPE_ARP || pkt->eth_type == ETHERTYPE_REVARP ) - // We also identify ARP for L3 over ethernet - l3 = BifEnum::L3_ARP; - } - else - l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_UNKNOWN, BifType::Enum::link_encap)); - - l2_hdr->Assign(1, new Val(pkt->len, TYPE_COUNT)); - l2_hdr->Assign(2, new Val(pkt->cap_len, TYPE_COUNT)); - - l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto)); - - pkt_hdr->Assign(0, l2_hdr); - - if ( pkt->l3_proto == L3_IPV4 ) - { - IP_Hdr ip_hdr((const struct ip*)(pkt->data + pkt->hdr_size), false); - return ip_hdr.BuildPktHdrVal(pkt_hdr, 1); - } - - else if ( pkt->l3_proto == L3_IPV6 ) - { - IP_Hdr ip6_hdr((const struct ip6_hdr*)(pkt->data + pkt->hdr_size), false, pkt->cap_len); - return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1); - } - - else - return pkt_hdr; - } - diff --git a/src/iosource/Layer2.h b/src/iosource/Layer2.h deleted file mode 100644 index 7152836ffc..0000000000 --- a/src/iosource/Layer2.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef l2_h -#define l2_h - -#include "config.h" -#include "net_util.h" -#include "IP.h" -#include "Reporter.h" -#include "Val.h" -#include "Type.h" -#include - -class Packet; - -/** - * A class that wraps an L2 packet. - */ -class L2_Hdr { -public: - L2_Hdr(const Packet *arg_pkt) : pkt(arg_pkt) { } - ~L2_Hdr() { } - - /** - * Returns a raw_pkt_hdr RecordVal, which includes L2 and also - * everything in IP_Hdr (i.e. IP4/6 + tcp/udp/icmp) - */ - RecordVal* BuildPktHdrVal() const; - -private: - Val *fmt_eui48(const u_char *mac) const; - const Packet *pkt; -}; - -#endif diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc index 41e5e31a8e..2ff910ed52 100644 --- a/src/iosource/Packet.cc +++ b/src/iosource/Packet.cc @@ -1,6 +1,54 @@ #include "Packet.h" #include "Sessions.h" +#include "iosource/Manager.h" + +extern "C" { +#ifdef HAVE_NET_ETHERNET_H +#include +#elif defined(HAVE_SYS_ETHERNET_H) +#include +#elif defined(HAVE_NETINET_IF_ETHER_H) +#include +#elif defined(HAVE_NET_ETHERTYPES_H) +#include +#endif +} + +void Packet::Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, + uint32 arg_len, const u_char *arg_data, int arg_copy, + std::string arg_tag) + { + if ( data && copy ) + delete [] data; + + link_type = arg_link_type; + ts = *arg_ts; + cap_len = arg_caplen; + len = arg_len; + tag = arg_tag; + + copy = arg_copy; + + if ( arg_data && arg_copy ) + { + data = new u_char[arg_caplen]; + memcpy(const_cast(data), arg_data, arg_caplen); + } + else + data = arg_data; + + time = ts.tv_sec + double(ts.tv_usec) / 1e6; + hdr_size = GetLinkHeaderSize(arg_link_type); + l3_proto = L3_UNKNOWN; + eth_type = 0; + vlan = 0; + + l2_valid = false; + + if ( data ) + ProcessLayer2(); + } void Packet::Weird(const char* name) { @@ -261,10 +309,169 @@ void Packet::ProcessLayer2() } // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs - // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else) + // (c) L3_ARP vs (d) L3_UNKNOWN. l3_proto = l3_proto; // Calculate how much header we've used up. hdr_size = (pdata - data); } +RecordVal* Packet::BuildPktHdrVal() const + { + static RecordType* l2_hdr_type = 0; + static RecordType* raw_pkt_hdr_type = 0; + + if ( ! raw_pkt_hdr_type ) + { + raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType(); + l2_hdr_type = internal_type("l2_hdr")->AsRecordType(); + } + + RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type); + RecordVal* l2_hdr = new RecordVal(l2_hdr_type); + + int is_ethernet = (link_type == DLT_EN10MB) ? 1 : 0; + + int l3 = BifEnum::L3_UNKNOWN; + + if ( l3_proto == L3_IPV4 ) + l3 = BifEnum::L3_IPV4; + + else if ( l3_proto == L3_IPV6 ) + l3 = BifEnum::L3_IPV6; + + else if ( l3_proto == L3_ARP ) + l3 = BifEnum::L3_ARP; + + // l2_hdr layout: + // encap: link_encap; ##< L2 link encapsulation + // len: count; ##< Total frame length on wire + // cap_len: count; ##< Captured length + // src: string &optional; ##< L2 source (if ethernet) + // dst: string &optional; ##< L2 destination (if ethernet) + // vlan: count &optional; ##< VLAN tag if any (and ethernet) + // ethertype: count &optional; ##< If ethernet + // proto: layer3_proto; ##< L3 proto + + if ( is_ethernet ) + { + // Ethernet header layout is: + // dst[6bytes] src[6bytes] ethertype[2bytes]... + l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_ETHERNET, BifType::Enum::link_encap)); + l2_hdr->Assign(3, FmtEUI48(data + 6)); // src + l2_hdr->Assign(4, FmtEUI48(data)); // dst + + if ( vlan ) + l2_hdr->Assign(5, new Val(vlan, TYPE_COUNT)); + + l2_hdr->Assign(6, new Val(eth_type, TYPE_COUNT)); + + if ( eth_type == ETHERTYPE_ARP || eth_type == ETHERTYPE_REVARP ) + // We also identify ARP for L3 over ethernet + l3 = BifEnum::L3_ARP; + } + else + l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_UNKNOWN, BifType::Enum::link_encap)); + + l2_hdr->Assign(1, new Val(len, TYPE_COUNT)); + l2_hdr->Assign(2, new Val(cap_len, TYPE_COUNT)); + + l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto)); + + pkt_hdr->Assign(0, l2_hdr); + + if ( l3_proto == L3_IPV4 ) + { + IP_Hdr ip_hdr((const struct ip*)(data + hdr_size), false); + return ip_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + + else if ( l3_proto == L3_IPV6 ) + { + IP_Hdr ip6_hdr((const struct ip6_hdr*)(data + hdr_size), false, cap_len); + return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1); + } + + else + return pkt_hdr; + } + +Val *Packet::FmtEUI48(const u_char *mac) const + { + char buf[20]; + snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return new StringVal(buf); + } + +void Packet::Describe(ODesc* d) const + { + const IP_Hdr ip = IP(); + d->Add(ip.SrcAddr()); + d->Add("->"); + d->Add(ip.DstAddr()); + } + +bool Packet::Serialize(SerialInfo* info) const + { + return SERIALIZE(uint32(ts.tv_sec)) && + SERIALIZE(uint32(ts.tv_usec)) && + SERIALIZE(uint32(len)) && + SERIALIZE(link_type) && + info->s->Write(tag.c_str(), tag.length(), "tag") && + info->s->Write((const char*)data, cap_len, "data"); + } + +#ifdef DEBUG +static iosource::PktDumper* dump = 0; +#endif + +Packet* Packet::Unserialize(UnserialInfo* info) + { + struct timeval ts; + uint32 len, link_type; + + if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) && + UNSERIALIZE((uint32 *)&ts.tv_usec) && + UNSERIALIZE(&len) && + UNSERIALIZE(&link_type)) ) + return 0; + + char* tag; + if ( ! info->s->Read((char**) &tag, 0, "tag") ) + return 0; + + const u_char* pkt; + int caplen; + if ( ! info->s->Read((char**) &pkt, &caplen, "data") ) + { + delete [] tag; + return 0; + } + + Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, + std::string(tag)); + delete [] tag; + + // For the global timer manager, we take the global network_time as the + // packet's timestamp for feeding it into our packet loop. + if ( p->tag == "" ) + p->time = timer_mgr->Time(); + else + p->time = p->ts.tv_sec + double(p->ts.tv_usec) / 1e6; + +#ifdef DEBUG + if ( debug_logger.IsEnabled(DBG_TM) ) + { + if ( ! dump ) + dump = iosource_mgr->OpenPktDumper("tm.pcap", true); + + if ( dump ) + { + dump->Dump(p); + } + } +#endif + + return p; + } diff --git a/src/iosource/Packet.h b/src/iosource/Packet.h index f4f4c01709..eaa1b90210 100644 --- a/src/iosource/Packet.h +++ b/src/iosource/Packet.h @@ -5,94 +5,125 @@ #include "IP.h" #include "NetVar.h" +/** + * The Layer 3 type of a packet, as determined by the parsing code in Packet. + */ enum Layer3Proto { - L3_UNKNOWN = -1, - L3_IPV4 = 1, - L3_IPV6 = 2, - L3_ARP = 3, + L3_UNKNOWN = -1, /// Layer 3 type could not be determined. + L3_IPV4 = 1, /// Layer 3 is IPv4. + L3_IPV6 = 2, /// Layer 3 is IPv6. + L3_ARP = 3, /// Layer 3 is ARP. }; -// A link-layer packet. -// -// Note that for serialization we don't use much of the support provided by -// the serialization framework. Serialize/Unserialize do all the work by -// themselves. In particular, Packets aren't derived from SerialObj. They are -// completely seperate and self-contained entities, and we don't need any of -// the sophisticated features like object caching. - +/** + * A link-layer packet. + * + * Note that for serialization we don't use much of the support provided by + * the serialization framework. Serialize/Unserialize do all the work by + * themselves. In particular, Packets aren't derived from SerialObj. They are + * completely seperate and self-contained entities, and we don't need any of + * the sophisticated features like object caching. + */ class Packet { public: - Packet() + /** + * Construct and initialize from packet data. + * + * @param link_type The link type in the form of a \c DLT_* constant. + * + * @param ts The timestamp associated with the packet. + * + * @param caplen The number of bytes valid in *data*. + * + * @param len The wire length of the packet, which must be more or + * equal *caplen* (but can't be less). + * + * @param data A pointer to the raw packet data, starting with the + * layer 2 header. The pointer must remain valid for the lifetime of + * the Packet instance, unless *copy* is true. + * + * @param copy If true, the constructor will make an internal copy of + * *data*, so that the caller can release its version. + * + * @param tag A textual tag to associate with the packet for + * differentiating the input streams. + */ + Packet(int link_type, struct timeval *ts, uint32 caplen, + uint32 len, const u_char *data, int copy = false, + std::string tag = std::string("")) : data(0) + { + Init(link_type, ts, caplen, len, data, copy, tag); + } + + /** + * Default constructor. For internal use only. + */ + Packet() : data(0) { struct timeval ts = {0, 0}; Init(0, &ts, 0, 0, 0); } - // Construct and initialize from packet data. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string("")) - { - Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag); - } + /** + * Destructor. + */ ~Packet() { - if ( free ) + if ( copy ) delete [] data; } - // Initialize with data from pointer. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0) - { - link_type = arg_link_type; - ts = *arg_ts; - cap_len = arg_caplen; - len = arg_len; - free = arg_free; + /** + * (Re-)initialize from packet data. + * + * @param link_type The link type in the form of a \c DLT_* constant. + * + * @param ts The timestamp associated with the packet. + * + * @param caplen The number of bytes valid in *data*. + * + * @param len The wire length of the packet, which must be more or + * equal *caplen* (but can't be less). + * + * @param data A pointer to the raw packet data, starting with the + * layer 2 header. The pointer must remain valid for the lifetime of + * the Packet instance, unless *copy* is true. + * + * @param copy If true, the constructor will make an internal copy of + * *data*, so that the caller can release its version. + * + * @param tag A textual tag to associate with the packet for + * differentiating the input streams. + */ + void Init(int link_type, struct timeval *ts, uint32 caplen, + uint32 len, const u_char *data, int copy = false, + std::string tag = std::string("")); - if ( free ) - { - data = new u_char[cap_len]; - memcpy(const_cast(data), arg_data, cap_len); - } - else - data = arg_data; - - hdr_size = arg_hdrsize; - l3_proto = L3_UNKNOWN; - tag = arg_tag; - time = ts.tv_sec + double(ts.tv_usec) / 1e6; - eth_type = 0; - vlan = 0; - - l2_valid = false; - - if ( data ) - ProcessLayer2(); - } - - const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (data + hdr_size), false); } - - // Returns true if parsing the Layer 2 fields failed, including when - // no data was passed into the constructor in the first place. + /** + * Returns true if parsing the layer 2 fields failed, including when + * no data was passed into the constructor in the first place. + */ bool Layer2Valid() { return l2_valid; } - void Describe(ODesc* d) const; + /** + * Interprets the Layer 3 of the packet as IP and returns a + * correspondign object. + */ + const IP_Hdr IP() const + { return IP_Hdr((struct ip *) (data + hdr_size), false); } /** - * Helper method to return the header size for a given link tyoe. + * Returns a \c raw_pkt_hdr RecordVal, which includes layer 2 and + * also everything in IP_Hdr (i.e., IP4/6 + TCP/UDP/ICMP). + */ + RecordVal* BuildPktHdrVal() const; + + /** + * Static method returning the link-layer header size for a given + * link type. * * @param link_type The link tyoe. * @@ -100,7 +131,19 @@ public: */ static int GetLinkHeaderSize(int link_type); + /** + * Describes the packet, with standard signature. + */ + void Describe(ODesc* d) const; + + /** + * Serializes the packet, with standard signature. + */ bool Serialize(SerialInfo* info) const; + + /** + * Unserializes the packet, with standard signature. + */ static Packet* Unserialize(UnserialInfo* info); // These are passed in through the constructor. @@ -114,10 +157,29 @@ public: // These are computed from Layer 2 data. These fields are only valid if // Layer2Valid() returns true. - uint32 hdr_size; /// Layer 2 header size - Layer3Proto l3_proto; /// Layer 3 protocol identified (if any) - uint32 eth_type; /// If L2==ethernet, innermost ethertype field - uint32 vlan; /// (Outermost) VLan tag if any, else 0 + + /** + * Layer 2 header size. Valid iff Layer2Valid() returns true. + */ + uint32 hdr_size; + + /** + * Layer 3 protocol identified (if any). Valid iff Layer2Valid() + * returns true. + */ + Layer3Proto l3_proto; /// + + /** + * If layer 2 is Ethernet, innermost ethertype field. Valid iff + * Layer2Valid() returns true. + */ + uint32 eth_type; /// + + /** + * (Outermost) VLAN tag if any, else 0. Valid iff Layer2Valid() + * returns true. + */ + uint32 vlan; /// private: // Calculate layer 2 attributes. Sets @@ -126,8 +188,12 @@ private: // Wrapper to generate a packet-level weird. void Weird(const char* name); - // should we delete associated packet memory upon destruction. - bool free; + // Renders an MAC address into its ASCII representation. + Val *FmtEUI48(const u_char *mac) const; + + // True if we need to delete associated packet memory upon + // destruction. + bool copy; // True if L2 processing succeeded. bool l2_valid; From e4c6779a67a3e22bc9bb38f20d10e4c26e4b340c Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 21 Jul 2015 08:35:17 -0700 Subject: [PATCH 24/26] Fixing compiler warning. --- CHANGES | 8 +++++++- VERSION | 2 +- src/analyzer/protocol/ssl/dtls-analyzer.pac | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 97665cf843..a8086af261 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ -2.4-39 | 2015-07-20 15:30:35 -0700 +2.4-41 | 2015-07-21 08:35:17 -0700 + + * Fixing compiler warning. (Robin Sommer) + + * Updates to IANA TLS registry. (Johanna Amann) + +2.4-38 | 2015-07-20 15:30:35 -0700 * Refactor code to use a common Packet type throught. (Jeff Barber/Robin Sommer) diff --git a/VERSION b/VERSION index 134135de59..ab3d92f8ce 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4-39 +2.4-41 diff --git a/src/analyzer/protocol/ssl/dtls-analyzer.pac b/src/analyzer/protocol/ssl/dtls-analyzer.pac index c29c5a785f..c38ebdf029 100644 --- a/src/analyzer/protocol/ssl/dtls-analyzer.pac +++ b/src/analyzer/protocol/ssl/dtls-analyzer.pac @@ -55,7 +55,7 @@ refine connection SSL_Conn += { if ( length > MAX_DTLS_HANDSHAKE_RECORD ) { - bro_analyzer()->ProtocolViolation(fmt("DTLS record length %lld larger than allowed maximum.", length)); + bro_analyzer()->ProtocolViolation(fmt("DTLS record length %" PRId64 " larger than allowed maximum.", length)); return true; } From ff21fa42d33a584ce41241805046d6edd8ac964b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 21 Jul 2015 09:39:36 -0700 Subject: [PATCH 25/26] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index 7eb2c58993..795665c2eb 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 7eb2c589939eaedb8ccbefef73531f891edbd5d9 +Subproject commit 795665c2ebef78b17a39d9cd82bee6824a5ffbf2 From 748450c61fa18b3a73cb7558dc2dd34e58a4756b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 21 Jul 2015 12:07:40 -0700 Subject: [PATCH 26/26] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index 795665c2eb..07af9748f4 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 795665c2ebef78b17a39d9cd82bee6824a5ffbf2 +Subproject commit 07af9748f40dc47d3a2b3290db494a90dcbddbdc