X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/73e8fef16186ef84cefa01b32c00308587b9e6ac..cc3ca65d6519faf3a0e4609b5150757c14af36e9:/pcap-int.h diff --git a/pcap-int.h b/pcap-int.h index a54f382b..c5a030f5 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -29,8 +29,6 @@ * 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. - * - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.94 2008-09-16 00:20:23 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -42,17 +40,16 @@ extern "C" { #endif -#ifdef HAVE_LIBDLPI -#include -#endif - -#ifdef WIN32 -#include -#endif /* WIN32 */ - -#ifdef MSDOS -#include -#include +#if defined(_WIN32) + /* + * Make sure Packet32.h doesn't define BPF structures that we've + * probably already defined as a result of including . + */ + #define BPF_MAJOR_VERSION + #include +#elif defined(MSDOS) + #include + #include #endif #if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/ @@ -88,120 +85,39 @@ extern "C" { #endif /* _MSC_VER */ /* - * Savefile - */ -typedef enum { - NOT_SWAPPED, - SWAPPED, - MAYBE_SWAPPED -} swapped_type_t; - -/* - * Used when reading a savefile. - */ -struct pcap_sf { - FILE *rfile; - int swapped; - size_t hdrsize; - swapped_type_t lengths_swapped; - int version_major; - int version_minor; - u_char *base; -}; - -/* - * Used when doing a live capture. - */ -struct pcap_md { - struct pcap_stat stat; - /*XXX*/ - int use_bpf; /* using kernel filter */ - u_long TotPkts; /* can't oflow 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 - * assocated 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 */ -}; - -/* - * Stuff to clear when we close. + * Maximum snapshot length. + * + * Somewhat arbitrary, but chosen to be: + * + * 1) big enough for maximum-size Linux loopback packets (65549) + * and some USB packets captured with USBPcap: + * + * http://desowin.org/usbpcap/ + * + * (> 131072, < 262144) + * + * and + * + * 2) small enough not to cause attempts to allocate huge amounts of + * memory; some applications might use the snapshot length in a + * savefile header to control the size of the buffer they allocate, + * so a size of, say, 2^31-1 might not work well. + * + * We don't enforce this in pcap_set_snaplen(), but we use it internally. */ -#define MUST_CLEAR_PROMISC 0x00000001 /* promiscuous mode */ -#define MUST_CLEAR_RFMON 0x00000002 /* rfmon (monitor) mode */ +#define MAXIMUM_SNAPLEN 262144 struct pcap_opt { + char *device; + int timeout; /* timeout for buffering */ int buffer_size; - char *source; int promisc; - int rfmon; + int rfmon; /* monitor mode */ + int immediate; /* immediate mode - deliver packets as soon as they arrive */ + int tstamp_type; + int tstamp_precision; }; -/* - * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H - * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything - * line up on a nice boundary. - */ -#ifdef __NetBSD__ -#include /* needed to declare __NetBSD_Version__ */ -#endif - -#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000) -#define PCAP_FDDIPAD 3 -#endif - typedef int (*activate_op_t)(pcap_t *); typedef int (*can_set_rfmon_op_t)(pcap_t *); typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *); @@ -212,27 +128,70 @@ typedef int (*set_datalink_op_t)(pcap_t *, int); typedef int (*getnonblock_op_t)(pcap_t *, char *); typedef int (*setnonblock_op_t)(pcap_t *, int, char *); typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *); -#ifdef WIN32 +#ifdef _WIN32 +typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *); typedef int (*setbuff_op_t)(pcap_t *, int); typedef int (*setmode_op_t)(pcap_t *, int); typedef int (*setmintocopy_op_t)(pcap_t *, int); +typedef HANDLE (*getevent_op_t)(pcap_t *); +typedef int (*oid_get_request_op_t)(pcap_t *, bpf_u_int32, void *, size_t *); +typedef int (*oid_set_request_op_t)(pcap_t *, bpf_u_int32, const void *, size_t *); +typedef u_int (*sendqueue_transmit_op_t)(pcap_t *, pcap_send_queue *, int); +typedef int (*setuserbuffer_op_t)(pcap_t *, int); +typedef int (*live_dump_op_t)(pcap_t *, char *, int, int); +typedef int (*live_dump_ended_op_t)(pcap_t *, int); +typedef PAirpcapHandle (*get_airpcap_handle_op_t)(pcap_t *); #endif typedef void (*cleanup_op_t)(pcap_t *); +/* + * We put all the stuff used in the read code path at the beginning, + * to try to keep it together in the same cache line or lines. + */ struct pcap { -#ifdef WIN32 + /* + * Method to call to read packets on a live capture. + */ + read_op_t read_op; + + /* + * Method to call to read packets from a savefile. + */ + int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **); + +#ifdef _WIN32 ADAPTER *adapter; - LPPACKET Packet; - int nonblock; #else int fd; int selectable_fd; - int send_fd; -#endif /* WIN32 */ +#endif /* _WIN32 */ + + /* + * Read buffer. + */ + int bufsize; + void *buffer; + u_char *bp; + int cc; + + int break_loop; /* flag set to force break from packet-reading loop */ + + void *priv; /* private data for methods */ + + int swapped; + FILE *rfile; /* null if live capture, non-null if savefile */ + int fddipad; + struct pcap *next; /* list of open pcaps that need stuff cleared on close */ + + /* + * File version number; meaningful only for a savefile, but we + * keep it here so that apps that (mistakenly) ask for the + * version numbers will get the same zero values that they + * always did. + */ + int version_major; + int version_minor; -#ifdef HAVE_LIBDLPI - dlpi_handle_t dlpi_hd; -#endif int snapshot; int linktype; /* Network linktype */ int linktype_ext; /* Extended information stored in the linktype field of a file */ @@ -241,42 +200,45 @@ struct pcap { int activated; /* true if the capture is really started */ int oldstyle; /* if we're opening with pcap_open_live() */ - int break_loop; /* flag set to force break from packet-reading loop */ + struct pcap_opt opt; -#ifdef PCAP_FDDIPAD - int fddipad; -#endif + /* + * Place holder for pcap_next(). + */ + u_char *pkt; -#ifdef MSDOS - void (*wait_proc)(void); /* call proc while waiting */ +#ifdef _WIN32 + struct pcap_stat stat; /* used for pcap_stats_ex() */ #endif - struct pcap_sf sf; - struct pcap_md md; - struct pcap_opt opt; + /* We're accepting only packets in this direction/these directions. */ + pcap_direction_t direction; /* - * Read buffer. + * Flags to affect BPF code generation. */ - int bufsize; - u_char *buffer; - u_char *bp; - int cc; + int bpf_codegen_flags; /* - * Place holder for pcap_next(). + * Placeholder for filter code if bpf not in kernel. */ - u_char *pkt; + struct bpf_program fcode; - /* We're accepting only packets in this direction/these directions. */ - pcap_direction_t direction; + char errbuf[PCAP_ERRBUF_SIZE + 1]; + int dlt_count; + u_int *dlt_list; + int tstamp_type_count; + u_int *tstamp_type_list; + int tstamp_precision_count; + u_int *tstamp_precision_list; + + struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ /* - * Methods. + * More methods. */ activate_op_t activate_op; can_set_rfmon_op_t can_set_rfmon_op; - read_op_t read_op; inject_op_t inject_op; setfilter_op_t setfilter_op; setdirection_op_t setdirection_op; @@ -285,29 +247,37 @@ struct pcap { setnonblock_op_t setnonblock_op; stats_op_t stats_op; -#ifdef WIN32 + /* + * Routine to use as callback for pcap_next()/pcap_next_ex(). + */ + pcap_handler oneshot_callback; + +#ifdef _WIN32 /* * These are, at least currently, specific to the Win32 NPF * driver. */ + stats_ex_op_t stats_ex_op; setbuff_op_t setbuff_op; setmode_op_t setmode_op; setmintocopy_op_t setmintocopy_op; + getevent_op_t getevent_op; + oid_get_request_op_t oid_get_request_op; + oid_set_request_op_t oid_set_request_op; + sendqueue_transmit_op_t sendqueue_transmit_op; + setuserbuffer_op_t setuserbuffer_op; + live_dump_op_t live_dump_op; + live_dump_ended_op_t live_dump_ended_op; + get_airpcap_handle_op_t get_airpcap_handle_op; #endif cleanup_op_t cleanup_op; - - /* - * Placeholder for filter code if bpf not in kernel. - */ - struct bpf_program fcode; - - char errbuf[PCAP_ERRBUF_SIZE + 1]; - int dlt_count; - u_int *dlt_list; - - struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; +/* + * BPF code generation flags. + */ +#define BPF_SPECIAL_VLAN_HANDLING 0x00000001 /* special VLAN handling for Linux */ + /* * This is a timeval as stored in a savefile. * It has to use the same types everywhere, independent of the actual @@ -344,12 +314,13 @@ struct pcap_timeval { * the old record header as well as files with the new record header * (using the magic number to determine the header format). * - * Then supply the changes as a patch at + * Then supply the changes by forking the branch at * - * http://sourceforge.net/projects/libpcap/ + * https://github.com/the-tcpdump-group/libpcap/issues * - * so that future versions of libpcap and programs that use it (such as - * tcpdump) will be able to read your new capture file format. + * and issuing a pull request, so that future versions of libpcap and + * programs that use it (such as tcpdump) will be able to read your new + * capture file format. */ struct pcap_sf_pkthdr { @@ -377,15 +348,21 @@ struct pcap_sf_patched_pkthdr { unsigned char pkt_type; }; -int yylex(void); +/* + * User data structure for the one-shot callback used for pcap_next() + * and pcap_next_ex(). + */ +struct oneshot_userdata { + struct pcap_pkthdr *hdr; + const u_char **pkt; + pcap_t *pd; +}; #ifndef min #define min(a, b) ((a) > (b) ? (b) : (a)) #endif -/* XXX should these be in pcap.h? */ int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); -int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); #ifndef HAVE_STRLCPY #define strlcpy(x, y, z) \ @@ -396,52 +373,142 @@ int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); #include -#if !defined(HAVE_SNPRINTF) -#define snprintf pcap_snprintf -extern int snprintf (char *, size_t, const char *, ...); +/* + * For flagging arguments as format strings in MSVC. + */ +#if _MSC_VER >= 1400 + #include + #if _MSC_VER > 1400 + #define FORMAT_STRING(p) _Printf_format_string_ p + #else + #define FORMAT_STRING(p) __format_string p + #endif +#else + #define FORMAT_STRING(p) p +#endif + +/* + * On Windows, snprintf(), with that name and with C99 behavior - i.e., + * guaranteeing that the formatted string is null-terminated - didn't + * appear until Visual Studio 2015. Prior to that, the C runtime had + * only _snprintf(), which *doesn't* guarantee that the string is + * null-terminated if it is truncated due to the buffer being too + * small. We therefore can't just define snprintf to be _snprintf + * and define vsnprintf to be _vsnprintf, as we're relying on null- + * termination of strings in all cases. + * + * We also want to allow this to be built with versions of Visual Studio + * prior to VS 2015, so we can't rely on snprintf() being present. + * + * And we want to make sure that, if we support plugins in the future, + * a routine with C99 snprintf() behavior will be available to them. + * We also don't want it to collide with the C library snprintf() if + * there is one. + * + * So we make pcap_snprintf() and pcap_vsnprintf() available, either by + * #defining them to be snprintf or vsnprintf, respectively, or by + * defining our own versions and exporting them. + */ +#ifdef HAVE_SNPRINTF +#define pcap_snprintf snprintf +#else +extern int pcap_snprintf(char *, size_t, FORMAT_STRING(const char *), ...); #endif -#if !defined(HAVE_VSNPRINTF) -#define vsnprintf pcap_vsnprintf -extern int vsnprintf (char *, size_t, const char *, va_list ap); +#ifdef HAVE_VSNPRINTF +#define pcap_vsnprintf vsnprintf +#else +extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap); #endif +/* + * Does the packet count argument to a module's read routine say + * "supply packets until you run out of packets"? + */ +#define PACKET_COUNT_IS_UNLIMITED(count) ((count) <= 0) + /* * Routines that most pcap implementations can use for non-blocking mode. */ -#if !defined(WIN32) && !defined(MSDOS) +#if !defined(_WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *, char *); int pcap_setnonblock_fd(pcap_t *p, int, char *); #endif -pcap_t *pcap_create_common(const char *, char *); +/* + * Internal interfaces for "pcap_create()". + * + * "pcap_create_interface()" is the routine to do a pcap_create on + * a regular network interface. There are multiple implementations + * of this, one for each platform type (Linux, BPF, DLPI, etc.), + * with the one used chosen by the configure script. + * + * "pcap_create_common()" allocates and fills in a pcap_t, for use + * by pcap_create routines. + */ +pcap_t *pcap_create_interface(const char *, char *); +pcap_t *pcap_create_common(char *, size_t); int pcap_do_addexit(pcap_t *); void pcap_add_to_pcaps_to_close(pcap_t *); void pcap_remove_from_pcaps_to_close(pcap_t *); void pcap_cleanup_live_common(pcap_t *); -int pcap_not_initialized(pcap_t *); int pcap_check_activated(pcap_t *); /* * Internal interfaces for "pcap_findalldevs()". * * "pcap_platform_finddevs()" is a platform-dependent routine to - * add devices not found by the "standard" mechanisms (SIOCGIFCONF, - * "getifaddrs()", etc.. + * find local network interfaces. * - * "pcap_add_if()" adds an interface to the list of interfaces. + * "pcap_findalldevs_interfaces()" is a helper to find those interfaces + * using the "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.). + * + * "pcap_add_if()" adds an interface to the list of interfaces, for + * use by various "find interfaces" routines. */ int pcap_platform_finddevs(pcap_if_t **, char *); -int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *, - size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, - struct sockaddr *, size_t, char *); -int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *); -struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); -int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, +#if !defined(_WIN32) && !defined(MSDOS) +int pcap_findalldevs_interfaces(pcap_if_t **, char *, + int (*)(const char *)); +#endif +int add_addr_to_iflist(pcap_if_t **, const char *, bpf_u_int32, + struct sockaddr *, size_t, struct sockaddr *, size_t, + struct sockaddr *, size_t, struct sockaddr *, size_t, char *); +int add_addr_to_dev(pcap_if_t *, struct sockaddr *, size_t, + struct sockaddr *, size_t, struct sockaddr *, size_t, + struct sockaddr *dstaddr, size_t, char *errbuf); +int pcap_add_if(pcap_if_t **, const char *, bpf_u_int32, const char *, + char *); +int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, bpf_u_int32, const char *, char *); +#ifndef _WIN32 +bpf_u_int32 if_flags_to_pcap_flags(const char *, u_int); +#endif + +/* + * Internal interfaces for "pcap_open_offline()". + * + * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use + * by pcap_open_offline routines. + * + * "sf_cleanup()" closes the file handle associated with a pcap_t, if + * appropriate, and frees all data common to all modules for handling + * savefile types. + */ +pcap_t *pcap_open_offline_common(char *ebuf, size_t size); +void sf_cleanup(pcap_t *p); + +/* + * Internal interfaces for both "pcap_create()" and routines that + * open savefiles. + * + * "pcap_oneshot()" is the standard one-shot callback for "pcap_next()" + * and "pcap_next_ex()". + */ +void pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *); -#ifdef WIN32 -char *pcap_win32strerror(void); +#ifdef _WIN32 +void pcap_win32_err_to_str(DWORD, char *); #endif int install_bpf_program(pcap_t *, struct bpf_program *);