zeek/src/Sessions.h
Max Kellermann 0db61f3094 include cleanup
The Zeek code base has very inconsistent #includes.  Many sources
included a few headers, and those headers included other headers, and
in the end, nearly everything is included everywhere, so missing
#includes were never noticed.  Another side effect was a lot of header
bloat which slows down the build.

First step to fix it: in each source file, its own header should be
included first to verify that each header's includes are correct, and
none is missing.

After adding the missing #includes, I replaced lots of #includes
inside headers with class forward declarations.  In most headers,
object pointers are never referenced, so declaring the function
prototypes with forward-declared classes is just fine.

This patch speeds up the build by 19%, because each compilation unit
gets smaller.  Here are the "time" numbers for a fresh build (with a
warm page cache but without ccache):

Before this patch:

 3144.94user 161.63system 3:02.87elapsed 1808%CPU (0avgtext+0avgdata 2168608maxresident)k
 760inputs+12008400outputs (1511major+57747204minor)pagefaults 0swaps

After this patch:

 2565.17user 141.83system 2:25.46elapsed 1860%CPU (0avgtext+0avgdata 1489076maxresident)k
 72576inputs+9130920outputs (1667major+49400430minor)pagefaults 0swaps
2020-02-04 20:51:02 +01:00

249 lines
8.2 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "Frag.h"
#include "PacketFilter.h"
#include "NetVar.h"
#include "analyzer/protocol/tcp/Stats.h"
#include <map>
#include <utility>
#include <sys/types.h> // for u_char
class EncapsulationStack;
class EncapsulatingConn;
class Packet;
class PacketProfiler;
class Connection;
class ConnCompressor;
struct ConnID;
class Discarder;
namespace analyzer { namespace stepping_stone { class SteppingStoneManager; } }
namespace analyzer { namespace arp { class ARP_Analyzer; } }
struct SessionStats {
size_t num_TCP_conns;
size_t max_TCP_conns;
uint64_t cumulative_TCP_conns;
size_t num_UDP_conns;
size_t max_UDP_conns;
uint64_t cumulative_UDP_conns;
size_t num_ICMP_conns;
size_t max_ICMP_conns;
uint64_t cumulative_ICMP_conns;
size_t num_fragments;
size_t max_fragments;
uint64_t num_packets;
};
class NetSessions {
public:
NetSessions();
~NetSessions();
// Main entry point for packet processing.
void NextPacket(double t, const Packet* pkt);
void Done(); // call to drain events before destructing
// Returns a reassembled packet, or nil if there are still
// some missing fragments.
FragReassembler* NextFragment(double t, const IP_Hdr* ip,
const u_char* pkt);
// Looks up the connection referred to by the given Val,
// which should be a conn_id record. Returns nil if there's
// no such connection or the Val is ill-formed.
Connection* FindConnection(Val* v);
void Remove(Connection* c);
void Remove(FragReassembler* f);
void Insert(Connection* c);
// Generating connection_pending events for all connections
// that are still active.
void Drain();
void GetStats(SessionStats& s) const;
void Weird(const char* name, const Packet* pkt,
const EncapsulationStack* encap = 0, const char* addl = "");
void Weird(const char* name, const IP_Hdr* ip,
const EncapsulationStack* encap = 0, const char* addl = "");
PacketFilter* GetPacketFilter()
{
if ( ! packet_filter )
packet_filter = new PacketFilter(packet_filter_default);
return packet_filter;
}
analyzer::stepping_stone::SteppingStoneManager* GetSTPManager() { return stp_manager; }
unsigned int CurrentConnections()
{
return tcp_conns.size() + udp_conns.size() + icmp_conns.size();
}
void DoNextPacket(double t, const Packet *pkt, const IP_Hdr* ip_hdr,
const EncapsulationStack* encapsulation);
/**
* Wrapper that recurses on DoNextPacket for encapsulated IP packets.
*
* @param t Network time.
* @param hdr If the outer pcap header is available, this pointer can be set
* so that the fake pcap header passed to DoNextPacket will use
* the same timeval. The caplen and len fields of the fake pcap
* header are always set to the TotalLength() of \a inner.
* @param inner Pointer to IP header wrapper of the inner packet, ownership
* of the pointer's memory is assumed by this function.
* @param prev Any previous encapsulation stack of the caller, not including
* the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
void DoNextInnerPacket(double t, const Packet *pkt,
const IP_Hdr* inner, const EncapsulationStack* prev,
const EncapsulatingConn& ec);
/**
* Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4
* or IPv6 header based on whether it's long enough to contain such a header,
* if version given in the header matches the proto argument, and also checks
* that the payload length field of that header matches the actual
* length of \a pkt given by \a caplen.
*
* @param caplen The length of \a pkt in bytes.
* @param pkt The inner IP packet data.
* @param proto Either IPPROTO_IPV6 or IPPROTO_IPV4 to indicate which IP
* protocol \a pkt corresponds to.
* @param inner The inner IP packet wrapper pointer to be allocated/assigned
* if \a pkt looks like a valid IP packet or at least long enough
* to hold an IP header.
* @return 0 If the inner IP packet appeared valid, else -1 if \a caplen
* is greater than the supposed IP packet's payload length field, -2
* if the version of the inner header does not match proto or
* 1 if \a caplen is less than the supposed packet's payload length.
* In the -1 case, \a inner may still be non-null if \a caplen was
* long enough to be an IP header, and \a inner is always non-null
* for other return values.
*/
int ParseIPPacket(int caplen, const u_char* const pkt, int proto,
IP_Hdr*& inner);
unsigned int ConnectionMemoryUsage();
unsigned int ConnectionMemoryUsageConnVals();
unsigned int MemoryAllocation();
analyzer::tcp::TCPStateStats tcp_stats; // keeps statistics on TCP states
protected:
friend class ConnCompressor;
friend class IPTunnelTimer;
using ConnectionMap = std::map<ConnIDKey, Connection*>;
using FragmentMap = std::map<FragReassemblerKey, FragReassembler*>;
Connection* NewConn(const ConnIDKey& k, double t, const ConnID* id,
const u_char* data, int proto, uint32_t flow_label,
const Packet* pkt, const EncapsulationStack* encapsulation);
Connection* LookupConn(const ConnectionMap& conns, const ConnIDKey& key);
// Returns true if the port corresonds to an application
// for which there's a Bro analyzer (even if it might not
// be used by the present policy script), or it's more
// generally a likely server port, false otherwise.
//
// Note, port is in host order.
bool IsLikelyServerPort(uint32_t port,
TransportProto transport_proto) const;
// Upon seeing the first packet of a connection, checks whether
// we want to analyze it (e.g., we may not want to look at partial
// connections), and, if yes, whether we should flip the roles of
// originator and responder (based on known ports or such).
// Use tcp_flags=0 for non-TCP.
bool WantConnection(uint16_t src_port, uint16_t dest_port,
TransportProto transport_proto,
uint8_t tcp_flags, bool& flip_roles);
// Record the given packet (if a dumper is active). If len=0
// then the whole packet is recorded, otherwise just the first
// len bytes.
void DumpPacket(const Packet *pkt, int len=0);
// For a given protocol, checks whether the header's length as derived
// from lower-level headers or the length actually captured is less
// than that protocol's minimum header size.
bool CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen,
const Packet *pkt, const EncapsulationStack* encap);
// Inserts a new connection into the sessions map. If a connection with
// the same key already exists in the map, it will be overwritten by
// the new one. Connection count stats get updated either way (so most
// cases should likely check that the key is not already in the map to
// avoid unnecessary incrementing of connecting counts).
void InsertConnection(ConnectionMap* m, const ConnIDKey& key, Connection* conn);
ConnectionMap tcp_conns;
ConnectionMap udp_conns;
ConnectionMap icmp_conns;
FragmentMap fragments;
SessionStats stats;
typedef pair<IPAddr, IPAddr> IPPair;
typedef pair<EncapsulatingConn, double> TunnelActivity;
typedef std::map<IPPair, TunnelActivity> IPTunnelMap;
IPTunnelMap ip_tunnels;
analyzer::arp::ARP_Analyzer* arp_analyzer;
analyzer::stepping_stone::SteppingStoneManager* stp_manager;
Discarder* discarder;
PacketFilter* packet_filter;
int dump_this_packet; // if true, current packet should be recorded
uint64_t num_packets_processed;
PacketProfiler* pkt_profiler;
};
class IPTunnelTimer : public Timer {
public:
IPTunnelTimer(double t, NetSessions::IPPair p)
: Timer(t + BifConst::Tunnel::ip_tunnel_timeout,
TIMER_IP_TUNNEL_INACTIVITY), tunnel_idx(p) {}
~IPTunnelTimer() override {}
void Dispatch(double t, int is_expire) override;
protected:
NetSessions::IPPair tunnel_idx;
};
class FragReassemblerTracker {
public:
FragReassemblerTracker(NetSessions* s, FragReassembler* f)
: net_sessions(s), frag_reassembler(f)
{ }
~FragReassemblerTracker()
{ net_sessions->Remove(frag_reassembler); }
private:
NetSessions* net_sessions;
FragReassembler* frag_reassembler;
};
// Manager for the currently active sessions.
extern NetSessions* sessions;