Determining final L3 layer protocol right inside PktSrc.

This commit is contained in:
Robin Sommer 2015-07-17 14:22:50 -07:00
parent 86440e44fc
commit 64a478dbd5
6 changed files with 41 additions and 55 deletions

View file

@ -3,6 +3,14 @@
#include "Desc.h" #include "Desc.h"
#include "IP.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. // A link-layer packet.
// //
@ -26,7 +34,7 @@ public:
Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, Packet(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen,
uint32 arg_len, const u_char *arg_data, int arg_free = false, uint32 arg_len, const u_char *arg_data, int arg_free = false,
std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0,
int arg_l3_proto = -1) Layer3Proto arg_l3_proto = L3_UNKNOWN)
{ {
Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag, Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag,
arg_hdrsize, arg_l3_proto); arg_hdrsize, arg_l3_proto);
@ -45,7 +53,7 @@ public:
void Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen, 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, uint32 arg_len, const u_char *arg_data, int arg_free = false,
std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0, std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0,
int arg_l3_proto = -1) Layer3Proto arg_l3_proto = L3_UNKNOWN)
{ {
link_type = arg_link_type; link_type = arg_link_type;
ts = *arg_ts; ts = *arg_ts;
@ -86,7 +94,7 @@ public:
uint32 cap_len; /// Captured packet length uint32 cap_len; /// Captured packet length
uint32 len; /// Actual length on wire uint32 len; /// Actual length on wire
uint32 hdr_size; /// Layer 2 header size uint32 hdr_size; /// Layer 2 header size
uint32 l3_proto; /// Layer 3 protocol identified (if any) Layer3Proto l3_proto; /// Layer 3 protocol identified (if any)
uint32 eth_type; /// If L2==ethernet, innermost ethertype field uint32 eth_type; /// If L2==ethernet, innermost ethertype field
uint32 vlan; /// (Outermost) VLan tag if any, else 0 uint32 vlan; /// (Outermost) VLan tag if any, else 0

View file

@ -1175,7 +1175,7 @@ Packet* Packet::Unserialize(UnserialInfo* info)
} }
Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true, Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true,
std::string(tag), hdr_size, l3_proto); std::string(tag), hdr_size, (Layer3Proto) l3_proto);
delete [] tag; delete [] tag;
// For the global timer manager, we take the global network_time as the // For the global timer manager, we take the global network_time as the

View file

@ -206,7 +206,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt)
uint32 caplen = pkt->cap_len - pkt->hdr_size; uint32 caplen = pkt->cap_len - pkt->hdr_size;
if ( pkt->l3_proto == AF_INET ) if ( pkt->l3_proto == L3_IPV4 )
{ {
if ( caplen < sizeof(struct ip) ) if ( caplen < sizeof(struct ip) )
{ {
@ -219,7 +219,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt)
DoNextPacket(t, pkt, &ip_hdr, 0); DoNextPacket(t, pkt, &ip_hdr, 0);
} }
else if ( pkt->l3_proto == AF_INET6 ) else if ( pkt->l3_proto == L3_IPV6 )
{ {
if ( caplen < sizeof(struct ip6_hdr) ) if ( caplen < sizeof(struct ip6_hdr) )
{ {
@ -231,7 +231,7 @@ void NetSessions::ProcNextPacket(double t, const Packet *pkt)
DoNextPacket(t, pkt, &ip_hdr, 0); DoNextPacket(t, pkt, &ip_hdr, 0);
} }
else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt) ) else if ( pkt->l3_proto == L3_ARP )
{ {
if ( arp_analyzer ) if ( arp_analyzer )
arp_analyzer->NextPacket(t, pkt); arp_analyzer->NextPacket(t, pkt);
@ -774,7 +774,7 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt,
struct timeval ts; struct timeval ts;
int link_type; int link_type;
int l3_proto; Layer3Proto l3_proto;
if ( pkt ) if ( pkt )
ts = pkt->ts; ts = pkt->ts;
@ -790,12 +790,12 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt,
if ( inner->IP4_Hdr() ) if ( inner->IP4_Hdr() )
{ {
data = (const u_char*) inner->IP4_Hdr(); data = (const u_char*) inner->IP4_Hdr();
l3_proto = AF_INET; l3_proto = L3_IPV4;
} }
else else
{ {
data = (const u_char*) inner->IP6_Hdr(); data = (const u_char*) inner->IP6_Hdr();
l3_proto = AF_INET6; l3_proto = L3_IPV6;
} }
EncapsulationStack* outer = prev ? EncapsulationStack* outer = prev ?

View file

@ -19,25 +19,6 @@ ARP_Analyzer::~ARP_Analyzer()
{ {
} }
// Assumes pkt->hdr_size indicates size of the Layer 2 header.
bool ARP_Analyzer::IsARP(const Packet* pkt)
{
if ( pkt->hdr_size < 2 )
return false;
unsigned short network_protocol =
*(unsigned short*) (pkt->data + pkt->hdr_size - 2);
switch ( ntohs(network_protocol) ) {
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
return true;
default:
return false;
}
}
// Argh! FreeBSD and Linux have almost completely different net/if_arp.h . // Argh! FreeBSD and Linux have almost completely different net/if_arp.h .
// ... and on Solaris we are missing half of the ARPOP codes, so define // ... and on Solaris we are missing half of the ARPOP codes, so define
// them here as necessary: // them here as necessary:

View file

@ -44,9 +44,6 @@ public:
const char* spa, const char* sha, const char* spa, const char* sha,
const char* tpa, const char* tha); const char* tpa, const char* tha);
// Whether a packet is of interest for ARP analysis.
static bool IsARP(const Packet *pkt);
protected: protected:
AddrVal* ConstructAddrVal(const void* addr); AddrVal* ConstructAddrVal(const void* addr);
StringVal* EthAddrToStr(const u_char* addr); StringVal* EthAddrToStr(const u_char* addr);

View file

@ -289,7 +289,7 @@ void PktSrc::Process()
// labels are in place. // labels are in place.
bool have_mpls = false; bool have_mpls = false;
int l3_proto = AF_UNSPEC; Layer3Proto l3_proto = L3_UNKNOWN;
const u_char* data = current_packet.data; const u_char* data = current_packet.data;
current_packet.link_type = props.link_type; current_packet.link_type = props.link_type;
@ -307,16 +307,17 @@ void PktSrc::Process()
// as the AF_ value." As we may be reading traces captured on // as the AF_ value." As we may be reading traces captured on
// platforms other than what we're running on, we accept them // platforms other than what we're running on, we accept them
// all here. // all here.
if ( protocol == 24 || protocol == 28 || protocol == 30 )
protocol = AF_INET6;
if ( protocol != AF_INET && protocol != AF_INET6 ) 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", &current_packet); Weird("non_ip_packet_in_null_transport", &current_packet);
goto done; goto done;
} }
l3_proto = protocol;
break; break;
} }
@ -365,9 +366,9 @@ void PktSrc::Process()
data += 8; // Skip the PPPoE session and PPP header data += 8; // Skip the PPPoE session and PPP header
if ( protocol == 0x0021 ) if ( protocol == 0x0021 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( protocol == 0x0057 ) else if ( protocol == 0x0057 )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -379,14 +380,14 @@ void PktSrc::Process()
} }
// Normal path to determine Layer 3 protocol. // Normal path to determine Layer 3 protocol.
if ( ! have_mpls && ! l3_proto ) if ( ! have_mpls && l3_proto == L3_UNKNOWN )
{ {
if ( protocol == 0x800 ) if ( protocol == 0x800 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( protocol == 0x86dd ) else if ( protocol == 0x86dd )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else if ( protocol == 0x0806 || protocol == 0x8035 ) else if ( protocol == 0x0806 || protocol == 0x8035 )
l3_proto = AF_UNSPEC; l3_proto = L3_ARP;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -411,9 +412,9 @@ void PktSrc::Process()
have_mpls = true; have_mpls = true;
} }
else if ( protocol == 0x0021 ) else if ( protocol == 0x0021 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( protocol == 0x0057 ) else if ( protocol == 0x0057 )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -430,9 +431,9 @@ void PktSrc::Process()
const struct ip* ip = (const struct ip *)data; const struct ip* ip = (const struct ip *)data;
if ( ip->ip_v == 4 ) if ( ip->ip_v == 4 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( ip->ip_v == 6 ) else if ( ip->ip_v == 6 )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -471,9 +472,9 @@ void PktSrc::Process()
const struct ip* ip = (const struct ip *)data; const struct ip* ip = (const struct ip *)data;
if ( ip->ip_v == 4 ) if ( ip->ip_v == 4 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( ip->ip_v == 6 ) else if ( ip->ip_v == 6 )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -495,9 +496,9 @@ void PktSrc::Process()
const struct ip* ip = (const struct ip *)data; const struct ip* ip = (const struct ip *)data;
if ( ip->ip_v == 4 ) if ( ip->ip_v == 4 )
l3_proto = AF_INET; l3_proto = L3_IPV4;
else if ( ip->ip_v == 6 ) else if ( ip->ip_v == 6 )
l3_proto = AF_INET6; l3_proto = L3_IPV6;
else else
{ {
// Neither IPv4 nor IPv6. // Neither IPv4 nor IPv6.
@ -507,9 +508,8 @@ void PktSrc::Process()
} }
// We've now determined (a) AF_INET (IPv4) vs (b) AF_INET6 (IPv6) vs // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs
// (c) AF_UNSPEC (0 == anything else) // (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else)
assert(l3_proto == AF_INET || l3_proto == AF_INET6 || l3_proto == AF_UNSPEC);
current_packet.l3_proto = l3_proto; current_packet.l3_proto = l3_proto;
// Calculate how much header we've used up. // Calculate how much header we've used up.
@ -556,7 +556,7 @@ bool PktSrc::ExtractNextPacketInternal()
if ( ExtractNextPacket(&current_packet) ) if ( ExtractNextPacket(&current_packet) )
{ {
current_packet.l3_proto = AF_UNSPEC; current_packet.l3_proto = L3_UNKNOWN;
if ( ! first_timestamp ) if ( ! first_timestamp )
first_timestamp = current_packet.time; first_timestamp = current_packet.time;