From 9edbf3e53c849635de62042afc82c0c5d0e128fc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 19 Oct 2012 14:02:35 -0500 Subject: [PATCH 01/29] Add GPRS Tunnelling Protocol (GTPv1) decapsulation. This currently supports automatic decapsulation of GTP-U packets on UDP port 2152. The GTPv1 headers for such tunnels can be inspected by handling the "gtpv1_g_pdu_packet" event, which has a parameter of type "gtpv1_hdr". Analyzer and test cases are derived from submissions by Carsten Langer. Addresses #690. --- scripts/base/frameworks/tunnels/main.bro | 5 +- scripts/base/init-bare.bro | 50 ++++++ src/Analyzer.cc | 4 + src/AnalyzerTags.h | 1 + src/CMakeLists.txt | 3 + src/GTPv1.cc | 24 +++ src/GTPv1.h | 29 ++++ src/NetVar.cc | 2 + src/NetVar.h | 1 + src/const.bif | 2 + src/event.bif | 15 +- src/gtpv1-analyzer.pac | 161 ++++++++++++++++++ src/gtpv1-protocol.pac | 27 +++ src/gtpv1.pac | 10 ++ src/types.bif | 1 + .../conn.log | 12 ++ .../http.log | 11 ++ .../tunnel.log | 13 ++ .../core.tunnels.gtp.false_gtp/conn.log | 10 ++ .../core.tunnels.gtp.false_gtp/dns.log | 10 ++ .../core.tunnels.gtp.inner_ipv6/conn.log | 12 ++ .../core.tunnels.gtp.inner_ipv6/tunnel.log | 11 ++ .../core.tunnels.gtp.inner_teredo/conn.log | 26 +++ .../core.tunnels.gtp.inner_teredo/tunnel.log | 27 +++ .../core.tunnels.gtp.non_recursive/out | 1 + .../conn.log | 11 ++ .../core.tunnels.gtp.opt_header/conn.log | 11 ++ .../Baseline/core.tunnels.gtp.opt_header/out | 31 ++++ .../core.tunnels.gtp.opt_header/tunnel.log | 11 ++ .../core.tunnels.gtp.outer_ip_frag/conn.log | 11 ++ .../core.tunnels.gtp.outer_ip_frag/http.log | 10 ++ .../core.tunnels.gtp.outer_ip_frag/tunnel.log | 11 ++ .../dpd.log | 10 ++ .../tunnel.log | 11 ++ .../Traces/tunnels/gtp/gtp10_not_0xff.pcap | Bin 0 -> 258 bytes .../gtp1_gn_normal_incl_fragmentation.pcap | Bin 0 -> 68590 bytes .../tunnels/gtp/gtp2_different_udp_port.pcap | Bin 0 -> 75398 bytes .../Traces/tunnels/gtp/gtp3_false_gtp.pcap | Bin 0 -> 122 bytes .../tunnels/gtp/gtp4_udp_2152_inside.pcap | Bin 0 -> 1020 bytes .../Traces/tunnels/gtp/gtp6_gtp_0x32.pcap | Bin 0 -> 5492 bytes .../btest/Traces/tunnels/gtp/gtp7_ipv6.pcap | Bin 0 -> 292 bytes .../btest/Traces/tunnels/gtp/gtp8_teredo.pcap | Bin 0 -> 1550 bytes .../gtp9_unknown_or_too_short_payload.pcap | Bin 0 -> 13195 bytes .../core/tunnels/gtp/different_dl_and_ul.test | 10 ++ testing/btest/core/tunnels/gtp/false_gtp.test | 8 + .../btest/core/tunnels/gtp/inner_ipv6.test | 6 + .../btest/core/tunnels/gtp/inner_teredo.test | 7 + .../btest/core/tunnels/gtp/non_recursive.test | 11 ++ .../core/tunnels/gtp/not_user_plane_data.test | 9 + .../btest/core/tunnels/gtp/opt_header.test | 12 ++ .../btest/core/tunnels/gtp/outer_ip_frag.test | 11 ++ .../tunnels/gtp/unknown_or_too_short.test | 13 ++ 52 files changed, 670 insertions(+), 2 deletions(-) create mode 100644 src/GTPv1.cc create mode 100644 src/GTPv1.h create mode 100644 src/gtpv1-analyzer.pac create mode 100644 src/gtpv1-protocol.pac create mode 100644 src/gtpv1.pac create mode 100644 testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.non_recursive/out create mode 100644 testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.opt_header/out create mode 100644 testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log create mode 100644 testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log create mode 100755 testing/btest/Traces/tunnels/gtp/gtp10_not_0xff.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp1_gn_normal_incl_fragmentation.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp2_different_udp_port.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp3_false_gtp.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp4_udp_2152_inside.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp6_gtp_0x32.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp7_ipv6.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp8_teredo.pcap create mode 100755 testing/btest/Traces/tunnels/gtp/gtp9_unknown_or_too_short_payload.pcap create mode 100644 testing/btest/core/tunnels/gtp/different_dl_and_ul.test create mode 100644 testing/btest/core/tunnels/gtp/false_gtp.test create mode 100644 testing/btest/core/tunnels/gtp/inner_ipv6.test create mode 100644 testing/btest/core/tunnels/gtp/inner_teredo.test create mode 100644 testing/btest/core/tunnels/gtp/non_recursive.test create mode 100644 testing/btest/core/tunnels/gtp/not_user_plane_data.test create mode 100644 testing/btest/core/tunnels/gtp/opt_header.test create mode 100644 testing/btest/core/tunnels/gtp/outer_ip_frag.test create mode 100644 testing/btest/core/tunnels/gtp/unknown_or_too_short.test diff --git a/scripts/base/frameworks/tunnels/main.bro b/scripts/base/frameworks/tunnels/main.bro index 0861559558..a3db7061d3 100644 --- a/scripts/base/frameworks/tunnels/main.bro +++ b/scripts/base/frameworks/tunnels/main.bro @@ -88,7 +88,10 @@ redef dpd_config += { [ANALYZER_AYIYA] = [$ports = ayiya_ports] }; const teredo_ports = { 3544/udp }; redef dpd_config += { [ANALYZER_TEREDO] = [$ports = teredo_ports] }; -redef likely_server_ports += { ayiya_ports, teredo_ports }; +const gtpv1u_ports = { 2152/udp }; +redef dpd_config += { [ANALYZER_GTPV1] = [$ports = gtpv1u_ports] }; + +redef likely_server_ports += { ayiya_ports, teredo_ports, gtpv1u_ports }; event bro_init() &priority=5 { diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 70026394e9..e8f60dfc64 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -1450,6 +1450,44 @@ type teredo_hdr: record { hdr: pkt_hdr; ##< IPv6 and transport protocol headers. }; +## A GTPv1 (GPRS Tunneling Protocol) header. +type gtpv1_hdr: record { + ## The 3-bit version field, which for GTPv1 should be 1. + version: count; + ## Protocol Type value differentiates GTP (value 1) from GTP' (value 0). + pt_flag: bool; + ## Reserved field, should be 0. + rsv: bool; + ## Extension Header flag. When 0, the *next_type* field may or may not + ## be present, but shouldn't be meaningful. When 1, *next_type* is + ## present and meaningful. + e_flag: bool; + ## Sequence Number flag. When 0, the *seq* field may or may not + ## be present, but shouldn't be meaningful. When 1, *seq* is + ## present and meaningful. + s_flag: bool; + ## N-PDU flag. When 0, the *n_pdu* field may or may not + ## be present, but shouldn't be meaningful. When 1, *n_pdu* is + ## present and meaningful. + pn_flag: bool; + ## Message Type. A value of 255 indicates user-plane data is encapsulated. + msg_type: count; + ## Length of the GTP packet payload (the rest of the packet following the + ## mandatory 8-byte GTP header). + length: count; + ## Tunnel Endpoint Identifier. Unambiguously identifies a tunnel endpoint + ## in receiving GTP-U or GTP-C protocol entity. + teid: count; + ## Sequence Number. Set if any *e_flag*, *s_flag*, or *pn_flag* field is + ## set. + seq: count &optional; + ## N-PDU Number. Set if any *e_flag*, *s_flag*, or *pn_flag* field is set. + n_pdu: count &optional; + ## Next Extension Header Type. Set if any *e_flag*, *s_flag*, or *pn_flag* + ## field is set. + next_type: count &optional; +}; + ## Definition of "secondary filters". A secondary filter is a BPF filter given as ## index in this table. For each such filter, the corresponding event is raised for ## all matching packets. @@ -2776,6 +2814,9 @@ export { ## Toggle whether to do IPv6-in-Teredo decapsulation. const enable_teredo = T &redef; + ## Toggle whether to do GTPv1 decapsulation. + const enable_gtpv1 = T &redef; + ## With this option set, the Teredo analysis will first check to see if ## other protocol analyzers have confirmed that they think they're ## parsing the right protocol and only continue with Teredo tunnel @@ -2792,6 +2833,15 @@ export { ## :bro:see:`Tunnel::yielding_teredo_decapsulation`. const delay_teredo_confirmation = T &redef; + ## With this set, the GTP analyzer waits until the most-recent upflow + ## and downflow packets are a valid GTPv1 encapsulation before + ## issuing :bro:see:`protocol_confirmation`. If it's false, the + ## first occurence of a packet with valid GTPv1 encapsulation causes + ## confirmation. Since the same inner connection can be carried + ## differing outer upflow/downflow connections, setting to false + ## may work better. + const delay_gtp_confirmation = F &redef; + ## How often to cleanup internal state for inactive IP tunnels. const ip_tunnel_timeout = 24hrs &redef; } # end export diff --git a/src/Analyzer.cc b/src/Analyzer.cc index 8c5573f96b..570b877881 100644 --- a/src/Analyzer.cc +++ b/src/Analyzer.cc @@ -40,6 +40,7 @@ #include "Syslog-binpac.h" #include "Teredo.h" #include "ConnSizeAnalyzer.h" +#include "GTPv1.h" // Keep same order here as in AnalyzerTag definition! const Analyzer::Config Analyzer::analyzer_configs[] = { @@ -139,6 +140,9 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { { AnalyzerTag::Teredo, "TEREDO", Teredo_Analyzer::InstantiateAnalyzer, Teredo_Analyzer::Available, 0, false }, + { AnalyzerTag::GTPv1, "GTPV1", + GTPv1_Analyzer::InstantiateAnalyzer, + GTPv1_Analyzer::Available, 0, false }, { AnalyzerTag::File, "FILE", File_Analyzer::InstantiateAnalyzer, File_Analyzer::Available, 0, false }, diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index 4301de8f71..21f50f3b52 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -37,6 +37,7 @@ namespace AnalyzerTag { AYIYA, SOCKS, Teredo, + GTPv1, // Other File, Backdoor, InterConn, SteppingStone, TCPStats, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b77863d107..fa30d9ff55 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -203,6 +203,8 @@ binpac_target(dns.pac dns-protocol.pac dns-analyzer.pac) binpac_target(dns_tcp.pac dns.pac) +binpac_target(gtpv1.pac + gtpv1-protocol.pac gtpv1-analyzer.pac) binpac_target(http.pac http-protocol.pac http-analyzer.pac) binpac_target(ncp.pac) @@ -330,6 +332,7 @@ set(bro_SRCS Frame.cc Func.cc Gnutella.cc + GTPv1.cc HTTP.cc HTTP-binpac.cc Hash.cc diff --git a/src/GTPv1.cc b/src/GTPv1.cc new file mode 100644 index 0000000000..b7a0fdc664 --- /dev/null +++ b/src/GTPv1.cc @@ -0,0 +1,24 @@ +#include "GTPv1.h" + +GTPv1_Analyzer::GTPv1_Analyzer(Connection* conn) +: Analyzer(AnalyzerTag::GTPv1, conn) + { + interp = new binpac::GTPv1::GTPv1_Conn(this); + } + +GTPv1_Analyzer::~GTPv1_Analyzer() + { + delete interp; + } + +void GTPv1_Analyzer::Done() + { + Analyzer::Done(); + Event(udp_session_done); + } + +void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) + { + Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + interp->NewData(orig, data, data + len); + } diff --git a/src/GTPv1.h b/src/GTPv1.h new file mode 100644 index 0000000000..e111158833 --- /dev/null +++ b/src/GTPv1.h @@ -0,0 +1,29 @@ +#ifndef GTPv1_h +#define GTPv1_h + +#include "gtpv1_pac.h" + +class GTPv1_Analyzer : public Analyzer { +public: + GTPv1_Analyzer(Connection* conn); + virtual ~GTPv1_Analyzer(); + + virtual void Done(); + virtual void DeliverPacket(int len, const u_char* data, bool orig, + int seq, const IP_Hdr* ip, int caplen); + + static Analyzer* InstantiateAnalyzer(Connection* conn) + { return new GTPv1_Analyzer(conn); } + + static bool Available() + { return BifConst::Tunnel::enable_gtpv1 && + BifConst::Tunnel::max_depth > 0; } + +protected: + friend class AnalyzerTimer; + void ExpireTimer(double t); + + binpac::GTPv1::GTPv1_Conn* interp; +}; + +#endif diff --git a/src/NetVar.cc b/src/NetVar.cc index 248ae15e1a..1783130f34 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -5,6 +5,7 @@ #include "Var.h" #include "NetVar.h" +RecordType* gtpv1_hdr_type; RecordType* conn_id; RecordType* endpoint; RecordType* endpoint_stats; @@ -308,6 +309,7 @@ void init_net_var() #include "input.bif.netvar_init" #include "reporter.bif.netvar_init" + gtpv1_hdr_type = internal_type("gtpv1_hdr")->AsRecordType(); conn_id = internal_type("conn_id")->AsRecordType(); endpoint = internal_type("endpoint")->AsRecordType(); endpoint_stats = internal_type("endpoint_stats")->AsRecordType(); diff --git a/src/NetVar.h b/src/NetVar.h index 2561fa0ad9..4bb2d2a7f9 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -8,6 +8,7 @@ #include "EventRegistry.h" #include "Stats.h" +extern RecordType* gtpv1_hdr_type; extern RecordType* conn_id; extern RecordType* endpoint; extern RecordType* endpoint_stats; diff --git a/src/const.bif b/src/const.bif index 7373403c11..ea7dc03817 100644 --- a/src/const.bif +++ b/src/const.bif @@ -15,8 +15,10 @@ const Tunnel::max_depth: count; const Tunnel::enable_ip: bool; const Tunnel::enable_ayiya: bool; const Tunnel::enable_teredo: bool; +const Tunnel::enable_gtpv1: bool; const Tunnel::yielding_teredo_decapsulation: bool; const Tunnel::delay_teredo_confirmation: bool; +const Tunnel::delay_gtp_confirmation: bool; const Tunnel::ip_tunnel_timeout: interval; const Threading::heartbeat_interval: interval; diff --git a/src/event.bif b/src/event.bif index 0c79c6159d..03df6a9071 100644 --- a/src/event.bif +++ b/src/event.bif @@ -577,6 +577,19 @@ event teredo_origin_indication%(outer: connection, inner: teredo_hdr%); ## it may become particularly expensive for real-time analysis. event teredo_bubble%(outer: connection, inner: teredo_hdr%); +## Generated for GTPv1 G-PDU packets. That is, packets with a UDP payload +## that includes a GTP header followed by an IPv4 or IPv6 packet. +## +## outer: The GTP outer tunnel connection. +## +## inner_gtp: The GTP header. +## +## inner_ip: The inner IP and transport layer packet headers. +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event gtpv1_g_pdu_packet%(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr%); + ## Generated for every packet that has a non-empty transport-layer payload. ## This is a very low-level and expensive event that should be avoided when ## at all possible. It's usually infeasible to handle when processing even @@ -858,7 +871,7 @@ event udp_contents%(u: connection, is_orig: bool, contents: string%); ## Generated when a UDP session for a supported protocol has finished. Some of ## Bro's application-layer UDP analyzers flag the end of a session by raising ## this event. Currently, the analyzers for DNS, NTP, Netbios, Syslog, AYIYA, -## and Teredo support this. +## Teredo, and GTPv1 support this. ## ## u: The connection record for the corresponding UDP flow. ## diff --git a/src/gtpv1-analyzer.pac b/src/gtpv1-analyzer.pac new file mode 100644 index 0000000000..08fbdef74a --- /dev/null +++ b/src/gtpv1-analyzer.pac @@ -0,0 +1,161 @@ + +connection GTPv1_Conn(bro_analyzer: BroAnalyzer) + { + upflow = GTPv1_Flow(true); + downflow = GTPv1_Flow(false); + + %member{ + bool valid_orig; + bool valid_resp; + %} + + %init{ + valid_orig = valid_resp = false; + %} + + function valid(orig: bool): bool + %{ + return orig ? valid_orig : valid_resp; + %} + + function set_valid(orig: bool, val: bool): void + %{ + if ( orig ) + valid_orig = val; + else + valid_resp = val; + %} + } + +%code{ +inline void violate(const char* r, const BroAnalyzer& a, const bytestring& p) + { + a->ProtocolViolation(r, (const char*) p.data(), p.length()); + } +%} + +flow GTPv1_Flow(is_orig: bool) + { + datagram = GTPv1_Header withcontext(connection, this); + + function process_gtpv1(pdu: GTPv1_Header): bool + %{ + BroAnalyzer a = connection()->bro_analyzer(); + Connection *c = a->Conn(); + const EncapsulationStack* e = c->GetEncapsulation(); + + connection()->set_valid(is_orig(), false); + + if ( e && e->Depth() >= BifConst::Tunnel::max_depth ) + { + reporter->Weird(c, "tunnel_depth"); + return false; + } + + if ( e && e->LastType() == BifEnum::Tunnel::GTPv1 ) + { + // GTP is never tunneled in GTP so, this must be a regular packet + violate("GTP-in-GTP", a, ${pdu.packet}); + return false; + } + + if ( ${pdu.version} != 1 ) + { + // Only know of GTPv1 with Version == 1 + violate("GTPv1 bad Version", a, ${pdu.packet}); + return false; + } + + if ( ! ${pdu.pt_flag} ) + { + // Not interested in GTP' + return false; + } + + if ( ${pdu.e_flag} ) + { + // TODO: can't currently parse past extension headers + return false; + } + + if ( ${pdu.msg_type} != 0xff ) + { + // Only interested in decapsulating user plane data beyond here. + return false; + } + + if ( ${pdu.packet}.length() < (int)sizeof(struct ip) ) + { + violate("Truncated GTPv1", a, ${pdu.packet}); + return false; + } + + const struct ip* ip = (const struct ip*) ${pdu.packet}.data(); + + if ( ip->ip_v != 4 && ip->ip_v != 6 ) + { + violate("non-IP packet in GTPv1", a, ${pdu.packet}); + return false; + } + + IP_Hdr* inner = 0; + int result = sessions->ParseIPPacket(${pdu.packet}.length(), + ${pdu.packet}.data(), ip->ip_v == 6 ? IPPROTO_IPV6 : IPPROTO_IPV4, + inner); + + if ( result == 0 ) + { + connection()->set_valid(is_orig(), true); + + if ( (! BifConst::Tunnel::delay_gtp_confirmation) || + (connection()->valid(true) && connection()->valid(false)) ) + a->ProtocolConfirmation(); + } + + else if ( result < 0 ) + violate("Truncated GTPv1", a, ${pdu.packet}); + + else + violate("GTPv1 payload length", a, ${pdu.packet}); + + if ( result != 0 ) + { + delete inner; + return false; + } + + if ( ::gtpv1_g_pdu_packet ) + { + RecordVal* rv = new RecordVal(gtpv1_hdr_type); + + rv->Assign(0, new Val(${pdu.version}, TYPE_COUNT)); + rv->Assign(1, new Val(${pdu.pt_flag}, TYPE_BOOL)); + rv->Assign(2, new Val(${pdu.rsv}, TYPE_BOOL)); + rv->Assign(3, new Val(${pdu.e_flag}, TYPE_BOOL)); + rv->Assign(4, new Val(${pdu.s_flag}, TYPE_BOOL)); + rv->Assign(5, new Val(${pdu.pn_flag}, TYPE_BOOL)); + rv->Assign(6, new Val(${pdu.msg_type}, TYPE_COUNT)); + rv->Assign(7, new Val(ntohs(${pdu.length}), TYPE_COUNT)); + rv->Assign(8, new Val(ntohl(${pdu.teid}), TYPE_COUNT)); + + if ( ${pdu.has_opt} ) + { + rv->Assign(9, new Val(ntohs(${pdu.opt_hdr.seq}), TYPE_COUNT)); + rv->Assign(10, new Val(${pdu.opt_hdr.n_pdu}, TYPE_COUNT)); + rv->Assign(11, new Val(${pdu.opt_hdr.next_type}, TYPE_COUNT)); + } + + BifEvent::generate_gtpv1_g_pdu_packet(a, c, rv, + inner->BuildPktHdrVal()); + } + + EncapsulatingConn ec(c, BifEnum::Tunnel::GTPv1); + + sessions->DoNextInnerPacket(network_time(), 0, inner, e, ec); + + return (result == 0) ? true : false; + %} + + }; + +refine typeattr GTPv1_Header += &let { proc_gtpv1 = $context.flow.process_gtpv1(this); }; diff --git a/src/gtpv1-protocol.pac b/src/gtpv1-protocol.pac new file mode 100644 index 0000000000..5bf31a48ee --- /dev/null +++ b/src/gtpv1-protocol.pac @@ -0,0 +1,27 @@ + +type GTPv1_Header = record { + flags: uint8; + msg_type: uint8; + length: uint16; + teid: uint32; + opt: case has_opt of { + true -> opt_hdr: GTPv1_Opt_Header; + false -> no_opt: empty; + } &requires(has_opt); + packet: bytestring &restofdata; + +} &let { + version: uint8 = (flags & 0xE0) >> 5; + pt_flag: bool = flags & 0x10; + rsv: bool = flags & 0x08; + e_flag: bool = flags & 0x04; + s_flag: bool = flags & 0x02; + pn_flag: bool = flags & 0x01; + has_opt: bool = flags & 0x07; +} &byteorder = littleendian; + +type GTPv1_Opt_Header = record { + seq: uint16; + n_pdu: uint8; + next_type: uint8; +} diff --git a/src/gtpv1.pac b/src/gtpv1.pac new file mode 100644 index 0000000000..d155ecfd67 --- /dev/null +++ b/src/gtpv1.pac @@ -0,0 +1,10 @@ +%include binpac.pac +%include bro.pac + +analyzer GTPv1 withcontext { + connection: GTPv1_Conn; + flow: GTPv1_Flow; +}; + +%include gtpv1-protocol.pac +%include gtpv1-analyzer.pac diff --git a/src/types.bif b/src/types.bif index 92cc8db551..b25f75c29a 100644 --- a/src/types.bif +++ b/src/types.bif @@ -177,6 +177,7 @@ enum Type %{ AYIYA, TEREDO, SOCKS, + GTPv1, %} type EncapsulatingConn: record; diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log new file mode 100644 index 0000000000..e2861b4ae1 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-03-55 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458850.321642 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 tcp http 0.257902 1138 63424 S3 - 0 ShADadf 29 2310 49 65396 UWkUyAuUGXf,k6kgXLOoSKl +1333458850.325787 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 udp gtpv1 0.251127 65788 0 S0 - 0 D 49 67160 0 0 (empty) +1333458850.321642 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 udp gtpv1 0.257902 2542 0 S0 - 0 D 29 3354 0 0 (empty) +#close 2012-10-19-17-03-55 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log new file mode 100644 index 0000000000..66b17e1200 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2012-10-19-17-03-55 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1333458850.340368 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 1 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=4&cac=1&t=728x90&cb=1333458879 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&channel=4&cb=1333458905296 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - application/x-shockwave-flash - - +1333458850.399501 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 2 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=0&cac=1&t=728x90&cb=1333458881 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&cb=1333458920207 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - application/x-shockwave-flash - - +#close 2012-10-19-17-03-55 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log new file mode 100644 index 0000000000..233ad1c850 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log @@ -0,0 +1,13 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-17-03-55 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458850.321642 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.325787 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.579544 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.579544 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2012-10-19-17-03-55 diff --git a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log new file mode 100644 index 0000000000..1234558195 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-07-44 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458871.219794 UWkUyAuUGXf 10.131.24.6 2152 195.178.38.3 53 udp dns - - - S0 - 0 D 1 64 0 0 (empty) +#close 2012-10-19-17-07-44 diff --git a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log new file mode 100644 index 0000000000..a293d6ff6a --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#open 2012-10-19-17-07-44 +#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 rejected +#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] bool +1333458871.219794 UWkUyAuUGXf 10.131.24.6 2152 195.178.38.3 53 udp 27595 abcd.efg.hijklm.nm 1 C_INTERNET 1 A - - F F T F 0 - - F +#close 2012-10-19-17-07-44 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log new file mode 100644 index 0000000000..326205172a --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-21-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458851.770000 arKYeMETxOg fe80::224c:4fff:fe43:414c 1234 ff02::1:3 5355 udp dns - - - S0 - 0 D 1 80 0 0 UWkUyAuUGXf +1333458851.770000 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 udp gtpv1 0.199236 152 0 S0 - 0 D 2 208 0 0 (empty) +1333458851.969236 k6kgXLOoSKl fe80::224c:4fff:fe43:414c 133 ff02::2 134 icmp - - - - OTH - 0 - 1 56 0 0 UWkUyAuUGXf +#close 2012-10-19-17-21-27 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log new file mode 100644 index 0000000000..dfae2ba269 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-17-21-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458851.770000 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458851.969236 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2012-10-19-17-21-27 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log new file mode 100644 index 0000000000..9c3e1f6f66 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log @@ -0,0 +1,26 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-34-25 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458850.037956 qCaWGmzFtM5 10.131.112.102 51403 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 GSxOnSLghOa +1333458850.040098 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 udp gtpv1 0.003698 192 0 S0 - 0 D 2 248 0 0 (empty) +1333458850.016620 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 udp teredo - - - S0 - 0 D 1 80 0 0 k6kgXLOoSKl +1333458850.029781 FrJExwHcSal 172.24.16.67 52298 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 88 0 0 TEfuqmmG4bh +1333458850.035456 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 udp gtpv1 0.000004 194 0 S0 - 0 D 2 250 0 0 (empty) +1333458850.016620 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 udp gtpv1 0.016267 88 92 SF - 0 Dd 1 116 1 120 (empty) +1333458850.029781 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 udp gtpv1 0.000002 192 0 S0 - 0 D 2 248 0 0 (empty) +1333458850.035460 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 udp teredo - - - S0 - 0 D 1 89 0 0 VW0XPVINV8a +1333458850.037956 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 udp gtpv1 - - - S0 - 0 D 1 120 0 0 (empty) +1333458850.014199 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 udp gtpv1 - - - S0 - 0 D 1 124 0 0 (empty) +1333458850.040098 h5DsfNtYzi1 172.24.203.81 54447 65.55.158.118 3544 udp teredo 0.003698 120 0 S0 - 0 D 2 176 0 0 70MGiRM1Qf4 +1333458850.029783 5OKnoww6xl4 172.24.16.67 52298 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 TEfuqmmG4bh +1333458850.032887 3PKsZ2Uye21 10.131.42.160 62069 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 k6kgXLOoSKl +1333458850.014199 arKYeMETxOg 172.24.204.200 56528 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 UWkUyAuUGXf +1333458850.035456 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 89 0 0 VW0XPVINV8a +1333458850.016620 j4u32Pc5bif 2001:0:5ef5:79fb:38b8:1695:2b37:be8e 128 2002:2571:c817::2571:c817 129 icmp - - - - OTH - 0 - 1 52 0 0 nQcgTWjvg4c +1333458850.035456 qSsw6ESzHV4 fe80::ffff:ffff:fffe 133 ff02::2 134 icmp - 0.000004 0 0 OTH - 0 - 2 96 0 0 fRFu0wcOle6,iE6yhOq3SF +#close 2012-10-19-17-34-25 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log new file mode 100644 index 0000000000..904fcc7db6 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log @@ -0,0 +1,27 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-17-34-25 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458850.014199 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.016620 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.016620 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.029781 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.035456 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.035456 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.035460 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.037956 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.040098 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.043796 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::CLOSE +1333458850.043796 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::CLOSE +1333458850.043796 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::CLOSE +#close 2012-10-19-17-34-25 diff --git a/testing/btest/Baseline/core.tunnels.gtp.non_recursive/out b/testing/btest/Baseline/core.tunnels.gtp.non_recursive/out new file mode 100644 index 0000000000..a299c4d592 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.non_recursive/out @@ -0,0 +1 @@ +protocol_violation, [orig_h=74.125.216.149, orig_p=2152/udp, resp_h=10.131.138.69, resp_p=2152/udp], GTP-in-GTP [n\xd9'|\x00\x00\x01\xb6[\xf6\xdc0\xb7d\xe5\xe6\xa76\x91\xfbk\x0e\x02\xc8A\x05\xa8\xe6\xf3Gi\x80(]\xcew\x84\xae}\xd2...] diff --git a/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log b/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log new file mode 100644 index 0000000000..ad6e4fb2c4 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-46-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458850.532814 UWkUyAuUGXf 247.56.43.90 2152 247.56.43.248 2152 udp - - - - S0 - 0 D 1 52 0 0 (empty) +1333458850.867091 arKYeMETxOg 247.56.43.214 2152 237.56.101.238 2152 udp - 0.028676 12 14 SF - 0 Dd 1 40 1 42 (empty) +#close 2012-10-19-17-46-48 diff --git a/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log b/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log new file mode 100644 index 0000000000..9f250903f2 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-17-19-16 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458852.011535 arKYeMETxOg 10.222.10.10 44960 173.194.69.188 5228 tcp ssl 0.573499 704 1026 S1 - 0 ShADad 17 1604 14 1762 UWkUyAuUGXf +1333458852.011535 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 udp gtpv1 0.573499 1740 1930 SF - 0 Dd 17 2216 14 2322 (empty) +#close 2012-10-19-17-19-16 diff --git a/testing/btest/Baseline/core.tunnels.gtp.opt_header/out b/testing/btest/Baseline/core.tunnels.gtp.opt_header/out new file mode 100644 index 0000000000..7feeb2a110 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.opt_header/out @@ -0,0 +1,31 @@ +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=60, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=60, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=64, teid=159098, seq=0, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=170, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=56, teid=159098, seq=1, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=194, teid=159098, seq=2, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=111, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=56, teid=159098, seq=3, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=89, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=56, teid=159098, seq=4, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=93, teid=159098, seq=5, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=457, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=157, teid=159098, seq=6, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=173, teid=159098, seq=7, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=137, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=56, teid=159098, seq=8, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=157, teid=159098, seq=9, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=189, teid=159098, seq=10, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=173, teid=159098, seq=11, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=205, teid=159098, seq=12, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=T, pn_flag=F, msg_type=255, length=189, teid=159098, seq=13, n_pdu=0, next_type=0] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] +gtpv1_packet, [version=1, pt_flag=T, rsv=F, e_flag=F, s_flag=F, pn_flag=F, msg_type=255, length=52, teid=1980578736, seq=, n_pdu=, next_type=] diff --git a/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log new file mode 100644 index 0000000000..a421f399ec --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-17-19-16 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458852.011535 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458852.585034 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2012-10-19-17-19-16 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log new file mode 100644 index 0000000000..b5f61564cf --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2012-10-19-16-44-02 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1333458850.364667 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 tcp http 0.069783 2100 56702 SF - 0 ShADadfF 27 3204 41 52594 UWkUyAuUGXf +1333458850.364667 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 udp gtpv1 0.069813 3420 52922 SF - 0 Dd 27 4176 41 54070 (empty) +#close 2012-10-19-16-44-02 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log new file mode 100644 index 0000000000..8a994d56af --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2012-10-19-16-44-02 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1333458850.375568 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 1 GET o-o.preferred.telekomrs-beg1.v2.lscache8.c.youtube.com /videoplayback?upn=MTU2MDY5NzQ5OTM0NTI3NDY4NDc&sparams=algorithm,burst,cp,factor,id,ip,ipbits,itag,source,upn,expire&fexp=912300,907210&algorithm=throttle-factor&itag=34&ip=212.0.0.0&burst=40&sver=3&signature=832FB1042E20780CFCA77A4DB5EA64AC593E8627.D1166C7E8365732E52DAFD68076DAE0146E0AE01&source=youtube&expire=1333484980&key=yt1&ipbits=8&factor=1.25&cp=U0hSSFRTUl9NSkNOMl9MTVZKOjh5eEN2SG8tZF84&id=ebf1e932d4bd1286&cm2=1 http://s.ytimg.com/yt/swfbin/watch_as3-vflqrJwOA.swf Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko; X-SBLSP) Chrome/17.0.963.83 Safari/535.11 0 56320 206 Partial Content - - - (empty) - - - application/octet-stream - - +#close 2012-10-19-16-44-02 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log new file mode 100644 index 0000000000..54c4acd0d6 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-16-44-02 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458850.364667 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.434480 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2012-10-19-16-44-02 diff --git a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log new file mode 100644 index 0000000000..221fa16f4f --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dpd +#open 2012-10-19-17-38-54 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto analyzer failure_reason +#types time string addr port addr port enum string string +1333458853.075889 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 udp GTPV1 Truncated GTPv1 [E\x00\x05\xc8G\xea@\x00\x80\x06\xb6\x83\x0a\x83w&\xd9\x14\x9c\x04\xd9\xc2\x00P\xddh\xb4\x8f41eVP\x10\x10\xe0u\xcf\x00\x00...] +#close 2012-10-19-17-38-54 diff --git a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log new file mode 100644 index 0000000000..659090a581 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open 2012-10-19-17-38-54 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +1333458853.034734 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458853.108391 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2012-10-19-17-38-54 diff --git a/testing/btest/Traces/tunnels/gtp/gtp10_not_0xff.pcap b/testing/btest/Traces/tunnels/gtp/gtp10_not_0xff.pcap new file mode 100755 index 0000000000000000000000000000000000000000..575edf55f9fd21ae83c90cbf8363d92b995b877f GIT binary patch literal 258 zcmca|c+)~A1{MYw`2U}Qff2}A^u5a8PmzPc3CIRv28K8W#(OWeduTHr;9ziNU@!@a zWMKFws50lfg?1DW|KP~r$Y4;2oM|M*AOO|?Bm@?GQVwWkV7YSQs{_bHVQXFn8=yD{ zGcfS5uX)k&;PZ+7AAlzAV9;3p0VpFF{~T!AwYL_j@4zOCcmx_TLLB%n6RZtLfXotK xjcgXkbqs2!Ew_SPw}U|oWY#;uwNF6ifXoA%C1&Mi#Kgb`G6iH7ACTr_000LSMXdk; literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp1_gn_normal_incl_fragmentation.pcap b/testing/btest/Traces/tunnels/gtp/gtp1_gn_normal_incl_fragmentation.pcap new file mode 100755 index 0000000000000000000000000000000000000000..7ca3b3b05dc3d3b18330ef1ae226daa2b5402d19 GIT binary patch literal 68590 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 literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp2_different_udp_port.pcap b/testing/btest/Traces/tunnels/gtp/gtp2_different_udp_port.pcap new file mode 100755 index 0000000000000000000000000000000000000000..fda97cdaf536a663c80cba7e531b61a08efd47ae GIT binary patch literal 75398 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 J@^V3Pi~xMY9l!tp literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp4_udp_2152_inside.pcap b/testing/btest/Traces/tunnels/gtp/gtp4_udp_2152_inside.pcap new file mode 100755 index 0000000000000000000000000000000000000000..ca67a370460ec34d5aa8bd071050d7b541b12f01 GIT binary patch literal 1020 zcmVu%X6d;kCewp;exFt=po=BGB1`)dvY z$Uz0D=JQ8sfGAzgcZ9Be(nojiMK%*dw@9aeaSg$7Ks2zq>j^wm;)C(z&yZPTn}Twj zJ~S}oRVGlywNK$=8@6}dit$Z(H&#!3+t$BKJZ%@9qeMN%eC*O5$xbZ ztIdiDR7m-fH5sefNTj-UFhP@wh>3Uu&7|ZbcZfXeW*!9^vj`73kK|062ol+~Rjq;2 z;LM)`Av*?lwa;sNbWBQ}>hgED-v#9@8ToCOE1mbsmX#@t!eW(Vm3dmTM~Chrf6Lc* zF15aQH1T9`D8#|qls-CyvPN`9m$OLaG&|ls&wFpIJflabROvqXG9JmIVtIEkN#yI_ zc%LQjQ_VzUBAtq;;9%YYikZFQvJ+&an9w4p3Od|ndwiPz>6Pl3dsO$_rPjZ6cf_(# zbd2#Pw#G$+LKXKg31xt$RZ!U;>zmufh3dVtl)zqA%9>t~t+=tgU5F-qX_76)-ldA2 ze5F&XHb%#k{pRy^eWuj*Vd5erCot-!^w0-U=4CGSytsZ0;6oXmAxo#?kV2itT{yed zNTZjnT6zo|M>3d&kwn`(ZhEE~y2CBck{G@|M_SuVWP)8IT!~)t54sV%T7CDjB0Uz7 z!lul+Zm!1ryH6gU>vJ6rL(XM#M|wx9t2~+EEbyho)#P#&y$+EEcX?8|oYR!k=^&+onBS9 qWv+4D9zzITUcP}UH9SpKb~9uWZIiZ6SUPa8-Q9PhZN0OXrL&h9E%pWg literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp6_gtp_0x32.pcap b/testing/btest/Traces/tunnels/gtp/gtp6_gtp_0x32.pcap new file mode 100755 index 0000000000000000000000000000000000000000..7dd3905c5d7a7f9b85aff9dd6d58c139d13003b4 GIT binary patch literal 5492 zcmai&2{@E%AI6`-*q1PtPKb(xBun%mDqARPAxn}Z;xOqX<%A<^${txlQj#?#6=f|n z%5t29Y~>(iNtTlDdERg}Grsv;*K=LAd4KPH|L^;G-kH{_qI5dI0G7WN7XiS*A2Mfr zjJUP};10h>3jlVedxIf8Q!k&5GXrgBVBZo9fExFDDWj*?t*7F0Ynh#yoq=IUp4=i( z`-4NZKpXx!eYYmiWQ-!PzGr34t<-*+pGG*PB_W-Tu9rqPKYnQp06GSIF#{blD_{@n zLBGe*)8i0*4Q+ZTMwg^X--FS4{}(;5@>lw0_Fw7v8~}*$7ia-s2XOBPOZ231&!Kin z;K*qYz!dk^2&5a`0jAx!zF&S3XaYJnAM_e+W}p@Z|4)i>VH9accR@InpQg@WBMd#r zNaImJ zP1i!y$eXKD1%17TVVstzt%%A`j{}}Ca&GiEBcGWUM8n|DpML)7S;{jJwdCfahubD4MKJM{@x4IHJ7ctVVmx^$sH;uw$sJAn#N0{nm% zumS}j54Hh3j5iT4(9Yrw{!L}bV1J)PQ3C~j`e)B zsVvpPli_~N#_gYm^8UZmI{^V+4u?Y*l{=fcXXFIVR{!?n><3JJq`O>F$C8OE0*Xq? z;q(dLeKu4_w5E!#PtguBOs@#7Jp2WDAaIzDM!tJCqNMS}lO>HZ-`ZHd1<8{pBM9?- z2j*L$5|(!DbF`@P9n;f-sN6YZ)Qcf{FyFr~<@@(^9W39St5OAh z74(ExsAGuwi%lXL?uOE>QSTys9H&kweA&f2KH_S#%~-gC@gZ~UQRi!s|H#yNafCkN zFmy=~8=m7wH_RnKPa~v8mMAJC$z)N{s~=wpDg9DNk6}@nr-;fO7*aD7Qgs+5WL1q2 z7YRmX43WbY=|MO&2`wtCe1~r%tC&W~tU4Lu1+B7LvdSu57qe=D!YVUtK+vkiqGhWh zcoA6uW=VATFU|n>c-%@FG+6d>O!1Xa`zU&GkQLWg&oJpEvu4YbKNt@$(S+EHm4r?H+HXtYlHjoX8*>`_Tyl8THlXtXBXC0 z=CDQI<*%D-|Eb%)H^uNU&5g&kR;(CQ~EC&4H-bwD8~? z+z!#AObTvv(gIO`y!w@jYrhmLw}`9znG{@I`aVRxdT~{%psx&F5;+wbf{W}BRClRM zd!x*kubE7r8(lcV$;F?*?vzq8p*9s9yvFCvmE=@E{l18uUPoGgs4wd8x11>T5Gf)F z%l7_r4NuH7^*Uh0b-Z5pR&LW7F0r@$aXwCUea2t!vXP30(z6^MbczynrHtH(W^B`Y z0=e#+jhkAHrXOXix`_C*<8T!+UquFYeiVrNN@yMM zDm*l+Qc|UAW#mJrZexADTRQakY7j5KbHBH?t-7x(80{^#3

M5<|q0OHa6L-9D zsH)n{61cbNv0TLW|18)r{n=QmH4`d682FdOTlq)rjCWjd8P9q8w?MI*jjZB_(#TKqfy2%> zihJkowmn*i5uTfo?!2N99$>P?aq$_VJU-gO2h%20z(W zVrkHQ5u5O&gBAysV={EpE!!UK&0f#ry^mdX(9zGTsv?gRzfqtx&XFfed(TZPBT-pv zTS@maBsXLyBaQ83HU<@YUi{Z$1Iq10AKOkSp21}~)ER8$(RT9W^GdPxYJ_;q5VhEV z7IhA0NR4|gmnPK!qwZiuLn*pogQ?ay~ROH{at+2^lNEf5u@*7#G=aevE^@b0(wIUf&<#Pdgo z`10vV`^~DG?92LA-|0SKl}>UJ7rBZAu0Q#nP?o3uP0DSPtlX5RImQi%JIm&bUZp^DV?TB>1~)&2Y5Vw zR;pS~DeniEQVT>r-@!zq{_SfK+2Ic|a&EooO8r@u>VFa=UtN_9>tFb4nM{yEWUT%s z4+}Ue?hT|b%JrmG2RWJB6!?wwGiYdaFZ{Vcc*!05an9)JjZI?PTn{sy_ajO%W$R27 zG4VzQOzoJVdu$q>Al9lm{6(uJnVYzl{)LFLx1pk92O6%xB^4ASB(b)akr7-yi$>f*S{aD%kU~%DNS9X{yCf}Dr ze$=vjMK5ak9zwiY)&iZX9|^_%3Rfqko=2Xs&N=TWc23-W5cj$7(Atk$nZ(ORr(9=i z3#3y?x3&*_{xGjt&3$4^zXqf4DIgrGxUlV&X-~>Rd6GQ-QE$g)s;cHBy8I7^8_fj zE)2f^gVVMlmwSY9S?(_Q(Dd`sn;^X$=18$IOXsf*IUdcDhsU0s={%jM8Bi`YeaME@ zv?E8_ZRbl;;Y48RwnL+(q<0678>jGAwDe|yOYJG@*S#aSx*Dtvxc;^F`Fv9GqAW{$ z<#RtJX-3`hnDVzqeBn_Zhd58Y>egLk6LDuz)~cJ)zU4V4)>0H2B);uyTEZ=H65dk8 zZu4Zb=-Ae}+t>7J@3pk_-$Ql`LOW=LUk$TEfy@q4UFS;pIhMljhS}jtVMo%k9R~W; zcKDTB6A%2|A4TlZ?5J|FsAigOjx)26oK?^$U$-Ovx}*-b4O8e$yRTWU4d;JvaIM43-K{ows^ z)b-E}TozY~Kha5Tv9^+}xKouyr~h=WWPT_e*8R84G|oa+0dzhLW{{l^lxN|7>{MDq zaVj~eGuW}CQ|VF8Pw6lPK{Y}IDMVGHO@$jOq^8lN9>Azvt5BmbssuGvoi=qHMopzj zHNvQz)YK!4h+0xeP2D$2)8VTamHhKYN{5XxD#t3+B#ipo3N;uyER7u2r%jE*sN|nB WQc_JYDmyjRUKCLu#;#C95cR(`itN<@ literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp7_ipv6.pcap b/testing/btest/Traces/tunnels/gtp/gtp7_ipv6.pcap new file mode 100755 index 0000000000000000000000000000000000000000..4f358bc374d6c0c69d4acd956cdca4f214cc233e GIT binary patch literal 292 zcmca|c+)~A1{MYw`2U}Qff2}A{JqNm!hUXsCLkMx85nrj*SzR>@cG344;&1x3=Adm zYzz!Gf>oYnF*TY%?7@-2k-?BK;kvhCK}X*GtRlY_nZ&k-??YFxAhha z0x(}jBLIVg+HYCm88U!E>{A1E#Bd)yJoS+%eDB3)Q3ZViN z$7L=?h$|P%y78H~fEoamxH?JgpwsS^Ri(ck6pcbq$!0md4Bo3HxKzT7a?a;=@_T2Q z<{FLZImvpzNUynAUq+BolaOv91fUsS4_dP0nIxO^2RM&2P+KHBL-$ZtjIwtq^W|jn zu?Un!s95_NltqXdNOtY4+QCkVg4s_4DDxRilheyKUS`>>N5`70C@Yq*TT-=a=}!Ra zsUS}j@-Tmd#w0p~t1g|@5e*V&A3g9BnKn?c+Fk|}m5ND=` z+h3U*hXDM<*&UP@Rg$Y>;_N<@#Q-zqj+w;>0|4B_DFKw1^@VLUqS4Q1!QYTC=Vtu9 zzg)`guB)31yUdwMu6UPVhL;$@N!O7klJzvU+D;{rN`+-C!uP2y+FQ9B94RlQ8>)t| z<#MVMZGEVUH*5EKu)s@y^IDG zb?7qEWiYb*$n?wRL#_w)iI%rKZ4*ax`GfXk0WE@~Ih$w(o@R5JXs@K>sbAkldHfSC zsC2nnKAxaj4%Q>h6WbVHORbozB^>2ynJlGRYD@T9rX-0*wf*4lc1q4A!Pk;@)mCYJ zT3B^ulev~IlkOU<4=>ccJcRqlzNuOhKUBc4Er05peL*R*?igEwx3xC1{eSU literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/tunnels/gtp/gtp9_unknown_or_too_short_payload.pcap b/testing/btest/Traces/tunnels/gtp/gtp9_unknown_or_too_short_payload.pcap new file mode 100755 index 0000000000000000000000000000000000000000..a39026aeffb05b292694e195e75bbb71da192737 GIT binary patch literal 13195 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 +# @TEST-EXEC: btest-diff out + +# In telecoms there is never a GTP tunnel within another GTP tunnel. +# So if we find inside a GTP tunnel anohter IP/UDP packet with port 2152, +# it is just a UDP packet, but not another GTP tunnel. + +event protocol_violation(c: connection, atype: count, aid: count, reason: string) + { + print "protocol_violation", c$id, reason; + } diff --git a/testing/btest/core/tunnels/gtp/not_user_plane_data.test b/testing/btest/core/tunnels/gtp/not_user_plane_data.test new file mode 100644 index 0000000000..a6a3333360 --- /dev/null +++ b/testing/btest/core/tunnels/gtp/not_user_plane_data.test @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -r $TRACES/tunnels/gtp/gtp10_not_0xff.pcap +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: test ! -e tunnel.log + +# There are GTP tunnel packets, which do not contain user plane data. Only +# those with gtp.message==0xff contain user plane data. Other GTP packets +# without user plane data are echo request, echo reply, error indication +# and stop marker (not included in trace). Those non-user plane GTP +# packets are ignored for now. diff --git a/testing/btest/core/tunnels/gtp/opt_header.test b/testing/btest/core/tunnels/gtp/opt_header.test new file mode 100644 index 0000000000..b7100f2190 --- /dev/null +++ b/testing/btest/core/tunnels/gtp/opt_header.test @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro -r $TRACES/tunnels/gtp/gtp6_gtp_0x32.pcap %INPUT >out +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff tunnel.log + +# Some GTPv1 headers have some optional fields totaling to a 4-byte extension +# of the mandatory header. + +event gtpv1_g_pdu_packet(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr) + { + print "gtpv1_packet", inner_gtp; + } diff --git a/testing/btest/core/tunnels/gtp/outer_ip_frag.test b/testing/btest/core/tunnels/gtp/outer_ip_frag.test new file mode 100644 index 0000000000..b2badb9c1b --- /dev/null +++ b/testing/btest/core/tunnels/gtp/outer_ip_frag.test @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro -C -r $TRACES/tunnels/gtp/gtp1_gn_normal_incl_fragmentation.pcap +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff http.log +# @TEST-EXEC: btest-diff tunnel.log + +# Normal GTP file, incl. TCP handshake and HTTP message. +# The inner IP packet is put into a GTP tunnel and as the original user payload +# is already 1500 byte, the tunneled packet incl. GTP/UDP/IP payload is +# bigger than 1500 byte and thus the outer IP must be fragmented, as seen here. +# (checksums are incorrect because packets were anonymized and tcprewrite +# seems to fail to correct the checksums when there's IP fragmentation). diff --git a/testing/btest/core/tunnels/gtp/unknown_or_too_short.test b/testing/btest/core/tunnels/gtp/unknown_or_too_short.test new file mode 100644 index 0000000000..e1b3d4ba20 --- /dev/null +++ b/testing/btest/core/tunnels/gtp/unknown_or_too_short.test @@ -0,0 +1,13 @@ +# @TEST-EXEC: bro -C -r $TRACES/tunnels/gtp/gtp9_unknown_or_too_short_payload.pcap +# @TEST-EXEC: btest-diff dpd.log +# @TEST-EXEC: btest-diff tunnel.log + +# Packet 11, epoch time 1333458853.075889 is malformed. Only 222 byte are +# captured, although according to the IP header a full packet should be +# available. In Sessions.cc this throws a weird message at line 710. +# Packet 12, epoch time 1333458853.075904 is malformed. The user plane +# packet is no IPv4 nor IPv6 packet. Very probably this is a follow up +# issue on a problem of the user plane packet before it was put into the +# tunnel. The user plane packet may got corrupt and then put into 2 tunnel +# packets, here packet 11 and 12, and in packet 12 the user plane data is +# part of the remainder of the broken user plane packet of packet 11. From 3e7fb3a659d617426259ac58bf282147a6d440e0 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 19 Oct 2012 14:17:29 -0500 Subject: [PATCH 02/29] Add GTP tunnel analyzer memory leak unit test. --- testing/btest/core/leaks/gtp_opt_header.test | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 testing/btest/core/leaks/gtp_opt_header.test diff --git a/testing/btest/core/leaks/gtp_opt_header.test b/testing/btest/core/leaks/gtp_opt_header.test new file mode 100644 index 0000000000..76c65d5762 --- /dev/null +++ b/testing/btest/core/leaks/gtp_opt_header.test @@ -0,0 +1,15 @@ +# Needs perftools support. +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-GROUP: leaks +# +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -r $TRACES/tunnels/gtp/gtp6_gtp_0x32.pcap %INPUT >out + +# Some GTPv1 headers have some optional fields totaling to a 4-byte extension +# of the mandatory header. + +event gtpv1_g_pdu_packet(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr) + { + print "gtpv1_packet", inner_gtp; + } From 7cf54b2541139bb62e8bb19240ab5f5f24f35f32 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 29 Oct 2012 12:15:48 -0500 Subject: [PATCH 03/29] Change binpac exceptions in AYIYA/GTP analyzers to do protocol_violation As opposed to creating weirds for e.g. "binpac::ExceptionOutOfBound". The protocol_violation will also result in the disabling of the analyzer by default. --- src/AYIYA.cc | 10 +++++++++- src/GTPv1.cc | 9 ++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/AYIYA.cc b/src/AYIYA.cc index c525a73b6c..79fa44e743 100644 --- a/src/AYIYA.cc +++ b/src/AYIYA.cc @@ -20,5 +20,13 @@ void AYIYA_Analyzer::Done() void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); - interp->NewData(orig, data, data + len); + + try + { + interp->NewData(orig, data, data + len); + } + catch ( const binpac::Exception& e ) + { + ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); + } } diff --git a/src/GTPv1.cc b/src/GTPv1.cc index b7a0fdc664..68b6f30a0c 100644 --- a/src/GTPv1.cc +++ b/src/GTPv1.cc @@ -20,5 +20,12 @@ void GTPv1_Analyzer::Done() void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); - interp->NewData(orig, data, data + len); + try + { + interp->NewData(orig, data, data + len); + } + catch ( const binpac::Exception& e ) + { + ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); + } } From c98301e51f6c4cfd48d299e7cfe59e03565cd2d8 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 26 Nov 2012 15:58:25 -0500 Subject: [PATCH 04/29] Fixed a DNS attribute issue (reported by Matt Thompson). --- scripts/base/protocols/dns/main.bro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index 8ae3806ab6..ee0e4166da 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -67,7 +67,7 @@ export { ready: bool &default=F; ## The total number of resource records in a reply message's answer ## section. - total_answers: count &default=0; + total_answers: count &optional; ## The total number of resource records in a reply message's answer, ## authority, and additional sections. total_replies: count &optional; @@ -231,6 +231,7 @@ event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) Log::write(DNS::LOG, c$dns); # This record is logged and no longer pending. delete c$dns_state$pending[c$dns$trans_id]; + delete c$dns; } } From 378ee699ffc058f368a06691e4237c7f1e791462 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 26 Nov 2012 16:54:36 -0600 Subject: [PATCH 05/29] Hook functions now directly callable instead of w/ "hook" statements. The return value of the call is an implicit boolean value of T if all hook handlers ran, or F if one hook handler exited as a result of a break statement and potentially prevented other handlers from running. Scripts don't need to declare hooks with an explicit return type of bool (internally, that's assumed), and any values given to (optional) return statements in handler definitions are just ignored. Addresses #918. --- doc/scripts/builtins.rst | 29 +++++----- src/Expr.cc | 11 ++-- src/Expr.h | 2 +- src/Func.cc | 23 ++++++-- src/SerialTypes.h | 1 - src/Stmt.cc | 54 ++----------------- src/Stmt.h | 18 ------- src/StmtEnums.h | 2 +- src/Var.cc | 4 +- src/parse.y | 24 ++------- testing/btest/Baseline/language.hook/out | 8 +++ .../btest/Baseline/language.invalid_hook/out | 1 - testing/btest/core/leaks/hook.bro | 30 ++++++++--- testing/btest/language/hook.bro | 30 ++++++++--- testing/btest/language/invalid_hook.bro | 16 ------ 15 files changed, 108 insertions(+), 145 deletions(-) delete mode 100644 testing/btest/Baseline/language.invalid_hook/out delete mode 100644 testing/btest/language/invalid_hook.bro diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index ba786ba0d2..cf62299783 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -505,15 +505,14 @@ The Bro scripting language supports the following built-in types. A hook is another flavor of function that shares characteristics of both a :bro:type:`function` and a :bro:type:`event`. They are like events in that many handler bodies can be defined for the same hook - identifier, they have no return vale, and the order of execution - can be enforced with :bro:attr:`&priority`. They are more like - functions in the way they are invoked/called, because, unlike - events, their execution is immediate and they do not get scheduled - through an event queue. Also, a unique feature of a hook is that - a given hook handler body can short-circuit the execution of - remaining hook handlers simply by exiting from the body as a result - of a ``break`` statement (as opposed to a ``return`` or just - reaching the end of the body). + identifier and the order of execution can be enforced with + :bro:attr:`&priority`. They are more like functions in the way they + are invoked/called, because, unlike events, their execution is + immediate and they do not get scheduled through an event queue. + Also, a unique feature of a hook is that a given hook handler body + can short-circuit the execution of remaining hook handlers simply by + exiting from the body as a result of a ``break`` statement (as + opposed to a ``return`` or just reaching the end of the body). A hook type is declared like:: @@ -553,12 +552,12 @@ The Bro scripting language supports the following built-in types. a hook type isn't strictly required, when it is provided, the argument types must match. - To invoke immediate execution of all hook handler bodies, a ``hook`` - statement must be used: + To invoke immediate execution of all hook handler bodies, they + can be called just like a function: .. code:: bro - hook myhook("hi"); + myhook("hi"); And the output would like like:: @@ -568,6 +567,12 @@ The Bro scripting language supports the following built-in types. Note how the modification to arguments can be seen by remaining hook handlers. + The return value of a hook call is an implicit :bro:type:`bool` + value with ``T`` meaning that all handlers for the hook were + executed and ``F`` meaning that only some of the handlers may have + executed due to one handler body exiting as a result of a ``break`` + statement. + Attributes ---------- diff --git a/src/Expr.cc b/src/Expr.cc index 733e0fe9a5..a7075566aa 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4374,7 +4374,7 @@ bool InExpr::DoUnserialize(UnserialInfo* info) return true; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) +CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) : Expr(EXPR_CALL) { func = arg_func; @@ -4415,13 +4415,8 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) break; case FUNC_FLAVOR_HOOK: - // It's fine to not have a yield if it's known that the call - // is being done from a hook statement. - if ( ! in_hook ) - { - Error("hook called in expression, use hook statement instead"); - SetError(); - } + Error("hook has no yield type"); + SetError(); break; default: diff --git a/src/Expr.h b/src/Expr.h index bd4824f8ee..c16cf86612 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -959,7 +959,7 @@ protected: class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args, bool in_hook = false); + CallExpr(Expr* func, ListExpr* args); ~CallExpr(); Expr* Func() const { return func; } diff --git a/src/Func.cc b/src/Func.cc index 27acce4f04..e3675ebc2c 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -349,16 +349,31 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const break; } - if ( flow == FLOW_BREAK && Flavor() == FUNC_FLAVOR_HOOK ) + if ( Flavor() == FUNC_FLAVOR_HOOK ) { - // short-circuit execution of remaining hook handler bodies - break; + // Ignore any return values of hook bodies, final return value + // depends on whether a body returns as a result of break statement + Unref(result); + result = 0; + + if ( flow == FLOW_BREAK ) + { + // short-circuit execution of remaining hook handler bodies + result = new Val(false, TYPE_BOOL); + break; + } } } + if ( Flavor() == FUNC_FLAVOR_HOOK ) + { + if ( ! result ) + result = new Val(true, TYPE_BOOL); + } + // Warn if the function returns something, but we returned from // the function without an explicit return, or without a value. - if ( FType()->YieldType() && FType()->YieldType()->Tag() != TYPE_VOID && + else if ( FType()->YieldType() && FType()->YieldType()->Tag() != TYPE_VOID && (flow != FLOW_RETURN /* we fell off the end */ || ! result /* explicit return with no result */) && ! f->HasDelayed() ) diff --git a/src/SerialTypes.h b/src/SerialTypes.h index a18c9bcc65..c47ff19298 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -165,7 +165,6 @@ SERIAL_STMT(EVENT_BODY_LIST, 16) SERIAL_STMT(INIT_STMT, 17) SERIAL_STMT(NULL_STMT, 18) SERIAL_STMT(WHEN_STMT, 19) -SERIAL_STMT(HOOK_STMT, 20) #define SERIAL_TYPE(name, val) SERIAL_CONST(name, val, BRO_TYPE) SERIAL_TYPE(BRO_TYPE, 1) diff --git a/src/Stmt.cc b/src/Stmt.cc index 0a5ae16ef6..c65b44a9bd 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -23,7 +23,7 @@ const char* stmt_name(BroStmtTag t) "print", "event", "expr", "if", "when", "switch", "for", "next", "break", "return", "add", "delete", "list", "bodylist", - "", "hook", + "", "null", }; @@ -933,52 +933,6 @@ bool EventStmt::DoUnserialize(UnserialInfo* info) return event_expr != 0; } -HookStmt::HookStmt(CallExpr* arg_e) : ExprStmt(STMT_HOOK, arg_e) - { - call_expr = arg_e; - } - -Val* HookStmt::Exec(Frame* f, stmt_flow_type& flow) const - { - RegisterAccess(); - - Val* ret = call_expr->Eval(f); - Unref(ret); - - flow = FLOW_NEXT; - - return 0; - } - -TraversalCode HookStmt::Traverse(TraversalCallback* cb) const - { - TraversalCode tc = cb->PreStmt(this); - HANDLE_TC_STMT_PRE(tc); - - // call expr is stored in base class's "e" field. - tc = e->Traverse(cb); - HANDLE_TC_STMT_PRE(tc); - - tc = cb->PostStmt(this); - HANDLE_TC_STMT_POST(tc); - } - -IMPLEMENT_SERIAL(HookStmt, SER_HOOK_STMT); - -bool HookStmt::DoSerialize(SerialInfo* info) const - { - DO_SERIALIZE(SER_HOOK_STMT, ExprStmt); - return call_expr->Serialize(info); - } - -bool HookStmt::DoUnserialize(UnserialInfo* info) - { - DO_UNSERIALIZE(ExprStmt); - - call_expr = (CallExpr*) Expr::Unserialize(info, EXPR_CALL); - return call_expr != 0; - } - ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) : ExprStmt(STMT_FOR, loop_expr) { @@ -1378,7 +1332,10 @@ ReturnStmt::ReturnStmt(Expr* arg_e) : ExprStmt(STMT_RETURN, arg_e) } else if ( ! e ) - Error("return statement needs expression"); + { + if ( ft->Flavor() != FUNC_FLAVOR_HOOK ) + Error("return statement needs expression"); + } else (void) check_and_promote_expr(e, yt); @@ -1990,7 +1947,6 @@ int same_stmt(const Stmt* s1, const Stmt* s2) case STMT_RETURN: case STMT_EXPR: case STMT_EVENT: - case STMT_HOOK: { const ExprStmt* e1 = (const ExprStmt*) s1; const ExprStmt* e2 = (const ExprStmt*) s2; diff --git a/src/Stmt.h b/src/Stmt.h index 68bb8d6425..7c3b42609b 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -286,24 +286,6 @@ protected: EventExpr* event_expr; }; -class HookStmt : public ExprStmt { -public: - HookStmt(CallExpr* e); - - Val* Exec(Frame* f, stmt_flow_type& flow) const; - - TraversalCode Traverse(TraversalCallback* cb) const; - -protected: - friend class Stmt; - - HookStmt() { call_expr = 0; } - - DECLARE_SERIAL(HookStmt); - - CallExpr* call_expr; -}; - class ForStmt : public ExprStmt { public: ForStmt(id_list* loop_vars, Expr* loop_expr); diff --git a/src/StmtEnums.h b/src/StmtEnums.h index fa5b70389d..f431e3fea1 100644 --- a/src/StmtEnums.h +++ b/src/StmtEnums.h @@ -15,7 +15,7 @@ typedef enum { STMT_RETURN, STMT_ADD, STMT_DELETE, STMT_LIST, STMT_EVENT_BODY_LIST, - STMT_INIT, STMT_HOOK, + STMT_INIT, STMT_NULL #define NUM_STMTS (int(STMT_NULL) + 1) } BroStmtTag; diff --git a/src/Var.cc b/src/Var.cc index 9c4fb5b978..68be18b55e 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -294,12 +294,12 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) void begin_func(ID* id, const char* module_name, function_flavor flavor, int is_redef, FuncType* t) { - if ( flavor == FUNC_FLAVOR_EVENT || flavor == FUNC_FLAVOR_HOOK ) + if ( flavor == FUNC_FLAVOR_EVENT ) { const BroType* yt = t->YieldType(); if ( yt && yt->Tag() != TYPE_VOID ) - id->Error("event/hook cannot yield a value", t); + id->Error("event cannot yield a value", t); t->ClearYieldType(flavor); } diff --git a/src/parse.y b/src/parse.y index b4eee1a56c..39673cacc2 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 88 +%expect 87 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -56,7 +56,6 @@ %type pattern %type expr init anonymous_function %type event -%type hook %type stmt stmt_list func_body for_head %type type opt_type enum_body %type func_hdr func_params @@ -212,7 +211,6 @@ static std::list* concat_opt_docs (std::list* pre, Val* val; RE_Matcher* re; Expr* expr; - CallExpr* call_expr; EventExpr* event_expr; Stmt* stmt; ListExpr* list; @@ -875,7 +873,7 @@ type: | TOK_HOOK '(' formal_args ')' { set_location(@1, @3); - $$ = new FuncType($3, 0, FUNC_FLAVOR_HOOK); + $$ = new FuncType($3, base_type(TYPE_BOOL), FUNC_FLAVOR_HOOK); } | TOK_FILE TOK_OF type @@ -1209,6 +1207,8 @@ func_hdr: } | TOK_HOOK def_global_id func_params { + $3->ClearYieldType(FUNC_FLAVOR_HOOK); + $3->SetYieldType(base_type(TYPE_BOOL)); begin_func($2, current_module.c_str(), FUNC_FLAVOR_HOOK, 0, $3); $$ = $3; @@ -1372,14 +1372,6 @@ stmt: brofiler.AddStmt($$); } - | TOK_HOOK hook ';' opt_no_test - { - set_location(@1, @4); - $$ = new HookStmt($2); - if ( ! $4 ) - brofiler.AddStmt($$); - } - | TOK_IF '(' expr ')' stmt { set_location(@1, @4); @@ -1533,14 +1525,6 @@ event: } ; -hook: - expr '(' opt_expr_list ')' - { - set_location(@1, @4); - $$ = new CallExpr($1, $3, true); - } - ; - case_list: case_list case { $1->append($2); } diff --git a/testing/btest/Baseline/language.hook/out b/testing/btest/Baseline/language.hook/out index 10688acc3b..18828ad15f 100644 --- a/testing/btest/Baseline/language.hook/out +++ b/testing/btest/Baseline/language.hook/out @@ -1,7 +1,15 @@ myhook, &priority=10, [a=1156, b=hello world] +myhook return F +myhook return T myhook, &priority=5, [a=37, b=goobye world] +F myhook3, 8 +T myhook4, 2 myhook4, 1 +T myhook, &priority=10, [a=2, b=it works] +myhook return F +myhook return T myhook, &priority=5, [a=37, b=goobye world] +F diff --git a/testing/btest/Baseline/language.invalid_hook/out b/testing/btest/Baseline/language.invalid_hook/out deleted file mode 100644 index 167d62ccc8..0000000000 --- a/testing/btest/Baseline/language.invalid_hook/out +++ /dev/null @@ -1 +0,0 @@ -error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_hook/invalid_hook.bro, line 15: hook called in expression, use hook statement instead (myhook(nope)) diff --git a/testing/btest/core/leaks/hook.bro b/testing/btest/core/leaks/hook.bro index eadb406e71..d9dcbff369 100644 --- a/testing/btest/core/leaks/hook.bro +++ b/testing/btest/core/leaks/hook.bro @@ -39,7 +39,25 @@ hook myhook(r: rec) &priority=10 r$b = "goobye world"; # returning from the handler early, is fine, remaining handlers still run. return; - print "ERROR: break statement should return from hook handler body"; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=9 + { + print "myhook return F"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return F; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=8 + { + print "myhook return T"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return T; + print "ERROR: return statement should return from hook handler body"; } # hook function doesn't need a declaration, we can go straight to defining @@ -63,16 +81,16 @@ event new_connection(c: connection) { print "new_connection", c$id; - hook myhook([$a=1156, $b="hello world"]); + print myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - hook myhook2("nope"); + print myhook2("nope"); - hook myhook3(8); - hook myhook4(); + print myhook3(8); + print myhook4(); # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - hook h([$a=2, $b="it works"]); + print h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook.bro b/testing/btest/language/hook.bro index 8f7a85ce95..eedd2ff056 100644 --- a/testing/btest/language/hook.bro +++ b/testing/btest/language/hook.bro @@ -34,7 +34,25 @@ hook myhook(r: rec) &priority=10 r$b = "goobye world"; # returning from the handler early, is fine, remaining handlers still run. return; - print "ERROR: break statement should return from hook handler body"; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=9 + { + print "myhook return F"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return F; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=8 + { + print "myhook return T"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return T; + print "ERROR: return statement should return from hook handler body"; } # hook function doesn't need a declaration, we can go straight to defining @@ -56,16 +74,16 @@ hook myhook4() &priority=2 event bro_init() { - hook myhook([$a=1156, $b="hello world"]); + print myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - hook myhook2("nope"); + print myhook2("nope"); - hook myhook3(8); - hook myhook4(); + print myhook3(8); + print myhook4(); # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - hook h([$a=2, $b="it works"]); + print h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/invalid_hook.bro b/testing/btest/language/invalid_hook.bro deleted file mode 100644 index 0dbbfd1b6f..0000000000 --- a/testing/btest/language/invalid_hook.bro +++ /dev/null @@ -1,16 +0,0 @@ -# @TEST-EXEC-FAIL: bro -b %INPUT >out 2>&1 -# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out - -global myhook: hook(s: string); - -hook myhook(s: string) - { - print "myhook", s; - } - -event bro_init() - { - # hooks must be invoked with a "hook", statement. They have no return - # value and don't make sense to evaluate as arbitrary expressions. - local r = myhook("nope"); - } From a0590b2140adae5b9cc4ae5520bd566d12a4331d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:19:48 -0600 Subject: [PATCH 06/29] Fix table(), set(), vector() constructors in table initializer lists. Also adds type checking of yield values to table() constructor and fixes the type checking of yield values in vector() constructor. Addresses #5. --- src/Expr.cc | 38 ++++++++-- src/Val.cc | 2 + .../output | 42 +++++++++++ .../language/table-init-container-ctors.bro | 74 +++++++++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 testing/btest/Baseline/language.table-init-container-ctors/output create mode 100644 testing/btest/language/table-init-container-ctors.bro diff --git a/src/Expr.cc b/src/Expr.cc index 733e0fe9a5..89680b9b5b 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2663,7 +2663,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const TableVal* tv = aggr->AsTableVal(); Val* index = op1->Eval(f); - Val* v = op2->Eval(f); + Val* v = check_and_promote(op2->Eval(f), t->YieldType(), 1); if ( ! index || ! v ) return; @@ -3386,7 +3386,14 @@ Val* TableConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + exprs[i]->EvalIntoAggregate(t, tval, 0); + + return tval; } void TableConstructorExpr::ExprDescribe(ODesc* d) const @@ -3456,7 +3463,26 @@ Val* SetConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + const BroType* index_type = t->AsTableType()->Indices(); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + { + Expr* e = exprs[i]; + Val* element = check_and_promote(e->Eval(0), index_type, 1); + + if ( ! element || ! tval->Assign(element, 0) ) + { + Error(fmt("initialization type mismatch in set"), e); + return 0; + } + + Unref(element); + } + + return tval; } void SetConstructorExpr::ExprDescribe(ODesc* d) const @@ -3536,14 +3562,14 @@ Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - VectorVal* vec = aggr->AsVectorVal(); - const BroType* vt = vec->Type()->AsVectorType()->YieldType(); + VectorType* vt = Type()->AsVectorType(); + VectorVal* vec = aggr ? aggr->AsVectorVal() : new VectorVal(vt); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) { Expr* e = exprs[i]; - Val* v = check_and_promote(e->Eval(0), vt, 1); + Val* v = check_and_promote(e->Eval(0), t->YieldType(), 1); if ( ! v || ! vec->Assign(i, v, e) ) { diff --git a/src/Val.cc b/src/Val.cc index 79fa8a0c69..0e30218b4b 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3117,6 +3117,8 @@ void VectorVal::ValDescribe(ODesc* d) const Val* check_and_promote(Val* v, const BroType* t, int is_init) { + if ( ! v ) return 0; + BroType* vt = v->Type(); vt = flatten_type(vt); diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output new file mode 100644 index 0000000000..feda20fea7 --- /dev/null +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -0,0 +1,42 @@ +table of set +{ +[13] = { +[bar, 2] , +[foo, 1] +}, +[5] = { +[bah, 3] , +[baz, 4] +} +} + +table of vector +{ +[13] = [1, 2], +[5] = [3, 4] +} + +table of table +{ +[13] = { +[bar, 2] = 2, +[foo, 1] = 1 +}, +[5] = { +[bah, 3] = 3, +[baz, 4] = 4 +} +} + +T +T +T +T +T +T +T +T +T +T +T +T diff --git a/testing/btest/language/table-init-container-ctors.bro b/testing/btest/language/table-init-container-ctors.bro new file mode 100644 index 0000000000..8882cb5640 --- /dev/null +++ b/testing/btest/language/table-init-container-ctors.bro @@ -0,0 +1,74 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# The various container constructor expressions should work in table +# initialization lists. + +type set_yield: set[string, count]; +type vector_yield: vector of count; +type table_yield: table[string, count] of count; + +global lone_set_ctor: set_yield = set(["foo", 1], ["bar", 2]); +global lone_vector_ctor: vector_yield = vector(1, 2); +global lone_table_ctor: table_yield = table(["foo", 1] = 1, ["bar", 2] = 2); + +global table_of_set: table[count] of set_yield = { + [13] = lone_set_ctor, + [5] = set(["bah", 3], ["baz", 4]), +}; + +global table_of_vector: table[count] of vector_yield = { + [13] = lone_vector_ctor, + [5] = vector(3, 4), +}; + +global table_of_table: table[count] of table_yield = { + [13] = lone_table_ctor, + [5] = table(["bah", 3] = 3, ["baz", 4] = 4), +}; + +# Just copying the inline ctors used in the table initializer lists here +# for later comparisons. +global inline_set_ctor: set_yield = set(["bah", 3], ["baz", 4]); +global inline_vector_ctor: vector_yield = vector(3, 4); +global inline_table_ctor: table_yield = table(["bah", 3] = 3, ["baz", 4] = 4); + +function compare_set_yield(a: set_yield, b: set_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b; + } + +function compare_vector_yield(a: vector_yield, b: vector_yield) + { + local c: count; + for ( c in a ) + print a[c] == b[c]; + } + +function compare_table_yield(a: table_yield, b: table_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b && a[s, c] == b[s, c]; + } + +print "table of set"; +print table_of_set; +print ""; +print "table of vector"; +print table_of_vector; +print ""; +print "table of table"; +print table_of_table; +print ""; + +compare_set_yield(table_of_set[13], lone_set_ctor); +compare_set_yield(table_of_set[5], inline_set_ctor); +compare_vector_yield(table_of_vector[13], lone_vector_ctor); +compare_vector_yield(table_of_vector[5], inline_vector_ctor); +compare_table_yield(table_of_table[13], lone_table_ctor); +compare_table_yield(table_of_table[5], inline_table_ctor); From 00f7bbda96d32d3c323ad03559669e757e4d20c4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:53:36 -0600 Subject: [PATCH 07/29] Add test of record() constructor to table initializer unit test. --- .../output | 8 +++++++ .../language/table-init-container-ctors.bro | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output index feda20fea7..27774a660a 100644 --- a/testing/btest/Baseline/language.table-init-container-ctors/output +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -28,6 +28,14 @@ table of table } } +table of record +{ +[13] = [a=1, b=foo], +[5] = [a=2, b=bar] +} + +T +T T T T diff --git a/testing/btest/language/table-init-container-ctors.bro b/testing/btest/language/table-init-container-ctors.bro index 8882cb5640..4829f41688 100644 --- a/testing/btest/language/table-init-container-ctors.bro +++ b/testing/btest/language/table-init-container-ctors.bro @@ -7,10 +7,15 @@ type set_yield: set[string, count]; type vector_yield: vector of count; type table_yield: table[string, count] of count; +type record_yield: record { + a: count; + b: string; +}; global lone_set_ctor: set_yield = set(["foo", 1], ["bar", 2]); global lone_vector_ctor: vector_yield = vector(1, 2); global lone_table_ctor: table_yield = table(["foo", 1] = 1, ["bar", 2] = 2); +global lone_record_ctor: record_yield = record($a=1, $b="foo"); global table_of_set: table[count] of set_yield = { [13] = lone_set_ctor, @@ -27,11 +32,17 @@ global table_of_table: table[count] of table_yield = { [5] = table(["bah", 3] = 3, ["baz", 4] = 4), }; +global table_of_record: table[count] of record_yield = { + [13] = lone_record_ctor, + [5] = record($a=2, $b="bar"), +}; + # Just copying the inline ctors used in the table initializer lists here # for later comparisons. global inline_set_ctor: set_yield = set(["bah", 3], ["baz", 4]); global inline_vector_ctor: vector_yield = vector(3, 4); global inline_table_ctor: table_yield = table(["bah", 3] = 3, ["baz", 4] = 4); +global inline_record_ctor: record_yield = record($a=2, $b="bar"); function compare_set_yield(a: set_yield, b: set_yield) { @@ -56,6 +67,11 @@ function compare_table_yield(a: table_yield, b: table_yield) print [s, c] in b && a[s, c] == b[s, c]; } +function compare_record_yield(a: record_yield, b: record_yield) + { + print a$a == b$a && a$b == b$b; + } + print "table of set"; print table_of_set; print ""; @@ -65,6 +81,9 @@ print ""; print "table of table"; print table_of_table; print ""; +print "table of record"; +print table_of_record; +print ""; compare_set_yield(table_of_set[13], lone_set_ctor); compare_set_yield(table_of_set[5], inline_set_ctor); @@ -72,3 +91,5 @@ compare_vector_yield(table_of_vector[13], lone_vector_ctor); compare_vector_yield(table_of_vector[5], inline_vector_ctor); compare_table_yield(table_of_table[13], lone_table_ctor); compare_table_yield(table_of_table[5], inline_table_ctor); +compare_record_yield(table_of_record[13], lone_record_ctor); +compare_record_yield(table_of_record[5], inline_record_ctor); From 3b3b05fbbb87f938399f86cd9e75fe636ced421e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Nov 2012 10:07:38 -0600 Subject: [PATCH 08/29] Clarification in hook documentation. --- doc/scripts/builtins.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index cf62299783..0e474e9677 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -548,9 +548,9 @@ The Bro scripting language supports the following built-in types. print "not going to happen", s; } - Note that, although the first (forward) declaration of ``myhook`` as - a hook type isn't strictly required, when it is provided, the - argument types must match. + Note that the first (forward) declaration of ``myhook`` as a hook + type isn't strictly required. Argument types must match for all + hook handlers and any forward declaration of a given hook. To invoke immediate execution of all hook handler bodies, they can be called just like a function: From f7e07f5f097036bf80252b03e5e79408f3f243be Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Nov 2012 15:44:03 -0600 Subject: [PATCH 09/29] Fix various bugs with table/set attributes. - Identifiers that are initialized with set()/table() constructor expressions now inherit attributes from the expression. Before, statements like const i: set[string] = set() &redef; associated the attribute with the set() constructor, but not the "i" identifier, preventing redefinition. Addresses #866. - Allow &default attribute to apply to tables initialized as empty (via either "{ }" or "table()") or if the expression supplied to it can evaluate to a type that's promotable to the same yield type as the table. --- src/Attr.cc | 10 ++ src/Expr.cc | 2 +- src/Expr.h | 4 + src/Var.cc | 28 +++++ .../Baseline/language.table-init-attrs/output | 91 ++++++++++++++ testing/btest/language/table-init-attrs.bro | 115 ++++++++++++++++++ 6 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/language.table-init-attrs/output create mode 100644 testing/btest/language/table-init-attrs.bro diff --git a/src/Attr.cc b/src/Attr.cc index 6e0769c7b0..6cc582f053 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -260,6 +260,11 @@ void Attributes::CheckAttr(Attr* a) // Ok. break; + if ( type->Tag() == TYPE_TABLE && + type->AsTableType()->IsUnspecifiedTable() ) + // Ok. + break; + a->AttrExpr()->Error("&default value has inconsistent type", type); } @@ -290,6 +295,11 @@ void Attributes::CheckAttr(Attr* a) // Ok. break; + Expr* e = a->AttrExpr(); + if ( check_and_promote_expr(e, ytype) ) + // Ok. + break; + Error("&default value has inconsistent type 2"); } diff --git a/src/Expr.cc b/src/Expr.cc index 89680b9b5b..5b472ab6a6 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3445,7 +3445,7 @@ Val* SetConstructorExpr::Eval(Frame* f) const if ( IsError() ) return 0; - TableVal* aggr = new TableVal(type->AsTableType(), 0); + TableVal* aggr = new TableVal(type->AsTableType(), attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) diff --git a/src/Expr.h b/src/Expr.h index bd4824f8ee..afdf02c124 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -747,6 +747,8 @@ public: TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs); ~TableConstructorExpr() { Unref(attrs); } + Attributes* Attrs() { return attrs; } + Val* Eval(Frame* f) const; protected: @@ -767,6 +769,8 @@ public: SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs); ~SetConstructorExpr() { Unref(attrs); } + Attributes* Attrs() { return attrs; } + Val* Eval(Frame* f) const; protected: diff --git a/src/Var.cc b/src/Var.cc index 9c4fb5b978..3526c96550 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -109,6 +109,34 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( attr ) id->AddAttrs(new Attributes(attr, t, false)); + if ( init ) + { + switch ( init->Tag() ) { + case EXPR_TABLE_CONSTRUCTOR: + { + TableConstructorExpr* ctor = (TableConstructorExpr*) init; + if ( ctor->Attrs() ) + { + ::Ref(ctor->Attrs()); + id->AddAttrs(ctor->Attrs()); + } + } + break; + case EXPR_SET_CONSTRUCTOR: + { + SetConstructorExpr* ctor = (SetConstructorExpr*) init; + if ( ctor->Attrs() ) + { + ::Ref(ctor->Attrs()); + id->AddAttrs(ctor->Attrs()); + } + } + break; + default: + break; + } + } + if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) ) { if ( dt == VAR_CONST ) diff --git a/testing/btest/Baseline/language.table-init-attrs/output b/testing/btest/Baseline/language.table-init-attrs/output new file mode 100644 index 0000000000..55df002ed0 --- /dev/null +++ b/testing/btest/Baseline/language.table-init-attrs/output @@ -0,0 +1,91 @@ +my_set_ctor_init +{ +test2, +test3, +test4, +test1 +} + +my_table_ctor_init +{ +[2] = test2, +[1] = test1, +[3] = test3 +} +nope + +my_set_init +{ +test2, +test3, +test4, +test1 +} + +my_table_init +{ +[2] = test2, +[4] = test4, +[1] = test1, +[3] = test3 +} +nope + +inception +{ +[0] = { +[13] = bar +} +} +{ +[13] = bar +} +bar +forty-two +{ + +} +we need to go deeper +{ +[0] = { +[13] = bar +} +} +{ +[13] = bar +} +bar +forty-two +{ + +} +we need to go deeper + +local table t1 +{ +[1] = foo +} +foo +nope + +local table t2 +{ +[1] = foo +} +foo +nope + +local table t3 +{ + +} +nope +nope + +local table t4 +{ + +} +nope +nope + diff --git a/testing/btest/language/table-init-attrs.bro b/testing/btest/language/table-init-attrs.bro new file mode 100644 index 0000000000..76d98b9fed --- /dev/null +++ b/testing/btest/language/table-init-attrs.bro @@ -0,0 +1,115 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# set()/table() constructors are allowed to have attributes. When initializing +# an identifier, those attributes should also apply to it. + +const my_set_ctor_init: set[string] = set("test1") &redef; + +redef my_set_ctor_init += { + "test2", + "test3", +}; + +redef my_set_ctor_init += set("test4"); + +const my_table_ctor_init: table[count] of string = table([1] = "test1") &redef &default="nope"; + +redef my_table_ctor_init += { + [2] = "test2", + [3] = "test3", +}; + +# initializer list versions work the same way. + +const my_set_init: set[string] = { "test1" } &redef; + +redef my_set_init += { + "test2", + "test3", +}; + +redef my_set_init += set("test4"); + +const my_table_init: table[count] of string = { [1] = "test1" } &redef &default="nope"; + +redef my_table_init += { + [2] = "test2", + [3] = "test3", +}; + +redef my_table_init += table([4] = "test4"); + +# For tables that yield tables, we can apply attributes to the both other and +# inner tables... + +global inception_table: table[count] of table[count] of string = table( + [0] = table([13] = "bar") &default="forty-two" +) &default=table() &default="we need to go deeper"; + +global inception_table2: table[count] of table[count] of string = { + [0] = table([13] = "bar") &default="forty-two", +} &default=table() &default="we need to go deeper"; + +event bro_init() + { + print "my_set_ctor_init"; + print my_set_ctor_init; + print ""; + print "my_table_ctor_init"; + print my_table_ctor_init; + print my_table_ctor_init[5]; + print ""; + print "my_set_init"; + print my_set_init; + print ""; + print "my_table_init"; + print my_table_init; + print my_table_init[5]; + print ""; + print "inception"; + print inception_table; + print inception_table[0]; + print inception_table[0][13]; + print inception_table[0][42]; + print inception_table[1]; + print inception_table[1][2]; + print inception_table2; + print inception_table2[0]; + print inception_table2[0][13]; + print inception_table2[0][42]; + print inception_table2[1]; + print inception_table2[1][2]; + print ""; + + # just checking attributes on locals works, too + print "local table t1"; + local t1: table[count] of string = table([1] = "foo") &default="nope"; + print t1; + print t1[1]; + print t1[2]; + print ""; + + print "local table t2"; + local t2: table[count] of string = {[1] = "foo"} &default="nope"; + print t2; + print t2[1]; + print t2[2]; + print ""; + + # and for empty initializers... + print "local table t3"; + local t3: table[count] of string = table() &default="nope"; + print t3; + print t3[1]; + print t3[2]; + print ""; + + print "local table t4"; + local t4: table[count] of string = {} &default="nope"; + print t4; + print t4[1]; + print t4[2]; + print ""; + + } From 4e85fe0454c853ea6bab90064c45de32ae35efe4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 30 Nov 2012 15:39:00 -0600 Subject: [PATCH 10/29] Change hook calls to only be allowed when preceded by "hook" keyword. --- doc/scripts/builtins.rst | 14 +++- src/Expr.cc | 9 +- src/Expr.h | 2 +- src/parse.y | 15 +++- testing/btest/Baseline/language.hook/out | 3 + .../Baseline/language.hook_calls/invalid.out | 10 +++ .../Baseline/language.hook_calls/valid.out | 42 ++++++++++ testing/btest/core/leaks/hook.bro | 14 ++-- testing/btest/language/hook.bro | 14 ++-- testing/btest/language/hook_calls.bro | 82 +++++++++++++++++++ 10 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 testing/btest/Baseline/language.hook_calls/invalid.out create mode 100644 testing/btest/Baseline/language.hook_calls/valid.out create mode 100644 testing/btest/language/hook_calls.bro diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 0e474e9677..322aafc2cf 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -553,13 +553,21 @@ The Bro scripting language supports the following built-in types. hook handlers and any forward declaration of a given hook. To invoke immediate execution of all hook handler bodies, they - can be called just like a function: + are called similarly to a function, except preceded by the ``hook`` + keyword: .. code:: bro - myhook("hi"); + hook myhook("hi"); - And the output would like like:: + or + + .. code:: bro + + if ( hook myhook("hi") ) + print "all handlers ran"; + + And the output would look like:: priority 10 myhook handler, hi break out of myhook handling, bye diff --git a/src/Expr.cc b/src/Expr.cc index a7075566aa..a910e0d2fb 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4374,7 +4374,7 @@ bool InExpr::DoUnserialize(UnserialInfo* info) return true; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) +CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) : Expr(EXPR_CALL) { func = arg_func; @@ -4394,6 +4394,13 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) return; } + if ( func_type->AsFuncType()->Flavor() == FUNC_FLAVOR_HOOK && ! in_hook ) + { + func->Error("hook cannot be called directly, use hook operator"); + SetError(); + return; + } + if ( ! func_type->MatchesIndex(args) ) SetError("argument type mismatch in function call"); else diff --git a/src/Expr.h b/src/Expr.h index c16cf86612..bd4824f8ee 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -959,7 +959,7 @@ protected: class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args); + CallExpr(Expr* func, ListExpr* args, bool in_hook = false); ~CallExpr(); Expr* Func() const { return func; } diff --git a/src/parse.y b/src/parse.y index 39673cacc2..0385c1c4e1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 87 +%expect 88 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -32,6 +32,7 @@ %token TOK_NO_TEST +%nonassoc TOK_HOOK %left ',' '|' %right '=' TOK_ADD_TO TOK_REMOVE_FROM %right '?' ':' @@ -118,6 +119,7 @@ extern const char* g_curr_debug_error; #define YYLTYPE yyltype +static int in_hook = 0; int in_init = 0; int in_record = 0; bool resolving_global_ID = false; @@ -515,7 +517,16 @@ expr: | expr '(' opt_expr_list ')' { set_location(@1, @4); - $$ = new CallExpr($1, $3); + $$ = new CallExpr($1, $3, in_hook > 0); + } + + | TOK_HOOK { ++in_hook; } expr + { + --in_hook; + set_location(@1, @3); + if ( $3->Tag() != EXPR_CALL ) + $3->Error("not a valid hook call expression"); + $$ = $3; } | expr TOK_HAS_FIELD TOK_ID diff --git a/testing/btest/Baseline/language.hook/out b/testing/btest/Baseline/language.hook/out index 18828ad15f..bef25193b8 100644 --- a/testing/btest/Baseline/language.hook/out +++ b/testing/btest/Baseline/language.hook/out @@ -8,6 +8,9 @@ T myhook4, 2 myhook4, 1 T +myhook4, 2 +myhook4, 1 +myhook4 all handlers ran myhook, &priority=10, [a=2, b=it works] myhook return F myhook return T diff --git a/testing/btest/Baseline/language.hook_calls/invalid.out b/testing/btest/Baseline/language.hook_calls/invalid.out new file mode 100644 index 0000000000..3412c1900e --- /dev/null +++ b/testing/btest/Baseline/language.hook_calls/invalid.out @@ -0,0 +1,10 @@ +error in ./invalid.bro, line 9: hook cannot be called directly, use hook operator (myhook) +warning in ./invalid.bro, line 9: expression value ignored (myhook(3)) +error in ./invalid.bro, line 10: hook cannot be called directly, use hook operator (myhook) +error in ./invalid.bro, line 11: hook cannot be called directly, use hook operator (myhook) +error in ./invalid.bro, line 12: not a valid hook call expression (2 + 2) +warning in ./invalid.bro, line 12: expression value ignored (2 + 2) +error in ./invalid.bro, line 13: not a valid hook call expression (2 + 2) +error in ./invalid.bro, line 15: hook cannot be called directly, use hook operator (h) +warning in ./invalid.bro, line 15: expression value ignored (h(3)) +error in ./invalid.bro, line 16: hook cannot be called directly, use hook operator (h) diff --git a/testing/btest/Baseline/language.hook_calls/valid.out b/testing/btest/Baseline/language.hook_calls/valid.out new file mode 100644 index 0000000000..c711115315 --- /dev/null +++ b/testing/btest/Baseline/language.hook_calls/valid.out @@ -0,0 +1,42 @@ +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T +myhook(), 0 +F +----------- +indirect() +myhook(), 3 +other myhook(), 3 +indirect() +myhook(), 3 +other myhook(), 3 +T +----------- +really_indirect() +indirect() +myhook(), 3 +other myhook(), 3 +really_indirect() +indirect() +myhook(), 3 +other myhook(), 3 +T +----------- +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T +myhook(), 3 +other myhook(), 3 +yes +myhook(), 0 +double yes +----------- +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T diff --git a/testing/btest/core/leaks/hook.bro b/testing/btest/core/leaks/hook.bro index d9dcbff369..9234184317 100644 --- a/testing/btest/core/leaks/hook.bro +++ b/testing/btest/core/leaks/hook.bro @@ -81,16 +81,20 @@ event new_connection(c: connection) { print "new_connection", c$id; - print myhook([$a=1156, $b="hello world"]); + print hook myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - print myhook2("nope"); + print hook myhook2("nope"); - print myhook3(8); - print myhook4(); + print hook myhook3(8); + print hook myhook4(); + if ( hook myhook4() ) + { + print "myhook4 all handlers ran"; + } # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - print h([$a=2, $b="it works"]); + print hook h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook.bro b/testing/btest/language/hook.bro index eedd2ff056..9c9ab30c18 100644 --- a/testing/btest/language/hook.bro +++ b/testing/btest/language/hook.bro @@ -74,16 +74,20 @@ hook myhook4() &priority=2 event bro_init() { - print myhook([$a=1156, $b="hello world"]); + print hook myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - print myhook2("nope"); + print hook myhook2("nope"); - print myhook3(8); - print myhook4(); + print hook myhook3(8); + print hook myhook4(); + if ( hook myhook4() ) + { + print "myhook4 all handlers ran"; + } # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - print h([$a=2, $b="it works"]); + print hook h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook_calls.bro b/testing/btest/language/hook_calls.bro new file mode 100644 index 0000000000..41ef6f52ae --- /dev/null +++ b/testing/btest/language/hook_calls.bro @@ -0,0 +1,82 @@ +# @TEST-EXEC: bro -b valid.bro >valid.out +# @TEST-EXEC: btest-diff valid.out +# @TEST-EXEC-FAIL: bro -b invalid.bro > invalid.out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff invalid.out + +# hook functions must be called using the "hook" keyword as an operator... + +@TEST-START-FILE valid.bro +hook myhook(i: count) + { + print "myhook()", i; + if ( i == 0 ) break; + } + +hook myhook(i: count) &priority=-1 + { + print "other myhook()", i; + } + +function indirect(): hook(i: count) + { + print "indirect()"; + return myhook; + } + +function really_indirect(): function(): hook(i: count) + { + print "really_indirect()"; + return indirect; + } + +global t: table[count] of hook(i: count) = { + [0] = myhook, +}; + +event bro_init() + { + hook myhook(3); + print hook myhook(3); + print hook myhook(0); + print "-----------"; + hook indirect()(3); + print hook indirect()(3); + print "-----------"; + hook really_indirect()()(3); + print hook really_indirect()()(3); + print "-----------"; + local h = t[0]; + hook h(3); + print hook h(3); + if ( hook h(3) ) + print "yes"; + if ( ! hook h(0) ) + print "double yes"; + print "-----------"; + hook t[0](3); + print hook t[0](3); + } + +@TEST-END-FILE + +@TEST-START-FILE invalid.bro +hook myhook(i: count) + { + print "myhook()", i; + if ( i == 0 ) break; + } + +event bro_init() + { + myhook(3); + print myhook(3); + print myhook(0); + hook 2+2; + print hook 2+2; + local h = myhook; + h(3); + if ( h(3) ) + print "hmm"; + print "done"; + } +@TEST-END-FILE From 95ffb1cf27a3833c723ff4193b87271139d63ee7 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 30 Nov 2012 17:44:36 -0600 Subject: [PATCH 11/29] Quick pass over unit tests, adding -b flag to bro so they run faster. Doing this made bifs/ ~3x faster and language/ ~2x faster. --- testing/btest/Baseline/bifs.strptime/.stdout | 2 -- testing/btest/Baseline/bifs.strptime/out | 3 +++ testing/btest/Baseline/bifs.strptime/reporter.log | 10 ---------- testing/btest/bifs/addr_count_conversion.bro | 2 +- testing/btest/bifs/addr_to_ptr_name.bro | 2 +- testing/btest/bifs/addr_version.bro | 2 +- testing/btest/bifs/all_set.bro | 2 +- testing/btest/bifs/analyzer_name.bro | 2 +- testing/btest/bifs/any_set.bro | 2 +- testing/btest/bifs/bro_version.bro | 2 +- testing/btest/bifs/byte_len.bro | 2 +- testing/btest/bifs/bytestring_to_double.bro | 2 +- testing/btest/bifs/bytestring_to_hexstr.bro | 2 +- testing/btest/bifs/capture_state_updates.bro | 2 +- testing/btest/bifs/cat.bro | 2 +- testing/btest/bifs/cat_string_array.bro | 2 +- testing/btest/bifs/checkpoint_state.bro | 2 +- testing/btest/bifs/clear_table.bro | 2 +- testing/btest/bifs/convert_for_pattern.bro | 2 +- testing/btest/bifs/count_to_addr.bro | 2 +- testing/btest/bifs/create_file.bro | 2 +- testing/btest/bifs/current_analyzer.bro | 2 +- testing/btest/bifs/current_time.bro | 2 +- testing/btest/bifs/edit.bro | 2 +- testing/btest/bifs/enable_raw_output.test | 2 +- testing/btest/bifs/entropy_test.bro | 2 +- testing/btest/bifs/escape_string.bro | 2 +- testing/btest/bifs/exit.bro | 2 +- testing/btest/bifs/file_mode.bro | 2 +- testing/btest/bifs/find_all.bro | 2 +- testing/btest/bifs/find_entropy.bro | 2 +- testing/btest/bifs/find_last.bro | 2 +- testing/btest/bifs/fmt.bro | 2 +- testing/btest/bifs/fmt_ftp_port.bro | 2 +- testing/btest/bifs/get_matcher_stats.bro | 11 ++++++++++- testing/btest/bifs/get_port_transport_proto.bro | 2 +- testing/btest/bifs/gethostname.bro | 2 +- testing/btest/bifs/getpid.bro | 2 +- testing/btest/bifs/getsetenv.bro | 2 +- testing/btest/bifs/global_ids.bro | 2 +- testing/btest/bifs/global_sizes.bro | 2 +- testing/btest/bifs/hexdump.bro | 2 +- testing/btest/bifs/identify_data.bro | 2 +- testing/btest/bifs/is_ascii.bro | 2 +- testing/btest/bifs/is_local_interface.bro | 2 +- testing/btest/bifs/is_port.bro | 2 +- testing/btest/bifs/join_string.bro | 2 +- testing/btest/bifs/length.bro | 2 +- testing/btest/bifs/lookup_ID.bro | 2 +- testing/btest/bifs/lowerupper.bro | 2 +- testing/btest/bifs/mask_addr.bro | 2 +- testing/btest/bifs/math.bro | 2 +- testing/btest/bifs/merge_pattern.bro | 2 +- testing/btest/bifs/netbios-functions.bro | 2 +- testing/btest/bifs/order.bro | 2 +- testing/btest/bifs/parse_ftp.bro | 2 +- testing/btest/bifs/piped_exec.bro | 2 +- testing/btest/bifs/ptr_name_to_addr.bro | 2 +- testing/btest/bifs/raw_bytes_to_v4_addr.bro | 2 +- testing/btest/bifs/reading_traces.bro | 2 +- testing/btest/bifs/record_type_to_vector.bro | 2 +- testing/btest/bifs/records_fields.bro | 2 +- testing/btest/bifs/remask_addr.bro | 2 +- testing/btest/bifs/resize.bro | 2 +- testing/btest/bifs/resource_usage.bro | 2 +- testing/btest/bifs/rotate_file.bro | 2 +- testing/btest/bifs/rotate_file_by_name.bro | 2 +- testing/btest/bifs/same_object.bro | 2 +- testing/btest/bifs/sort.bro | 2 +- testing/btest/bifs/sort_string_array.bro | 2 +- testing/btest/bifs/split.bro | 2 +- testing/btest/bifs/str_shell_escape.bro | 2 +- testing/btest/bifs/strcmp.bro | 2 +- testing/btest/bifs/strftime.bro | 2 +- testing/btest/bifs/string_fill.bro | 2 +- testing/btest/bifs/string_to_pattern.bro | 2 +- testing/btest/bifs/strip.bro | 2 +- testing/btest/bifs/strptime.bro | 7 +++---- testing/btest/bifs/strstr.bro | 2 +- testing/btest/bifs/sub.bro | 2 +- testing/btest/bifs/subst_string.bro | 2 +- testing/btest/bifs/system.bro | 2 +- testing/btest/bifs/system_env.bro | 2 +- testing/btest/bifs/to_count.bro | 2 +- testing/btest/bifs/to_double.bro | 2 +- testing/btest/bifs/to_int.bro | 2 +- testing/btest/bifs/to_interval.bro | 2 +- testing/btest/bifs/to_port.bro | 2 +- testing/btest/bifs/to_time.bro | 2 +- testing/btest/bifs/type_name.bro | 2 +- testing/btest/bifs/unique_id-rnd.bro | 4 ++-- testing/btest/bifs/unique_id.bro | 2 +- testing/btest/bifs/uuid_to_string.bro | 2 +- testing/btest/bifs/val_size.bro | 2 +- testing/btest/core/discarder.bro | 8 ++++---- testing/btest/core/ipv6_esp.test | 2 +- testing/btest/core/ipv6_zero_len_ah.test | 2 +- testing/btest/core/load-duplicates.bro | 10 +++++----- testing/btest/core/load-pkg.bro | 2 +- testing/btest/core/load-relative.bro | 2 +- testing/btest/core/load-unload.bro | 2 +- testing/btest/language/any.bro | 2 +- testing/btest/language/at-if.bro | 2 +- testing/btest/language/at-ifdef.bro | 2 +- testing/btest/language/at-ifndef.bro | 2 +- testing/btest/language/at-load.bro | 2 +- testing/btest/language/bool.bro | 2 +- testing/btest/language/conditional-expression.bro | 2 +- testing/btest/language/copy.bro | 2 +- testing/btest/language/count.bro | 2 +- testing/btest/language/cross-product-init.bro | 2 +- testing/btest/language/delete-field-set.bro | 2 +- testing/btest/language/delete-field.bro | 2 +- testing/btest/language/double.bro | 2 +- testing/btest/language/enum-scope.bro | 2 +- testing/btest/language/enum.bro | 2 +- testing/btest/language/event.bro | 2 +- testing/btest/language/file.bro | 2 +- testing/btest/language/for.bro | 2 +- testing/btest/language/function.bro | 2 +- testing/btest/language/if.bro | 2 +- testing/btest/language/int.bro | 2 +- testing/btest/language/interval.bro | 2 +- testing/btest/language/module.bro | 2 +- testing/btest/language/next-test.bro | 2 +- testing/btest/language/no-module.bro | 2 +- testing/btest/language/null-statement.bro | 2 +- testing/btest/language/pattern.bro | 2 +- testing/btest/language/port.bro | 2 +- testing/btest/language/precedence.bro | 2 +- testing/btest/language/raw_output_attr.test | 2 +- testing/btest/language/rec-comp-init.bro | 2 +- testing/btest/language/rec-nested-opt.bro | 2 +- testing/btest/language/rec-of-tbl.bro | 2 +- testing/btest/language/rec-table-default.bro | 2 +- testing/btest/language/record-extension.bro | 2 +- testing/btest/language/record-recursive-coercion.bro | 2 +- testing/btest/language/record-ref-assign.bro | 2 +- testing/btest/language/set-opt-record-index.bro | 2 +- testing/btest/language/set.bro | 2 +- testing/btest/language/short-circuit.bro | 2 +- testing/btest/language/sizeof.bro | 2 +- testing/btest/language/smith-waterman-test.bro | 2 +- testing/btest/language/string.bro | 2 +- testing/btest/language/strings.bro | 2 +- testing/btest/language/table-init.bro | 2 +- testing/btest/language/time.bro | 2 +- testing/btest/language/timeout.bro | 2 +- testing/btest/language/vector-coerce-expr.bro | 2 +- testing/btest/language/vector-list-init-records.bro | 2 +- testing/btest/language/vector.bro | 2 +- testing/btest/language/wrong-delete-field.bro | 2 +- testing/btest/language/wrong-record-extension.bro | 2 +- 153 files changed, 172 insertions(+), 173 deletions(-) delete mode 100644 testing/btest/Baseline/bifs.strptime/.stdout create mode 100644 testing/btest/Baseline/bifs.strptime/out delete mode 100644 testing/btest/Baseline/bifs.strptime/reporter.log diff --git a/testing/btest/Baseline/bifs.strptime/.stdout b/testing/btest/Baseline/bifs.strptime/.stdout deleted file mode 100644 index 179612d4c4..0000000000 --- a/testing/btest/Baseline/bifs.strptime/.stdout +++ /dev/null @@ -1,2 +0,0 @@ -1350604800.0 -0.0 diff --git a/testing/btest/Baseline/bifs.strptime/out b/testing/btest/Baseline/bifs.strptime/out new file mode 100644 index 0000000000..5fad7cd8e6 --- /dev/null +++ b/testing/btest/Baseline/bifs.strptime/out @@ -0,0 +1,3 @@ +warning: strptime conversion failed: fmt:%m d:1980-10-24 +1350604800.0 +0.0 diff --git a/testing/btest/Baseline/bifs.strptime/reporter.log b/testing/btest/Baseline/bifs.strptime/reporter.log deleted file mode 100644 index 367dbd63c1..0000000000 --- a/testing/btest/Baseline/bifs.strptime/reporter.log +++ /dev/null @@ -1,10 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path reporter -#open 2012-10-19-06-06-36 -#fields ts level message location -#types time enum string string -0.000000 Reporter::WARNING strptime conversion failed: fmt:%m d:1980-10-24 (empty) -#close 2012-10-19-06-06-36 diff --git a/testing/btest/bifs/addr_count_conversion.bro b/testing/btest/bifs/addr_count_conversion.bro index 360994a8e5..fb87a0c6a3 100644 --- a/testing/btest/bifs/addr_count_conversion.bro +++ b/testing/btest/bifs/addr_count_conversion.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global v: index_vec; diff --git a/testing/btest/bifs/addr_to_ptr_name.bro b/testing/btest/bifs/addr_to_ptr_name.bro index b9c831d061..ac2391cf9b 100644 --- a/testing/btest/bifs/addr_to_ptr_name.bro +++ b/testing/btest/bifs/addr_to_ptr_name.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output print addr_to_ptr_name([2607:f8b0:4009:802::1012]); diff --git a/testing/btest/bifs/addr_version.bro b/testing/btest/bifs/addr_version.bro index 3e0123ef42..bf96c0d1f3 100644 --- a/testing/btest/bifs/addr_version.bro +++ b/testing/btest/bifs/addr_version.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out print is_v4_addr(1.2.3.4); diff --git a/testing/btest/bifs/all_set.bro b/testing/btest/bifs/all_set.bro index 31544eb31e..67ae36622b 100644 --- a/testing/btest/bifs/all_set.bro +++ b/testing/btest/bifs/all_set.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/analyzer_name.bro b/testing/btest/bifs/analyzer_name.bro index 034344f5c4..9297d2ca27 100644 --- a/testing/btest/bifs/analyzer_name.bro +++ b/testing/btest/bifs/analyzer_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/any_set.bro b/testing/btest/bifs/any_set.bro index 5fe046cdf4..9f3f364556 100644 --- a/testing/btest/bifs/any_set.bro +++ b/testing/btest/bifs/any_set.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bro_version.bro b/testing/btest/bifs/bro_version.bro index 7465cbc0f5..35975559a5 100644 --- a/testing/btest/bifs/bro_version.bro +++ b/testing/btest/bifs/bro_version.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/byte_len.bro b/testing/btest/bifs/byte_len.bro index 25191fd173..bd15b0c390 100644 --- a/testing/btest/bifs/byte_len.bro +++ b/testing/btest/bifs/byte_len.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bytestring_to_double.bro b/testing/btest/bifs/bytestring_to_double.bro index cc0a3a69f0..78820b207c 100644 --- a/testing/btest/bifs/bytestring_to_double.bro +++ b/testing/btest/bifs/bytestring_to_double.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bytestring_to_hexstr.bro b/testing/btest/bifs/bytestring_to_hexstr.bro index 976a4ccf71..4087047f40 100644 --- a/testing/btest/bifs/bytestring_to_hexstr.bro +++ b/testing/btest/bifs/bytestring_to_hexstr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/capture_state_updates.bro b/testing/btest/bifs/capture_state_updates.bro index 3abfdffdc1..6a44e0f86f 100644 --- a/testing/btest/bifs/capture_state_updates.bro +++ b/testing/btest/bifs/capture_state_updates.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # @TEST-EXEC: test -f testfile diff --git a/testing/btest/bifs/cat.bro b/testing/btest/bifs/cat.bro index b85b3af550..e923d5d066 100644 --- a/testing/btest/bifs/cat.bro +++ b/testing/btest/bifs/cat.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/cat_string_array.bro b/testing/btest/bifs/cat_string_array.bro index d2c2242411..e799f4b282 100644 --- a/testing/btest/bifs/cat_string_array.bro +++ b/testing/btest/bifs/cat_string_array.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/checkpoint_state.bro b/testing/btest/bifs/checkpoint_state.bro index 2a66bd1729..7a46516ba0 100644 --- a/testing/btest/bifs/checkpoint_state.bro +++ b/testing/btest/bifs/checkpoint_state.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: test -f .state/state.bst event bro_init() diff --git a/testing/btest/bifs/clear_table.bro b/testing/btest/bifs/clear_table.bro index 94779285af..9485eba1f5 100644 --- a/testing/btest/bifs/clear_table.bro +++ b/testing/btest/bifs/clear_table.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT > out +# @TEST-EXEC: bro -b %INPUT > out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/convert_for_pattern.bro b/testing/btest/bifs/convert_for_pattern.bro index 11533cd49b..b99b010f97 100644 --- a/testing/btest/bifs/convert_for_pattern.bro +++ b/testing/btest/bifs/convert_for_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/count_to_addr.bro b/testing/btest/bifs/count_to_addr.bro index ffb2d975bf..993a701bc8 100644 --- a/testing/btest/bifs/count_to_addr.bro +++ b/testing/btest/bifs/count_to_addr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/create_file.bro b/testing/btest/bifs/create_file.bro index 8f3d6cfdcd..af2cfb4979 100644 --- a/testing/btest/bifs/create_file.bro +++ b/testing/btest/bifs/create_file.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff testfile # @TEST-EXEC: btest-diff testfile2 diff --git a/testing/btest/bifs/current_analyzer.bro b/testing/btest/bifs/current_analyzer.bro index 45b495c046..e221d7aed0 100644 --- a/testing/btest/bifs/current_analyzer.bro +++ b/testing/btest/bifs/current_analyzer.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/current_time.bro b/testing/btest/bifs/current_time.bro index 5d16df396d..9d4899aa06 100644 --- a/testing/btest/bifs/current_time.bro +++ b/testing/btest/bifs/current_time.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/edit.bro b/testing/btest/bifs/edit.bro index c9a73d17f1..346c0bdbf7 100644 --- a/testing/btest/bifs/edit.bro +++ b/testing/btest/bifs/edit.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/enable_raw_output.test b/testing/btest/bifs/enable_raw_output.test index 92e0037a04..ebaff36c8f 100644 --- a/testing/btest/bifs/enable_raw_output.test +++ b/testing/btest/bifs/enable_raw_output.test @@ -1,7 +1,7 @@ # Files which enable raw output via the BiF shouldn't interpret NUL characters # in strings that are `print`ed to it. -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: tr '\000' 'X' output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cmp myfile hookfile diff --git a/testing/btest/bifs/entropy_test.bro b/testing/btest/bifs/entropy_test.bro index ca01c79ed7..8dc54e09b2 100644 --- a/testing/btest/bifs/entropy_test.bro +++ b/testing/btest/bifs/entropy_test.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/escape_string.bro b/testing/btest/bifs/escape_string.bro index 92b7b535d8..fd796497be 100644 --- a/testing/btest/bifs/escape_string.bro +++ b/testing/btest/bifs/escape_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/exit.bro b/testing/btest/bifs/exit.bro index e551144caa..b942a5e81c 100644 --- a/testing/btest/bifs/exit.bro +++ b/testing/btest/bifs/exit.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out || test $? -eq 7 +# @TEST-EXEC: bro -b %INPUT >out || test $? -eq 7 # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/file_mode.bro b/testing/btest/bifs/file_mode.bro index c63a2fa188..62bee05c6c 100644 --- a/testing/btest/bifs/file_mode.bro +++ b/testing/btest/bifs/file_mode.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_all.bro b/testing/btest/bifs/find_all.bro index edf3530c8a..4fe451a9d4 100644 --- a/testing/btest/bifs/find_all.bro +++ b/testing/btest/bifs/find_all.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_entropy.bro b/testing/btest/bifs/find_entropy.bro index 24f1c0ed84..2eb24fe118 100644 --- a/testing/btest/bifs/find_entropy.bro +++ b/testing/btest/bifs/find_entropy.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_last.bro b/testing/btest/bifs/find_last.bro index b1a567f73a..00ae2a874d 100644 --- a/testing/btest/bifs/find_last.bro +++ b/testing/btest/bifs/find_last.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/fmt.bro b/testing/btest/bifs/fmt.bro index 53b5f2235d..93607c2740 100644 --- a/testing/btest/bifs/fmt.bro +++ b/testing/btest/bifs/fmt.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type color: enum { Red, Blue }; diff --git a/testing/btest/bifs/fmt_ftp_port.bro b/testing/btest/bifs/fmt_ftp_port.bro index 09ec5369e2..6a7b4d20c7 100644 --- a/testing/btest/bifs/fmt_ftp_port.bro +++ b/testing/btest/bifs/fmt_ftp_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/get_matcher_stats.bro b/testing/btest/bifs/get_matcher_stats.bro index baee49fe1e..eeaa8cb86a 100644 --- a/testing/btest/bifs/get_matcher_stats.bro +++ b/testing/btest/bifs/get_matcher_stats.bro @@ -1,5 +1,14 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b -s mysig %INPUT + +@TEST-START-FILE mysig.sig +signature my_ftp_client { + ip-proto == tcp + payload /(|.*[\n\r]) *[uU][sS][eE][rR] / + tcp-state originator + event "matched my_ftp_client" +} +@TEST-END-FILE event bro_init() { diff --git a/testing/btest/bifs/get_port_transport_proto.bro b/testing/btest/bifs/get_port_transport_proto.bro index c9b5e626ec..ae3c496d88 100644 --- a/testing/btest/bifs/get_port_transport_proto.bro +++ b/testing/btest/bifs/get_port_transport_proto.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/gethostname.bro b/testing/btest/bifs/gethostname.bro index 97af719745..1d760525cb 100644 --- a/testing/btest/bifs/gethostname.bro +++ b/testing/btest/bifs/gethostname.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/getpid.bro b/testing/btest/bifs/getpid.bro index 98edc19a44..1852b1287e 100644 --- a/testing/btest/bifs/getpid.bro +++ b/testing/btest/bifs/getpid.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/getsetenv.bro b/testing/btest/bifs/getsetenv.bro index b4ee9a0931..d217a14ea9 100644 --- a/testing/btest/bifs/getsetenv.bro +++ b/testing/btest/bifs/getsetenv.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: TESTBRO=testvalue bro %INPUT >out +# @TEST-EXEC: TESTBRO=testvalue bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/global_ids.bro b/testing/btest/bifs/global_ids.bro index 65f8944ed4..2dcb6e844d 100644 --- a/testing/btest/bifs/global_ids.bro +++ b/testing/btest/bifs/global_ids.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/global_sizes.bro b/testing/btest/bifs/global_sizes.bro index 4862db318b..4b0805172c 100644 --- a/testing/btest/bifs/global_sizes.bro +++ b/testing/btest/bifs/global_sizes.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/hexdump.bro b/testing/btest/bifs/hexdump.bro index 4c248efb77..1c86ce0db8 100644 --- a/testing/btest/bifs/hexdump.bro +++ b/testing/btest/bifs/hexdump.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/identify_data.bro b/testing/btest/bifs/identify_data.bro index 39f289d40b..68cac55c61 100644 --- a/testing/btest/bifs/identify_data.bro +++ b/testing/btest/bifs/identify_data.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT | sed 's/PNG image data/PNG image/g' >out +# @TEST-EXEC: bro -b %INPUT | sed 's/PNG image data/PNG image/g' >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_ascii.bro b/testing/btest/bifs/is_ascii.bro index 4d1daf96b4..fa2d39d2d8 100644 --- a/testing/btest/bifs/is_ascii.bro +++ b/testing/btest/bifs/is_ascii.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_local_interface.bro b/testing/btest/bifs/is_local_interface.bro index 8befdca385..ac21b04bd3 100644 --- a/testing/btest/bifs/is_local_interface.bro +++ b/testing/btest/bifs/is_local_interface.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_port.bro b/testing/btest/bifs/is_port.bro index fe2c3f7c35..2fe4964913 100644 --- a/testing/btest/bifs/is_port.bro +++ b/testing/btest/bifs/is_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/join_string.bro b/testing/btest/bifs/join_string.bro index 16222d6303..83917ef322 100644 --- a/testing/btest/bifs/join_string.bro +++ b/testing/btest/bifs/join_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/length.bro b/testing/btest/bifs/length.bro index 335223c124..ca82d7eab7 100644 --- a/testing/btest/bifs/length.bro +++ b/testing/btest/bifs/length.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT > out +# @TEST-EXEC: bro -b %INPUT > out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/lookup_ID.bro b/testing/btest/bifs/lookup_ID.bro index b8a29ef41f..e263c192da 100644 --- a/testing/btest/bifs/lookup_ID.bro +++ b/testing/btest/bifs/lookup_ID.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out global a = "bro test"; diff --git a/testing/btest/bifs/lowerupper.bro b/testing/btest/bifs/lowerupper.bro index fcfdcde319..77e6b1c9d1 100644 --- a/testing/btest/bifs/lowerupper.bro +++ b/testing/btest/bifs/lowerupper.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/mask_addr.bro b/testing/btest/bifs/mask_addr.bro index e1e3bccfb6..e69a55f590 100644 --- a/testing/btest/bifs/mask_addr.bro +++ b/testing/btest/bifs/mask_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; diff --git a/testing/btest/bifs/math.bro b/testing/btest/bifs/math.bro index 90aed5b4e6..84ace8620c 100644 --- a/testing/btest/bifs/math.bro +++ b/testing/btest/bifs/math.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/merge_pattern.bro b/testing/btest/bifs/merge_pattern.bro index b447f9a15b..de4a3afd6a 100644 --- a/testing/btest/bifs/merge_pattern.bro +++ b/testing/btest/bifs/merge_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/netbios-functions.bro b/testing/btest/bifs/netbios-functions.bro index 1fd033dd59..9b075e8729 100644 --- a/testing/btest/bifs/netbios-functions.bro +++ b/testing/btest/bifs/netbios-functions.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/order.bro b/testing/btest/bifs/order.bro index 333a8acac1..9e59caa827 100644 --- a/testing/btest/bifs/order.bro +++ b/testing/btest/bifs/order.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function myfunc1(a: addr, b: addr): int diff --git a/testing/btest/bifs/parse_ftp.bro b/testing/btest/bifs/parse_ftp.bro index ffdc941b4b..a8993fa6e0 100644 --- a/testing/btest/bifs/parse_ftp.bro +++ b/testing/btest/bifs/parse_ftp.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/piped_exec.bro b/testing/btest/bifs/piped_exec.bro index 3a76eba8f5..70f8d70523 100644 --- a/testing/btest/bifs/piped_exec.bro +++ b/testing/btest/bifs/piped_exec.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output # @TEST-EXEC: btest-diff test.txt diff --git a/testing/btest/bifs/ptr_name_to_addr.bro b/testing/btest/bifs/ptr_name_to_addr.bro index 89679ba57a..d1a7878e3d 100644 --- a/testing/btest/bifs/ptr_name_to_addr.bro +++ b/testing/btest/bifs/ptr_name_to_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global v6 = ptr_name_to_addr("2.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.2.0.8.0.9.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa"); diff --git a/testing/btest/bifs/raw_bytes_to_v4_addr.bro b/testing/btest/bifs/raw_bytes_to_v4_addr.bro index 754580a5b0..bd685216ef 100644 --- a/testing/btest/bifs/raw_bytes_to_v4_addr.bro +++ b/testing/btest/bifs/raw_bytes_to_v4_addr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/reading_traces.bro b/testing/btest/bifs/reading_traces.bro index fc83c50ccb..46ad04c25f 100644 --- a/testing/btest/bifs/reading_traces.bro +++ b/testing/btest/bifs/reading_traces.bro @@ -1,5 +1,5 @@ -# @TEST-EXEC: bro %INPUT >out1 +# @TEST-EXEC: bro -b %INPUT >out1 # @TEST-EXEC: btest-diff out1 # @TEST-EXEC: bro -r $TRACES/web.trace %INPUT >out2 # @TEST-EXEC: btest-diff out2 diff --git a/testing/btest/bifs/record_type_to_vector.bro b/testing/btest/bifs/record_type_to_vector.bro index 18ddf35022..9795ce886b 100644 --- a/testing/btest/bifs/record_type_to_vector.bro +++ b/testing/btest/bifs/record_type_to_vector.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type myrecord: record { diff --git a/testing/btest/bifs/records_fields.bro b/testing/btest/bifs/records_fields.bro index 4f8cc0538a..ccaf5a719d 100644 --- a/testing/btest/bifs/records_fields.bro +++ b/testing/btest/bifs/records_fields.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type r: record { diff --git a/testing/btest/bifs/remask_addr.bro b/testing/btest/bifs/remask_addr.bro index d387667b6a..7b7e89c018 100644 --- a/testing/btest/bifs/remask_addr.bro +++ b/testing/btest/bifs/remask_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; diff --git a/testing/btest/bifs/resize.bro b/testing/btest/bifs/resize.bro index 37e4ac38d9..f4067f31c7 100644 --- a/testing/btest/bifs/resize.bro +++ b/testing/btest/bifs/resize.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/resource_usage.bro b/testing/btest/bifs/resource_usage.bro index 35f5b020d6..5cf3f0f962 100644 --- a/testing/btest/bifs/resource_usage.bro +++ b/testing/btest/bifs/resource_usage.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/rotate_file.bro b/testing/btest/bifs/rotate_file.bro index 7132b0aaa8..a6109ff677 100644 --- a/testing/btest/bifs/rotate_file.bro +++ b/testing/btest/bifs/rotate_file.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/rotate_file_by_name.bro b/testing/btest/bifs/rotate_file_by_name.bro index 952b09aff3..f647edefe2 100644 --- a/testing/btest/bifs/rotate_file_by_name.bro +++ b/testing/btest/bifs/rotate_file_by_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/same_object.bro b/testing/btest/bifs/same_object.bro index eee8b1621d..dddfd80d3d 100644 --- a/testing/btest/bifs/same_object.bro +++ b/testing/btest/bifs/same_object.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/sort.bro b/testing/btest/bifs/sort.bro index 14aa286021..7b4ac9ba63 100644 --- a/testing/btest/bifs/sort.bro +++ b/testing/btest/bifs/sort.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function myfunc1(a: addr, b: addr): int diff --git a/testing/btest/bifs/sort_string_array.bro b/testing/btest/bifs/sort_string_array.bro index 23c4f55848..1916f93d0c 100644 --- a/testing/btest/bifs/sort_string_array.bro +++ b/testing/btest/bifs/sort_string_array.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/split.bro b/testing/btest/bifs/split.bro index fc1b5e96a0..4fd994ce41 100644 --- a/testing/btest/bifs/split.bro +++ b/testing/btest/bifs/split.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/str_shell_escape.bro b/testing/btest/bifs/str_shell_escape.bro index a71cb4dcf6..e631458bc1 100644 --- a/testing/btest/bifs/str_shell_escape.bro +++ b/testing/btest/bifs/str_shell_escape.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strcmp.bro b/testing/btest/bifs/strcmp.bro index af46c7fa96..92d0430f1d 100644 --- a/testing/btest/bifs/strcmp.bro +++ b/testing/btest/bifs/strcmp.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strftime.bro b/testing/btest/bifs/strftime.bro index 31f9538632..3d9e388c90 100644 --- a/testing/btest/bifs/strftime.bro +++ b/testing/btest/bifs/strftime.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/string_fill.bro b/testing/btest/bifs/string_fill.bro index c47f1916cc..0968215cc0 100644 --- a/testing/btest/bifs/string_fill.bro +++ b/testing/btest/bifs/string_fill.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/string_to_pattern.bro b/testing/btest/bifs/string_to_pattern.bro index 5164c4576f..4bd04bbcea 100644 --- a/testing/btest/bifs/string_to_pattern.bro +++ b/testing/btest/bifs/string_to_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strip.bro b/testing/btest/bifs/strip.bro index de6601b83c..e508f20e3d 100644 --- a/testing/btest/bifs/strip.bro +++ b/testing/btest/bifs/strip.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strptime.bro b/testing/btest/bifs/strptime.bro index 7a58989679..215299b300 100644 --- a/testing/btest/bifs/strptime.bro +++ b/testing/btest/bifs/strptime.bro @@ -1,10 +1,9 @@ # -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout -# @TEST-EXEC: btest-diff reporter.log +# @TEST-EXEC: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: btest-diff out event bro_init() { print strptime("%Y-%m-%d", "2012-10-19"); print strptime("%m", "1980-10-24"); - } \ No newline at end of file + } diff --git a/testing/btest/bifs/strstr.bro b/testing/btest/bifs/strstr.bro index 58f79d593b..40cd8aa5fd 100644 --- a/testing/btest/bifs/strstr.bro +++ b/testing/btest/bifs/strstr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/sub.bro b/testing/btest/bifs/sub.bro index f6a956f26a..773530ac74 100644 --- a/testing/btest/bifs/sub.bro +++ b/testing/btest/bifs/sub.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/subst_string.bro b/testing/btest/bifs/subst_string.bro index 81a3f89424..6ebed72321 100644 --- a/testing/btest/bifs/subst_string.bro +++ b/testing/btest/bifs/subst_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/system.bro b/testing/btest/bifs/system.bro index ab2642319c..bd27fc3db5 100644 --- a/testing/btest/bifs/system.bro +++ b/testing/btest/bifs/system.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/system_env.bro b/testing/btest/bifs/system_env.bro index 23928e9b10..cfe4e7dd2a 100644 --- a/testing/btest/bifs/system_env.bro +++ b/testing/btest/bifs/system_env.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff testfile event bro_init() diff --git a/testing/btest/bifs/to_count.bro b/testing/btest/bifs/to_count.bro index c1fe72ce52..33754117d4 100644 --- a/testing/btest/bifs/to_count.bro +++ b/testing/btest/bifs/to_count.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_double.bro b/testing/btest/bifs/to_double.bro index f13d34f69a..b6fb9917a7 100644 --- a/testing/btest/bifs/to_double.bro +++ b/testing/btest/bifs/to_double.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_int.bro b/testing/btest/bifs/to_int.bro index 9d108a9da7..0562209cd0 100644 --- a/testing/btest/bifs/to_int.bro +++ b/testing/btest/bifs/to_int.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_interval.bro b/testing/btest/bifs/to_interval.bro index 8fded315d2..71d73fed62 100644 --- a/testing/btest/bifs/to_interval.bro +++ b/testing/btest/bifs/to_interval.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_port.bro b/testing/btest/bifs/to_port.bro index 382bf5d333..0dfecac43e 100644 --- a/testing/btest/bifs/to_port.bro +++ b/testing/btest/bifs/to_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_time.bro b/testing/btest/bifs/to_time.bro index 97b109e647..d5a81b0934 100644 --- a/testing/btest/bifs/to_time.bro +++ b/testing/btest/bifs/to_time.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/type_name.bro b/testing/btest/bifs/type_name.bro index 3ec13fb27d..f331fe6aa9 100644 --- a/testing/btest/bifs/type_name.bro +++ b/testing/btest/bifs/type_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type color: enum { Red, Blue }; diff --git a/testing/btest/bifs/unique_id-rnd.bro b/testing/btest/bifs/unique_id-rnd.bro index 4188725373..02be9fcb92 100644 --- a/testing/btest/bifs/unique_id-rnd.bro +++ b/testing/btest/bifs/unique_id-rnd.bro @@ -1,6 +1,6 @@ # -# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT >out -# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT >>out +# @TEST-EXEC: BRO_SEED_FILE= bro -b %INPUT >out +# @TEST-EXEC: BRO_SEED_FILE= bro -b %INPUT >>out # @TEST-EXEC: cat out | sort | uniq | wc -l | sed 's/ //g' >count # @TEST-EXEC: btest-diff count diff --git a/testing/btest/bifs/unique_id.bro b/testing/btest/bifs/unique_id.bro index 097f5d490d..d87c757f3f 100644 --- a/testing/btest/bifs/unique_id.bro +++ b/testing/btest/bifs/unique_id.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out print unique_id("A-"); diff --git a/testing/btest/bifs/uuid_to_string.bro b/testing/btest/bifs/uuid_to_string.bro index a64e81d783..dc84f349fa 100644 --- a/testing/btest/bifs/uuid_to_string.bro +++ b/testing/btest/bifs/uuid_to_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/val_size.bro b/testing/btest/bifs/val_size.bro index 5b2e535c5c..57b512b776 100644 --- a/testing/btest/bifs/val_size.bro +++ b/testing/btest/bifs/val_size.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/core/discarder.bro b/testing/btest/core/discarder.bro index 0c87eece18..9e8f5e7a2f 100644 --- a/testing/btest/core/discarder.bro +++ b/testing/btest/core/discarder.bro @@ -1,7 +1,7 @@ -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-ip.bro >output -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output -# @TEST-EXEC: bro -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-ip.bro >output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output +# @TEST-EXEC: bro -b -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/ipv6_esp.test b/testing/btest/core/ipv6_esp.test index 8744df0036..508a4597f2 100644 --- a/testing/btest/core/ipv6_esp.test +++ b/testing/btest/core/ipv6_esp.test @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro -r $TRACES/ip6_esp.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/ip6_esp.trace %INPUT >output # @TEST-EXEC: btest-diff output # Just check that the event is raised correctly for a packet containing diff --git a/testing/btest/core/ipv6_zero_len_ah.test b/testing/btest/core/ipv6_zero_len_ah.test index dc3acf8443..014ba7b3cc 100644 --- a/testing/btest/core/ipv6_zero_len_ah.test +++ b/testing/btest/core/ipv6_zero_len_ah.test @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro -r $TRACES/ipv6_zero_len_ah.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/ipv6_zero_len_ah.trace %INPUT >output # @TEST-EXEC: btest-diff output # Shouldn't crash, but we also won't have seq and data fields set of the ip6_ah diff --git a/testing/btest/core/load-duplicates.bro b/testing/btest/core/load-duplicates.bro index e5dd365838..8c86fbc272 100644 --- a/testing/btest/core/load-duplicates.bro +++ b/testing/btest/core/load-duplicates.bro @@ -3,11 +3,11 @@ # @TEST-EXEC: mkdir -p foo/bar # @TEST-EXEC: echo "@load bar/test" >loader.bro # @TEST-EXEC: cp %INPUT foo/bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader bar/test -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader foo/bar/test -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader foo/bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader `pwd`/foo/bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader bar/test +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader foo/bar/test +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader foo/bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader `pwd`/foo/bar/test.bro type Test: enum { TEST, diff --git a/testing/btest/core/load-pkg.bro b/testing/btest/core/load-pkg.bro index 26e190a14c..e6671e038d 100644 --- a/testing/btest/core/load-pkg.bro +++ b/testing/btest/core/load-pkg.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro foo >output +# @TEST-EXEC: bro -b foo >output # @TEST-EXEC: btest-diff output @TEST-START-FILE foo/__load__.bro diff --git a/testing/btest/core/load-relative.bro b/testing/btest/core/load-relative.bro index 4050150d93..3bd082cf8a 100644 --- a/testing/btest/core/load-relative.bro +++ b/testing/btest/core/load-relative.bro @@ -1,6 +1,6 @@ # A test of relative-path-based @load'ing -# @TEST-EXEC: bro foo/foo >output +# @TEST-EXEC: bro -b foo/foo >output # @TEST-EXEC: btest-diff output @TEST-START-FILE foo/foo.bro diff --git a/testing/btest/core/load-unload.bro b/testing/btest/core/load-unload.bro index f76e9e337d..6525a8e8ea 100644 --- a/testing/btest/core/load-unload.bro +++ b/testing/btest/core/load-unload.bro @@ -1,6 +1,6 @@ # This tests the @unload directive # -# @TEST-EXEC: bro %INPUT misc/loaded-scripts dontloadmebro > output +# @TEST-EXEC: bro -b %INPUT misc/loaded-scripts dontloadmebro > output # @TEST-EXEC: btest-diff output # @TEST-EXEC: grep -q dontloadmebro loaded_scripts.log && exit 1 || exit 0 diff --git a/testing/btest/language/any.bro b/testing/btest/language/any.bro index 7437ee9851..fca23f6db8 100644 --- a/testing/btest/language/any.bro +++ b/testing/btest/language/any.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-if.bro b/testing/btest/language/at-if.bro index 979ed0bb9a..0a3e87adfa 100644 --- a/testing/btest/language/at-if.bro +++ b/testing/btest/language/at-if.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-ifdef.bro b/testing/btest/language/at-ifdef.bro index c30236f204..e7bb961833 100644 --- a/testing/btest/language/at-ifdef.bro +++ b/testing/btest/language/at-ifdef.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-ifndef.bro b/testing/btest/language/at-ifndef.bro index c98287590f..8bff0c456b 100644 --- a/testing/btest/language/at-ifndef.bro +++ b/testing/btest/language/at-ifndef.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-load.bro b/testing/btest/language/at-load.bro index b51594be16..7427cd639a 100644 --- a/testing/btest/language/at-load.bro +++ b/testing/btest/language/at-load.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # In this script, we try to access each object defined in a "@load"ed script diff --git a/testing/btest/language/bool.bro b/testing/btest/language/bool.bro index b75343025f..8a1404459c 100644 --- a/testing/btest/language/bool.bro +++ b/testing/btest/language/bool.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/conditional-expression.bro b/testing/btest/language/conditional-expression.bro index 74648b6ce8..ea0acf009f 100644 --- a/testing/btest/language/conditional-expression.bro +++ b/testing/btest/language/conditional-expression.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/copy.bro b/testing/btest/language/copy.bro index 6740a080c7..3ddbc15e23 100644 --- a/testing/btest/language/copy.bro +++ b/testing/btest/language/copy.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/count.bro b/testing/btest/language/count.bro index d6dcf5a97e..b0972e29fa 100644 --- a/testing/btest/language/count.bro +++ b/testing/btest/language/count.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/cross-product-init.bro b/testing/btest/language/cross-product-init.bro index c12f9eb0bd..8cb9c48367 100644 --- a/testing/btest/language/cross-product-init.bro +++ b/testing/btest/language/cross-product-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output global my_subs = { 1.2.3.4/19, 5.6.7.8/21 }; diff --git a/testing/btest/language/delete-field-set.bro b/testing/btest/language/delete-field-set.bro index ad7cf6e9fb..1f1c5b0c27 100644 --- a/testing/btest/language/delete-field-set.bro +++ b/testing/btest/language/delete-field-set.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type FooBar: record { diff --git a/testing/btest/language/delete-field.bro b/testing/btest/language/delete-field.bro index 477466b76a..99136ff2b9 100644 --- a/testing/btest/language/delete-field.bro +++ b/testing/btest/language/delete-field.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/double.bro b/testing/btest/language/double.bro index 62ca768e22..f85b216828 100644 --- a/testing/btest/language/double.bro +++ b/testing/btest/language/double.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/enum-scope.bro b/testing/btest/language/enum-scope.bro index c8667bfada..82e7c7fd7c 100644 --- a/testing/btest/language/enum-scope.bro +++ b/testing/btest/language/enum-scope.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type foo: enum { a, b } &redef; diff --git a/testing/btest/language/enum.bro b/testing/btest/language/enum.bro index 5cafb323a6..6de7d345da 100644 --- a/testing/btest/language/enum.bro +++ b/testing/btest/language/enum.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/event.bro b/testing/btest/language/event.bro index 1ea5c7b6d8..e251a3e579 100644 --- a/testing/btest/language/event.bro +++ b/testing/btest/language/event.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/file.bro b/testing/btest/language/file.bro index 1f631eb4fe..47430b6813 100644 --- a/testing/btest/language/file.bro +++ b/testing/btest/language/file.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff out1 # @TEST-EXEC: btest-diff out2 diff --git a/testing/btest/language/for.bro b/testing/btest/language/for.bro index f10ef0eb1b..eb99a2705d 100644 --- a/testing/btest/language/for.bro +++ b/testing/btest/language/for.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/function.bro b/testing/btest/language/function.bro index 13efbb91f8..ab60c4fa62 100644 --- a/testing/btest/language/function.bro +++ b/testing/btest/language/function.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/if.bro b/testing/btest/language/if.bro index e9acea865f..785030a012 100644 --- a/testing/btest/language/if.bro +++ b/testing/btest/language/if.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/int.bro b/testing/btest/language/int.bro index 5cfa1620bd..f511d82bbb 100644 --- a/testing/btest/language/int.bro +++ b/testing/btest/language/int.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/interval.bro b/testing/btest/language/interval.bro index 66d44206d3..660683f5ca 100644 --- a/testing/btest/language/interval.bro +++ b/testing/btest/language/interval.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/module.bro b/testing/btest/language/module.bro index 4c70546406..3278697a8d 100644 --- a/testing/btest/language/module.bro +++ b/testing/btest/language/module.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT secondtestfile >out +# @TEST-EXEC: bro -b %INPUT secondtestfile >out # @TEST-EXEC: btest-diff out # In this source file, we define a module and export some objects diff --git a/testing/btest/language/next-test.bro b/testing/btest/language/next-test.bro index 7e9626a62c..d46ad187c4 100644 --- a/testing/btest/language/next-test.bro +++ b/testing/btest/language/next-test.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # This script tests "next" being called during the last iteration of a diff --git a/testing/btest/language/no-module.bro b/testing/btest/language/no-module.bro index eadce66c18..24795df0fb 100644 --- a/testing/btest/language/no-module.bro +++ b/testing/btest/language/no-module.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT secondtestfile >out +# @TEST-EXEC: bro -b %INPUT secondtestfile >out # @TEST-EXEC: btest-diff out # This is the same test as "module.bro", but here we omit the module definition diff --git a/testing/btest/language/null-statement.bro b/testing/btest/language/null-statement.bro index 420ebd8a6c..20c70f4876 100644 --- a/testing/btest/language/null-statement.bro +++ b/testing/btest/language/null-statement.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/pattern.bro b/testing/btest/language/pattern.bro index ec50dc66fe..b904fe8737 100644 --- a/testing/btest/language/pattern.bro +++ b/testing/btest/language/pattern.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/port.bro b/testing/btest/language/port.bro index 1874e1dca3..a9c7fd33e7 100644 --- a/testing/btest/language/port.bro +++ b/testing/btest/language/port.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/precedence.bro b/testing/btest/language/precedence.bro index da8fef311c..27fc1e024a 100644 --- a/testing/btest/language/precedence.bro +++ b/testing/btest/language/precedence.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/raw_output_attr.test b/testing/btest/language/raw_output_attr.test index 22e565e4b4..8bcd479fbf 100644 --- a/testing/btest/language/raw_output_attr.test +++ b/testing/btest/language/raw_output_attr.test @@ -1,7 +1,7 @@ # Files with the &raw_output attribute shouldn't interpret NUL characters # in strings that are `print`ed to it. -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: tr '\000' 'X' output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cmp myfile hookfile diff --git a/testing/btest/language/rec-comp-init.bro b/testing/btest/language/rec-comp-init.bro index 598c0cf3bd..c65ef69097 100644 --- a/testing/btest/language/rec-comp-init.bro +++ b/testing/btest/language/rec-comp-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Make sure composit types in records are initialized. diff --git a/testing/btest/language/rec-nested-opt.bro b/testing/btest/language/rec-nested-opt.bro index ab1a64dffd..3b4a478f6b 100644 --- a/testing/btest/language/rec-nested-opt.bro +++ b/testing/btest/language/rec-nested-opt.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type Version: record { diff --git a/testing/btest/language/rec-of-tbl.bro b/testing/btest/language/rec-of-tbl.bro index 59d770bb30..8d2c9ab0e0 100644 --- a/testing/btest/language/rec-of-tbl.bro +++ b/testing/btest/language/rec-of-tbl.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type x: record { diff --git a/testing/btest/language/rec-table-default.bro b/testing/btest/language/rec-table-default.bro index ee4a0e25ee..27e0043dc3 100644 --- a/testing/btest/language/rec-table-default.bro +++ b/testing/btest/language/rec-table-default.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/record-extension.bro b/testing/btest/language/record-extension.bro index 21b704ca7a..78ef929a86 100644 --- a/testing/btest/language/record-extension.bro +++ b/testing/btest/language/record-extension.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Foo: record { diff --git a/testing/btest/language/record-recursive-coercion.bro b/testing/btest/language/record-recursive-coercion.bro index ad9e41bd3a..0eb24a70d9 100644 --- a/testing/btest/language/record-recursive-coercion.bro +++ b/testing/btest/language/record-recursive-coercion.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Version: record { diff --git a/testing/btest/language/record-ref-assign.bro b/testing/btest/language/record-ref-assign.bro index f71bc3890c..a9539ab716 100644 --- a/testing/btest/language/record-ref-assign.bro +++ b/testing/btest/language/record-ref-assign.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type State: record { diff --git a/testing/btest/language/set-opt-record-index.bro b/testing/btest/language/set-opt-record-index.bro index 18ec963809..d42de8b041 100644 --- a/testing/btest/language/set-opt-record-index.bro +++ b/testing/btest/language/set-opt-record-index.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Make sure a set can be indexed with a record that has optional fields diff --git a/testing/btest/language/set.bro b/testing/btest/language/set.bro index 5e56e3b9b8..d1eef7e6f0 100644 --- a/testing/btest/language/set.bro +++ b/testing/btest/language/set.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/short-circuit.bro b/testing/btest/language/short-circuit.bro index f0ba585cea..598ac8da35 100644 --- a/testing/btest/language/short-circuit.bro +++ b/testing/btest/language/short-circuit.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/sizeof.bro b/testing/btest/language/sizeof.bro index 99d7b51ce8..8b29e119bd 100644 --- a/testing/btest/language/sizeof.bro +++ b/testing/btest/language/sizeof.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Demo policy for the sizeof operator "|x|". diff --git a/testing/btest/language/smith-waterman-test.bro b/testing/btest/language/smith-waterman-test.bro index 50f5c1dae1..2113d88e24 100644 --- a/testing/btest/language/smith-waterman-test.bro +++ b/testing/btest/language/smith-waterman-test.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output global params: sw_params = [ $min_strlen = 2, $sw_variant = 0 ]; diff --git a/testing/btest/language/string.bro b/testing/btest/language/string.bro index 3b9137cda5..abaa556b26 100644 --- a/testing/btest/language/string.bro +++ b/testing/btest/language/string.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/strings.bro b/testing/btest/language/strings.bro index 8e9eef43bf..f601797978 100644 --- a/testing/btest/language/strings.bro +++ b/testing/btest/language/strings.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Demo policy for string functions diff --git a/testing/btest/language/table-init.bro b/testing/btest/language/table-init.bro index 5df682c5d2..7419a50879 100644 --- a/testing/btest/language/table-init.bro +++ b/testing/btest/language/table-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global global_table: table[count] of string = { diff --git a/testing/btest/language/time.bro b/testing/btest/language/time.bro index 43b6694101..dd4b6336fe 100644 --- a/testing/btest/language/time.bro +++ b/testing/btest/language/time.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/timeout.bro b/testing/btest/language/timeout.bro index 6bc0419b2f..b16ddd6e7c 100644 --- a/testing/btest/language/timeout.bro +++ b/testing/btest/language/timeout.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/vector-coerce-expr.bro b/testing/btest/language/vector-coerce-expr.bro index d58417f226..97f9617665 100644 --- a/testing/btest/language/vector-coerce-expr.bro +++ b/testing/btest/language/vector-coerce-expr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/vector-list-init-records.bro b/testing/btest/language/vector-list-init-records.bro index ee2b78c4a5..b1eee0ac92 100644 --- a/testing/btest/language/vector-list-init-records.bro +++ b/testing/btest/language/vector-list-init-records.bro @@ -1,7 +1,7 @@ # Initializing a vector with a list of records should promote elements as # necessary to match the vector's yield type. -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Foo: record { diff --git a/testing/btest/language/vector.bro b/testing/btest/language/vector.bro index 928ddcb645..76fc8b69e3 100644 --- a/testing/btest/language/vector.bro +++ b/testing/btest/language/vector.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/wrong-delete-field.bro b/testing/btest/language/wrong-delete-field.bro index e0d0093258..63573faf8a 100644 --- a/testing/btest/language/wrong-delete-field.bro +++ b/testing/btest/language/wrong-delete-field.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC-FAIL: bro %INPUT >output 2>&1 +# @TEST-EXEC-FAIL: bro -b %INPUT >output 2>&1 # @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff output type X: record { diff --git a/testing/btest/language/wrong-record-extension.bro b/testing/btest/language/wrong-record-extension.bro index 4e0210546a..a8ef6a64e9 100644 --- a/testing/btest/language/wrong-record-extension.bro +++ b/testing/btest/language/wrong-record-extension.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC-FAIL: bro %INPUT >output.tmp 2>&1 +# @TEST-EXEC-FAIL: bro -b %INPUT >output.tmp 2>&1 # @TEST-EXEC: sed 's#^.*:##g' output # @TEST-EXEC: btest-diff output From e98343b5621bb38debded896a78404f1f7ff3bb3 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Fri, 30 Nov 2012 20:04:10 -0500 Subject: [PATCH 12/29] Remove hardcoded HTTP verbs from the analyzer (#741) --- scripts/base/protocols/http/main.bro | 14 ++++++++++ src/HTTP.cc | 42 ++++++++-------------------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro index 21b4fb6113..ec8a5ffad8 100644 --- a/scripts/base/protocols/http/main.bro +++ b/scripts/base/protocols/http/main.bro @@ -94,6 +94,17 @@ export { "XROXY-CONNECTION", "PROXY-CONNECTION", } &redef; + + ## A list of HTTP methods. Other methods will generate a weird. + const http_methods: set[string] = { + "GET", "POST", "HEAD", "OPTIONS", + "PUT", "DELETE", "TRACE", "CONNECT", + # HTTP methods for distributed authoring: + "PROPFIND", "PROPPATCH", "MKCOL", + "COPY", "MOVE", "LOCK", "UNLOCK", + "POLL", "REPORT", "SUBSCRIBE", "BMOVE", + "SEARCH" + } &redef; ## Event that can be handled to access the HTTP record as it is sent on ## to the logging framework. @@ -180,6 +191,9 @@ event http_request(c: connection, method: string, original_URI: string, c$http$method = method; c$http$uri = unescaped_URI; + + if ( !(method in http_methods) ) + event conn_weird("unknown_HTTP_method", c, method); } event http_reply(c: connection, version: string, code: count, reason: string) &priority=5 diff --git a/src/HTTP.cc b/src/HTTP.cc index 9d9f01be64..0748ca55a7 100644 --- a/src/HTTP.cc +++ b/src/HTTP.cc @@ -1118,36 +1118,18 @@ const char* HTTP_Analyzer::PrefixWordMatch(const char* line, int HTTP_Analyzer::HTTP_RequestLine(const char* line, const char* end_of_line) { - const char* rest = 0; - static const char* http_methods[] = { - "GET", "POST", "HEAD", - - "OPTIONS", "PUT", "DELETE", "TRACE", "CONNECT", - - // HTTP methods for distributed authoring. - "PROPFIND", "PROPPATCH", "MKCOL", "DELETE", "PUT", - "COPY", "MOVE", "LOCK", "UNLOCK", - "POLL", "REPORT", "SUBSCRIBE", "BMOVE", - - "SEARCH", - - 0, - }; - - int i; - for ( i = 0; http_methods[i]; ++i ) - if ( (rest = PrefixWordMatch(line, end_of_line, http_methods[i])) != 0 ) - break; - - if ( ! http_methods[i] ) - { - // Weird("HTTP_unknown_method"); - if ( RequestExpected() ) - HTTP_Event("unknown_HTTP_method", new_string_val(line, end_of_line)); - return 0; - } - - request_method = new StringVal(http_methods[i]); + const char* request_method_str; + int request_method_len; + const char* rest; + get_word(strlen(line), line, request_method_len, request_method_str); + + request_method = new StringVal(request_method_len, request_method_str); + if ( (rest = PrefixWordMatch(line, end_of_line, (const char*) request_method->AsString()->Bytes() )) == 0) + { + // Most likely a DPD failure - this is pretty noisy for me, so leaving commented for now + // reporter->InternalError("HTTP RequestLine failed"); + return 0; + } if ( ! ParseRequest(rest, end_of_line) ) reporter->InternalError("HTTP ParseRequest failed"); From 318f38df4301f58e06ac9f9df153b89eed3a5b73 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Fri, 30 Nov 2012 22:06:54 -0500 Subject: [PATCH 13/29] A test for HTTP methods, including some horribly illegal requests. --- .../http.log | 58 ++++++++++++++++++ .../weird.log | 35 +++++++++++ testing/btest/Traces/http-methods.trace | Bin 0 -> 238829 bytes .../base/protocols/http/http-methods.bro | 9 +++ 4 files changed, 102 insertions(+) create mode 100644 testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log create mode 100644 testing/btest/Traces/http-methods.trace create mode 100644 testing/btest/scripts/base/protocols/http/http-methods.bro diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log new file mode 100644 index 0000000000..68ffd2e63d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log @@ -0,0 +1,58 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2012-12-01-03-01-54 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328874.237327 arKYeMETxOg 128.2.6.136 46563 173.194.75.103 80 1 OPTIONS www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328874.364020 j4u32Pc5bif 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - text/html - - +1354328878.470424 TEfuqmmG4bh 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - text/html - - +1354328882.575456 FrJExwHcSal 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - text/html - - +1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 1 GET/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328882.990373 VW0XPVINV8a 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - text/html - - +1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83 www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83 www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 1 CCM_POST/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 1 CONNECT/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328903.697693 UfGkYA2HI2g 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328907.743696 i2rO3KD1Syg 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328911.790590 2cx26uAvUPl 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 1 TRACE/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328911.918511 zno26fFZkrh 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328915.964678 v5rgkJBig5l 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328920.010458 eWZCH7OONC1 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 1 DELETE/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328920.136714 yC2d6kVg709 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328924.183211 VcgagLjnO92 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - +1354328924.224567 bdRoHfaPBo3 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - +1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 1 PUT/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.350343 xNYSS2hJkle 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - +1354328924.391728 vMVjlplKKbd 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - +1354328924.433150 3omNawSNrxj 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - +1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 1 POST/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.559704 E490YZTUozc 128.2.6.136 46606 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - +1354328928.625437 YIeWJmXWNWj 128.2.6.136 46607 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - +1354328932.692706 ydiZblvsYri 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - +1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 1 HEAD/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +#close 2012-12-01-03-01-54 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log new file mode 100644 index 0000000000..aa1dcb7559 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log @@ -0,0 +1,35 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path weird +#open 2012-12-01-03-01-54 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer +#types time string addr port addr port string string bool string +1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 unknown_HTTP_method GET/ F bro +1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83 F bro +1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83 F bro +1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83/ F bro +1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83/ F bro +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 unknown_HTTP_method CCM_POST/ F bro +1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 unknown_HTTP_method CONNECT/ F bro +1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 unknown_HTTP_method TRACE/ F bro +1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 unknown_HTTP_method DELETE/ F bro +1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 unknown_HTTP_method PUT/ F bro +1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 unknown_HTTP_method POST/ F bro +1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 unknown_HTTP_method HEAD/ F bro +1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 unmatched_HTTP_reply - F bro +#close 2012-12-01-03-01-54 diff --git a/testing/btest/Traces/http-methods.trace b/testing/btest/Traces/http-methods.trace new file mode 100644 index 0000000000000000000000000000000000000000..323e6ee06ac9e4a09b15e8b9d52111794f486648 GIT binary patch literal 238829 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 Date: Mon, 3 Dec 2012 11:57:00 -0500 Subject: [PATCH 14/29] Slightly fix up file name extraction from Content-Disposition headers. --- scripts/base/utils/files.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base/utils/files.bro b/scripts/base/utils/files.bro index ccd03df0e6..e1e599b0b6 100644 --- a/scripts/base/utils/files.bro +++ b/scripts/base/utils/files.bro @@ -19,7 +19,7 @@ function generate_extraction_filename(prefix: string, c: connection, suffix: str ## the filename. function extract_filename_from_content_disposition(data: string): string { - local filename = sub(data, /^.*[fF][iI][lL][eE][nN][aA][mM][eE]=/, ""); + local filename = sub(data, /^.*[fF][iI][lL][eE][nN][aA][mM][eE][[:blank:]]*=[[:blank:]]*/, ""); # Remove quotes around the filename if they are there. if ( /^\"/ in filename ) filename = split_n(filename, /\"/, F, 2)[2]; From 63d43e6545dcfd564a3456dbe1cfab0a0f491655 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 3 Dec 2012 14:35:47 -0800 Subject: [PATCH 15/29] Renaming ASCII writer filter option 'only_single_header_row' to 'tsv'. Also clarifying usage. Closes #912. --- CHANGES | 5 +++++ VERSION | 2 +- .../base/frameworks/logging/writers/ascii.bro | 11 +++++++---- src/logging/writers/Ascii.cc | 16 ++++++++-------- src/logging/writers/Ascii.h | 2 +- .../ssh-filtered.log | 0 .../logging/{ascii-csv.bro => ascii-tsv.bro} | 2 +- 7 files changed, 23 insertions(+), 15 deletions(-) rename testing/btest/Baseline/{scripts.base.frameworks.logging.ascii-csv => scripts.base.frameworks.logging.ascii-tsv}/ssh-filtered.log (100%) rename testing/btest/scripts/base/frameworks/logging/{ascii-csv.bro => ascii-tsv.bro} (94%) diff --git a/CHANGES b/CHANGES index abe92547d9..475207a99f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.1-194 | 2012-12-03 14:36:26 -0800 + + * Renaming ASCII writer filter option 'only_single_header_row' to + 'tsv'. Also clarifying usage. Closes #912. (Robin Sommer) + 2.1-193 | 2012-12-03 14:11:14 -0800 * Fix a set of bugs with table/set attributes. (Jon Siwek) diff --git a/VERSION b/VERSION index c8d43d4760..57be098d90 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-193 +2.1-194 diff --git a/scripts/base/frameworks/logging/writers/ascii.bro b/scripts/base/frameworks/logging/writers/ascii.bro index 800af51502..352006666b 100644 --- a/scripts/base/frameworks/logging/writers/ascii.bro +++ b/scripts/base/frameworks/logging/writers/ascii.bro @@ -2,11 +2,14 @@ ##! to tweak the output format of ASCII logs. ##! ##! The ASCII writer supports currently one writer-specific filter option via -##! ``config``: setting ``only_single_header_row`` to ``T`` turns the output into -##! into CSV mode where only a single header row with the column names is printed -##! out as meta information. Example filter using this:: +##! ``config``: setting ``tsv`` to the string ``T`` turns the output into into +##! "tab-separated-value" mode where only a single header row with the column names +##! is printed out as meta information, with no "# fields" prepended; no other meta +##! data gets included in that mode. ##! -##! local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["only_single_header_row"] = "T")]; +##! Example filter using this:: +##! +##! local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["tsv"] = "T")]; ##! module LogAscii; diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc index c65b0701c3..15b50344d5 100644 --- a/src/logging/writers/Ascii.cc +++ b/src/logging/writers/Ascii.cc @@ -19,7 +19,7 @@ Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend) { fd = 0; ascii_done = false; - only_single_header_row = false; + tsv = false; output_to_stdout = BifConst::LogAscii::output_to_stdout; include_meta = BifConst::LogAscii::include_meta; @@ -81,7 +81,7 @@ void Ascii::CloseFile(double t) if ( ! fd ) return; - if ( include_meta && ! only_single_header_row ) + if ( include_meta && ! tsv ) WriteHeaderField("close", Timestamp(0)); safe_close(fd); @@ -111,17 +111,17 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * for ( WriterInfo::config_map::const_iterator i = info.config.begin(); i != info.config.end(); i++ ) { - if ( strcmp(i->first, "only_single_header_row") == 0 ) + if ( strcmp(i->first, "tsv") == 0 ) { if ( strcmp(i->second, "T") == 0 ) - only_single_header_row = true; + tsv = true; else if ( strcmp(i->second, "F") == 0 ) - only_single_header_row = false; + tsv = false; else { - Error("invalid value for 'only_single_header_row', must be boolean (T/F)"); + Error("invalid value for 'tsv', must be a string and either \"T\" or \"F\""); return false; } } @@ -144,9 +144,9 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * types += fields[i]->TypeName().c_str(); } - if ( only_single_header_row ) + if ( tsv ) { - // A single CSV-style line is all we need. + // A single TSV-style line is all we need. string str = names + "\n"; if ( ! safe_write(fd, str.c_str(), str.length()) ) goto write_error; diff --git a/src/logging/writers/Ascii.h b/src/logging/writers/Ascii.h index 37ec19aba6..9fff5aae30 100644 --- a/src/logging/writers/Ascii.h +++ b/src/logging/writers/Ascii.h @@ -45,7 +45,7 @@ private: // Options set from the script-level. bool output_to_stdout; bool include_meta; - bool only_single_header_row; + bool tsv; char* separator; int separator_len; diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-tsv/ssh-filtered.log similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log rename to testing/btest/Baseline/scripts.base.frameworks.logging.ascii-tsv/ssh-filtered.log diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro b/testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro similarity index 94% rename from testing/btest/scripts/base/frameworks/logging/ascii-csv.bro rename to testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro index 1c10f5fc6b..09276a08fd 100644 --- a/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro +++ b/testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro @@ -22,7 +22,7 @@ event bro_init() Log::create_stream(SSH::LOG, [$columns=Log]); local filter = Log::get_filter(SSH::LOG, "default"); - filter$config = table(["only_single_header_row"] = "T"); + filter$config = table(["tsv"] = "T"); Log::add_filter(SSH::LOG, filter); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; From 05e6289719adba3f0e49954039c1e9819b68553b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 3 Dec 2012 14:50:33 -0800 Subject: [PATCH 16/29] Catching out-of-memory in patricia tree code. Based on patch by Bill Parker. --- CHANGES | 4 ++ VERSION | 2 +- src/patricia.c | 131 ++++++++++++++++++++++++++++--------------------- src/util.cc | 2 +- src/util.h | 2 +- 5 files changed, 83 insertions(+), 58 deletions(-) diff --git a/CHANGES b/CHANGES index 475207a99f..9ff294055c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.1-195 | 2012-12-03 14:50:33 -0800 + + * Catching out-of-memory in patricia tree code. (Bill Parker) + 2.1-194 | 2012-12-03 14:36:26 -0800 * Renaming ASCII writer filter option 'only_single_header_row' to diff --git a/VERSION b/VERSION index 57be098d90..5f2036da97 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-194 +2.1-195 diff --git a/src/patricia.c b/src/patricia.c index 1dbc795ab7..6998576fdb 100644 --- a/src/patricia.c +++ b/src/patricia.c @@ -2,7 +2,7 @@ * Dave Plonka * * This product includes software developed by the University of Michigan, - * Merit Network, Inc., and their contributors. + * Merit Network, Inc., and their contributors. * * This file had been called "radix.c" in the MRT sources. * @@ -12,28 +12,28 @@ */ /* From copyright.txt: - * + * * Copyright (c) 1997, 1998, 1999 - * - * + * + * * The Regents of the University of Michigan ("The Regents") and Merit Network, * Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the * following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other * materials provided with the distribution. - * 3. All advertising materials mentioning features or use of - * this software must display the following acknowledgement: + * 3. All advertising materials mentioning features or use of + * this software must display the following acknowledgement: * This product includes software developed by the University of Michigan, Merit - * Network, Inc., and their contributors. + * Network, Inc., and their contributors. * 4. Neither the name of the University, Merit Network, nor the - * names of their contributors may be used to endorse or - * promote products derived from this software without + * names of their contributors may be used to endorse or + * promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -44,7 +44,7 @@ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static char copyright[] = @@ -66,6 +66,9 @@ static char copyright[] = #define Delete free +// From Bro for reporting memory exhaustion. +extern void out_of_memory(const char* where); + /* { from prefix.c */ /* prefix_tochar @@ -80,7 +83,7 @@ prefix_tochar (prefix_t * prefix) return ((u_char *) & prefix->add.sin); } -int +int comp_with_mask (void *addr, void *dest, u_int mask) { @@ -95,15 +98,15 @@ comp_with_mask (void *addr, void *dest, u_int mask) } /* inet_pton substitute implementation - * Uses inet_addr to convert an IP address in dotted decimal notation into + * Uses inet_addr to convert an IP address in dotted decimal notation into * unsigned long and copies the result to dst. - * Only supports AF_INET. Follows standard error return conventions of + * Only supports AF_INET. Follows standard error return conventions of * inet_pton. */ int local_inet_pton (int af, const char *src, void *dst) { - u_long result; + u_long result; if (af == AF_INET) { result = inet_addr(src); @@ -166,7 +169,7 @@ my_inet_pton (int af, const char *src, void *dst) } } -/* +/* * convert prefix information to ascii string with length * thread safe and (almost) re-entrant implementation */ @@ -251,6 +254,9 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) default_bitlen = 128; if (prefix == NULL) { prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); + dynamic_allocated++; } memcpy (&prefix->add.sin6, dest, 16); @@ -260,12 +266,16 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) if (prefix == NULL) { #ifndef NT prefix = calloc(1, sizeof (prefix4_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #else //for some reason, compiler is getting //prefix4_t size incorrect on NT - prefix = calloc(1, sizeof (prefix_t)); + prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #endif /* NT */ - + dynamic_allocated++; } memcpy (&prefix->add.sin, dest, 4); @@ -368,7 +378,7 @@ Ref_Prefix (prefix_t * prefix) return (prefix); } -void +void Deref_Prefix (prefix_t * prefix) { if (prefix == NULL) @@ -396,6 +406,8 @@ patricia_tree_t * New_Patricia (int maxbits) { patricia_tree_t *patricia = calloc(1, sizeof *patricia); + if (patricia == NULL) + out_of_memory("patrica/new_patricia: unable to allocate memory"); patricia->maxbits = maxbits; patricia->head = NULL; @@ -503,10 +515,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take right %s/%d\n", + fprintf (stderr, "patricia_search_exact: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take right at %d\n", + fprintf (stderr, "patricia_search_exact: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -514,10 +526,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take left %s/%d\n", + fprintf (stderr, "patricia_search_exact: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take left at %d\n", + fprintf (stderr, "patricia_search_exact: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -529,7 +541,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", + fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: stop at %d\n", node->bit); @@ -541,7 +553,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_exact: found %s/%d\n", + fprintf (stderr, "patricia_search_exact: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -575,7 +587,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node->prefix) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: push %s/%d\n", + fprintf (stderr, "patricia_search_best: push %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ stack[cnt++] = node; @@ -584,10 +596,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take right %s/%d\n", + fprintf (stderr, "patricia_search_best: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take right at %d\n", + fprintf (stderr, "patricia_search_best: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -595,10 +607,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take left %s/%d\n", + fprintf (stderr, "patricia_search_best: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take left at %d\n", + fprintf (stderr, "patricia_search_best: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -615,7 +627,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node == NULL) fprintf (stderr, "patricia_search_best: stop at null\n"); else if (node->prefix) - fprintf (stderr, "patricia_search_best: stop at %s/%d\n", + fprintf (stderr, "patricia_search_best: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: stop at %d\n", node->bit); @@ -627,14 +639,14 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv while (--cnt >= 0) { node = stack[cnt]; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: pop %s/%d\n", + fprintf (stderr, "patricia_search_best: pop %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - if (comp_with_mask (prefix_tochar (node->prefix), + if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), node->prefix->bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: found %s/%d\n", + fprintf (stderr, "patricia_search_best: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -665,6 +677,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (patricia->head == NULL) { node = calloc(1, sizeof *node); + if (node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + node->bit = prefix->bitlen; node->prefix = Ref_Prefix (prefix); node->parent = NULL; @@ -672,7 +687,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->data = NULL; patricia->head = node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", + fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ patricia->num_active_node++; @@ -691,7 +706,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take right %s/%d\n", + fprintf (stderr, "patricia_lookup: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take right at %d\n", node->bit); @@ -703,7 +718,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take left %s/%d\n", + fprintf (stderr, "patricia_lookup: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take left at %d\n", node->bit); @@ -716,7 +731,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) assert (node->prefix); #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: stop at %s/%d\n", + fprintf (stderr, "patricia_lookup: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ @@ -751,7 +766,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) parent = node->parent; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: up to %s/%d\n", + fprintf (stderr, "patricia_lookup: up to %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: up to %d\n", node->bit); @@ -760,8 +775,8 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (differ_bit == bitlen && node->bit == bitlen) { if (node->prefix) { -#ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: found %s/%d\n", +#ifdef PATRICIA_DEBUG + fprintf (stderr, "patricia_lookup: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -776,6 +791,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } new_node = calloc(1, sizeof *new_node); + if (new_node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + new_node->bit = prefix->bitlen; new_node->prefix = Ref_Prefix (prefix); new_node->parent = NULL; @@ -795,7 +813,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->l = new_node; } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", + fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (new_node); @@ -822,12 +840,15 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = new_node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", + fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } else { glue = calloc(1, sizeof *glue); + if (glue == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + glue->bit = differ_bit; glue->prefix = NULL; glue->parent = node->parent; @@ -856,7 +877,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = glue; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", + fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } @@ -874,13 +895,13 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r && node->l) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", + fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - + /* this might be a placeholder node -- have to check and make sure * there is a prefix aossciated with it ! */ - if (node->prefix != NULL) + if (node->prefix != NULL) Deref_Prefix (node->prefix); node->prefix = NULL; /* Also I needed to clear data pointer -- masaki */ @@ -890,7 +911,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r == NULL && node->l == NULL) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", + fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ parent = node->parent; @@ -937,7 +958,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", + fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ if (node->r) { @@ -996,7 +1017,7 @@ try_search_exact (patricia_tree_t *tree, char *string) printf ("try_search_exact: not found\n"); } else { - printf ("try_search_exact: %s/%d found\n", + printf ("try_search_exact: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); } Deref_Prefix (prefix); @@ -1023,7 +1044,7 @@ try_search_best (patricia_tree_t *tree, char *string) if ((node = patricia_search_best (tree, prefix)) == NULL) printf ("try_search_best: not found\n"); else - printf ("try_search_best: %s/%d found\n", + printf ("try_search_best: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); Deref_Prefix (prefix); return 0; // [RS] What is supposed to be returned here? diff --git a/src/util.cc b/src/util.cc index 80cd3a0685..c36ff6a31c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1416,7 +1416,7 @@ void safe_close(int fd) } } -void out_of_memory(const char* where) +extern "C" void out_of_memory(const char* where) { fprintf(stderr, "out of memory in %s.\n", where); diff --git a/src/util.h b/src/util.h index 71b9c494e8..7d65f42fa8 100644 --- a/src/util.h +++ b/src/util.h @@ -303,7 +303,7 @@ extern bool safe_write(int fd, const char* data, int len); // Wraps close(2) to emit error messages and abort on unrecoverable errors. extern void safe_close(int fd); -extern void out_of_memory(const char* where); +extern "C" void out_of_memory(const char* where); inline void* safe_realloc(void* ptr, size_t size) { From f7440375f175c0081d7d05ca5f0581480031130f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 4 Dec 2012 12:38:09 -0600 Subject: [PATCH 17/29] Interpreter exceptions occurring in "when" blocks are now handled. The scripting error that caused the exception is still reported, but it no longer causes Bro to terminate. Addresses #779 --- src/Trigger.cc | 20 +++++- .../core.dns-interpreter-exceptions/out | 12 ++++ .../btest/core/dns-interpreter-exceptions.bro | 63 +++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 testing/btest/Baseline/core.dns-interpreter-exceptions/out create mode 100644 testing/btest/core/dns-interpreter-exceptions.bro diff --git a/src/Trigger.cc b/src/Trigger.cc index 164f11b885..b7e08b557e 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -217,8 +217,15 @@ bool Trigger::Eval() Name()); Unref(v); + v = 0; stmt_flow_type flow; - v = body->Exec(f, flow); + + try + { + v = body->Exec(f, flow); + } + catch ( InterpreterException& e ) + { /* Already reported. */ } if ( is_return ) { @@ -300,7 +307,14 @@ void Trigger::Timeout() { stmt_flow_type flow; Frame* f = frame->Clone(); - Val* v = timeout_stmts->Exec(f, flow); + Val* v = 0; + + try + { + v = timeout_stmts->Exec(f, flow); + } + catch ( InterpreterException& e ) + { /* Already reported. */ } if ( is_return ) { @@ -382,7 +396,7 @@ void Trigger::Attach(Trigger *trigger) void Trigger::Cache(const CallExpr* expr, Val* v) { - if ( disabled ) + if ( disabled || ! v ) return; ValCache::iterator i = cache.find(expr); diff --git a/testing/btest/Baseline/core.dns-interpreter-exceptions/out b/testing/btest/Baseline/core.dns-interpreter-exceptions/out new file mode 100644 index 0000000000..c081edc489 --- /dev/null +++ b/testing/btest/Baseline/core.dns-interpreter-exceptions/out @@ -0,0 +1,12 @@ +1300475167.096535 expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.dns-interpreter-exceptions/dns-interpreter-exceptions.bro, line 28: field value missing [p$ip] +1300475167.096535 expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.dns-interpreter-exceptions/dns-interpreter-exceptions.bro, line 49: field value missing [p$ip] +1300475168.902195 expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.dns-interpreter-exceptions/dns-interpreter-exceptions.bro, line 39: field value missing [p$ip] +1300475168.902195 expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.dns-interpreter-exceptions/dns-interpreter-exceptions.bro, line 12: field value missing [p$ip] +timeout g(), F +timeout g(), T +timeout +g() done, no exception, T +localhost resolved +localhost resolved from f(), T +localhost resolved from f(), F +f() done, no exception, T diff --git a/testing/btest/core/dns-interpreter-exceptions.bro b/testing/btest/core/dns-interpreter-exceptions.bro new file mode 100644 index 0000000000..a795971b58 --- /dev/null +++ b/testing/btest/core/dns-interpreter-exceptions.bro @@ -0,0 +1,63 @@ +# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out +# interpreter exceptions in "when" blocks shouldn't cause termination +global p: pkt_hdr; + +function f(do_exception: bool): bool + { + return when ( local addrs = lookup_hostname("localhost") ) + { + print "localhost resolved from f()", do_exception; + if ( do_exception ) + print p$ip; + return T; + } + return F; + } + +function g(do_exception: bool): bool + { + return when ( local addrs = lookup_hostname("localhost") ) + { + print "shouldn't get here, g()", do_exception; + } + timeout 0 sec + { + print "timeout g()", do_exception; + if ( do_exception ) + print p$ip; + return T; + } + return F; + } + +event bro_init() + { + when ( local addrs = lookup_hostname("localhost") ) + { + print "localhost resolved"; + print p$ip; + } + + when ( local addrs2 = lookup_hostname("localhost") ) + { + print "shouldn't get here"; + } + timeout 0 sec + { + print "timeout"; + print p$ip; + } + + when ( local b = f(T) ) + print "f() exception done (shouldn't be printed)", b; + + when ( local b2 = g(T) ) + print "g() exception done (shouldn't be printed)", b2; + + when ( local b3 = f(F) ) + print "f() done, no exception", b3; + + when ( local b4 = g(F) ) + print "g() done, no exception", b4; + } From 7758f4dc9cab60fbb23e8e69a51463dfa0800e20 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 4 Dec 2012 12:45:52 -0600 Subject: [PATCH 18/29] Bump CPack RPM package requirement to python >= 2.6.0. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17ba34ab3b..e2a83e10f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,7 @@ CheckOptionalBuildSources(aux/broccoli Broccoli INSTALL_BROCCOLI) if (INSTALL_BROCTL) # CPack RPM Generator may not automatically detect this - set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.4.0") + set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.6.0") endif () # If this CMake project is a sub-project of another, we will not From 75278af8a101395f06b3371e5a5dc3795032efad Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 4 Dec 2012 15:22:16 -0600 Subject: [PATCH 19/29] Invalid vector indices now generate error message (addresses #24). The error/behavior is the same as accessing tables at invalid indices. --- src/Expr.cc | 14 +++++--------- testing/btest/Baseline/language.invalid_index/out | 7 +++++++ testing/btest/language/invalid_index.bro | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 testing/btest/Baseline/language.invalid_index/out create mode 100644 testing/btest/language/invalid_index.bro diff --git a/src/Expr.cc b/src/Expr.cc index 07ee4eb1e1..97099a8995 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2950,16 +2950,12 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const if ( IsError() ) return 0; - if ( v1->Type()->Tag() == TYPE_VECTOR ) - { - Val* v = v1->AsVectorVal()->Lookup(v2); - // ### dangerous - this can silently fail larger operations - // due to a missing element - return v ? v->Ref() : 0; - } + Val* v = 0; - TableVal* v_tbl = v1->AsTableVal(); - Val* v = v_tbl->Lookup(v2); + if ( v1->Type()->Tag() == TYPE_VECTOR ) + v = v1->AsVectorVal()->Lookup(v2); + else + v = v1->AsTableVal()->Lookup(v2); if ( v ) return v->Ref(); diff --git a/testing/btest/Baseline/language.invalid_index/out b/testing/btest/Baseline/language.invalid_index/out new file mode 100644 index 0000000000..9110a8979d --- /dev/null +++ b/testing/btest/Baseline/language.invalid_index/out @@ -0,0 +1,7 @@ +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_index/invalid_index.bro, line 8: no such index (foo[1]) +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_index/invalid_index.bro, line 9: no such index (foo[2]) +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_index/invalid_index.bro, line 12: no such index (foo2[1]) +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_index/invalid_index.bro, line 13: no such index (foo2[2]) +foo[0], 42 +foo2[0], 13 +done diff --git a/testing/btest/language/invalid_index.bro b/testing/btest/language/invalid_index.bro new file mode 100644 index 0000000000..96b7fa78c5 --- /dev/null +++ b/testing/btest/language/invalid_index.bro @@ -0,0 +1,15 @@ +# @TEST-EXEC: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +global foo: vector of count = { 42 }; +global foo2: table[count] of count = { [0] = 13 }; + +print "foo[0]", foo[0]; +print "foo[1]", foo[1]; +print "foo[2]", foo[2]; + +print "foo2[0]", foo2[0]; +print "foo2[1]", foo2[1]; +print "foo2[2]", foo2[2]; + +print "done"; From 32239ea63395e523b7ad6ccdfa3a56c34d35a0fa Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 4 Dec 2012 16:29:23 -0600 Subject: [PATCH 20/29] Bad record constructor initializers now give an error (addresses #34). As opposed to a segfault. --- src/Expr.cc | 22 ++++++++++--------- .../Baseline/language.record-bad-ctor/out | 3 +++ testing/btest/language/record-bad-ctor.bro | 8 +++++++ 3 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 testing/btest/Baseline/language.record-bad-ctor/out create mode 100644 testing/btest/language/record-bad-ctor.bro diff --git a/src/Expr.cc b/src/Expr.cc index 97099a8995..7995d5d495 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3286,20 +3286,22 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const { - RecordVal* rv = Eval(0)->AsRecordVal(); - RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr); + Val* v = Eval(0); - if ( ar ) + if ( v ) { - Unref(rv); - return ar; + RecordVal* rv = v->AsRecordVal(); + RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr); + + if ( ar ) + { + Unref(rv); + return ar; + } } - else - { - Error("bad record initializer"); - return 0; - } + Error("bad record initializer"); + return 0; } Val* RecordConstructorExpr::Fold(Val* v) const diff --git a/testing/btest/Baseline/language.record-bad-ctor/out b/testing/btest/Baseline/language.record-bad-ctor/out new file mode 100644 index 0000000000..2b890419ae --- /dev/null +++ b/testing/btest/Baseline/language.record-bad-ctor/out @@ -0,0 +1,3 @@ +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.record-bad-ctor/record-bad-ctor.bro, line 6: no type given (asdfasdf) +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.record-bad-ctor/record-bad-ctor.bro, line 7: uninitialized list value ($ports=asdfasdf) +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.record-bad-ctor/record-bad-ctor.bro, line 7: bad record initializer ([$ports=asdfasdf]) diff --git a/testing/btest/language/record-bad-ctor.bro b/testing/btest/language/record-bad-ctor.bro new file mode 100644 index 0000000000..6b7ae4ff19 --- /dev/null +++ b/testing/btest/language/record-bad-ctor.bro @@ -0,0 +1,8 @@ +# @TEST-EXEC-FAIL: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +# At least shouldn't crash Bro, just report the invalid record ctor. + +global asdfasdf; +const blah = [$ports=asdfasdf]; +print blah; From f403e537ece415ec338e8b21d0cb233daf7f970c Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 5 Dec 2012 12:36:09 -0600 Subject: [PATCH 21/29] Fix segfault: uninitialized identifiers w/ &synchronized (addresses #66) Synchronization of state between connecting peers now skips over identifiers that aren't initialized with a value yet. If they're assigned a value later, that will be synchronized like usual. --- src/RemoteSerializer.cc | 8 ++++++++ testing/btest/Baseline/istate.sync/receiver.vars.log | 1 + testing/btest/Baseline/istate.sync/sender.vars.log | 1 + testing/btest/istate/sync.bro | 11 ++++++++--- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 564ad2be68..54986610bc 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -1032,6 +1032,14 @@ bool RemoteSerializer::SendAllSynchronized(Peer* peer, SerialInfo* info) for ( ; index < sync_ids.length(); ++index ) { + if ( ! sync_ids[index]->ID_Val() ) + { +#ifdef DEBUG + DBG_LOG(DBG_COMM, "Skip sync of ID with null value: %s\n", + sync_ids[index]->Name()); +#endif + continue; + } cont->SaveContext(); StateAccess sa(OP_ASSIGN, sync_ids[index], diff --git a/testing/btest/Baseline/istate.sync/receiver.vars.log b/testing/btest/Baseline/istate.sync/receiver.vars.log index b28cfbd5c9..192876bd3e 100644 --- a/testing/btest/Baseline/istate.sync/receiver.vars.log +++ b/testing/btest/Baseline/istate.sync/receiver.vars.log @@ -31,3 +31,4 @@ file "test2" of string 6667/tcp [2, 20, 3, 4] [a=zxzxzx, b=[a=pop, b=43, c=9.999], c=[a=IOIOI, b=201, c=612.2], d=6.6666, e=] +122112 diff --git a/testing/btest/Baseline/istate.sync/sender.vars.log b/testing/btest/Baseline/istate.sync/sender.vars.log index b28cfbd5c9..192876bd3e 100644 --- a/testing/btest/Baseline/istate.sync/sender.vars.log +++ b/testing/btest/Baseline/istate.sync/sender.vars.log @@ -31,3 +31,4 @@ file "test2" of string 6667/tcp [2, 20, 3, 4] [a=zxzxzx, b=[a=pop, b=43, c=9.999], c=[a=IOIOI, b=201, c=612.2], d=6.6666, e=] +122112 diff --git a/testing/btest/istate/sync.bro b/testing/btest/istate/sync.bro index e1364a9553..a297e8a50f 100644 --- a/testing/btest/istate/sync.bro +++ b/testing/btest/istate/sync.bro @@ -1,7 +1,7 @@ # @TEST-SERIALIZE: comm # -# @TEST-EXEC: btest-bg-run sender bro %INPUT ../sender.bro -# @TEST-EXEC: btest-bg-run receiver bro %INPUT ../receiver.bro +# @TEST-EXEC: btest-bg-run sender bro -b %INPUT ../sender.bro +# @TEST-EXEC: btest-bg-run receiver bro -b %INPUT ../receiver.bro # @TEST-EXEC: btest-bg-wait 20 # # @TEST-EXEC: btest-diff sender/vars.log @@ -27,6 +27,7 @@ global foo13 = { [1,"ABC"] = 101, [2,"DEF"] = 102, [3,"GHI"] = 103 } &persiste global foo14 = { [12345] = foo11, [12346] = foo11 } &persistent &synchronized; global foo15 = 42/udp &persistent &synchronized; global foo16: vector of count = [1,2,3] &persistent &synchronized; +global foo18: count &persistent &synchronized; # not initialized type type1: record { a: string; @@ -70,6 +71,7 @@ event bro_done() print out, foo15; print out, foo16; print out, foo17; + print out, foo18; } @@ -128,7 +130,8 @@ function modify() delete foo17$e; foo2 = 1234567; -} + foo18 = 122112; + } @load frameworks/communication/listen @@ -148,6 +151,8 @@ redef Communication::nodes += { @TEST-START-FILE receiver.bro +@load base/frameworks/communication + event bro_init() { capture_events("events.bst"); From d367e227c1041b180fb1d49b6016f25d4db24457 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 5 Dec 2012 12:40:00 -0800 Subject: [PATCH 22/29] ok, this one is a bit... embarrassing. Delete the correct entry in case of error. Fixes a segfault when the faulty data is of type string and not the last field of the input... --- src/input/readers/Ascii.cc | 2 +- .../.stderrwithoutfirstline | 4 ++ .../out | 3 ++ .../base/frameworks/input/invalidtext.bro | 46 +++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/.stderrwithoutfirstline create mode 100644 testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/out create mode 100644 testing/btest/scripts/base/frameworks/input/invalidtext.bro diff --git a/src/input/readers/Ascii.cc b/src/input/readers/Ascii.cc index e9cba27205..173ce418ca 100644 --- a/src/input/readers/Ascii.cc +++ b/src/input/readers/Ascii.cc @@ -572,7 +572,7 @@ bool Ascii::DoUpdate() // array structure. for ( int i = 0; i < fpos; i++ ) - delete fields[fpos]; + delete fields[i]; delete [] fields; continue; diff --git a/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/.stderrwithoutfirstline b/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/.stderrwithoutfirstline new file mode 100644 index 0000000000..3d8ba5e267 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/.stderrwithoutfirstline @@ -0,0 +1,4 @@ +error: ../input.log/Input::READER_ASCII: String 'l' contained no parseable number +error: ../input.log/Input::READER_ASCII: Could not convert line ' l' to Val. Ignoring line. +received termination signal +>>> diff --git a/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/out b/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/out new file mode 100644 index 0000000000..4950b6f590 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.input.invalidtext/out @@ -0,0 +1,3 @@ +{ +[] = [c=5] +} diff --git a/testing/btest/scripts/base/frameworks/input/invalidtext.bro b/testing/btest/scripts/base/frameworks/input/invalidtext.bro new file mode 100644 index 0000000000..75efb1247d --- /dev/null +++ b/testing/btest/scripts/base/frameworks/input/invalidtext.bro @@ -0,0 +1,46 @@ +# (uses listen.bro just to ensure input sources are more reliably fully-read). +# @TEST-SERIALIZE: comm +# +# @TEST-EXEC: btest-bg-run bro bro -b %INPUT +# @TEST-EXEC: btest-bg-wait -k 5 +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: sed 1d .stderr > .stderrwithoutfirstline +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderrwithoutfirstline + +@TEST-START-FILE input.log +#separator \x09 +#fields i c +#types int count + l + 5 +@TEST-END-FILE + +@load frameworks/communication/listen + +global outfile: file; + +module A; + +type Idx: record { + i: string; +}; + +type Val: record { + c: count; +}; + +global servers: table[string] of Val = table(); + +event bro_init() + { + outfile = open("../out"); + # first read in the old stuff into the table... + Input::add_table([$source="../input.log", $name="ssh", $idx=Idx, $val=Val, $destination=servers]); + Input::remove("ssh"); + } + +event Input::end_of_data(name: string, source:string) + { + print outfile, servers; + terminate(); + } From 90fc5c97e5682a357fb501fd7971e96479dbcff2 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 5 Dec 2012 15:47:32 -0800 Subject: [PATCH 23/29] Reporting warnings if kill/waitpid fail in communication system. Also replace bzero with memset(). Patches from Bill Parker. --- CHANGES | 23 +++++++++++++++++++++++ VERSION | 2 +- aux/broccoli | 2 +- src/RemoteSerializer.cc | 19 +++++++++++++------ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 4ce30b9a35..64eee13f71 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,27 @@ +2.1-207 | 2012-12-05 15:47:32 -0800 + + * Reporting warnings if kill/waitpid fail in communication system. + (Bill Parker) + + * Replace() bzero with memset(). (Bill Parker) + + * Merge remote-tracking branch 'vlad/topic/vladg/http-verbs' + + * vlad/topic/vladg/http-verbs: + A test for HTTP methods, including some horribly illegal requests. + Remove hardcoded HTTP verbs from the analyzer (#741) + + I added a "bad_HTTP_request" weird for HTTP request lines that don't + have more than a single word. + + Closes #741. (Robin Sommer) + + * A test for HTTP methods, including some horribly illegal requests. (Vlad Grigorescu) + + * Remove hardcoded HTTP verbs from the analyzer (#741) (Vlad Grigorescu) + + 2.1-203 | 2012-12-05 14:36:56 -0800 * Fix segfault: Synchronization of state between connecting peers diff --git a/VERSION b/VERSION index 5a8388c35d..e0c0306d87 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-203 +2.1-207 diff --git a/aux/broccoli b/aux/broccoli index a8846fc5b0..5c983a00ce 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit a8846fc5b004ffe4e3d00e826d0077ba19518192 +Subproject commit 5c983a00ce45b2687d0235b67602c98916910412 diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 54986610bc..66f8def489 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -545,8 +545,11 @@ RemoteSerializer::~RemoteSerializer() { if ( child_pid ) { - kill(child_pid, SIGKILL); - waitpid(child_pid, 0, 0); + if ( kill(child_pid, SIGKILL) < 0 ) + reporter->Warning("warning: cannot kill child (pid %d), %s", child_pid, strerror(errno)); + + else if ( waitpid(child_pid, 0, 0) < 0 ) + reporter->Warning("warning: error encountered during waitpid(%d), %s", child_pid, strerror(errno)); } delete io; @@ -3161,7 +3164,10 @@ void RemoteSerializer::FatalError(const char* msg) reporter->Error("%s", msg); closed = true; - kill(child_pid, SIGQUIT); + + if ( kill(child_pid, SIGQUIT) < 0 ) + reporter->Warning("warning: cannot kill child pid %d, %s", child_pid, strerror(errno)); + child_pid = 0; using_communication = false; io->Clear(); @@ -3971,7 +3977,7 @@ bool SocketComm::Connect(Peer* peer) { int status; addrinfo hints, *res, *res0; - bzero(&hints, sizeof(hints)); + memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; @@ -4103,7 +4109,7 @@ bool SocketComm::Listen() { int status, on = 1; addrinfo hints, *res, *res0; - bzero(&hints, sizeof(hints)); + memset(&hints, 0, sizeof(hints)); IPAddr listen_ip(listen_if); @@ -4368,7 +4374,8 @@ void SocketComm::Kill() CloseListenFDs(); - kill(getpid(), SIGTERM); + if ( kill(getpid(), SIGTERM) < 0 ) + Log(fmt("warning: cannot kill SocketComm pid %d, %s", getpid(), strerror(errno))); while ( 1 ) ; // loop until killed From c8d264f10502ddc1fc25dbd2387426218646d3c0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 5 Dec 2012 15:50:46 -0800 Subject: [PATCH 24/29] Updating submodule(s). [nomail] --- aux/broccoli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broccoli b/aux/broccoli index 5c983a00ce..06682dbb15 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 5c983a00ce45b2687d0235b67602c98916910412 +Subproject commit 06682dbb15d26d2688bdc9ad76efec17d38dc80f From 57510464a1c100f174382daa48934f2404762f3d Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 5 Dec 2012 16:44:04 -0800 Subject: [PATCH 25/29] Adapting the HTTP request line parsing to only accept methods consisting of letters [A-Za-z]. I had some bogus HTTP sessions now with the test-suite that reported data as HTTP because it started with "Weird(Conn(), "bad_HTTP_request"); - return 0; + // The method must consist of only letters. + if ( (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z') ) + goto error; } + rest = skip_whitespace(end_of_request, end_of_line); + if ( rest == end_of_request ) + // End of line already reached. Most likely a DPD failure. + goto error; + request_method = new StringVal(request_method_len, request_method_str); if ( ! ParseRequest(rest, end_of_line) ) @@ -1144,6 +1152,10 @@ int HTTP_Analyzer::HTTP_RequestLine(const char* line, const char* end_of_line) unescaped_URI->AsString()->Len(), true, true, true, true); return 1; + +error: + reporter->Weird(Conn(), "bad_HTTP_request"); + return 0; } int HTTP_Analyzer::ParseRequest(const char* line, const char* end_of_line) diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log index 37d8410143..8626071e18 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path http -#open 2012-12-05-23-27-37 +#open 2012-12-06-00-55-27 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file 1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - text/html - - @@ -13,46 +13,46 @@ 1354328874.364020 j4u32Pc5bif 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - text/html - - 1354328878.470424 TEfuqmmG4bh 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - text/html - - 1354328882.575456 FrJExwHcSal 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - text/html - - -1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 1 GET/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328882.990373 VW0XPVINV8a 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - text/html - - -1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83 www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - -1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83 www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 0 - - - - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 1 \xc3\x83\xc3\x82\xc3\x83/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 1 CCM_POST/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.328583 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 0 - - - - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328895.375116 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328895.500315 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 0 - - - - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 1 CONNECT/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328903.697693 UfGkYA2HI2g 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328907.743696 i2rO3KD1Syg 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328911.790590 2cx26uAvUPl 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 1 TRACE/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328911.918511 zno26fFZkrh 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328915.964678 v5rgkJBig5l 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328920.010458 eWZCH7OONC1 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 1 DELETE/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328920.136714 yC2d6kVg709 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328924.183211 VcgagLjnO92 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - 1354328924.224567 bdRoHfaPBo3 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - -1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 1 PUT/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328924.350343 xNYSS2hJkle 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - 1354328924.391728 vMVjlplKKbd 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - 1354328924.433150 3omNawSNrxj 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - -1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 1 POST/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328924.559704 E490YZTUozc 128.2.6.136 46606 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - 1354328928.625437 YIeWJmXWNWj 128.2.6.136 46607 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - 1354328932.692706 ydiZblvsYri 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - -1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 1 HEAD/ www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -#close 2012-12-05-23-27-37 +#close 2012-12-06-00-55-28 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log index c09c4e7158..8a9dcf17cc 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log @@ -3,44 +3,59 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-12-05-23-27-37 +#open 2012-12-06-00-55-27 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1354328874.278822 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 bad_HTTP_request - F bro 1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328874.321792 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 bad_HTTP_request - F bro 1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 unknown_HTTP_method GET/ F bro +1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 bad_HTTP_request - F bro +1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328882.949510 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 bad_HTTP_request - F bro 1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83 F bro -1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83 F bro -1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83/ F bro +1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 bad_HTTP_request - F bro +1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328891.226199 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 bad_HTTP_request - F bro 1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 unknown_HTTP_method \xc3\x83\xc3\x82\xc3\x83/ F bro -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 unknown_HTTP_method CCM_POST/ F bro +1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.328583 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 bad_HTTP_request - F bro +1354328895.375116 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 bad_HTTP_request - F bro +1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328895.438812 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 bad_HTTP_request - F bro 1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 unknown_HTTP_method CONNECT/ F bro +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 bad_HTTP_request - F bro +1354328895.500315 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 bad_HTTP_request - F bro +1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328903.656369 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 bad_HTTP_request - F bro 1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 unknown_HTTP_method TRACE/ F bro +1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 bad_HTTP_request - F bro +1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328911.876341 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 bad_HTTP_request - F bro 1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 unknown_HTTP_method DELETE/ F bro +1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 bad_HTTP_request - F bro +1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328920.094072 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 bad_HTTP_request - F bro 1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 unknown_HTTP_method PUT/ F bro +1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328924.308714 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 bad_HTTP_request - F bro 1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 unknown_HTTP_method POST/ F bro +1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328924.518204 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 bad_HTTP_request - F bro 1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 unknown_HTTP_method HEAD/ F bro +1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 bad_HTTP_request - F bro +1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328932.776609 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 bad_HTTP_request - F bro 1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 unmatched_HTTP_reply - F bro -#close 2012-12-05-23-27-37 +#close 2012-12-06-00-55-28 From a31161ef267e2e4d54170e39bfcee9920ff385bd Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 6 Dec 2012 08:34:46 -0800 Subject: [PATCH 26/29] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 834131cd0e..5629b535c5 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 834131cd0ec0f63cce9de818726fe6167dedbf34 +Subproject commit 5629b535c564a3e389fd5bbcf0c16b1b57687e3b From 5598e1ca9b121e55acec47ba1689d6381c62ba46 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 6 Dec 2012 15:52:36 -0800 Subject: [PATCH 27/29] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 5629b535c5..91e3b8ad44 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 5629b535c564a3e389fd5bbcf0c16b1b57687e3b +Subproject commit 91e3b8ad445cb4d8919b4ee1cc6f0753c3fa0a55 From e2d20cb7bc5139192977fa5d0a63249b8a4a22ce Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 7 Dec 2012 19:42:03 -0800 Subject: [PATCH 28/29] Changing the HTTP parser to accept methods that align with the RFC. --- src/HTTP.cc | 42 +++++++++++-------- .../http.log | 10 ++--- .../weird.log | 13 +++--- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/HTTP.cc b/src/HTTP.cc index 7a18e903e8..7e4079b853 100644 --- a/src/HTTP.cc +++ b/src/HTTP.cc @@ -1116,33 +1116,39 @@ const char* HTTP_Analyzer::PrefixWordMatch(const char* line, return line; } +static bool is_HTTP_token_char(char c) + { + return c > 31 && c != 127 && // CTL per RFC 2616. + c != ' ' && c != '\t' && // Separators. + c != '(' && c != ')' && c != '<' && c != '>' && c != '@' && + c != ',' && c != ';' && c != ':' && c != '\\' && c != '"' && + c != '/' && c != '[' && c != ']' && c != '?' && c != '=' && + c != '{' && c != '}'; + } + +static const char* get_HTTP_token(const char* s, const char* e) + { + while ( s < e && is_HTTP_token_char(*s) ) + ++s; + + return s; + } + + int HTTP_Analyzer::HTTP_RequestLine(const char* line, const char* end_of_line) { - const char* request_method_str = 0; - const char* end_of_request = 0; const char* rest = 0; - int request_method_len = 0; + const char* end_of_method = get_HTTP_token(line, end_of_line); - get_word(end_of_line - line, line, request_method_len, request_method_str); - - if ( request_method_len == 0 ) + if ( end_of_method == line ) goto error; - end_of_request = request_method_str + request_method_len; + rest = skip_whitespace(end_of_method, end_of_line); - for ( const char* p = request_method_str; p < end_of_request; p++ ) - { - // The method must consist of only letters. - if ( (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z') ) - goto error; - } - - rest = skip_whitespace(end_of_request, end_of_line); - if ( rest == end_of_request ) - // End of line already reached. Most likely a DPD failure. + if ( rest == end_of_method ) goto error; - request_method = new StringVal(request_method_len, request_method_str); + request_method = new StringVal(end_of_method - line, line); if ( ! ParseRequest(rest, end_of_line) ) reporter->InternalError("HTTP ParseRequest failed"); diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log index 8626071e18..ac84e5ae7a 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path http -#open 2012-12-06-00-55-27 +#open 2012-12-07-04-43-19 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file 1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - text/html - - @@ -21,11 +21,11 @@ 1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328891.328583 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 0 - - - - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - -1354328895.375116 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -1354328895.500315 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 0 - - - - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - 1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - @@ -55,4 +55,4 @@ 1354328932.692706 ydiZblvsYri 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - 1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - 1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - -#close 2012-12-06-00-55-28 +#close 2012-12-07-04-43-19 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log index 8a9dcf17cc..8b963f00cf 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-12-06-00-55-27 +#open 2012-12-07-04-43-19 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1354328874.278822 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 bad_HTTP_request - F bro @@ -24,16 +24,13 @@ 1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 bad_HTTP_request - F bro 1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 bad_HTTP_request - F bro -1354328891.328583 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 bad_HTTP_request - F bro -1354328895.375116 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro 1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 bad_HTTP_request - F bro 1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328895.438812 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 bad_HTTP_request - F bro 1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 bad_HTTP_request - F bro -1354328895.500315 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro 1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 bad_HTTP_request - F bro 1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328903.656369 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 bad_HTTP_request - F bro @@ -58,4 +55,4 @@ 1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 unmatched_HTTP_reply - F bro 1354328932.776609 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 bad_HTTP_request - F bro 1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 unmatched_HTTP_reply - F bro -#close 2012-12-06-00-55-28 +#close 2012-12-07-04-43-19 From e8482fef9962bf142092eb44c0acfd9086393c10 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 8 Dec 2012 12:05:32 -0800 Subject: [PATCH 29/29] Updating CHANGES and VERSION. --- CHANGES | 5 +++++ VERSION | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b912354f04..fd6b69f099 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.1-212 | 2012-12-07 19:42:03 -0800 + + * Changing the HTTP parser to accept request methods in alignment + with the RFC. (Robin Sommer) + 2.1-209 | 2012-12-05 16:44:04 -0800 * Adapting the HTTP request line parsing to only accept methods diff --git a/VERSION b/VERSION index f169e62b3a..ae0289baaf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-209 +2.1-212