diff --git a/src/packet_analysis/protocol/ip/IP.cc b/src/packet_analysis/protocol/ip/IP.cc index 982cb51f40..1263317317 100644 --- a/src/packet_analysis/protocol/ip/IP.cc +++ b/src/packet_analysis/protocol/ip/IP.cc @@ -47,11 +47,11 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) // data about the header. auto ip = (const struct ip*)data; uint32_t protocol = ip->ip_v; + std::shared_ptr ip_hdr; - // This is a unique pointer because of the mass of early returns from this method. if ( protocol == 4 ) { - packet->ip_hdr = std::make_shared(ip, false); + ip_hdr = std::make_shared(ip, false); packet->l3_proto = L3_IPV4; } else if ( protocol == 6 ) @@ -62,7 +62,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) return false; } - packet->ip_hdr = std::make_shared((const struct ip6_hdr*)data, false, len); + ip_hdr = std::make_shared((const struct ip6_hdr*)data, false, len); packet->l3_proto = L3_IPV6; } else @@ -71,20 +71,9 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) return false; } - // If there's an encapsulation stack in this packet, meaning this packet is part of a chain - // of tunnels, make sure to store the IP header in the last flow in the stack so it can be - // used by previous analyzers as we return up the chain. - if ( packet->encap ) - { - if ( auto* ec = packet->encap->Last() ) - ec->ip_hdr = packet->ip_hdr; - } - - const struct ip* ip4 = packet->ip_hdr->IP4_Hdr(); - // TotalLen() returns the full length of the IP portion of the packet, including // the IP header and payload. - uint32_t total_len = packet->ip_hdr->TotalLen(); + uint32_t total_len = ip_hdr->TotalLen(); if ( total_len == 0 ) { // TCP segmentation offloading can zero out the ip_len field. @@ -107,7 +96,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) // For both of these it is safe to pass ip_hdr because the presence // is guaranteed for the functions that pass data to us. - uint16_t ip_hdr_len = packet->ip_hdr->HdrLen(); + uint16_t ip_hdr_len = ip_hdr->HdrLen(); if ( ip_hdr_len > total_len ) { Weird("invalid_IP_header_size", packet); @@ -120,7 +109,9 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) return false; } - if ( packet->ip_hdr->IP4_Hdr() ) + const struct ip* ip4 = ip_hdr->IP4_Hdr(); + + if ( ip4 ) { if ( ip_hdr_len < sizeof(struct ip) ) { @@ -137,6 +128,18 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) } } + // If we got here, the IP_Hdr is most likely valid and safe to use. + packet->ip_hdr = ip_hdr; + + // If there's an encapsulation stack in this packet, meaning this packet is part of a chain + // of tunnels, make sure to store the IP header in the last flow in the stack so it can be + // used by previous analyzers as we return up the chain. + if ( packet->encap ) + { + if ( auto* ec = packet->encap->Last() ) + ec->ip_hdr = packet->ip_hdr; + } + // Ignore if packet matches packet filter. detail::PacketFilter* packet_filter = packet_mgr->GetPacketFilter(false); if ( packet_filter && packet_filter->Match(packet->ip_hdr, total_len, len) )