From 9ae9b2aa4dca3c7fe1c4cb310dac8563caa36700 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 26 Jun 2012 16:59:56 -0500 Subject: [PATCH] Extract ICMPv6 NDP options and include in ICMP events (addresses #833). This adds a new parameter of type "icmp6_nd_options" to the ICMPv6 neighbor discovery events (icmp_redirect, icmp_router_solicitation, icmp_router_advertisement, icmp_neighbor_solicitation, icmp_neighbor_advertisement) which includes data extracted from all neighbor discovery options (RFC 4861) that are present in the ICMPv6 message. --- scripts/base/init-bare.bro | 55 +++++ src/ICMP.cc | 197 +++++++++++++++--- src/ICMP.h | 5 +- src/event.bif | 20 +- .../Baseline/core.icmp.icmp6-events/output | 5 + .../core.icmp.icmp6-nd-options/output | 28 +++ .../btest/Traces/icmp/icmp6-nd-options.pcap | Bin 0 -> 2144 bytes .../Traces/icmp/icmp6-redirect-hdr-opt.pcap | Bin 0 -> 198 bytes testing/btest/core/icmp/icmp6-events.test | 15 +- testing/btest/core/icmp/icmp6-nd-options.test | 35 ++++ 10 files changed, 321 insertions(+), 39 deletions(-) create mode 100644 testing/btest/Baseline/core.icmp.icmp6-nd-options/output create mode 100644 testing/btest/Traces/icmp/icmp6-nd-options.pcap create mode 100644 testing/btest/Traces/icmp/icmp6-redirect-hdr-opt.pcap create mode 100644 testing/btest/core/icmp/icmp6-nd-options.test diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 3a323ad7fe..ec75c76beb 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -115,6 +115,61 @@ type icmp_context: record { DF: bool; ##< True if the packets *don't fragment* flag is set. }; +## Values extracted from a Prefix Information option in an ICMPv6 neighbor +## discovery message as specified by :rfc:`4861`. +## +## .. bro:see:: icmp6_nd_option +type icmp6_nd_prefix_info: record { + ## Number of leading bits of the *prefix* that are valid. + prefix_len: count; + ## Flag indicating the prefix can be used for on-link determination. + L_flag: bool; + ## Autonomous address-configuration flag. + A_flag: bool; + ## Length of time in seconds that the prefix is valid for purpose of + ## on-link determination (0xffffffff represents infinity). + valid_lifetime: interval; + ## Length of time in seconds that the addresses generated from the prefix + ## via stateless address autoconfiguration remain preferred + ## (0xffffffff represents infinity). + preferred_lifetime: interval; + ## An IP address or prefix of an IP address. Use the *prefix_len* field + ## to convert this into a :bro:type:`subnet`. + prefix: addr; +}; + +## Options extracted from ICMPv6 neighbor discovery messages as specified +## by :rfc:`4861`. +## +## .. bro:see:: icmp_router_solicitation icmp_router_advertisement +## icmp_neighbor_advertisement icmp_neighbor_solicitation icmp_redirect +## icmp6_nd_options +type icmp6_nd_option: record { + ## 8-bit identifier of the type of option. + otype: count; + ## 8-bit integer representing the length of the option (including the type + ## and length fields) in units of 8 octets. + len: count; + ## Source Link-Layer Address (Type 1) or Target Link-Layer Address (Type 2). + ## Byte ordering of this is dependent on the actual link-layer. + link_address: string &optional; + ## Prefix Information (Type 3). + prefix: icmp6_nd_prefix_info &optional; + ## Redirected header (Type 4). This field contains the context of the + ## original, redirected packet. + redirect: icmp_context &optional; + ## Recommended MTU for the link (Type 5). + mtu: count &optional; + ## The raw data of the option (everything after type & length fields), + ## useful for unknown option types or when the full option payload is + ## truncated in the captured packet. In those cases, option fields + ## won't be pre-extracted into the fields above. + payload: string &optional; +}; + +## A type alias for a vector of ICMPv6 neighbor discovery message options. +type icmp6_nd_options: vector of icmp6_nd_option; + # A DNS mapping between IP address and hostname resolved by Bro's internal # resolver. # diff --git a/src/ICMP.cc b/src/ICMP.cc index b8ddb8a292..5531d6ee45 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -169,8 +169,10 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr); break; case ND_ROUTER_SOLICIT: + RouterSolicit(t, icmpp, len, caplen, data, ip_hdr); + break; case ICMP6_ROUTER_RENUMBERING: - Router(t, icmpp, len, caplen, data, ip_hdr); + ICMPEvent(icmp_sent, icmpp, len, 1, ip_hdr); break; #if 0 @@ -515,10 +517,12 @@ 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; + uint32 reachable = 0, retrans = 0; - memcpy(&reachable, data, sizeof(reachable)); - memcpy(&retrans, data + sizeof(reachable), sizeof(retrans)); + if ( caplen >= (int)sizeof(reachable) ) + memcpy(&reachable, data, sizeof(reachable)); + if ( caplen >= (int)sizeof(reachable) + (int)sizeof(retrans) ) + memcpy(&retrans, data + sizeof(reachable), sizeof(retrans)); val_list* vl = new val_list; vl->append(BuildConnVal()); @@ -534,6 +538,9 @@ void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len, vl->append(new IntervalVal((double)ntohl(reachable), Milliseconds)); vl->append(new IntervalVal((double)ntohl(retrans), Milliseconds)); + int opt_offset = sizeof(reachable) + sizeof(retrans); + vl->append(BuildNDOptionsVal(caplen - opt_offset, data + opt_offset)); + ConnectionEvent(f, vl); } @@ -542,9 +549,10 @@ 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; + IPAddr tgtaddr; - memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + if ( caplen >= (int)sizeof(in6_addr) ) + tgtaddr = IPAddr(*((const in6_addr*)data)); val_list* vl = new val_list; vl->append(BuildConnVal()); @@ -552,7 +560,10 @@ void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len, vl->append(new Val(icmpp->icmp_num_addrs & 0x80, TYPE_BOOL)); // Router vl->append(new Val(icmpp->icmp_num_addrs & 0x40, TYPE_BOOL)); // Solicited vl->append(new Val(icmpp->icmp_num_addrs & 0x20, TYPE_BOOL)); // Override - vl->append(new AddrVal(IPAddr(tgtaddr))); + vl->append(new AddrVal(tgtaddr)); + + int opt_offset = sizeof(in6_addr); + vl->append(BuildNDOptionsVal(caplen - opt_offset, data + opt_offset)); ConnectionEvent(f, vl); } @@ -562,14 +573,18 @@ 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; + IPAddr tgtaddr; - memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + if ( caplen >= (int)sizeof(in6_addr) ) + tgtaddr = IPAddr(*((const in6_addr*)data)); val_list* vl = new val_list; vl->append(BuildConnVal()); vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr)); - vl->append(new AddrVal(IPAddr(tgtaddr))); + vl->append(new AddrVal(tgtaddr)); + + int opt_offset = sizeof(in6_addr); + vl->append(BuildNDOptionsVal(caplen - opt_offset, data + opt_offset)); ConnectionEvent(f, vl); } @@ -579,40 +594,35 @@ 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; + IPAddr tgtaddr, dstaddr; - memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); - memcpy(&dstaddr.s6_addr, data + sizeof(tgtaddr.s6_addr), sizeof(dstaddr.s6_addr)); + if ( caplen >= (int)sizeof(in6_addr) ) + tgtaddr = IPAddr(*((const in6_addr*)data)); + if ( caplen >= 2 * (int)sizeof(in6_addr) ) + dstaddr = IPAddr(*((const in6_addr*)(data + sizeof(in6_addr)))); val_list* vl = new val_list; vl->append(BuildConnVal()); vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr)); - vl->append(new AddrVal(IPAddr(tgtaddr))); - vl->append(new AddrVal(IPAddr(dstaddr))); + vl->append(new AddrVal(tgtaddr)); + vl->append(new AddrVal(dstaddr)); + + int opt_offset = 2 * sizeof(in6_addr); + vl->append(BuildNDOptionsVal(caplen - opt_offset, data + opt_offset)); ConnectionEvent(f, vl); } -void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, +void ICMP_Analyzer::RouterSolicit(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 ND_ROUTER_SOLICIT: - f = icmp_router_solicitation; - break; - case ICMP6_ROUTER_RENUMBERING: - default: - ICMPEvent(icmp_sent, icmpp, len, 1, ip_hdr); - return; - } + EventHandlerPtr f = icmp_router_solicitation; val_list* vl = new val_list; vl->append(BuildConnVal()); vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr)); + vl->append(BuildNDOptionsVal(caplen, data)); ConnectionEvent(f, vl); } @@ -685,6 +695,137 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, } } +VectorVal* ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data) + { + static RecordType* icmp6_nd_option_type = 0; + static RecordType* icmp6_nd_prefix_info_type = 0; + if ( ! icmp6_nd_option_type ) + { + icmp6_nd_option_type = internal_type("icmp6_nd_option")->AsRecordType(); + icmp6_nd_prefix_info_type = + internal_type("icmp6_nd_prefix_info")->AsRecordType(); + } + + VectorVal* vv = new VectorVal( + internal_type("icmp6_nd_options")->AsVectorType()); + + while ( caplen > 0 ) + { + // Must have at least type & length to continue parsing options. + if ( caplen < 2 ) + { + Weird("truncated_ICMPv6_ND_options"); + break; + } + + uint8 type = *((const uint8*)data); + uint8 length = *((const uint8*)(data + 1)); + + if ( length == 0 ) + { + Weird("zero_length_ICMPv6_ND_option"); + break; + } + + RecordVal* rv = new RecordVal(icmp6_nd_option_type); + rv->Assign(0, new Val(type, TYPE_COUNT)); + rv->Assign(1, new Val(length, TYPE_COUNT)); + + // adjust length to be in units of bytes, exclude type/length fields + length = length * 8 - 2; + + data += 2; + caplen -= 2; + + bool set_payload_field = false; + // Only parse out known options that are there in full. + switch ( type ) { + case 1: + case 2: + // Source/Target Link-layer Address option + { + if ( caplen >= length ) + { + BroString* link_addr = new BroString(data, length, 0); + rv->Assign(2, new StringVal(link_addr)); + } + else + set_payload_field = true; + } + break; + + case 3: + // Prefix Information option + { + if ( caplen >= 30 ) + { + RecordVal* info = new RecordVal(icmp6_nd_prefix_info_type); + uint8 prefix_len = *((const uint8*)(data)); + bool L_flag = (*((const uint8*)(data + 1)) & 0x80) != 0; + bool A_flag = (*((const uint8*)(data + 1)) & 0x40) != 0; + uint32 valid_life = *((const uint32*)(data + 2)); + uint32 prefer_life = *((const uint32*)(data + 6)); + in6_addr prefix = *((const in6_addr*)(data + 14)); + info->Assign(0, new Val(prefix_len, TYPE_COUNT)); + info->Assign(1, new Val(L_flag, TYPE_BOOL)); + info->Assign(2, new Val(A_flag, TYPE_BOOL)); + info->Assign(3, new IntervalVal((double)ntohl(valid_life), Seconds)); + info->Assign(4, new IntervalVal((double)ntohl(prefer_life), Seconds)); + info->Assign(5, new AddrVal(IPAddr(prefix))); + rv->Assign(3, info); + } + else + set_payload_field = true; + } + break; + + case 4: + // Redirected Header option + { + if ( caplen >= length ) + { + const u_char* hdr = data + 6; + rv->Assign(4, ExtractICMP6Context(length - 6, hdr)); + } + else + set_payload_field = true; + } + break; + + case 5: + // MTU option + { + if ( caplen >= 6 ) + rv->Assign(5, new Val(ntohl(*((const uint32*)(data + 2))), + TYPE_COUNT)); + else + set_payload_field = true; + } + break; + + default: + { + set_payload_field = true; + } + break; + } + + if ( set_payload_field ) + { + BroString* payload = + new BroString(data, min((int)length, caplen), 0); + rv->Assign(6, new StringVal(payload)); + } + + data += length; + caplen -= length; + + vv->Assign(vv->Size(), rv, 0); + } + + return vv; + } + int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; diff --git a/src/ICMP.h b/src/ICMP.h index 33773b9762..1e30b7ff54 100644 --- a/src/ICMP.h +++ b/src/ICMP.h @@ -48,7 +48,7 @@ protected: 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, + void RouterSolicit(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); void Describe(ODesc* d) const; @@ -75,6 +75,9 @@ protected: void Context6(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + // RFC 4861 Neighbor Discover message options + VectorVal* BuildNDOptionsVal(int caplen, const u_char* data); + RecordVal* icmp_conn_val; int type; int code; diff --git a/src/event.bif b/src/event.bif index a924bf4888..e0d1c2e1c6 100644 --- a/src/event.bif +++ b/src/event.bif @@ -1054,9 +1054,11 @@ event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, conte ## icmp: Additional ICMP-specific information augmenting the standard connection ## record *c*. ## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## ## .. bro:see:: icmp_router_advertisement ## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect -event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); +event icmp_router_solicitation%(c: connection, icmp: icmp_conn, options: icmp6_nd_options%); ## Generated for ICMP *router advertisement* messages. ## @@ -1090,9 +1092,11 @@ event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); ## ## retrans_timer: How long a host should wait before retransmitting. ## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## ## .. bro:see:: icmp_router_solicitation ## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect -event icmp_router_advertisement%(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval%); +event icmp_router_advertisement%(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options%); ## Generated for ICMP *neighbor solicitation* messages. ## @@ -1107,9 +1111,11 @@ event icmp_router_advertisement%(c: connection, icmp: icmp_conn, cur_hop_limit: ## ## tgt: The IP address of the target of the solicitation. ## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## ## .. bro:see:: icmp_router_solicitation icmp_router_advertisement ## icmp_neighbor_advertisement icmp_redirect -event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt:addr%); +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt: addr, options: icmp6_nd_options%); ## Generated for ICMP *neighbor advertisement* messages. ## @@ -1131,9 +1137,11 @@ event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt:addr%); ## tgt: the Target Address in the soliciting message or the address whose ## link-layer address has changed for unsolicited adverts. ## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## ## .. bro:see:: icmp_router_solicitation icmp_router_advertisement ## icmp_neighbor_solicitation icmp_redirect -event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt:addr%); +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options%); ## Generated for ICMP *redirect* messages. ## @@ -1151,9 +1159,11 @@ event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, router: bool, ## ## dest: The address of the destination which is redirected to the target. ## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## ## .. bro:see:: icmp_router_solicitation icmp_router_advertisement ## icmp_neighbor_solicitation icmp_neighbor_advertisement -event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr%); +event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options%); ## Generated when a TCP connection terminated, passing on statistics about the ## two endpoints. This event is always generated when Bro flushes the internal diff --git a/testing/btest/Baseline/core.icmp.icmp6-events/output b/testing/btest/Baseline/core.icmp.icmp6-events/output index 81075b716a..fdb58e5be1 100644 --- a/testing/btest/Baseline/core.icmp.icmp6-events/output +++ b/testing/btest/Baseline/core.icmp.icmp6-events/output @@ -41,6 +41,7 @@ icmp_echo_reply (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi) 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, hlim=255, v6=T] + options: [] icmp_router_advertisement cur_hop_limit=13 managed=T @@ -54,15 +55,19 @@ icmp_router_advertisement retrans_timer=1.0 sec 300.0 msecs 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, hlim=255, v6=T] + options: [] icmp_neighbor_advertisement (tgt=fe80::babe) router=T solicited=F override=T 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, hlim=255, v6=T] + options: [] 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, hlim=255, v6=T] + options: [] 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, hlim=255, v6=T] + options: [] diff --git a/testing/btest/Baseline/core.icmp.icmp6-nd-options/output b/testing/btest/Baseline/core.icmp.icmp6-nd-options/output new file mode 100644 index 0000000000..1a3958f32d --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp6-nd-options/output @@ -0,0 +1,28 @@ +icmp_redirect options + [otype=4, len=8, link_address=, prefix=, redirect=[id=[orig_h=fe80::aaaa, orig_p=30000/udp, resp_h=fe80::bbbb, resp_p=13000/udp], len=56, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F], mtu=, payload=] +icmp_neighbor_advertisement options + [otype=2, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 +icmp_router_advertisement options + [otype=1, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 + [otype=5, len=1, link_address=, prefix=, redirect=, mtu=1500, payload=] + [otype=3, len=4, link_address=, prefix=[prefix_len=64, L_flag=T, A_flag=T, valid_lifetime=30.0 days, preferred_lifetime=7.0 days, prefix=2001:db8:0:1::], redirect=, mtu=, payload=] +icmp_neighbor_advertisement options + [otype=2, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 +icmp_router_advertisement options + [otype=1, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 + [otype=5, len=1, link_address=, prefix=, redirect=, mtu=1500, payload=] + [otype=3, len=4, link_address=, prefix=[prefix_len=64, L_flag=T, A_flag=T, valid_lifetime=30.0 days, preferred_lifetime=7.0 days, prefix=2001:db8:0:1::], redirect=, mtu=, payload=] +icmp_router_advertisement options + [otype=1, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 + [otype=5, len=1, link_address=, prefix=, redirect=, mtu=1500, payload=] + [otype=3, len=4, link_address=, prefix=[prefix_len=64, L_flag=T, A_flag=T, valid_lifetime=30.0 days, preferred_lifetime=7.0 days, prefix=2001:db8:0:1::], redirect=, mtu=, payload=] +icmp_router_advertisement options + [otype=1, len=1, link_address=\xc2\0T\xf5\0\0, prefix=, redirect=, mtu=, payload=] + MAC: c20054f50000 + [otype=5, len=1, link_address=, prefix=, redirect=, mtu=1500, payload=] + [otype=3, len=4, link_address=, prefix=[prefix_len=64, L_flag=T, A_flag=T, valid_lifetime=30.0 days, preferred_lifetime=7.0 days, prefix=2001:db8:0:1::], redirect=, mtu=, payload=] diff --git a/testing/btest/Traces/icmp/icmp6-nd-options.pcap b/testing/btest/Traces/icmp/icmp6-nd-options.pcap new file mode 100644 index 0000000000000000000000000000000000000000..1103d9bf9c853e79ba52b6d3addd9ad609dd2864 GIT binary patch literal 2144 zcmca|c+)~A1{MZ5P+(wS1ah(yHhKKiV?K(g&_9#Diq!sW_AouLe<286NL;y~DzHijer92nR+fChj8Bh++OP%tsD z-eG2OIKZIZ%fP^C)c_JvVC3Baq`HpA)H!`OoK*&cLGyB-`#L07H>M0g+2VTo6DCaYm4OSiWm!cn-?d z81f)nd>(Kz*a7807@WJAP;BAATTX%uWol)p2Ad8ttp#WrQmKpXW5t7JW#Pb;hagu-u4hD!7l8^rln^5nFF^H(c$uIE@+(Tb0p&rq z)B$Zl3Q2TZ2!$k2eLKUR=OEKz`SS1dpC490O<#*@I$815`5oDGSUgPzx_#ell$49^ tc3=ph$1ZvZAVNr51!N1l{1l)q+dP<%;{n|dglqw-N7z!d4Z{|oJOFqZl^g&7 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/icmp/icmp6-redirect-hdr-opt.pcap b/testing/btest/Traces/icmp/icmp6-redirect-hdr-opt.pcap new file mode 100644 index 0000000000000000000000000000000000000000..d05351910849141fd8f407973a86bd7340bd3406 GIT binary patch literal 198 zcmca|c+)~A1{MYw_+QV!zzF1o>%8)Rw~>iq9*_;f|G@yFs_kw9h>>CS|6c=$0R#8e zqVo5>?__v<3?z#xe(E18f7d=14u}~EAWA^c0abq0DpdaN-K7RbCl~}K^F%-a0Iz>6 AssI20 literal 0 HcmV?d00001 diff --git a/testing/btest/core/icmp/icmp6-events.test b/testing/btest/core/icmp/icmp6-events.test index 052ba91ee6..5263dd6e7f 100644 --- a/testing/btest/core/icmp/icmp6-events.test +++ b/testing/btest/core/icmp/icmp6-events.test @@ -66,11 +66,12 @@ event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, contex print " icmp_context: " + fmt("%s", context); } -event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr) +event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options) { print "icmp_redirect (tgt=" + fmt("%s", tgt) + ", dest=" + fmt("%s", dest) + ")"; print " conn_id: " + fmt("%s", c$id); print " icmp_conn: " + fmt("%s", icmp); + print " options: " + fmt("%s", options); } event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) @@ -81,14 +82,15 @@ event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: i print " icmp_context: " + fmt("%s", context); } -event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr) +event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr, options: icmp6_nd_options) { print "icmp_neighbor_solicitation (tgt=" + fmt("%s", tgt) + ")"; print " conn_id: " + fmt("%s", c$id); print " icmp_conn: " + fmt("%s", icmp); + print " options: " + fmt("%s", options); } -event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr) +event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options) { print "icmp_neighbor_advertisement (tgt=" + fmt("%s", tgt) + ")"; print " router=" + fmt("%s", router); @@ -96,16 +98,18 @@ event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, router: bool, print " override=" + fmt("%s", override); print " conn_id: " + fmt("%s", c$id); print " icmp_conn: " + fmt("%s", icmp); + print " options: " + fmt("%s", options); } -event icmp_router_solicitation(c: connection, icmp: icmp_conn) +event icmp_router_solicitation(c: connection, icmp: icmp_conn, options: icmp6_nd_options) { print "icmp_router_solicitation"; print " conn_id: " + fmt("%s", c$id); print " icmp_conn: " + fmt("%s", icmp); + print " options: " + fmt("%s", options); } -event icmp_router_advertisement(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval) +event icmp_router_advertisement(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options) { print "icmp_router_advertisement"; print " cur_hop_limit=" + fmt("%s", cur_hop_limit); @@ -120,4 +124,5 @@ event icmp_router_advertisement(c: connection, icmp: icmp_conn, cur_hop_limit: c print " retrans_timer=" + fmt("%s", retrans_timer); print " conn_id: " + fmt("%s", c$id); print " icmp_conn: " + fmt("%s", icmp); + print " options: " + fmt("%s", options); } diff --git a/testing/btest/core/icmp/icmp6-nd-options.test b/testing/btest/core/icmp/icmp6-nd-options.test new file mode 100644 index 0000000000..64543852a3 --- /dev/null +++ b/testing/btest/core/icmp/icmp6-nd-options.test @@ -0,0 +1,35 @@ +# These tests all check that ICMP6 events get raised with correct arguments. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-redirect-hdr-opt.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-nd-options.pcap %INPUT >>output 2>&1 + +# @TEST-EXEC: btest-diff output + +event icmp_router_advertisement(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options) + { + print "icmp_router_advertisement options"; + for ( o in options ) + { + print fmt(" %s", options[o]); + if ( options[o]$otype == 1 && options[o]?$link_address ) + print fmt(" MAC: %s", + string_to_ascii_hex(options[o]$link_address)); + } + } + +event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options) + { + print "icmp_neighbor_advertisement options"; + for ( o in options ) + { + print fmt(" %s", options[o]); + if ( options[o]$otype == 2 && options[o]?$link_address ) print fmt(" MAC: %s", string_to_ascii_hex(options[o]$link_address)); + } + } + +event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options) + { + print "icmp_redirect options"; + for ( o in options ) + print fmt(" %s", options[o]); + }