diff --git a/CHANGES b/CHANGES index aefe5d7929..7902f9ea7f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,12 @@ +<<<<<<< HEAD +======= +2.4-39 | 2015-07-20 15:30:35 -0700 + + * Refactoring layer 2 parsing code to reside in the Packet class, + plus further layer 2 cleanup. (Robin Sommer) + +>>>>>>> c7602ac... Cleanup 2.4-32 | 2015-07-16 17:21:29 -0700 * Refactor code to use a common Packet type throught. (Jeff Barber) diff --git a/VERSION b/VERSION index 1116eda970..c281ab1728 100644 --- a/VERSION +++ b/VERSION @@ -1 +1,5 @@ +<<<<<<< HEAD 2.4-32 +======= +2.4-39 +>>>>>>> c7602ac... Cleanup diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f28d5d695..bdbd3839ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -297,7 +297,6 @@ set(bro_SRCS IntSet.cc IP.cc IPAddr.cc - Layer2.cc List.cc Reporter.cc NFA.cc diff --git a/src/Packet.h b/src/Packet.h deleted file mode 100644 index f1dd233be5..0000000000 --- a/src/Packet.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef packet_h -#define packet_h - -#include "Desc.h" -#include "IP.h" -#include "NetVar.h" - -enum Layer3Proto { - L3_UNKNOWN = -1, - L3_IPV4 = 1, - L3_IPV6 = 2, - L3_ARP = 3, -}; - -// A link-layer packet. -// -// Note that for serialization we don't use much of the support provided by -// the serialization framework. Serialize/Unserialize do all the work by -// themselves. In particular, Packets aren't derived from SerialObj. They are -// completely seperate and self-contained entities, and we don't need any of -// the sophisticated features like object caching. - -class Packet { -public: - Packet() - { - struct timeval ts = {0, 0}; - Init(0, &ts, 0, 0, 0); - } - // Construct and initialize from packet data. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - Layer3Proto arg_l3_proto = L3_UNKNOWN) - { - Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag, - arg_hdrsize, arg_l3_proto); - } - - ~Packet() - { - if ( free ) - delete [] data; - } - - // Initialize with data from pointer. - // - // arg_free: If true makes an internal copy of the *data*. If false, - // stores just a pointer to *data*, which must remain valid. - void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, - uint32 arg_len, const u_char *arg_data, int arg_free = false, - std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, - Layer3Proto arg_l3_proto = L3_UNKNOWN) - { - link_type = arg_link_type; - ts = *arg_ts; - cap_len = arg_caplen; - len = arg_len; - free = arg_free; - - if ( free ) - { - data = new u_char[cap_len]; - memcpy(const_cast(data), arg_data, cap_len); - } - else - data = arg_data; - - hdr_size = arg_hdrsize; - l3_proto = arg_l3_proto; - tag = arg_tag; - time = ts.tv_sec + double(ts.tv_usec) / 1e6; - eth_type = 0; - vlan = 0; - } - - const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (data + hdr_size), false); } - - void Describe(ODesc* d) const; - - bool Serialize(SerialInfo* info) const; - static Packet* Unserialize(UnserialInfo* info); - - std::string tag; /// Used in serialization - double time; /// Timestamp reconstituted as float - - struct timeval ts; /// Capture timestamp - const u_char* data; /// Packet data. - uint32 link_type; /// pcap link_type (DLT_EN10MB, DLT_RAW, etc) - uint32 cap_len; /// Captured packet length - uint32 len; /// Actual length on wire - uint32 hdr_size; /// Layer 2 header size - Layer3Proto l3_proto; /// Layer 3 protocol identified (if any) - uint32 eth_type; /// If L2==ethernet, innermost ethertype field - uint32 vlan; /// (Outermost) VLan tag if any, else 0 - -private: - // should we delete associated packet memory upon destruction. - bool free; -}; - -#endif // packet_h diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 3c0dec4f20..44ec678a0f 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -200,7 +200,7 @@ extern "C" { // Gets incremented each time there's an incompatible change // to the communication internals. -static const unsigned short PROTOCOL_VERSION = 0x08; +static const unsigned short PROTOCOL_VERSION = 0x07; static const char MSG_NONE = 0x00; static const char MSG_VERSION = 0x01; diff --git a/src/Serializer.cc b/src/Serializer.cc index d45e572611..554e8b36b6 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1136,9 +1136,7 @@ bool Packet::Serialize(SerialInfo* info) const return SERIALIZE(uint32(ts.tv_sec)) && SERIALIZE(uint32(ts.tv_usec)) && SERIALIZE(uint32(len)) && - SERIALIZE(uint32(link_type)) && - SERIALIZE(uint32(hdr_size)) && - SERIALIZE(uint32(l3_proto)) && + SERIALIZE(link_type) && info->s->Write(tag.c_str(), tag.length(), "tag") && info->s->Write((const char*)data, cap_len, "data"); } @@ -1152,14 +1150,12 @@ static iosource::PktDumper* dump = 0; Packet* Packet::Unserialize(UnserialInfo* info) { struct timeval ts; - uint32 len, link_type, hdr_size, l3_proto; + uint32 len, link_type; if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) && UNSERIALIZE((uint32 *)&ts.tv_usec) && UNSERIALIZE(&len) && - UNSERIALIZE(&link_type) && - UNSERIALIZE(&hdr_size) && - UNSERIALIZE(&l3_proto)) ) + UNSERIALIZE(&link_type)) ) return 0; char* tag; @@ -1175,7 +1171,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) } Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, - std::string(tag), hdr_size, (Layer3Proto) l3_proto); + std::string(tag)); delete [] tag; // For the global timer manager, we take the global network_time as the diff --git a/src/Sessions.cc b/src/Sessions.cc index db1944634a..19f4f6104f 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -15,7 +15,7 @@ #include "Sessions.h" #include "Reporter.h" #include "OSFinger.h" -#include "Layer2.h" +#include "iosource/Layer2.h" #include "analyzer/protocol/icmp/ICMP.h" #include "analyzer/protocol/udp/UDP.h" @@ -169,11 +169,8 @@ void NetSessions::Done() void NetSessions::DispatchPacket(double t, const Packet* pkt, iosource::PktSrc* src_ps) { - NextPacket(t, pkt); - } + SegmentProfiler(segment_logger, "dispatching-packet"); -void NetSessions::NextPacket(double t, const Packet* pkt) - { if ( raw_packet ) { val_list* vl = new val_list(); @@ -185,9 +182,6 @@ void NetSessions::NextPacket(double t, const Packet* pkt) ProcNextPacket(t, pkt); } -void NetSessions::ProcNextPacket(double t, const Packet *pkt) - { - SegmentProfiler(segment_logger, "processing-packet"); if ( pkt_profiler ) pkt_profiler->ProfilePkt(t, pkt->cap_len); @@ -804,7 +798,7 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, // Construct fake packet for DoNextPacket Packet p; - p.Init(DLT_RAW, &ts, caplen, len, data, false, "", 0, l3_proto); + p.Init(DLT_RAW, &ts, caplen, len, data, false, ""); DoNextPacket(t, &p, inner, outer); delete inner; diff --git a/src/Sessions.h b/src/Sessions.h index 51539c42ef..6561b555e7 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -214,10 +214,6 @@ protected: TransportProto transport_proto, uint8 tcp_flags, bool& flip_roles); - void NextPacket(double t, const Packet* pkt); - - void ProcNextPacket(double t, const Packet *pkt); - // Record the given packet (if a dumper is active). If len=0 // then the whole packet is recorded, otherwise just the first // len bytes. diff --git a/src/analyzer/protocol/arp/ARP.h b/src/analyzer/protocol/arp/ARP.h index d0b035ef24..1778f5e200 100644 --- a/src/analyzer/protocol/arp/ARP.h +++ b/src/analyzer/protocol/arp/ARP.h @@ -24,7 +24,8 @@ #endif #include "NetVar.h" -#include "Packet.h" + +class Packet; extern "C" { #include diff --git a/src/bro.bif b/src/bro.bif index 9d3a2c42a8..629abe7735 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -20,9 +20,9 @@ #include "Reporter.h" #include "IPAddr.h" #include "util.h" -#include "Packet.h" #include "file_analysis/Manager.h" #include "iosource/Manager.h" +#include "iosource/Packet.h" using namespace std; diff --git a/src/event.bif b/src/event.bif index 7ba6fc2e1e..456de20b3a 100644 --- a/src/event.bif +++ b/src/event.bif @@ -225,21 +225,21 @@ event udp_session_done%(u: connection%); ## ``ANALYZER_*`` constants right now. event scheduled_analyzer_applied%(c: connection, a: Analyzer::Tag%); -## Generated for every packet Bro sees that has a valid link-layer header. This +## Generated for every packet Bro sees that have a valid link-layer header. This ## is a very very low-level and expensive event that should be avoided when at all ## possible. It's usually infeasible to handle when processing even medium volumes ## of traffic in real-time. That said, if you work from a trace and want to do some -## packet-level analysis, it may come in handy. +## packet-level analysis, it may come in handy. ## ## p: Information from the header of the packet that triggered the event. ## ## .. bro:see:: new_packet packet_contents event raw_packet%(p: raw_pkt_hdr%); -## Generated for all packets that make it into Bro's connection processing . In -## contrast to :bro:id:`raw_packet` this filters out some packets that, e.g., don't -## pass certain sanity checks. -## +## Generated for all packets that make it into Bro's connection processing. In +## contrast to :bro:id:`raw_packet` this filters out some more packets that don't +## pass certain sanity checks. +## ## This is a very low-level and expensive event that should be avoided when at all ## possible. It's usually infeasible to handle when processing even medium volumes ## of traffic in real-time. That said, if you work from a trace and want to do some diff --git a/src/iosource/CMakeLists.txt b/src/iosource/CMakeLists.txt index a36667aee7..b08e62334a 100644 --- a/src/iosource/CMakeLists.txt +++ b/src/iosource/CMakeLists.txt @@ -11,7 +11,9 @@ add_subdirectory(pcap) set(iosource_SRCS BPF_Program.cc Component.cc + Layer2.cc Manager.cc + Packet.cc PktDumper.cc PktSrc.cc ) diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index e22f8da6dd..8012f79f1b 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -17,7 +17,6 @@ PktSrc::Properties::Properties() { selectable_fd = -1; link_type = -1; - hdr_size = -1; netmask = NETMASK_UNKNOWN; is_live = false; } @@ -67,11 +66,6 @@ bool PktSrc::IsError() const return ErrorMsg(); } -int PktSrc::HdrSize() const - { - return IsOpen() ? props.hdr_size : -1; - } - int PktSrc::SnapLen() const { return snaplen; // That's a global. Change? @@ -98,7 +92,7 @@ double PktSrc::CurrentPacketWallClock() void PktSrc::Opened(const Properties& arg_props) { - if ( arg_props.hdr_size < 0 ) + if ( Packet::GetLinkHeaderSize(arg_props.link_type) < 0 ) { char buf[512]; safe_snprintf(buf, sizeof(buf), @@ -160,33 +154,6 @@ void PktSrc::ContinueAfterSuspend() current_wallclock = current_time(true); } -int PktSrc::GetLinkHeaderSize(int link_type) - { - switch ( link_type ) { - case DLT_NULL: - return 4; - - case DLT_EN10MB: - return 14; - - case DLT_FDDI: - return 13 + 8; // fddi_header + LLC - -#ifdef DLT_LINUX_SLL - case DLT_LINUX_SLL: - return 16; -#endif - - case DLT_PPP_SERIAL: // PPP_SERIAL - return 4; - - case DLT_RAW: - return 0; - } - - return -1; - } - double PktSrc::CheckPseudoTime() { if ( ! IsOpen() ) @@ -284,249 +251,20 @@ void PktSrc::Process() if ( ! ExtractNextPacketInternal() ) return; - // Unfortunately some packets on the link might have MPLS labels - // while others don't. That means we need to ask the link-layer if - // labels are in place. - bool have_mpls = false; - - Layer3Proto l3_proto = L3_UNKNOWN; - const u_char* data = current_packet.data; - - current_packet.link_type = props.link_type; - - switch ( props.link_type ) { - case DLT_NULL: + if ( current_packet.Layer2Valid() ) { - int protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; - data += GetLinkHeaderSize(props.link_type); + if ( pseudo_realtime ) + { + current_pseudo = CheckPseudoTime(); + net_packet_dispatch(current_pseudo, ¤t_packet, this); + if ( ! first_wallclock ) + first_wallclock = current_time(true); + } - // From the Wireshark Wiki: "AF_INET6, unfortunately, has - // different values in {NetBSD,OpenBSD,BSD/OS}, - // {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6 - // packet might have a link-layer header with 24, 28, or 30 - // as the AF_ value." As we may be reading traces captured on - // platforms other than what we're running on, we accept them - // all here. - - if ( protocol == AF_INET ) - l3_proto = L3_IPV4; - else if ( protocol == 24 || protocol == 28 || protocol == 30 ) - l3_proto = L3_IPV6; else - { - Weird("non_ip_packet_in_null_transport", ¤t_packet); - goto done; - } - - break; + net_packet_dispatch(current_packet.time, ¤t_packet, this); } - case DLT_EN10MB: - { - // Get protocol being carried from the ethernet frame. - int protocol = (data[12] << 8) + data[13]; - data += GetLinkHeaderSize(props.link_type); - current_packet.eth_type = protocol; - - switch ( protocol ) - { - // MPLS carried over the ethernet frame. - case 0x8847: - have_mpls = true; - break; - - // VLAN carried over the ethernet frame. - // 802.1q / 802.1ad - case 0x8100: - case 0x9100: - current_packet.vlan = ((data[0] << 8) + data[1]) & 0xfff; - protocol = ((data[2] << 8) + data[3]); - data += 4; // Skip the vlan header - - // Check for MPLS in VLAN. - if ( protocol == 0x8847 ) - { - have_mpls = true; - break; - } - - // Check for double-tagged (802.1ad) - if ( protocol == 0x8100 || protocol == 0x9100 ) - { - protocol = ((data[2] << 8) + data[3]); - data += 4; // Skip the vlan header - } - - current_packet.eth_type = protocol; - break; - - // PPPoE carried over the ethernet frame. - case 0x8864: - protocol = (data[6] << 8) + data[7]; - data += 8; // Skip the PPPoE session and PPP header - - if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_pppoe_encapsulation", ¤t_packet); - goto done; - } - - break; - } - - // Normal path to determine Layer 3 protocol. - if ( ! have_mpls && l3_proto == L3_UNKNOWN ) - { - if ( protocol == 0x800 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x86dd ) - l3_proto = L3_IPV6; - else if ( protocol == 0x0806 || protocol == 0x8035 ) - l3_proto = L3_ARP; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ethernet", ¤t_packet); - goto done; - } - } - - break; - } - - case DLT_PPP_SERIAL: - { - // Get PPP protocol. - int protocol = (data[2] << 8) + data[3]; - data += GetLinkHeaderSize(props.link_type); - - if ( protocol == 0x0281 ) - { - // MPLS Unicast. Remove the data link layer and - // denote a header size of zero before the IP header. - have_mpls = true; - } - else if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ppp_encapsulation", ¤t_packet); - goto done; - } - break; - } - - default: - { - // Assume we're pointing at IP. Just figure out which version. - data += GetLinkHeaderSize(props.link_type); - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet", ¤t_packet); - goto done; - } - - break; - } - } - - if ( have_mpls ) - { - // Skip the MPLS label stack. - bool end_of_stack = false; - - while ( ! end_of_stack ) - { - end_of_stack = *(data + 2) & 0x01; - data += 4; - - if ( data >= current_packet.data + current_packet.cap_len ) - { - Weird("no_mpls_payload", ¤t_packet); - goto done; - } - } - - // We assume that what remains is IP - if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) - { - Weird("no_ip_in_mpls_payload", ¤t_packet); - goto done; - } - - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_mpls_payload", ¤t_packet); - goto done; - } - } - - else if ( encap_hdr_size ) - { - // Blanket encapsulation. We assume that what remains is IP. - data += encap_hdr_size; - if ( data + sizeof(struct ip) >= current_packet.data + current_packet.cap_len ) - { - Weird("no_ip_left_after_encap", ¤t_packet); - goto done; - } - - const struct ip* ip = (const struct ip *)data; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_encap", ¤t_packet); - goto done; - } - - } - - // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs - // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else) - current_packet.l3_proto = l3_proto; - - // Calculate how much header we've used up. - current_packet.hdr_size = (data - current_packet.data); - - if ( pseudo_realtime ) - { - current_pseudo = CheckPseudoTime(); - net_packet_dispatch(current_pseudo, ¤t_packet, this); - if ( ! first_wallclock ) - first_wallclock = current_time(true); - } - - else - net_packet_dispatch(current_packet.time, ¤t_packet, this); - -done: have_packet = 0; DoneWithPacket(); } @@ -556,8 +294,6 @@ bool PktSrc::ExtractNextPacketInternal() if ( ExtractNextPacket(¤t_packet) ) { - current_packet.l3_proto = L3_UNKNOWN; - if ( ! first_timestamp ) first_timestamp = current_packet.time; diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index 0f20bb3a0a..bf4c811dca 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -215,22 +215,6 @@ public: */ virtual void Statistics(Stats* stats) = 0; - /** - * Helper method to return the header size for a given link tyoe. - * - * @param link_type The link tyoe. - * - * @return The header size in bytes. - */ - static int GetLinkHeaderSize(int link_type); - - /** - * Return the pcap link encapsulation type we started with. - * - * @return DLT_EN10MB (etc.) - */ - int GetLinkEncap(void); - protected: friend class Manager; @@ -258,13 +242,6 @@ protected: */ int link_type; - /** - * The size of the link-layer header for packets from this - * source. \a GetLinkHeaderSize() may be used to derive this - * value. - */ - int hdr_size; - /** * Returns the netmask associated with the source, or \c * NETMASK_UNKNOWN if unknown. diff --git a/src/iosource/pcap/Dumper.cc b/src/iosource/pcap/Dumper.cc index e6909f32b1..5bea6231f7 100644 --- a/src/iosource/pcap/Dumper.cc +++ b/src/iosource/pcap/Dumper.cc @@ -79,7 +79,7 @@ void PcapDumper::Open() } props.open_time = network_time; - props.hdr_size = PktSrc::GetLinkHeaderSize(pcap_datalink(pd)); + props.hdr_size = Packet::GetLinkHeaderSize(pcap_datalink(pd)); Opened(props); } diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 45e8c89298..bebe02c018 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -5,6 +5,7 @@ #include "config.h" #include "Source.h" +#include "iosource/Packet.h" #ifdef HAVE_PCAP_INT_H #include @@ -274,7 +275,6 @@ void PcapSource::SetHdrSize() char errbuf[PCAP_ERRBUF_SIZE]; props.link_type = pcap_datalink(pd); - props.hdr_size = GetLinkHeaderSize(props.link_type); } iosource::PktSrc* PcapSource::Instantiate(const std::string& path, bool is_live) diff --git a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc index afd5621d0f..af752a20bf 100644 --- a/testing/btest/plugins/pktsrc-plugin/src/Foo.cc +++ b/testing/btest/plugins/pktsrc-plugin/src/Foo.cc @@ -17,7 +17,6 @@ Foo::Foo(const std::string& path, bool is_live) props.path = path; props.selectable_fd = open("/bin/sh", O_RDONLY); // any fd is fine. props.link_type = DLT_RAW; - props.hdr_size = 0; props.netmask = 0; props.is_live = 0; }