mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 17:18:20 +00:00
Moving the remaining code from Layer2.* into Packet.* and documenting
the Packet API. Plus, some more cleanup, including removing a legacy option time_machine_profiling.
This commit is contained in:
parent
f69edd1437
commit
f97b2b180c
11 changed files with 350 additions and 326 deletions
|
@ -270,7 +270,7 @@ void net_packet_dispatch(double t, const Packet* pkt, iosource::PktSrc* src_ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sessions->DispatchPacket(t, pkt, src_ps);
|
sessions->NextPacket(t, pkt);
|
||||||
mgr.Drain();
|
mgr.Drain();
|
||||||
|
|
||||||
if ( sp )
|
if ( sp )
|
||||||
|
|
|
@ -226,8 +226,6 @@ int suppress_local_output;
|
||||||
|
|
||||||
double timer_mgr_inactivity_timeout;
|
double timer_mgr_inactivity_timeout;
|
||||||
|
|
||||||
int time_machine_profiling;
|
|
||||||
|
|
||||||
StringVal* trace_output_file;
|
StringVal* trace_output_file;
|
||||||
|
|
||||||
int record_all_packets;
|
int record_all_packets;
|
||||||
|
@ -522,7 +520,6 @@ void init_net_var()
|
||||||
|
|
||||||
timer_mgr_inactivity_timeout =
|
timer_mgr_inactivity_timeout =
|
||||||
opt_internal_double("timer_mgr_inactivity_timeout");
|
opt_internal_double("timer_mgr_inactivity_timeout");
|
||||||
time_machine_profiling = opt_internal_int("time_machine_profiling");
|
|
||||||
|
|
||||||
script_id = internal_type("script_id")->AsRecordType();
|
script_id = internal_type("script_id")->AsRecordType();
|
||||||
id_table = internal_type("id_table")->AsTableType();
|
id_table = internal_type("id_table")->AsTableType();
|
||||||
|
|
|
@ -230,8 +230,6 @@ extern int suppress_local_output;
|
||||||
|
|
||||||
extern double timer_mgr_inactivity_timeout;
|
extern double timer_mgr_inactivity_timeout;
|
||||||
|
|
||||||
extern int time_machine_profiling;
|
|
||||||
|
|
||||||
extern StringVal* trace_output_file;
|
extern StringVal* trace_output_file;
|
||||||
|
|
||||||
extern int record_all_packets;
|
extern int record_all_packets;
|
||||||
|
|
|
@ -1122,87 +1122,3 @@ void EventPlayer::Process()
|
||||||
|
|
||||||
ne_time = 0;
|
ne_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::Describe(ODesc* d) const
|
|
||||||
{
|
|
||||||
const IP_Hdr ip = IP();
|
|
||||||
d->Add(ip.SrcAddr());
|
|
||||||
d->Add("->");
|
|
||||||
d->Add(ip.DstAddr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Packet::Serialize(SerialInfo* info) const
|
|
||||||
{
|
|
||||||
return SERIALIZE(uint32(ts.tv_sec)) &&
|
|
||||||
SERIALIZE(uint32(ts.tv_usec)) &&
|
|
||||||
SERIALIZE(uint32(len)) &&
|
|
||||||
SERIALIZE(link_type) &&
|
|
||||||
info->s->Write(tag.c_str(), tag.length(), "tag") &&
|
|
||||||
info->s->Write((const char*)data, cap_len, "data");
|
|
||||||
}
|
|
||||||
|
|
||||||
static BroFile* profiling_output = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static iosource::PktDumper* dump = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Packet* Packet::Unserialize(UnserialInfo* info)
|
|
||||||
{
|
|
||||||
struct timeval ts;
|
|
||||||
uint32 len, link_type;
|
|
||||||
|
|
||||||
if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) &&
|
|
||||||
UNSERIALIZE((uint32 *)&ts.tv_usec) &&
|
|
||||||
UNSERIALIZE(&len) &&
|
|
||||||
UNSERIALIZE(&link_type)) )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char* tag;
|
|
||||||
if ( ! info->s->Read((char**) &tag, 0, "tag") )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const u_char* pkt;
|
|
||||||
int caplen;
|
|
||||||
if ( ! info->s->Read((char**) &pkt, &caplen, "data") )
|
|
||||||
{
|
|
||||||
delete [] tag;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true,
|
|
||||||
std::string(tag));
|
|
||||||
delete [] tag;
|
|
||||||
|
|
||||||
// For the global timer manager, we take the global network_time as the
|
|
||||||
// packet's timestamp for feeding it into our packet loop.
|
|
||||||
if ( p->tag == "" )
|
|
||||||
p->time = timer_mgr->Time();
|
|
||||||
else
|
|
||||||
p->time = p->ts.tv_sec + double(p->ts.tv_usec) / 1e6;
|
|
||||||
|
|
||||||
if ( time_machine_profiling )
|
|
||||||
{
|
|
||||||
if ( ! profiling_output )
|
|
||||||
profiling_output =
|
|
||||||
new BroFile("tm-prof.packets.log", "w");
|
|
||||||
|
|
||||||
profiling_output->Write(fmt("%.6f %s %d\n", current_time(),
|
|
||||||
(p->tag != "" ? p->tag.c_str() : "-"), p->len));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if ( debug_logger.IsEnabled(DBG_TM) )
|
|
||||||
{
|
|
||||||
if ( ! dump )
|
|
||||||
dump = iosource_mgr->OpenPktDumper("tm.pcap", true);
|
|
||||||
|
|
||||||
if ( dump )
|
|
||||||
{
|
|
||||||
dump->Dump(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "Sessions.h"
|
#include "Sessions.h"
|
||||||
#include "Reporter.h"
|
#include "Reporter.h"
|
||||||
#include "OSFinger.h"
|
#include "OSFinger.h"
|
||||||
#include "iosource/Layer2.h"
|
|
||||||
|
|
||||||
#include "analyzer/protocol/icmp/ICMP.h"
|
#include "analyzer/protocol/icmp/ICMP.h"
|
||||||
#include "analyzer/protocol/udp/UDP.h"
|
#include "analyzer/protocol/udp/UDP.h"
|
||||||
|
@ -166,22 +165,17 @@ void NetSessions::Done()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetSessions::DispatchPacket(double t, const Packet* pkt,
|
void NetSessions::NextPacket(double t, const Packet* pkt)
|
||||||
iosource::PktSrc* src_ps)
|
|
||||||
{
|
{
|
||||||
SegmentProfiler(segment_logger, "dispatching-packet");
|
SegmentProfiler(segment_logger, "dispatching-packet");
|
||||||
|
|
||||||
if ( raw_packet )
|
if ( raw_packet )
|
||||||
{
|
{
|
||||||
val_list* vl = new val_list();
|
val_list* vl = new val_list();
|
||||||
L2_Hdr l2_hdr(pkt);
|
vl->append(pkt->BuildPktHdrVal());
|
||||||
vl->append(l2_hdr.BuildPktHdrVal());
|
|
||||||
mgr.QueueEvent(raw_packet, vl);
|
mgr.QueueEvent(raw_packet, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcNextPacket(t, pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pkt_profiler )
|
if ( pkt_profiler )
|
||||||
pkt_profiler->ProfilePkt(t, pkt->cap_len);
|
pkt_profiler->ProfilePkt(t, pkt->cap_len);
|
||||||
|
|
||||||
|
|
|
@ -66,11 +66,8 @@ public:
|
||||||
NetSessions();
|
NetSessions();
|
||||||
~NetSessions();
|
~NetSessions();
|
||||||
|
|
||||||
// Main entry point for packet processing. Dispatches the packet
|
// Main entry point for packet processing.
|
||||||
// either through NextPacket(), optionally employing the packet
|
void NextPacket(double t, const Packet* pkt);
|
||||||
// sorter first.
|
|
||||||
void DispatchPacket(double t, const Packet* pkt,
|
|
||||||
iosource::PktSrc* src_ps);
|
|
||||||
|
|
||||||
void Done(); // call to drain events before destructing
|
void Done(); // call to drain events before destructing
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ add_subdirectory(pcap)
|
||||||
set(iosource_SRCS
|
set(iosource_SRCS
|
||||||
BPF_Program.cc
|
BPF_Program.cc
|
||||||
Component.cc
|
Component.cc
|
||||||
Layer2.cc
|
|
||||||
Manager.cc
|
Manager.cc
|
||||||
Packet.cc
|
Packet.cc
|
||||||
PktDumper.cc
|
PktDumper.cc
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
|
||||||
|
|
||||||
#include "IP.h"
|
|
||||||
#include "Type.h"
|
|
||||||
#include "Val.h"
|
|
||||||
#include "Var.h"
|
|
||||||
#include "NetVar.h"
|
|
||||||
#include "iosource/Layer2.h"
|
|
||||||
#include "iosource/Packet.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <pcap.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#ifdef HAVE_NET_ETHERNET_H
|
|
||||||
#include <net/ethernet.h>
|
|
||||||
#elif defined(HAVE_SYS_ETHERNET_H)
|
|
||||||
#include <sys/ethernet.h>
|
|
||||||
#elif defined(HAVE_NETINET_IF_ETHER_H)
|
|
||||||
#include <netinet/if_ether.h>
|
|
||||||
#elif defined(HAVE_NET_ETHERTYPES_H)
|
|
||||||
#include <net/ethertypes.h>
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Val *L2_Hdr::fmt_eui48(const u_char *mac) const
|
|
||||||
{
|
|
||||||
char buf[20];
|
|
||||||
snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
return new StringVal(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordVal* L2_Hdr::BuildPktHdrVal() const
|
|
||||||
{
|
|
||||||
static RecordType* l2_hdr_type = 0;
|
|
||||||
static RecordType* raw_pkt_hdr_type = 0;
|
|
||||||
|
|
||||||
if ( ! raw_pkt_hdr_type )
|
|
||||||
{
|
|
||||||
raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType();
|
|
||||||
l2_hdr_type = internal_type("l2_hdr")->AsRecordType();
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type);
|
|
||||||
RecordVal* l2_hdr = new RecordVal(l2_hdr_type);
|
|
||||||
|
|
||||||
int is_ethernet = (pkt->link_type == DLT_EN10MB) ? 1 : 0;
|
|
||||||
|
|
||||||
int l3 = BifEnum::L3_UNKNOWN;
|
|
||||||
|
|
||||||
if ( pkt->l3_proto == L3_IPV4 )
|
|
||||||
l3 = BifEnum::L3_IPV4;
|
|
||||||
|
|
||||||
else if ( pkt->l3_proto == L3_IPV6 )
|
|
||||||
l3 = BifEnum::L3_IPV6;
|
|
||||||
|
|
||||||
else if ( pkt->l3_proto == L3_ARP )
|
|
||||||
l3 = BifEnum::L3_ARP;
|
|
||||||
|
|
||||||
// l2_hdr layout:
|
|
||||||
// encap: link_encap; ##< L2 link encapsulation
|
|
||||||
// len: count; ##< Total frame length on wire
|
|
||||||
// cap_len: count; ##< Captured length
|
|
||||||
// src: string &optional; ##< L2 source (if ethernet)
|
|
||||||
// dst: string &optional; ##< L2 destination (if ethernet)
|
|
||||||
// vlan: count &optional; ##< VLAN tag if any (and ethernet)
|
|
||||||
// ethertype: count &optional; ##< If ethernet
|
|
||||||
// proto: layer3_proto; ##< L3 proto
|
|
||||||
|
|
||||||
if ( is_ethernet )
|
|
||||||
{
|
|
||||||
// Ethernet header layout is:
|
|
||||||
// dst[6bytes] src[6bytes] ethertype[2bytes]...
|
|
||||||
l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_ETHERNET, BifType::Enum::link_encap));
|
|
||||||
l2_hdr->Assign(3, fmt_eui48(pkt->data + 6)); // src
|
|
||||||
l2_hdr->Assign(4, fmt_eui48(pkt->data)); // dst
|
|
||||||
|
|
||||||
if ( pkt->vlan )
|
|
||||||
l2_hdr->Assign(5, new Val(pkt->vlan, TYPE_COUNT));
|
|
||||||
|
|
||||||
l2_hdr->Assign(6, new Val(pkt->eth_type, TYPE_COUNT));
|
|
||||||
|
|
||||||
if ( pkt->eth_type == ETHERTYPE_ARP || pkt->eth_type == ETHERTYPE_REVARP )
|
|
||||||
// We also identify ARP for L3 over ethernet
|
|
||||||
l3 = BifEnum::L3_ARP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_UNKNOWN, BifType::Enum::link_encap));
|
|
||||||
|
|
||||||
l2_hdr->Assign(1, new Val(pkt->len, TYPE_COUNT));
|
|
||||||
l2_hdr->Assign(2, new Val(pkt->cap_len, TYPE_COUNT));
|
|
||||||
|
|
||||||
l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto));
|
|
||||||
|
|
||||||
pkt_hdr->Assign(0, l2_hdr);
|
|
||||||
|
|
||||||
if ( pkt->l3_proto == L3_IPV4 )
|
|
||||||
{
|
|
||||||
IP_Hdr ip_hdr((const struct ip*)(pkt->data + pkt->hdr_size), false);
|
|
||||||
return ip_hdr.BuildPktHdrVal(pkt_hdr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( pkt->l3_proto == L3_IPV6 )
|
|
||||||
{
|
|
||||||
IP_Hdr ip6_hdr((const struct ip6_hdr*)(pkt->data + pkt->hdr_size), false, pkt->cap_len);
|
|
||||||
return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
return pkt_hdr;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef l2_h
|
|
||||||
#define l2_h
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "net_util.h"
|
|
||||||
#include "IP.h"
|
|
||||||
#include "Reporter.h"
|
|
||||||
#include "Val.h"
|
|
||||||
#include "Type.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Packet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class that wraps an L2 packet.
|
|
||||||
*/
|
|
||||||
class L2_Hdr {
|
|
||||||
public:
|
|
||||||
L2_Hdr(const Packet *arg_pkt) : pkt(arg_pkt) { }
|
|
||||||
~L2_Hdr() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a raw_pkt_hdr RecordVal, which includes L2 and also
|
|
||||||
* everything in IP_Hdr (i.e. IP4/6 + tcp/udp/icmp)
|
|
||||||
*/
|
|
||||||
RecordVal* BuildPktHdrVal() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Val *fmt_eui48(const u_char *mac) const;
|
|
||||||
const Packet *pkt;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,54 @@
|
||||||
|
|
||||||
#include "Packet.h"
|
#include "Packet.h"
|
||||||
#include "Sessions.h"
|
#include "Sessions.h"
|
||||||
|
#include "iosource/Manager.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#ifdef HAVE_NET_ETHERNET_H
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#elif defined(HAVE_SYS_ETHERNET_H)
|
||||||
|
#include <sys/ethernet.h>
|
||||||
|
#elif defined(HAVE_NETINET_IF_ETHER_H)
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
#elif defined(HAVE_NET_ETHERTYPES_H)
|
||||||
|
#include <net/ethertypes.h>
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::Init(int arg_link_type, struct timeval *arg_ts, uint32 arg_caplen,
|
||||||
|
uint32 arg_len, const u_char *arg_data, int arg_copy,
|
||||||
|
std::string arg_tag)
|
||||||
|
{
|
||||||
|
if ( data && copy )
|
||||||
|
delete [] data;
|
||||||
|
|
||||||
|
link_type = arg_link_type;
|
||||||
|
ts = *arg_ts;
|
||||||
|
cap_len = arg_caplen;
|
||||||
|
len = arg_len;
|
||||||
|
tag = arg_tag;
|
||||||
|
|
||||||
|
copy = arg_copy;
|
||||||
|
|
||||||
|
if ( arg_data && arg_copy )
|
||||||
|
{
|
||||||
|
data = new u_char[arg_caplen];
|
||||||
|
memcpy(const_cast<u_char *>(data), arg_data, arg_caplen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data = arg_data;
|
||||||
|
|
||||||
|
time = ts.tv_sec + double(ts.tv_usec) / 1e6;
|
||||||
|
hdr_size = GetLinkHeaderSize(arg_link_type);
|
||||||
|
l3_proto = L3_UNKNOWN;
|
||||||
|
eth_type = 0;
|
||||||
|
vlan = 0;
|
||||||
|
|
||||||
|
l2_valid = false;
|
||||||
|
|
||||||
|
if ( data )
|
||||||
|
ProcessLayer2();
|
||||||
|
}
|
||||||
|
|
||||||
void Packet::Weird(const char* name)
|
void Packet::Weird(const char* name)
|
||||||
{
|
{
|
||||||
|
@ -261,10 +309,169 @@ void Packet::ProcessLayer2()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs
|
// We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs
|
||||||
// (c) L3_ARP vs (d) L3_UNKNOWN (0 == anything else)
|
// (c) L3_ARP vs (d) L3_UNKNOWN.
|
||||||
l3_proto = l3_proto;
|
l3_proto = l3_proto;
|
||||||
|
|
||||||
// Calculate how much header we've used up.
|
// Calculate how much header we've used up.
|
||||||
hdr_size = (pdata - data);
|
hdr_size = (pdata - data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordVal* Packet::BuildPktHdrVal() const
|
||||||
|
{
|
||||||
|
static RecordType* l2_hdr_type = 0;
|
||||||
|
static RecordType* raw_pkt_hdr_type = 0;
|
||||||
|
|
||||||
|
if ( ! raw_pkt_hdr_type )
|
||||||
|
{
|
||||||
|
raw_pkt_hdr_type = internal_type("raw_pkt_hdr")->AsRecordType();
|
||||||
|
l2_hdr_type = internal_type("l2_hdr")->AsRecordType();
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordVal* pkt_hdr = new RecordVal(raw_pkt_hdr_type);
|
||||||
|
RecordVal* l2_hdr = new RecordVal(l2_hdr_type);
|
||||||
|
|
||||||
|
int is_ethernet = (link_type == DLT_EN10MB) ? 1 : 0;
|
||||||
|
|
||||||
|
int l3 = BifEnum::L3_UNKNOWN;
|
||||||
|
|
||||||
|
if ( l3_proto == L3_IPV4 )
|
||||||
|
l3 = BifEnum::L3_IPV4;
|
||||||
|
|
||||||
|
else if ( l3_proto == L3_IPV6 )
|
||||||
|
l3 = BifEnum::L3_IPV6;
|
||||||
|
|
||||||
|
else if ( l3_proto == L3_ARP )
|
||||||
|
l3 = BifEnum::L3_ARP;
|
||||||
|
|
||||||
|
// l2_hdr layout:
|
||||||
|
// encap: link_encap; ##< L2 link encapsulation
|
||||||
|
// len: count; ##< Total frame length on wire
|
||||||
|
// cap_len: count; ##< Captured length
|
||||||
|
// src: string &optional; ##< L2 source (if ethernet)
|
||||||
|
// dst: string &optional; ##< L2 destination (if ethernet)
|
||||||
|
// vlan: count &optional; ##< VLAN tag if any (and ethernet)
|
||||||
|
// ethertype: count &optional; ##< If ethernet
|
||||||
|
// proto: layer3_proto; ##< L3 proto
|
||||||
|
|
||||||
|
if ( is_ethernet )
|
||||||
|
{
|
||||||
|
// Ethernet header layout is:
|
||||||
|
// dst[6bytes] src[6bytes] ethertype[2bytes]...
|
||||||
|
l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_ETHERNET, BifType::Enum::link_encap));
|
||||||
|
l2_hdr->Assign(3, FmtEUI48(data + 6)); // src
|
||||||
|
l2_hdr->Assign(4, FmtEUI48(data)); // dst
|
||||||
|
|
||||||
|
if ( vlan )
|
||||||
|
l2_hdr->Assign(5, new Val(vlan, TYPE_COUNT));
|
||||||
|
|
||||||
|
l2_hdr->Assign(6, new Val(eth_type, TYPE_COUNT));
|
||||||
|
|
||||||
|
if ( eth_type == ETHERTYPE_ARP || eth_type == ETHERTYPE_REVARP )
|
||||||
|
// We also identify ARP for L3 over ethernet
|
||||||
|
l3 = BifEnum::L3_ARP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
l2_hdr->Assign(0, new EnumVal(BifEnum::LINK_UNKNOWN, BifType::Enum::link_encap));
|
||||||
|
|
||||||
|
l2_hdr->Assign(1, new Val(len, TYPE_COUNT));
|
||||||
|
l2_hdr->Assign(2, new Val(cap_len, TYPE_COUNT));
|
||||||
|
|
||||||
|
l2_hdr->Assign(7, new EnumVal(l3, BifType::Enum::layer3_proto));
|
||||||
|
|
||||||
|
pkt_hdr->Assign(0, l2_hdr);
|
||||||
|
|
||||||
|
if ( l3_proto == L3_IPV4 )
|
||||||
|
{
|
||||||
|
IP_Hdr ip_hdr((const struct ip*)(data + hdr_size), false);
|
||||||
|
return ip_hdr.BuildPktHdrVal(pkt_hdr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( l3_proto == L3_IPV6 )
|
||||||
|
{
|
||||||
|
IP_Hdr ip6_hdr((const struct ip6_hdr*)(data + hdr_size), false, cap_len);
|
||||||
|
return ip6_hdr.BuildPktHdrVal(pkt_hdr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return pkt_hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Val *Packet::FmtEUI48(const u_char *mac) const
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
return new StringVal(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::Describe(ODesc* d) const
|
||||||
|
{
|
||||||
|
const IP_Hdr ip = IP();
|
||||||
|
d->Add(ip.SrcAddr());
|
||||||
|
d->Add("->");
|
||||||
|
d->Add(ip.DstAddr());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Packet::Serialize(SerialInfo* info) const
|
||||||
|
{
|
||||||
|
return SERIALIZE(uint32(ts.tv_sec)) &&
|
||||||
|
SERIALIZE(uint32(ts.tv_usec)) &&
|
||||||
|
SERIALIZE(uint32(len)) &&
|
||||||
|
SERIALIZE(link_type) &&
|
||||||
|
info->s->Write(tag.c_str(), tag.length(), "tag") &&
|
||||||
|
info->s->Write((const char*)data, cap_len, "data");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static iosource::PktDumper* dump = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Packet* Packet::Unserialize(UnserialInfo* info)
|
||||||
|
{
|
||||||
|
struct timeval ts;
|
||||||
|
uint32 len, link_type;
|
||||||
|
|
||||||
|
if ( ! (UNSERIALIZE((uint32 *)&ts.tv_sec) &&
|
||||||
|
UNSERIALIZE((uint32 *)&ts.tv_usec) &&
|
||||||
|
UNSERIALIZE(&len) &&
|
||||||
|
UNSERIALIZE(&link_type)) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char* tag;
|
||||||
|
if ( ! info->s->Read((char**) &tag, 0, "tag") )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const u_char* pkt;
|
||||||
|
int caplen;
|
||||||
|
if ( ! info->s->Read((char**) &pkt, &caplen, "data") )
|
||||||
|
{
|
||||||
|
delete [] tag;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet *p = new Packet(link_type, &ts, caplen, len, pkt, true,
|
||||||
|
std::string(tag));
|
||||||
|
delete [] tag;
|
||||||
|
|
||||||
|
// For the global timer manager, we take the global network_time as the
|
||||||
|
// packet's timestamp for feeding it into our packet loop.
|
||||||
|
if ( p->tag == "" )
|
||||||
|
p->time = timer_mgr->Time();
|
||||||
|
else
|
||||||
|
p->time = p->ts.tv_sec + double(p->ts.tv_usec) / 1e6;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if ( debug_logger.IsEnabled(DBG_TM) )
|
||||||
|
{
|
||||||
|
if ( ! dump )
|
||||||
|
dump = iosource_mgr->OpenPktDumper("tm.pcap", true);
|
||||||
|
|
||||||
|
if ( dump )
|
||||||
|
{
|
||||||
|
dump->Dump(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
|
@ -5,94 +5,125 @@
|
||||||
#include "IP.h"
|
#include "IP.h"
|
||||||
#include "NetVar.h"
|
#include "NetVar.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Layer 3 type of a packet, as determined by the parsing code in Packet.
|
||||||
|
*/
|
||||||
enum Layer3Proto {
|
enum Layer3Proto {
|
||||||
L3_UNKNOWN = -1,
|
L3_UNKNOWN = -1, /// Layer 3 type could not be determined.
|
||||||
L3_IPV4 = 1,
|
L3_IPV4 = 1, /// Layer 3 is IPv4.
|
||||||
L3_IPV6 = 2,
|
L3_IPV6 = 2, /// Layer 3 is IPv6.
|
||||||
L3_ARP = 3,
|
L3_ARP = 3, /// Layer 3 is ARP.
|
||||||
};
|
};
|
||||||
|
|
||||||
// A link-layer packet.
|
/**
|
||||||
//
|
* 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
|
* Note that for serialization we don't use much of the support provided by
|
||||||
// themselves. In particular, Packets aren't derived from SerialObj. They are
|
* the serialization framework. Serialize/Unserialize do all the work by
|
||||||
// completely seperate and self-contained entities, and we don't need any of
|
* themselves. In particular, Packets aren't derived from SerialObj. They are
|
||||||
// the sophisticated features like object caching.
|
* completely seperate and self-contained entities, and we don't need any of
|
||||||
|
* the sophisticated features like object caching.
|
||||||
|
*/
|
||||||
class Packet {
|
class Packet {
|
||||||
public:
|
public:
|
||||||
Packet()
|
/**
|
||||||
|
* Construct and initialize from packet data.
|
||||||
|
*
|
||||||
|
* @param link_type The link type in the form of a \c DLT_* constant.
|
||||||
|
*
|
||||||
|
* @param ts The timestamp associated with the packet.
|
||||||
|
*
|
||||||
|
* @param caplen The number of bytes valid in *data*.
|
||||||
|
*
|
||||||
|
* @param len The wire length of the packet, which must be more or
|
||||||
|
* equal *caplen* (but can't be less).
|
||||||
|
*
|
||||||
|
* @param data A pointer to the raw packet data, starting with the
|
||||||
|
* layer 2 header. The pointer must remain valid for the lifetime of
|
||||||
|
* the Packet instance, unless *copy* is true.
|
||||||
|
*
|
||||||
|
* @param copy If true, the constructor will make an internal copy of
|
||||||
|
* *data*, so that the caller can release its version.
|
||||||
|
*
|
||||||
|
* @param tag A textual tag to associate with the packet for
|
||||||
|
* differentiating the input streams.
|
||||||
|
*/
|
||||||
|
Packet(int link_type, struct timeval *ts, uint32 caplen,
|
||||||
|
uint32 len, const u_char *data, int copy = false,
|
||||||
|
std::string tag = std::string("")) : data(0)
|
||||||
|
{
|
||||||
|
Init(link_type, ts, caplen, len, data, copy, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor. For internal use only.
|
||||||
|
*/
|
||||||
|
Packet() : data(0)
|
||||||
{
|
{
|
||||||
struct timeval ts = {0, 0};
|
struct timeval ts = {0, 0};
|
||||||
Init(0, &ts, 0, 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(""))
|
|
||||||
{
|
|
||||||
Init(arg_link_type, arg_ts, arg_caplen, arg_len, arg_data, arg_free, arg_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
~Packet()
|
~Packet()
|
||||||
{
|
{
|
||||||
if ( free )
|
if ( copy )
|
||||||
delete [] data;
|
delete [] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize with data from pointer.
|
/**
|
||||||
//
|
* (Re-)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.
|
* @param link_type The link type in the form of a \c DLT_* constant.
|
||||||
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,
|
* @param ts The timestamp associated with the packet.
|
||||||
std::string arg_tag = std::string(""), uint32 arg_hdrsize = 0)
|
*
|
||||||
{
|
* @param caplen The number of bytes valid in *data*.
|
||||||
link_type = arg_link_type;
|
*
|
||||||
ts = *arg_ts;
|
* @param len The wire length of the packet, which must be more or
|
||||||
cap_len = arg_caplen;
|
* equal *caplen* (but can't be less).
|
||||||
len = arg_len;
|
*
|
||||||
free = arg_free;
|
* @param data A pointer to the raw packet data, starting with the
|
||||||
|
* layer 2 header. The pointer must remain valid for the lifetime of
|
||||||
|
* the Packet instance, unless *copy* is true.
|
||||||
|
*
|
||||||
|
* @param copy If true, the constructor will make an internal copy of
|
||||||
|
* *data*, so that the caller can release its version.
|
||||||
|
*
|
||||||
|
* @param tag A textual tag to associate with the packet for
|
||||||
|
* differentiating the input streams.
|
||||||
|
*/
|
||||||
|
void Init(int link_type, struct timeval *ts, uint32 caplen,
|
||||||
|
uint32 len, const u_char *data, int copy = false,
|
||||||
|
std::string tag = std::string(""));
|
||||||
|
|
||||||
if ( free )
|
/**
|
||||||
{
|
* Returns true if parsing the layer 2 fields failed, including when
|
||||||
data = new u_char[cap_len];
|
* no data was passed into the constructor in the first place.
|
||||||
memcpy(const_cast<u_char *>(data), arg_data, cap_len);
|
*/
|
||||||
}
|
|
||||||
else
|
|
||||||
data = arg_data;
|
|
||||||
|
|
||||||
hdr_size = arg_hdrsize;
|
|
||||||
l3_proto = L3_UNKNOWN;
|
|
||||||
tag = arg_tag;
|
|
||||||
time = ts.tv_sec + double(ts.tv_usec) / 1e6;
|
|
||||||
eth_type = 0;
|
|
||||||
vlan = 0;
|
|
||||||
|
|
||||||
l2_valid = false;
|
|
||||||
|
|
||||||
if ( data )
|
|
||||||
ProcessLayer2();
|
|
||||||
}
|
|
||||||
|
|
||||||
const IP_Hdr IP() const
|
|
||||||
{ return IP_Hdr((struct ip *) (data + hdr_size), false); }
|
|
||||||
|
|
||||||
// Returns true if parsing the Layer 2 fields failed, including when
|
|
||||||
// no data was passed into the constructor in the first place.
|
|
||||||
bool Layer2Valid()
|
bool Layer2Valid()
|
||||||
{
|
{
|
||||||
return l2_valid;
|
return l2_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Describe(ODesc* d) const;
|
/**
|
||||||
|
* Interprets the Layer 3 of the packet as IP and returns a
|
||||||
|
* correspondign object.
|
||||||
|
*/
|
||||||
|
const IP_Hdr IP() const
|
||||||
|
{ return IP_Hdr((struct ip *) (data + hdr_size), false); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to return the header size for a given link tyoe.
|
* Returns a \c raw_pkt_hdr RecordVal, which includes layer 2 and
|
||||||
|
* also everything in IP_Hdr (i.e., IP4/6 + TCP/UDP/ICMP).
|
||||||
|
*/
|
||||||
|
RecordVal* BuildPktHdrVal() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static method returning the link-layer header size for a given
|
||||||
|
* link type.
|
||||||
*
|
*
|
||||||
* @param link_type The link tyoe.
|
* @param link_type The link tyoe.
|
||||||
*
|
*
|
||||||
|
@ -100,7 +131,19 @@ public:
|
||||||
*/
|
*/
|
||||||
static int GetLinkHeaderSize(int link_type);
|
static int GetLinkHeaderSize(int link_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the packet, with standard signature.
|
||||||
|
*/
|
||||||
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the packet, with standard signature.
|
||||||
|
*/
|
||||||
bool Serialize(SerialInfo* info) const;
|
bool Serialize(SerialInfo* info) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unserializes the packet, with standard signature.
|
||||||
|
*/
|
||||||
static Packet* Unserialize(UnserialInfo* info);
|
static Packet* Unserialize(UnserialInfo* info);
|
||||||
|
|
||||||
// These are passed in through the constructor.
|
// These are passed in through the constructor.
|
||||||
|
@ -114,10 +157,29 @@ public:
|
||||||
|
|
||||||
// These are computed from Layer 2 data. These fields are only valid if
|
// These are computed from Layer 2 data. These fields are only valid if
|
||||||
// Layer2Valid() returns true.
|
// Layer2Valid() returns true.
|
||||||
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
|
* Layer 2 header size. Valid iff Layer2Valid() returns true.
|
||||||
uint32 vlan; /// (Outermost) VLan tag if any, else 0
|
*/
|
||||||
|
uint32 hdr_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layer 3 protocol identified (if any). Valid iff Layer2Valid()
|
||||||
|
* returns true.
|
||||||
|
*/
|
||||||
|
Layer3Proto l3_proto; ///
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If layer 2 is Ethernet, innermost ethertype field. Valid iff
|
||||||
|
* Layer2Valid() returns true.
|
||||||
|
*/
|
||||||
|
uint32 eth_type; ///
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Outermost) VLAN tag if any, else 0. Valid iff Layer2Valid()
|
||||||
|
* returns true.
|
||||||
|
*/
|
||||||
|
uint32 vlan; ///
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Calculate layer 2 attributes. Sets
|
// Calculate layer 2 attributes. Sets
|
||||||
|
@ -126,8 +188,12 @@ private:
|
||||||
// Wrapper to generate a packet-level weird.
|
// Wrapper to generate a packet-level weird.
|
||||||
void Weird(const char* name);
|
void Weird(const char* name);
|
||||||
|
|
||||||
// should we delete associated packet memory upon destruction.
|
// Renders an MAC address into its ASCII representation.
|
||||||
bool free;
|
Val *FmtEUI48(const u_char *mac) const;
|
||||||
|
|
||||||
|
// True if we need to delete associated packet memory upon
|
||||||
|
// destruction.
|
||||||
|
bool copy;
|
||||||
|
|
||||||
// True if L2 processing succeeded.
|
// True if L2 processing succeeded.
|
||||||
bool l2_valid;
|
bool l2_valid;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue