// See the file "COPYING" in the main distribution directory for copyright. #ifndef IOSOURCE_PKTSRC_PKTSRC_H #define IOSOURCE_PKTSRC_PKTSRC_H #include "IOSource.h" #include "BPF_Program.h" #include "Dict.h" declare(PDict,BPF_Program); namespace iosource { /** * Base class for packet sources. */ class PktSrc : public IOSource { public: /** * Struct for returning statistics on a packet source. */ struct Stats { /** * Packets received by source after filtering (w/o drops). */ unsigned int received; /** * Packets dropped by source. */ unsigned int dropped; // pkts dropped /** * Total number of packets on link before filtering. * Optional, can be left unset if not available. */ unsigned int link; Stats() { received = dropped = link = 0; } }; /** * Constructor. */ PktSrc(); /** * Destructor. */ virtual ~PktSrc(); /** * Returns the path associated with the source. This is the interface * name for live source, and a filename for offline sources. */ const std::string& Path() const; /** * Returns true if this is a live source. */ bool IsLive() const; /** * Returns the link type of the source. */ int LinkType() const; /** * Returns the netmask associated with the source, or \c * PCAP_NETMASK_UNKNOWN if unknown. */ uint32 Netmask() const; /** * Returns true if the source has flagged an error. */ bool IsError() const; /** * If the source encountered an error, returns a corresponding error * message. Returns an empty string otherwise. */ const char* ErrorMsg() const; /** * Returns the size of the link-layer header for this source. */ int HdrSize() const; /** * Returns the snap length for this source. */ int SnapLen() const; /** * In pseudo-realtime mode, returns the logical timestamp of the * current packet. Undefined if not running pseudo-realtime mode. */ double CurrentPacketTimestamp(); /** * In pseudo-realtime mode, returns the wall clock time associated * with current packet. Undefined if not running pseudo-realtime * mode. */ double CurrentPacketWallClock(); /** * Signals packet source that processing is going to be continued * after previous suspension. */ void ContinueAfterSuspend(); /** * Precompiles a BPF filter and associates the given index with it. * The compiled filter will be then available via \a GetBPFFilter(). * * This is primarily a helper for packet source implementation that * want to apply BPF filtering to their packets. * * @param index The index to associate with the filter. * * @param BPF filter The filter string to precompile. * * @return True on success, false if a problem occurred. */ bool PrecompileBPFFilter(int index, const std::string& filter); /** * Returns the precompiled BPF filter associated with a given index, * if any, as compiled by \a PrecompileBPFFilter(). * * This is primarily a helper for packet source implementation that * want to apply BPF filtering to their packets. * * @return The BPF filter associated, or null if none has been * (successfully) compiled. */ BPF_Program* GetBPFFilter(int index); /** * Applies a precompiled BPF filter to a packet. This will close the * source with an error message if no filter with that index has been * compiled. * * This is primarily a helper for packet source implementation that * want to apply BPF filtering to their packets. * * @param index The index of the filter to apply. * * @param hdr The header of the packet to filter. * * @param pkt The content of the packet to filter. * * @return True if it maches. */ bool ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_char *pkt); /** * Returns the packet currently being processed, if available. * * @param hdr A pointer to pass the header of the current packet back. * * @param pkt A pointer to pass the content of the current packet * back. * * @return True if the current packet is available, or false if not. */ bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt); // PacketSource interace for derived classes to override. /** * Precompiles a filter and associates a given index with it. The * filter syntax is defined by the packet source's implenentation. * * Derived classes must implement this to implement their filtering. * If they want to use BPF but don't support it natively, they can * call the corresponding helper method provided by \a PktSrc. * * @param index The index to associate with the filter * * @param filter The filter string to precompile. * * @return True on success, false if a problem occurred or filtering * is not supported. */ virtual bool PrecompileFilter(int index, const std::string& filter) = 0; /** * Activates a precompiled filter with the given index. * * Derived classes must implement this to implement their filtering. * If they want to use BPF but don't support it natively, they can * call the corresponding helper method provided by \a PktSrc. * * @param index The index of the filter to activate. * * @return True on success, false if a problem occurred or the * filtering is not supported. */ virtual bool SetFilter(int index) = 0; /** * Returns current statistics about the source. * * Derived classes must implement this method. * * @param stats A statistics structure that the method fill out. */ virtual void Statistics(Stats* stats) = 0; /** * Helper method to return the header size for a given link tyoe. * * @param link_type The link tyoe. * * @return The header size in bytes. */ static int GetLinkHeaderSize(int link_type); protected: friend class Manager; // Methods to use by derived classes. /** * Structure to pass back information about the packet source to the * base class. Derived class pass an instance of this to \a Opened(). */ struct Properties { /** * The path associated with the source. This is the interface * name for live source, and a filename for offline sources. */ std::string path; /** * A file descriptor suitable to use with \a select() for * determining if there's input available from this source. */ int selectable_fd; /** * The link type for packets from this source. */ int link_type; /** * The size of the link-layer header for packets from this * source. \a GetLinkHeaderSize() may be used to derive this * value. */ int hdr_size; /** * The netmask associated with the source, or \c * PCAP_NETMASK_UNKNOWN if unknown. */ uint32 netmask; /** * True if the source is reading live inout, false for * working offline. */ bool is_live; Properties() { selectable_fd = -1; link_type = -1; hdr_size = -1; netmask = PCAP_NETMASK_UNKNOWN; is_live = false; } }; /** * Structure describing a packet. */ struct Packet { /** * Time associated with the packet. */ double ts; /** * The pcap header associated with the packet. */ const struct ::pcap_pkthdr* hdr; /** * The full content of the packet. */ const u_char* data; }; /** * Called from the implementations of \a Open() to signal that the * source has been successully opened. * * @param props A properties instance describing the now open source. */ void Opened(const Properties& props); /** * Called from the implementations of \a Close() to signal that the * source has been closed. */ void Closed(); /** * Can be called from derived classes to send an informational * message to the user. * * @param msg The message to pass on. */ void Info(const std::string& msg); /** * Can be called from derived classes to flag send an error. * * @param msg The message going with the error. */ void Error(const std::string& msg); /** * Can be called from derived classes to flah a "weird" situation. * * @param msg The message to pass on. * * @param pkt The packet associated with the weird, or null if none. */ void Weird(const std::string& msg, const Packet* pkt); /** * Can be called from derived classes to flag an internal error, * which will abort execution. * * @param msg The message to pass on. */ void InternalError(const std::string& msg); // PktSrc interface for derived classes to implement. /** * Called by the manager system to open the source. * * Derived classes must implement this method. If successful, the * implementation must call \a Opened(); if not, it must call Error() * with a corresponding message. */ virtual void Open() = 0; /** * Called by the manager system to close the source. * * Derived classes must implement this method. If successful, the * implementation must call \a Closed(); if not, it must call Error() * with a corresponding message. */ virtual void Close() = 0; /** * Provides the next packet from the source. * * @param pkt The packet structure to fill in with the packet's * information. The callee keep ownership of the data but must * guaranetee that it stays available at least until \a * DoneWithPacket() is called. It is guaranteed that no two calls to * this method will hapen with \a DoneWithPacket() in between. * * @return True if a packet is available and *pkt* filled in. False * if not packet is available or an error occured (which must be * flageed via Error()). */ virtual bool ExtractNextPacket(Packet* pkt) = 0; /** * Signals that the data of previously extracted packet will no * longer be needed. */ virtual void DoneWithPacket() = 0; private: // Checks if the current packet has a pseudo-time <= current_time. If // yes, returns pseudo-time, otherwise 0. double CheckPseudoTime(); // Internal helper for ExtractNextPacket(). bool ExtractNextPacketInternal(); // IOSource interface implementation. virtual void Init(); virtual void Done(); virtual void GetFds(iosource::FD_Set* read, iosource::FD_Set* write, iosource::FD_Set* except); virtual double NextTimestamp(double* local_network_time); virtual void Process(); virtual const char* Tag(); Properties props; bool have_packet; Packet current_packet; // For BPF filtering support. PDict(BPF_Program) filters; // Only set in pseudo-realtime mode. double first_timestamp; double first_wallclock; double current_wallclock; double current_pseudo; double next_sync_point; // For trace synchronziation in pseudo-realtime std::string errbuf; }; } #endif