/* * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Politecnico di Torino, CACE Technologies * 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __PCAP_RPCAP_H__ #define __PCAP_RPCAP_H__ #include "pcap.h" #include "sockutils.h" /* Needed for some structures (like SOCKET, sockaddr_in) which are used here */ /* * \file pcap-pcap.h * * This file keeps all the new definitions and typedefs that are exported to the user and * that are needed for the RPCAP protocol. * * \warning All the RPCAP functions that are allowed to return a buffer containing * the error description can return max PCAP_ERRBUF_SIZE characters. * However there is no guarantees that the string will be zero-terminated. * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1' * and to insert manually the termination char at the end of the buffer. This will * guarantee that no buffer overflows occur even if we use the printf() to show * the error on the screen. * * \warning This file declares some typedefs that MUST be of a specific size. * These definitions (i.e. typedefs) could need to be changed on other platforms than * Intel IA32. * * \warning This file defines some structures that are used to transfer data on the network. * Be careful that you compiler MUST not insert padding into these structures * for better alignment. * These structures have been created in order to be correctly aligned to a 32 bits * boundary, but be careful in any case. */ /********************************************************* * * * General definitions / typedefs for the RPCAP protocol * * * *********************************************************/ /* All the following structures and typedef belongs to the Private Documentation */ /* * \addtogroup remote_pri_struct * \{ */ #define RPCAP_DEFAULT_NETPORT "2002" /* Default port on which the RPCAP daemon is waiting for connections. */ /* Default port on which the client workstation is waiting for connections in case of active mode. */ #define RPCAP_DEFAULT_NETPORT_ACTIVE "2003" #define RPCAP_DEFAULT_NETADDR "" /* Default network address on which the RPCAP daemon binds to. */ #define RPCAP_VERSION 0 /* Present version of the RPCAP protocol (0 = Experimental). */ #define RPCAP_TIMEOUT_INIT 90 /* Initial timeout for RPCAP connections (default: 90 sec) */ #define RPCAP_TIMEOUT_RUNTIME 180 /* Run-time timeout for RPCAP connections (default: 3 min) */ #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */ #define RPCAP_SUSPEND_WRONGAUTH 1 /* If the authentication is wrong, stops 1 sec before accepting a new auth message */ /* * \brief Buffer used by socket functions to send-receive packets. * In case you plan to have messages larger than this value, you have to increase it. */ #define RPCAP_NETBUF_SIZE 64000 /* * \brief Separators used for the host list. * * It is used: * - by the rpcapd daemon, when you types a list of allowed connecting hosts * - by the rpcap in active mode, when the client waits for incoming connections from other hosts */ #define RPCAP_HOSTLIST_SEP " ,;\n\r" /* WARNING: These could need to be changed on other platforms */ typedef unsigned char uint8; /* Provides an 8-bits unsigned integer */ typedef unsigned short uint16; /* Provides a 16-bits unsigned integer */ typedef unsigned int uint32; /* Provides a 32-bits unsigned integer */ typedef int int32; /* Provides a 32-bits integer */ /* * \brief Keeps a list of all the opened connections in the active mode. * * This structure defines a linked list of items that are needed to keep the info required to * manage the active mode. * In other words, when a new connection in active mode starts, this structure is updated so that * it reflects the list of active mode connections currently opened. * This structure is required by findalldevs() and open_remote() to see if they have to open a new * control connection toward the host, or they already have a control connection in place. */ struct activehosts { struct sockaddr_storage host; SOCKET sockctrl; struct activehosts *next; }; /********************************************************* * * * Protocol messages formats * * * *********************************************************/ /* WARNING Take care you compiler does not insert padding for better alignments into these structs */ /* Common header for all the RPCAP messages */ struct rpcap_header { uint8 ver; /* RPCAP version number */ uint8 type; /* RPCAP message type (error, findalldevs, ...) */ uint16 value; /* Message-dependent value (not always used) */ uint32 plen; /* Length of the payload of this RPCAP message */ }; /* Format of the message for the interface description (findalldevs command) */ struct rpcap_findalldevs_if { uint16 namelen; /* Length of the interface name */ uint16 desclen; /* Length of the interface description */ uint32 flags; /* Interface flags */ uint16 naddr; /* Number of addresses */ uint16 dummy; /* Must be zero */ }; /* Format of the message for the address listing (findalldevs command) */ struct rpcap_findalldevs_ifaddr { struct sockaddr_storage addr; /* Network address */ struct sockaddr_storage netmask; /* Netmask for that address */ struct sockaddr_storage broadaddr; /* Broadcast address for that address */ struct sockaddr_storage dstaddr; /* P2P destination address for that address */ }; /* * \brief Format of the message of the connection opening reply (open command). * * This structure transfers over the network some of the values useful on the client side. */ struct rpcap_openreply { int32 linktype; /* Link type */ int32 tzoff; /* Timezone offset */ }; /* Format of the message that starts a remote capture (startcap command) */ struct rpcap_startcapreq { uint32 snaplen; /* Length of the snapshot (number of bytes to capture for each packet) */ uint32 read_timeout; /* Read timeout in milliseconds */ uint16 flags; /* Flags (see RPCAP_STARTCAPREQ_FLAG_xxx) */ uint16 portdata; /* Network port on which the client is waiting at (if 'serveropen') */ }; /* Format of the reply message that devoted to start a remote capture (startcap reply command) */ struct rpcap_startcapreply { int32 bufsize; /* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */ uint16 portdata; /* Network port on which the server is waiting at (passive mode only) */ uint16 dummy; /* Must be zero */ }; /* * \brief Format of the header which encapsulates captured packets when transmitted on the network. * * This message requires the general header as well, since we want to be able to exchange * more information across the network in the future (for example statistics, and kind like that). */ struct rpcap_pkthdr { uint32 timestamp_sec; /* 'struct timeval' compatible, it represents the 'tv_sec' field */ uint32 timestamp_usec; /* 'struct timeval' compatible, it represents the 'tv_usec' field */ uint32 caplen; /* Length of portion present in the capture */ uint32 len; /* Real length this packet (off wire) */ uint32 npkt; /* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */ }; /* General header used for the pcap_setfilter() command; keeps just the number of BPF instructions */ struct rpcap_filter { uint16 filtertype; /* type of the filter transferred (BPF instructions, ...) */ uint16 dummy; /* Must be zero */ uint32 nitems; /* Number of items contained into the filter (e.g. BPF instructions for BPF filters) */ }; /* Structure that keeps a single BPF instuction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */ struct rpcap_filterbpf_insn { uint16 code; /* opcode of the instruction */ uint8 jt; /* relative offset to jump to in case of 'true' */ uint8 jf; /* relative offset to jump to in case of 'false' */ int32 k; /* instruction-dependent value */ }; /* Structure that keeps the data required for the authentication on the remote host */ struct rpcap_auth { uint16 type; /* Authentication type */ uint16 dummy; /* Must be zero */ uint16 slen1; /* Length of the first authentication item (e.g. username) */ uint16 slen2; /* Length of the second authentication item (e.g. password) */ }; /* Structure that keeps the statistics about the number of packets captured, dropped, etc. */ struct rpcap_stats { uint32 ifrecv; /* Packets received by the kernel filter (i.e. pcap_stats.ps_recv) */ uint32 ifdrop; /* Packets dropped by the network interface (e.g. not enough buffers) (i.e. pcap_stats.ps_ifdrop) */ uint32 krnldrop; /* Packets dropped by the kernel filter (i.e. pcap_stats.ps_drop) */ uint32 svrcapt; /* Packets captured by the RPCAP daemon and sent on the network */ }; /* Structure that is needed to set sampling parameters */ struct rpcap_sampling { uint8 method; /* Sampling method */ uint8 dummy1; /* Must be zero */ uint16 dummy2; /* Must be zero */ uint32 value; /* Parameter related to the sampling method */ }; /* * Private data for doing a live capture. */ struct pcap_md { struct pcap_stat stat; /* XXX */ int use_bpf; /* using kernel filter */ u_long TotPkts; /* can't overflow for 79 hrs on ether */ u_long TotAccepted; /* count accepted by filter */ u_long TotDrops; /* count of dropped packets */ long TotMissed; /* missed by i/f during this run */ long OrigMissed; /* missed by i/f before this run */ char *device; /* device name */ int timeout; /* timeout for buffering */ int must_clear; /* stuff we must clear when we close */ struct pcap *next; /* list of open pcaps that need stuff cleared on close */ #ifdef linux int sock_packet; /* using Linux 2.0 compatible interface */ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ int ifindex; /* interface index of device we're bound to */ int lo_ifindex; /* interface index of the loopback device */ u_int packets_read; /* count of packets read with recvfrom() */ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ u_int tp_version; /* version of tpacket_hdr for mmaped ring */ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ #endif /* linux */ #ifdef HAVE_DAG_API #ifdef HAVE_DAG_STREAMS_API u_char *dag_mem_bottom;/* DAG card current memory bottom pointer */ u_char *dag_mem_top; /* DAG card current memory top pointer */ #else /* HAVE_DAG_STREAMS_API */ void *dag_mem_base; /* DAG card memory base address */ u_int dag_mem_bottom; /* DAG card current memory bottom offset */ u_int dag_mem_top; /* DAG card current memory top offset */ #endif /* HAVE_DAG_STREAMS_API */ int dag_fcs_bits; /* Number of checksum bits from link layer */ int dag_offset_flags; /* Flags to pass to dag_offset(). */ int dag_stream; /* DAG stream number */ int dag_timeout; /* timeout specified to pcap_open_live. * Same as in linux above, introduce * generally? */ #endif /* HAVE_DAG_API */ #ifdef HAVE_ZEROCOPY_BPF /* * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will * alternative between these two actual mmap'd buffers as required. * As there is a header on the front size of the mmap'd buffer, only * some of the buffer is exposed to libpcap as a whole via bufsize; * zbufsize is the true size. zbuffer tracks the current zbuf * associated with buffer so that it can be used to decide which the * next buffer to read will be. */ u_char *zbuf1, *zbuf2, *zbuffer; u_int zbufsize; u_int zerocopy; u_int interrupted; struct timespec firstsel; /* * If there's currently a buffer being actively processed, then it is * referenced here; 'buffer' is also pointed at it, but offset by the * size of the header. */ struct bpf_zbuf_header *bzh; #endif /* HAVE_ZEROCOPY_BPF */ #ifdef HAVE_REMOTE /* * There is really a mess with previous variables, and it seems to me that they are not used * (they are used in pcap_pf.c only). I think we have to start using them. * The meaning is the following: * * - TotPkts: the amount of packets received by the bpf filter, *before* applying the filter * - TotAccepted: the amount of packets that satisfies the filter * - TotDrops: the amount of packet that were dropped into the kernel buffer because of lack of space * - TotMissed: the amount of packets that were dropped by the physical interface; it is basically * the value of the hardware counter into the card. This number is never put to zero, so this number * takes into account the *total* number of interface drops starting from the interface power-on. * - OrigMissed: the amount of packets that were dropped by the interface *when the capture begins*. * This value is used to detect the number of packets dropped by the interface *during the present * capture*, so that (ps_ifdrops= TotMissed - OrigMissed). */ unsigned int TotNetDrops; /* keeps the number of packets that have been dropped by the network */ /* * \brief It keeps the number of packets that have been received by the application. * * Packets dropped by the kernel buffer are not counted in this variable. The variable is always * equal to (TotAccepted - TotDrops), except for the case of remote capture, in which we have also * packets in flight, i.e. that have been transmitted by the remote host, but that have not been * received (yet) from the client. In this case, (TotAccepted - TotDrops - TotNetDrops) gives a * wrong result, since this number does not corresponds always to the number of packet received by * the application. For this reason, in the remote capture we need another variable that takes * into account of the number of packets actually received by the application. */ unsigned int TotCapt; /*! \brief '1' if we're the network client; needed by several functions (like pcap_setfilter() ) to know if they have to use the socket or they have to open the local adapter. */ int rmt_clientside; SOCKET rmt_sockctrl; //!< socket ID of the socket used for the control connection SOCKET rmt_sockdata; //!< socket ID of the socket used for the data connection int rmt_flags; //!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture() int rmt_capstarted; //!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture() struct pcap_samp rmt_samp; //!< Keeps the parameters related to the sampling process. char *currentfilter; //!< Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on. #endif /* HAVE_REMOTE */ }; /* Messages field coding */ #define RPCAP_MSG_ERROR 1 /* Message that keeps an error notification */ #define RPCAP_MSG_FINDALLIF_REQ 2 /* Request to list all the remote interfaces */ #define RPCAP_MSG_OPEN_REQ 3 /* Request to open a remote device */ #define RPCAP_MSG_STARTCAP_REQ 4 /* Request to start a capture on a remote device */ #define RPCAP_MSG_UPDATEFILTER_REQ 5 /* Send a compiled filter into the remote device */ #define RPCAP_MSG_CLOSE 6 /* Close the connection with the remote peer */ #define RPCAP_MSG_PACKET 7 /* This is a 'data' message, which carries a network packet */ #define RPCAP_MSG_AUTH_REQ 8 /* Message that keeps the authentication parameters */ #define RPCAP_MSG_STATS_REQ 9 /* It requires to have network statistics */ #define RPCAP_MSG_ENDCAP_REQ 10 /* Stops the current capture, keeping the device open */ #define RPCAP_MSG_SETSAMPLING_REQ 11 /* Set sampling parameters */ #define RPCAP_MSG_FINDALLIF_REPLY (128+RPCAP_MSG_FINDALLIF_REQ) /* Keeps the list of all the remote interfaces */ #define RPCAP_MSG_OPEN_REPLY (128+RPCAP_MSG_OPEN_REQ) /* The remote device has been opened correctly */ #define RPCAP_MSG_STARTCAP_REPLY (128+RPCAP_MSG_STARTCAP_REQ) /* The capture is starting correctly */ #define RPCAP_MSG_UPDATEFILTER_REPLY (128+RPCAP_MSG_UPDATEFILTER_REQ) /* The filter has been applied correctly on the remote device */ #define RPCAP_MSG_AUTH_REPLY (128+RPCAP_MSG_AUTH_REQ) /* Sends a message that says 'ok, authorization successful' */ #define RPCAP_MSG_STATS_REPLY (128+RPCAP_MSG_STATS_REQ) /* Message that keeps the network statistics */ #define RPCAP_MSG_ENDCAP_REPLY (128+RPCAP_MSG_ENDCAP_REQ) /* Confirms that the capture stopped successfully */ #define RPCAP_MSG_SETSAMPLING_REPLY (128+RPCAP_MSG_SETSAMPLING_REQ) /* Confirms that the capture stopped successfully */ #define RPCAP_STARTCAPREQ_FLAG_PROMISC 1 /* Enables promiscuous mode (default: disabled) */ #define RPCAP_STARTCAPREQ_FLAG_DGRAM 2 /* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/ #define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN 4 /* The server has to open the data connection toward the client */ #define RPCAP_STARTCAPREQ_FLAG_INBOUND 8 /* Capture only inbound packets (take care: the flag has no effects with promiscuous enabled) */ #define RPCAP_STARTCAPREQ_FLAG_OUTBOUND 16 /* Capture only outbound packets (take care: the flag has no effects with promiscuous enabled) */ #define RPCAP_UPDATEFILTER_BPF 1 /* This code tells us that the filter is encoded with the BPF/NPF syntax */ /* Network error codes */ #define PCAP_ERR_NETW 1 /* Network error */ #define PCAP_ERR_INITTIMEOUT 2 /* The RPCAP initial timeout has expired */ #define PCAP_ERR_AUTH 3 /* Generic authentication error */ #define PCAP_ERR_FINDALLIF 4 /* Generic findalldevs error */ #define PCAP_ERR_NOREMOTEIF 5 /* The findalldevs was ok, but the remote end had no interfaces to list */ #define PCAP_ERR_OPEN 6 /* Generic pcap_open error */ #define PCAP_ERR_UPDATEFILTER 7 /* Generic updatefilter error */ #define PCAP_ERR_GETSTATS 8 /* Generic pcap_stats error */ #define PCAP_ERR_READEX 9 /* Generic pcap_next_ex error */ #define PCAP_ERR_HOSTNOAUTH 10 /* The host is not authorized to connect to this server */ #define PCAP_ERR_REMOTEACCEPT 11 /* Generic pcap_remoteaccept error */ #define PCAP_ERR_STARTCAPTURE 12 /* Generic pcap_startcapture error */ #define PCAP_ERR_ENDCAPTURE 13 /* Generic pcap_endcapture error */ #define PCAP_ERR_RUNTIMETIMEOUT 14 /* The RPCAP run-time timeout has expired */ #define PCAP_ERR_SETSAMPLING 15 /* Error during the settings of sampling parameters */ #define PCAP_ERR_WRONGMSG 16 /* The other end endpoint sent a message which has not been recognized */ #define PCAP_ERR_WRONGVER 17 /* The other end endpoint has a version number that is not compatible with our */ /* * \} * // end of private documentation */ /********************************************************* * * * Exported function prototypes * * * *********************************************************/ int pcap_opensource_remote(pcap_t *p, struct pcap_rmtauth *auth); int pcap_startcapture_remote(pcap_t *fp); void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length); int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf); int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...); int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf); int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf); SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf); #endif