// $Id: Sessions.h,v 1.27 2003/08/31 00:38:11 vern Exp $
//
// Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef sessions_h
#define sessions_h

#include "Dict.h"
#include "CompHash.h"
#include "IP.h"
#include "Frag.h"
#include "PacketFilter.h"

struct pcap_pkthdr;

class Connection;
class ConnID;
class TCP_Connection;
class UDP_Connection;
class ICMP_Connection;

declare(PDict,TCP_Connection);
declare(PDict,UDP_Connection);
declare(PDict,ICMP_Connection);
declare(PDict,FragReassembler);

class Discarder;
class SteppingStoneManager;
class PacketFilter;

class PacketSortElement;

struct SessionStats {
	int num_TCP_conns;
	int num_UDP_conns;
	int num_ICMP_conns;
	int num_fragments;
	int num_timers;

	int max_TCP_conns;
	int max_UDP_conns;
	int max_ICMP_conns;
	int max_fragments;
	int max_timers;
};

class NetSessions {
public:
	NetSessions();
	~NetSessions();

	void Done();	// Call this and drain events before destructing.

	void NextPacket(double t, const struct pcap_pkthdr* hdr,
			const u_char* const pkt, int hdr_size,
			PacketSortElement* e);

	// 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, uint32 frag_field);

	// 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);

	// caller_is_timer indicates whether the method is called from a timer
	void Remove(Connection* c, int caller_is_timer);
	void Remove(FragReassembler* f);

	// Generating connection_pending events for all connections
	// that are still active.
	void Drain();

	// Called periodically to generate statistics reports.
	void HeartBeat(double t);

	void GetStats(SessionStats& s) const;

	void Weird(const char* name,
		const struct pcap_pkthdr* hdr, const u_char* pkt);
	void Weird(const char* name, const IP_Hdr* ip);

	PacketFilter* GetPacketFilter()
		{
		if ( ! packet_filter )
			packet_filter = new PacketFilter(); 
		return packet_filter;
		}

protected:
	Connection* NewConn(HashKey* k, double t, const ConnID* id,
			const u_char* data, int is_tcp);

	TCP_Connection* NewConn(HashKey* k, double t, const ConnID* id,
			const struct tcphdr* tp);

	// 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), false otherwise.
	//
	// Note, port is in host order.
	int IsAnalyzedTCP_App(uint32 port) const;

	UDP_Connection* NewConn(HashKey* k, double t, const ConnID* id,
			const struct udphdr* up);

	ICMP_Connection* NewConn(HashKey* k, double t, const ConnID* id,
			const struct icmp* icmpp);

	void DoNextPacket(double t, const struct pcap_pkthdr* hdr,
			const IP_Hdr* ip_hdr, const u_char* const pkt,
			int hdr_size);

	// 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 struct pcap_pkthdr* hdr, const u_char* pkt,
			int len=0);

	void Internal(const char* msg, const struct pcap_pkthdr* hdr,
			const u_char* pkt);

	CompositeHash* ch;
	PDict(TCP_Connection) tcp_conns;
	PDict(UDP_Connection) udp_conns;
	PDict(ICMP_Connection) icmp_conns;
	PDict(FragReassembler) fragments;

	SteppingStoneManager* stp_manager;
	Discarder* discarder;
	PacketFilter* packet_filter;
	int build_backdoor_analyzer;
	int dump_this_packet;	// if true, current packet should be recorded
};

// Manager for the currently active sessions.
extern NetSessions* sessions;

#endif
