From cb64bb687427cb757e8ebe77731455cba371b298 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 13 Jan 2011 14:58:53 -0800 Subject: [PATCH 01/19] Porting Matti's branch to git. No changes. --- aux/broctl | 2 +- policy/bro.init | 12 +- policy/icmp.bro | 144 +++++++++++- src/Analyzer.cc | 8 +- src/AnalyzerTags.h | 2 +- src/DPM.cc | 12 +- src/ICMP.cc | 555 +++++++++++++++++++++++++++++++++++++++------ src/ICMP.h | 77 ++----- src/Sessions.cc | 50 +++- src/Val.cc | 1 - src/Val.h | 8 +- src/event.bif | 18 +- src/net_util.cc | 59 ++++- src/net_util.h | 1 + 14 files changed, 795 insertions(+), 154 deletions(-) diff --git a/aux/broctl b/aux/broctl index a05be1242b..0d8b64252f 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit a05be1242b4e06dca1bb1a38ed871e7e2d78181b +Subproject commit 0d8b64252f00f147f31f5e8c02a6a710699b67d9 diff --git a/policy/bro.init b/policy/bro.init index 1ba8f59b4d..e812db0075 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -38,11 +38,12 @@ type icmp_context: record { id: conn_id; len: count; proto: count; - frag_offset: count; - bad_hdr_len: bool; - bad_checksum: bool; - MF: bool; - DF: bool; + frag_offset: count &optional; #no frag offset for IPv6 + bad_hdr_len: bool &optional; + bad_checksum: bool &optional; #no checksum in IPv6 header + MF: bool &optional; #no MF for IPv6 + DF: bool &optional; #no DF for IPv6 + ICMP6Flag: bool; }; type addr_set: set[addr]; @@ -534,6 +535,7 @@ const IPPROTO_IGMP = 2; # group mgmt protocol const IPPROTO_IPIP = 4; # IP encapsulation in IP const IPPROTO_TCP = 6; # TCP const IPPROTO_UDP = 17; # user datagram protocol +const IPPROTO_ICMPV6 = 58; # ICMP for IPv6 const IPPROTO_RAW = 255; # raw IP packet type ip_hdr: record { diff --git a/policy/icmp.bro b/policy/icmp.bro index c6c3c87d44..d75b2a3731 100644 --- a/policy/icmp.bro +++ b/policy/icmp.bro @@ -1,4 +1,5 @@ # $Id: icmp.bro 6883 2009-08-19 21:08:09Z vern $ +# While using this script, please notice that the last F/T value is the IPv6 Flag @load hot @load weird @@ -55,8 +56,16 @@ type flow_info: record { payload: string; }; +#Insert whitelisted routers here, Router advertisements from other +#routers will be logged as possible rogue router attacks +const routers_whitelist: table[string] of bool = { + #["fe80::260:97ff:fe07:69ea"] = T, #an example + } &redef &default = F; + const names: table[count] of string = { [0] = "echo_reply", + [1] = "unreach", #icmpv6 + [2] = "too_big", #icmpv6 [3] = "unreach", [4] = "quench", [5] = "redirect", @@ -71,6 +80,33 @@ const names: table[count] of string = { [16] = "info_reply", [17] = "mask_req", [18] = "mask_reply", + [128] = "echo_req", #icmpv6 + [129] = "echo_reply", #icmpv6 + [130] = "group_memb_query", #icmpv6 + [131] = "group_memb_report", #icmpv6 + [132] = "group_memb_reduct", #icmpv6 + [133] = "router_sol", #icmpv6 + [134] = "router_ad", #icmpv6 + [135] = "neighbor_sol", #icmpv6 + [136] = "neighbor_ad", #icmpv6 + [137] = "redirect", #icmpv6 + [138] = "router_renum", #icmpv6 + [139] = "node_info_query", #icmpv6 + [140] = "node_info_resp", #icmpv6 + [141] = "inv_neigh_disc_sol", #icmpv6 + [142] = "inv_neigh_disc_ad", #icmpv6 + [143] = "mul_lis_report", #icmpv6 + [144] = "home_agent_addr_req", #icmpv6 + [145] = "home_agent_addr_reply",#icmpv6 + [146] = "mobible_prefx_sol", #icmpv6 + [147] = "mobible_prefx_ad", #icmpv6 + [148] = "cert_path_sol", #icmpv6 + [149] = "cert_path_ad", #icmpv6 + [150] = "experimental", #icmpv6 + [151] = "mcast_router_ad", #icmpv6 + [152] = "mcast_router_sol", #icmpv6 + [153] = "mcast_router_term", #icmpv6 + [154] = "fmip", #icmpv6 } &default = function(n: count): string { return fmt("icmp-%d", n); }; @@ -80,7 +116,8 @@ const IP_proto_name: table[count] of string = { [2] = "IGMP", [6] = "TCP", [17] = "UDP", - [41] = "IPV6", + [41] = "IP6", + [58] = "ICMP6", } &default = function(n: count): string { return fmt("%s", n); } &redef; @@ -123,12 +160,13 @@ global flows: table[flow_id] of flow_info &read_expire = 45 sec &expire_func = flush_flow; -event icmp_sent(c: connection, icmp: icmp_conn) +event icmp_sent(c: connection, icmp: icmp_conn, ICMP6: bool) { - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s", + + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s", network_time(), 0.0, icmp$orig_h, icmp$resp_h, names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "SH"); + icmp$len, "0", "SH", ICMP6); } event flow_summary(flow: flow_id, last_time: time) @@ -173,13 +211,64 @@ function update_flow(icmp: icmp_conn, id: count, is_orig: bool, payload: string) schedule +30sec { flow_summary(fid, fi$last_time) }; } -event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + +event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) #for other but the unreach types, which is preserved + { + + if ( active_connection(context$id) ) + { + # This section allows Bro to act on ICMP error message packets + # that happen in the context of an active connection. It is + # not currently used. + local c2 = connection_record(context$id); + local os = c2$orig$state; + local rs = c2$resp$state; + local is_attempt = + is_tcp_port(c2$id$orig_p) ? + (os == TCP_SYN_SENT && rs == TCP_INACTIVE) : + (os == UDP_ACTIVE && rs == UDP_INACTIVE); + + # Insert action here. + } + + if ( log_details ) + { + # ICMP error message packets are logged here. + # Due to the connection data contained *within* + # them, each log line will contain two connections' worth + # of data. The initial ICMP connection info is the same + # as logged for connections. + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", + network_time(), 0.0, icmp$orig_h, icmp$resp_h, + names[icmp$itype], icmp$itype, icmp$icode, "icmp", + icmp$len, "0", "EncapPkt:", + # This is the encapsulated packet: + context$id$orig_h, context$id$orig_p, + context$id$resp_h, context$id$resp_p, + context$len, IP_proto_name[context$proto], + context$len, context$bad_hdr_len, + context$bad_checksum, context$ICMP6Flag); + } + + } + + + +event icmp6_placeholder(c: connection, icmp: icmp_conn, ICMP6: bool) #just for testing + { + print "icmp6_placeholder triggered"; + } + + +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool) { update_flow(icmp, id, T, payload); + local orig = icmp$orig_h; local resp = icmp$resp_h; + # Simple ping scan detector. if ( detect_scans && (orig !in Scan::distinct_peers || @@ -231,7 +320,7 @@ event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, p } event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, - seq: count, payload: string) + seq: count, payload: string, ICMP6: bool) { # Check payload with the associated flow. @@ -240,6 +329,8 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, fid$resp_h = icmp$orig_h; # it's an echo reply. fid$id = id; + + if ( fid !in flows ) { # NOTICE([$note=ICMPUnpairedEchoReply, @@ -266,9 +357,12 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, update_flow(icmp, id, F, payload); } + + event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) { + if ( active_connection(context$id) ) { # This section allows Bro to act on ICMP-unreachable packets @@ -292,7 +386,7 @@ event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, # them, each log line will contain two connections' worth # of data. The initial ICMP connection info is the same # as logged for connections. - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", network_time(), 0.0, icmp$orig_h, icmp$resp_h, names[icmp$itype], icmp$itype, icmp$icode, "icmp", icmp$len, "0", "EncapPkt:", @@ -301,6 +395,40 @@ event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context$id$resp_h, context$id$resp_p, context$len, IP_proto_name[context$proto], context$len, context$bad_hdr_len, - context$bad_checksum); + context$bad_checksum, context$ICMP6Flag); } } + + + event icmp_router_advertisement(c: connection, icmp: icmp_conn, ICMP6: bool) + { + if ( routers_whitelist[ fmt("%s",icmp$orig_h) ] ) + { + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s", + network_time(), 0.0, icmp$orig_h, icmp$resp_h, + names[icmp$itype], icmp$itype, icmp$icode, "icmp", + icmp$len, "0", "SH", ICMP6); + } + else + { + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s", + network_time(), 0.0, icmp$orig_h, icmp$resp_h, + names[icmp$itype], "Possible Rogue Router Detected", icmp$itype, icmp$icode, + icmp$len, ICMP6); + } + + } + + + + + + + + + + + + + + diff --git a/src/Analyzer.cc b/src/Analyzer.cc index c323f99e23..a3f6bbfc2c 100644 --- a/src/Analyzer.cc +++ b/src/Analyzer.cc @@ -48,7 +48,7 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { { AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer, ICMP_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_TimeExceeded, "ICMP_TIMEEXCEEDED", + /*{ AnalyzerTag::ICMP_TimeExceeded, "ICMP_TIMEEXCEEDED", ICMP_TimeExceeded_Analyzer::InstantiateAnalyzer, ICMP_TimeExceeded_Analyzer::Available, 0, false }, { AnalyzerTag::ICMP_Unreachable, "ICMP_UNREACHABLE", @@ -56,7 +56,11 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { ICMP_Unreachable_Analyzer::Available, 0, false }, { AnalyzerTag::ICMP_Echo, "ICMP_ECHO", ICMP_Echo_Analyzer::InstantiateAnalyzer, - ICMP_Echo_Analyzer::Available, 0, false }, + ICMP_Echo_Analyzer::Available, 0, false },*/ + + + + { AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer, TCP_Analyzer::Available, 0, false }, diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index 9bf3efbd3c..eb18a03a73 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -22,7 +22,7 @@ namespace AnalyzerTag { PIA_TCP, PIA_UDP, // Transport-layer analyzers. - ICMP, ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo, TCP, UDP, + ICMP,/* ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo*/ TCP, UDP, // Application-layer analyzers (hand-written). BitTorrent, BitTorrentTracker, diff --git a/src/DPM.cc b/src/DPM.cc index 35111a38fa..7be9376b9f 100644 --- a/src/DPM.cc +++ b/src/DPM.cc @@ -215,7 +215,10 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn, case TRANSPORT_ICMP: { const struct icmp* icmpp = (const struct icmp *) data; - switch ( icmpp->icmp_type ) { + + + //Old code, moving to having only one ICMP analyzer + /*switch ( icmpp->icmp_type ) { case ICMP_ECHO: case ICMP_ECHOREPLY: @@ -241,10 +244,11 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn, DBG_DPD(conn, "activated ICMP Time Exceeded analyzer"); } break; - } + }*/ + //if ( ! root ) - if ( ! root ) - root = new ICMP_Analyzer(conn); + root = new ICMP_Analyzer(conn); + DBG_DPD(conn, "activated ICMP analyzer"); analyzed = true; break; diff --git a/src/ICMP.cc b/src/ICMP.cc index d73a9a781e..b83cf76a40 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -9,12 +9,17 @@ #include "Event.h" #include "ICMP.h" +#include + + + ICMP_Analyzer::ICMP_Analyzer(Connection* c) : TransportLayerAnalyzer(AnalyzerTag::ICMP, c) { icmp_conn_val = 0; c->SetInactivityTimeout(icmp_inactivity_timeout); request_len = reply_len = -1; + } ICMP_Analyzer::ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* c) @@ -45,16 +50,43 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, // Subtract off the common part of ICMP header. PacketContents(data + 8, min(len, caplen) - 8); + const struct icmp* icmpp = (const struct icmp*) data; len = arg_len; - if ( ! ignore_checksums && caplen >= len && - icmp_checksum(icmpp, len) != 0xffff ) + + //We need a separate calculation for ICMP6 checksums, pseudoheader is appended to the + //ICMP6 checksum calculation, which is different from ICMP4 +#ifdef BROv6 + + + if (ip->NextProto() == IPPROTO_ICMPV6 && ! ignore_checksums && + caplen >= len && icmp6_checksum(icmpp,ip->IP6_Hdr(),len )!= 0xffff ) + { + Weird("bad_ICMP6_checksum"); + return; + } + else if (ip->NextProto() != IPPROTO_ICMPV6 && ! ignore_checksums && + caplen >= len && icmp_checksum(icmpp, len) != 0xffff ) { Weird("bad_ICMP_checksum"); return; } + + +#else + + if ( ! ignore_checksums && caplen >= len && + icmp_checksum(icmpp, len) != 0xffff ) + { + Weird("bad_ICMP_checksum"); + return; + } +#endif + + + Conn()->SetLastTime(current_timestamp); if ( rule_matcher ) @@ -66,7 +98,7 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, type = icmpp->icmp_type; code = icmpp->icmp_code; - // Move past common portion of ICMP header. + // Move past common portion of ICMP header. //OK for ICMPv6? data += 8; caplen -= 8; len -= 8; @@ -77,33 +109,113 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, else len_stat += len; - NextICMP(current_timestamp, icmpp, len, caplen, data); + NextICMP(current_timestamp, icmpp, len, caplen, data, ip); if ( rule_matcher ) matcher_state.Match(Rule::PAYLOAD, data, len, is_orig, false, false, true); } -void ICMP_Analyzer::NextICMP(double /* t */, const struct icmp* /* icmpp */, - int /* len */, int /* caplen */, - const u_char*& /* data */) - { - ICMPEvent(icmp_sent); - } -void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f) - { + +/********************Generic analyzer for all ICMP4/ICMP6******************************/ +void ICMP_Analyzer::NextICMP(double t , const struct icmp* icmpp , int len , int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ) + { + int ICMP6Flag = 0; + + //printf("Executing: ICMP_Analyzer::NextICMP\n"); + //printf("New analyzer structure\n"); + + if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) + { + //printf("ICMP6!\n"); + ICMP6Flag = 1; + + switch (type) //Add new ICMP6 functions here, you can also use codes to narrow the area of single functions. + { + //All the echo stuff here + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: + Echo(t, icmpp, len, caplen, data, ip_hdr); + break; + + + //Error messages all have the same structure for their context, and are handled by the same function. + case ICMP6_PARAM_PROB: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PACKET_TOO_BIG: + case ICMP6_DST_UNREACH: + Context(t, icmpp, len, caplen, data, ip_hdr); + break; + + //All router related stuff should eventually be handled by the Router() + case ND_REDIRECT: + case ND_ROUTER_SOLICIT: + case ICMP6_ROUTER_RENUMBERING: + case ND_ROUTER_ADVERT: + Router(t, icmpp, len, caplen, data, ip_hdr); //currently only logs the router stuff for other than router_advert + break; + + /* listed for convenience + case ICMP6_PARAM_PROB: break; + case MLD_LISTENER_QUERY: break; + case MLD_LISTENER_REPORT: break; + case MLD_LISTENER_REDUCTION: break; + case ND_NEIGHBOR_SOLICIT: break; + case ND_NEIGHBOR_ADVERT: break; + case ND_REDIRECT: break; + case ICMP6_ROUTER_RENUMBERING: break; + case ND_NEIGHBOR_SOLICIT: break; + case ND_NEIGHBOR_ADVERT: break; + case ICMP6_TIME_EXCEEDED: break; + */ + + default: ICMPEvent(icmp_sent, ICMP6Flag); break; + } + } + else if ( ip_hdr->NextProto() == IPPROTO_ICMP ) + { + + switch (type) //Add new ICMP4 functions here + { + case ICMP_ECHO: + case ICMP_ECHOREPLY: + Echo(t, icmpp, len, caplen, data, ip_hdr); + break; + + case ICMP_UNREACH: + case ICMP_TIMXCEED: + Context(t, icmpp, len, caplen, data, ip_hdr); + break; + + default: ICMPEvent(icmp_sent, ICMP6Flag); break; + } + + + } + else + Weird("Malformed ip header"); + } + + +void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, int ICMP6Flag) + { if ( ! f ) - return; + return; + val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); + vl->append(BuildICMPVal(ICMP6Flag)); + //if ( f == icmp_sent ) //for now, testing purposes + vl->append(new Val(ICMP6Flag, TYPE_BOOL)); ConnectionEvent(f, vl); } -RecordVal* ICMP_Analyzer::BuildICMPVal() + +RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag) { if ( ! icmp_conn_val ) { @@ -111,7 +223,13 @@ RecordVal* ICMP_Analyzer::BuildICMPVal() icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr())); icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr())); - icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT)); + + if ( ICMP6Flag == 1 ) + icmp_conn_val->Assign(2, new Val(Type6to4(type), TYPE_COUNT)); //to avoid errors in getting the message type *name* right on the scripting level, type number will be different from true ipv6 + else + icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT)); + + icmp_conn_val->Assign(3, new Val(code, TYPE_COUNT)); icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT)); } @@ -121,48 +239,170 @@ RecordVal* ICMP_Analyzer::BuildICMPVal() return icmp_conn_val; } -RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) +RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) { - const struct ip* ip = (const struct ip *) data; - uint32 ip_hdr_len = ip->ip_hl * 4; + /** + * For use only with ICMP4, ICMPV6 context extraction is still non-functional + */ + + const IP_Hdr ip_hdr_data((const struct ip*) data); + const IP_Hdr* ip_hdr = &ip_hdr_data; + int ICMP6Flag = 0; + + uint32 ip_hdr_len = ip_hdr->HdrLen(); uint32 ip_len, frag_offset; TransportProto proto = TRANSPORT_UNKNOWN; int DF, MF, bad_hdr_len, bad_checksum; - uint32 src_addr, dst_addr; + uint32 src_addr, dst_addr,src_addr2, dst_addr2; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) - { // We don't have an entire IP header. + if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) + { // We don't have an entire IP header. + bad_hdr_len = 1; + ip_len = frag_offset = 0; + DF = MF = bad_checksum = 0; + src_addr = dst_addr = 0; + src_port = dst_port = 0; + } + + else + { + bad_hdr_len = 0; + ip_len = ip_hdr->TotalLen(); + bad_checksum = ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff; + + src_addr = ip_hdr->SrcAddr4(); + dst_addr = ip_hdr->DstAddr4(); + + switch ( ip_hdr->NextProto() ) { + case 1: proto = TRANSPORT_ICMP; break; + case 6: proto = TRANSPORT_TCP; break; + case 17: proto = TRANSPORT_UDP; break; + + // Default uses TRANSPORT_UNKNOWN, per initialization above. + } + + uint32 frag_field = ip_hdr->FragField(); + DF = ip_hdr->DF(); + MF = frag_field & 0x2000; + frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff; + + const u_char* transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len); + + if ( uint32(len) < ip_hdr_len + 4 ) //what is this value for ipv6? + { + // 4 above is the magic number meaning that both + // port numbers are included in the ICMP. + bad_hdr_len = 1; + src_port = dst_port = 0; + } + + switch ( proto ) { + case TRANSPORT_ICMP: + { + const struct icmp* icmpp = + (const struct icmp *) transport_hdr; + bool is_one_way; // dummy + src_port = ntohs(icmpp->icmp_type); + dst_port = ntohs(ICMP4_counterpart(icmpp->icmp_type, + icmpp->icmp_code, + is_one_way)); + } + break; + + case TRANSPORT_TCP: + { + const struct tcphdr* tp = + (const struct tcphdr *) transport_hdr; + src_port = ntohs(tp->th_sport); + dst_port = ntohs(tp->th_dport); + } + break; + + case TRANSPORT_UDP: + { + const struct udphdr* up = + (const struct udphdr *) transport_hdr; + src_port = ntohs(up->uh_sport); + dst_port = ntohs(up->uh_dport); + } + break; + + default: + src_port = dst_port = ntohs(0); + } + } + + RecordVal* iprec = new RecordVal(icmp_context); + RecordVal* id_val = new RecordVal(conn_id); + + id_val->Assign(0, new AddrVal(src_addr)); + id_val->Assign(1, new PortVal(src_port, proto)); + id_val->Assign(2, new AddrVal(dst_addr)); + id_val->Assign(3, new PortVal(dst_port, proto)); + iprec->Assign(0, id_val); + + iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); + iprec->Assign(2, new Val(proto, TYPE_COUNT)); + iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); + iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL)); + iprec->Assign(6, new Val(MF, TYPE_BOOL)); + iprec->Assign(7, new Val(DF, TYPE_BOOL)); + iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL)); + + return iprec; + } + + + + +RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) + { + /** + * For use with ICMP6 error message context extraction (possibly very frail function) + */ + + const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data); + const IP_Hdr* ip_hdr = &ip_hdr_data; + int ICMP6Flag = 1; + int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0; + + uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40 + uint32* src_addr; + uint32* dst_addr; + uint32 ip_len, frag_offset = 0; + TransportProto proto = TRANSPORT_UNKNOWN; + uint32 src_port, dst_port; + + if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) + { bad_hdr_len = 1; - ip_len = frag_offset = 0; - DF = MF = bad_checksum = 0; + ip_len = 0; src_addr = dst_addr = 0; src_port = dst_port = 0; } - else { - bad_hdr_len = 0; - ip_len = ntohs(ip->ip_len); - bad_checksum = ones_complement_checksum((void*) ip, ip_hdr_len, 0) != 0xffff; + ip_len = ip_hdr->TotalLen(); - src_addr = uint32(ip->ip_src.s_addr); - dst_addr = uint32(ip->ip_dst.s_addr); + src_addr = (uint32 *) ip_hdr->SrcAddr(); + dst_addr = (uint32 *) ip_hdr->DstAddr(); - switch ( ip->ip_p ) { + + + switch ( ip_hdr->NextProto() ) { case 1: proto = TRANSPORT_ICMP; break; case 6: proto = TRANSPORT_TCP; break; case 17: proto = TRANSPORT_UDP; break; + case 58: proto = TRANSPORT_ICMP; break; //TransportProto Hack // Default uses TRANSPORT_UNKNOWN, per initialization above. } - uint32 frag_field = ntohs(ip->ip_off); - DF = frag_field & 0x4000; - MF = frag_field & 0x2000; - frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff; - const u_char* transport_hdr = ((u_char *) ip + ip_hdr_len); + + const u_char* transport_hdr = ((u_char *)ip_hdr->IP6_Hdr() + ip_hdr_len); if ( uint32(len) < ip_hdr_len + 4 ) { @@ -179,7 +419,7 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) (const struct icmp *) transport_hdr; bool is_one_way; // dummy src_port = ntohs(icmpp->icmp_type); - dst_port = ntohs(ICMP_counterpart(icmpp->icmp_type, + dst_port = ntohs(ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, is_one_way)); } @@ -215,19 +455,42 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) id_val->Assign(1, new PortVal(src_port, proto)); id_val->Assign(2, new AddrVal(dst_addr)); id_val->Assign(3, new PortVal(dst_port, proto)); - iprec->Assign(0, id_val); + iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - iprec->Assign(2, new Val(proto, TYPE_COUNT)); - iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); + + //TransportProto Hack + if ( ip_hdr->NextProto() == 58 || 17 ) //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more + { + iprec->Assign(2, new Val(58, TYPE_COUNT)); + } + else + { + iprec->Assign(2, new Val(proto, TYPE_COUNT)); + } + + iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); //NA for ip6 iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL)); - iprec->Assign(6, new Val(MF, TYPE_BOOL)); - iprec->Assign(7, new Val(DF, TYPE_BOOL)); + iprec->Assign(6, new Val(MF, TYPE_BOOL)); //NA for ip6 + iprec->Assign(7, new Val(DF, TYPE_BOOL)); //NA for ip6 + iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL)); //ICMP6Flag return iprec; } + + + + + + + + + + + + bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */) { return 0; @@ -277,57 +540,156 @@ unsigned int ICMP_Analyzer::MemoryAllocation() const + (icmp_conn_val ? icmp_conn_val->MemoryAllocation() : 0); } -ICMP_Echo_Analyzer::ICMP_Echo_Analyzer(Connection* c) -: ICMP_Analyzer(AnalyzerTag::ICMP_Echo, c) - { - } -void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len, - int caplen, const u_char*& data) - { - EventHandlerPtr f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply; +void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + { //For handling all Echo related ICMP messages + EventHandlerPtr f = 0; + int ICMP6Flag = 0; + + //printf("Executing: Echo, NextProto:%d\n",ip_hdr->NextProto()); + + if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) + { + f = type == ICMP6_ECHO_REQUEST ? icmp_echo_request : icmp_echo_reply; + ICMP6Flag = 1; + } + else + f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply; + if ( ! f ) return; int iid = ntohs(icmpp->icmp_hun.ih_idseq.icd_id); int iseq = ntohs(icmpp->icmp_hun.ih_idseq.icd_seq); + //printf("Check these values: iid:[%d] iseq:[%d]\n",iid,iseq); + BroString* payload = new BroString(data, caplen, 0); val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); + vl->append(BuildICMPVal(ICMP6Flag)); vl->append(new Val(iid, TYPE_COUNT)); vl->append(new Val(iseq, TYPE_COUNT)); vl->append(new StringVal(payload)); + vl->append(new Val(ICMP6Flag, TYPE_BOOL)); ConnectionEvent(f, vl); } -void ICMP_Context_Analyzer::NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data) + + + + + + + + +void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + //For handling router related ICMP messages, { EventHandlerPtr f = 0; - switch ( type ) { - case ICMP_UNREACH: f = icmp_unreachable; break; - case ICMP_TIMXCEED: f = icmp_time_exceeded; break; + int ICMP6Flag = 1; + + switch ( type ) + { + case ND_ROUTER_ADVERT: f = icmp_router_advertisement; break; + + case ND_REDIRECT: + case ND_ROUTER_SOLICIT: + case ICMP6_ROUTER_RENUMBERING: + default: ICMPEvent(icmp_sent,ICMP6Flag); return; + } + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(ICMP6Flag)); + vl->append(new Val(ICMP6Flag, TYPE_BOOL)); + + ConnectionEvent(f, vl); } - if ( f ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); - vl->append(new Val(code, TYPE_COUNT)); - vl->append(ExtractICMPContext(caplen, data)); - ConnectionEvent(f, vl); + + + + + + + + + + + + +void ICMP_Analyzer::Context(double t, const struct icmp* icmpp, + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + {//For handling the ICMP error messages + + EventHandlerPtr f = 0; + int ICMP6Flag = 0; + + + if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) //is ip6 + { + + ICMP6Flag = 1; + //printf("Executing: Context for ICMPv6\n"); + + switch ( type ) + { + case ICMP6_DST_UNREACH: f = icmp_unreachable; break; + case ICMP6_PARAM_PROB: f = icmp_error_message; break; + case ICMP6_TIME_EXCEEDED: f = icmp_error_message; break; + case ICMP6_PACKET_TOO_BIG: f = icmp_error_message; break; + } + + if ( f ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); //check for ip6 functionality + vl->append(BuildICMPVal(ICMP6Flag)); //check for ip6 functionality + vl->append(new Val(code, TYPE_COUNT)); + vl->append(ExtractICMP6Context(caplen, data)); + + ConnectionEvent(f, vl); + } + + } + else if ( ip_hdr->NextProto() == IPPROTO_ICMP ) + { + //printf("Executing: Context for ICMP\n"); + switch ( type ) + { + case ICMP_UNREACH: f = icmp_unreachable; break; + case ICMP_TIMXCEED: f = icmp_error_message; break; + } + + if ( f ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(ICMP6Flag)); + vl->append(new Val(code, TYPE_COUNT)); + vl->append(ExtractICMP4Context(caplen, data)); + + + ConnectionEvent(f, vl); + } + + } + else + { + Weird("ICMP packet, invalid data\n"); //make this more descriptive } } -int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way) + +int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; @@ -338,14 +700,77 @@ int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way) switch ( icmp_type ) { case ICMP_ECHO: return ICMP_ECHOREPLY; case ICMP_ECHOREPLY: return ICMP_ECHO; + case ICMP_TSTAMP: return ICMP_TSTAMPREPLY; case ICMP_TSTAMPREPLY: return ICMP_TSTAMP; + case ICMP_IREQ: return ICMP_IREQREPLY; case ICMP_IREQREPLY: return ICMP_IREQ; + case ICMP_ROUTERSOLICIT: return ICMP_ROUTERADVERT; + case ICMP_MASKREQ: return ICMP_MASKREPLY; case ICMP_MASKREPLY: return ICMP_MASKREQ; default: is_one_way = true; return icmp_code; } } + +int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) + { + is_one_way = false; + + /**ICMP6 version of the ICMP4_counterpart, under work**/ + //not yet used anywhere, for the context class + + switch ( icmp_type ) { + + + case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY; + case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST; + + case ND_ROUTER_SOLICIT: return ND_ROUTER_ADVERT; + case ND_ROUTER_ADVERT: return ND_ROUTER_SOLICIT; + + case ND_NEIGHBOR_SOLICIT: return ND_NEIGHBOR_ADVERT; + case ND_NEIGHBOR_ADVERT: return ND_NEIGHBOR_SOLICIT; + + case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT; + case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY; + + case 139: return 140; //ICMP node information query and response respectively (not defined in icmp6.h) + case 140: return 139; + + case 144: return 145; //Home Agent Address Discovery Request Message and reply + case 145: return 144; + + //check the rest of the counterparts + + default: is_one_way = true; return icmp_code; + } + } + + //For mapping ICMP types and codes of v6 to v4. Because we are using same events for both icmpv4 and icmpv6 there is some overlap + //in ICMP types. If this function is used, the name (checked from a table in the scripts) will be incorrect for the listed + //types, but the names will be correct for all ICMP types. + int Type6to4(int icmp_type) + { + switch ( icmp_type ) //For these three values, the type number will be wrong if this is used! + { //easy way to disable this is just to comment all the cases out, and leave only the default. + case ICMP6_DST_UNREACH: return ICMP_UNREACH; break; + case ICMP6_TIME_EXCEEDED: return ICMP_TIMXCEED; break; + case ICMP6_PARAM_PROB: return ICMP_PARAMPROB; break; + + default: return icmp_type; break; + } + } + + int Code6to4(int icmp_code) //not used yet for anything + { + switch ( icmp_code ) + { + default: return icmp_code; break; + } + } + + diff --git a/src/ICMP.h b/src/ICMP.h index 43921f1aac..14f6971915 100644 --- a/src/ICMP.h +++ b/src/ICMP.h @@ -34,15 +34,27 @@ protected: virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; - void ICMPEvent(EventHandlerPtr f); + void ICMPEvent(EventHandlerPtr f, int ICMP6Flag); + + void Echo(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Context(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Router(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + + + void Describe(ODesc* d) const; - RecordVal* BuildICMPVal(); + RecordVal* BuildICMPVal(int ICMP6Flag); virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + + RecordVal* ExtractICMP4Context(int len, const u_char*& data); + RecordVal* ExtractICMP6Context(int len, const u_char*& data); - RecordVal* ExtractICMPContext(int len, const u_char*& data); RecordVal* icmp_conn_val; int type; @@ -54,65 +66,24 @@ protected: RuleMatcherState matcher_state; }; -class ICMP_Echo_Analyzer : public ICMP_Analyzer { -public: - ICMP_Echo_Analyzer(Connection* conn); +/*class ICMP4_Analyzer : public ICMP_Analyzer { - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_Echo_Analyzer(conn); } - static bool Available() { return icmp_echo_request || icmp_echo_reply; } -protected: - ICMP_Echo_Analyzer() { } - - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); }; -class ICMP_Context_Analyzer : public ICMP_Analyzer { -public: - ICMP_Context_Analyzer(AnalyzerTag::Tag tag, Connection* conn) - : ICMP_Analyzer(tag, conn) { } +class ICMP6_Analyzer : public ICMP_Analyzer { -protected: - ICMP_Context_Analyzer() { } - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); -}; - -class ICMP_TimeExceeded_Analyzer : public ICMP_Context_Analyzer { -public: - ICMP_TimeExceeded_Analyzer(Connection* conn) - : ICMP_Context_Analyzer(AnalyzerTag::ICMP_TimeExceeded, conn) { } - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_TimeExceeded_Analyzer(conn); } - - static bool Available() { return icmp_time_exceeded; } - -protected: - ICMP_TimeExceeded_Analyzer() { } -}; - -class ICMP_Unreachable_Analyzer : public ICMP_Context_Analyzer { -public: - ICMP_Unreachable_Analyzer(Connection* conn) - : ICMP_Context_Analyzer(AnalyzerTag::ICMP_Unreachable, conn) { } - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_Unreachable_Analyzer(conn); } - - static bool Available() { return icmp_unreachable; } - -protected: - ICMP_Unreachable_Analyzer() { } -}; +};*/ // Returns the counterpart type to the given type (e.g., the counterpart // to ICMP_ECHOREPLY is ICMP_ECHO). -extern int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +//extern int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +extern int Type6to4(int icmp_type); +extern int Code6to4(int icmp_code); #endif diff --git a/src/Sessions.cc b/src/Sessions.cc index fd443d4dcc..de0a1cb488 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -299,6 +299,7 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr, } const struct ip* ip = (const struct ip*) (pkt + hdr_size); + if ( ip->ip_v == 4 ) { IP_Hdr ip_hdr(ip); @@ -332,6 +333,8 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* ++num_packets_processed; + + uint32 caplen = hdr->caplen - hdr_size; if ( caplen < sizeof(struct ip) ) { @@ -459,7 +462,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, int proto = ip_hdr->NextProto(); if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && - proto != IPPROTO_ICMP ) + proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) // Added ICMPV6, Matti { dump_this_packet = 1; return; @@ -530,7 +533,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, caplen -= ip_hdr_len; uint32 min_hdr_len = (proto == IPPROTO_TCP) ? sizeof(struct tcphdr) : - (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); + (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); //needs checking for ICMPV6?, Matti if ( len < min_hdr_len ) { @@ -582,7 +585,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, const struct icmp* icmpp = (const struct icmp *) data; id.src_port = icmpp->icmp_type; - id.dst_port = ICMP_counterpart(icmpp->icmp_type, + id.dst_port = ICMP4_counterpart(icmpp->icmp_type, icmpp->icmp_code, id.is_one_way); @@ -593,6 +596,23 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, break; } + case IPPROTO_ICMPV6: // new case, identical to ICMP, is this correct?? Matti + { + const struct icmp* icmpp = (const struct icmp *) data; + + id.src_port = icmpp->icmp_type; + //printf("TYPE: %d\n", id.src_port); //testing, Matti + id.dst_port = ICMP6_counterpart(icmpp->icmp_type, + icmpp->icmp_code, + id.is_one_way); + + id.src_port = htons(id.src_port); + id.dst_port = htons(id.dst_port); + + d = &icmp_conns; + break; + + } default: Weird(fmt("unknown_protocol %d", proto), hdr, pkt); return; @@ -611,6 +631,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, else { conn = (Connection*) d->Lookup(h); + + if ( ! conn ) { conn = NewConn(h, t, &id, data, proto); @@ -620,6 +642,9 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, else { // We already know that connection. + + + int consistent = CheckConnectionTag(conn); if ( consistent < 0 ) { @@ -773,6 +798,19 @@ Val* NetSessions::BuildHeader(const struct ip* ip) break; } + case IPPROTO_ICMPV6: //Added, Matti + { + const struct icmp* icmpp = (const struct icmp *) data; + RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); + + //printf("datalen:%d",data_len); //Testing, Matti + + icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); + + pkt_hdr->Assign(3, icmp_hdr); + break; + } + default: { // This is not a protocol we understand. @@ -968,7 +1006,7 @@ void NetSessions::Remove(Connection* c) ; else if ( ! tcp_conns.RemoveEntry(k) ) - internal_error("connection missing"); + internal_error(fmt("connection missing")); break; case TRANSPORT_UDP: @@ -1157,6 +1195,9 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, case IPPROTO_UDP: tproto = TRANSPORT_UDP; break; + case IPPROTO_ICMPV6: //TransportProto Hack + tproto = TRANSPORT_ICMP; + break; default: internal_error("unknown transport protocol"); break; @@ -1242,7 +1283,6 @@ bool NetSessions::IsLikelyServerPort(uint32 port, TransportProto proto) const port |= UDP_PORT_MASK; else if ( proto == TRANSPORT_ICMP ) port |= ICMP_PORT_MASK; - return port_cache.find(port) != port_cache.end(); } diff --git a/src/Val.cc b/src/Val.cc index 9a1ee700ff..66770cbdb1 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -872,7 +872,6 @@ PortVal::PortVal(uint32 p, TransportProto port_type) : Val(TYPE_PORT) case TRANSPORT_ICMP: p |= ICMP_PORT_MASK; break; - default: break; // "other" } diff --git a/src/Val.h b/src/Val.h index 5a2faee9d7..b6effcb9e9 100644 --- a/src/Val.h +++ b/src/Val.h @@ -513,9 +513,10 @@ protected: #define NUM_PORT_SPACES 4 #define PORT_SPACE_MASK 0x30000 -#define TCP_PORT_MASK 0x10000 -#define UDP_PORT_MASK 0x20000 -#define ICMP_PORT_MASK 0x30000 +#define TCP_PORT_MASK 0x10000 +#define UDP_PORT_MASK 0x20000 +#define ICMP_PORT_MASK 0x30000 + typedef enum { TRANSPORT_UNKNOWN, TRANSPORT_TCP, TRANSPORT_UDP, TRANSPORT_ICMP, @@ -537,6 +538,7 @@ public: int IsUDP() const; int IsICMP() const; + TransportProto PortType() const { if ( IsTCP() ) diff --git a/src/event.bif b/src/event.bif index 3171b02dde..ffee9244b7 100644 --- a/src/event.bif +++ b/src/event.bif @@ -52,11 +52,21 @@ event udp_request%(u: connection%); event udp_reply%(u: connection%); event udp_contents%(u: connection, is_orig: bool, contents: string%); event udp_session_done%(u: connection%); -event icmp_sent%(c: connection, icmp: icmp_conn%); -event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); -event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); + +event icmp_sent%(c: connection, icmp: icmp_conn, ICMP6: bool%); +event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool%); +event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool%); event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); +event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); +event icmp_router_advertisement%(c: connection, icmp: icmp_conn, ICMP6: bool%); + + + +event icmp6_placeholder%(c: connection, icmp: icmp_conn, ICMP6: bool%); + + + + event net_stats_update%(t: time, ns: net_stats%); event conn_stats%(c: connection, os: endpoint_stats, rs: endpoint_stats%); event conn_weird%(name: string, c: connection%); diff --git a/src/net_util.cc b/src/net_util.cc index e49d575fa0..4c57f12213 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -86,6 +86,14 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len) #ifdef BROv6 int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) { + /**From RFC for udp4 (same for udp6, except for different pseudoheader which is same as for icmp6) + Computed as the 16-bit one's complement of the one's complement sum of a + pseudo header of information from the IP header, the UDP header, and the + data, padded as needed with zero bytes at the end to make a multiple of + two bytes. If the checksum is cleared to zero, then checksuming is + disabled. If the computed checksum is zero, then this field must be set + to 0xFFFF. + **/ uint32 sum; if ( len % 2 == 1 ) @@ -97,19 +105,61 @@ int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum); sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum); - sum = ones_complement_checksum((void*) &len, 4, sum); + uint32 l = htonl(len); + sum = ones_complement_checksum((void*) &l, 4, sum); uint32 addl_pseudo = htons(IPPROTO_UDP); sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); sum = ones_complement_checksum((void*) up, len, sum); + //printf("checksum, calculated for UDP6: %d\n",sum); + return sum; } + + +int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) + { + /**From RFC + Checksum that covers the ICMPv6 message. This field contains the 16-bit one's + complement of the one's complement sum of the entire ICMPv6 message starting + with the ICMPv6 message type field, prepended with a pseudo-header of IPv6 + header fields. + **/ + uint32 sum; + + if ( len % 2 == 1 ) + // Add in pad byte. + sum += htons(((const u_char*) icmpp)[len - 1] << 8); + else + sum = 0; + + //pseudoheader as in udp6 above + sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum); + sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum); + uint32 l = htonl(len); + sum = ones_complement_checksum((void*) &l, 4, sum); + uint32 addl_pseudo = htons(IPPROTO_ICMPV6); + sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); + //pseudoheader complete + + sum = ones_complement_checksum((void*) icmpp, len, sum); + + //printf("checksum, calculated for ICMP6: %d\n",sum); + + return sum; + } + #endif int icmp_checksum(const struct icmp* icmpp, int len) { + /**From RFC + Checksum that covers the ICMP message. This is the 16-bit one's + complement of the one's complement sum of the ICMP message starting + with the Type field. The checksum field should be cleared to zero + before generating the checksum. + **/ uint32 sum; - if ( len % 2 == 1 ) // Add in pad byte. sum = htons(((const u_char*) icmpp)[len - 1] << 8); @@ -118,10 +168,15 @@ int icmp_checksum(const struct icmp* icmpp, int len) sum = ones_complement_checksum((void*) icmpp, len, sum); + //printf("checksum, calculated for ICMP4: %d\n",sum); + return sum; } + + + #define CLASS_A 0x00000000 #define CLASS_B 0x80000000 #define CLASS_C 0xc0000000 diff --git a/src/net_util.h b/src/net_util.h index 25b6b293fc..4c17104573 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -91,6 +91,7 @@ extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len); #ifdef BROv6 extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up, int len); +extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len); #endif extern int icmp_checksum(const struct icmp* icmpp, int len); From 50181edd8415e2f698a705932af42e0fb0e5c2f9 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 25 Jan 2011 17:54:20 -0800 Subject: [PATCH 02/19] Significant edit pass over ICMPv6 code. Matti, more per mail. --- policy/bro.init | 13 +- policy/icmp.bro | 243 +++++---------- src/Analyzer.cc | 14 - src/AnalyzerTags.h | 2 +- src/DPM.cc | 34 --- src/ICMP.cc | 741 ++++++++++++++++++--------------------------- src/ICMP.h | 43 ++- src/event.bif | 8 +- src/net_util.cc | 39 +-- src/net_util.h | 6 +- 10 files changed, 424 insertions(+), 719 deletions(-) diff --git a/policy/bro.init b/policy/bro.init index e812db0075..5b963169df 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -28,6 +28,8 @@ type icmp_conn: record { itype: count; icode: count; len: count; + + v6: bool; # true if it's an ICMPv6 packet. }; type icmp_hdr: record { @@ -38,12 +40,11 @@ type icmp_context: record { id: conn_id; len: count; proto: count; - frag_offset: count &optional; #no frag offset for IPv6 - bad_hdr_len: bool &optional; - bad_checksum: bool &optional; #no checksum in IPv6 header - MF: bool &optional; #no MF for IPv6 - DF: bool &optional; #no DF for IPv6 - ICMP6Flag: bool; + bad_hdr_len: bool; + bad_checksum: bool; # always true for ICMPv6. + frag_offset: count; # always 0 for IMCPv6. + MF: bool; # always false for IMCPv6. + DF: bool; # always true for ICMPv6. }; type addr_set: set[addr]; diff --git a/policy/icmp.bro b/policy/icmp.bro index d75b2a3731..d5e06c4afa 100644 --- a/policy/icmp.bro +++ b/policy/icmp.bro @@ -1,5 +1,4 @@ # $Id: icmp.bro 6883 2009-08-19 21:08:09Z vern $ -# While using this script, please notice that the last F/T value is the IPv6 Flag @load hot @load weird @@ -18,6 +17,7 @@ export { ICMPAsymPayload, # payload in echo req-resp not the same ICMPConnectionPair, # too many ICMPs between hosts ICMPAddressScan, + ICMPRogueRouter, # v6 advertisement from unknown router # The following isn't presently sufficiently useful due # to cold start and packet drops. @@ -35,6 +35,12 @@ export { const detect_conn_pairs = F &redef; # switch for connection pair const detect_payload_asym = F &redef; # switch for echo payload const conn_pair_threshold = 200 &redef; + + # If the IPv6 routers in a network are all known, they can be + # whitelisted here. If so, any other router seen sending an + # announcement will be reported. If this set remains empty, no such + # detection will be done. + const router_whitelist: set[addr] &redef; } global conn_pair:table[addr] of set[addr] &create_expire = 1 day; @@ -56,16 +62,10 @@ type flow_info: record { payload: string; }; -#Insert whitelisted routers here, Router advertisements from other -#routers will be logged as possible rogue router attacks -const routers_whitelist: table[string] of bool = { - #["fe80::260:97ff:fe07:69ea"] = T, #an example - } &redef &default = F; - const names: table[count] of string = { [0] = "echo_reply", - [1] = "unreach", #icmpv6 - [2] = "too_big", #icmpv6 + [1] = "unreach", # icmpv6 + [2] = "too_big", # icmpv6 [3] = "unreach", [4] = "quench", [5] = "redirect", @@ -80,33 +80,33 @@ const names: table[count] of string = { [16] = "info_reply", [17] = "mask_req", [18] = "mask_reply", - [128] = "echo_req", #icmpv6 - [129] = "echo_reply", #icmpv6 - [130] = "group_memb_query", #icmpv6 - [131] = "group_memb_report", #icmpv6 - [132] = "group_memb_reduct", #icmpv6 - [133] = "router_sol", #icmpv6 - [134] = "router_ad", #icmpv6 - [135] = "neighbor_sol", #icmpv6 - [136] = "neighbor_ad", #icmpv6 - [137] = "redirect", #icmpv6 - [138] = "router_renum", #icmpv6 - [139] = "node_info_query", #icmpv6 - [140] = "node_info_resp", #icmpv6 - [141] = "inv_neigh_disc_sol", #icmpv6 - [142] = "inv_neigh_disc_ad", #icmpv6 - [143] = "mul_lis_report", #icmpv6 - [144] = "home_agent_addr_req", #icmpv6 - [145] = "home_agent_addr_reply",#icmpv6 - [146] = "mobible_prefx_sol", #icmpv6 - [147] = "mobible_prefx_ad", #icmpv6 - [148] = "cert_path_sol", #icmpv6 - [149] = "cert_path_ad", #icmpv6 - [150] = "experimental", #icmpv6 - [151] = "mcast_router_ad", #icmpv6 - [152] = "mcast_router_sol", #icmpv6 - [153] = "mcast_router_term", #icmpv6 - [154] = "fmip", #icmpv6 + [128] = "echo_req", # icmpv6 + [129] = "echo_reply", # icmpv6 + [130] = "group_memb_query", # icmpv6 + [131] = "group_memb_report", # icmpv6 + [132] = "group_memb_reduct", # icmpv6 + [133] = "router_sol", # icmpv6 + [134] = "router_ad", # icmpv6 + [135] = "neighbor_sol", # icmpv6 + [136] = "neighbor_ad", # icmpv6 + [137] = "redirect", # icmpv6 + [138] = "router_renum", # icmpv6 + [139] = "node_info_query", # icmpv6 + [140] = "node_info_resp", # icmpv6 + [141] = "inv_neigh_disc_sol", # icmpv6 + [142] = "inv_neigh_disc_ad", # icmpv6 + [143] = "mul_lis_report", # icmpv6 + [144] = "home_agent_addr_req", # icmpv6 + [145] = "home_agent_addr_reply",# icmpv6 + [146] = "mobible_prefx_sol", # icmpv6 + [147] = "mobible_prefx_ad", # icmpv6 + [148] = "cert_path_sol", # icmpv6 + [149] = "cert_path_ad", # icmpv6 + [150] = "experimental", # icmpv6 + [151] = "mcast_router_ad", # icmpv6 + [152] = "mcast_router_sol", # icmpv6 + [153] = "mcast_router_term", # icmpv6 + [154] = "fmip", # icmpv6 } &default = function(n: count): string { return fmt("icmp-%d", n); }; @@ -116,8 +116,8 @@ const IP_proto_name: table[count] of string = { [2] = "IGMP", [6] = "TCP", [17] = "UDP", - [41] = "IP6", - [58] = "ICMP6", + [41] = "IPV6", + [58] = "ICMPV6", } &default = function(n: count): string { return fmt("%s", n); } &redef; @@ -160,13 +160,38 @@ global flows: table[flow_id] of flow_info &read_expire = 45 sec &expire_func = flush_flow; -event icmp_sent(c: connection, icmp: icmp_conn, ICMP6: bool) +function print_log(c: connection, icmp: icmp_conn, addl: string) { + if ( ! log_details ) + return; - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s", + print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s", network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "SH", ICMP6); + names[icmp$itype], icmp$itype, icmp$icode, + icmp$v6 ? "icmp6" : "icmp", icmp$len, addl); + } + +function print_log_with_context(c: connection, icmp: icmp_conn, context: icmp_context, addl: string) + { + # Due to the connection data contained *within* + # them, each log line will contain two connections' worth + # of data. The initial ICMP connection info is the same + # as logged for connections. + + local ctx = fmt("0 EncapPkt: %s %s %s %s %s %s %s %s %s", + context$id$orig_h, context$id$orig_p, + context$id$resp_h, context$id$resp_p, + context$len, IP_proto_name[context$proto], + context$len, context$bad_hdr_len, + context$bad_checksum); + + print_log(c, icmp, ctx); + } + + +event icmp_sent(c: connection, icmp: icmp_conn) + { + print_log(c, icmp, "0 SH"); } event flow_summary(flow: flow_id, last_time: time) @@ -212,63 +237,18 @@ function update_flow(icmp: icmp_conn, id: count, is_orig: bool, payload: string) } -event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) #for other but the unreach types, which is preserved +event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) { - - if ( active_connection(context$id) ) - { - # This section allows Bro to act on ICMP error message packets - # that happen in the context of an active connection. It is - # not currently used. - local c2 = connection_record(context$id); - local os = c2$orig$state; - local rs = c2$resp$state; - local is_attempt = - is_tcp_port(c2$id$orig_p) ? - (os == TCP_SYN_SENT && rs == TCP_INACTIVE) : - (os == UDP_ACTIVE && rs == UDP_INACTIVE); - - # Insert action here. - } - - if ( log_details ) - { - # ICMP error message packets are logged here. - # Due to the connection data contained *within* - # them, each log line will contain two connections' worth - # of data. The initial ICMP connection info is the same - # as logged for connections. - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "EncapPkt:", - # This is the encapsulated packet: - context$id$orig_h, context$id$orig_p, - context$id$resp_h, context$id$resp_p, - context$len, IP_proto_name[context$proto], - context$len, context$bad_hdr_len, - context$bad_checksum, context$ICMP6Flag); - } - + print_log_with_context(c, icmp, context, ""); } - - -event icmp6_placeholder(c: connection, icmp: icmp_conn, ICMP6: bool) #just for testing - { - print "icmp6_placeholder triggered"; - } - - -event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool) +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) { update_flow(icmp, id, T, payload); - local orig = icmp$orig_h; local resp = icmp$resp_h; - # Simple ping scan detector. if ( detect_scans && (orig !in Scan::distinct_peers || @@ -320,7 +300,7 @@ event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, p } event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, - seq: count, payload: string, ICMP6: bool) + seq: count, payload: string) { # Check payload with the associated flow. @@ -329,8 +309,6 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, fid$resp_h = icmp$orig_h; # it's an echo reply. fid$id = id; - - if ( fid !in flows ) { # NOTICE([$note=ICMPUnpairedEchoReply, @@ -357,78 +335,19 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, update_flow(icmp, id, F, payload); } - - event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) { - - if ( active_connection(context$id) ) - { - # This section allows Bro to act on ICMP-unreachable packets - # that happen in the context of an active connection. It is - # not currently used. - local c2 = connection_record(context$id); - local os = c2$orig$state; - local rs = c2$resp$state; - local is_attempt = - is_tcp_port(c2$id$orig_p) ? - (os == TCP_SYN_SENT && rs == TCP_INACTIVE) : - (os == UDP_ACTIVE && rs == UDP_INACTIVE); - - # Insert action here. - } - - if ( log_details ) - { - # ICMP unreachable packets are the only ones currently - # logged. Due to the connection data contained *within* - # them, each log line will contain two connections' worth - # of data. The initial ICMP connection info is the same - # as logged for connections. - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "EncapPkt:", - # This is the encapsulated packet: - context$id$orig_h, context$id$orig_p, - context$id$resp_h, context$id$resp_p, - context$len, IP_proto_name[context$proto], - context$len, context$bad_hdr_len, - context$bad_checksum, context$ICMP6Flag); - } + print_log_with_context(c, icmp, context, ""); } - - - event icmp_router_advertisement(c: connection, icmp: icmp_conn, ICMP6: bool) + +event icmp_router_advertisement(c: connection, icmp: icmp_conn) { - if ( routers_whitelist[ fmt("%s",icmp$orig_h) ] ) - { - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "SH", ICMP6); - } - else - { - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], "Possible Rogue Router Detected", icmp$itype, icmp$icode, - icmp$len, ICMP6); - } - - } - + print_log(c, icmp, ""); - - - - - - - - - - - - + if ( |router_whitelist| == 0 || icmp$orig_h in router_whitelist ) + return; + + NOTICE([$note=ICMPRogueRouter, + $msg=fmt("rouge router advertisement from %s", icmp$orig_h)]); + } diff --git a/src/Analyzer.cc b/src/Analyzer.cc index a3f6bbfc2c..06b05960b7 100644 --- a/src/Analyzer.cc +++ b/src/Analyzer.cc @@ -48,20 +48,6 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { { AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer, ICMP_Analyzer::Available, 0, false }, - /*{ AnalyzerTag::ICMP_TimeExceeded, "ICMP_TIMEEXCEEDED", - ICMP_TimeExceeded_Analyzer::InstantiateAnalyzer, - ICMP_TimeExceeded_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_Unreachable, "ICMP_UNREACHABLE", - ICMP_Unreachable_Analyzer::InstantiateAnalyzer, - ICMP_Unreachable_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_Echo, "ICMP_ECHO", - ICMP_Echo_Analyzer::InstantiateAnalyzer, - ICMP_Echo_Analyzer::Available, 0, false },*/ - - - - - { AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer, TCP_Analyzer::Available, 0, false }, { AnalyzerTag::UDP, "UDP", UDP_Analyzer::InstantiateAnalyzer, diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index eb18a03a73..231b39364a 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -22,7 +22,7 @@ namespace AnalyzerTag { PIA_TCP, PIA_UDP, // Transport-layer analyzers. - ICMP,/* ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo*/ TCP, UDP, + ICMP, TCP, UDP, // Application-layer analyzers (hand-written). BitTorrent, BitTorrentTracker, diff --git a/src/DPM.cc b/src/DPM.cc index 7be9376b9f..b9afb15196 100644 --- a/src/DPM.cc +++ b/src/DPM.cc @@ -214,42 +214,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn, break; case TRANSPORT_ICMP: { - const struct icmp* icmpp = (const struct icmp *) data; - - - //Old code, moving to having only one ICMP analyzer - /*switch ( icmpp->icmp_type ) { - - case ICMP_ECHO: - case ICMP_ECHOREPLY: - if ( ICMP_Echo_Analyzer::Available() ) - { - root = new ICMP_Echo_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Echo analyzer"); - } - break; - - case ICMP_UNREACH: - if ( ICMP_Unreachable_Analyzer::Available() ) - { - root = new ICMP_Unreachable_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Unreachable analyzer"); - } - break; - - case ICMP_TIMXCEED: - if ( ICMP_TimeExceeded_Analyzer::Available() ) - { - root = new ICMP_TimeExceeded_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Time Exceeded analyzer"); - } - break; - }*/ - //if ( ! root ) - root = new ICMP_Analyzer(conn); DBG_DPD(conn, "activated ICMP analyzer"); - analyzed = true; break; } diff --git a/src/ICMP.cc b/src/ICMP.cc index b83cf76a40..1ec1d2901c 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -11,15 +11,12 @@ #include - - ICMP_Analyzer::ICMP_Analyzer(Connection* c) : TransportLayerAnalyzer(AnalyzerTag::ICMP, c) { icmp_conn_val = 0; c->SetInactivityTimeout(icmp_inactivity_timeout); request_len = reply_len = -1; - } ICMP_Analyzer::ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* c) @@ -37,7 +34,7 @@ void ICMP_Analyzer::Done() matcher_state.FinishEndpointMatcher(); } -void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, +void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) { assert(ip); @@ -50,42 +47,39 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, // Subtract off the common part of ICMP header. PacketContents(data + 8, min(len, caplen) - 8); - const struct icmp* icmpp = (const struct icmp*) data; - len = arg_len; + assert(caplen >= len); // Should have been caught earlier already. + + if ( ! ignore_checksums ) + { + int chksum; - //We need a separate calculation for ICMP6 checksums, pseudoheader is appended to the - //ICMP6 checksum calculation, which is different from ICMP4 #ifdef BROv6 - - - if (ip->NextProto() == IPPROTO_ICMPV6 && ! ignore_checksums && - caplen >= len && icmp6_checksum(icmpp,ip->IP6_Hdr(),len )!= 0xffff ) + switch ( ip->NextProto() ) { - Weird("bad_ICMP6_checksum"); - return; + case IPPROTO_ICMP: + chksum = icmp_checksum(icmpp, len); + break; + + case IPPROTO_ICMPV6: + chksum = icmp6_checksum(icmpp, ip->IP6_Hdr(), len); + break; + + default: + internal_error("unexpected IP proto in ICMP analyzer"); } - else if (ip->NextProto() != IPPROTO_ICMPV6 && ! ignore_checksums && - caplen >= len && icmp_checksum(icmpp, len) != 0xffff ) - { - Weird("bad_ICMP_checksum"); - return; - } - - - #else - - if ( ! ignore_checksums && caplen >= len && - icmp_checksum(icmpp, len) != 0xffff ) - { - Weird("bad_ICMP_checksum"); - return; - } + # Classic v4 version. + chksum = icmp_checksum(icmpp, len); #endif - + if ( chksum != 0xffff ) + { + Weird("bad_ICMP6_checksum"); + return; + } + } Conn()->SetLastTime(current_timestamp); @@ -95,127 +89,104 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, matcher_state.InitEndpointMatcher(this, ip, len, is_orig, 0); } - type = icmpp->icmp_type; - code = icmpp->icmp_code; - - // Move past common portion of ICMP header. //OK for ICMPv6? + // Move past common portion of ICMP header. data += 8; caplen -= 8; len -= 8; - int& len_stat = is_orig ? request_len : reply_len; - if ( len_stat < 0 ) - len_stat = len; + if ( ip->NextProto() == IPPROTO_ICMP ) + NextICMP4(current_timestamp, icmpp, len, caplen, data, ip); else - len_stat += len; + NextICMP6(current_timestamp, icmpp, len, caplen, data, ip); - NextICMP(current_timestamp, icmpp, len, caplen, data, ip); if ( rule_matcher ) matcher_state.Match(Rule::PAYLOAD, data, len, is_orig, false, false, true); } - - -/********************Generic analyzer for all ICMP4/ICMP6******************************/ -void ICMP_Analyzer::NextICMP(double t , const struct icmp* icmpp , int len , int caplen, +void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr ) { - int ICMP6Flag = 0; - - //printf("Executing: ICMP_Analyzer::NextICMP\n"); - //printf("New analyzer structure\n"); - - if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) + switch ( icmpp->icmp_type ) { - //printf("ICMP6!\n"); - ICMP6Flag = 1; - - switch (type) //Add new ICMP6 functions here, you can also use codes to narrow the area of single functions. - { - //All the echo stuff here - case ICMP6_ECHO_REQUEST: - case ICMP6_ECHO_REPLY: + case ICMP_ECHO: + case ICMP_ECHOREPLY: Echo(t, icmpp, len, caplen, data, ip_hdr); break; + case ICMP_UNREACH: + case ICMP_TIMXCEED: + Context4(t, icmpp, len, caplen, data, ip_hdr); + break; - //Error messages all have the same structure for their context, and are handled by the same function. - case ICMP6_PARAM_PROB: - case ICMP6_TIME_EXCEEDED: - case ICMP6_PACKET_TOO_BIG: - case ICMP6_DST_UNREACH: - Context(t, icmpp, len, caplen, data, ip_hdr); - break; - - //All router related stuff should eventually be handled by the Router() - case ND_REDIRECT: - case ND_ROUTER_SOLICIT: - case ICMP6_ROUTER_RENUMBERING: - case ND_ROUTER_ADVERT: - Router(t, icmpp, len, caplen, data, ip_hdr); //currently only logs the router stuff for other than router_advert - break; - - /* listed for convenience - case ICMP6_PARAM_PROB: break; - case MLD_LISTENER_QUERY: break; - case MLD_LISTENER_REPORT: break; - case MLD_LISTENER_REDUCTION: break; - case ND_NEIGHBOR_SOLICIT: break; - case ND_NEIGHBOR_ADVERT: break; - case ND_REDIRECT: break; - case ICMP6_ROUTER_RENUMBERING: break; - case ND_NEIGHBOR_SOLICIT: break; - case ND_NEIGHBOR_ADVERT: break; - case ICMP6_TIME_EXCEEDED: break; - */ - - default: ICMPEvent(icmp_sent, ICMP6Flag); break; - } + default: + ICMPEvent(icmp_sent, icmpp, len, 0); break; } - else if ( ip_hdr->NextProto() == IPPROTO_ICMP ) - { + } - switch (type) //Add new ICMP4 functions here - { - case ICMP_ECHO: - case ICMP_ECHOREPLY: +#ifdef BROv6 +void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ) + { + switch ( icmpp->icmp_type ) + { + // Echo types. + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: Echo(t, icmpp, len, caplen, data, ip_hdr); break; - case ICMP_UNREACH: - case ICMP_TIMXCEED: - Context(t, icmpp, len, caplen, data, ip_hdr); + // Error messages all have the same structure for their context, + // and are handled by the same function. + case ICMP6_PARAM_PROB: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PACKET_TOO_BIG: + case ICMP6_DST_UNREACH: + Context6(t, icmpp, len, caplen, data, ip_hdr); break; - default: ICMPEvent(icmp_sent, ICMP6Flag); break; - } - + // Router related messages. + case ND_REDIRECT: + case ND_ROUTER_SOLICIT: + case ICMP6_ROUTER_RENUMBERING: + case ND_ROUTER_ADVERT: + Router(t, icmpp, len, caplen, data, ip_hdr); + break; +#if 0 + // Currently not specifically implemented. + case ICMP6_PARAM_PROB: + case MLD_LISTENER_QUERY: + case MLD_LISTENER_REPORT: + case MLD_LISTENER_REDUCTION: + case ND_NEIGHBOR_SOLICIT: + case ND_NEIGHBOR_ADVERT: + case ND_REDIRECT: + case ICMP6_ROUTER_RENUMBERING: + case ND_NEIGHBOR_SOLICIT: + case ND_NEIGHBOR_ADVERT: + case ICMP6_TIME_EXCEEDED: +#endif + default: + ICMPEvent(icmp_sent, icmpp, len, 1); + break; } - else - Weird("Malformed ip header"); - } + } +#endif - -void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, int ICMP6Flag) +void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6) { if ( ! f ) - return; - + return; val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal(ICMP6Flag)); - //if ( f == icmp_sent ) //for now, testing purposes - vl->append(new Val(ICMP6Flag, TYPE_BOOL)); - + vl->append(BuildICMPVal(icmpp, len, icmpv6)); ConnectionEvent(f, vl); } - -RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag) +RecordVal* ICMP_Analyzer::BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6) { if ( ! icmp_conn_val ) { @@ -223,15 +194,10 @@ RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag) icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr())); icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr())); - - if ( ICMP6Flag == 1 ) - icmp_conn_val->Assign(2, new Val(Type6to4(type), TYPE_COUNT)); //to avoid errors in getting the message type *name* right on the scripting level, type number will be different from true ipv6 - else - icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT)); - - - icmp_conn_val->Assign(3, new Val(code, TYPE_COUNT)); + icmp_conn_val->Assign(2, new Val(icmpp->icmp_type, TYPE_COUNT)); + icmp_conn_val->Assign(3, new Val(icmpp->icmp_code, TYPE_COUNT)); icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT)); + icmp_conn_val->Assign(5, new Val(icmpv6, TYPE_BOOL)); } Ref(icmp_conn_val); @@ -239,15 +205,74 @@ RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag) return icmp_conn_val; } +TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, uint32* dst_port) + { + const u_char* transport_hdr; + uint32 ip_hdr_len = ip_hdr->HdrLen(); + bool ip4 = ip_hdr->IP4_Hdr(); + + if ( ip4 ) + transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len); + else + transport_hdr = ((u_char *) ip_hdr->IP6_Hdr() + ip_hdr_len); + + TransportProto proto; + + switch ( ip_hdr->NextProto() ) { + case 1: proto = TRANSPORT_ICMP; break; + case 6: proto = TRANSPORT_TCP; break; + case 17: proto = TRANSPORT_UDP; break; + case 58: proto = TRANSPORT_ICMP; //TransportProto Hack // XXX What's this? + default: proto = TRANSPORT_UNKNOWN; break; + } + + switch ( proto ) { + case TRANSPORT_ICMP: + { + const struct icmp* icmpp = + (const struct icmp *) transport_hdr; + bool is_one_way; // dummy + *src_port = ntohs(icmpp->icmp_type); + + if ( ip4 ) + *dst_port = ntohs(ICMP4_counterpart(icmpp->icmp_type, + icmpp->icmp_code, is_one_way)); + else + *dst_port = ntohs(ICMP6_counterpart(icmpp->icmp_type, + icmpp->icmp_code, is_one_way)); + + break; + } + + case TRANSPORT_TCP: + { + const struct tcphdr* tp = + (const struct tcphdr *) transport_hdr; + *src_port = ntohs(tp->th_sport); + *dst_port = ntohs(tp->th_dport); + break; + } + + case TRANSPORT_UDP: + { + const struct udphdr* up = + (const struct udphdr *) transport_hdr; + *src_port = ntohs(up->uh_sport); + *dst_port = ntohs(up->uh_dport); + break; + } + + default: + *src_port = *dst_port = ntohs(0); + } + + return proto; + } + RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) { - /** - * For use only with ICMP4, ICMPV6 context extraction is still non-functional - */ - const IP_Hdr ip_hdr_data((const struct ip*) data); const IP_Hdr* ip_hdr = &ip_hdr_data; - int ICMP6Flag = 0; uint32 ip_hdr_len = ip_hdr->HdrLen(); @@ -257,132 +282,82 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) uint32 src_addr, dst_addr,src_addr2, dst_addr2; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) - { // We don't have an entire IP header. - bad_hdr_len = 1; - ip_len = frag_offset = 0; - DF = MF = bad_checksum = 0; - src_addr = dst_addr = 0; - src_port = dst_port = 0; - } - - else - { - bad_hdr_len = 0; - ip_len = ip_hdr->TotalLen(); - bad_checksum = ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff; - - src_addr = ip_hdr->SrcAddr4(); - dst_addr = ip_hdr->DstAddr4(); - - switch ( ip_hdr->NextProto() ) { - case 1: proto = TRANSPORT_ICMP; break; - case 6: proto = TRANSPORT_TCP; break; - case 17: proto = TRANSPORT_UDP; break; - - // Default uses TRANSPORT_UNKNOWN, per initialization above. - } - - uint32 frag_field = ip_hdr->FragField(); - DF = ip_hdr->DF(); - MF = frag_field & 0x2000; - frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff; - - const u_char* transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len); - - if ( uint32(len) < ip_hdr_len + 4 ) //what is this value for ipv6? - { - // 4 above is the magic number meaning that both - // port numbers are included in the ICMP. - bad_hdr_len = 1; - src_port = dst_port = 0; - } - - switch ( proto ) { - case TRANSPORT_ICMP: - { - const struct icmp* icmpp = - (const struct icmp *) transport_hdr; - bool is_one_way; // dummy - src_port = ntohs(icmpp->icmp_type); - dst_port = ntohs(ICMP4_counterpart(icmpp->icmp_type, - icmpp->icmp_code, - is_one_way)); - } - break; - - case TRANSPORT_TCP: - { - const struct tcphdr* tp = - (const struct tcphdr *) transport_hdr; - src_port = ntohs(tp->th_sport); - dst_port = ntohs(tp->th_dport); - } - break; - - case TRANSPORT_UDP: - { - const struct udphdr* up = - (const struct udphdr *) transport_hdr; - src_port = ntohs(up->uh_sport); - dst_port = ntohs(up->uh_dport); - } - break; - - default: - src_port = dst_port = ntohs(0); - } - } - - RecordVal* iprec = new RecordVal(icmp_context); - RecordVal* id_val = new RecordVal(conn_id); - - id_val->Assign(0, new AddrVal(src_addr)); - id_val->Assign(1, new PortVal(src_port, proto)); - id_val->Assign(2, new AddrVal(dst_addr)); - id_val->Assign(3, new PortVal(dst_port, proto)); - iprec->Assign(0, id_val); - - iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - iprec->Assign(2, new Val(proto, TYPE_COUNT)); - iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); - iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); - iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL)); - iprec->Assign(6, new Val(MF, TYPE_BOOL)); - iprec->Assign(7, new Val(DF, TYPE_BOOL)); - iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL)); - - return iprec; + if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) + { + // We don't have an entire IP header. + bad_hdr_len = 1; + ip_len = frag_offset = 0; + DF = MF = bad_checksum = 0; + src_addr = dst_addr = 0; + src_port = dst_port = 0; } + else + { + bad_hdr_len = 0; + ip_len = ip_hdr->TotalLen(); + bad_checksum = ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff; + src_addr = ip_hdr->SrcAddr4(); + dst_addr = ip_hdr->DstAddr4(); + uint32 frag_field = ip_hdr->FragField(); + DF = ip_hdr->DF(); + MF = frag_field & 0x2000; + frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff; + + if ( uint32(len) >= ip_hdr_len + 4 ) + proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); + else + { + // 4 above is the magic number meaning that both + // port numbers are included in the ICMP. + src_port = dst_port = 0; + bad_hdr_len = 1; + } + } + + RecordVal* iprec = new RecordVal(icmp_context); + RecordVal* id_val = new RecordVal(conn_id); + + id_val->Assign(0, new AddrVal(src_addr)); + id_val->Assign(1, new PortVal(src_port, proto)); + id_val->Assign(2, new AddrVal(dst_addr)); + id_val->Assign(3, new PortVal(dst_port, proto)); + + iprec->Assign(0, id_val); + iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); + iprec->Assign(2, new Val(proto, TYPE_COUNT)); + iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); + iprec->Assign(4, new Val(bad_checksum, TYPE_BOOL)); + iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(6, new Val(MF, TYPE_BOOL)); + iprec->Assign(7, new Val(DF, TYPE_BOOL)); + + return iprec; + } RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) { - /** - * For use with ICMP6 error message context extraction (possibly very frail function) - */ - const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data); const IP_Hdr* ip_hdr = &ip_hdr_data; - int ICMP6Flag = 1; int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0; + TransportProto proto = TRANSPORT_UNKNOWN; uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40 uint32* src_addr; uint32* dst_addr; uint32 ip_len, frag_offset = 0; - TransportProto proto = TRANSPORT_UNKNOWN; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) + if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) // XXX What's the 2nd part doing? { bad_hdr_len = 1; ip_len = 0; src_addr = dst_addr = 0; src_port = dst_port = 0; } + else { ip_len = ip_hdr->TotalLen(); @@ -390,62 +365,15 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) src_addr = (uint32 *) ip_hdr->SrcAddr(); dst_addr = (uint32 *) ip_hdr->DstAddr(); - - - switch ( ip_hdr->NextProto() ) { - case 1: proto = TRANSPORT_ICMP; break; - case 6: proto = TRANSPORT_TCP; break; - case 17: proto = TRANSPORT_UDP; break; - case 58: proto = TRANSPORT_ICMP; break; //TransportProto Hack - - // Default uses TRANSPORT_UNKNOWN, per initialization above. - } - - - const u_char* transport_hdr = ((u_char *)ip_hdr->IP6_Hdr() + ip_hdr_len); - - if ( uint32(len) < ip_hdr_len + 4 ) + if ( uint32(len) >= ip_hdr_len + 4 ) + proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); + else { // 4 above is the magic number meaning that both // port numbers are included in the ICMP. - bad_hdr_len = 1; src_port = dst_port = 0; + bad_hdr_len = 1; } - - switch ( proto ) { - case TRANSPORT_ICMP: - { - const struct icmp* icmpp = - (const struct icmp *) transport_hdr; - bool is_one_way; // dummy - src_port = ntohs(icmpp->icmp_type); - dst_port = ntohs(ICMP6_counterpart(icmpp->icmp_type, - icmpp->icmp_code, - is_one_way)); - } - break; - - case TRANSPORT_TCP: - { - const struct tcphdr* tp = - (const struct tcphdr *) transport_hdr; - src_port = ntohs(tp->th_sport); - dst_port = ntohs(tp->th_dport); - } - break; - - case TRANSPORT_UDP: - { - const struct udphdr* up = - (const struct udphdr *) transport_hdr; - src_port = ntohs(up->uh_sport); - dst_port = ntohs(up->uh_dport); - } - break; - - default: - src_port = dst_port = ntohs(0); - } } RecordVal* iprec = new RecordVal(icmp_context); @@ -459,7 +387,7 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - //TransportProto Hack + //TransportProto Hack // XXX Likewise. if ( ip_hdr->NextProto() == 58 || 17 ) //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more { iprec->Assign(2, new Val(58, TYPE_COUNT)); @@ -469,28 +397,18 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) iprec->Assign(2, new Val(proto, TYPE_COUNT)); } - iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); //NA for ip6 - iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); - iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL)); - iprec->Assign(6, new Val(MF, TYPE_BOOL)); //NA for ip6 - iprec->Assign(7, new Val(DF, TYPE_BOOL)); //NA for ip6 - iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL)); //ICMP6Flag + iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); + + // The following are not available for IPv6. + iprec->Assign(4, new Val(0, TYPE_BOOL)); // bad_checksum + iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); // frag_offset + iprec->Assign(6, new Val(0, TYPE_BOOL)); // MF + iprec->Assign(7, new Val(1, TYPE_BOOL)); // DF return iprec; } - - - - - - - - - - - bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */) { return 0; @@ -504,10 +422,12 @@ void ICMP_Analyzer::Describe(ODesc* d) const d->AddSP(")"); d->Add(dotted_addr(Conn()->OrigAddr())); +#if 0 d->Add("."); d->Add(type); d->Add("."); d->Add(code); +#endif d->SP(); d->AddSP("->"); @@ -543,19 +463,16 @@ unsigned int ICMP_Analyzer::MemoryAllocation() const void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) - { //For handling all Echo related ICMP messages + { + // For handling all Echo related ICMP messages EventHandlerPtr f = 0; - int ICMP6Flag = 0; - - //printf("Executing: Echo, NextProto:%d\n",ip_hdr->NextProto()); +#ifdef BROv6 if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) - { - f = type == ICMP6_ECHO_REQUEST ? icmp_echo_request : icmp_echo_reply; - ICMP6Flag = 1; - } + f = (icmpp->icmp_type == ICMP6_ECHO_REQUEST) ? icmp_echo_request : icmp_echo_reply; else - f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply; +#endif + f = (icmpp->icmp_type == ICMP_ECHO) ? icmp_echo_request : icmp_echo_reply; if ( ! f ) return; @@ -563,137 +480,110 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len, int iid = ntohs(icmpp->icmp_hun.ih_idseq.icd_id); int iseq = ntohs(icmpp->icmp_hun.ih_idseq.icd_seq); - //printf("Check these values: iid:[%d] iseq:[%d]\n",iid,iseq); - BroString* payload = new BroString(data, caplen, 0); val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal(ICMP6Flag)); + vl->append(BuildICMPVal(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP)); vl->append(new Val(iid, TYPE_COUNT)); vl->append(new Val(iseq, TYPE_COUNT)); vl->append(new StringVal(payload)); - vl->append(new Val(ICMP6Flag, TYPE_BOOL)); ConnectionEvent(f, vl); } - - - - - - - - void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) - //For handling router related ICMP messages, { EventHandlerPtr f = 0; - int ICMP6Flag = 1; - switch ( type ) + switch ( icmpp->icmp_type ) { - case ND_ROUTER_ADVERT: f = icmp_router_advertisement; break; + case ND_ROUTER_ADVERT: + f = icmp_router_advertisement; + break; case ND_REDIRECT: case ND_ROUTER_SOLICIT: case ICMP6_ROUTER_RENUMBERING: - default: ICMPEvent(icmp_sent,ICMP6Flag); return; + default: + ICMPEvent(icmp_sent, icmpp, len, 1); + return; } val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal(ICMP6Flag)); - vl->append(new Val(ICMP6Flag, TYPE_BOOL)); + vl->append(BuildICMPVal(icmpp, len, 1)); ConnectionEvent(f, vl); } - - - - - - - - - - - - -void ICMP_Analyzer::Context(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) - {//For handling the ICMP error messages - +void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp, + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + { EventHandlerPtr f = 0; - int ICMP6Flag = 0; - - if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) //is ip6 - { - - ICMP6Flag = 1; - //printf("Executing: Context for ICMPv6\n"); - - switch ( type ) - { - case ICMP6_DST_UNREACH: f = icmp_unreachable; break; - case ICMP6_PARAM_PROB: f = icmp_error_message; break; - case ICMP6_TIME_EXCEEDED: f = icmp_error_message; break; - case ICMP6_PACKET_TOO_BIG: f = icmp_error_message; break; - } - - if ( f ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); //check for ip6 functionality - vl->append(BuildICMPVal(ICMP6Flag)); //check for ip6 functionality - vl->append(new Val(code, TYPE_COUNT)); - vl->append(ExtractICMP6Context(caplen, data)); - - ConnectionEvent(f, vl); - } - - } - else if ( ip_hdr->NextProto() == IPPROTO_ICMP ) - { - //printf("Executing: Context for ICMP\n"); - switch ( type ) - { - case ICMP_UNREACH: f = icmp_unreachable; break; - case ICMP_TIMXCEED: f = icmp_error_message; break; - } - - if ( f ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(BuildICMPVal(ICMP6Flag)); - vl->append(new Val(code, TYPE_COUNT)); - vl->append(ExtractICMP4Context(caplen, data)); - - - ConnectionEvent(f, vl); - } - - } - else + switch ( icmpp->icmp_type ) { - Weird("ICMP packet, invalid data\n"); //make this more descriptive + case ICMP_UNREACH: + f = icmp_unreachable; + break; + + case ICMP_TIMXCEED: + f = icmp_error_message; + break; + } + + if ( f ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 0)); + vl->append(new Val(icmpp->icmp_code, TYPE_COUNT)); + vl->append(ExtractICMP4Context(caplen, data)); + ConnectionEvent(f, vl); } } +#ifdef BROv6 +void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + { + EventHandlerPtr f = 0; + + switch ( icmpp->icmp_type ) + { + case ICMP6_DST_UNREACH: + f = icmp_unreachable; + break; + + case ICMP6_PARAM_PROB: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PACKET_TOO_BIG: + f = icmp_error_message; + break; + } + + if ( f ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new Val(icmpp->icmp_code, TYPE_COUNT)); + vl->append(ExtractICMP6Context(caplen, data)); + ConnectionEvent(f, vl); + } + } +#endif int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; - // return the counterpart type if one exists. This allows us + // Return the counterpart type if one exists. This allows us // to track corresponding ICMP requests/replies. // Note that for the two-way ICMP messages, icmp_code is // always 0 (RFC 792). @@ -720,57 +610,30 @@ int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; - /**ICMP6 version of the ICMP4_counterpart, under work**/ - //not yet used anywhere, for the context class - switch ( icmp_type ) { + case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY; + case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST; + case ND_ROUTER_SOLICIT: return ND_ROUTER_ADVERT; + case ND_ROUTER_ADVERT: return ND_ROUTER_SOLICIT; - case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY; - case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST; + case ND_NEIGHBOR_SOLICIT: return ND_NEIGHBOR_ADVERT; + case ND_NEIGHBOR_ADVERT: return ND_NEIGHBOR_SOLICIT; - case ND_ROUTER_SOLICIT: return ND_ROUTER_ADVERT; - case ND_ROUTER_ADVERT: return ND_ROUTER_SOLICIT; + case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT; + case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY; - case ND_NEIGHBOR_SOLICIT: return ND_NEIGHBOR_ADVERT; - case ND_NEIGHBOR_ADVERT: return ND_NEIGHBOR_SOLICIT; + // ICMP node information query and response respectively (not defined in + // icmp6.h) + case 139: return 140; + case 140: return 139; - case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT; - case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY; - - case 139: return 140; //ICMP node information query and response respectively (not defined in icmp6.h) - case 140: return 139; - - case 144: return 145; //Home Agent Address Discovery Request Message and reply + // Home Agent Address Discovery Request Message and reply + case 144: return 145; case 145: return 144; - //check the rest of the counterparts + // TODO: Add further counterparts. default: is_one_way = true; return icmp_code; } } - - //For mapping ICMP types and codes of v6 to v4. Because we are using same events for both icmpv4 and icmpv6 there is some overlap - //in ICMP types. If this function is used, the name (checked from a table in the scripts) will be incorrect for the listed - //types, but the names will be correct for all ICMP types. - int Type6to4(int icmp_type) - { - switch ( icmp_type ) //For these three values, the type number will be wrong if this is used! - { //easy way to disable this is just to comment all the cases out, and leave only the default. - case ICMP6_DST_UNREACH: return ICMP_UNREACH; break; - case ICMP6_TIME_EXCEEDED: return ICMP_TIMXCEED; break; - case ICMP6_PARAM_PROB: return ICMP_PARAMPROB; break; - - default: return icmp_type; break; - } - } - - int Code6to4(int icmp_code) //not used yet for anything - { - switch ( icmp_code ) - { - default: return icmp_code; break; - } - } - - diff --git a/src/ICMP.h b/src/ICMP.h index 14f6971915..aed814d2b1 100644 --- a/src/ICMP.h +++ b/src/ICMP.h @@ -34,7 +34,7 @@ protected: virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; - void ICMPEvent(EventHandlerPtr f, int ICMP6Flag); + void ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6); void Echo(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); @@ -43,47 +43,40 @@ protected: void Router(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); - - void Describe(ODesc* d) const; - RecordVal* BuildICMPVal(int ICMP6Flag); + RecordVal* BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6); - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ); RecordVal* ExtractICMP4Context(int len, const u_char*& data); + + void Context4(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr); + + TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, + uint32* dst_port); + +#ifdef BROv6 + void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ); + RecordVal* ExtractICMP6Context(int len, const u_char*& data); + void Context6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr); +#endif RecordVal* icmp_conn_val; - int type; - int code; - int len; - int request_len, reply_len; RuleMatcherState matcher_state; }; -/*class ICMP4_Analyzer : public ICMP_Analyzer { - - - -}; - -class ICMP6_Analyzer : public ICMP_Analyzer { - - - -};*/ - // Returns the counterpart type to the given type (e.g., the counterpart // to ICMP_ECHOREPLY is ICMP_ECHO). -//extern int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way); extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way); extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way); -extern int Type6to4(int icmp_type); -extern int Code6to4(int icmp_code); #endif diff --git a/src/event.bif b/src/event.bif index ffee9244b7..d0cee28c03 100644 --- a/src/event.bif +++ b/src/event.bif @@ -53,12 +53,12 @@ event udp_reply%(u: connection%); event udp_contents%(u: connection, is_orig: bool, contents: string%); event udp_session_done%(u: connection%); -event icmp_sent%(c: connection, icmp: icmp_conn, ICMP6: bool%); -event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool%); -event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool%); +event icmp_sent%(c: connection, icmp: icmp_conn%); +event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); +event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_router_advertisement%(c: connection, icmp: icmp_conn, ICMP6: bool%); +event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); diff --git a/src/net_util.cc b/src/net_util.cc index 4c57f12213..75dfd929c2 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -86,14 +86,8 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len) #ifdef BROv6 int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) { - /**From RFC for udp4 (same for udp6, except for different pseudoheader which is same as for icmp6) - Computed as the 16-bit one's complement of the one's complement sum of a - pseudo header of information from the IP header, the UDP header, and the - data, padded as needed with zero bytes at the end to make a multiple of - two bytes. If the checksum is cleared to zero, then checksuming is - disabled. If the computed checksum is zero, then this field must be set - to 0xFFFF. - **/ + // UDP over IPv6 uses the same checksum function as over IPv4 but a + // different pseuod-header over which it is computed. uint32 sum; if ( len % 2 == 1 ) @@ -108,23 +102,18 @@ int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) uint32 l = htonl(len); sum = ones_complement_checksum((void*) &l, 4, sum); uint32 addl_pseudo = htons(IPPROTO_UDP); + sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); sum = ones_complement_checksum((void*) up, len, sum); - //printf("checksum, calculated for UDP6: %d\n",sum); - return sum; } int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) { - /**From RFC - Checksum that covers the ICMPv6 message. This field contains the 16-bit one's - complement of the one's complement sum of the entire ICMPv6 message starting - with the ICMPv6 message type field, prepended with a pseudo-header of IPv6 - header fields. - **/ + // ICMP6 uses the same checksum function as over ICMP4 but a different + // pseuod-header over which it is computed. uint32 sum; if ( len % 2 == 1 ) @@ -133,19 +122,17 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) else sum = 0; - //pseudoheader as in udp6 above + // Pseudo-header as for UDP over IPv6 above. sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum); sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum); uint32 l = htonl(len); sum = ones_complement_checksum((void*) &l, 4, sum); + uint32 addl_pseudo = htons(IPPROTO_ICMPV6); sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); - //pseudoheader complete sum = ones_complement_checksum((void*) icmpp, len, sum); - //printf("checksum, calculated for ICMP6: %d\n",sum); - return sum; } @@ -153,12 +140,6 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) int icmp_checksum(const struct icmp* icmpp, int len) { - /**From RFC - Checksum that covers the ICMP message. This is the 16-bit one's - complement of the one's complement sum of the ICMP message starting - with the Type field. The checksum field should be cleared to zero - before generating the checksum. - **/ uint32 sum; if ( len % 2 == 1 ) // Add in pad byte. @@ -168,15 +149,9 @@ int icmp_checksum(const struct icmp* icmpp, int len) sum = ones_complement_checksum((void*) icmpp, len, sum); - //printf("checksum, calculated for ICMP4: %d\n",sum); - return sum; } - - - - #define CLASS_A 0x00000000 #define CLASS_B 0x80000000 #define CLASS_C 0xc0000000 diff --git a/src/net_util.h b/src/net_util.h index 4c17104573..9a6c12b3c3 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -88,12 +88,14 @@ extern int ones_complement_checksum(const void* p, int b, uint32 sum); extern int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len); extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len); +extern int icmp_checksum(const struct icmp* icmpp, int len); + #ifdef BROv6 extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up, int len); -extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len); +extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, + int len); #endif -extern int icmp_checksum(const struct icmp* icmpp, int len); // Given an address in host order, returns its "classical network prefix", // also in host order. From c03efbb5701b57f1cfb809de67db008a9ddee16b Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 27 Jan 2012 22:55:42 -0500 Subject: [PATCH 03/19] Small updates for the bittorrent analyzer to support 64bit types in binpac. - This branch removes the attempt at bittorrent resynchronization. I don't think that the bittorrent resynchronization would really work very well anyway. - This need to be merged after the topic/seth/64bit-type branch in binpac. --- aux/binpac | 2 +- src/BitTorrent.cc | 67 ++++++++++++++++++++----------------- src/bittorrent-analyzer.pac | 24 ++++++------- src/bittorrent-protocol.pac | 14 ++++---- 4 files changed, 56 insertions(+), 51 deletions(-) diff --git a/aux/binpac b/aux/binpac index 43308aab47..35d69ffd88 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 43308aab47a3357ca1885e1b6954154a2744d821 +Subproject commit 35d69ffd88f14820c495a7b66c103f9b94a604ae diff --git a/src/BitTorrent.cc b/src/BitTorrent.cc index c58eb4cf65..66ebe31252 100644 --- a/src/BitTorrent.cc +++ b/src/BitTorrent.cc @@ -66,39 +66,44 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig) { - uint64 entry_offset = orig ? - *interp->upflow()->next_message_offset() : - *interp->downflow()->next_message_offset(); - uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp; - bool& this_stop = orig ? stop_orig : stop_resp; - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); - this_stream_len += len; - - if ( entry_offset < this_stream_len ) - { // entry point is somewhere in the gap - DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig); - this_stop = true; - if ( stop_orig && stop_resp ) - ProtocolViolation("BitTorrent: content gap and/or protocol violation"); - } - else - { // fill the gap - try - { - u_char gap[len]; - memset(gap, 0, len); - interp->NewData(orig, gap, gap + len); - } - catch ( binpac::Exception const &e ) - { - DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig); - this_stop = true; - if ( stop_orig && stop_resp ) - ProtocolViolation("BitTorrent: content gap and/or protocol violation"); - } - } + // I think that shoving data that is definitely wrong into the + // parser seems like a really bad idea. The way it's currently + // tracking the next message offset isn't compatible with + // new 64bit int support in binpac either. + + //uint64 entry_offset = orig ? + // *interp->upflow()->next_message_offset() : + // *interp->downflow()->next_message_offset(); + //uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp; + //bool& this_stop = orig ? stop_orig : stop_resp; + // + //this_stream_len += len; + // + //if ( entry_offset < this_stream_len ) + // { // entry point is somewhere in the gap + // DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig); + // this_stop = true; + // if ( stop_orig && stop_resp ) + // ProtocolViolation("BitTorrent: content gap and/or protocol violation"); + // } + //else + // { // fill the gap + // try + // { + // u_char gap[len]; + // memset(gap, 0, len); + // interp->NewData(orig, gap, gap + len); + // } + // catch ( binpac::Exception const &e ) + // { + // DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig); + // this_stop = true; + // if ( stop_orig && stop_resp ) + // ProtocolViolation("BitTorrent: content gap and/or protocol violation"); + // } + // } } void BitTorrent_Analyzer::EndpointEOF(TCP_Reassembler* endp) diff --git a/src/bittorrent-analyzer.pac b/src/bittorrent-analyzer.pac index ee7a70ea21..3bc6d90230 100644 --- a/src/bittorrent-analyzer.pac +++ b/src/bittorrent-analyzer.pac @@ -10,25 +10,25 @@ flow BitTorrent_Flow(is_orig: bool) { %member{ bool handshake_ok; - uint64 _next_message_offset; + //uint64 _next_message_offset; %} %init{ handshake_ok = false; - _next_message_offset = 0; + //_next_message_offset = 0; %} - function next_message_offset(): uint64 - %{ - return &_next_message_offset; - %} + #function next_message_offset(): uint64 + # %{ + # return &_next_message_offset; + # %} - function increment_next_message_offset(go: bool, len: uint32): bool - %{ - if ( go ) - _next_message_offset += len; - return true; - %} + #function increment_next_message_offset(go: bool, len: uint32): bool + # %{ + # if ( go ) + # _next_message_offset += len; + # return true; + # %} function is_handshake_delivered(): bool %{ diff --git a/src/bittorrent-protocol.pac b/src/bittorrent-protocol.pac index d3a147f157..76bbafbf20 100644 --- a/src/bittorrent-protocol.pac +++ b/src/bittorrent-protocol.pac @@ -22,8 +22,8 @@ type BitTorrent_Handshake = record { } &length = 68, &let { validate: bool = $context.flow.validate_handshake(pstrlen, pstr); - incoffsetffset: bool = - $context.flow.increment_next_message_offset(true, 68); + #incoffsetffset: bool = + # $context.flow.increment_next_message_offset(true, 68); deliver: bool = $context.flow.deliver_handshake(reserved, info_hash, peer_id); }; @@ -72,8 +72,8 @@ type BitTorrent_PieceHeader(len: uint32) = record { index: uint32; begin: uint32; } &let { - incoffset: bool = - $context.flow.increment_next_message_offset(true, len + 5); + #incoffset: bool = + # $context.flow.increment_next_message_offset(true, len + 5); }; type BitTorrent_Piece(len: uint32) = record { @@ -134,9 +134,9 @@ type BitTorrent_Message = record { default -> message_id: BitTorrent_MessageID(len.len); }; } &length = 4 + len.len, &let { - incoffset: bool = $context.flow.increment_next_message_offset( - len.len == 0 || message_id.id != TYPE_PIECE, - 4 + len.len); + #incoffset: bool = $context.flow.increment_next_message_offset( + # len.len == 0 || message_id.id != TYPE_PIECE, + # 4 + len.len); }; type BitTorrent_PDU = case $context.flow.is_handshake_delivered() of { From 6a3d0147a89aed473c9151d72cced6cbbb76a8e0 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Wed, 29 Feb 2012 11:29:28 -0600 Subject: [PATCH 04/19] Fix compile failure after merge from master --- src/ICMP.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ICMP.cc b/src/ICMP.cc index 7883686b00..b2b8f092f1 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -270,7 +270,7 @@ TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* s RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) { - const IP_Hdr ip_hdr_data((const struct ip*) data); + const IP_Hdr ip_hdr_data((const struct ip*) data, false); const IP_Hdr* ip_hdr = &ip_hdr_data; uint32 ip_hdr_len = ip_hdr->HdrLen(); @@ -338,7 +338,7 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) { - const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data); + const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false); const IP_Hdr* ip_hdr = &ip_hdr_data; int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0; TransportProto proto = TRANSPORT_UNKNOWN; From 6eb9f63e17845099e5c1137ba6e87b7f1821a700 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Fri, 2 Mar 2012 12:29:18 -0600 Subject: [PATCH 05/19] Add more icmpv6 events, and general code cleanup --- src/AnalyzerTags.h | 3 +- src/ICMP.cc | 59 ++++++++++---------- src/Sessions.cc | 18 +++---- src/Val.cc | 1 + src/Val.h | 1 - src/event.bif | 130 ++++++++++++++++++++++++++++++++++++++++++--- src/net_util.cc | 6 +-- 7 files changed, 164 insertions(+), 54 deletions(-) diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index 42d2f5626c..dc10a55f22 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -20,8 +20,7 @@ namespace AnalyzerTag { PIA_TCP, PIA_UDP, // Transport-layer analyzers. - ICMP, - TCP, UDP, + ICMP, TCP, UDP, // Application-layer analyzers (hand-written). BitTorrent, BitTorrentTracker, diff --git a/src/ICMP.cc b/src/ICMP.cc index b2b8f092f1..2fb1a9daab 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -52,10 +52,10 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, assert(caplen >= len); // Should have been caught earlier already. if ( ! ignore_checksums ) - { - int chksum = 0; + { + int chksum = 0; - switch ( ip->NextProto() ) + switch ( ip->NextProto() ) { case IPPROTO_ICMP: chksum = icmp_checksum(icmpp, len); @@ -69,11 +69,11 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, reporter->InternalError("unexpected IP proto in ICMP analyzer"); } - if ( chksum != 0xffff ) - { - Weird("bad_ICMP6_checksum"); - return; - } + if ( chksum != 0xffff ) + { + Weird("bad_ICMP_checksum"); + return; + } } Conn()->SetLastTime(current_timestamp); @@ -147,6 +147,8 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c break; // Router related messages. + case ND_NEIGHBOR_SOLICIT: + case ND_NEIGHBOR_ADVERT: case ND_REDIRECT: case ND_ROUTER_SOLICIT: case ICMP6_ROUTER_RENUMBERING: @@ -156,17 +158,9 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c #if 0 // Currently not specifically implemented. - case ICMP6_PARAM_PROB: case MLD_LISTENER_QUERY: case MLD_LISTENER_REPORT: case MLD_LISTENER_REDUCTION: - case ND_NEIGHBOR_SOLICIT: - case ND_NEIGHBOR_ADVERT: - case ND_REDIRECT: - case ICMP6_ROUTER_RENUMBERING: - case ND_NEIGHBOR_SOLICIT: - case ND_NEIGHBOR_ADVERT: - case ICMP6_TIME_EXCEEDED: #endif default: ICMPEvent(icmp_sent, icmpp, len, 1); @@ -221,7 +215,7 @@ TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* s case 1: proto = TRANSPORT_ICMP; break; case 6: proto = TRANSPORT_TCP; break; case 17: proto = TRANSPORT_UDP; break; - case 58: proto = TRANSPORT_ICMP; //TransportProto Hack // XXX What's this? + case 58: proto = TRANSPORT_ICMP; break; default: proto = TRANSPORT_UNKNOWN; break; } @@ -386,15 +380,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - //TransportProto Hack // XXX Likewise. - if ( ip_hdr->NextProto() == 58 || 17 ) //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more - { - iprec->Assign(2, new Val(58, TYPE_COUNT)); - } - else - { - iprec->Assign(2, new Val(proto, TYPE_COUNT)); - } + //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more + iprec->Assign(2, new Val(58, TYPE_COUNT)); iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); @@ -509,12 +496,21 @@ void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, switch ( icmpp->icmp_type ) { + case ND_NEIGHBOR_ADVERT: + f = icmp_neighbor_advertisement; + break; + case ND_NEIGHBOR_SOLICIT: + f = icmp_neighbor_solicitation; + break; case ND_ROUTER_ADVERT: f = icmp_router_advertisement; break; - - case ND_REDIRECT: case ND_ROUTER_SOLICIT: + f = icmp_router_solicitation; + break; + case ND_REDIRECT: + f = icmp_redirect; + break; case ICMP6_ROUTER_RENUMBERING: default: ICMPEvent(icmp_sent, icmpp, len, 1); @@ -567,11 +563,14 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, case ICMP6_DST_UNREACH: f = icmp_unreachable; break; - case ICMP6_PARAM_PROB: + f = icmp_parameter_problem; + break; case ICMP6_TIME_EXCEEDED: + f = icmp_time_exceeded; + break; case ICMP6_PACKET_TOO_BIG: - f = icmp_error_message; + f = icmp_packet_too_big; break; } diff --git a/src/Sessions.cc b/src/Sessions.cc index cd9d7bb250..309e841a06 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -310,8 +310,6 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* ++num_packets_processed; - - uint32 caplen = hdr->caplen - hdr_size; if ( caplen < sizeof(struct ip) ) { @@ -446,7 +444,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, int proto = ip_hdr->NextProto(); if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && - proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) // Added ICMPV6, Matti + proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) { dump_this_packet = 1; return; @@ -489,7 +487,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, caplen -= ip_hdr_len; uint32 min_hdr_len = (proto == IPPROTO_TCP) ? sizeof(struct tcphdr) : - (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); //needs checking for ICMPV6?, Matti + (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); if ( len < min_hdr_len ) { @@ -550,12 +548,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, break; } - case IPPROTO_ICMPV6: // new case, identical to ICMP, is this correct?? Matti + case IPPROTO_ICMPV6: { const struct icmp* icmpp = (const struct icmp *) data; id.src_port = icmpp->icmp_type; - //printf("TYPE: %d\n", id.src_port); //testing, Matti id.dst_port = ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, id.is_one_way); @@ -565,8 +562,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, d = &icmp_conns; break; - } + default: Weird(fmt("unknown_protocol %d", proto), hdr, pkt); return; @@ -735,13 +732,11 @@ Val* NetSessions::BuildHeader(const struct ip* ip) break; } - case IPPROTO_ICMPV6: //Added, Matti + case IPPROTO_ICMPV6: { const struct icmp* icmpp = (const struct icmp *) data; RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); - //printf("datalen:%d",data_len); //Testing, Matti - icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); pkt_hdr->Assign(3, icmp_hdr); @@ -1065,7 +1060,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, case IPPROTO_UDP: tproto = TRANSPORT_UDP; break; - case IPPROTO_ICMPV6: //TransportProto Hack + case IPPROTO_ICMPV6: tproto = TRANSPORT_ICMP; break; default: @@ -1150,6 +1145,7 @@ bool NetSessions::IsLikelyServerPort(uint32 port, TransportProto proto) const port |= UDP_PORT_MASK; else if ( proto == TRANSPORT_ICMP ) port |= ICMP_PORT_MASK; + return port_cache.find(port) != port_cache.end(); } diff --git a/src/Val.cc b/src/Val.cc index e19fffa379..db6e9eb23a 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -788,6 +788,7 @@ PortVal::PortVal(uint32 p, TransportProto port_type) : Val(TYPE_PORT) case TRANSPORT_ICMP: p |= ICMP_PORT_MASK; break; + default: break; // "other" } diff --git a/src/Val.h b/src/Val.h index fe6164e48f..ae8c53308e 100644 --- a/src/Val.h +++ b/src/Val.h @@ -534,7 +534,6 @@ public: int IsUDP() const; int IsICMP() const; - TransportProto PortType() const { if ( IsTCP() ) diff --git a/src/event.bif b/src/event.bif index db7464db55..d4148a2611 100644 --- a/src/event.bif +++ b/src/event.bif @@ -798,6 +798,24 @@ event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, ## icmp_time_exceeded icmp_unreachable event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); +## Generated for all ICMP error messages that are not handled separately with dedicated +## ICMP events. Bro's ICMP analyzer handles a number of ICMP messages directly +## with dedicated events. This handler acts as a fallback for those it doesn't. +## The *icmp* record provides more information about the message. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect +## icmp_time_exceeded icmp_unreachable +event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + ## Generated for ICMP *destination unreachable* messages. ## ## See `Wikipedia @@ -821,13 +839,28 @@ event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, pa ## icmp_time_exceeded event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); - - - -event icmp6_placeholder%(c: connection, icmp: icmp_conn, ICMP6: bool%); - +## Generated for ICMP *packet too big* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *too big* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Too big* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note +## that if the *too big* includes only a partial IP header for some reason, no +## fields of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded +event icmp_packet_too_big%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); ## Generated for ICMP *time exceeded* messages. ## @@ -852,6 +885,89 @@ event icmp6_placeholder%(c: connection, icmp: icmp_conn, ICMP6: bool%); ## icmp_unreachable event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); +## Generated for ICMP *parameter problem* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *parameter problem* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Parameter problem* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note that +## if the *parameter problem* includes only a partial IP header for some reason, no fields +## of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_unreachable +event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *router solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *router advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *neighbor solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *neighbor advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn%); + ## Generated for ICMP *redirect* messages. ## ## See `Wikipedia diff --git a/src/net_util.cc b/src/net_util.cc index d66e56711f..a367429257 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -90,7 +90,7 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len) int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) { // UDP over IPv6 uses the same checksum function as over IPv4 but a - // different pseuod-header over which it is computed. + // different pseudo-header over which it is computed. uint32 sum; if ( len % 2 == 1 ) @@ -116,8 +116,8 @@ int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) { - // ICMP6 uses the same checksum function as over ICMP4 but a different - // pseuod-header over which it is computed. + // ICMP6 uses the same checksum function as ICMP4 but a different + // pseudo-header over which it is computed. uint32 sum; if ( len % 2 == 1 ) From 9d1e51a91e162f6d8144aae094983db3dfc36bfa Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Fri, 2 Mar 2012 13:52:45 -0600 Subject: [PATCH 06/19] More code cleanup --- src/ICMP.cc | 15 ++++++++------- src/Val.h | 6 +++--- src/net_util.cc | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ICMP.cc b/src/ICMP.cc index 2fb1a9daab..76b19398fa 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -67,6 +67,7 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, default: reporter->InternalError("unexpected IP proto in ICMP analyzer"); + break; } if ( chksum != 0xffff ) @@ -108,7 +109,7 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr ) - { + { switch ( icmpp->icmp_type ) { case ICMP_ECHO: @@ -119,10 +120,11 @@ void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int c case ICMP_UNREACH: case ICMP_TIMXCEED: Context4(t, icmpp, len, caplen, data, ip_hdr); - break; + break; default: - ICMPEvent(icmp_sent, icmpp, len, 0); break; + ICMPEvent(icmp_sent, icmpp, len, 0); + break; } } @@ -257,6 +259,7 @@ TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* s default: *src_port = *dst_port = ntohs(0); + break; } return proto; @@ -350,7 +353,6 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) src_addr = dst_addr = 0; src_port = dst_port = 0; } - else { ip_len = ip_hdr->TotalLen(); @@ -394,7 +396,6 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) return iprec; } - bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */) { return 0; @@ -534,11 +535,11 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp, { case ICMP_UNREACH: f = icmp_unreachable; - break; + break; case ICMP_TIMXCEED: f = icmp_error_message; - break; + break; } if ( f ) diff --git a/src/Val.h b/src/Val.h index ae8c53308e..64c19b2d92 100644 --- a/src/Val.h +++ b/src/Val.h @@ -509,9 +509,9 @@ protected: #define NUM_PORT_SPACES 4 #define PORT_SPACE_MASK 0x30000 -#define TCP_PORT_MASK 0x10000 -#define UDP_PORT_MASK 0x20000 -#define ICMP_PORT_MASK 0x30000 +#define TCP_PORT_MASK 0x10000 +#define UDP_PORT_MASK 0x20000 +#define ICMP_PORT_MASK 0x30000 typedef enum { diff --git a/src/net_util.cc b/src/net_util.cc index a367429257..856e351138 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -122,7 +122,7 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) if ( len % 2 == 1 ) // Add in pad byte. - sum += htons(((const u_char*) icmpp)[len - 1] << 8); + sum = htons(((const u_char*) icmpp)[len - 1] << 8); else sum = 0; From 169b3c833fc66fde49fbd653c87fbf56d951b846 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Tue, 27 Mar 2012 17:55:39 -0500 Subject: [PATCH 07/19] Add more data to icmp events --- src/ICMP.cc | 101 ++++++++++++++++++++++++++++++++++++++++++-------- src/ICMP.h | 8 ++++ src/event.bif | 8 ++-- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/ICMP.cc b/src/ICMP.cc index 4df9cc049e..a5cfdbcb64 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -149,12 +149,20 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c break; // Router related messages. - case ND_NEIGHBOR_SOLICIT: - case ND_NEIGHBOR_ADVERT: case ND_REDIRECT: + Redirect(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_ROUTER_ADVERT: + RouterAdvert(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_NEIGHBOR_ADVERT: + NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_NEIGHBOR_SOLICIT: + NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr); + break; case ND_ROUTER_SOLICIT: case ICMP6_ROUTER_RENUMBERING: - case ND_ROUTER_ADVERT: Router(t, icmpp, len, caplen, data, ip_hdr); break; @@ -489,6 +497,81 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len, } +void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_router_advertisement; + uint32 reachable, retrans; + + memcpy(&reachable, data, sizeof(reachable)); + memcpy(&retrans, data + sizeof(reachable), sizeof(retrans)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new Val(icmpp->icmp_num_addrs, TYPE_COUNT)); + vl->append(new Val(icmpp->icmp_wpa & 0x80, TYPE_BOOL)); + vl->append(new Val(htons(icmpp->icmp_lifetime), TYPE_COUNT)); + vl->append(new Val(reachable, TYPE_INTERVAL)); + vl->append(new Val(retrans, TYPE_INTERVAL)); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_neighbor_advertisement; + in6_addr tgtaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_neighbor_solicitation; + in6_addr tgtaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::Redirect(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_redirect; + in6_addr tgtaddr, dstaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + memcpy(&dstaddr.s6_addr, data + sizeof(tgtaddr.s6_addr), sizeof(dstaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + vl->append(new AddrVal(IPAddr(dstaddr))); + + ConnectionEvent(f, vl); + } + + void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) { @@ -496,21 +579,9 @@ void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, switch ( icmpp->icmp_type ) { - case ND_NEIGHBOR_ADVERT: - f = icmp_neighbor_advertisement; - break; - case ND_NEIGHBOR_SOLICIT: - f = icmp_neighbor_solicitation; - break; - case ND_ROUTER_ADVERT: - f = icmp_router_advertisement; - break; case ND_ROUTER_SOLICIT: f = icmp_router_solicitation; break; - case ND_REDIRECT: - f = icmp_redirect; - break; case ICMP6_ROUTER_RENUMBERING: default: ICMPEvent(icmp_sent, icmpp, len, 1); diff --git a/src/ICMP.h b/src/ICMP.h index 427c183612..59a399f74f 100644 --- a/src/ICMP.h +++ b/src/ICMP.h @@ -39,6 +39,14 @@ protected: int caplen, const u_char*& data, const IP_Hdr* ip_hdr); void Context(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Redirect(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void RouterAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void NeighborAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void NeighborSolicit(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); void Router(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); diff --git a/src/event.bif b/src/event.bif index 7d0d4b2ef5..8e7b0be8a8 100644 --- a/src/event.bif +++ b/src/event.bif @@ -955,7 +955,7 @@ event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); ## ## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent ## icmp_time_exceeded icmp_unreachable -event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); +event icmp_router_advertisement%(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval%); ## Generated for ICMP *neighbor solicitation* messages. ## @@ -970,7 +970,7 @@ event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); ## ## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent ## icmp_time_exceeded icmp_unreachable -event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn%); +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt:addr%); ## Generated for ICMP *neighbor advertisement* messages. ## @@ -985,7 +985,7 @@ event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn%); ## ## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent ## icmp_time_exceeded icmp_unreachable -event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn%); +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, tgt:addr%); ## Generated for ICMP *redirect* messages. ## @@ -1002,7 +1002,7 @@ event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn%); ## ## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent ## icmp_time_exceeded icmp_unreachable -event icmp_redirect%(c: connection, icmp: icmp_conn, a: addr%); +event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr%); ## Generated when a TCP connection terminated, passing on statistics about the ## two endpoints. This event is always generated when Bro flushes the internal From 958c6c7cf438cbd8d118e63754f4849531d72196 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Apr 2012 11:09:07 -0500 Subject: [PATCH 08/19] Update IPv6 atomic fragment unit test to filter output of ICMPv6. Since that's not relevant to test. --- testing/btest/core/ipv6-atomic-frag.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing/btest/core/ipv6-atomic-frag.test b/testing/btest/core/ipv6-atomic-frag.test index 0829d8e973..8c8fe6ca64 100644 --- a/testing/btest/core/ipv6-atomic-frag.test +++ b/testing/btest/core/ipv6-atomic-frag.test @@ -3,5 +3,6 @@ event new_connection(c: connection) { - print c$id; + if ( c$id$resp_p == 80/tcp ) + print c$id; } From 27ba3118c1b7fb2efddac3ce2ec8ce5a3e26f554 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Apr 2012 11:37:08 -0500 Subject: [PATCH 09/19] Change ICMPv6 checksum calculation to use IP_Hdr wrapper. So that src/dst addresses used in pseudo-header are correct when there's certain extension headers (routing/destination). Add ICMP/ICMPv6 checksum unit tests. --- src/ICMP.cc | 2 +- src/net_util.cc | 6 +++--- src/net_util.h | 5 ++--- testing/btest/Baseline/core.checksums/bad.out | 4 ++++ testing/btest/Baseline/core.checksums/good.out | 1 + .../btest/Traces/chksums/ip4-icmp-bad-chksum.pcap | Bin 0 -> 82 bytes .../Traces/chksums/ip4-icmp-good-chksum.pcap | Bin 0 -> 82 bytes .../Traces/chksums/ip6-icmp6-bad-chksum.pcap | Bin 0 -> 109 bytes .../Traces/chksums/ip6-icmp6-good-chksum.pcap | Bin 0 -> 109 bytes .../chksums/ip6-route0-icmp6-bad-chksum.pcap | Bin 0 -> 133 bytes .../chksums/ip6-route0-icmp6-good-chksum.pcap | Bin 0 -> 133 bytes testing/btest/core/checksums.test | 8 ++++++++ 12 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap create mode 100644 testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap create mode 100644 testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap create mode 100644 testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap create mode 100644 testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap create mode 100644 testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap diff --git a/src/ICMP.cc b/src/ICMP.cc index a5cfdbcb64..9bd004e7f8 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -62,7 +62,7 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, break; case IPPROTO_ICMPV6: - chksum = icmp6_checksum(icmpp, ip->IP6_Hdr(), len); + chksum = icmp6_checksum(icmpp, ip, len); break; default: diff --git a/src/net_util.cc b/src/net_util.cc index 362a33b201..d91cf02de9 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -80,7 +80,7 @@ int mobility_header_checksum(const IP_Hdr* ip) } #endif -int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) +int icmp6_checksum(const struct icmp* icmpp, const IP_Hdr* ip, int len) { // ICMP6 uses the same checksum function as ICMP4 but a different // pseudo-header over which it is computed. @@ -93,8 +93,8 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) sum = 0; // Pseudo-header as for UDP over IPv6 above. - sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum); - sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum); + sum = ones_complement_checksum(ip->SrcAddr(), sum); + sum = ones_complement_checksum(ip->DstAddr(), sum); uint32 l = htonl(len); sum = ones_complement_checksum((void*) &l, 4, sum); diff --git a/src/net_util.h b/src/net_util.h index 92f0880014..fb410503f4 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -65,18 +65,17 @@ inline int seq_delta(uint32 a, uint32 b) } class IPAddr; +class IP_Hdr; // Returns the ones-complement checksum of a chunk of b short-aligned bytes. extern int ones_complement_checksum(const void* p, int b, uint32 sum); extern int ones_complement_checksum(const IPAddr& a, uint32 sum); -extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, - int len); +extern int icmp6_checksum(const struct icmp* icmpp, const IP_Hdr* ip, int len); extern int icmp_checksum(const struct icmp* icmpp, int len); #ifdef ENABLE_MOBILE_IPV6 -class IP_Hdr; extern int mobility_header_checksum(const IP_Hdr* ip); #endif diff --git a/testing/btest/Baseline/core.checksums/bad.out b/testing/btest/Baseline/core.checksums/bad.out index cd3c799277..57089a72a6 100644 --- a/testing/btest/Baseline/core.checksums/bad.out +++ b/testing/btest/Baseline/core.checksums/bad.out @@ -1,9 +1,13 @@ 1332784981.078396 weird: bad_IP_checksum 1332784885.686428 weird: bad_TCP_checksum 1332784933.501023 weird: bad_UDP_checksum +1334075363.536871 weird: bad_ICMP_checksum 1332785210.013051 weird: routing0_hdr 1332785210.013051 weird: bad_TCP_checksum 1332782580.798420 weird: routing0_hdr 1332782580.798420 weird: bad_UDP_checksum +1334075111.800086 weird: routing0_hdr +1334075111.800086 weird: bad_ICMP_checksum 1332785250.469132 weird: bad_TCP_checksum 1332781342.923813 weird: bad_UDP_checksum +1334074939.467194 weird: bad_ICMP_checksum diff --git a/testing/btest/Baseline/core.checksums/good.out b/testing/btest/Baseline/core.checksums/good.out index 627a330928..4330967d8d 100644 --- a/testing/btest/Baseline/core.checksums/good.out +++ b/testing/btest/Baseline/core.checksums/good.out @@ -1,2 +1,3 @@ 1332785125.596793 weird: routing0_hdr 1332782508.592037 weird: routing0_hdr +1334075027.053380 weird: routing0_hdr diff --git a/testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..cc60d879c4a7895581a609caa47aebe32d7cfa5e GIT binary patch literal 82 zcmca|c+)~A1{MYwaA0F#U<7g=$G7;a8*(sc0ofqTAaJ|m()$y8PE5PBfP=x6fk6hO W%z^RSu>&g@Q-C;?gMon;q!0iERTH29 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap b/testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..2b07326eabd4a1ba68f6b00bbefe7c072b372a08 GIT binary patch literal 82 zcmca|c+)~A1{MYwaA0F#U<7iO$G7;4=rS>A0ofqTAaJ|m()$y8PE5PBfP=x6fk6hO W%z^RSu>&g@Q-C;?gW>yskU{|aBo#0K literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..ce1dfa547a3b787632159f67c65b6603c1284e5b GIT binary patch literal 109 zcmca|c+)~A1{MYwaA0F#U<7ik<68WGDX=rR0@)z^9}FO>+U_QR82nZa3XCj2fSTEv d9yI>{7xe!>Dt}gX0|NsuNU5c7LB3I;GXUYo9wYz& literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..4051fa5bc550def32285d6d93fde68342216354e GIT binary patch literal 109 zcmca|c+)~A1{MYwaA0F#U<7jR$F}$j=x{K&0@)z^9}FO>+U_QR82nZa3XCj2fSTEv d9yI>{7xe!>Dt}gX14GDpkkax37dO9fGXUUU9{~UW literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..15e11ed3261c33a8319dd27d48a80d65eedc942b GIT binary patch literal 133 zcmca|c+)~A1{MYwaA0F#U<7iW$F=x}nes5i0@)z^9}FO>+U_QR80y*%3XCj2fSTEv t9yI>{7xe!>Dt}hC6%*Jn1_efj3Lwh}qMw1Wfq{V+#LjbZOb;$~1pv0KAEf{Q literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap new file mode 100644 index 0000000000000000000000000000000000000000..b7924cab6fd6a5188614cdefb6d9db64e6a41ab8 GIT binary patch literal 133 zcmca|c+)~A1{MYwaA0F#U<7g|$F=ykTwq{`1+qc-KNvt%wcSksG1Rpk6c|~405!8S tJ!t&@FX;b&RQ{}ND<-gE3<``46+o5|L_YH*#jAhtzTu%%nN3jptnAs_$% literal 0 HcmV?d00001 diff --git a/testing/btest/core/checksums.test b/testing/btest/core/checksums.test index c01ab710af..f5b3230686 100644 --- a/testing/btest/core/checksums.test +++ b/testing/btest/core/checksums.test @@ -1,15 +1,23 @@ # @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-tcp-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-icmp-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-tcp-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-icmp6-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-tcp-bad-chksum.pcap >>bad.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-icmp6-bad-chksum.pcap >>bad.out 2>&1 + + # @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-tcp-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-icmp-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-tcp-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-icmp6-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-tcp-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-icmp6-good-chksum.pcap >>good.out 2>&1 # @TEST-EXEC: btest-diff bad.out # @TEST-EXEC: btest-diff good.out From 86834c941cb45bfefb12b2096a0812aa17f2c02d Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 10 Apr 2012 16:14:33 -0700 Subject: [PATCH 10/19] Adding missing leak groups to a couple tests. Also activating leak checking for proxy in basic-cluster test. --- testing/btest/core/leaks/basic-cluster.bro | 9 ++++++--- testing/btest/core/leaks/remote.bro | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/testing/btest/core/leaks/basic-cluster.bro b/testing/btest/core/leaks/basic-cluster.bro index a82f52c8b2..f5b40c1104 100644 --- a/testing/btest/core/leaks/basic-cluster.bro +++ b/testing/btest/core/leaks/basic-cluster.bro @@ -1,11 +1,14 @@ # Needs perftools support. # +# @TEST-GROUP: leaks + # @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks + # @TEST-EXEC: btest-bg-run manager-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro -m %INPUT -# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT +# @TEST-EXEC: btest-bg-run proxy-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro -m %INPUT # @TEST-EXEC: sleep 1 -# @TEST-EXEC: btest-bg-run worker-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT -# @TEST-EXEC: btest-bg-run worker-2 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT +# @TEST-EXEC: btest-bg-run worker-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT +# @TEST-EXEC: btest-bg-run worker-2 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT # @TEST-EXEC: btest-bg-wait -k 30 # @TEST-EXEC: btest-diff manager-1/metrics.log diff --git a/testing/btest/core/leaks/remote.bro b/testing/btest/core/leaks/remote.bro index fa72ce6024..f888d8f6ee 100644 --- a/testing/btest/core/leaks/remote.bro +++ b/testing/btest/core/leaks/remote.bro @@ -1,5 +1,7 @@ # Needs perftools support. # +# @TEST-GROUP: leaks +# # @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks # # @TEST-EXEC: btest-bg-run sender HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m --pseudo-realtime %INPUT ../sender.bro From 51bad73e1ec0c2bc93c3770950491b6ac09345c5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 11 Apr 2012 16:27:31 -0500 Subject: [PATCH 11/19] Fixes for IPv6 truncation and ICMP/ICMP6 analysis. - Add more guards against trying to analyze captured packets with a truncated IPv6 static header or extension header chain. - Add back in the ICMP payload tracking for ICMP "connections". - Fix 'icmp_context' record construction. Some field assignments were mismatched for ICMP and ICMP6. Source and destination addresses were set incorrectly for context packets that don't contain a full IP header. Some fields for ICMP6 weren't filled out. - Changed ICMP Time Exceeded packets to raise the 'icmp_time_exceeded' event instead of 'icmp_error_message'. - Add unit tests for truncation and the main types of ICMP/ICMP6 that have specific events. - Documentation clarifications. --- scripts/base/init-bare.bro | 8 +- src/Frag.cc | 10 +- src/ICMP.cc | 52 +++++---- src/IP.cc | 28 ++++- src/IP.h | 68 +++++++++-- src/PacketSort.cc | 4 +- src/Sessions.cc | 7 +- .../Baseline/core.icmp.icmp-context/output | 12 ++ .../Baseline/core.icmp.icmp-events/output | 20 ++++ .../Baseline/core.icmp.icmp6-context/output | 16 +++ .../Baseline/core.icmp.icmp6-events/output | 55 +++++++++ testing/btest/Baseline/core.truncation/output | 3 + .../Traces/icmp/icmp-destunreach-ip.pcap | Bin 0 -> 102 bytes .../icmp/icmp-destunreach-no-context.pcap | Bin 0 -> 82 bytes .../icmp-destunreach-udp.pcap} | Bin testing/btest/Traces/icmp/icmp-ping.pcap | Bin 0 -> 480 bytes .../btest/Traces/icmp/icmp-timeexceeded.pcap | Bin 0 -> 114 bytes .../icmp/icmp6-destunreach-ip6ext-trunc.pcap | Bin 0 -> 142 bytes .../icmp/icmp6-destunreach-ip6ext-udp.pcap | Bin 0 -> 162 bytes .../Traces/icmp/icmp6-destunreach-ip6ext.pcap | Bin 0 -> 150 bytes .../icmp/icmp6-destunreach-no-context.pcap | Bin 0 -> 102 bytes .../Traces/icmp/icmp6-neighbor-advert.pcap | Bin 0 -> 118 bytes .../Traces/icmp/icmp6-neighbor-solicit.pcap | Bin 0 -> 118 bytes .../btest/Traces/icmp/icmp6-paramprob.pcap | Bin 0 -> 154 bytes testing/btest/Traces/icmp/icmp6-ping.pcap | Bin 0 -> 904 bytes testing/btest/Traces/icmp/icmp6-redirect.pcap | Bin 0 -> 134 bytes .../Traces/icmp/icmp6-router-advert.pcap | Bin 0 -> 110 bytes .../Traces/icmp/icmp6-router-solicit.pcap | Bin 0 -> 102 bytes .../btest/Traces/icmp/icmp6-timeexceeded.pcap | Bin 0 -> 154 bytes testing/btest/Traces/icmp/icmp6-toobig.pcap | Bin 0 -> 154 bytes testing/btest/Traces/trunc/ip4-trunc.pcap | Bin 0 -> 60 bytes testing/btest/Traces/trunc/ip6-ext-trunc.pcap | Bin 0 -> 94 bytes testing/btest/Traces/trunc/ip6-trunc.pcap | Bin 0 -> 88 bytes testing/btest/core/discarder.bro | 2 +- testing/btest/core/icmp/icmp-context.test | 14 +++ testing/btest/core/icmp/icmp-events.test | 44 +++++++ testing/btest/core/icmp/icmp6-context.test | 15 +++ testing/btest/core/icmp/icmp6-events.test | 110 ++++++++++++++++++ testing/btest/core/truncation.test | 6 + 39 files changed, 422 insertions(+), 52 deletions(-) create mode 100644 testing/btest/Baseline/core.icmp.icmp-context/output create mode 100644 testing/btest/Baseline/core.icmp.icmp-events/output create mode 100644 testing/btest/Baseline/core.icmp.icmp6-context/output create mode 100644 testing/btest/Baseline/core.icmp.icmp6-events/output create mode 100644 testing/btest/Baseline/core.truncation/output create mode 100644 testing/btest/Traces/icmp/icmp-destunreach-ip.pcap create mode 100644 testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap rename testing/btest/Traces/{icmp-unreach.trace => icmp/icmp-destunreach-udp.pcap} (100%) create mode 100644 testing/btest/Traces/icmp/icmp-ping.pcap create mode 100644 testing/btest/Traces/icmp/icmp-timeexceeded.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-trunc.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-neighbor-solicit.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-paramprob.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-ping.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-redirect.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-router-advert.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-router-solicit.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-timeexceeded.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-toobig.pcap create mode 100644 testing/btest/Traces/trunc/ip4-trunc.pcap create mode 100644 testing/btest/Traces/trunc/ip6-ext-trunc.pcap create mode 100644 testing/btest/Traces/trunc/ip6-trunc.pcap create mode 100644 testing/btest/core/icmp/icmp-context.test create mode 100644 testing/btest/core/icmp/icmp-events.test create mode 100644 testing/btest/core/icmp/icmp6-context.test create mode 100644 testing/btest/core/icmp/icmp6-events.test create mode 100644 testing/btest/core/truncation.test diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 3e615f7669..1863e44552 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -102,11 +102,13 @@ type icmp_conn: record { ## .. bro:see:: icmp_time_exceeded icmp_unreachable type icmp_context: record { id: conn_id; ##< The packet's 4-tuple. - len: count; ##< The lenght of the packet's IP header. + len: count; ##< The length of the IP packet (headers + payload). proto: count; ##< The packet's transport-layer protocol. frag_offset: count; ##< The packet's fragementation offset. - ## True if the packet's IP header is fully included in the context. If that is not - ## the case, the other fields will all be set to null values. + ## True if the packet's IP header is not fully included in the context + ## or if there is not enough of the transport header to determine source + ## and destination ports. If that is the cast, the appropriate fields + ## of this record will be set to null values. bad_hdr_len: bool; bad_checksum: bool; ##< True if the packet's IP checksum is not correct. MF: bool; ##< True if the packets *more fragements* flag is set. diff --git a/src/Frag.cc b/src/Frag.cc index 0261b97bf0..d873f5bc0c 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -150,7 +150,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n) { - IP_Hdr proto_h(proto_hdr, false); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); if ( memcmp((const void*) b1, (const void*) b2, n) ) s->Weird("fragment_inconsistency", &proto_h); @@ -182,7 +182,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) // can happen for benign reasons when we're // intermingling parts of two fragmented packets. - IP_Hdr proto_h(proto_hdr, false); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); s->Weird("fragment_size_inconsistency", &proto_h); // We decide to analyze the contiguous portion now. @@ -196,7 +196,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) else if ( last_block->upper > frag_size ) { - IP_Hdr proto_h(proto_hdr, false); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); s->Weird("fragment_size_inconsistency", &proto_h); frag_size = last_block->upper; } @@ -250,8 +250,8 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) { struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); - const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto); - reassembled_pkt = new IP_Hdr(reassem6, true, chain); + const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n); + reassembled_pkt = new IP_Hdr(reassem6, true, n, chain); } else diff --git a/src/ICMP.cc b/src/ICMP.cc index 9bd004e7f8..f65965f86f 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -93,6 +93,12 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, caplen -= 8; len -= 8; + int& len_stat = is_orig ? request_len : reply_len; + if ( len_stat < 0 ) + len_stat = len; + else + len_stat += len; + if ( ip->NextProto() == IPPROTO_ICMP ) NextICMP4(current_timestamp, icmpp, len, caplen, data, ip); else @@ -286,13 +292,12 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) IPAddr src_addr, dst_addr; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) + if ( len < (int)sizeof(struct ip) || ip_hdr_len > uint32(len) ) { // We don't have an entire IP header. bad_hdr_len = 1; ip_len = frag_offset = 0; DF = MF = bad_checksum = 0; - src_addr = dst_addr = 0; src_port = dst_port = 0; } @@ -331,9 +336,9 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); iprec->Assign(2, new Val(proto, TYPE_COUNT)); - iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); - iprec->Assign(4, new Val(bad_checksum, TYPE_BOOL)); - iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); + iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL)); iprec->Assign(6, new Val(MF, TYPE_BOOL)); iprec->Assign(7, new Val(DF, TYPE_BOOL)); @@ -342,32 +347,33 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) { - const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false); - const IP_Hdr* ip_hdr = &ip_hdr_data; - int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0; + int DF = 0, MF = 0, bad_hdr_len = 0; TransportProto proto = TRANSPORT_UNKNOWN; - uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40 IPAddr src_addr; IPAddr dst_addr; uint32 ip_len, frag_offset = 0; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) // XXX What's the 2nd part doing? + if ( len < (int)sizeof(struct ip6_hdr) ) { bad_hdr_len = 1; ip_len = 0; - src_addr = dst_addr = 0; src_port = dst_port = 0; } else { - ip_len = ip_hdr->TotalLen(); + const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false, len); + const IP_Hdr* ip_hdr = &ip_hdr_data; + ip_len = ip_hdr->TotalLen(); src_addr = ip_hdr->SrcAddr(); dst_addr = ip_hdr->DstAddr(); + frag_offset = ip_hdr->FragOffset(); + MF = ip_hdr->MF(); + DF = ip_hdr->DF(); - if ( uint32(len) >= ip_hdr_len + 4 ) + if ( uint32(len) >= uint32(ip_hdr->HdrLen() + 4) ) proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); else { @@ -388,17 +394,13 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - - //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more - iprec->Assign(2, new Val(58, TYPE_COUNT)); - - iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL)); - - // The following are not available for IPv6. - iprec->Assign(4, new Val(0, TYPE_BOOL)); // bad_checksum - iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); // frag_offset - iprec->Assign(6, new Val(0, TYPE_BOOL)); // MF - iprec->Assign(7, new Val(1, TYPE_BOOL)); // DF + iprec->Assign(2, new Val(proto, TYPE_COUNT)); + iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); + // bad_checksum is always false since IPv6 layer doesn't have a checksum + iprec->Assign(5, new Val(0, TYPE_BOOL)); + iprec->Assign(6, new Val(MF, TYPE_BOOL)); + iprec->Assign(7, new Val(DF, TYPE_BOOL)); return iprec; } @@ -608,7 +610,7 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp, break; case ICMP_TIMXCEED: - f = icmp_error_message; + f = icmp_time_exceeded; break; } diff --git a/src/IP.cc b/src/IP.cc index 3c4d1e4a8c..3decdae13f 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -419,20 +419,35 @@ static inline bool isIPv6ExtHeader(uint8 type) } } -void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) +void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len, + bool set_next, uint16 next) { length = 0; uint8 current_type, next_type; next_type = IPPROTO_IPV6; const u_char* hdrs = (const u_char*) ip6; + if ( total_len < (int)sizeof(struct ip6_hdr) ) + reporter->InternalError("IPv6_HdrChain::Init with truncated IP header"); + do { + // We can't determine a given header's length if there's less than + // two bytes of data available (2nd byte of extension headers is length) + if ( total_len < 2 ) return; + current_type = next_type; IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs); next_type = p->NextHdr(); - uint16 len = p->Length(); + uint16 cur_len = p->Length(); + + // If this header is truncated, don't add it to chain, don't go further + if ( cur_len > total_len ) + { + delete p; + return; + } if ( set_next && next_type == IPPROTO_FRAGMENT ) { @@ -444,16 +459,17 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next) // Check for routing headers and remember final destination address. if ( current_type == IPPROTO_ROUTING ) - ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, len); + ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, cur_len); #ifdef ENABLE_MOBILE_IPV6 // Only Mobile IPv6 has a destination option we care about right now. if ( current_type == IPPROTO_DSTOPTS ) - ProcessDstOpts((const struct ip6_dest*) hdrs, len); + ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len); #endif - hdrs += len; - length += len; + hdrs += cur_len; + length += cur_len; + total_len -= cur_len; } while ( current_type != IPPROTO_FRAGMENT && current_type != IPPROTO_ESP && #ifdef ENABLE_MOBILE_IPV6 diff --git a/src/IP.h b/src/IP.h index 96642f08f7..7e05ee98ea 100644 --- a/src/IP.h +++ b/src/IP.h @@ -142,12 +142,12 @@ public: /** * Initializes the header chain from an IPv6 header structure. */ - IPv6_Hdr_Chain(const struct ip6_hdr* ip6) : + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) : #ifdef ENABLE_MOBILE_IPV6 homeAddr(0), #endif finalDst(0) - { Init(ip6, false); } + { Init(ip6, len, false); } ~IPv6_Hdr_Chain() { @@ -250,14 +250,20 @@ protected: * Initializes the header chain from an IPv6 header structure, and replaces * the first next protocol pointer field that points to a fragment header. */ - IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next) : + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next, int len) : #ifdef ENABLE_MOBILE_IPV6 homeAddr(0), #endif finalDst(0) - { Init(ip6, true, next); } + { Init(ip6, len, true, next); } - void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0); + /** + * Initializes the header chain from an IPv6 header structure of a given + * length, possibly setting the first next protocol pointer field that + * points to a fragment header. + */ + void Init(const struct ip6_hdr* ip6, int total_len, bool set_next, + uint16 next = 0); /** * Process a routing header and allocate/remember the final destination @@ -294,9 +300,21 @@ protected: IPAddr* finalDst; }; +/** + * A class that wraps either an IPv4 or IPv6 packet and abstracts methods + * for inquiring about common features between the two. + */ class IP_Hdr { public: - IP_Hdr(const u_char* p, bool arg_del) + /** + * Attempts to construct the header from some blob of data based on IP + * version number. Caller must have already checked that the header + * is not truncated. + * @param p pointer to memory containing an IPv4 or IPv6 packet. + * @param arg_del whether to take ownership of \a p pointer's memory. + * @param len the length of data, in bytes, pointed to by \a p. + */ + IP_Hdr(const u_char* p, bool arg_del, int len) : ip4(0), ip6(0), del(arg_del), ip6_hdrs(0) { if ( ((const struct ip*)p)->ip_v == 4 ) @@ -304,7 +322,7 @@ public: else if ( ((const struct ip*)p)->ip_v == 6 ) { ip6 = (const struct ip6_hdr*)p; - ip6_hdrs = new IPv6_Hdr_Chain(ip6); + ip6_hdrs = new IPv6_Hdr_Chain(ip6, len); } else { @@ -314,18 +332,38 @@ public: } } + /** + * Construct the header wrapper from an IPv4 packet. Caller must have + * already checked that the header is not truncated. + * @param arg_ip4 pointer to memory containing an IPv4 packet. + * @param arg_del whether to take ownership of \a arg_ip4 pointer's memory. + */ IP_Hdr(const struct ip* arg_ip4, bool arg_del) : ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0) { } - IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, + /** + * Construct the header wrapper from an IPv6 packet. Caller must have + * already checked that the static IPv6 header is not truncated. If + * the packet contains extension headers and they are truncated, that can + * be checked afterwards by comparing \a len with \a TotalLen. E.g. + * NetSessions::DoNextPacket does this to skip truncated packets. + * @param arg_ip6 pointer to memory containing an IPv6 packet. + * @param arg_del whether to take ownership of \a arg_ip6 pointer's memory. + * @param len the packet's length in bytes. + * @param c an already-constructed header chain to take ownership of. + */ + IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len, const IPv6_Hdr_Chain* c = 0) : ip4(0), ip6(arg_ip6), del(arg_del), - ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6)) + ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)) { } + /** + * Destructor. + */ ~IP_Hdr() { if ( ip6 ) @@ -340,8 +378,14 @@ public: } } + /** + * If an IPv4 packet is wrapped, return a pointer to it, else null. + */ const struct ip* IP4_Hdr() const { return ip4; } + /** + * If an IPv6 packet is wrapped, return a pointer to it, else null. + */ const struct ip6_hdr* IP6_Hdr() const { return ip6; } /** @@ -441,9 +485,15 @@ public: { return ip4 ? ip4->ip_p : ((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); } + /** + * Returns the IPv4 Time to Live or IPv6 Hop Limit field. + */ unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; } + /** + * Returns whether the IP header indicates this packet is a fragment. + */ bool IsFragment() const { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : ip6_hdrs->IsFragment(); } diff --git a/src/PacketSort.cc b/src/PacketSort.cc index 04c525c4d1..a7e2b04572 100644 --- a/src/PacketSort.cc +++ b/src/PacketSort.cc @@ -28,8 +28,8 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, const struct ip* ip = (const struct ip*) (pkt + hdr_size); if ( ip->ip_v == 4 ) ip_hdr = new IP_Hdr(ip, false); - else if ( ip->ip_v == 6 ) - ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false); + else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) ) + ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size); else // Weird will be generated later in NetSessions::NextPacket. return; diff --git a/src/Sessions.cc b/src/Sessions.cc index d734f4b4a2..2dd6f7027b 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -281,7 +281,12 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr, else if ( ip->ip_v == 6 ) { - IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false); + if ( caplen < sizeof(struct ip6_hdr) ) + { + Weird("truncated_IP", hdr, pkt); + return; + } + IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen); DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size); } diff --git a/testing/btest/Baseline/core.icmp.icmp-context/output b/testing/btest/Baseline/core.icmp.icmp-context/output new file mode 100644 index 0000000000..9e252d8c38 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp-context/output @@ -0,0 +1,12 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=0, v6=F] + icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=20, v6=F] + icmp_context: [id=[orig_h=10.0.0.2, orig_p=0/unknown, resp_h=10.0.0.1, resp_p=0/unknown], len=20, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=3) + conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp] + icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F] + icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] diff --git a/testing/btest/Baseline/core.icmp.icmp-events/output b/testing/btest/Baseline/core.icmp.icmp-events/output new file mode 100644 index 0000000000..9d8f484921 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp-events/output @@ -0,0 +1,20 @@ +icmp_unreachable (code=3) + conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp] + icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F] + icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_time_exceeded (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=11/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=11, icode=0, len=32, v6=F] + icmp_context: [id=[orig_h=10.0.0.2, orig_p=30000/udp, resp_h=10.0.0.1, resp_p=13000/udp], len=32, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_echo_request (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_reply (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_request (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_reply (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] diff --git a/testing/btest/Baseline/core.icmp.icmp6-context/output b/testing/btest/Baseline/core.icmp.icmp6-context/output new file mode 100644 index 0000000000..4b75210a18 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp6-context/output @@ -0,0 +1,16 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=0, v6=T] + icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=40, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=48, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] diff --git a/testing/btest/Baseline/core.icmp.icmp6-events/output b/testing/btest/Baseline/core.icmp.icmp6-events/output new file mode 100644 index 0000000000..1ff26ff889 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp6-events/output @@ -0,0 +1,55 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_packet_too_big (code=0) + conn_id: [orig_h=fe80::dead, orig_p=2/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=2, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_time_exceeded (code=0) + conn_id: [orig_h=fe80::dead, orig_p=3/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=3, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_parameter_problem (code=0) + conn_id: [orig_h=fe80::dead, orig_p=4/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=4, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_echo_request (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_redirect (tgt=fe80::cafe, dest=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=137/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=137, icode=0, len=32, v6=T] +icmp_router_advertisement (hop_limit=0, managed=F, rlifetime=1800, reachable=0.000000, retrans=0.000000) + conn_id: [orig_h=fe80::dead, orig_p=134/icmp, resp_h=fe80::beef, resp_p=133/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=134, icode=0, len=8, v6=T] +icmp_neighbor_advertisement (tgt=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=136/icmp, resp_h=fe80::beef, resp_p=135/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=136, icode=0, len=16, v6=T] +icmp_router_solicitation + conn_id: [orig_h=fe80::dead, orig_p=133/icmp, resp_h=fe80::beef, resp_p=134/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=133, icode=0, len=0, v6=T] +icmp_neighbor_solicitation (tgt=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=135/icmp, resp_h=fe80::beef, resp_p=136/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=135, icode=0, len=16, v6=T] diff --git a/testing/btest/Baseline/core.truncation/output b/testing/btest/Baseline/core.truncation/output new file mode 100644 index 0000000000..ba8d3eedee --- /dev/null +++ b/testing/btest/Baseline/core.truncation/output @@ -0,0 +1,3 @@ +1334160095.895421 weird: truncated_IP +1334156241.519125 weird: truncated_IP +1334094648.590126 weird: truncated_IP diff --git a/testing/btest/Traces/icmp/icmp-destunreach-ip.pcap b/testing/btest/Traces/icmp/icmp-destunreach-ip.pcap new file mode 100644 index 0000000000000000000000000000000000000000..982f2e4734a8546743a4f16f956100587f20155a GIT binary patch literal 102 zcmca|c+)~A1{MYwaA0F#U<7g=-E8%*wBTj11F}JwLEv`BrS~WHoS1fL0SALC1A_rb hnFC|mDK4M}AZB7_`12p65GW@CmSaeJ4iX2+0|1#g6pH`= literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap b/testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap new file mode 100644 index 0000000000000000000000000000000000000000..1f904e3d9155161efe80e7d06747618935a649c4 GIT binary patch literal 82 zcmca|c+)~A1{MYwaA0F#U<7jZ-D>q;V8+9s1!RLTgTU>MOYcwYIWg_h0uBaO1_l|B VG6%-Adt5*bK+MF<@aI2BApi$W5@rAZ literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp-unreach.trace b/testing/btest/Traces/icmp/icmp-destunreach-udp.pcap similarity index 100% rename from testing/btest/Traces/icmp-unreach.trace rename to testing/btest/Traces/icmp/icmp-destunreach-udp.pcap diff --git a/testing/btest/Traces/icmp/icmp-ping.pcap b/testing/btest/Traces/icmp/icmp-ping.pcap new file mode 100644 index 0000000000000000000000000000000000000000..499769b280e4b3bb15d624cad1d12b83dc8e2ba9 GIT binary patch literal 480 zcmca|c+)~A1{MYw`2U}Qff2}Ye$eW#{DzMq3CIRv27%i^;>4a4K$3&Om4P8d**NJp!bXT)5PKmuF127_uwY!?53&tpD+5Cz zMK-zsZCv*OVI!s=7p(yKagjX2k13r%KQaRS=)%DFp_WuXf^7WxA7LXge$1iBMgT{r BV*~&I literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp-timeexceeded.pcap b/testing/btest/Traces/icmp/icmp-timeexceeded.pcap new file mode 100644 index 0000000000000000000000000000000000000000..27804b55592e6e857a7cde11c9e9fce153c900d9 GIT binary patch literal 114 zcmca|c+)~A1{MYwaA0F#U<7iW-Dvgy7Rkim1!RLTgTU>MOYcwYIWg_h0uBaO1_m3D rG6%-AeOy2dK+MF=z^MRI2$WL*%L%5P0*Qm~u=;a+= literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap new file mode 100644 index 0000000000000000000000000000000000000000..5aca9af1b5d72fac60a392d196c87be1ed57e31d GIT binary patch literal 162 zcmca|c+)~A1{MYwaA0F#U<7iiDq8$~TR9l2Kx`oX4+aobZFdtu3>Pbhe+?i84BT6b r%HQ{%k>TSqkZb~o5Me-5zwbS&`g>~y85qG%DK#)U!N9}Q7XbtSO1UAm literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap new file mode 100644 index 0000000000000000000000000000000000000000..996048e5ab117ff8e9bd87261c891dad320ac270 GIT binary patch literal 150 zcmca|c+)~A1{MYwaA0F#U<7iS3tRl(ePw3I1F}K*KNvt%wcSksF)XYc{xyIYFmP`z hDu3U5Mh0CbkZb~o;9x*gzwbS&`g?1w85qG%0RZo^9k2iZ literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap new file mode 100644 index 0000000000000000000000000000000000000000..cf15a7cf65c22b1922057b338802b61bb6470f51 GIT binary patch literal 102 zcmca|c+)~A1{MYwaA0F#U<7jb_O$xX?`31K1F}K*KNvt%wcSksF*vLo{xyIYFmP`z ODu3U5MurqQkSqY44i$O; literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap b/testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap new file mode 100644 index 0000000000000000000000000000000000000000..0a06329fb542245747ee47488d63499fc51af3e7 GIT binary patch literal 118 zcmca|c+)~A1{MYwaA0F#U<7hf&bIoCaIrG@0ofq@9}FO>+U_QR7!p?h|22RZFmP`z UDu3Vm4uM9eQ6r7 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-paramprob.pcap b/testing/btest/Traces/icmp/icmp6-paramprob.pcap new file mode 100644 index 0000000000000000000000000000000000000000..ab2d41cd3a294305fc65394648ea41424dccf628 GIT binary patch literal 154 zcmca|c+)~A1{MYwaA0F#U<7jfkGJ~&n!&iea_C^K`qHMbYwC$WW!Zxz~#t-xx3)~Yp{06e^ z)@FolWc!UM+pYp_d##VKjcmX10sY2G$ZsIqcI`meMz-IGvh5nsHU$HOZDjk67w9)O PLVg3;)M9MTH%| literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-router-advert.pcap b/testing/btest/Traces/icmp/icmp6-router-advert.pcap new file mode 100644 index 0000000000000000000000000000000000000000..9c3e557a9d26e12d1e8a1a3e8b2a818612a1dded GIT binary patch literal 110 zcmca|c+)~A1{MYwaA0F#U<7jho^JKG@nU9h1F}K*KNvt%wcSksF$Aps|7!p-VBp?b SRQ|sAZ45V9893NEU@8Ehi5Hy! literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-router-solicit.pcap b/testing/btest/Traces/icmp/icmp6-router-solicit.pcap new file mode 100644 index 0000000000000000000000000000000000000000..b33495aa8d3bb8d7b96ab21544882e6c90c87145 GIT binary patch literal 102 zcmca|c+)~A1{MYwaA0F#U<7h*o@wd$1Z0Eoe=vZkYP*{NV%S(Y{A&O)VBp?b mRQ|sA%nToPfn*av1dkw^`hD+F)!$oNYG8DNfrqCr0tf)R6(Vr} literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-toobig.pcap b/testing/btest/Traces/icmp/icmp6-toobig.pcap new file mode 100644 index 0000000000000000000000000000000000000000..92bf50f240fef9e6a75f84fe6f31b4e39c17bb7a GIT binary patch literal 154 zcmca|c+)~A1{MYwaA0F#U<7jf4z~KYxG^vk0ofq@9}FO>+U_QR7&cZ8{~ACH7`V3< pmA~&j6T_Qb3=FIc2_Pjrf@tdZy+>7lZ*8f8(Fq0~p1uem003M{A+rDg literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/trunc/ip4-trunc.pcap b/testing/btest/Traces/trunc/ip4-trunc.pcap new file mode 100644 index 0000000000000000000000000000000000000000..30df0ea94d9fef8ec78d6a461a2d0fc17b99aca8 GIT binary patch literal 60 zcmca|c+)~A1{MYwaA0F#U<7jRuWI$*yONhd1jyC{NebNVxb*(So)gn9E#P2qWnfTX GU<3fDI}bnr literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/trunc/ip6-ext-trunc.pcap b/testing/btest/Traces/trunc/ip6-ext-trunc.pcap new file mode 100644 index 0000000000000000000000000000000000000000..1de659084e22fcd6b1eec1d6fd9c5157e568c77c GIT binary patch literal 94 zcmca|c+)~A1{MYwaA0F#U<7h3R=4=;F>*4P0ofq@9}FO>+U_QR7$OV~3XCj2fSTEv Q9yI>{7xe!>Dt}fs009pgS^xk5 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/trunc/ip6-trunc.pcap b/testing/btest/Traces/trunc/ip6-trunc.pcap new file mode 100644 index 0000000000000000000000000000000000000000..0111caed0f32737b3b6d6667ecfd2e207e039c94 GIT binary patch literal 88 zcmca|c+)~A1{MYwaA0F#U<7h5&TjR;`kI}=0Lboutput # @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output # @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output -# @TEST-EXEC: bro -C -r $TRACES/icmp-unreach.trace discarder-icmp.bro >>output +# @TEST-EXEC: bro -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output # @TEST-EXEC: btest-diff output @TEST-START-FILE discarder-ip.bro diff --git a/testing/btest/core/icmp/icmp-context.test b/testing/btest/core/icmp/icmp-context.test new file mode 100644 index 0000000000..ca7a34c5aa --- /dev/null +++ b/testing/btest/core/icmp/icmp-context.test @@ -0,0 +1,14 @@ +# These tests all check that IPv6 context packet construction for ICMP6 works. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-no-context.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-ip.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: btest-diff output + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp-events.test b/testing/btest/core/icmp/icmp-events.test new file mode 100644 index 0000000000..1a54f05fba --- /dev/null +++ b/testing/btest/core/icmp/icmp-events.test @@ -0,0 +1,44 @@ +# These tests all check that ICMP6 events get raised with correct arguments. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-timeexceeded.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-ping.pcap %INPUT >>output 2>&1 + +# @TEST-EXEC: btest-diff output + +event icmp_sent(c: connection, icmp: icmp_conn) + { + print "icmp_sent"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_time_exceeded (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp6-context.test b/testing/btest/core/icmp/icmp6-context.test new file mode 100644 index 0000000000..dfa8271cbc --- /dev/null +++ b/testing/btest/core/icmp/icmp6-context.test @@ -0,0 +1,15 @@ +# These tests all check that IPv6 context packet construction for ICMP6 works. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-no-context.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-trunc.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: btest-diff output + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp6-events.test b/testing/btest/core/icmp/icmp6-events.test new file mode 100644 index 0000000000..64c14920ff --- /dev/null +++ b/testing/btest/core/icmp/icmp6-events.test @@ -0,0 +1,110 @@ +# These tests all check that ICMP6 events get raised with correct arguments. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-toobig.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-timeexceeded.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-paramprob.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-ping.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-redirect.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-advert.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-advert.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-solicit.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-solicit.pcap %INPUT >>output 2>&1 + +# @TEST-EXEC: btest-diff output + +event icmp_sent(c: connection, icmp: icmp_conn) + { + print "icmp_sent"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_packet_too_big (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_time_exceeded (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_parameter_problem (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr) + { + print "icmp_redirect (tgt=" + fmt("%s", tgt) + ", dest=" + fmt("%s", dest) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_error_message (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr) + { + print "icmp_neighbor_solicitation (tgt=" + fmt("%s", tgt) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr) + { + print "icmp_neighbor_advertisement (tgt=" + fmt("%s", tgt) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_router_solicitation(c: connection, icmp: icmp_conn) + { + print "icmp_router_solicitation"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval) + { + print "icmp_router_advertisement (hop_limit=" + fmt("%d", hop_limit) + ", managed=" + fmt("%s", managed) + ", rlifetime=" + fmt("%d", router_lifetime) + ", reachable=" + fmt("%f", reachable_time) + ", retrans=" + fmt("%f", retrans_timer) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } diff --git a/testing/btest/core/truncation.test b/testing/btest/core/truncation.test new file mode 100644 index 0000000000..16a60fe6db --- /dev/null +++ b/testing/btest/core/truncation.test @@ -0,0 +1,6 @@ +# Truncated IP packet's should not be analyzed, and generate truncated_IP weird + +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip4-trunc.pcap >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-trunc.pcap >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-ext-trunc.pcap >>output 2>&1 +# @TEST-EXEC: btest-diff output From c90148d073c276e3434b5977ed9e96498434b611 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 12 Apr 2012 10:28:10 -0500 Subject: [PATCH 12/19] Sync up patricia.c/h with pysubnettree repo --- src/patricia.c | 20 +------------------- src/patricia.h | 7 ------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/src/patricia.c b/src/patricia.c index c2e2016570..1dbc795ab7 100644 --- a/src/patricia.c +++ b/src/patricia.c @@ -115,16 +115,12 @@ local_inet_pton (int af, const char *src, void *dst) } } #ifdef NT -#ifdef HAVE_IPV6 else if (af == AF_INET6) { struct in6_addr Address; return (inet6_addr(src, &Address)); } -#endif /* HAVE_IPV6 */ -#endif /* NT */ -#ifndef NT +#else else { - errno = EAFNOSUPPORT; return -1; } @@ -160,10 +156,8 @@ my_inet_pton (int af, const char *src, void *dst) } memcpy (dst, xp, 4); return (1); -#ifdef HAVE_IPV6 } else if (af == AF_INET6) { return (local_inet_pton (af, src, dst)); -#endif /* HAVE_IPV6 */ } else { #ifndef NT errno = EAFNOSUPPORT; @@ -217,7 +211,6 @@ prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#ifdef HAVE_IPV6 else if (prefix->family == AF_INET6) { char *r; r = (char *) inet_ntop (AF_INET6, &prefix->add.sin6, buff, 48 /* a guess value */ ); @@ -227,7 +220,6 @@ prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#endif /* HAVE_IPV6 */ else return (NULL); } @@ -255,7 +247,6 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) int dynamic_allocated = 0; int default_bitlen = 32; -#ifdef HAVE_IPV6 if (family == AF_INET6) { default_bitlen = 128; if (prefix == NULL) { @@ -265,7 +256,6 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) memcpy (&prefix->add.sin6, dest, 16); } else -#endif /* HAVE_IPV6 */ if (family == AF_INET) { if (prefix == NULL) { #ifndef NT @@ -308,9 +298,7 @@ ascii2prefix (int family, char *string) u_long bitlen, maxbitlen = 0; char *cp; struct in_addr sin; -#ifdef HAVE_IPV6 struct in6_addr sin6; -#endif /* HAVE_IPV6 */ int result; char save[MAXLINE]; @@ -320,19 +308,15 @@ ascii2prefix (int family, char *string) /* easy way to handle both families */ if (family == 0) { family = AF_INET; -#ifdef HAVE_IPV6 if (strchr (string, ':')) family = AF_INET6; -#endif /* HAVE_IPV6 */ } if (family == AF_INET) { maxbitlen = 32; } -#ifdef HAVE_IPV6 else if (family == AF_INET6) { maxbitlen = 128; } -#endif /* HAVE_IPV6 */ if ((cp = strchr (string, '/')) != NULL) { bitlen = atol (cp + 1); @@ -355,7 +339,6 @@ ascii2prefix (int family, char *string) return (New_Prefix (AF_INET, &sin, bitlen)); } -#ifdef HAVE_IPV6 else if (family == AF_INET6) { // Get rid of this with next IPv6 upgrade #if defined(NT) && !defined(HAVE_INET_NTOP) @@ -367,7 +350,6 @@ ascii2prefix (int family, char *string) #endif /* NT */ return (New_Prefix (AF_INET6, &sin6, bitlen)); } -#endif /* HAVE_IPV6 */ else return (NULL); } diff --git a/src/patricia.h b/src/patricia.h index c4d3ce9b08..dc67226362 100644 --- a/src/patricia.h +++ b/src/patricia.h @@ -52,11 +52,6 @@ #include - -#ifndef HAVE_IPV6 -#define HAVE_IPV6 -#endif - /* typedef unsigned int u_int; */ typedef void (*void_fn_t)(); /* { from defs.h */ @@ -86,9 +81,7 @@ typedef struct _prefix_t { int ref_count; /* reference count */ union { struct in_addr sin; -#ifdef HAVE_IPV6 struct in6_addr sin6; -#endif /* IPV6 */ } add; } prefix_t; From 6aa4f00159b86eac4494d1646fe12f1debccb36e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Apr 2012 14:59:38 -0500 Subject: [PATCH 13/19] Add more support for 's that lack some structure definitions. --- config.h.in | 44 +++++++++++++++++++++++++++++ src/IP.h | 1 - src/net_util.h | 75 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/config.h.in b/config.h.in index 6c64fb61bc..b8e2cb9a88 100644 --- a/config.h.in +++ b/config.h.in @@ -152,3 +152,47 @@ #ifndef HAVE_DLT_PPP_SERIAL #define DLT_PPP_SERIAL @DLT_PPP_SERIAL@ #endif + +/* IPv6 Next Header values defined by RFC 3542 */ +#cmakedefine HAVE_IPPROTO_HOPOPTS +#ifndef HAVE_IPPROTO_HOPOPTS +#define IPPROTO_HOPOPTS 0 +#endif +#cmakedefine HAVE_IPPROTO_IPV6 +#ifndef HAVE_IPPROTO_IPV6 +#define IPPROTO_IPV6 41 +#endif +#cmakedefine HAVE_IPPROTO_ROUTING +#ifndef HAVE_IPPROTO_ROUTING +#define IPPROTO_ROUTING 43 +#endif +#cmakedefine HAVE_IPPROTO_FRAGMENT +#ifndef HAVE_IPPROTO_FRAGMENT +#define IPPROTO_FRAGMENT 44 +#endif +#cmakedefine HAVE_IPPROTO_ESP +#ifndef HAVE_IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif +#cmakedefine HAVE_IPPROTO_AH +#ifndef HAVE_IPPROTO_AH +#define IPPROTO_AH 51 +#endif +#cmakedefine HAVE_IPPROTO_ICMPV6 +#ifndef HAVE_IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif +#cmakedefine HAVE_IPPROTO_NONE +#ifndef HAVE_IPPROTO_NONE +#define IPPROTO_NONE 59 +#endif +#cmakedefine HAVE_IPPROTO_DSTOPTS +#ifndef HAVE_IPPROTO_DSTOPTS +#define IPPROTO_DSTOPTS 60 +#endif + +/* IPv6 options structure defined by RFC 3542 */ +#cmakedefine HAVE_IP6_OPT + +/* Common IPv6 extension structure */ +#cmakedefine HAVE_IP6_EXT diff --git a/src/IP.h b/src/IP.h index 96642f08f7..aacec3f190 100644 --- a/src/IP.h +++ b/src/IP.h @@ -12,7 +12,6 @@ #include #include #include -#include #ifdef ENABLE_MOBILE_IPV6 diff --git a/src/net_util.h b/src/net_util.h index 3f8eb01e2a..92188237d9 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -31,13 +31,80 @@ typedef enum { IPv4, IPv6 } IPFamily; #ifdef HAVE_NETINET_IP6_H #include + +#ifndef HAVE_IP6_OPT +struct ip6_opt { + uint8 ip6o_type; + uint8 ip6o_len; +}; +#endif // HAVE_IP6_OPT + +#ifndef HAVE_IP6_EXT +struct ip6_ext { + uint8 ip6e_nxt; + uint8 ip6e_len; +}; +#endif // HAVE_IP6_EXT + #else struct ip6_hdr { - uint16 ip6_plen; - uint8 ip6_nxt; - uint8 ip6_hlim; + union { + struct ip6_hdrctl { + uint32 ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits + flow-ID */ + uint16 ip6_un1_plen; /* payload length */ + uint8 ip6_un1_nxt; /* next header */ + uint8 ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8 ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ }; -#endif +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +struct ip6_opt { + uint8 ip6o_type; + uint8 ip6o_len; +}; + +struct ip6_ext { + uint8 ip6e_nxt; + uint8 ip6e_len; +}; + +struct ip6_frag { + uint8 ip6f_nxt; /* next header */ + uint8 ip6f_reserved; /* reserved field */ + uint16 ip6f_offlg; /* offset, reserved, and flag */ + uint32 ip6f_ident; /* identification */ +}; + +struct ip6_hbh { + uint8 ip6h_nxt; /* next header */ + uint8 ip6h_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +struct ip6_dest { + uint8 ip6d_nxt; /* next header */ + uint8 ip6d_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +struct ip6_rthdr { + uint8 ip6r_nxt; /* next header */ + uint8 ip6r_len; /* length in units of 8 octets */ + uint8 ip6r_type; /* routing type */ + uint8 ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ +}; +#endif // HAVE_NETINET_IP6_H // For Solaris. #if !defined(TCPOPT_WINDOW) && defined(TCPOPT_WSCALE) From bfa2720a81efbab660fa34b7e382b81b10cb12c5 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Sun, 15 Apr 2012 22:52:48 -0400 Subject: [PATCH 14/19] Removing QR flag from DNS log in response to question on mailing list. --- scripts/base/protocols/dns/main.bro | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index f73a947b5f..c50a8bdc54 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -39,8 +39,6 @@ export { rcode: count &log &optional; ## A descriptive name for the response code value. rcode_name: string &log &optional; - ## Whether the message is a query (F) or response (T). - QR: bool &log &default=F; ## The Authoritative Answer bit for response messages specifies that ## the responding name server is an authority for the domain name ## in the question section. From 18f5018a0d6cb7e3595fb186d58016b9c2ce2843 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Sun, 15 Apr 2012 22:52:48 -0400 Subject: [PATCH 15/19] Removing QR flag from DNS log in response to question on mailing list. --- scripts/base/protocols/dns/main.bro | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index f73a947b5f..c50a8bdc54 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -39,8 +39,6 @@ export { rcode: count &log &optional; ## A descriptive name for the response code value. rcode_name: string &log &optional; - ## Whether the message is a query (F) or response (T). - QR: bool &log &default=F; ## The Authoritative Answer bit for response messages specifies that ## the responding name server is an authority for the domain name ## in the question section. From fe2535b08ddc55203df035c74f0205b2acb61061 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 16 Apr 2012 18:08:16 -0700 Subject: [PATCH 16/19] Updating baselines for DNS change. --- testing/btest/Baseline/core.ipv6-frag/dns.log | 8 ++++---- .../scripts.policy.protocols.dns.event-priority/dns.log | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/testing/btest/Baseline/core.ipv6-frag/dns.log b/testing/btest/Baseline/core.ipv6-frag/dns.log index 50c9684bac..251f35d789 100644 --- a/testing/btest/Baseline/core.ipv6-frag/dns.log +++ b/testing/btest/Baseline/core.ipv6-frag/dns.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path dns -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z answers TTLs -#types time string addr port addr port enum count string count string count string count string bool bool bool bool bool count vector[string] vector[interval] -1331084278.438444 UWkUyAuUGXf 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR F T F T F 0 This TXT record should be ignored 1.000000 -1331084293.592245 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR F T F T F 0 This TXT record should be ignored 1.000000 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs +#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] +1331084278.438444 UWkUyAuUGXf 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 +1331084293.592245 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 diff --git a/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log index 9d80898e0f..f636093677 100644 --- a/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log +++ b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log @@ -3,6 +3,6 @@ #empty_field (empty) #unset_field - #path dns -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z answers TTLs auth addl -#types time string addr port addr port enum count string count string count string count string bool bool bool bool bool count vector[string] vector[interval] table[string] table[string] -930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F F T 0 4.3.2.1 31337.000000 - - +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs auth addl +#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] table[string] table[string] +930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F T 0 4.3.2.1 31337.000000 - - From fede289d74e1e651ea209b938c8a51204582a155 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 16 Apr 2012 18:12:25 -0700 Subject: [PATCH 17/19] Updating submodule(s). [nomail] --- aux/broctl | 2 +- aux/btest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aux/broctl b/aux/broctl index 2524b3aeda..d50e0efe13 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 2524b3aeda916b5daaad215c42860c1477c2606b +Subproject commit d50e0efe133c50d824753c86d068467e54a3c47d diff --git a/aux/btest b/aux/btest index 8da6c55697..1897d224ce 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 8da6c55697ff580600cfff474f4ccba2a592f911 +Subproject commit 1897d224ce295e91d20e458851759c99734a0a74 From b3596f28d7d865763d554cceac2d77f5bffd2b99 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 17 Apr 2012 17:40:39 -0700 Subject: [PATCH 18/19] Updating submodule(s). [nomail] --- CHANGES | 7 +++++++ VERSION | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 96f943d207..adebfff084 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,11 @@ +2.0-281 | 2012-04-17 17:40:39 -0700 + + * Small updates for the bittorrent analyzer to support 64bit types + in binpac. (Seth Hall) + + * Removed the attempt at bittorrent resynchronization. (Seth Hall) + 2.0-276 | 2012-04-17 17:35:56 -0700 * Add more support for 's that lack some structure diff --git a/VERSION b/VERSION index 04d66ce0ad..e628d94e94 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0-276 +2.0-281 diff --git a/aux/bro-aux b/aux/bro-aux index 12d32194c1..d885987e79 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 12d32194c19d2dce06818588a2aeccf234de1889 +Subproject commit d885987e7968669e34504b0403ac89bd13928e9a diff --git a/aux/broccoli b/aux/broccoli index 60898666ba..bead1168ae 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 60898666ba1df1913c08ad5045b1e56f974060cc +Subproject commit bead1168ae9c2d2ae216dd58522fbc05498ff2c8 diff --git a/aux/broctl b/aux/broctl index d50e0efe13..44cc3de5f6 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit d50e0efe133c50d824753c86d068467e54a3c47d +Subproject commit 44cc3de5f6f98a86b2516bdc48dd168e6a6a28fd From 94c666f30523520f220147ac303160b74bf9f268 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 17 Apr 2012 17:42:38 -0700 Subject: [PATCH 19/19] Updating submodule(s). [nomail] --- aux/binpac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/binpac b/aux/binpac index bdc1cb65b4..71c37019bc 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit bdc1cb65b49c75d171eac58335a763f74a5bf930 +Subproject commit 71c37019bc371eb7863fb6aa47a7daa4540f4f1f