mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Updated the included libpcap to 1.5.3
This commit is contained in:
@@ -1,3 +1,90 @@
|
||||
Wednesday December 18, 2013 guy@alum.mit.edu
|
||||
Summary for 1.5.3 libpcap release
|
||||
Don't let packets that don't match the current filter get to the
|
||||
application when TPACKET_V3 is used. (GitHub issue #331)
|
||||
Fix handling of pcap_loop()/pcap_dispatch() with a packet count
|
||||
of 0 on some platforms (including Linux with TPACKET_V3).
|
||||
(GitHub issue #333)
|
||||
Work around TPACKET_V3 deficiency that causes packets to be lost
|
||||
when a timeout of 0 is specified. (GitHub issue #335)
|
||||
Man page formatting fixes.
|
||||
|
||||
Wednesday December 4, 2013 guy@alum.mit.edu
|
||||
Summary for 1.5.2 libpcap release
|
||||
Fix libpcap to work when compiled with TPACKET_V3 support and
|
||||
running on a kernel without TPACKET_V3 support. (GitHub
|
||||
issue #329)
|
||||
|
||||
Wednesday November 20, 2013 guy@alum.mit.edu
|
||||
Summary for 1.5.1 libpcap release
|
||||
Report an error, rather than crashing, if an IPv6 address is
|
||||
used for link-layer filtering. (Wireshark bug 9376)
|
||||
|
||||
Wednesday October 30, 2013 guy@alum.mit.edu
|
||||
Summary for 1.5.0 libpcap release
|
||||
TPACKET_V3 support added for Linux
|
||||
Point users to the the-tcpdump-group repository on GitHub rather
|
||||
than the mcr repository
|
||||
Checks added for malloc()/realloc()/etc. failures
|
||||
Fixed build on Solaris 11
|
||||
Support filtering filtering E1 SS7 traffic on MTP2 layer Annex A
|
||||
Use "ln -s" to link man pages by default
|
||||
Add support for getting nanosecond-resolution time stamps when
|
||||
capturing and reading capture files
|
||||
Many changes to autoconf to deal better with non-GCC compilers
|
||||
added many new DLT types
|
||||
|
||||
Saturday April 6, 2013 guy@alum.mit.edu
|
||||
Summary for 1.4.0 libpcap release
|
||||
Add netfilter/nfqueue interface.
|
||||
If we don't have support for IPv6 address resolution, support,
|
||||
in filter expressions, what IPv6 stuff we can.
|
||||
Fix pcap-config to include -lpthread if canusb support is
|
||||
present
|
||||
Try to fix "pcap_parse not defined" problems when --without-flex
|
||||
and --without-bison are used when you have Flex and Bison
|
||||
Fix some issues with the pcap_loop man page.
|
||||
Fix pcap_getnonblock() and pcap_setnonblock() to fill in the
|
||||
supplied error message buffer
|
||||
Fix typo that, it appeared, would cause pcap-libdlpi.c not to
|
||||
compile (perhaps systems with libdlpi also have BPF and use
|
||||
that instead)
|
||||
Catch attempts to call pcap_compile() on a non-activated pcap_t
|
||||
Fix crash on Linux with CAN-USB support without usbfs
|
||||
Fix addition of VLAN tags for Linux cooked captures
|
||||
Check for both EOPNOTSUPP and EINVAL after SIOCETHTOOL ioctl, so
|
||||
that the driver can report either one if it doesn't support
|
||||
SIOCETHTOOL
|
||||
Add DLT_INFINIBAND and DLT_SCTP
|
||||
Describe "proto XXX" and "protochain XXX" in the pcap-filter man
|
||||
page
|
||||
Handle either directories, or symlinks to directories, that
|
||||
correspond to interfaces in /sys/class/net
|
||||
Fix handling of VLAN tag insertion to check, on Linux 3.x
|
||||
kernels, for VLAN tag valid flag
|
||||
Clean up some man pages
|
||||
Support libnl3 as well as libnl1 and libnl2 on Linux
|
||||
Fix handling of Bluetooth devices on 3.x Linux kernels
|
||||
|
||||
Friday March 30, 2012. mcr@sandelman.ca
|
||||
Summary for 1.3.0 libpcap release
|
||||
Handle DLT_PFSYNC in {FreeBSD, other *BSD+Mac OS X, other}.
|
||||
Linux: Don't fail if netfilter isn't enabled in the kernel.
|
||||
Add new link-layer type for NFC Forum LLCP.
|
||||
Put the CANUSB stuff into EXTRA_DIST, so it shows up in the release tarball.
|
||||
Add LINKTYPE_NG40/DLT_NG40.
|
||||
Add DLT_MPEG_2_TS/LINKTYPE_MPEG_2_TS for MPEG-2 transport streams.
|
||||
[PATCH] Fix AIX-3.5 crash with read failure during stress
|
||||
AIX fixes.
|
||||
Introduce --disable-shared configure option.
|
||||
Added initial support for canusb devices.
|
||||
Include the pcap(3PCAP) additions as 1.2.1 changes.
|
||||
many updates to documentation: pcap.3pcap.in
|
||||
Improve 'inbound'/'outbound' capture filters under Linux.
|
||||
Note the cleanup of handling of new DLT_/LINKTYPE_ values.
|
||||
On Lion, don't build for PPC.
|
||||
For mac80211 devices we need to clean up monitor mode on exit.
|
||||
|
||||
Friday December 9, 2011. guy@alum.mit.edu.
|
||||
Summary for 1.2.1 libpcap release
|
||||
Update README file.
|
||||
|
||||
@@ -2,6 +2,7 @@ This file lists people who have contributed to libpcap:
|
||||
|
||||
The current maintainers:
|
||||
Bill Fenner <fenner at research dot att dot com>
|
||||
Denis Ovsienko <infrastation at yandex dot ru>
|
||||
Fulvio Risso <risso at polito dot it>
|
||||
Guy Harris <guy at alum dot mit dot edu>
|
||||
Hannes Gredler <hannes at juniper dot net>
|
||||
@@ -9,18 +10,23 @@ The current maintainers:
|
||||
|
||||
Additional people who have contributed patches:
|
||||
|
||||
Akos Vandra <axos88 at gmail dot com>
|
||||
Alan Bawden <Alan at LCS dot MIT dot EDU>
|
||||
Albert Chin <china at thewrittenword dot com>
|
||||
Alexander 'Leo' Bergolth <Leo dot Bergolth at wu-wien dot ac dot at>
|
||||
Alexey Kuznetsov <kuznet at ms2 dot inr dot ac dot ru>
|
||||
Alon Bar-Lev <alonbl at sourceforge dot net>
|
||||
Andres Perera <andres dot p at zoho dot com>
|
||||
Andrew Brown <atatat at atatdot dot net>
|
||||
<andy-1 at sourceforge dot net>
|
||||
Ani Sinha <ani at aristanetworks dot com>
|
||||
Antti Kantee <pooka at netbsd dot org>
|
||||
Arien Vijn <arienvijn at sourceforge dot net>
|
||||
Arkadiusz Miskiewicz <misiek at pld dot org dot pl>
|
||||
Armando L. Caro Jr. <acaro at mail dot eecis dot udel dot edu>
|
||||
Assar Westerlund <assar at sics dot se>
|
||||
Bill Parker <wp02855 at gmail dot com>
|
||||
Brent Cook <brent at boundary dot com>
|
||||
Brian Ginsbach <ginsbach at cray dot com>
|
||||
Charles M. Hannum <mycroft at netbsd dot org>
|
||||
Chris G. Demetriou <cgd at netbsd dot org>
|
||||
@@ -29,14 +35,21 @@ Additional people who have contributed patches:
|
||||
Chris Pepper <pepper at mail dot reppep dot com>
|
||||
Christian Bell <csbell at myri dot com>
|
||||
Christian Peron <csjp at freebsd dot org>
|
||||
Christian Svensson <blue at cmd dot nu>
|
||||
Daniele Orlandi <daniele at orlandi dot com>
|
||||
Darren Lim <darren dot lim at endace dot com>
|
||||
Darren Reed <darrenr at sun dot com>
|
||||
David Clark <david dot clark at datasoft dot com>
|
||||
David Kaelbling <drk at sgi dot com>
|
||||
David Ward <david dot ward at ll dot mit dot edu>
|
||||
David Young <dyoung at ojctech dot com>
|
||||
Dean Gaudet <dean at arctic dot org>
|
||||
dhruv <rsrivat at sourceforge dot net>
|
||||
Don Ebright <Don dot Ebright at compuware dot com>
|
||||
Dug Song <dugsong at monkey dot org>
|
||||
Dustin Spicuzza <dustin at virtualroadside dot com>
|
||||
dzejarczech <dzejarczech at sourceforge dot net>
|
||||
Edward Sheldrake <ejs1920 at sourceforge dot net>
|
||||
Eric Anderson <anderse at hpl dot hp dot com>
|
||||
Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
|
||||
Felix Obenhuber <felix at obenhuber dot de>
|
||||
@@ -45,31 +58,37 @@ Additional people who have contributed patches:
|
||||
frederich <frederich at sourceforge dot net>
|
||||
Fulko Hew <fulko dot hew at gmail dot com>
|
||||
Fumiyuki Shimizu <fumifumi at abacustech dot jp>
|
||||
Gabor Tatarka <gabor dot tatarka at ericsson dot com>
|
||||
Garrett Cooper <yaberauneya at sourceforge dot net>
|
||||
George Neville-Neil <gnn at freebsd dot org>
|
||||
Gianluca Varenni <gianluca dot varenni at gmail dot com>
|
||||
Gilbert Hoyek <gil_hoyek at hotmail dot com>
|
||||
Gisle Vanem <gvanem at broadpark dot no>
|
||||
Graeme Hewson <ghewson at cix dot compulink dot co dot uk>
|
||||
Gregor Maier <gregor at net dot in dot tum dot de>
|
||||
Greg Stark <gsstark at mit dot edu>
|
||||
Greg Troxel <gdt at ir dot bbn dot com>
|
||||
Gregor Maier <gregor at net dot in dot tum dot de>
|
||||
Guillaume Pelat <endymion_ at users dot sourceforge dot net>
|
||||
Gustavo Zacarias <gustavo at zacarias dot com dot ar>
|
||||
Hagen Paul Pfeifer <hagen at jauu dot net>
|
||||
Henri Doreau <hdoreau at sourceforge dot net>
|
||||
Hyung Sik Yoon <hsyn at kr dot ibm dot com>
|
||||
Igor Khristophorov <igor at atdot dot org>
|
||||
Jakub Zawadzki <darkjames at darkjames dot pl>
|
||||
Jan-Philip Velders <jpv at veldersjes dot net>
|
||||
Jason R. Thorpe <thorpej at netbsd dot org>
|
||||
Javier Achirica <achirica at ttd dot net>
|
||||
Jean-Louis Charton <Jean-Louis dot CHARTON at oikialog dot com>
|
||||
Jean Tourrilhes <jt at hpl dot hp dot com>
|
||||
Jean-Louis Charton <Jean-Louis.CHARTON at oikialog dot com>
|
||||
Jefferson Ogata <jogata at nodc dot noaa dot gov>
|
||||
Jesper Dangaard Brouer <hawk at comx dot dk>
|
||||
Jesper Peterson <jesper at endace dot com>
|
||||
Jiri Slaby <jirislaby at gmail dot com>
|
||||
Joerg Mayer <jmayer at loplof dot de>
|
||||
John Bankier <jbankier at rainfinity dot com>
|
||||
Jon Lindgren <jonl at yubyub dot net>
|
||||
Jon Smirl <jonsmirl at gmail dot com>
|
||||
Jorge Boncompte [DTI2] <jorge at dti2 dot net>
|
||||
Juergen Schoenwaelder <schoenw at ibr dot cs dot tu-bs dot de>
|
||||
Julien Moutinho <julm at savines dot alpes dot fr dot eu dot org>
|
||||
Jung-uk Kim <jkim at FreeBSD dot org>
|
||||
@@ -83,6 +102,7 @@ Additional people who have contributed patches:
|
||||
Love Hörnquist-Åstrand <lha at stacken dot kth dot se>
|
||||
Luis MartinGarcia <luis dot mgarc at gmail dot com>
|
||||
Maciej W. Rozycki <macro at ds2 dot pg dot gda dot pl>
|
||||
Mansour Behabadi <mansour at oxplot dot com>
|
||||
Marcus Felipe Pereira <marcus at task dot com dot br>
|
||||
Mark C. Brown <mbrown at hp dot com>
|
||||
Mark Pizzolato <List-tcpdump-workers at subscriptions dot pizzolato dot net>
|
||||
@@ -91,14 +111,17 @@ Additional people who have contributed patches:
|
||||
Márton Németh <nm127 at freemail dot hu>
|
||||
Matthew Luckie <mjl at luckie dot org dot nz>
|
||||
Max Laier <max at love2party dot net>
|
||||
Michal Labedzki
|
||||
Michal Sekletar <msekleta at redhat dot com>
|
||||
Mike Frysinger <vapier at gmail dot com>
|
||||
Mike Kershaw <dragorn at kismetwireless dot net>
|
||||
Mike Wiacek <mike at iroot dot net>
|
||||
Miroslav Lichvar <mlichvar at redhat dot com>
|
||||
Monroe Williams <monroe at pobox dot com>
|
||||
<nvercamm at sourceforge dot net>
|
||||
N. Leiten <nleiten at sourceforge dot net>
|
||||
Nicolas Dade <ndade at nsd dot dyndns dot org>
|
||||
Niko Delarich <niko dot delarich at gmail dot com>
|
||||
N. Leiten <nleiten at sourceforge dot net>
|
||||
<nvercamm at sourceforge dot net>
|
||||
Octavian Cerna <tavy at ylabs dot com>
|
||||
Olaf Kirch <okir at caldera dot de>
|
||||
Ollie Wild <aaw at users dot sourceforge dot net>
|
||||
@@ -142,8 +165,8 @@ Additional people who have contributed patches:
|
||||
Xianjie Zhang <xzhang at cup dot hp dot com>
|
||||
Xin Li <delphij at FreeBSD dot org>
|
||||
Yen Yen Lim
|
||||
Yvan Vanhullebus <vanhu at sourceforge dot net>
|
||||
Yoann Vandoorselaere <yoann at prelude-ids dot org>
|
||||
Yvan Vanhullebus <vanhu at sourceforge dot net>
|
||||
|
||||
The original LBL crew:
|
||||
Steve McCanne
|
||||
@@ -151,4 +174,4 @@ The original LBL crew:
|
||||
Van Jacobson
|
||||
|
||||
Past maintainers:
|
||||
Jun-ichiro itojun Hagino <itojun at iijlab dot net>
|
||||
Jun-ichiro itojun Hagino <itojun at iijlab dot net> Also see: http://www.wide.ad.jp/itojun-award/
|
||||
|
||||
22
libpcap/Makefile-devel-adds
Normal file
22
libpcap/Makefile-devel-adds
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Auto-regenerate configure script or Makefile when things change.
|
||||
# From autoconf.info . Works best with GNU Make.
|
||||
#
|
||||
${srcdir}/configure: configure.in aclocal.m4
|
||||
cd ${srcdir} && autoconf
|
||||
|
||||
# autoheader might not change config.h.in, so touch a stamp file.
|
||||
${srcdir}/config.h.in: ${srcdir}/stamp-h.in
|
||||
${srcdir}/stamp-h.in: configure.in aclocal.m4
|
||||
cd ${srcdir} && autoheader
|
||||
echo timestamp > ${srcdir}/stamp-h.in
|
||||
|
||||
config.h: stamp-h
|
||||
stamp-h: ${srcdir}/config.h.in config.status
|
||||
./config.status
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
config.status: ${srcdir}/configure
|
||||
./config.status --recheck
|
||||
@@ -47,6 +47,8 @@ VPATH = @srcdir@
|
||||
LD = /usr/bin/ld
|
||||
CC = @CC@
|
||||
AR = @AR@
|
||||
LN_S = @LN_S@
|
||||
MKDEP = @MKDEP@
|
||||
CCOPT = @V_CCOPT@
|
||||
INCLS = -I. @V_INCLS@
|
||||
DEFS = @DEFS@ @V_DEFS@
|
||||
@@ -57,6 +59,7 @@ CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
DYEXT = @DYEXT@
|
||||
V_RPATH_OPT = @V_RPATH_OPT@
|
||||
DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
|
||||
PROG=libpcap
|
||||
|
||||
# Standard CFLAGS
|
||||
@@ -74,7 +77,7 @@ RANLIB = @RANLIB@
|
||||
@rm -f $@
|
||||
$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
|
||||
|
||||
PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@ @NETFILTER_SRC@
|
||||
PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@
|
||||
FSRC = fad-@V_FINDALLDEVS@.c
|
||||
SSRC = @SSRC@
|
||||
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
|
||||
@@ -122,7 +125,8 @@ TESTS = \
|
||||
findalldevstest \
|
||||
nonblocktest \
|
||||
opentest \
|
||||
selpolltest
|
||||
selpolltest \
|
||||
valgrindtest
|
||||
|
||||
TESTS_SRC = \
|
||||
tests/filtertest.c \
|
||||
@@ -130,7 +134,8 @@ TESTS_SRC = \
|
||||
tests/nonblocktest.c \
|
||||
tests/opentest.c \
|
||||
tests/reactivatetest.c \
|
||||
tests/selpolltest.c
|
||||
tests/selpolltest.c \
|
||||
tests/valgrindtest.c
|
||||
|
||||
GENHDR = \
|
||||
scanner.h tokdefs.h version.h
|
||||
@@ -149,10 +154,12 @@ MAN3PCAP_EXPAND = \
|
||||
pcap_compile.3pcap.in \
|
||||
pcap_datalink.3pcap.in \
|
||||
pcap_dump_open.3pcap.in \
|
||||
pcap_get_tstamp_precision.3pcap.in \
|
||||
pcap_list_datalinks.3pcap.in \
|
||||
pcap_list_tstamp_types.3pcap.in \
|
||||
pcap_open_dead.3pcap.in \
|
||||
pcap_open_offline.3pcap.in \
|
||||
pcap_set_tstamp_precision.3pcap.in \
|
||||
pcap_set_tstamp_type.3pcap.in
|
||||
|
||||
MAN3PCAP_NOEXPAND = \
|
||||
@@ -186,6 +193,7 @@ MAN3PCAP_NOEXPAND = \
|
||||
pcap_open_live.3pcap \
|
||||
pcap_set_buffer_size.3pcap \
|
||||
pcap_set_datalink.3pcap \
|
||||
pcap_set_immediate_mode.3pcap \
|
||||
pcap_set_promisc.3pcap \
|
||||
pcap_set_rfmon.3pcap \
|
||||
pcap_set_snaplen.3pcap \
|
||||
@@ -219,6 +227,7 @@ EXTRA_DIST = \
|
||||
INSTALL.txt \
|
||||
LICENSE \
|
||||
Makefile.in \
|
||||
Makefile-devel-adds \
|
||||
README \
|
||||
README.aix \
|
||||
README.dag \
|
||||
@@ -281,9 +290,13 @@ EXTRA_DIST = \
|
||||
pcap-bt-linux.h \
|
||||
pcap-can-linux.c \
|
||||
pcap-can-linux.h \
|
||||
pcap-canusb-linux.c \
|
||||
pcap-canusb-linux.h \
|
||||
pcap-config.in \
|
||||
pcap-dag.c \
|
||||
pcap-dag.h \
|
||||
pcap-dbus.c \
|
||||
pcap-dbus.h \
|
||||
pcap-dlpi.c \
|
||||
pcap-dos.c \
|
||||
pcap-dos.h \
|
||||
@@ -518,6 +531,9 @@ opentest: tests/opentest.c libpcap.a
|
||||
selpolltest: tests/selpolltest.c libpcap.a
|
||||
$(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/tests/selpolltest.c libpcap.a $(LIBS)
|
||||
|
||||
valgrindtest: tests/valgrindtest.c libpcap.a
|
||||
$(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/tests/valgrindtest.c libpcap.a $(LIBS)
|
||||
|
||||
install: install-shared install-archive pcap-config
|
||||
[ -d $(DESTDIR)$(libdir) ] || \
|
||||
(mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
|
||||
@@ -548,42 +564,39 @@ install: install-shared install-archive pcap-config
|
||||
for i in $(MAN3PCAP_EXPAND:.in=); do \
|
||||
$(INSTALL_DATA) $$i \
|
||||
$(DESTDIR)$(mandir)/man3/$$i; done
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_name.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_dump_open.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_findalldevs.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_geterr.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_inject.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_list_datalinks.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_list_tstamp_types.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_loop.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_major_version.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_next_ex.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_next.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_open_offline.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
|
||||
ln $(DESTDIR)$(mandir)/man3/pcap_setnonblock.3pcap \
|
||||
$(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
|
||||
(cd $(DESTDIR)$(mandir)/man3 && \
|
||||
rm -f pcap_datalink_val_to_description.3pcap && \
|
||||
$(LN_S) pcap_datalink_val_to_name.3pcap \
|
||||
pcap_datalink_val_to_description.3pcap && \
|
||||
rm -f pcap_dump_fopen.3pcap && \
|
||||
$(LN_S) pcap_dump_open.3pcap pcap_dump_fopen.3pcap && \
|
||||
rm -f pcap_freealldevs.3pcap && \
|
||||
$(LN_S) pcap_findalldevs.3pcap pcap_freealldevs.3pcap && \
|
||||
rm -f pcap_perror.3pcap && \
|
||||
$(LN_S) pcap_geterr.3pcap pcap_perror.3pcap && \
|
||||
rm -f pcap_sendpacket.3pcap && \
|
||||
$(LN_S) pcap_inject.3pcap pcap_sendpacket.3pcap && \
|
||||
rm -f pcap_free_datalinks.3pcap && \
|
||||
$(LN_S) pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap && \
|
||||
rm -f pcap_free_tstamp_types.3pcap && \
|
||||
$(LN_S) pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap && \
|
||||
rm -f pcap_dispatch.3pcap && \
|
||||
$(LN_S) pcap_loop.3pcap pcap_dispatch.3pcap && \
|
||||
rm -f pcap_minor_version.3pcap && \
|
||||
$(LN_S) pcap_major_version.3pcap pcap_minor_version.3pcap && \
|
||||
rm -f pcap_next.3pcap && \
|
||||
$(LN_S) pcap_next_ex.3pcap pcap_next.3pcap && \
|
||||
rm -f pcap_open_dead_with_tstamp_precision.3pcap && \
|
||||
$(LN_S) pcap_open_dead.3pcap \
|
||||
pcap_open_dead_with_tstamp_precision.3pcap && \
|
||||
rm -f pcap_open_offline_with_tstamp_precision.3pcap && \
|
||||
$(LN_S) pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap && \
|
||||
rm -f pcap_fopen_offline.3pcap && \
|
||||
$(LN_S) pcap_open_offline.3pcap pcap_fopen_offline.3pcap && \
|
||||
rm -f pcap_fopen_offline_with_tstamp_precision.3pcap && \
|
||||
$(LN_S) pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap && \
|
||||
rm -f pcap_getnonblock.3pcap && \
|
||||
$(LN_S) pcap_setnonblock.3pcap pcap_getnonblock.3pcap)
|
||||
for i in $(MANFILE); do \
|
||||
$(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
|
||||
$(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
|
||||
@@ -660,7 +673,10 @@ uninstall: uninstall-shared
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_open_dead_with_tstamp_precision.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_open_offline_with_tstamp_precision.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline_with_tstamp_precision.3pcap
|
||||
rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
|
||||
for i in $(MANFILE); do \
|
||||
rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
|
||||
@@ -705,7 +721,7 @@ packaging/pcap.spec: packaging/pcap.spec.in VERSION
|
||||
RPMVERSION=`cat VERSION | sed s/-.*//g`; \
|
||||
sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $< > $@
|
||||
|
||||
releasetar:
|
||||
releasetar:
|
||||
@cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
|
||||
mkdir $$name; \
|
||||
tar cf - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
|
||||
@@ -715,9 +731,4 @@ releasetar:
|
||||
rm -rf $$name
|
||||
|
||||
depend: $(GENSRC) $(GENHDR) bpf_filter.c
|
||||
./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
@echo your Makefile was out of date, now run $(MAKE) again
|
||||
exit 1
|
||||
$(MKDEP) -c $(CC) -m $(DEPENDENCY_CFLAG) $(DEFS) $(INCLS) $(SRC)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 0198a593ef29d7af319b02dd33f251b58d117827 Mon Sep 17 00:00:00 2001
|
||||
From: David Fifield <david@bamsoftware.com>
|
||||
Date: Mon, 9 Apr 2012 16:55:51 -0700
|
||||
Subject: [PATCH 1/4] Don't autogenerate Lex/Yacc files.
|
||||
Subject: [PATCH 1/2] Don't autogenerate Lex/Yacc files.
|
||||
|
||||
---
|
||||
Makefile.in | 30 ++++++++++--------------------
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 3807934db1b073534a01d9a8546cddcec9be501f Mon Sep 17 00:00:00 2001
|
||||
From: David Fifield <david@bamsoftware.com>
|
||||
Date: Mon, 9 Apr 2012 17:02:40 -0700
|
||||
Subject: [PATCH 2/4] Add the --disable-packet-ring configure option.
|
||||
Subject: [PATCH 2/2] Add the --disable-packet-ring configure option.
|
||||
|
||||
This allows the creation of 32-bit binaries that are compatible with
|
||||
64-bit Linux kernels before version 2.6.27.
|
||||
@@ -40,28 +40,34 @@ index 24097b2..5eca6ab 100644
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
diff --git pcap-linux.c pcap-linux.c
|
||||
index d4f50b7..213558b 100644
|
||||
index 17bd0f5..bd2457d 100644
|
||||
--- pcap-linux.c
|
||||
+++ pcap-linux.c
|
||||
@@ -219,14 +219,16 @@ static const char rcsid[] _U_ =
|
||||
@@ -196,17 +196,19 @@ static const char rcsid[] _U_ =
|
||||
/* check for memory mapped access avaibility. We assume every needed
|
||||
* struct is defined if the macro TPACKET_HDRLEN is defined, because it
|
||||
* uses many ring related structs and macros */
|
||||
-# ifdef TPACKET_HDRLEN
|
||||
-# define HAVE_PACKET_RING
|
||||
-# ifdef TPACKET3_HDRLEN
|
||||
-# define HAVE_TPACKET3
|
||||
-# endif /* TPACKET3_HDRLEN */
|
||||
-# ifdef TPACKET2_HDRLEN
|
||||
-# define HAVE_TPACKET2
|
||||
-# else
|
||||
-# define TPACKET_V1 0
|
||||
-# else /* TPACKET2_HDRLEN */
|
||||
-# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */
|
||||
-# endif /* TPACKET2_HDRLEN */
|
||||
-# endif /* TPACKET_HDRLEN */
|
||||
+# ifdef PCAP_SUPPORT_PACKET_RING
|
||||
+# ifdef TPACKET_HDRLEN
|
||||
+# define HAVE_PACKET_RING
|
||||
+# ifdef TPACKET3_HDRLEN
|
||||
+# define HAVE_TPACKET3
|
||||
+# endif /* TPACKET3_HDRLEN */
|
||||
+# ifdef TPACKET2_HDRLEN
|
||||
+# define HAVE_TPACKET2
|
||||
+# else
|
||||
+# define TPACKET_V1 0
|
||||
+# else /* TPACKET2_HDRLEN */
|
||||
+# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */
|
||||
+# endif /* TPACKET2_HDRLEN */
|
||||
+# endif /* TPACKET_HDRLEN */
|
||||
+# endif /* PCAP_SUPPORT_PACKET_RING */
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
From 6a31f45eb5ae5c7319263806c2962c844efb0e99 Mon Sep 17 00:00:00 2001
|
||||
From: David Fifield <david@bamsoftware.com>
|
||||
Date: Mon, 9 Apr 2012 17:10:19 -0700
|
||||
Subject: [PATCH 3/4] Add a memset call that removes a Valgrind error.
|
||||
|
||||
http://seclists.org/nmap-dev/2010/q3/796
|
||||
---
|
||||
pcap-linux.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git pcap-linux.c pcap-linux.c
|
||||
index 213558b..97092ac 100644
|
||||
--- pcap-linux.c
|
||||
+++ pcap-linux.c
|
||||
@@ -2315,6 +2315,7 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
|
||||
struct sock_fprog fcode;
|
||||
int can_filter_in_kernel;
|
||||
int err = 0;
|
||||
+ memset(&fcode, 0, sizeof(struct sock_fprog));
|
||||
#endif
|
||||
|
||||
if (!handle)
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
From c819d7677bafa2b8f899f50895b498275c0a6375 Mon Sep 17 00:00:00 2001
|
||||
From: David Fifield <david@bamsoftware.com>
|
||||
Date: Mon, 9 Apr 2012 19:48:21 -0700
|
||||
Subject: [PATCH 4/4] Include <netpacket/packet.h> before "pcap/bpf.h".
|
||||
|
||||
On Solaris 11, <netpacket/packet.h> includes <net/bpf.h>, which defines
|
||||
the symbols bpf_program and bpf_insn. The included "pcap/bpf.h" also
|
||||
includes these symbols, and checks whether any bpf.h has already been
|
||||
included; if so, it doesn't include itself. When the includes go in the
|
||||
other order there is no such guard. This is the error I get on Solaris
|
||||
11:
|
||||
|
||||
gcc -O2 -fpic -I. -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./fad-getad.c
|
||||
In file included from /usr/include/netpacket/packet.h:10:0,
|
||||
from ./fad-getad.c:66:
|
||||
/usr/include/net/bpf.h:73:8: error: redefinition of 'struct bpf_program'
|
||||
./pcap/bpf.h:107:8: note: originally defined here
|
||||
In file included from /usr/include/netpacket/packet.h:10:0,
|
||||
from ./fad-getad.c:66:
|
||||
/usr/include/net/bpf.h:253:8: error: redefinition of 'struct bpf_insn'
|
||||
./pcap/bpf.h:109:9: note: originally defined here
|
||||
---
|
||||
fad-getad.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git fad-getad.c fad-getad.c
|
||||
index 742ae1f..519893a 100644
|
||||
--- fad-getad.c
|
||||
+++ fad-getad.c
|
||||
@@ -54,12 +54,6 @@ static const char rcsid[] _U_ =
|
||||
#include <string.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
-#include "pcap-int.h"
|
||||
-
|
||||
-#ifdef HAVE_OS_PROTO_H
|
||||
-#include "os-proto.h"
|
||||
-#endif
|
||||
-
|
||||
#ifdef AF_PACKET
|
||||
# ifdef HAVE_NETPACKET_PACKET_H
|
||||
/* Solaris 11 and later, Linux distributions with newer glibc */
|
||||
@@ -77,6 +71,12 @@ static const char rcsid[] _U_ =
|
||||
# endif /* HAVE_NETPACKET_PACKET_H */
|
||||
#endif /* AF_PACKET */
|
||||
|
||||
+#include "pcap-int.h"
|
||||
+
|
||||
+#ifdef HAVE_OS_PROTO_H
|
||||
+#include "os-proto.h"
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* This is fun.
|
||||
*
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
@@ -3,7 +3,7 @@ and verify the signature.
|
||||
|
||||
cd
|
||||
# Make a copy of this directory.
|
||||
cp -r ~/nmap/NMAP_MODIFICATIONS .
|
||||
cp -r ~/nmap/libpcap/NMAP_MODIFICATIONS .
|
||||
tar xzvf libpcap-X.Y.tar.gz
|
||||
cd nmap
|
||||
rsync -rv --delete ~/libpcap-X.Y/ ~/nmap/libpcap/
|
||||
|
||||
@@ -10,15 +10,15 @@ Please send inquiries/comments/reports to:
|
||||
Anonymous Git is available via:
|
||||
git clone git://bpf.tcpdump.org/libpcap
|
||||
|
||||
Version 1.x.y of LIBPCAP can be retrieved with the CVS tag "libpcap_1_{x}rel{y}":
|
||||
cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_{x}rel{y} libpcap
|
||||
Please submit patches by forking the branch on GitHub at
|
||||
|
||||
Please submit patches against the master copy to the libpcap project on
|
||||
sourceforge.net.
|
||||
http://github.com/the-tcpdump-group/libpcap/tree/master
|
||||
|
||||
and issuing a pull request.
|
||||
|
||||
formerly from Lawrence Berkeley National Laboratory
|
||||
Network Research Group <libpcap@ee.lbl.gov>
|
||||
ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4)
|
||||
ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
|
||||
|
||||
This directory contains source code for libpcap, a system-independent
|
||||
interface for user-level packet capture. libpcap provides a portable
|
||||
@@ -91,15 +91,18 @@ a particular release of libpcap.
|
||||
|
||||
Problems, bugs, questions, desirable enhancements, etc. should be sent
|
||||
to the address "tcpdump-workers@lists.tcpdump.org". Bugs, support
|
||||
requests, and feature requests may also be submitted on the SourceForge
|
||||
site for libpcap at
|
||||
requests, and feature requests may also be submitted on the GitHub issue
|
||||
tracker for libpcap at
|
||||
|
||||
http://sourceforge.net/projects/libpcap/
|
||||
https://github.com/the-tcpdump-group/libpcap/issues
|
||||
|
||||
Source code contributions, etc. should be sent to the email address
|
||||
submitted as patches on the SourceForge site for libpcap.
|
||||
above or submitted by forking the branch on GitHub at
|
||||
|
||||
Current versions can be found at www.tcpdump.org, or the SourceForge
|
||||
site for libpcap.
|
||||
http://github.com/the-tcpdump-group/libpcap/tree/master
|
||||
|
||||
and issuing a pull request.
|
||||
|
||||
Current versions can be found at www.tcpdump.org.
|
||||
|
||||
- The TCPdump team
|
||||
|
||||
@@ -19,11 +19,13 @@ Using BPF:
|
||||
possible a description of the symptoms, including indications of the
|
||||
network link-layer type being wrong or time stamps being wrong).
|
||||
|
||||
If you fix the problems yourself, please submit a patch to
|
||||
If you fix the problems yourself, please submit a patch by forking
|
||||
the branch at
|
||||
|
||||
http://sourceforge.net/projects/libpcap/
|
||||
https://github.com/the-tcpdump-group/libpcap/issues
|
||||
|
||||
so we can incorporate them into the next release.
|
||||
and issuing a pull request, so we can incorporate the fixes into the
|
||||
next release.
|
||||
|
||||
If you don't fix the problems yourself, you can, as a workaround,
|
||||
make libpcap use DLPI instead of BPF.
|
||||
|
||||
@@ -96,12 +96,20 @@ implemented.
|
||||
DAG cards by default capture entire packets including the L2
|
||||
CRC/FCS. If the card is not configured to discard the CRC/FCS, this
|
||||
can confuse applications that use libpcap if they're not prepared for
|
||||
packets to have an FCS. Libpcap now reads the environment variable
|
||||
ERF_FCS_BITS to determine how many bits of CRC/FCS to strip from the
|
||||
end of the captured frame. This defaults to 32 for use with
|
||||
Ethernet. If the card is configured to strip the CRC/FCS, then set
|
||||
ERF_FCS_BITS=0. If used with a HDLC/PoS/PPP/Frame Relay link with 16
|
||||
bit CRC/FCS, then set ERF_FCS_BITS=16.
|
||||
packets to have an FCS.
|
||||
|
||||
Libpcap now reads the environment variable ERF_FCS_BITS to determine
|
||||
how many bits of CRC/FCS to strip from the end of the captured
|
||||
frame. This defaults to 32 for use with Ethernet. If the card is
|
||||
configured to strip the CRC/FCS, then set ERF_FCS_BITS=0. If used with
|
||||
a HDLC/PoS/PPP/Frame Relay link with 16 bit CRC/FCS, then set
|
||||
ERF_FCS_BITS=16.
|
||||
|
||||
If you wish to create a pcap file that DOES contain the Ethernet FCS,
|
||||
specify the environment variable ERF_DONT_STRIP_FCS. This will cause
|
||||
the existing FCS to be captured into the pcap file. Note some
|
||||
applications may incorrectly report capture errors or oversize packets
|
||||
when reading these files.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.2.1
|
||||
1.5.3
|
||||
|
||||
472
libpcap/aclocal.m4
vendored
472
libpcap/aclocal.m4
vendored
@@ -38,16 +38,15 @@ dnl AC_LBL_C_INIT. Now, we run AC_LBL_C_INIT_BEFORE_CC, AC_PROG_CC,
|
||||
dnl and AC_LBL_C_INIT at the top level.
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_C_INIT_BEFORE_CC,
|
||||
[AC_PREREQ(2.50)
|
||||
[
|
||||
AC_BEFORE([$0], [AC_LBL_C_INIT])
|
||||
AC_BEFORE([$0], [AC_PROG_CC])
|
||||
AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
|
||||
AC_BEFORE([$0], [AC_LBL_DEVEL])
|
||||
AC_ARG_WITH(gcc, [ --without-gcc don't use gcc])
|
||||
$1="-O"
|
||||
$2=""
|
||||
$1=""
|
||||
if test "${srcdir}" != "." ; then
|
||||
$2="-I\$(srcdir)"
|
||||
$1="-I\$(srcdir)"
|
||||
fi
|
||||
if test "${CFLAGS+set}" = set; then
|
||||
LBL_CFLAGS="$CFLAGS"
|
||||
@@ -73,9 +72,15 @@ AC_DEFUN(AC_LBL_C_INIT_BEFORE_CC,
|
||||
dnl
|
||||
dnl Determine which compiler we're using (cc or gcc)
|
||||
dnl If using gcc, determine the version number
|
||||
dnl If using cc, require that it support ansi prototypes
|
||||
dnl If using gcc, use -O2 (otherwise use -O)
|
||||
dnl If using cc, explicitly specify /usr/local/include
|
||||
dnl If using cc:
|
||||
dnl require that it support ansi prototypes
|
||||
dnl use -O (AC_PROG_CC will use -g -O2 on gcc, so we don't need to
|
||||
dnl do that ourselves for gcc)
|
||||
dnl add -g flags, as appropriate
|
||||
dnl explicitly specify /usr/local/include
|
||||
dnl
|
||||
dnl NOTE WELL: with newer versions of autoconf, "gcc" means any compiler
|
||||
dnl that defines __GNUC__, which means clang, for example, counts as "gcc".
|
||||
dnl
|
||||
dnl usage:
|
||||
dnl
|
||||
@@ -87,102 +92,106 @@ dnl $1 (copt set)
|
||||
dnl $2 (incls set)
|
||||
dnl CC
|
||||
dnl LDFLAGS
|
||||
dnl ac_cv_lbl_gcc_vers
|
||||
dnl LBL_CFLAGS
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_C_INIT,
|
||||
[AC_PREREQ(2.50)
|
||||
[
|
||||
AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
|
||||
AC_BEFORE([$0], [AC_LBL_DEVEL])
|
||||
AC_BEFORE([$0], [AC_LBL_SHLIBS_INIT])
|
||||
if test "$GCC" = yes ; then
|
||||
if test "$SHLICC2" = yes ; then
|
||||
ac_cv_lbl_gcc_vers=2
|
||||
$1="-O2"
|
||||
else
|
||||
AC_MSG_CHECKING(gcc version)
|
||||
AC_CACHE_VAL(ac_cv_lbl_gcc_vers,
|
||||
ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \
|
||||
sed -e '/^gcc version /!d' \
|
||||
-e 's/^gcc version //' \
|
||||
-e 's/ .*//' -e 's/^[[[^0-9]]]*//' \
|
||||
-e 's/\..*//'`)
|
||||
AC_MSG_RESULT($ac_cv_lbl_gcc_vers)
|
||||
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
|
||||
$1="-O2"
|
||||
fi
|
||||
fi
|
||||
#
|
||||
# -Werror forces warnings to be errors.
|
||||
#
|
||||
ac_lbl_cc_force_warning_errors=-Werror
|
||||
else
|
||||
AC_MSG_CHECKING(that $CC handles ansi prototypes)
|
||||
AC_CACHE_VAL(ac_cv_lbl_cc_ansi_prototypes,
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>],
|
||||
[int frob(int, char *)],
|
||||
ac_cv_lbl_cc_ansi_prototypes=yes,
|
||||
ac_cv_lbl_cc_ansi_prototypes=no))
|
||||
AC_MSG_RESULT($ac_cv_lbl_cc_ansi_prototypes)
|
||||
if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
|
||||
case "$host_os" in
|
||||
|
||||
hpux*)
|
||||
AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE))
|
||||
savedcflags="$CFLAGS"
|
||||
CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
|
||||
AC_CACHE_VAL(ac_cv_lbl_cc_hpux_cc_aa,
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>],
|
||||
[int frob(int, char *)],
|
||||
ac_cv_lbl_cc_hpux_cc_aa=yes,
|
||||
ac_cv_lbl_cc_hpux_cc_aa=no))
|
||||
AC_MSG_RESULT($ac_cv_lbl_cc_hpux_cc_aa)
|
||||
if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
|
||||
AC_MSG_ERROR(see the INSTALL doc for more info)
|
||||
fi
|
||||
CFLAGS="$savedcflags"
|
||||
$1="-Aa $$1"
|
||||
AC_DEFINE(_HPUX_SOURCE,1,[needed on HP-UX])
|
||||
;;
|
||||
|
||||
osf*)
|
||||
AC_MSG_CHECKING(for ansi mode in DEC compiler ($CC -std1))
|
||||
savedcflags="$CFLAGS"
|
||||
CFLAGS="-std1"
|
||||
AC_CACHE_VAL(ac_cv_lbl_cc_osf1_cc_std1,
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>],
|
||||
[int frob(int, char *)],
|
||||
ac_cv_lbl_cc_osf1_cc_std1=yes,
|
||||
ac_cv_lbl_cc_osf1_cc_std1=no))
|
||||
AC_MSG_RESULT($ac_cv_lbl_cc_osf1_cc_std1)
|
||||
if test $ac_cv_lbl_cc_osf1_cc_std1 = no ; then
|
||||
AC_MSG_ERROR(see the INSTALL doc for more info)
|
||||
fi
|
||||
CFLAGS="$savedcflags"
|
||||
$1="-std1 $$1"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR(see the INSTALL doc for more info)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
$2="$$2 -I/usr/local/include"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
|
||||
case "$host_os" in
|
||||
|
||||
darwin*)
|
||||
#
|
||||
# This is assumed either to be GCC or clang, both
|
||||
# of which use -Werror to force warnings to be errors.
|
||||
#
|
||||
ac_lbl_cc_force_warning_errors=-Werror
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
#
|
||||
# HP C, which is what we presume we're using, doesn't
|
||||
# exit with a non-zero exit status if we hand it an
|
||||
# invalid -W flag, can't be forced to do so even with
|
||||
# +We, and doesn't handle GCC-style -W flags, so we
|
||||
# don't want to try using GCC-style -W flags.
|
||||
#
|
||||
ac_lbl_cc_dont_try_gcc_dashW=yes
|
||||
;;
|
||||
|
||||
irix*)
|
||||
#
|
||||
# MIPS C, which is what we presume we're using, doesn't
|
||||
# necessarily exit with a non-zero exit status if we
|
||||
# hand it an invalid -W flag, can't be forced to do
|
||||
# so, and doesn't handle GCC-style -W flags, so we
|
||||
# don't want to try using GCC-style -W flags.
|
||||
#
|
||||
ac_lbl_cc_dont_try_gcc_dashW=yes
|
||||
#
|
||||
# It also, apparently, defaults to "char" being
|
||||
# unsigned, unlike most other C implementations;
|
||||
# I suppose we could say "signed char" whenever
|
||||
# we want to guarantee a signed "char", but let's
|
||||
# just force signed chars.
|
||||
#
|
||||
# -xansi is normally the default, but the
|
||||
# configure script was setting it; perhaps -cckr
|
||||
# was the default in the Old Days. (Then again,
|
||||
# that would probably be for backwards compatibility
|
||||
# in the days when ANSI C was Shiny and New, i.e.
|
||||
# 1989 and the early '90's, so maybe we can just
|
||||
# drop support for those compilers.)
|
||||
#
|
||||
# -g is equivalent to -g2, which turns off
|
||||
# optimization; we choose -g3, which generates
|
||||
# debugging information but doesn't turn off
|
||||
# optimization (even if the optimization would
|
||||
# cause inaccuracies in debugging).
|
||||
#
|
||||
$1="$$1 -xansi -signed -g3"
|
||||
;;
|
||||
|
||||
osf*)
|
||||
#
|
||||
#
|
||||
# Presumed to be DEC OSF/1, Digital UNIX, or
|
||||
# Tru64 UNIX.
|
||||
#
|
||||
# The DEC C compiler, which is what we presume we're
|
||||
# using, doesn't exit with a non-zero exit status if we
|
||||
# hand it an invalid -W flag, can't be forced to do
|
||||
# so, and doesn't handle GCC-style -W flags, so we
|
||||
# don't want to try using GCC-style -W flags.
|
||||
#
|
||||
ac_lbl_cc_dont_try_gcc_dashW=yes
|
||||
#
|
||||
# -g is equivalent to -g2, which turns off
|
||||
# optimization; we choose -g3, which generates
|
||||
# debugging information but doesn't turn off
|
||||
# optimization (even if the optimization would
|
||||
# cause inaccuracies in debugging).
|
||||
#
|
||||
$1="$$1 -g3"
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
#
|
||||
# Assumed to be Sun C, which requires -errwarn to force
|
||||
# warnings to be treated as errors.
|
||||
#
|
||||
ac_lbl_cc_force_warning_errors=-errwarn
|
||||
;;
|
||||
|
||||
ultrix*)
|
||||
AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
|
||||
AC_CACHE_VAL(ac_cv_lbl_cc_const_proto,
|
||||
@@ -199,9 +208,178 @@ AC_DEFUN(AC_LBL_C_INIT,
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
$1="$$1 -O"
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check whether, if you pass an unknown warning option to the
|
||||
dnl compiler, it fails or just prints a warning message and succeeds.
|
||||
dnl Set ac_lbl_unknown_warning_option_error to the appropriate flag
|
||||
dnl to force an error if it would otherwise just print a warning message
|
||||
dnl and succeed.
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR,
|
||||
[
|
||||
AC_MSG_CHECKING([whether the compiler fails when given an unknown warning option])
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wxyzzy-this-will-never-succeed-xyzzy"
|
||||
AC_TRY_COMPILE(
|
||||
[],
|
||||
[return 0],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
#
|
||||
# We're assuming this is clang, where
|
||||
# -Werror=unknown-warning-option is the appropriate
|
||||
# option to force the compiler to fail.
|
||||
#
|
||||
ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check whether the compiler option specified as the second argument
|
||||
dnl is supported by the compiler and, if so, add it to the macro
|
||||
dnl specified as the first argument
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_CHECK_COMPILER_OPT,
|
||||
[
|
||||
AC_MSG_CHECKING([whether the compiler supports the $2 option])
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
|
||||
AC_TRY_COMPILE(
|
||||
[],
|
||||
[return 0],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
$1="$$1 $2"
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check whether the compiler supports an option to generate
|
||||
dnl Makefile-style dependency lines
|
||||
dnl
|
||||
dnl GCC uses -M for this. Non-GCC compilers that support this
|
||||
dnl use a variety of flags, including but not limited to -M.
|
||||
dnl
|
||||
dnl We test whether the flag in question is supported, as older
|
||||
dnl versions of compilers might not support it.
|
||||
dnl
|
||||
dnl We don't try all the possible flags, just in case some flag means
|
||||
dnl "generate dependencies" on one compiler but means something else
|
||||
dnl on another compiler.
|
||||
dnl
|
||||
dnl Most compilers that support this send the output to the standard
|
||||
dnl output by default. IBM's XLC, however, supports -M but sends
|
||||
dnl the output to {sourcefile-basename}.u, and AIX has no /dev/stdout
|
||||
dnl to work around that, so we don't bother with XLC.
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT,
|
||||
[
|
||||
AC_MSG_CHECKING([whether the compiler supports generating dependencies])
|
||||
if test "$GCC" = yes ; then
|
||||
#
|
||||
# GCC, or a compiler deemed to be GCC by AC_PROG_CC (even
|
||||
# though it's not); we assume that, in this case, the flag
|
||||
# would be -M.
|
||||
#
|
||||
ac_lbl_dependency_flag="-M"
|
||||
else
|
||||
#
|
||||
# Not GCC or a compiler deemed to be GCC; what platform is
|
||||
# this? (We're assuming that if the compiler isn't GCC
|
||||
# it's the compiler from the vendor of the OS; that won't
|
||||
# necessarily be true for x86 platforms, where it might be
|
||||
# the Intel C compiler.)
|
||||
#
|
||||
case "$host_os" in
|
||||
|
||||
irix*|osf*|darwin*)
|
||||
#
|
||||
# MIPS C for IRIX, DEC C, and clang all use -M.
|
||||
#
|
||||
ac_lbl_dependency_flag="-M"
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
#
|
||||
# Sun C uses -xM.
|
||||
#
|
||||
ac_lbl_dependency_flag="-xM"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
#
|
||||
# HP's older C compilers don't support this.
|
||||
# HP's newer C compilers support this with
|
||||
# either +M or +Make; the older compilers
|
||||
# interpret +M as something completely
|
||||
# different, so we use +Make so we don't
|
||||
# think it works with the older compilers.
|
||||
#
|
||||
ac_lbl_dependency_flag="+Make"
|
||||
;;
|
||||
|
||||
*)
|
||||
#
|
||||
# Not one of the above; assume no support for
|
||||
# generating dependencies.
|
||||
#
|
||||
ac_lbl_dependency_flag=""
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#
|
||||
# Is ac_lbl_dependency_flag defined and, if so, does the compiler
|
||||
# complain about it?
|
||||
#
|
||||
# Note: clang doesn't seem to exit with an error status when handed
|
||||
# an unknown non-warning error, even if you pass it
|
||||
# -Werror=unknown-warning-option. However, it always supports
|
||||
# -M, so the fact that this test always succeeds with clang
|
||||
# isn't an issue.
|
||||
#
|
||||
if test ! -z "$ac_lbl_dependency_flag"; then
|
||||
AC_LANG_CONFTEST(
|
||||
[AC_LANG_SOURCE([[int main(void) { return 0; }]])])
|
||||
echo "$CC" $ac_lbl_dependency_flag conftest.c >&5
|
||||
if "$CC" $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT([yes, with $ac_lbl_dependency_flag])
|
||||
DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
|
||||
MKDEP='${srcdir}/mkdep'
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
#
|
||||
# We can't run mkdep, so have "make depend" do
|
||||
# nothing.
|
||||
#
|
||||
MKDEP=:
|
||||
fi
|
||||
rm -rf conftest*
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
#
|
||||
# We can't run mkdep, so have "make depend" do
|
||||
# nothing.
|
||||
#
|
||||
MKDEP=:
|
||||
fi
|
||||
AC_SUBST(DEPENDENCY_CFLAG)
|
||||
AC_SUBST(MKDEP)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Determine what options are needed to build a shared library
|
||||
dnl
|
||||
@@ -256,7 +434,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
|
||||
sparc64*)
|
||||
case "$host_os" in
|
||||
|
||||
freebsd*)
|
||||
freebsd*|openbsd*)
|
||||
PIC_OPT=-fPIC
|
||||
;;
|
||||
esac
|
||||
@@ -458,7 +636,22 @@ dnl Check for flex, default to lex
|
||||
dnl Require flex 2.4 or higher
|
||||
dnl Check for bison, default to yacc
|
||||
dnl Default to lex/yacc if both flex and bison are not available
|
||||
dnl Define the yy prefix string if using flex and bison
|
||||
dnl
|
||||
dnl If we're using flex and bison, pass -P to flex and -p to bison
|
||||
dnl to define a prefix string for the lexer and parser
|
||||
dnl
|
||||
dnl If we're not using flex and bison, don't pass those options
|
||||
dnl (as they might not work - although if "lex" is a wrapper for
|
||||
dnl Flex and "yacc" is a wrapper for Bison, they will work), and
|
||||
dnl define NEED_YYPARSE_WRAPPER (we *CANNOT* use YYBISON to check
|
||||
dnl whether the wrapper is needed, as some people apparently, for
|
||||
dnl some unknown reason, choose to use --without-flex and
|
||||
dnl --without-bison on systems that have Flex and Bison, which
|
||||
dnl means that the "yacc" they end up using is a wrapper that
|
||||
dnl runs "bison -y", and at least some versions of Bison define
|
||||
dnl YYBISON even if run with "-y", so we end up not compiling
|
||||
dnl the yyparse wrapper and end up with a libpcap that doesn't
|
||||
dnl define pcap_parse())
|
||||
dnl
|
||||
dnl usage:
|
||||
dnl
|
||||
@@ -510,6 +703,8 @@ AC_DEFUN(AC_LBL_LEX_AND_YACC,
|
||||
if test "$$1" = flex -a -n "$3" ; then
|
||||
$1="$$1 -P$3"
|
||||
$2="$$2 -p $3"
|
||||
else
|
||||
AC_DEFINE(NEED_YYPARSE_WRAPPER,1,[if we need a pcap_parse wrapper around yyparse])
|
||||
fi])
|
||||
|
||||
dnl
|
||||
@@ -751,9 +946,8 @@ EOF
|
||||
fi])
|
||||
|
||||
dnl
|
||||
dnl If using gcc and the file .devel exists:
|
||||
dnl Compile with -g (if supported) and -Wall
|
||||
dnl If using gcc 2 or later, do extra prototype checking
|
||||
dnl If the file .devel exists:
|
||||
dnl Add some warning flags if the compiler supports them
|
||||
dnl If an os prototype include exists, symlink os-proto.h to it
|
||||
dnl
|
||||
dnl usage:
|
||||
@@ -772,27 +966,24 @@ AC_DEFUN(AC_LBL_DEVEL,
|
||||
$1="$$1 ${LBL_CFLAGS}"
|
||||
fi
|
||||
if test -f .devel ; then
|
||||
if test "$GCC" = yes ; then
|
||||
if test "${LBL_CFLAGS+set}" != set; then
|
||||
if test "$ac_cv_prog_cc_g" = yes ; then
|
||||
$1="-g $$1"
|
||||
fi
|
||||
$1="$$1 -Wall"
|
||||
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
|
||||
$1="$$1 -Wmissing-prototypes -Wstrict-prototypes"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
case "$host_os" in
|
||||
|
||||
irix6*)
|
||||
V_CCOPT="$V_CCOPT -n32"
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
#
|
||||
# Skip all the warning option stuff on some compilers.
|
||||
#
|
||||
if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
|
||||
AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR()
|
||||
AC_LBL_CHECK_COMPILER_OPT($1, -Wall)
|
||||
AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-prototypes)
|
||||
AC_LBL_CHECK_COMPILER_OPT($1, -Wstrict-prototypes)
|
||||
fi
|
||||
AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT()
|
||||
#
|
||||
# We used to set -n32 for IRIX 6 when not using GCC (presumed
|
||||
# to mean that we're using MIPS C or MIPSpro C); it specified
|
||||
# the "new" faster 32-bit ABI, introduced in IRIX 6.2. I'm
|
||||
# not sure why that would be something to do *only* with a
|
||||
# .devel file; why should the ABI for which we produce code
|
||||
# depend on .devel?
|
||||
#
|
||||
os=`echo $host_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
|
||||
name="lbl/os-$os.h"
|
||||
if test -f $name ; then
|
||||
@@ -929,7 +1120,7 @@ dnl
|
||||
AC_DEFUN(AC_C___ATTRIBUTE__, [
|
||||
AC_MSG_CHECKING(for __attribute__)
|
||||
AC_CACHE_VAL(ac_cv___attribute__, [
|
||||
AC_COMPILE_IFELSE(
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_SOURCE([[
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -946,16 +1137,83 @@ main(int argc, char **argv)
|
||||
{
|
||||
foo();
|
||||
}
|
||||
]]),
|
||||
]])],
|
||||
ac_cv___attribute__=yes,
|
||||
ac_cv___attribute__=no)])
|
||||
if test "$ac_cv___attribute__" = "yes"; then
|
||||
AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__])
|
||||
else
|
||||
#
|
||||
# We can't use __attribute__, so we can't use __attribute__((unused)),
|
||||
# so we define _U_ to an empty string.
|
||||
#
|
||||
V_DEFS="$V_DEFS -D_U_=\"\""
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv___attribute__)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Test whether __attribute__((unused)) can be used without warnings
|
||||
dnl
|
||||
|
||||
AC_DEFUN(AC_C___ATTRIBUTE___UNUSED, [
|
||||
AC_MSG_CHECKING([whether __attribute__((unused)) can be used without warnings])
|
||||
AC_CACHE_VAL(ac_cv___attribute___unused, [
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_SOURCE([[
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main(int argc __attribute((unused)), char **argv __attribute((unused)))
|
||||
{
|
||||
printf("Hello, world!\n");
|
||||
return 0;
|
||||
}
|
||||
]])],
|
||||
ac_cv___attribute___unused=yes,
|
||||
ac_cv___attribute___unused=no)])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
if test "$ac_cv___attribute___unused" = "yes"; then
|
||||
V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\""
|
||||
else
|
||||
V_DEFS="$V_DEFS -D_U_=\"\""
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv___attribute__)
|
||||
AC_MSG_RESULT($ac_cv___attribute___unused)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Test whether __attribute__((format)) can be used without warnings
|
||||
dnl
|
||||
|
||||
AC_DEFUN(AC_C___ATTRIBUTE___FORMAT, [
|
||||
AC_MSG_CHECKING([whether __attribute__((format)) can be used without warnings])
|
||||
AC_CACHE_VAL(ac_cv___attribute___format, [
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_SOURCE([[
|
||||
#include <stdlib.h>
|
||||
|
||||
extern int foo(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
foo("%s", "test");
|
||||
}
|
||||
]])],
|
||||
ac_cv___attribute___format=yes,
|
||||
ac_cv___attribute___format=no)])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
if test "$ac_cv___attribute___format" = "yes"; then
|
||||
AC_DEFINE(__ATTRIBUTE___FORMAT_OK, 1,
|
||||
[define if your compiler allows __attribute__((format)) without a warning])
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv___attribute___format)
|
||||
])
|
||||
|
||||
dnl
|
||||
|
||||
@@ -292,11 +292,14 @@ bpf_image(p, n)
|
||||
break;
|
||||
}
|
||||
(void)snprintf(operand, sizeof operand, fmt, v);
|
||||
(void)snprintf(image, sizeof image,
|
||||
(BPF_CLASS(p->code) == BPF_JMP &&
|
||||
BPF_OP(p->code) != BPF_JA) ?
|
||||
"(%03d) %-8s %-16s jt %d\tjf %d"
|
||||
: "(%03d) %-8s %s",
|
||||
n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
|
||||
if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
|
||||
(void)snprintf(image, sizeof image,
|
||||
"(%03d) %-8s %-16s jt %d\tjf %d",
|
||||
n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
|
||||
} else {
|
||||
(void)snprintf(image, sizeof image,
|
||||
"(%03d) %-8s %s",
|
||||
n, op, operand);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,15 @@
|
||||
/* if libnl exists and is version 2.x */
|
||||
#undef HAVE_LIBNL_2_x
|
||||
|
||||
/* if libnl exists and is version 3.x */
|
||||
#undef HAVE_LIBNL_3_x
|
||||
|
||||
/* libnl has NLE_FAILURE */
|
||||
#undef HAVE_LIBNL_NLE
|
||||
|
||||
/* libnl has new-style socket api */
|
||||
#undef HAVE_LIBNL_SOCKETS
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
@@ -211,6 +220,9 @@
|
||||
/* path for device for USB sniffing */
|
||||
#undef LINUX_USB_MON_DEV
|
||||
|
||||
/* if we need a pcap_parse wrapper around yyparse */
|
||||
#undef NEED_YYPARSE_WRAPPER
|
||||
|
||||
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
|
||||
#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
|
||||
|
||||
@@ -232,6 +244,9 @@
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
@@ -244,6 +259,12 @@
|
||||
/* target host supports CAN sniffing */
|
||||
#undef PCAP_SUPPORT_CAN
|
||||
|
||||
/* target host supports canusb */
|
||||
#undef PCAP_SUPPORT_CANUSB
|
||||
|
||||
/* support D-Bus sniffing */
|
||||
#undef PCAP_SUPPORT_DBUS
|
||||
|
||||
/* target host supports netfilter sniffing */
|
||||
#undef PCAP_SUPPORT_NETFILTER
|
||||
|
||||
@@ -253,18 +274,23 @@
|
||||
/* include ACN support */
|
||||
#undef SITA
|
||||
|
||||
/* if struct sockaddr_hci has hci_channel member */
|
||||
#undef SOCKADDR_HCI_HAS_HCI_CHANNEL
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable parser debugging */
|
||||
#undef YYDEBUG
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* needed on HP-UX */
|
||||
#undef _HPUX_SOURCE
|
||||
|
||||
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
|
||||
#undef _LARGEFILE_SOURCE
|
||||
|
||||
@@ -274,6 +300,9 @@
|
||||
/* define on AIX to get certain functions */
|
||||
#undef _SUN
|
||||
|
||||
/* define if your compiler allows __attribute__((format)) without a warning */
|
||||
#undef __ATTRIBUTE___FORMAT_OK
|
||||
|
||||
/* to handle Ultrix compilers that don't support const in prototypes */
|
||||
#undef const
|
||||
|
||||
|
||||
1254
libpcap/configure
vendored
1254
libpcap/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,7 @@ dnl
|
||||
# config.sub.
|
||||
#
|
||||
|
||||
AC_REVISION($Revision: 1.168 $)
|
||||
AC_PREREQ(2.50)
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(pcap.c)
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
@@ -27,6 +26,10 @@ AC_LBL_C_INIT(V_CCOPT, V_INCLS)
|
||||
AC_LBL_SHLIBS_INIT
|
||||
AC_LBL_C_INLINE
|
||||
AC_C___ATTRIBUTE__
|
||||
if test "$ac_cv___attribute__" = "yes"; then
|
||||
AC_C___ATTRIBUTE___UNUSED
|
||||
AC_C___ATTRIBUTE___FORMAT
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(sys/bitypes.h)
|
||||
|
||||
@@ -345,6 +348,16 @@ AC_MSG_RESULT($V_PCAP)
|
||||
#
|
||||
case "$V_PCAP" in
|
||||
dlpi)
|
||||
#
|
||||
# Needed for common functions used by pcap-[dlpi,libdlpi].c
|
||||
#
|
||||
SSRC="dlpisubs.c"
|
||||
|
||||
#
|
||||
# Checks for some header files.
|
||||
#
|
||||
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
|
||||
|
||||
#
|
||||
# Checks to see if Solaris has the public libdlpi(3LIB) library.
|
||||
# Note: The existence of /usr/include/libdlpi.h does not mean it is the
|
||||
@@ -359,9 +372,11 @@ dlpi)
|
||||
saved_ldflags=$LDFLAGS
|
||||
LDFLAGS="$LIBS -L/lib"
|
||||
AC_CHECK_LIB(dlpi, dlpi_walk,
|
||||
LIBS="-ldlpi $LIBS"
|
||||
V_PCAP=libdlpi
|
||||
AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists]),
|
||||
[
|
||||
LIBS="-ldlpi $LIBS"
|
||||
V_PCAP=libdlpi
|
||||
AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists])
|
||||
],
|
||||
V_PCAP=dlpi)
|
||||
LDFLAGS=$saved_ldflags
|
||||
|
||||
@@ -430,19 +445,44 @@ linux)
|
||||
with_libnl=$withval,,)
|
||||
|
||||
if test x$with_libnl != xno ; then
|
||||
have_any_nl="no"
|
||||
|
||||
#
|
||||
# Try libnl 2.x first.
|
||||
# Try libnl 3.x first.
|
||||
#
|
||||
AC_CHECK_LIB(nl, nl_socket_alloc,
|
||||
AC_CHECK_LIB(nl-3, nl_socket_alloc,
|
||||
[
|
||||
#
|
||||
# Yes, we have libnl 2.x.
|
||||
# Yes, we have libnl 3.x.
|
||||
#
|
||||
LIBS="-lnl-genl -lnl $LIBS"
|
||||
LIBS="-lnl-genl-3 -lnl-3 $LIBS"
|
||||
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
|
||||
AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
|
||||
],
|
||||
[
|
||||
AC_DEFINE(HAVE_LIBNL_3_x,1,[if libnl exists and is version 3.x])
|
||||
AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
|
||||
AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
|
||||
V_INCLS="$V_INCLS -I/usr/include/libnl3"
|
||||
have_any_nl="yes"
|
||||
])
|
||||
|
||||
if test x$have_any_nl = xno ; then
|
||||
#
|
||||
# Try libnl 2.x
|
||||
#
|
||||
AC_CHECK_LIB(nl, nl_socket_alloc,
|
||||
[
|
||||
#
|
||||
# Yes, we have libnl 2.x.
|
||||
#
|
||||
LIBS="-lnl-genl -lnl $LIBS"
|
||||
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
|
||||
AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
|
||||
AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
|
||||
AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
|
||||
have_any_nl="yes"
|
||||
])
|
||||
fi
|
||||
|
||||
if test x$have_any_nl = xno ; then
|
||||
#
|
||||
# No, we don't; do we have libnl 1.x?
|
||||
#
|
||||
@@ -453,16 +493,18 @@ linux)
|
||||
#
|
||||
LIBS="-lnl $LIBS"
|
||||
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
|
||||
],
|
||||
[
|
||||
#
|
||||
# No, we don't have libnl at all.
|
||||
#
|
||||
if test x$with_libnl = xyes ; then
|
||||
AC_MSG_ERROR([libnl support requested but libnl not found])
|
||||
fi
|
||||
have_any_nl="yes"
|
||||
])
|
||||
])
|
||||
fi
|
||||
|
||||
if test x$have_any_nl = xno ; then
|
||||
#
|
||||
# No, we don't have libnl at all.
|
||||
#
|
||||
if test x$with_libnl = xyes ; then
|
||||
AC_MSG_ERROR([libnl support requested but libnl not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(linux/ethtool.h,,,
|
||||
@@ -573,7 +615,6 @@ else
|
||||
case "$V_PCAP" in
|
||||
|
||||
dlpi|libdlpi)
|
||||
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
|
||||
#
|
||||
# This might be Solaris 8 or later, with
|
||||
# SIOCGLIFCONF, or it might be some other OS
|
||||
@@ -597,10 +638,6 @@ else
|
||||
else
|
||||
V_FINDALLDEVS=gifc
|
||||
fi
|
||||
#
|
||||
# Needed for common functions used by pcap-[dlpi,libdlpi].c
|
||||
#
|
||||
SSRC="dlpisubs.c"
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -1058,6 +1095,45 @@ darwin*)
|
||||
if test "$enable_universal" != "no"; then
|
||||
case "$host_os" in
|
||||
|
||||
darwin[0-7].*)
|
||||
#
|
||||
# Pre-Tiger. Build only for 32-bit PowerPC; no
|
||||
# need for any special compiler or linker flags.
|
||||
#
|
||||
;;
|
||||
|
||||
darwin8.[0123]*)
|
||||
#
|
||||
# Tiger, prior to Intel support. Build for 32-bit
|
||||
# PowerPC and 64-bit PowerPC, with 32-bit PowerPC
|
||||
# first. (I'm guessing that's what Apple does.)
|
||||
#
|
||||
V_CCOPT="$V_CCOPT -arch ppc -arch ppc64"
|
||||
LDFLAGS="$LDFLAGS -arch ppc -arch ppc64"
|
||||
;;
|
||||
|
||||
darwin8.[456]*)
|
||||
#
|
||||
# Tiger, subsequent to Intel support but prior to
|
||||
# x86-64 support. Build for 32-bit PowerPC, 64-bit
|
||||
# PowerPC, and x86, with 32-bit PowerPC first.
|
||||
# (I'm guessing that's what Apple does.)
|
||||
#
|
||||
V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386"
|
||||
LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386"
|
||||
;;
|
||||
|
||||
darwin8.*)
|
||||
#
|
||||
# All other Tiger, so subsequent to x86-64
|
||||
# support. Build for 32-bit PowerPC, 64-bit
|
||||
# PowerPC, x86, and x86-64, and with 32-bit PowerPC
|
||||
# first. (I'm guessing that's what Apple does.)
|
||||
#
|
||||
V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
|
||||
LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
|
||||
;;
|
||||
|
||||
darwin9.*)
|
||||
#
|
||||
# Leopard. Build for 32-bit PowerPC, 64-bit
|
||||
@@ -1082,11 +1158,13 @@ darwin*)
|
||||
LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
|
||||
;;
|
||||
|
||||
darwin11.*)
|
||||
darwin*)
|
||||
#
|
||||
# Lion. Build for x86-64 and x86, with x86-64
|
||||
# first. (That's probably what Apple does,
|
||||
# given that Rosetta is gone.)
|
||||
# Post-Snow Leopard. Build for x86-64 and
|
||||
# x86, with x86-64 first. (That's probably what
|
||||
# Apple does, given that Rosetta is gone.)
|
||||
# XXX - update if and when Apple drops support
|
||||
# for 32-bit x86 code.
|
||||
#
|
||||
V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
|
||||
LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
|
||||
@@ -1206,9 +1284,16 @@ solaris*)
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(shared,
|
||||
AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@]))
|
||||
test "x$enable_shared" = "xno" && DYEXT="none"
|
||||
|
||||
AC_PROG_RANLIB
|
||||
AC_CHECK_TOOL([AR], [ar])
|
||||
|
||||
AC_PROG_LN_S
|
||||
AC_SUBST(LN_S)
|
||||
|
||||
AC_LBL_DEVEL(V_CCOPT)
|
||||
|
||||
AC_LBL_SOCKADDR_SA_LEN
|
||||
@@ -1323,11 +1408,14 @@ linux*)
|
||||
AC_TRY_COMPILE([
|
||||
AC_INCLUDES_DEFAULT
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_log.h>],
|
||||
#include <linux/netfilter/nfnetlink_log.h>
|
||||
#include <linux/netfilter/nfnetlink_queue.h>],
|
||||
[],
|
||||
ac_cv_netfilter_can_compile=yes,
|
||||
ac_cv_netfilter_can_compile=no))
|
||||
@@ -1347,7 +1435,8 @@ AC_SUBST(NETFILTER_SRC)
|
||||
|
||||
AC_ARG_ENABLE([bluetooth],
|
||||
[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
|
||||
,enable_bluetooth=yes)
|
||||
[],
|
||||
[enable_bluetooth=yes])
|
||||
|
||||
if test "x$enable_bluetooth" != "xno" ; then
|
||||
dnl check for Bluetooth sniffing support
|
||||
@@ -1358,6 +1447,26 @@ if test "x$enable_bluetooth" != "xno" ; then
|
||||
AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
|
||||
BT_SRC=pcap-bt-linux.c
|
||||
AC_MSG_NOTICE(Bluetooth sniffing is supported)
|
||||
|
||||
#
|
||||
# OK, does struct sockaddr_hci have an hci_channel
|
||||
# member?
|
||||
#
|
||||
AC_MSG_CHECKING(if struct sockaddr_hci has hci_channel member)
|
||||
AC_CACHE_VAL(ac_cv_lbl_sockaddr_hci_has_hci_channel,
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
],
|
||||
[u_int i = sizeof(((struct sockaddr_hci *)0)->hci_channel)],
|
||||
ac_cv_lbl_sockaddr_hci_has_hci_channel=yes,
|
||||
ac_cv_lbl_sockaddr_hci_has_hci_channel=no))
|
||||
AC_MSG_RESULT($ac_cv_lbl_sockaddr_hci_has_hci_channel)
|
||||
if test $ac_cv_lbl_sockaddr_hci_has_hci_channel = yes ; then
|
||||
AC_DEFINE(SOCKADDR_HCI_HAS_HCI_CHANNEL,,
|
||||
[if struct sockaddr_hci has hci_channel member])
|
||||
fi
|
||||
],
|
||||
AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
|
||||
)
|
||||
@@ -1370,9 +1479,37 @@ if test "x$enable_bluetooth" != "xno" ; then
|
||||
AC_SUBST(BT_SRC)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([canusb],
|
||||
[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])],
|
||||
[],
|
||||
[enable_canusb=yes])
|
||||
|
||||
if test "x$enable_canusb" != "xno" ; then
|
||||
dnl check for canusb support
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_CHECK_HEADER(libusb-1.0/libusb.h,
|
||||
[
|
||||
AC_DEFINE(PCAP_SUPPORT_CANUSB, 1, [target host supports canusb])
|
||||
CANUSB_SRC=pcap-canusb-linux.c
|
||||
LIBS="-lusb-1.0 -lpthread $LIBS"
|
||||
AC_MSG_NOTICE(canusb sniffing is supported)
|
||||
],
|
||||
AC_MSG_NOTICE(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
|
||||
)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_NOTICE(no canusb support implemented for $host_os)
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(PCAP_SUPPORT_CANUSB)
|
||||
AC_SUBST(CANUSB_SRC)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([can],
|
||||
[AC_HELP_STRING([--enable-can],[enable CAN support @<:@default=yes, if support available@:>@])],
|
||||
,enable_can=yes)
|
||||
[],
|
||||
[enable_can=yes])
|
||||
|
||||
if test "x$enable_can" != "xno" ; then
|
||||
dnl check for CAN sniffing support
|
||||
@@ -1394,6 +1531,57 @@ if test "x$enable_can" != "xno" ; then
|
||||
AC_SUBST(CAN_SRC)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([dbus],
|
||||
[AC_HELP_STRING([--enable-dbus],[enable D-Bus capture support @<:@default=yes, if support available@:>@])],
|
||||
[],
|
||||
[enable_dbus=ifavailable])
|
||||
|
||||
if test "x$enable_dbus" != "xno"; then
|
||||
AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
|
||||
if test "x$PKGCONFIG" != "xno"; then
|
||||
AC_MSG_CHECKING([for D-Bus])
|
||||
if "$PKGCONFIG" dbus-1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
|
||||
DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $DBUS_CFLAGS"
|
||||
LIBS="$LIBS $DBUS_LIBS"
|
||||
AC_MSG_CHECKING(whether the D-Bus library defines dbus_connection_read_write)
|
||||
AC_TRY_LINK(
|
||||
[#include <string.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dbus/dbus.h>],
|
||||
[return dbus_connection_read_write(NULL, 0);],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(PCAP_SUPPORT_DBUS, 1, [support D-Bus sniffing])
|
||||
DBUS_SRC=pcap-dbus.c
|
||||
V_INCLS="$V_INCLS $DBUS_CFLAGS"
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
if test "x$enable_dbus" = "xyes"; then
|
||||
AC_MSG_ERROR([--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()])
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
if test "x$enable_dbus" = "xyes"; then
|
||||
AC_MSG_ERROR([--enable-dbus was given, but the dbus-1 package is not installed])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(PCAP_SUPPORT_DBUS)
|
||||
AC_SUBST(DBUS_SRC)
|
||||
fi
|
||||
|
||||
dnl check for hardware timestamp support
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@@ -1426,14 +1614,16 @@ AC_PROG_INSTALL
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_OUTPUT_COMMANDS([if test -f .devel; then
|
||||
echo timestamp > stamp-h
|
||||
cat Makefile-devel-adds >> Makefile
|
||||
make depend
|
||||
fi])
|
||||
AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
|
||||
pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
|
||||
pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
|
||||
pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap
|
||||
pcap_open_dead.3pcap pcap_open_offline.3pcap
|
||||
pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap
|
||||
pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap
|
||||
pcap_open_offline.3pcap pcap_set_tstamp_precision.3pcap
|
||||
pcap_set_tstamp_type.3pcap)
|
||||
|
||||
if test -f .devel ; then
|
||||
make depend
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -66,6 +66,10 @@ static const char rcsid[] _U_ =
|
||||
#include <stropts.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_LIBDLPI
|
||||
#include <libdlpi.h>
|
||||
#endif
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "dlpisubs.h"
|
||||
|
||||
@@ -79,6 +83,7 @@ static void pcap_stream_err(const char *, int, char *);
|
||||
int
|
||||
pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
|
||||
/*
|
||||
* "ps_recv" counts packets handed to the filter, not packets
|
||||
@@ -103,7 +108,7 @@ pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
|
||||
* the kernel by libpcap, but they may include packets not
|
||||
* yet read from libpcap by the application.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
*ps = pd->stat;
|
||||
|
||||
/*
|
||||
* Add in the drop count, as per the above comment.
|
||||
@@ -120,6 +125,7 @@ int
|
||||
pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
|
||||
int count, u_char *bufp, int len)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
int n, caplen, origlen;
|
||||
u_char *ep, *pk;
|
||||
struct pcap_pkthdr pkthdr;
|
||||
@@ -162,7 +168,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
|
||||
} else
|
||||
#endif
|
||||
sbp = (struct sb_hdr *)bufp;
|
||||
p->md.stat.ps_drop = sbp->sbh_drops;
|
||||
pd->stat.ps_drop = sbp->sbh_drops;
|
||||
pk = bufp + sizeof(*sbp);
|
||||
bufp += sbp->sbh_totlen;
|
||||
origlen = sbp->sbh_origlen;
|
||||
@@ -173,7 +179,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
|
||||
pk = bufp;
|
||||
bufp += caplen;
|
||||
#endif
|
||||
++p->md.stat.ps_recv;
|
||||
++pd->stat.ps_recv;
|
||||
if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
|
||||
@@ -187,7 +193,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
|
||||
if (pkthdr.caplen > p->snapshot)
|
||||
pkthdr.caplen = p->snapshot;
|
||||
(*callback)(user, &pkthdr, pk);
|
||||
if (++n >= count && count >= 0) {
|
||||
if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
|
||||
p->cc = ep - bufp;
|
||||
p->bp = bufp;
|
||||
return (n);
|
||||
@@ -267,46 +273,53 @@ pcap_process_mactype(pcap_t *p, u_int mactype)
|
||||
* Push and configure the buffer module. Returns -1 for error, otherwise 0.
|
||||
*/
|
||||
int
|
||||
pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout)
|
||||
pcap_conf_bufmod(pcap_t *p, int snaplen)
|
||||
{
|
||||
int retv = 0;
|
||||
|
||||
struct timeval to;
|
||||
bpf_u_int32 ss, chunksize;
|
||||
|
||||
/* Non-standard call to get the data nicely buffered. */
|
||||
if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
|
||||
pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
|
||||
retv = -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ss = snaplen;
|
||||
if (ss > 0 &&
|
||||
strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
|
||||
pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
|
||||
retv = -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set up the bufmod timeout. */
|
||||
if (timeout != 0) {
|
||||
struct timeval to;
|
||||
|
||||
to.tv_sec = timeout / 1000;
|
||||
to.tv_usec = (timeout * 1000) % 1000000;
|
||||
if (p->opt.immediate) {
|
||||
/* Set the timeout to zero, for immediate delivery. */
|
||||
to.tv_sec = 0;
|
||||
to.tv_usec = 0;
|
||||
if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
|
||||
pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
|
||||
retv = -1;
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/* Set up the bufmod timeout. */
|
||||
if (p->opt.timeout != 0) {
|
||||
to.tv_sec = p->opt.timeout / 1000;
|
||||
to.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
|
||||
pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the chunk length. */
|
||||
chunksize = CHUNKSIZE;
|
||||
if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
|
||||
!= 0) {
|
||||
pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the chunk length. */
|
||||
chunksize = CHUNKSIZE;
|
||||
if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
|
||||
!= 0) {
|
||||
pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
|
||||
retv = -1;
|
||||
}
|
||||
|
||||
return (retv);
|
||||
return (0);
|
||||
}
|
||||
#endif /* HAVE_SYS_BUFMOD_H */
|
||||
|
||||
|
||||
@@ -10,13 +10,27 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions used by dlpisubs.c.
|
||||
* Private data for capturing on DLPI devices.
|
||||
*/
|
||||
struct pcap_dlpi {
|
||||
#ifdef HAVE_LIBDLPI
|
||||
dlpi_handle_t dlpi_hd;
|
||||
#endif /* HAVE_LIBDLPI */
|
||||
#ifdef DL_HP_RAWDLS
|
||||
int send_fd;
|
||||
#endif /* DL_HP_RAWDLS */
|
||||
|
||||
struct pcap_stat stat;
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions defined by dlpisubs.c.
|
||||
*/
|
||||
int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
|
||||
int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
|
||||
int pcap_process_mactype(pcap_t *, u_int);
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
int pcap_conf_bufmod(pcap_t *, int, int);
|
||||
int pcap_conf_bufmod(pcap_t *, int);
|
||||
#endif
|
||||
int pcap_alloc_databuf(pcap_t *);
|
||||
int strioctl(int, int, int, char *);
|
||||
|
||||
@@ -54,9 +54,21 @@ static const char rcsid[] _U_ =
|
||||
#include <string.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#ifdef AF_PACKET
|
||||
#include "pcap-int.h"
|
||||
|
||||
#ifdef HAVE_OS_PROTO_H
|
||||
#include "os-proto.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We don't do this on Solaris 11 and later, as it appears there aren't
|
||||
* any AF_PACKET addresses on interfaces, so we don't need this, and
|
||||
* we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
|
||||
* and their definitions of some data structures collide.
|
||||
*/
|
||||
#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
|
||||
# ifdef HAVE_NETPACKET_PACKET_H
|
||||
/* Solaris 11 and later, Linux distributions with newer glibc */
|
||||
/* Linux distributions with newer glibc */
|
||||
# include <netpacket/packet.h>
|
||||
# else /* HAVE_NETPACKET_PACKET_H */
|
||||
/* LynxOS, Linux distributions with older glibc */
|
||||
@@ -69,13 +81,7 @@ static const char rcsid[] _U_ =
|
||||
# include <linux/if_packet.h>
|
||||
# endif /* __Lynx__ */
|
||||
# endif /* HAVE_NETPACKET_PACKET_H */
|
||||
#endif /* AF_PACKET */
|
||||
|
||||
#include "pcap-int.h"
|
||||
|
||||
#ifdef HAVE_OS_PROTO_H
|
||||
#include "os-proto.h"
|
||||
#endif
|
||||
#endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
|
||||
|
||||
/*
|
||||
* This is fun.
|
||||
@@ -120,7 +126,7 @@ get_sa_len(struct sockaddr *addr)
|
||||
return (sizeof (struct sockaddr_in6));
|
||||
#endif
|
||||
|
||||
#ifdef AF_PACKET
|
||||
#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
|
||||
case AF_PACKET:
|
||||
return (sizeof (struct sockaddr_ll));
|
||||
#endif
|
||||
@@ -141,11 +147,9 @@ get_sa_len(struct sockaddr *addr)
|
||||
* Returns -1 on error, 0 otherwise.
|
||||
* The list, as returned through "alldevsp", may be null if no interfaces
|
||||
* were up and could be opened.
|
||||
*
|
||||
* This is the implementation used on platforms that have "getifaddrs()".
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
pcap_if_t *devlist = NULL;
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
@@ -273,15 +277,6 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
|
||||
freeifaddrs(ifap);
|
||||
|
||||
if (ret != -1) {
|
||||
/*
|
||||
* We haven't had any errors yet; do any platform-specific
|
||||
* operations to add devices.
|
||||
*/
|
||||
if (pcap_platform_finddevs(&devlist, errbuf) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* We had an error; free the list we've been constructing.
|
||||
|
||||
@@ -133,10 +133,11 @@ struct rtentry; /* declarations in <net/if.h> */
|
||||
*
|
||||
* XXX - or platforms that have other, better mechanisms but for which
|
||||
* we don't yet have code to use that mechanism; I think there's a better
|
||||
* way on Linux, for example.
|
||||
* way on Linux, for example, but if that better way is "getifaddrs()",
|
||||
* we already have that.
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
pcap_if_t *devlist = NULL;
|
||||
register int fd;
|
||||
@@ -409,15 +410,6 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
free(buf);
|
||||
(void)close(fd);
|
||||
|
||||
if (ret != -1) {
|
||||
/*
|
||||
* We haven't had any errors yet; do any platform-specific
|
||||
* operations to add devices.
|
||||
*/
|
||||
if (pcap_platform_finddevs(&devlist, errbuf) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* We had an error; free the list we've been constructing.
|
||||
|
||||
@@ -80,7 +80,7 @@ struct rtentry; /* declarations in <net/if.h> */
|
||||
* SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
pcap_if_t *devlist = NULL;
|
||||
register int fd4, fd6, fd;
|
||||
@@ -362,15 +362,6 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
(void)close(fd6);
|
||||
(void)close(fd4);
|
||||
|
||||
if (ret != -1) {
|
||||
/*
|
||||
* We haven't had any errors yet; do any platform-specific
|
||||
* operations to add devices.
|
||||
*/
|
||||
if (pcap_platform_finddevs(&devlist, errbuf) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* We had an error; free the list we've been constructing.
|
||||
|
||||
@@ -53,7 +53,7 @@ static const char rcsid[] _U_ =
|
||||
* packet capture.
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
/*
|
||||
* Succeed, but don't return any interfaces; we return only those
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
extern pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
|
||||
|
||||
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) {
|
||||
int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) {
|
||||
|
||||
//printf("pcap_findalldevs()\n"); // fulko
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
||||
* Win32 implementation, based on WinPcap
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
pcap_if_t *devlist = NULL;
|
||||
int ret = 0;
|
||||
@@ -225,6 +225,24 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
ULONG NameLength;
|
||||
char *name;
|
||||
|
||||
/*
|
||||
* Find out how big a buffer we need.
|
||||
*
|
||||
* This call should always return FALSE; if the error is
|
||||
* ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
|
||||
* the size of the buffer we need, otherwise there's a
|
||||
* problem, and NameLength should be set to 0.
|
||||
*
|
||||
* It shouldn't require NameLength to be set, but,
|
||||
* at least as of WinPcap 4.1.3, it checks whether
|
||||
* NameLength is big enough before it checks for a
|
||||
* NULL buffer argument, so, while it'll still do
|
||||
* the right thing if NameLength is uninitialized and
|
||||
* whatever junk happens to be there is big enough
|
||||
* (because the pointer argument will be null), it's
|
||||
* still reading an uninitialized variable.
|
||||
*/
|
||||
NameLength = 0;
|
||||
if (!PacketGetAdapterNames(NULL, &NameLength))
|
||||
{
|
||||
DWORD last_error = GetLastError();
|
||||
|
||||
@@ -84,6 +84,11 @@ static const char rcsid[] _U_ =
|
||||
#include "pcap/sll.h"
|
||||
#include "pcap/ipnet.h"
|
||||
#include "arcnet.h"
|
||||
#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/filter.h>
|
||||
#endif
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
@@ -102,6 +107,18 @@ static const char rcsid[] _U_ =
|
||||
|
||||
#define ETHERMTU 1500
|
||||
|
||||
#ifndef IPPROTO_HOPOPTS
|
||||
#define IPPROTO_HOPOPTS 0
|
||||
#endif
|
||||
#ifndef IPPROTO_ROUTING
|
||||
#define IPPROTO_ROUTING 43
|
||||
#endif
|
||||
#ifndef IPPROTO_FRAGMENT
|
||||
#define IPPROTO_FRAGMENT 44
|
||||
#endif
|
||||
#ifndef IPPROTO_DSTOPTS
|
||||
#define IPPROTO_DSTOPTS 60
|
||||
#endif
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
@@ -124,9 +141,7 @@ static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
|
||||
#endif
|
||||
|
||||
/* XXX */
|
||||
#ifdef PCAP_FDDIPAD
|
||||
static int pcap_fddipad;
|
||||
#endif
|
||||
|
||||
/* VARARGS */
|
||||
void
|
||||
@@ -256,20 +271,16 @@ static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
|
||||
static struct block *gen_ipfrag(void);
|
||||
static struct block *gen_portatom(int, bpf_int32);
|
||||
static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
|
||||
#ifdef INET6
|
||||
static struct block *gen_portatom6(int, bpf_int32);
|
||||
static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
|
||||
#endif
|
||||
struct block *gen_portop(int, int, int);
|
||||
static struct block *gen_port(int, int, int);
|
||||
struct block *gen_portrangeop(int, int, int, int);
|
||||
static struct block *gen_portrange(int, int, int, int);
|
||||
#ifdef INET6
|
||||
struct block *gen_portop6(int, int, int);
|
||||
static struct block *gen_port6(int, int, int);
|
||||
struct block *gen_portrangeop6(int, int, int, int);
|
||||
static struct block *gen_portrange6(int, int, int, int);
|
||||
#endif
|
||||
static int lookup_proto(const char *, int);
|
||||
static struct block *gen_protochain(int, int, int);
|
||||
static struct block *gen_proto(int, int, int);
|
||||
@@ -418,8 +429,17 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
|
||||
{
|
||||
extern int n_errors;
|
||||
const char * volatile xbuf = buf;
|
||||
int len;
|
||||
u_int len;
|
||||
|
||||
/*
|
||||
* If this pcap_t hasn't been activated, it doesn't have a
|
||||
* link-layer type, so we can't use it.
|
||||
*/
|
||||
if (!p->activated) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"not-yet-activated pcap_t passed to pcap_compile");
|
||||
return (-1);
|
||||
}
|
||||
no_optimize = 0;
|
||||
n_errors = 0;
|
||||
root = NULL;
|
||||
@@ -854,6 +874,7 @@ static u_int off_proto;
|
||||
* These are offsets for the MTP2 fields.
|
||||
*/
|
||||
static u_int off_li;
|
||||
static u_int off_li_hsl;
|
||||
|
||||
/*
|
||||
* These are offsets for the MTP3 fields.
|
||||
@@ -903,9 +924,7 @@ init_linktype(p)
|
||||
pcap_t *p;
|
||||
{
|
||||
linktype = pcap_datalink(p);
|
||||
#ifdef PCAP_FDDIPAD
|
||||
pcap_fddipad = p->fddipad;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assume it's not raw ATM with a pseudo-header, for now.
|
||||
@@ -927,6 +946,7 @@ init_linktype(p)
|
||||
* And assume we're not doing SS7.
|
||||
*/
|
||||
off_li = -1;
|
||||
off_li_hsl = -1;
|
||||
off_sio = -1;
|
||||
off_opc = -1;
|
||||
off_dpc = -1;
|
||||
@@ -1042,13 +1062,9 @@ init_linktype(p)
|
||||
* XXX - should we generate code to check for SNAP?
|
||||
*/
|
||||
off_linktype = 13;
|
||||
#ifdef PCAP_FDDIPAD
|
||||
off_linktype += pcap_fddipad;
|
||||
#endif
|
||||
off_macpl = 13; /* FDDI MAC header length */
|
||||
#ifdef PCAP_FDDIPAD
|
||||
off_macpl += pcap_fddipad;
|
||||
#endif
|
||||
off_nl = 8; /* 802.2+SNAP */
|
||||
off_nl_nosnap = 3; /* 802.2 */
|
||||
return;
|
||||
@@ -1319,6 +1335,13 @@ init_linktype(p)
|
||||
off_nl_nosnap = -1; /* no 802.2 LLC */
|
||||
return;
|
||||
|
||||
case DLT_BACNET_MS_TP:
|
||||
off_linktype = -1;
|
||||
off_macpl = -1;
|
||||
off_nl = -1;
|
||||
off_nl_nosnap = -1;
|
||||
return;
|
||||
|
||||
case DLT_JUNIPER_SERVICES:
|
||||
off_linktype = 12;
|
||||
off_macpl = -1; /* L3 proto location dep. on cookie type */
|
||||
@@ -1359,6 +1382,7 @@ init_linktype(p)
|
||||
|
||||
case DLT_MTP2:
|
||||
off_li = 2;
|
||||
off_li_hsl = 4;
|
||||
off_sio = 3;
|
||||
off_opc = 4;
|
||||
off_dpc = 4;
|
||||
@@ -1371,6 +1395,7 @@ init_linktype(p)
|
||||
|
||||
case DLT_MTP2_WITH_PHDR:
|
||||
off_li = 6;
|
||||
off_li_hsl = 8;
|
||||
off_sio = 7;
|
||||
off_opc = 8;
|
||||
off_dpc = 8;
|
||||
@@ -1383,6 +1408,7 @@ init_linktype(p)
|
||||
|
||||
case DLT_ERF:
|
||||
off_li = 22;
|
||||
off_li_hsl = 24;
|
||||
off_sio = 23;
|
||||
off_opc = 24;
|
||||
off_dpc = 24;
|
||||
@@ -1393,14 +1419,12 @@ init_linktype(p)
|
||||
off_nl_nosnap = -1;
|
||||
return;
|
||||
|
||||
#ifdef DLT_PFSYNC
|
||||
case DLT_PFSYNC:
|
||||
off_linktype = -1;
|
||||
off_macpl = 4;
|
||||
off_nl = 0;
|
||||
off_nl_nosnap = 0;
|
||||
return;
|
||||
#endif
|
||||
|
||||
case DLT_AX25_KISS:
|
||||
/*
|
||||
@@ -2829,11 +2853,9 @@ ethertype_to_ppptype(proto)
|
||||
proto = PPP_IP;
|
||||
break;
|
||||
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
proto = PPP_IPV6;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ETHERTYPE_DN:
|
||||
proto = PPP_DECNET;
|
||||
@@ -3041,11 +3063,10 @@ gen_linktype(proto)
|
||||
case ETHERTYPE_IP:
|
||||
/* Check for a version number of 4. */
|
||||
return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
|
||||
#ifdef INET6
|
||||
|
||||
case ETHERTYPE_IPV6:
|
||||
/* Check for a version number of 6. */
|
||||
return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return gen_false(); /* always false */
|
||||
@@ -3069,10 +3090,8 @@ gen_linktype(proto)
|
||||
/*
|
||||
* Raw IPv6, so no type field.
|
||||
*/
|
||||
#ifdef INET6
|
||||
if (proto == ETHERTYPE_IPV6)
|
||||
return gen_true(); /* always true */
|
||||
#endif
|
||||
|
||||
/* Checking for something other than IPv6; always false */
|
||||
return gen_false();
|
||||
@@ -3178,8 +3197,7 @@ gen_linktype(proto)
|
||||
* Then we run it through "htonl()", and
|
||||
* generate code to compare against the result.
|
||||
*/
|
||||
if (bpf_pcap->sf.rfile != NULL &&
|
||||
bpf_pcap->sf.swapped)
|
||||
if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
|
||||
proto = SWAPLONG(proto);
|
||||
proto = htonl(proto);
|
||||
}
|
||||
@@ -3194,11 +3212,9 @@ gen_linktype(proto)
|
||||
if (proto == ETHERTYPE_IP)
|
||||
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
|
||||
BPF_B, (bpf_int32)AF_INET));
|
||||
#ifdef INET6
|
||||
else if (proto == ETHERTYPE_IPV6)
|
||||
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
|
||||
BPF_B, (bpf_int32)AF_INET6));
|
||||
#endif /* INET6 */
|
||||
else
|
||||
return gen_false();
|
||||
/*NOTREACHED*/
|
||||
@@ -3216,11 +3232,9 @@ gen_linktype(proto)
|
||||
default:
|
||||
return gen_false();
|
||||
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
return (gen_cmp(OR_LINK, off_linktype, BPF_B,
|
||||
(bpf_int32)ARCTYPE_INET6));
|
||||
#endif /* INET6 */
|
||||
|
||||
case ETHERTYPE_IP:
|
||||
b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
|
||||
@@ -3272,13 +3286,11 @@ gen_linktype(proto)
|
||||
*/
|
||||
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
|
||||
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
/*
|
||||
* Check for the special NLPID for IPv6.
|
||||
*/
|
||||
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
|
||||
#endif
|
||||
|
||||
case LLCSAP_ISONS:
|
||||
/*
|
||||
@@ -3340,6 +3352,9 @@ gen_linktype(proto)
|
||||
*/
|
||||
return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
|
||||
|
||||
case DLT_BACNET_MS_TP:
|
||||
return gen_mcmp(OR_LINK, 0, BPF_W, 0x55FF0000, 0xffff0000);
|
||||
|
||||
case DLT_IPNET:
|
||||
return gen_ipnet_linktype(proto);
|
||||
|
||||
@@ -3356,10 +3371,8 @@ gen_linktype(proto)
|
||||
case DLT_ERF:
|
||||
bpf_error("ERF link-layer type filtering not implemented");
|
||||
|
||||
#ifdef DLT_PFSYNC
|
||||
case DLT_PFSYNC:
|
||||
bpf_error("PFSYNC link-layer type filtering not implemented");
|
||||
#endif
|
||||
|
||||
case DLT_LINUX_LAPD:
|
||||
bpf_error("LAPD link-layer type filtering not implemented");
|
||||
@@ -3627,7 +3640,7 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
|
||||
gen_and(b0, b1);
|
||||
return b1;
|
||||
}
|
||||
#endif /*INET6*/
|
||||
#endif
|
||||
|
||||
static struct block *
|
||||
gen_ehostop(eaddr, dir)
|
||||
@@ -3696,18 +3709,10 @@ gen_fhostop(eaddr, dir)
|
||||
|
||||
switch (dir) {
|
||||
case Q_SRC:
|
||||
#ifdef PCAP_FDDIPAD
|
||||
return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
|
||||
#else
|
||||
return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
|
||||
#endif
|
||||
|
||||
case Q_DST:
|
||||
#ifdef PCAP_FDDIPAD
|
||||
return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
|
||||
#else
|
||||
return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
|
||||
#endif
|
||||
|
||||
case Q_AND:
|
||||
b0 = gen_fhostop(eaddr, Q_SRC);
|
||||
@@ -4505,13 +4510,11 @@ gen_host(addr, mask, proto, dir, type)
|
||||
case Q_MOPRC:
|
||||
bpf_error("MOPRC host filtering not implemented");
|
||||
|
||||
#ifdef INET6
|
||||
case Q_IPV6:
|
||||
bpf_error("'ip6' modifier applied to ip host");
|
||||
|
||||
case Q_ICMPV6:
|
||||
bpf_error("'icmp6' modifier applied to %s", typestr);
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_AH:
|
||||
bpf_error("'ah' modifier applied to %s", typestr);
|
||||
@@ -4570,6 +4573,9 @@ gen_host6(addr, mask, proto, dir, type)
|
||||
case Q_DEFAULT:
|
||||
return gen_host6(addr, mask, Q_IPV6, dir, type);
|
||||
|
||||
case Q_LINK:
|
||||
bpf_error("link-layer modifier applied to ip6 %s", typestr);
|
||||
|
||||
case Q_IP:
|
||||
bpf_error("'ip' modifier applied to ip6 %s", typestr);
|
||||
|
||||
@@ -4668,7 +4674,7 @@ gen_host6(addr, mask, proto, dir, type)
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif /*INET6*/
|
||||
#endif
|
||||
|
||||
#ifndef INET6
|
||||
static struct block *
|
||||
@@ -4760,26 +4766,20 @@ gen_proto_abbrev(proto)
|
||||
|
||||
case Q_SCTP:
|
||||
b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Q_TCP:
|
||||
b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Q_UDP:
|
||||
b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Q_ICMP:
|
||||
@@ -4807,10 +4807,8 @@ gen_proto_abbrev(proto)
|
||||
|
||||
case Q_PIM:
|
||||
b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifndef IPPROTO_VRRP
|
||||
@@ -4872,7 +4870,6 @@ gen_proto_abbrev(proto)
|
||||
b1 = gen_linktype(ETHERTYPE_MOPRC);
|
||||
break;
|
||||
|
||||
#ifdef INET6
|
||||
case Q_IPV6:
|
||||
b1 = gen_linktype(ETHERTYPE_IPV6);
|
||||
break;
|
||||
@@ -4883,17 +4880,14 @@ gen_proto_abbrev(proto)
|
||||
case Q_ICMPV6:
|
||||
b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
|
||||
#ifndef IPPROTO_AH
|
||||
#define IPPROTO_AH 51
|
||||
#endif
|
||||
case Q_AH:
|
||||
b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifndef IPPROTO_ESP
|
||||
@@ -4901,10 +4895,8 @@ gen_proto_abbrev(proto)
|
||||
#endif
|
||||
case Q_ESP:
|
||||
b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
|
||||
gen_or(b0, b1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Q_ISO:
|
||||
@@ -5037,7 +5029,6 @@ gen_portatom(off, v)
|
||||
return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static struct block *
|
||||
gen_portatom6(off, v)
|
||||
int off;
|
||||
@@ -5045,7 +5036,6 @@ gen_portatom6(off, v)
|
||||
{
|
||||
return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
|
||||
}
|
||||
#endif/*INET6*/
|
||||
|
||||
struct block *
|
||||
gen_portop(port, proto, dir)
|
||||
@@ -5137,7 +5127,6 @@ gen_port(port, ip_proto, dir)
|
||||
return b1;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
struct block *
|
||||
gen_portop6(port, proto, dir)
|
||||
int port, proto, dir;
|
||||
@@ -5210,7 +5199,6 @@ gen_port6(port, ip_proto, dir)
|
||||
gen_and(b0, b1);
|
||||
return b1;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
/* gen_portrange code */
|
||||
static struct block *
|
||||
@@ -5315,7 +5303,6 @@ gen_portrange(port1, port2, ip_proto, dir)
|
||||
return b1;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static struct block *
|
||||
gen_portrangeatom6(off, v1, v2)
|
||||
int off;
|
||||
@@ -5416,7 +5403,6 @@ gen_portrange6(port1, port2, ip_proto, dir)
|
||||
gen_and(b0, b1);
|
||||
return b1;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
static int
|
||||
lookup_proto(name, proto)
|
||||
@@ -5551,7 +5537,7 @@ gen_protochain(v, proto, dir)
|
||||
s[i]->s.k = off_macpl + off_nl;
|
||||
i++;
|
||||
break;
|
||||
#ifdef INET6
|
||||
|
||||
case Q_IPV6:
|
||||
b0 = gen_linktype(ETHERTYPE_IPV6);
|
||||
|
||||
@@ -5564,7 +5550,7 @@ gen_protochain(v, proto, dir)
|
||||
s[i]->s.k = 40;
|
||||
i++;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
bpf_error("unsupported proto to gen_protochain");
|
||||
/*NOTREACHED*/
|
||||
@@ -5591,7 +5577,6 @@ gen_protochain(v, proto, dir)
|
||||
fix2 = i;
|
||||
i++;
|
||||
|
||||
#ifdef INET6
|
||||
if (proto == Q_IPV6) {
|
||||
int v6start, v6end, v6advance, j;
|
||||
|
||||
@@ -5673,9 +5658,7 @@ gen_protochain(v, proto, dir)
|
||||
/* fixup */
|
||||
for (j = v6start; j <= v6end; j++)
|
||||
s[j]->s.jt = s[v6advance];
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
} else {
|
||||
/* nop */
|
||||
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
|
||||
s[i]->s.k = 0;
|
||||
@@ -5819,20 +5802,20 @@ gen_proto(v, proto, dir)
|
||||
int dir;
|
||||
{
|
||||
struct block *b0, *b1;
|
||||
#ifndef CHASE_CHAIN
|
||||
struct block *b2;
|
||||
#endif
|
||||
|
||||
if (dir != Q_DEFAULT)
|
||||
bpf_error("direction applied to 'proto'");
|
||||
|
||||
switch (proto) {
|
||||
case Q_DEFAULT:
|
||||
#ifdef INET6
|
||||
b0 = gen_proto(v, Q_IP, dir);
|
||||
b1 = gen_proto(v, Q_IPV6, dir);
|
||||
gen_or(b0, b1);
|
||||
return b1;
|
||||
#else
|
||||
/*FALLTHROUGH*/
|
||||
#endif
|
||||
|
||||
case Q_IP:
|
||||
/*
|
||||
* For FDDI, RFC 1188 says that SNAP encapsulation is used,
|
||||
@@ -5983,11 +5966,18 @@ gen_proto(v, proto, dir)
|
||||
bpf_error("'carp proto' is bogus");
|
||||
/* NOTREACHED */
|
||||
|
||||
#ifdef INET6
|
||||
case Q_IPV6:
|
||||
b0 = gen_linktype(ETHERTYPE_IPV6);
|
||||
#ifndef CHASE_CHAIN
|
||||
b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
|
||||
/*
|
||||
* Also check for a fragment header before the final
|
||||
* header.
|
||||
*/
|
||||
b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
|
||||
b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
|
||||
gen_and(b2, b1);
|
||||
b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
|
||||
gen_or(b2, b1);
|
||||
#else
|
||||
b1 = gen_protochain(v, Q_IPV6);
|
||||
#endif
|
||||
@@ -5996,7 +5986,6 @@ gen_proto(v, proto, dir)
|
||||
|
||||
case Q_ICMPV6:
|
||||
bpf_error("'icmp6 proto' is bogus");
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_AH:
|
||||
bpf_error("'ah proto' is bogus");
|
||||
@@ -6253,13 +6242,9 @@ gen_scode(name, q)
|
||||
bpf_error("illegal port number %d < 0", port);
|
||||
if (port > 65535)
|
||||
bpf_error("illegal port number %d > 65535", port);
|
||||
#ifndef INET6
|
||||
return gen_port(port, real_proto, dir);
|
||||
#else
|
||||
b = gen_port(port, real_proto, dir);
|
||||
gen_or(gen_port6(port, real_proto, dir), b);
|
||||
return b;
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_PORTRANGE:
|
||||
if (proto != Q_DEFAULT &&
|
||||
@@ -6303,13 +6288,9 @@ gen_scode(name, q)
|
||||
if (port2 > 65535)
|
||||
bpf_error("illegal port number %d > 65535", port2);
|
||||
|
||||
#ifndef INET6
|
||||
return gen_portrange(port1, port2, real_proto, dir);
|
||||
#else
|
||||
b = gen_portrange(port1, port2, real_proto, dir);
|
||||
gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
|
||||
return b;
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_GATEWAY:
|
||||
#ifndef INET6
|
||||
@@ -6457,16 +6438,12 @@ gen_ncode(s, v, q)
|
||||
if (v > 65535)
|
||||
bpf_error("illegal port number %u > 65535", v);
|
||||
|
||||
#ifndef INET6
|
||||
return gen_port((int)v, proto, dir);
|
||||
#else
|
||||
{
|
||||
struct block *b;
|
||||
b = gen_port((int)v, proto, dir);
|
||||
gen_or(gen_port6((int)v, proto, dir), b);
|
||||
return b;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_PORTRANGE:
|
||||
if (proto == Q_UDP)
|
||||
@@ -6483,16 +6460,12 @@ gen_ncode(s, v, q)
|
||||
if (v > 65535)
|
||||
bpf_error("illegal port number %u > 65535", v);
|
||||
|
||||
#ifndef INET6
|
||||
return gen_portrange((int)v, (int)v, proto, dir);
|
||||
#else
|
||||
{
|
||||
struct block *b;
|
||||
b = gen_portrange((int)v, (int)v, proto, dir);
|
||||
gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
|
||||
return b;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
case Q_GATEWAY:
|
||||
bpf_error("'gateway' requires a name");
|
||||
@@ -6782,9 +6755,7 @@ gen_load(proto, inst, size)
|
||||
case Q_LAT:
|
||||
case Q_MOPRC:
|
||||
case Q_MOPDL:
|
||||
#ifdef INET6
|
||||
case Q_IPV6:
|
||||
#endif
|
||||
/*
|
||||
* The offset is relative to the beginning of
|
||||
* the network-layer header.
|
||||
@@ -6893,16 +6864,12 @@ gen_load(proto, inst, size)
|
||||
gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
|
||||
if (inst->b)
|
||||
gen_and(inst->b, b);
|
||||
#ifdef INET6
|
||||
gen_and(gen_proto_abbrev(Q_IP), b);
|
||||
#endif
|
||||
inst->b = b;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case Q_ICMPV6:
|
||||
bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
|
||||
/*NOTREACHED*/
|
||||
#endif
|
||||
}
|
||||
inst->regno = regno;
|
||||
s = new_stmt(BPF_ST);
|
||||
@@ -7454,13 +7421,11 @@ gen_multicast(proto)
|
||||
gen_and(b0, b1);
|
||||
return b1;
|
||||
|
||||
#ifdef INET6
|
||||
case Q_IPV6:
|
||||
b0 = gen_linktype(ETHERTYPE_IPV6);
|
||||
b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
|
||||
gen_and(b0, b1);
|
||||
return b1;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
|
||||
/* NOTREACHED */
|
||||
@@ -7468,9 +7433,13 @@ gen_multicast(proto)
|
||||
}
|
||||
|
||||
/*
|
||||
* generate command for inbound/outbound. It's here so we can
|
||||
* make it link-type specific. 'dir' = 0 implies "inbound",
|
||||
* = 1 implies "outbound".
|
||||
* Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
|
||||
* Outbound traffic is sent by this machine, while inbound traffic is
|
||||
* sent by a remote machine (and may include packets destined for a
|
||||
* unicast or multicast link-layer address we are not subscribing to).
|
||||
* These are the same definitions implemented by pcap_setdirection().
|
||||
* Capturing only unicast traffic destined for this host is probably
|
||||
* better accomplished using a higher-layer filter.
|
||||
*/
|
||||
struct block *
|
||||
gen_inbound(dir)
|
||||
@@ -7500,23 +7469,11 @@ gen_inbound(dir)
|
||||
break;
|
||||
|
||||
case DLT_LINUX_SLL:
|
||||
if (dir) {
|
||||
/*
|
||||
* Match packets sent by this machine.
|
||||
*/
|
||||
b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
|
||||
} else {
|
||||
/*
|
||||
* Match packets sent to this machine.
|
||||
* (No broadcast or multicast packets, or
|
||||
* packets sent to some other machine and
|
||||
* received promiscuously.)
|
||||
*
|
||||
* XXX - packets sent to other machines probably
|
||||
* shouldn't be matched, but what about broadcast
|
||||
* or multicast packets we received?
|
||||
*/
|
||||
b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
|
||||
/* match outgoing packets */
|
||||
b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
|
||||
if (!dir) {
|
||||
/* to filter on inbound traffic, invert the match */
|
||||
gen_not(b0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -7572,10 +7529,38 @@ gen_inbound(dir)
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* If we have packet meta-data indicating a direction,
|
||||
* check it, otherwise give up as this link-layer type
|
||||
* has nothing in the packet data.
|
||||
*/
|
||||
#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
|
||||
/*
|
||||
* This is Linux with PF_PACKET support.
|
||||
* If this is a *live* capture, we can look at
|
||||
* special meta-data in the filter expression;
|
||||
* if it's a savefile, we can't.
|
||||
*/
|
||||
if (bpf_pcap->rfile != NULL) {
|
||||
/* We have a FILE *, so this is a savefile */
|
||||
bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
|
||||
linktype);
|
||||
b0 = NULL;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* match outgoing packets */
|
||||
b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
|
||||
PACKET_OUTGOING);
|
||||
if (!dir) {
|
||||
/* to filter on inbound traffic, invert the match */
|
||||
gen_not(b0);
|
||||
}
|
||||
#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
|
||||
bpf_error("inbound/outbound not supported on linktype %d",
|
||||
linktype);
|
||||
b0 = NULL;
|
||||
/* NOTREACHED */
|
||||
#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
|
||||
}
|
||||
return (b0);
|
||||
}
|
||||
@@ -8035,9 +8020,10 @@ gen_pppoed()
|
||||
}
|
||||
|
||||
struct block *
|
||||
gen_pppoes()
|
||||
gen_pppoes(sess_num)
|
||||
int sess_num;
|
||||
{
|
||||
struct block *b0;
|
||||
struct block *b0, *b1;
|
||||
|
||||
/*
|
||||
* Test against the PPPoE session link-layer type.
|
||||
@@ -8077,6 +8063,14 @@ gen_pppoes()
|
||||
orig_nl = off_nl;
|
||||
is_pppoes = 1;
|
||||
|
||||
/* If a specific session is requested, check PPPoE session id */
|
||||
if (sess_num >= 0) {
|
||||
b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W,
|
||||
(bpf_int32)sess_num, 0x0000ffff);
|
||||
gen_and(b0, b1);
|
||||
b0 = b1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "network-layer" protocol is PPPoE, which has a 6-byte
|
||||
* PPPoE header, followed by a PPP packet.
|
||||
@@ -8266,6 +8260,7 @@ gen_atmtype_abbrev(type)
|
||||
* FISU, length is null
|
||||
* LSSU, length is 1 or 2
|
||||
* MSU, length is 3 or more
|
||||
* For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
|
||||
*/
|
||||
struct block *
|
||||
gen_mtp2type_abbrev(type)
|
||||
@@ -8302,6 +8297,33 @@ gen_mtp2type_abbrev(type)
|
||||
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
|
||||
break;
|
||||
|
||||
case MH_FISU:
|
||||
if ( (linktype != DLT_MTP2) &&
|
||||
(linktype != DLT_ERF) &&
|
||||
(linktype != DLT_MTP2_WITH_PHDR) )
|
||||
bpf_error("'hfisu' supported only on MTP2_HSL");
|
||||
/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
|
||||
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
|
||||
break;
|
||||
|
||||
case MH_LSSU:
|
||||
if ( (linktype != DLT_MTP2) &&
|
||||
(linktype != DLT_ERF) &&
|
||||
(linktype != DLT_MTP2_WITH_PHDR) )
|
||||
bpf_error("'hlssu' supported only on MTP2_HSL");
|
||||
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
|
||||
b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
|
||||
gen_and(b1, b0);
|
||||
break;
|
||||
|
||||
case MH_MSU:
|
||||
if ( (linktype != DLT_MTP2) &&
|
||||
(linktype != DLT_ERF) &&
|
||||
(linktype != DLT_MTP2_WITH_PHDR) )
|
||||
bpf_error("'hmsu' supported only on MTP2_HSL");
|
||||
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -8317,9 +8339,17 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
|
||||
{
|
||||
struct block *b0;
|
||||
bpf_u_int32 val1 , val2 , val3;
|
||||
u_int newoff_sio=off_sio;
|
||||
u_int newoff_opc=off_opc;
|
||||
u_int newoff_dpc=off_dpc;
|
||||
u_int newoff_sls=off_sls;
|
||||
|
||||
switch (mtp3field) {
|
||||
|
||||
case MH_SIO:
|
||||
newoff_sio += 3; /* offset for MTP2_HSL */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case M_SIO:
|
||||
if (off_sio == (u_int)-1)
|
||||
bpf_error("'sio' supported only on SS7");
|
||||
@@ -8327,10 +8357,12 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
|
||||
if(jvalue > 255)
|
||||
bpf_error("sio value %u too big; max value = 255",
|
||||
jvalue);
|
||||
b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
|
||||
b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
|
||||
(u_int)jtype, reverse, (u_int)jvalue);
|
||||
break;
|
||||
|
||||
case MH_OPC:
|
||||
newoff_opc+=3;
|
||||
case M_OPC:
|
||||
if (off_opc == (u_int)-1)
|
||||
bpf_error("'opc' supported only on SS7");
|
||||
@@ -8347,10 +8379,14 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
|
||||
val3 = jvalue & 0x00000003;
|
||||
val3 = val3 <<22;
|
||||
jvalue = val1 + val2 + val3;
|
||||
b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
|
||||
b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
|
||||
(u_int)jtype, reverse, (u_int)jvalue);
|
||||
break;
|
||||
|
||||
case MH_DPC:
|
||||
newoff_dpc += 3;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case M_DPC:
|
||||
if (off_dpc == (u_int)-1)
|
||||
bpf_error("'dpc' supported only on SS7");
|
||||
@@ -8365,10 +8401,12 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
|
||||
val2 = jvalue & 0x00003f00;
|
||||
val2 = val2 << 8;
|
||||
jvalue = val1 + val2;
|
||||
b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
|
||||
b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
|
||||
(u_int)jtype, reverse, (u_int)jvalue);
|
||||
break;
|
||||
|
||||
case MH_SLS:
|
||||
newoff_sls+=3;
|
||||
case M_SLS:
|
||||
if (off_sls == (u_int)-1)
|
||||
bpf_error("'sls' supported only on SS7");
|
||||
@@ -8379,7 +8417,7 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
|
||||
/* the following instruction is made to convert jvalue
|
||||
* to the forme used to write sls in an ss7 message*/
|
||||
jvalue = jvalue << 4;
|
||||
b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0,
|
||||
b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
|
||||
(u_int)jtype,reverse, (u_int)jvalue);
|
||||
break;
|
||||
|
||||
|
||||
@@ -186,12 +186,23 @@
|
||||
#define M_LSSU 23 /* LSSU */
|
||||
#define M_MSU 24 /* MSU */
|
||||
|
||||
/* MTP2 HSL types */
|
||||
#define MH_FISU 25 /* FISU for HSL */
|
||||
#define MH_LSSU 26 /* LSSU */
|
||||
#define MH_MSU 27 /* MSU */
|
||||
|
||||
/* MTP3 field types */
|
||||
#define M_SIO 1
|
||||
#define M_OPC 2
|
||||
#define M_DPC 3
|
||||
#define M_SLS 4
|
||||
|
||||
/* MTP3 field types in case of MTP2 HSL */
|
||||
#define MH_SIO 5
|
||||
#define MH_OPC 6
|
||||
#define MH_DPC 7
|
||||
#define MH_SLS 8
|
||||
|
||||
|
||||
struct slist;
|
||||
|
||||
@@ -240,8 +251,8 @@ struct block {
|
||||
struct slist *stmts; /* side effect stmts */
|
||||
struct stmt s; /* branch stmt */
|
||||
int mark;
|
||||
int longjt; /* jt branch requires long jump */
|
||||
int longjf; /* jf branch requires long jump */
|
||||
u_int longjt; /* jt branch requires long jump */
|
||||
u_int longjf; /* jf branch requires long jump */
|
||||
int level;
|
||||
int offset;
|
||||
int sense;
|
||||
@@ -303,7 +314,7 @@ struct block *gen_vlan(int);
|
||||
struct block *gen_mpls(int);
|
||||
|
||||
struct block *gen_pppoed(void);
|
||||
struct block *gen_pppoes(void);
|
||||
struct block *gen_pppoes(int);
|
||||
|
||||
struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse);
|
||||
struct block *gen_atmtype_abbrev(int type);
|
||||
@@ -325,12 +336,16 @@ struct block *gen_p80211_fcdir(int);
|
||||
|
||||
void bpf_optimize(struct block **);
|
||||
void bpf_error(const char *, ...)
|
||||
__attribute__((noreturn, format (printf, 1, 2)));
|
||||
__attribute__((noreturn))
|
||||
#ifdef __ATTRIBUTE___FORMAT_OK
|
||||
__attribute__((format (printf, 1, 2)))
|
||||
#endif /* __ATTRIBUTE___FORMAT_OK */
|
||||
;
|
||||
|
||||
void finish_parse(struct block *);
|
||||
char *sdup(const char *);
|
||||
|
||||
struct bpf_insn *icode_to_fcode(struct block *, int *);
|
||||
struct bpf_insn *icode_to_fcode(struct block *, u_int *);
|
||||
int pcap_parse(void);
|
||||
void lex_init(const char *);
|
||||
void lex_cleanup(void);
|
||||
|
||||
3157
libpcap/grammar.c
3157
libpcap/grammar.c
File diff suppressed because it is too large
Load Diff
@@ -167,7 +167,7 @@ yyerror(const char *msg)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#ifndef YYBISON
|
||||
#ifdef NEED_YYPARSE_WRAPPER
|
||||
int yyparse(void);
|
||||
|
||||
int
|
||||
@@ -294,8 +294,9 @@ pfaction_to_num(const char *action)
|
||||
%token OAM OAMF4 CONNECTMSG METACONNECT
|
||||
%token VPI VCI
|
||||
%token RADIO
|
||||
%token FISU LSSU MSU
|
||||
%token SIO OPC DPC SLS
|
||||
%token FISU LSSU MSU HFISU HLSSU HMSU
|
||||
%token SIO OPC DPC SLS HSIO HOPC HDPC HSLS
|
||||
|
||||
|
||||
%type <s> ID
|
||||
%type <e> EID
|
||||
@@ -506,7 +507,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
|
||||
| MPLS pnum { $$ = gen_mpls($2); }
|
||||
| MPLS { $$ = gen_mpls(-1); }
|
||||
| PPPOED { $$ = gen_pppoed(); }
|
||||
| PPPOES { $$ = gen_pppoes(); }
|
||||
| PPPOES pnum { $$ = gen_pppoes($2); }
|
||||
| PPPOES { $$ = gen_pppoes(-1); }
|
||||
| pfvar { $$ = $1; }
|
||||
| pqual p80211 { $$ = $2; }
|
||||
;
|
||||
@@ -670,12 +672,19 @@ atmlistvalue: atmfieldvalue
|
||||
mtp2type: FISU { $$ = M_FISU; }
|
||||
| LSSU { $$ = M_LSSU; }
|
||||
| MSU { $$ = M_MSU; }
|
||||
| HFISU { $$ = MH_FISU; }
|
||||
| HLSSU { $$ = MH_LSSU; }
|
||||
| HMSU { $$ = MH_MSU; }
|
||||
;
|
||||
/* MTP3 field types quantifier */
|
||||
mtp3field: SIO { $$.mtp3fieldtype = M_SIO; }
|
||||
| OPC { $$.mtp3fieldtype = M_OPC; }
|
||||
| DPC { $$.mtp3fieldtype = M_DPC; }
|
||||
| SLS { $$.mtp3fieldtype = M_SLS; }
|
||||
| HSIO { $$.mtp3fieldtype = MH_SIO; }
|
||||
| HOPC { $$.mtp3fieldtype = MH_OPC; }
|
||||
| HDPC { $$.mtp3fieldtype = MH_DPC; }
|
||||
| HSLS { $$.mtp3fieldtype = MH_SLS; }
|
||||
;
|
||||
mtp3value: mtp3fieldvalue
|
||||
| relop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
|
||||
@@ -687,7 +696,11 @@ mtp3fieldvalue: NUM {
|
||||
if ($$.mtp3fieldtype == M_SIO ||
|
||||
$$.mtp3fieldtype == M_OPC ||
|
||||
$$.mtp3fieldtype == M_DPC ||
|
||||
$$.mtp3fieldtype == M_SLS )
|
||||
$$.mtp3fieldtype == M_SLS ||
|
||||
$$.mtp3fieldtype == MH_SIO ||
|
||||
$$.mtp3fieldtype == MH_OPC ||
|
||||
$$.mtp3fieldtype == MH_DPC ||
|
||||
$$.mtp3fieldtype == MH_SLS)
|
||||
$$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -18,6 +18,7 @@ export PATH
|
||||
|
||||
MAKE=Makefile # default makefile name is "Makefile"
|
||||
CC=cc # default C compiler is "cc"
|
||||
DEPENDENCY_CFLAG=-M # default dependency-generation flag is -M
|
||||
|
||||
while :
|
||||
do case "$1" in
|
||||
@@ -31,6 +32,11 @@ while :
|
||||
MAKE=$2
|
||||
shift; shift ;;
|
||||
|
||||
# -m allows you to specify the dependency-generation flag
|
||||
-m)
|
||||
DEPENDENCY_CFLAG=$2
|
||||
shift; shift ;;
|
||||
|
||||
# the -p flag produces "program: program.c" style dependencies
|
||||
# so .o's don't get produced
|
||||
-p)
|
||||
@@ -42,7 +48,7 @@ while :
|
||||
done
|
||||
|
||||
if [ $# = 0 ] ; then
|
||||
echo 'usage: mkdep [-p] [-c cc] [-f makefile] [flags] file ...'
|
||||
echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [flags] file ...'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -74,7 +80,7 @@ _EOF_
|
||||
# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
|
||||
|
||||
# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
|
||||
$CC -M $* |
|
||||
$CC $DEPENDENCY_CFLAG $* |
|
||||
sed "
|
||||
s; \./; ;g
|
||||
$SED" |
|
||||
|
||||
@@ -247,6 +247,7 @@ pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
|
||||
free(cpy);
|
||||
return 0;
|
||||
}
|
||||
free(cpy);
|
||||
|
||||
if (*proto != save_proto)
|
||||
*proto = PROTO_UNDEF;
|
||||
@@ -414,6 +415,8 @@ pcap_ether_aton(const char *s)
|
||||
register u_int d;
|
||||
|
||||
e = ep = (u_char *)malloc(6);
|
||||
if (e == NULL)
|
||||
return (NULL);
|
||||
|
||||
while (*s) {
|
||||
if (*s == ':' || *s == '.' || *s == '-')
|
||||
|
||||
@@ -112,51 +112,9 @@ static int cur_mark;
|
||||
static void opt_init(struct block *);
|
||||
static void opt_cleanup(void);
|
||||
|
||||
static void make_marks(struct block *);
|
||||
static void mark_code(struct block *);
|
||||
|
||||
static void intern_blocks(struct block *);
|
||||
|
||||
static int eq_slist(struct slist *, struct slist *);
|
||||
|
||||
static void find_levels_r(struct block *);
|
||||
|
||||
static void find_levels(struct block *);
|
||||
static void find_dom(struct block *);
|
||||
static void propedom(struct edge *);
|
||||
static void find_edom(struct block *);
|
||||
static void find_closure(struct block *);
|
||||
static int atomuse(struct stmt *);
|
||||
static int atomdef(struct stmt *);
|
||||
static void compute_local_ud(struct block *);
|
||||
static void find_ud(struct block *);
|
||||
static void init_val(void);
|
||||
static int F(int, int, int);
|
||||
static inline void vstore(struct stmt *, int *, int, int);
|
||||
static void opt_blk(struct block *, int);
|
||||
static int use_conflict(struct block *, struct block *);
|
||||
static void opt_j(struct edge *);
|
||||
static void or_pullup(struct block *);
|
||||
static void and_pullup(struct block *);
|
||||
static void opt_blks(struct block *, int);
|
||||
static inline void link_inedge(struct edge *, struct block *);
|
||||
static void find_inedges(struct block *);
|
||||
static void opt_root(struct block **);
|
||||
static void opt_loop(struct block *, int);
|
||||
static void fold_op(struct stmt *, int, int);
|
||||
static inline struct slist *this_op(struct slist *);
|
||||
static void opt_not(struct block *);
|
||||
static void opt_peep(struct block *);
|
||||
static void opt_stmt(struct stmt *, int[], int);
|
||||
static void deadstmt(struct stmt *, struct stmt *[]);
|
||||
static void opt_deadstores(struct block *);
|
||||
static struct block *fold_edge(struct block *, struct edge *);
|
||||
static inline int eq_blk(struct block *, struct block *);
|
||||
static int slength(struct slist *);
|
||||
static int count_blocks(struct block *);
|
||||
static void number_blks_r(struct block *);
|
||||
static int count_stmts(struct block *);
|
||||
static int convert_code_r(struct block *);
|
||||
#ifdef BDEBUG
|
||||
static void opt_dump(struct block *);
|
||||
#endif
|
||||
@@ -232,8 +190,7 @@ static uset all_edge_sets;
|
||||
#endif
|
||||
|
||||
static void
|
||||
find_levels_r(b)
|
||||
struct block *b;
|
||||
find_levels_r(struct block *b)
|
||||
{
|
||||
int level;
|
||||
|
||||
@@ -261,8 +218,7 @@ find_levels_r(b)
|
||||
* with the 'link' field of the struct block.
|
||||
*/
|
||||
static void
|
||||
find_levels(root)
|
||||
struct block *root;
|
||||
find_levels(struct block *root)
|
||||
{
|
||||
memset((char *)levels, 0, n_blocks * sizeof(*levels));
|
||||
unMarkAll();
|
||||
@@ -274,8 +230,7 @@ find_levels(root)
|
||||
* Assumes graph has been leveled.
|
||||
*/
|
||||
static void
|
||||
find_dom(root)
|
||||
struct block *root;
|
||||
find_dom(struct block *root)
|
||||
{
|
||||
int i;
|
||||
struct block *b;
|
||||
@@ -305,8 +260,7 @@ find_dom(root)
|
||||
}
|
||||
|
||||
static void
|
||||
propedom(ep)
|
||||
struct edge *ep;
|
||||
propedom(struct edge *ep)
|
||||
{
|
||||
SET_INSERT(ep->edom, ep->id);
|
||||
if (ep->succ) {
|
||||
@@ -320,8 +274,7 @@ propedom(ep)
|
||||
* Assumes graph has been leveled and predecessors established.
|
||||
*/
|
||||
static void
|
||||
find_edom(root)
|
||||
struct block *root;
|
||||
find_edom(struct block *root)
|
||||
{
|
||||
int i;
|
||||
uset x;
|
||||
@@ -350,8 +303,7 @@ find_edom(root)
|
||||
* Assumes graph has been leveled.
|
||||
*/
|
||||
static void
|
||||
find_closure(root)
|
||||
struct block *root;
|
||||
find_closure(struct block *root)
|
||||
{
|
||||
int i;
|
||||
struct block *b;
|
||||
@@ -381,8 +333,7 @@ find_closure(root)
|
||||
* The implementation should probably change to an array access.
|
||||
*/
|
||||
static int
|
||||
atomuse(s)
|
||||
struct stmt *s;
|
||||
atomuse(struct stmt *s)
|
||||
{
|
||||
register int c = s->code;
|
||||
|
||||
@@ -427,8 +378,7 @@ atomuse(s)
|
||||
* The implementation should probably change to an array access.
|
||||
*/
|
||||
static int
|
||||
atomdef(s)
|
||||
struct stmt *s;
|
||||
atomdef(struct stmt *s)
|
||||
{
|
||||
if (s->code == NOP)
|
||||
return -1;
|
||||
@@ -464,8 +414,7 @@ atomdef(s)
|
||||
* register by a predecessor block of this block.
|
||||
*/
|
||||
static void
|
||||
compute_local_ud(b)
|
||||
struct block *b;
|
||||
compute_local_ud(struct block *b)
|
||||
{
|
||||
struct slist *s;
|
||||
atomset def = 0, use = 0, kill = 0;
|
||||
@@ -526,8 +475,7 @@ compute_local_ud(b)
|
||||
* Assume graph is already leveled.
|
||||
*/
|
||||
static void
|
||||
find_ud(root)
|
||||
struct block *root;
|
||||
find_ud(struct block *root)
|
||||
{
|
||||
int i, maxlevel;
|
||||
struct block *p;
|
||||
@@ -582,7 +530,7 @@ struct valnode *vnode_base;
|
||||
struct valnode *next_vnode;
|
||||
|
||||
static void
|
||||
init_val()
|
||||
init_val(void)
|
||||
{
|
||||
curval = 0;
|
||||
next_vnode = vnode_base;
|
||||
@@ -592,9 +540,7 @@ init_val()
|
||||
|
||||
/* Because we really don't have an IR, this stuff is a little messy. */
|
||||
static int
|
||||
F(code, v0, v1)
|
||||
int code;
|
||||
int v0, v1;
|
||||
F(int code, int v0, int v1)
|
||||
{
|
||||
u_int hash;
|
||||
int val;
|
||||
@@ -625,11 +571,7 @@ F(code, v0, v1)
|
||||
}
|
||||
|
||||
static inline void
|
||||
vstore(s, valp, newval, alter)
|
||||
struct stmt *s;
|
||||
int *valp;
|
||||
int newval;
|
||||
int alter;
|
||||
vstore(struct stmt *s, int *valp, int newval, int alter)
|
||||
{
|
||||
if (alter && *valp == newval)
|
||||
s->code = NOP;
|
||||
@@ -637,10 +579,12 @@ vstore(s, valp, newval, alter)
|
||||
*valp = newval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do constant-folding on binary operators.
|
||||
* (Unary operators are handled elsewhere.)
|
||||
*/
|
||||
static void
|
||||
fold_op(s, v0, v1)
|
||||
struct stmt *s;
|
||||
int v0, v1;
|
||||
fold_op(struct stmt *s, int v0, int v1)
|
||||
{
|
||||
bpf_u_int32 a, b;
|
||||
|
||||
@@ -682,10 +626,6 @@ fold_op(s, v0, v1)
|
||||
a >>= b;
|
||||
break;
|
||||
|
||||
case BPF_NEG:
|
||||
a = -a;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -695,8 +635,7 @@ fold_op(s, v0, v1)
|
||||
}
|
||||
|
||||
static inline struct slist *
|
||||
this_op(s)
|
||||
struct slist *s;
|
||||
this_op(struct slist *s)
|
||||
{
|
||||
while (s != 0 && s->s.code == NOP)
|
||||
s = s->next;
|
||||
@@ -704,8 +643,7 @@ this_op(s)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_not(b)
|
||||
struct block *b;
|
||||
opt_not(struct block *b)
|
||||
{
|
||||
struct block *tmp = JT(b);
|
||||
|
||||
@@ -714,8 +652,7 @@ opt_not(b)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_peep(b)
|
||||
struct block *b;
|
||||
opt_peep(struct block *b)
|
||||
{
|
||||
struct slist *s;
|
||||
struct slist *next, *last;
|
||||
@@ -978,10 +915,7 @@ opt_peep(b)
|
||||
* evaluation and code transformations weren't folded together.
|
||||
*/
|
||||
static void
|
||||
opt_stmt(s, val, alter)
|
||||
struct stmt *s;
|
||||
int val[];
|
||||
int alter;
|
||||
opt_stmt(struct stmt *s, int val[], int alter)
|
||||
{
|
||||
int op;
|
||||
int v;
|
||||
@@ -1166,9 +1100,7 @@ opt_stmt(s, val, alter)
|
||||
}
|
||||
|
||||
static void
|
||||
deadstmt(s, last)
|
||||
register struct stmt *s;
|
||||
register struct stmt *last[];
|
||||
deadstmt(register struct stmt *s, register struct stmt *last[])
|
||||
{
|
||||
register int atom;
|
||||
|
||||
@@ -1192,8 +1124,7 @@ deadstmt(s, last)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_deadstores(b)
|
||||
register struct block *b;
|
||||
opt_deadstores(register struct block *b)
|
||||
{
|
||||
register struct slist *s;
|
||||
register int atom;
|
||||
@@ -1213,9 +1144,7 @@ opt_deadstores(b)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_blk(b, do_stmts)
|
||||
struct block *b;
|
||||
int do_stmts;
|
||||
opt_blk(struct block *b, int do_stmts)
|
||||
{
|
||||
struct slist *s;
|
||||
struct edge *p;
|
||||
@@ -1319,8 +1248,7 @@ opt_blk(b, do_stmts)
|
||||
* from 'b'.
|
||||
*/
|
||||
static int
|
||||
use_conflict(b, succ)
|
||||
struct block *b, *succ;
|
||||
use_conflict(struct block *b, struct block *succ)
|
||||
{
|
||||
int atom;
|
||||
atomset use = succ->out_use;
|
||||
@@ -1336,9 +1264,7 @@ use_conflict(b, succ)
|
||||
}
|
||||
|
||||
static struct block *
|
||||
fold_edge(child, ep)
|
||||
struct block *child;
|
||||
struct edge *ep;
|
||||
fold_edge(struct block *child, struct edge *ep)
|
||||
{
|
||||
int sense;
|
||||
int aval0, aval1, oval0, oval1;
|
||||
@@ -1390,8 +1316,7 @@ fold_edge(child, ep)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_j(ep)
|
||||
struct edge *ep;
|
||||
opt_j(struct edge *ep)
|
||||
{
|
||||
register int i, k;
|
||||
register struct block *target;
|
||||
@@ -1446,8 +1371,7 @@ opt_j(ep)
|
||||
|
||||
|
||||
static void
|
||||
or_pullup(b)
|
||||
struct block *b;
|
||||
or_pullup(struct block *b)
|
||||
{
|
||||
int val, at_top;
|
||||
struct block *pull;
|
||||
@@ -1539,8 +1463,7 @@ or_pullup(b)
|
||||
}
|
||||
|
||||
static void
|
||||
and_pullup(b)
|
||||
struct block *b;
|
||||
and_pullup(struct block *b)
|
||||
{
|
||||
int val, at_top;
|
||||
struct block *pull;
|
||||
@@ -1631,9 +1554,7 @@ and_pullup(b)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_blks(root, do_stmts)
|
||||
struct block *root;
|
||||
int do_stmts;
|
||||
opt_blks(struct block *root, int do_stmts)
|
||||
{
|
||||
int i, maxlevel;
|
||||
struct block *p;
|
||||
@@ -1670,17 +1591,14 @@ opt_blks(root, do_stmts)
|
||||
}
|
||||
|
||||
static inline void
|
||||
link_inedge(parent, child)
|
||||
struct edge *parent;
|
||||
struct block *child;
|
||||
link_inedge(struct edge *parent, struct block *child)
|
||||
{
|
||||
parent->next = child->in_edges;
|
||||
child->in_edges = parent;
|
||||
}
|
||||
|
||||
static void
|
||||
find_inedges(root)
|
||||
struct block *root;
|
||||
find_inedges(struct block *root)
|
||||
{
|
||||
int i;
|
||||
struct block *b;
|
||||
@@ -1701,8 +1619,7 @@ find_inedges(root)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_root(b)
|
||||
struct block **b;
|
||||
opt_root(struct block **b)
|
||||
{
|
||||
struct slist *tmp, *s;
|
||||
|
||||
@@ -1726,9 +1643,7 @@ opt_root(b)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_loop(root, do_stmts)
|
||||
struct block *root;
|
||||
int do_stmts;
|
||||
opt_loop(struct block *root, int do_stmts)
|
||||
{
|
||||
|
||||
#ifdef BDEBUG
|
||||
@@ -1758,8 +1673,7 @@ opt_loop(root, do_stmts)
|
||||
* Optimize the filter code in its dag representation.
|
||||
*/
|
||||
void
|
||||
bpf_optimize(rootp)
|
||||
struct block **rootp;
|
||||
bpf_optimize(struct block **rootp)
|
||||
{
|
||||
struct block *root;
|
||||
|
||||
@@ -1786,8 +1700,7 @@ bpf_optimize(rootp)
|
||||
}
|
||||
|
||||
static void
|
||||
make_marks(p)
|
||||
struct block *p;
|
||||
make_marks(struct block *p)
|
||||
{
|
||||
if (!isMarked(p)) {
|
||||
Mark(p);
|
||||
@@ -1803,8 +1716,7 @@ make_marks(p)
|
||||
* only for nodes that are alive.
|
||||
*/
|
||||
static void
|
||||
mark_code(p)
|
||||
struct block *p;
|
||||
mark_code(struct block *p)
|
||||
{
|
||||
cur_mark += 1;
|
||||
make_marks(p);
|
||||
@@ -1815,8 +1727,7 @@ mark_code(p)
|
||||
* the accumulator.
|
||||
*/
|
||||
static int
|
||||
eq_slist(x, y)
|
||||
struct slist *x, *y;
|
||||
eq_slist(struct slist *x, struct slist *y)
|
||||
{
|
||||
while (1) {
|
||||
while (x && x->s.code == NOP)
|
||||
@@ -1835,8 +1746,7 @@ eq_slist(x, y)
|
||||
}
|
||||
|
||||
static inline int
|
||||
eq_blk(b0, b1)
|
||||
struct block *b0, *b1;
|
||||
eq_blk(struct block *b0, struct block *b1)
|
||||
{
|
||||
if (b0->s.code == b1->s.code &&
|
||||
b0->s.k == b1->s.k &&
|
||||
@@ -1847,8 +1757,7 @@ eq_blk(b0, b1)
|
||||
}
|
||||
|
||||
static void
|
||||
intern_blocks(root)
|
||||
struct block *root;
|
||||
intern_blocks(struct block *root)
|
||||
{
|
||||
struct block *p;
|
||||
int i, j;
|
||||
@@ -1891,7 +1800,7 @@ intern_blocks(root)
|
||||
}
|
||||
|
||||
static void
|
||||
opt_cleanup()
|
||||
opt_cleanup(void)
|
||||
{
|
||||
free((void *)vnode_base);
|
||||
free((void *)vmap);
|
||||
@@ -1904,11 +1813,10 @@ opt_cleanup()
|
||||
/*
|
||||
* Return the number of stmts in 's'.
|
||||
*/
|
||||
static int
|
||||
slength(s)
|
||||
struct slist *s;
|
||||
static u_int
|
||||
slength(struct slist *s)
|
||||
{
|
||||
int n = 0;
|
||||
u_int n = 0;
|
||||
|
||||
for (; s; s = s->next)
|
||||
if (s->s.code != NOP)
|
||||
@@ -1921,8 +1829,7 @@ slength(s)
|
||||
* All nodes should be initially unmarked.
|
||||
*/
|
||||
static int
|
||||
count_blocks(p)
|
||||
struct block *p;
|
||||
count_blocks(struct block *p)
|
||||
{
|
||||
if (p == 0 || isMarked(p))
|
||||
return 0;
|
||||
@@ -1935,8 +1842,7 @@ count_blocks(p)
|
||||
* the basic blocks, and entering them into the 'blocks' array.`
|
||||
*/
|
||||
static void
|
||||
number_blks_r(p)
|
||||
struct block *p;
|
||||
number_blks_r(struct block *p)
|
||||
{
|
||||
int n;
|
||||
|
||||
@@ -1970,11 +1876,10 @@ number_blks_r(p)
|
||||
*
|
||||
* an extra long jump if the false branch requires it (p->longjf).
|
||||
*/
|
||||
static int
|
||||
count_stmts(p)
|
||||
struct block *p;
|
||||
static u_int
|
||||
count_stmts(struct block *p)
|
||||
{
|
||||
int n;
|
||||
u_int n;
|
||||
|
||||
if (p == 0 || isMarked(p))
|
||||
return 0;
|
||||
@@ -1989,8 +1894,7 @@ count_stmts(p)
|
||||
* from the total number of blocks and/or statements.
|
||||
*/
|
||||
static void
|
||||
opt_init(root)
|
||||
struct block *root;
|
||||
opt_init(struct block *root)
|
||||
{
|
||||
bpf_u_int32 *p;
|
||||
int i, n, max_stmts;
|
||||
@@ -2088,8 +1992,7 @@ int bids[1000];
|
||||
* properly.
|
||||
*/
|
||||
static int
|
||||
convert_code_r(p)
|
||||
struct block *p;
|
||||
convert_code_r(struct block *p)
|
||||
{
|
||||
struct bpf_insn *dst;
|
||||
struct slist *src;
|
||||
@@ -2261,11 +2164,9 @@ filled:
|
||||
* done with the filter program. See the pcap man page.
|
||||
*/
|
||||
struct bpf_insn *
|
||||
icode_to_fcode(root, lenp)
|
||||
struct block *root;
|
||||
int *lenp;
|
||||
icode_to_fcode(struct block *root, u_int *lenp)
|
||||
{
|
||||
int n;
|
||||
u_int n;
|
||||
struct bpf_insn *fp;
|
||||
|
||||
/*
|
||||
@@ -2333,8 +2234,7 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
|
||||
|
||||
#ifdef BDEBUG
|
||||
static void
|
||||
opt_dump(root)
|
||||
struct block *root;
|
||||
opt_dump(struct block *root)
|
||||
{
|
||||
struct bpf_program f;
|
||||
|
||||
|
||||
@@ -66,8 +66,10 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
%{_bindir}/pcap-config
|
||||
%{_includedir}/pcap*.h
|
||||
%{_includedir}/pcap/*.h
|
||||
%{_includedir}/pcap.h
|
||||
%{_includedir}/pcap-bpf.h
|
||||
%{_includedir}/pcap-namedb.h
|
||||
%{_libdir}/libpcap.so
|
||||
%{_libdir}/libpcap.a
|
||||
%{_mandir}/man1/pcap-config.1*
|
||||
|
||||
@@ -122,18 +122,60 @@ static int bpf_load(char *errbuf);
|
||||
|
||||
#include "pcap-int.h"
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
#include "pcap-dag.h"
|
||||
#endif /* HAVE_DAG_API */
|
||||
|
||||
#ifdef HAVE_SNF_API
|
||||
#include "pcap-snf.h"
|
||||
#endif /* HAVE_SNF_API */
|
||||
|
||||
#ifdef HAVE_OS_PROTO_H
|
||||
#include "os-proto.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Later versions of NetBSD stick padding in front of FDDI frames
|
||||
* to align the IP header on a 4-byte boundary.
|
||||
*/
|
||||
#if defined(__NetBSD__) && __NetBSD_Version__ > 106000000
|
||||
#define PCAP_FDDIPAD 3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private data for capturing on BPF devices.
|
||||
*/
|
||||
struct pcap_bpf {
|
||||
#ifdef PCAP_FDDIPAD
|
||||
int fddipad;
|
||||
#endif
|
||||
|
||||
#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;
|
||||
int nonblock; /* true if in nonblocking mode */
|
||||
#endif /* HAVE_ZEROCOPY_BPF */
|
||||
|
||||
char *device; /* device name */
|
||||
int filtering_in_kernel; /* using kernel filter */
|
||||
int must_do_on_close; /* stuff we must do when we close */
|
||||
};
|
||||
|
||||
/*
|
||||
* Stuff to do when we close.
|
||||
*/
|
||||
#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
|
||||
|
||||
#ifdef BIOCGDLTLIST
|
||||
# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
|
||||
#define HAVE_BSD_IEEE80211
|
||||
@@ -155,6 +197,10 @@ static void remove_802_11(pcap_t *);
|
||||
|
||||
#endif /* BIOCGDLTLIST */
|
||||
|
||||
#if defined(sun) && defined(LIFNAMSIZ) && defined(lifr_zoneid)
|
||||
#include <zone.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
|
||||
* don't get DLT_DOCSIS defined.
|
||||
@@ -188,22 +234,17 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
|
||||
|
||||
/*
|
||||
* For zerocopy bpf, the setnonblock/getnonblock routines need to modify
|
||||
* p->md.timeout so we don't call select(2) if the pcap handle is in non-
|
||||
* blocking mode. We preserve the timeout supplied by pcap_open functions
|
||||
* to make sure it does not get clobbered if the pcap handle moves between
|
||||
* blocking and non-blocking mode.
|
||||
* pb->nonblock so we don't call select(2) if the pcap handle is in non-
|
||||
* blocking mode.
|
||||
*/
|
||||
static int
|
||||
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
|
||||
{
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (p->md.zerocopy) {
|
||||
/*
|
||||
* Use a negative value for the timeout to represent that the
|
||||
* pcap handle is in non-blocking mode.
|
||||
*/
|
||||
return (p->md.timeout < 0);
|
||||
}
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
|
||||
if (pb->zerocopy)
|
||||
return (pb->nonblock);
|
||||
#endif
|
||||
return (pcap_getnonblock_fd(p, errbuf));
|
||||
}
|
||||
@@ -212,34 +253,10 @@ static int
|
||||
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (p->md.zerocopy) {
|
||||
/*
|
||||
* Map each value to the corresponding 2's complement, to
|
||||
* preserve the timeout value provided with pcap_set_timeout.
|
||||
* (from pcap-linux.c).
|
||||
*/
|
||||
if (nonblock) {
|
||||
if (p->md.timeout >= 0) {
|
||||
/*
|
||||
* Timeout is non-negative, so we're not
|
||||
* currently in non-blocking mode; set it
|
||||
* to the 2's complement, to make it
|
||||
* negative, as an indication that we're
|
||||
* in non-blocking mode.
|
||||
*/
|
||||
p->md.timeout = p->md.timeout * -1 - 1;
|
||||
}
|
||||
} else {
|
||||
if (p->md.timeout < 0) {
|
||||
/*
|
||||
* Timeout is negative, so we're currently
|
||||
* in blocking mode; reverse the previous
|
||||
* operation, to make the timeout non-negative
|
||||
* again.
|
||||
*/
|
||||
p->md.timeout = (p->md.timeout + 1) * -1;
|
||||
}
|
||||
}
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
|
||||
if (pb->zerocopy) {
|
||||
pb->nonblock = nonblock;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
@@ -259,25 +276,26 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
|
||||
static int
|
||||
pcap_next_zbuf_shm(pcap_t *p, int *cc)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
struct bpf_zbuf_header *bzh;
|
||||
|
||||
if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) {
|
||||
bzh = (struct bpf_zbuf_header *)p->md.zbuf1;
|
||||
if (pb->zbuffer == pb->zbuf2 || pb->zbuffer == NULL) {
|
||||
bzh = (struct bpf_zbuf_header *)pb->zbuf1;
|
||||
if (bzh->bzh_user_gen !=
|
||||
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
|
||||
p->md.bzh = bzh;
|
||||
p->md.zbuffer = (u_char *)p->md.zbuf1;
|
||||
p->buffer = p->md.zbuffer + sizeof(*bzh);
|
||||
pb->bzh = bzh;
|
||||
pb->zbuffer = (u_char *)pb->zbuf1;
|
||||
p->buffer = pb->zbuffer + sizeof(*bzh);
|
||||
*cc = bzh->bzh_kernel_len;
|
||||
return (1);
|
||||
}
|
||||
} else if (p->md.zbuffer == p->md.zbuf1) {
|
||||
bzh = (struct bpf_zbuf_header *)p->md.zbuf2;
|
||||
} else if (pb->zbuffer == pb->zbuf1) {
|
||||
bzh = (struct bpf_zbuf_header *)pb->zbuf2;
|
||||
if (bzh->bzh_user_gen !=
|
||||
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
|
||||
p->md.bzh = bzh;
|
||||
p->md.zbuffer = (u_char *)p->md.zbuf2;
|
||||
p->buffer = p->md.zbuffer + sizeof(*bzh);
|
||||
pb->bzh = bzh;
|
||||
pb->zbuffer = (u_char *)pb->zbuf2;
|
||||
p->buffer = pb->zbuffer + sizeof(*bzh);
|
||||
*cc = bzh->bzh_kernel_len;
|
||||
return (1);
|
||||
}
|
||||
@@ -296,6 +314,7 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc)
|
||||
static int
|
||||
pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
struct bpf_zbuf bz;
|
||||
struct timeval tv;
|
||||
struct timespec cur;
|
||||
@@ -319,15 +338,15 @@ pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
* our timeout is less then or equal to zero, handle it like a
|
||||
* regular timeout.
|
||||
*/
|
||||
tmout = p->md.timeout;
|
||||
tmout = p->opt.timeout;
|
||||
if (tmout)
|
||||
(void) clock_gettime(CLOCK_MONOTONIC, &cur);
|
||||
if (p->md.interrupted && p->md.timeout) {
|
||||
expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout;
|
||||
if (pb->interrupted && p->opt.timeout) {
|
||||
expire = TSTOMILLI(&pb->firstsel) + p->opt.timeout;
|
||||
tmout = expire - TSTOMILLI(&cur);
|
||||
#undef TSTOMILLI
|
||||
if (tmout <= 0) {
|
||||
p->md.interrupted = 0;
|
||||
pb->interrupted = 0;
|
||||
data = pcap_next_zbuf_shm(p, cc);
|
||||
if (data)
|
||||
return (data);
|
||||
@@ -344,7 +363,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
* the next timeout. Note that we only call select if the handle
|
||||
* is in blocking mode.
|
||||
*/
|
||||
if (p->md.timeout >= 0) {
|
||||
if (!pb->nonblock) {
|
||||
FD_ZERO(&r_set);
|
||||
FD_SET(p->fd, &r_set);
|
||||
if (tmout != 0) {
|
||||
@@ -352,11 +371,11 @@ pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
tv.tv_usec = (tmout * 1000) % 1000000;
|
||||
}
|
||||
r = select(p->fd + 1, &r_set, NULL, NULL,
|
||||
p->md.timeout != 0 ? &tv : NULL);
|
||||
p->opt.timeout != 0 ? &tv : NULL);
|
||||
if (r < 0 && errno == EINTR) {
|
||||
if (!p->md.interrupted && p->md.timeout) {
|
||||
p->md.interrupted = 1;
|
||||
p->md.firstsel = cur;
|
||||
if (!pb->interrupted && p->opt.timeout) {
|
||||
pb->interrupted = 1;
|
||||
pb->firstsel = cur;
|
||||
}
|
||||
return (0);
|
||||
} else if (r < 0) {
|
||||
@@ -365,7 +384,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
return (PCAP_ERROR);
|
||||
}
|
||||
}
|
||||
p->md.interrupted = 0;
|
||||
pb->interrupted = 0;
|
||||
/*
|
||||
* Check again for data, which may exist now that we've either been
|
||||
* woken up as a result of data or timed out. Try the "there's data"
|
||||
@@ -393,30 +412,22 @@ pcap_next_zbuf(pcap_t *p, int *cc)
|
||||
static int
|
||||
pcap_ack_zbuf(pcap_t *p)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
|
||||
atomic_store_rel_int(&p->md.bzh->bzh_user_gen,
|
||||
p->md.bzh->bzh_kernel_gen);
|
||||
p->md.bzh = NULL;
|
||||
atomic_store_rel_int(&pb->bzh->bzh_user_gen,
|
||||
pb->bzh->bzh_kernel_gen);
|
||||
pb->bzh = NULL;
|
||||
p->buffer = NULL;
|
||||
return (0);
|
||||
}
|
||||
#endif /* HAVE_ZEROCOPY_BPF */
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
if (strstr(device, "dag"))
|
||||
return (dag_create(device, ebuf));
|
||||
#endif /* HAVE_DAG_API */
|
||||
#ifdef HAVE_SNF_API
|
||||
if (strstr(device, "snf"))
|
||||
return (snf_create(device, ebuf));
|
||||
#endif /* HAVE_SNF_API */
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -812,6 +823,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
|
||||
static int
|
||||
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
int cc;
|
||||
int n = 0;
|
||||
register u_char *bp, *ep;
|
||||
@@ -847,7 +859,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
* buffer.
|
||||
*/
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (p->md.zerocopy) {
|
||||
if (pb->zerocopy) {
|
||||
if (p->buffer != NULL)
|
||||
pcap_ack_zbuf(p);
|
||||
i = pcap_next_zbuf(p, &cc);
|
||||
@@ -995,7 +1007,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
* skipping that padding.
|
||||
#endif
|
||||
*/
|
||||
if (p->md.use_bpf ||
|
||||
if (pb->filtering_in_kernel ||
|
||||
bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
|
||||
struct pcap_pkthdr pkthdr;
|
||||
|
||||
@@ -1025,7 +1037,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
#endif
|
||||
(*callback)(user, &pkthdr, datap);
|
||||
bp += BPF_WORDALIGN(caplen + hdrlen);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
p->bp = bp;
|
||||
p->cc = ep - bp;
|
||||
/*
|
||||
@@ -1262,19 +1274,20 @@ bpf_load(char *errbuf)
|
||||
static void
|
||||
pcap_cleanup_bpf(pcap_t *p)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
#ifdef HAVE_BSD_IEEE80211
|
||||
int sock;
|
||||
struct ifmediareq req;
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
if (p->md.must_do_on_close != 0) {
|
||||
if (pb->must_do_on_close != 0) {
|
||||
/*
|
||||
* There's something we have to do when closing this
|
||||
* pcap_t.
|
||||
*/
|
||||
#ifdef HAVE_BSD_IEEE80211
|
||||
if (p->md.must_do_on_close & MUST_CLEAR_RFMON) {
|
||||
if (pb->must_do_on_close & MUST_CLEAR_RFMON) {
|
||||
/*
|
||||
* We put the interface into rfmon mode;
|
||||
* take it out of rfmon mode.
|
||||
@@ -1291,7 +1304,7 @@ pcap_cleanup_bpf(pcap_t *p)
|
||||
strerror(errno));
|
||||
} else {
|
||||
memset(&req, 0, sizeof(req));
|
||||
strncpy(req.ifm_name, p->md.device,
|
||||
strncpy(req.ifm_name, pb->device,
|
||||
sizeof(req.ifm_name));
|
||||
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
|
||||
fprintf(stderr,
|
||||
@@ -1306,7 +1319,7 @@ pcap_cleanup_bpf(pcap_t *p)
|
||||
*/
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
(void)strncpy(ifr.ifr_name,
|
||||
p->md.device,
|
||||
pb->device,
|
||||
sizeof(ifr.ifr_name));
|
||||
ifr.ifr_media =
|
||||
req.ifm_current & ~IFM_IEEE80211_MONITOR;
|
||||
@@ -1329,11 +1342,11 @@ pcap_cleanup_bpf(pcap_t *p)
|
||||
* have to take the interface out of some mode.
|
||||
*/
|
||||
pcap_remove_from_pcaps_to_close(p);
|
||||
p->md.must_do_on_close = 0;
|
||||
pb->must_do_on_close = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (p->md.zerocopy) {
|
||||
if (pb->zerocopy) {
|
||||
/*
|
||||
* Delete the mappings. Note that p->buffer gets
|
||||
* initialized to one of the mmapped regions in
|
||||
@@ -1341,16 +1354,16 @@ pcap_cleanup_bpf(pcap_t *p)
|
||||
* null it out so that pcap_cleanup_live_common()
|
||||
* doesn't try to free it.
|
||||
*/
|
||||
if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
|
||||
(void) munmap(p->md.zbuf1, p->md.zbufsize);
|
||||
if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
|
||||
(void) munmap(p->md.zbuf2, p->md.zbufsize);
|
||||
if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL)
|
||||
(void) munmap(pb->zbuf1, pb->zbufsize);
|
||||
if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL)
|
||||
(void) munmap(pb->zbuf2, pb->zbufsize);
|
||||
p->buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
if (p->md.device != NULL) {
|
||||
free(p->md.device);
|
||||
p->md.device = NULL;
|
||||
if (pb->device != NULL) {
|
||||
free(pb->device);
|
||||
pb->device = NULL;
|
||||
}
|
||||
pcap_cleanup_live_common(p);
|
||||
}
|
||||
@@ -1451,15 +1464,25 @@ check_setif_failure(pcap_t *p, int error)
|
||||
* Default capture buffer size.
|
||||
* 32K isn't very much for modern machines with fast networks; we
|
||||
* pick .5M, as that's the maximum on at least some systems with BPF.
|
||||
*
|
||||
* However, on AIX 3.5, the larger buffer sized caused unrecoverable
|
||||
* read failures under stress, so we leave it as 32K; yet another
|
||||
* place where AIX's BPF is broken.
|
||||
*/
|
||||
#ifdef _AIX
|
||||
#define DEFAULT_BUFSIZE 32768
|
||||
#else
|
||||
#define DEFAULT_BUFSIZE 524288
|
||||
#endif
|
||||
|
||||
static int
|
||||
pcap_activate_bpf(pcap_t *p)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
int status = 0;
|
||||
int fd;
|
||||
#ifdef LIFNAMSIZ
|
||||
char *zonesep;
|
||||
struct lifreq ifr;
|
||||
char *ifrname = ifr.lifr_name;
|
||||
const size_t ifnamsiz = sizeof(ifr.lifr_name);
|
||||
@@ -1514,8 +1537,31 @@ pcap_activate_bpf(pcap_t *p)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
p->md.device = strdup(p->opt.source);
|
||||
if (p->md.device == NULL) {
|
||||
#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
|
||||
/*
|
||||
* Check if the given source network device has a '/' separated
|
||||
* zonename prefix string. The zonename prefixed source device
|
||||
* can be used by libpcap consumers to capture network traffic
|
||||
* in non-global zones from the global zone on Solaris 11 and
|
||||
* above. If the zonename prefix is present then we strip the
|
||||
* prefix and pass the zone ID as part of lifr_zoneid.
|
||||
*/
|
||||
if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
|
||||
char zonename[ZONENAME_MAX];
|
||||
int znamelen;
|
||||
char *lnamep;
|
||||
|
||||
znamelen = zonesep - p->opt.source;
|
||||
(void) strlcpy(zonename, p->opt.source, znamelen + 1);
|
||||
lnamep = strdup(zonesep + 1);
|
||||
ifr.lifr_zoneid = getzoneidbyname(zonename);
|
||||
free(p->opt.source);
|
||||
p->opt.source = lnamep;
|
||||
}
|
||||
#endif
|
||||
|
||||
pb->device = strdup(p->opt.source);
|
||||
if (pb->device == NULL) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
|
||||
pcap_strerror(errno));
|
||||
status = PCAP_ERROR;
|
||||
@@ -1623,7 +1669,7 @@ pcap_activate_bpf(pcap_t *p)
|
||||
/*
|
||||
* We have zerocopy BPF; use it.
|
||||
*/
|
||||
p->md.zerocopy = 1;
|
||||
pb->zerocopy = 1;
|
||||
|
||||
/*
|
||||
* How to pick a buffer size: first, query the maximum buffer
|
||||
@@ -1653,22 +1699,22 @@ pcap_activate_bpf(pcap_t *p)
|
||||
#ifndef roundup
|
||||
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
|
||||
#endif
|
||||
p->md.zbufsize = roundup(v, getpagesize());
|
||||
if (p->md.zbufsize > zbufmax)
|
||||
p->md.zbufsize = zbufmax;
|
||||
p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
|
||||
pb->zbufsize = roundup(v, getpagesize());
|
||||
if (pb->zbufsize > zbufmax)
|
||||
pb->zbufsize = zbufmax;
|
||||
pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON, -1, 0);
|
||||
p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
|
||||
pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON, -1, 0);
|
||||
if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) {
|
||||
if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
bzero(&bz, sizeof(bz));
|
||||
bz.bz_bufa = p->md.zbuf1;
|
||||
bz.bz_bufb = p->md.zbuf2;
|
||||
bz.bz_buflen = p->md.zbufsize;
|
||||
memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */
|
||||
bz.bz_bufa = pb->zbuf1;
|
||||
bz.bz_bufb = pb->zbuf2;
|
||||
bz.bz_buflen = pb->zbufsize;
|
||||
if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
|
||||
pcap_strerror(errno));
|
||||
@@ -1680,7 +1726,7 @@ pcap_activate_bpf(pcap_t *p)
|
||||
p->opt.source, pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
|
||||
v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -1992,8 +2038,8 @@ pcap_activate_bpf(pcap_t *p)
|
||||
if (v == DLT_FDDI)
|
||||
p->fddipad = PCAP_FDDIPAD;
|
||||
else
|
||||
p->fddipad = 0;
|
||||
#endif
|
||||
p->fddipad = 0;
|
||||
p->linktype = v;
|
||||
|
||||
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
|
||||
@@ -2015,9 +2061,14 @@ pcap_activate_bpf(pcap_t *p)
|
||||
#endif
|
||||
/* set timeout */
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (p->md.timeout != 0 && !p->md.zerocopy) {
|
||||
/*
|
||||
* In zero-copy mode, we just use the timeout in select().
|
||||
* XXX - what if we're in non-blocking mode and the *application*
|
||||
* is using select() or poll() or kqueues or....?
|
||||
*/
|
||||
if (p->opt.timeout && !pb->zerocopy) {
|
||||
#else
|
||||
if (p->md.timeout) {
|
||||
if (p->opt.timeout) {
|
||||
#endif
|
||||
/*
|
||||
* XXX - is this seconds/nanoseconds in AIX?
|
||||
@@ -2041,8 +2092,8 @@ pcap_activate_bpf(pcap_t *p)
|
||||
struct BPF_TIMEVAL bpf_to;
|
||||
|
||||
if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) {
|
||||
bpf_to.tv_sec = p->md.timeout / 1000;
|
||||
bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000;
|
||||
bpf_to.tv_sec = p->opt.timeout / 1000;
|
||||
bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
|
||||
@@ -2051,8 +2102,8 @@ pcap_activate_bpf(pcap_t *p)
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
to.tv_sec = p->md.timeout / 1000;
|
||||
to.tv_usec = (p->md.timeout * 1000) % 1000000;
|
||||
to.tv_sec = p->opt.timeout / 1000;
|
||||
to.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
|
||||
@@ -2064,7 +2115,6 @@ pcap_activate_bpf(pcap_t *p)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _AIX
|
||||
#ifdef BIOCIMMEDIATE
|
||||
/*
|
||||
* Darren Reed notes that
|
||||
@@ -2076,51 +2126,38 @@ pcap_activate_bpf(pcap_t *p)
|
||||
* is reducing things to only a few packets (i.e. one every
|
||||
* second or so).
|
||||
*
|
||||
* so we turn BIOCIMMEDIATE mode on if this is AIX.
|
||||
* so we always turn BIOCIMMEDIATE mode on if this is AIX.
|
||||
*
|
||||
* We don't turn it on for other platforms, as that means we
|
||||
* get woken up for every packet, which may not be what we want;
|
||||
* in the Winter 1993 USENIX paper on BPF, they say:
|
||||
* For other platforms, we don't turn immediate mode on by default,
|
||||
* as that would mean we get woken up for every packet, which
|
||||
* probably isn't what you want for a packet sniffer.
|
||||
*
|
||||
* Since a process might want to look at every packet on a
|
||||
* network and the time between packets can be only a few
|
||||
* microseconds, it is not possible to do a read system call
|
||||
* per packet and BPF must collect the data from several
|
||||
* packets and return it as a unit when the monitoring
|
||||
* application does a read.
|
||||
*
|
||||
* which I infer is the reason for the timeout - it means we
|
||||
* wait that amount of time, in the hopes that more packets
|
||||
* will arrive and we'll get them all with one read.
|
||||
*
|
||||
* Setting BIOCIMMEDIATE mode on FreeBSD (and probably other
|
||||
* BSDs) causes the timeout to be ignored.
|
||||
*
|
||||
* On the other hand, some platforms (e.g., Linux) don't support
|
||||
* timeouts, they just hand stuff to you as soon as it arrives;
|
||||
* if that doesn't cause a problem on those platforms, it may
|
||||
* be OK to have BIOCIMMEDIATE mode on BSD as well.
|
||||
*
|
||||
* (Note, though, that applications may depend on the read
|
||||
* completing, even if no packets have arrived, when the timeout
|
||||
* expires, e.g. GUI applications that have to check for input
|
||||
* while waiting for packets to arrive; a non-zero timeout
|
||||
* prevents "select()" from working right on FreeBSD and
|
||||
* possibly other BSDs, as the timer doesn't start until a
|
||||
* "read()" is done, so the timer isn't in effect if the
|
||||
* application is blocked on a "select()", and the "select()"
|
||||
* doesn't get woken up for a BPF device until the buffer
|
||||
* fills up.)
|
||||
* We set immediate mode if the caller requested it by calling
|
||||
* pcap_set_immediate() before calling pcap_activate().
|
||||
*/
|
||||
v = 1;
|
||||
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
|
||||
pcap_strerror(errno));
|
||||
#ifndef _AIX
|
||||
if (p->opt.immediate) {
|
||||
#endif /* _AIX */
|
||||
v = 1;
|
||||
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"BIOCIMMEDIATE: %s", pcap_strerror(errno));
|
||||
status = PCAP_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
#ifndef _AIX
|
||||
}
|
||||
#endif /* _AIX */
|
||||
#else /* BIOCIMMEDIATE */
|
||||
if (p->opt.immediate) {
|
||||
/*
|
||||
* We don't support immediate mode. Fail.
|
||||
*/
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
|
||||
status = PCAP_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
#endif /* BIOCIMMEDIATE */
|
||||
#endif /* _AIX */
|
||||
#endif /* BIOCIMMEDIATE */
|
||||
|
||||
if (p->opt.promisc) {
|
||||
/* set promiscuous mode, just warn if it fails */
|
||||
@@ -2139,7 +2176,7 @@ pcap_activate_bpf(pcap_t *p)
|
||||
}
|
||||
p->bufsize = v;
|
||||
#ifdef HAVE_ZEROCOPY_BPF
|
||||
if (!p->md.zerocopy) {
|
||||
if (!pb->zerocopy) {
|
||||
#endif
|
||||
p->buffer = (u_char *)malloc(p->bufsize);
|
||||
if (p->buffer == NULL) {
|
||||
@@ -2240,22 +2277,13 @@ pcap_activate_bpf(pcap_t *p)
|
||||
|
||||
return (status);
|
||||
bad:
|
||||
pcap_cleanup_bpf(p);
|
||||
pcap_cleanup_bpf(p);
|
||||
return (status);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
#ifdef HAVE_DAG_API
|
||||
if (dag_platform_finddevs(alldevsp, errbuf) < 0)
|
||||
return (-1);
|
||||
#endif /* HAVE_DAG_API */
|
||||
#ifdef HAVE_SNF_API
|
||||
if (snf_platform_finddevs(alldevsp, errbuf) < 0)
|
||||
return (-1);
|
||||
#endif /* HAVE_SNF_API */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -2263,6 +2291,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
static int
|
||||
monitor_mode(pcap_t *p, int set)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
int sock;
|
||||
struct ifmediareq req;
|
||||
int *media_list;
|
||||
@@ -2400,7 +2429,7 @@ monitor_mode(pcap_t *p, int set)
|
||||
return (PCAP_ERROR);
|
||||
}
|
||||
|
||||
p->md.must_do_on_close |= MUST_CLEAR_RFMON;
|
||||
pb->must_do_on_close |= MUST_CLEAR_RFMON;
|
||||
|
||||
/*
|
||||
* Add this to the list of pcaps to close when we exit.
|
||||
@@ -2577,6 +2606,8 @@ remove_802_11(pcap_t *p)
|
||||
static int
|
||||
pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
|
||||
{
|
||||
struct pcap_bpf *pb = p->priv;
|
||||
|
||||
/*
|
||||
* Free any user-mode filter we might happen to have installed.
|
||||
*/
|
||||
@@ -2589,7 +2620,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
|
||||
/*
|
||||
* It worked.
|
||||
*/
|
||||
p->md.use_bpf = 1; /* filtering in the kernel */
|
||||
pb->filtering_in_kernel = 1; /* filtering in the kernel */
|
||||
|
||||
/*
|
||||
* Discard any previously-received packets, as they might
|
||||
@@ -2629,7 +2660,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
|
||||
*/
|
||||
if (install_bpf_program(p, fp) < 0)
|
||||
return (-1);
|
||||
p->md.use_bpf = 0; /* filtering in userland */
|
||||
pb->filtering_in_kernel = 0; /* filtering in userland */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,15 +70,21 @@ static int bt_inject_linux(pcap_t *, const void *, size_t);
|
||||
static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
|
||||
static int bt_stats_linux(pcap_t *, struct pcap_stat *);
|
||||
|
||||
/*
|
||||
* Private data for capturing on Linux Bluetooth devices.
|
||||
*/
|
||||
struct pcap_bt {
|
||||
int dev_id; /* device ID of device we're bound to */
|
||||
};
|
||||
|
||||
int
|
||||
bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
|
||||
{
|
||||
pcap_if_t *found_dev = *alldevsp;
|
||||
struct hci_dev_list_req *dev_list;
|
||||
struct hci_dev_req *dev_req;
|
||||
int i, sock;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
|
||||
if (sock < 0)
|
||||
{
|
||||
@@ -117,7 +123,7 @@ bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
|
||||
snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
|
||||
|
||||
if (pcap_add_if(&found_dev, dev_name, 0,
|
||||
if (pcap_add_if(alldevsp, dev_name, 0,
|
||||
dev_descr, err_str) < 0)
|
||||
{
|
||||
ret = -1;
|
||||
@@ -135,11 +141,41 @@ done:
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
bt_create(const char *device, char *ebuf)
|
||||
bt_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
char *cpend;
|
||||
long devnum;
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like a Bluetooth device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
/* Does it begin with BT_IFACE? */
|
||||
if (strncmp(cp, BT_IFACE, sizeof BT_IFACE - 1) != 0) {
|
||||
/* Nope, doesn't begin with BT_IFACE */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Yes - is BT_IFACE followed by a number? */
|
||||
cp += sizeof BT_IFACE - 1;
|
||||
devnum = strtol(cp, &cpend, 10);
|
||||
if (cpend == cp || *cpend != '\0') {
|
||||
/* Not followed by a number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (devnum < 0) {
|
||||
/* Followed by a non-valid number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_bt));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -150,6 +186,7 @@ bt_create(const char *device, char *ebuf)
|
||||
static int
|
||||
bt_activate(pcap_t* handle)
|
||||
{
|
||||
struct pcap_bt *handlep = handle->priv;
|
||||
struct sockaddr_hci addr;
|
||||
int opt;
|
||||
int dev_id;
|
||||
@@ -178,7 +215,7 @@ bt_activate(pcap_t* handle)
|
||||
handle->getnonblock_op = pcap_getnonblock_fd;
|
||||
handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
handle->stats_op = bt_stats_linux;
|
||||
handle->md.ifindex = dev_id;
|
||||
handlep->dev_id = dev_id;
|
||||
|
||||
/* Create HCI socket */
|
||||
handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
|
||||
@@ -223,10 +260,13 @@ bt_activate(pcap_t* handle)
|
||||
|
||||
/* Bind socket to the HCI device */
|
||||
addr.hci_family = AF_BLUETOOTH;
|
||||
addr.hci_dev = handle->md.ifindex;
|
||||
addr.hci_dev = handlep->dev_id;
|
||||
#ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL
|
||||
addr.hci_channel = HCI_CHANNEL_RAW;
|
||||
#endif
|
||||
if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"Can't attach to device %d: %s", handle->md.ifindex,
|
||||
"Can't attach to device %d: %s", handlep->dev_id,
|
||||
strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
@@ -341,10 +381,11 @@ bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
|
||||
static int
|
||||
bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
struct pcap_bt *handlep = handle->priv;
|
||||
int ret;
|
||||
struct hci_dev_info dev_info;
|
||||
struct hci_dev_stats * s = &dev_info.stat;
|
||||
dev_info.dev_id = handle->md.ifindex;
|
||||
dev_info.dev_id = handlep->dev_id;
|
||||
|
||||
/* ignore eintr */
|
||||
do {
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
/*
|
||||
* Prototypes for Bluetooth-related functions
|
||||
*/
|
||||
int bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *bt_create(const char *device, char *ebuf);
|
||||
int bt_findalldevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *bt_create(const char *device, char *ebuf, int *is_ours);
|
||||
|
||||
@@ -72,12 +72,66 @@ static int can_setfilter_linux(pcap_t *, struct bpf_program *);
|
||||
static int can_setdirection_linux(pcap_t *, pcap_direction_t);
|
||||
static int can_stats_linux(pcap_t *, struct pcap_stat *);
|
||||
|
||||
pcap_t *
|
||||
can_create(const char *device, char *ebuf)
|
||||
/*
|
||||
* Private data for capturing on Linux CANbus devices.
|
||||
*/
|
||||
struct pcap_can {
|
||||
int ifindex; /* interface index of device we're bound to */
|
||||
};
|
||||
|
||||
int
|
||||
can_findalldevs(pcap_if_t **devlistp, char *errbuf)
|
||||
{
|
||||
/*
|
||||
* There are no platform-specific devices since each device
|
||||
* exists as a regular network interface.
|
||||
*
|
||||
* XXX - true?
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
can_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
char *cpend;
|
||||
long devnum;
|
||||
pcap_t* p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like a CANbus device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
/* Does it begin with "can" or "vcan"? */
|
||||
if (strncmp(cp, "can", 3) == 0) {
|
||||
/* Begins with "can" */
|
||||
cp += 3; /* skip past "can" */
|
||||
} else if (strncmp(cp, "vcan", 4) == 0) {
|
||||
/* Begins with "vcan" */
|
||||
cp += 4;
|
||||
} else {
|
||||
/* Nope, doesn't begin with "can" or "vcan" */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Yes - is "can" or "vcan" followed by a number from 0? */
|
||||
devnum = strtol(cp, &cpend, 10);
|
||||
if (cpend == cp || *cpend != '\0') {
|
||||
/* Not followed by a number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (devnum < 0) {
|
||||
/* Followed by a non-valid number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_can));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -89,6 +143,7 @@ can_create(const char *device, char *ebuf)
|
||||
static int
|
||||
can_activate(pcap_t* handle)
|
||||
{
|
||||
struct pcap_can *handlep = handle->priv;
|
||||
struct sockaddr_can addr;
|
||||
struct ifreq ifr;
|
||||
|
||||
@@ -125,7 +180,7 @@ can_activate(pcap_t* handle)
|
||||
pcap_cleanup_live_common(handle);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
handle->md.ifindex = ifr.ifr_ifindex;
|
||||
handlep->ifindex = ifr.ifr_ifindex;
|
||||
|
||||
/* allocate butter */
|
||||
handle->buffer = malloc(handle->bufsize);
|
||||
@@ -139,11 +194,11 @@ can_activate(pcap_t* handle)
|
||||
|
||||
/* Bind to the socket */
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = handle->md.ifindex;
|
||||
addr.can_ifindex = handlep->ifindex;
|
||||
if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 )
|
||||
{
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
|
||||
handle->md.ifindex, errno, strerror(errno));
|
||||
handlep->ifindex, errno, strerror(errno));
|
||||
pcap_cleanup_live_common(handle);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
@@ -152,7 +207,7 @@ can_activate(pcap_t* handle)
|
||||
{
|
||||
/* Monitor mode doesn't apply to CAN devices. */
|
||||
pcap_cleanup_live_common(handle);
|
||||
return PCAP_ERROR;
|
||||
return PCAP_ERROR_RFMON_NOTSUP;
|
||||
}
|
||||
|
||||
handle->selectable_fd = handle->fd;
|
||||
|
||||
@@ -32,4 +32,5 @@
|
||||
/*
|
||||
* Prototypes for SocketCAN related functions
|
||||
*/
|
||||
pcap_t* can_create(const char *device, char *ebuf);
|
||||
pcap_t* can_create(const char *device, char *ebuf, int *is_ours);
|
||||
int can_findalldevs(pcap_if_t **devlistp, char *errbuf);
|
||||
|
||||
472
libpcap/pcap-canusb-linux.c
Normal file
472
libpcap/pcap-canusb-linux.c
Normal file
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Felix Obenhuber
|
||||
* 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. The name of the author may not 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.
|
||||
*
|
||||
* Sockettrace sniffing API implementation for Linux platform
|
||||
* By Felix Obenhuber <felix@obenhuber.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "pcap-canusb-linux.h"
|
||||
|
||||
#define CANUSB_IFACE "canusb"
|
||||
|
||||
#define CANUSB_VID 0x0403
|
||||
#define CANUSB_PID 0x8990
|
||||
|
||||
#define USE_THREAD 1
|
||||
|
||||
#if USE_THREAD == 0
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* forward declaration */
|
||||
static int canusb_activate(pcap_t *);
|
||||
static int canusb_read_linux(pcap_t *, int , pcap_handler , u_char *);
|
||||
static int canusb_inject_linux(pcap_t *, const void *, size_t);
|
||||
static int canusb_setfilter_linux(pcap_t *, struct bpf_program *);
|
||||
static int canusb_setdirection_linux(pcap_t *, pcap_direction_t);
|
||||
static int canusb_stats_linux(pcap_t *, struct pcap_stat *);
|
||||
|
||||
struct CAN_Msg
|
||||
{
|
||||
uint32_t timestamp;
|
||||
uint32_t id;
|
||||
uint32_t length;
|
||||
uint8_t data[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* Private data for capturing on Linux CANbus USB devices.
|
||||
*/
|
||||
struct pcap_canusb {
|
||||
libusb_context *ctx;
|
||||
libusb_device_handle *dev;
|
||||
pthread_t worker;
|
||||
int rdpipe, wrpipe;
|
||||
volatile int loop;
|
||||
};
|
||||
|
||||
int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
|
||||
{
|
||||
libusb_context *fdctx;
|
||||
libusb_device** devs;
|
||||
unsigned char sernum[65];
|
||||
int cnt, i;
|
||||
|
||||
if (libusb_init(&fdctx) != 0) {
|
||||
/*
|
||||
* XXX - if this doesn't just mean "no USB file system mounted",
|
||||
* perhaps we should report a real error rather than just
|
||||
* saying "no CANUSB devices".
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
cnt = libusb_get_device_list(fdctx,&devs);
|
||||
|
||||
for(i=0;i<cnt;i++)
|
||||
{
|
||||
int ret;
|
||||
// Check if this device is interesting.
|
||||
struct libusb_device_descriptor desc;
|
||||
libusb_get_device_descriptor(devs[i],&desc);
|
||||
|
||||
if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
|
||||
continue; //It is not, check next device
|
||||
|
||||
//It is!
|
||||
libusb_device_handle *dh = NULL;
|
||||
|
||||
if ((ret = libusb_open(devs[i],&dh)) == 0)
|
||||
{
|
||||
char dev_name[30];
|
||||
char dev_descr[50];
|
||||
int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64);
|
||||
sernum[n] = 0;
|
||||
|
||||
snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
|
||||
snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
|
||||
|
||||
libusb_close(dh);
|
||||
|
||||
if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
|
||||
{
|
||||
libusb_free_device_list(devs,1);
|
||||
libusb_exit(fdctx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(devs,1);
|
||||
libusb_exit(fdctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial)
|
||||
{
|
||||
libusb_device** devs;
|
||||
unsigned char serial[65];
|
||||
int cnt,i,n;
|
||||
|
||||
cnt = libusb_get_device_list(ctx,&devs);
|
||||
|
||||
for(i=0;i<cnt;i++)
|
||||
{
|
||||
// Check if this device is interesting.
|
||||
struct libusb_device_descriptor desc;
|
||||
libusb_get_device_descriptor(devs[i],&desc);
|
||||
|
||||
if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
|
||||
continue;
|
||||
|
||||
//Found one!
|
||||
libusb_device_handle *dh = NULL;
|
||||
|
||||
if (libusb_open(devs[i],&dh) != 0) continue;
|
||||
|
||||
n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64);
|
||||
serial[n] = 0;
|
||||
|
||||
if ((devserial) && (strcmp((char *)serial,devserial) != 0))
|
||||
{
|
||||
libusb_close(dh);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((libusb_kernel_driver_active(dh,0)) && (libusb_detach_kernel_driver(dh,0) != 0))
|
||||
{
|
||||
libusb_close(dh);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libusb_set_configuration(dh,1) != 0)
|
||||
{
|
||||
libusb_close(dh);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libusb_claim_interface(dh,0) != 0)
|
||||
{
|
||||
libusb_close(dh);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Fount it!
|
||||
libusb_free_device_list(devs,1);
|
||||
return dh;
|
||||
}
|
||||
|
||||
libusb_free_device_list(devs,1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
pcap_t *
|
||||
canusb_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
char *cpend;
|
||||
long devnum;
|
||||
pcap_t* p;
|
||||
struct pcap_canusb *canusb;
|
||||
|
||||
/* Does this look like a DAG device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
/* Does it begin with "canusb"? */
|
||||
if (strncmp(cp, "canusb", 6) != 0) {
|
||||
/* Nope, doesn't begin with "canusb" */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Yes - is "canusb" followed by a number? */
|
||||
cp += 6;
|
||||
devnum = strtol(cp, &cpend, 10);
|
||||
if (cpend == cp || *cpend != '\0') {
|
||||
/* Not followed by a number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (devnum < 0) {
|
||||
/* Followed by a non-valid number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_canusb));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
canusb = p->priv;
|
||||
canusb->ctx = NULL;
|
||||
canusb->dev = NULL;
|
||||
canusb->rdpipe = -1;
|
||||
canusb->wrpipe = -1;
|
||||
|
||||
p->activate_op = canusb_activate;
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
||||
static void* canusb_capture_thread(void *arg)
|
||||
{
|
||||
struct pcap_canusb *canusb = arg;
|
||||
int i;
|
||||
struct
|
||||
{
|
||||
uint8_t rxsz, txsz;
|
||||
} status;
|
||||
|
||||
fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
|
||||
|
||||
while(canusb->loop)
|
||||
{
|
||||
int sz;
|
||||
struct CAN_Msg msg;
|
||||
|
||||
libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
|
||||
//HACK!!!!! -> drop buffered data, read new one by reading twice.
|
||||
libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
|
||||
|
||||
for(i = 0; i<status.rxsz; i++)
|
||||
{
|
||||
libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
|
||||
write(canusb->wrpipe, &msg, sizeof(msg));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int canusb_startcapture(struct pcap_canusb* this)
|
||||
{
|
||||
int pipefd[2];
|
||||
|
||||
if (pipe(pipefd) == -1)
|
||||
return -1;
|
||||
|
||||
this->rdpipe = pipefd[0];
|
||||
this->wrpipe = pipefd[1];
|
||||
|
||||
this->loop = 1;
|
||||
pthread_create(&this->worker, NULL, canusb_capture_thread, this);
|
||||
|
||||
return this->rdpipe;
|
||||
}
|
||||
|
||||
static void canusb_clearbufs(struct pcap_canusb* this)
|
||||
{
|
||||
unsigned char cmd[16];
|
||||
int al;
|
||||
|
||||
cmd[0] = 1; //Empty incoming buffer
|
||||
cmd[1] = 1; //Empty outgoing buffer
|
||||
cmd[3] = 0; //Not a write to serial number
|
||||
memset(&cmd[4],0,16-4);
|
||||
|
||||
libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
|
||||
}
|
||||
|
||||
|
||||
static void canusb_close(pcap_t* handle)
|
||||
{
|
||||
struct pcap_canusb *canusb = handle->priv;
|
||||
|
||||
canusb->loop = 0;
|
||||
pthread_join(canusb->worker, NULL);
|
||||
|
||||
if (canusb->dev)
|
||||
{
|
||||
libusb_close(canusb->dev);
|
||||
canusb->dev = NULL;
|
||||
}
|
||||
if (canusb->ctx)
|
||||
{
|
||||
libusb_exit(canusb->ctx);
|
||||
canusb->ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int canusb_activate(pcap_t* handle)
|
||||
{
|
||||
struct pcap_canusb *canusb = handle->priv;
|
||||
char *serial;
|
||||
|
||||
if (libusb_init(&canusb->ctx) != 0) {
|
||||
/*
|
||||
* XXX - what causes this to fail?
|
||||
*/
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed");
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
handle->read_op = canusb_read_linux;
|
||||
|
||||
handle->inject_op = canusb_inject_linux;
|
||||
handle->setfilter_op = canusb_setfilter_linux;
|
||||
handle->setdirection_op = canusb_setdirection_linux;
|
||||
handle->getnonblock_op = pcap_getnonblock_fd;
|
||||
handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
handle->stats_op = canusb_stats_linux;
|
||||
handle->cleanup_op = canusb_close;
|
||||
|
||||
/* Initialize some components of the pcap structure. */
|
||||
handle->bufsize = 32;
|
||||
handle->offset = 8;
|
||||
handle->linktype = DLT_CAN_SOCKETCAN;
|
||||
handle->set_datalink_op = NULL;
|
||||
|
||||
serial = handle->opt.source + strlen(CANUSB_IFACE);
|
||||
|
||||
canusb->dev = canusb_opendevice(canusb->ctx, serial);
|
||||
if (!canusb->dev)
|
||||
{
|
||||
libusb_exit(canusb->ctx);
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device");
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
canusb_clearbufs(canusb);
|
||||
|
||||
handle->fd = canusb_startcapture(canusb);
|
||||
handle->selectable_fd = handle->fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
{
|
||||
static struct timeval firstpacket = { -1, -1};
|
||||
int i = 0;
|
||||
struct CAN_Msg msg;
|
||||
struct pcap_pkthdr pkth;
|
||||
|
||||
while(i < max_packets)
|
||||
{
|
||||
int n;
|
||||
usleep(10 * 1000);
|
||||
n = read(handle->fd, &msg, sizeof(msg));
|
||||
if (n <= 0)
|
||||
break;
|
||||
pkth.caplen = pkth.len = n;
|
||||
pkth.caplen -= 4;
|
||||
pkth.caplen -= 8 - msg.length;
|
||||
|
||||
if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
|
||||
gettimeofday(&firstpacket, NULL);
|
||||
|
||||
pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
|
||||
pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
|
||||
if (pkth.ts.tv_usec > 1000000)
|
||||
{
|
||||
pkth.ts.tv_usec -= 1000000;
|
||||
pkth.ts.tv_sec++;
|
||||
}
|
||||
|
||||
callback(user, &pkth, (void*)&msg.id);
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
canusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
|
||||
{
|
||||
/* not yet implemented */
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
/* not yet implemented */
|
||||
stats->ps_recv = 0; /* number of packets received */
|
||||
stats->ps_drop = 0; /* number of packets dropped */
|
||||
stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
|
||||
{
|
||||
/* not yet implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
canusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
|
||||
{
|
||||
/* no support for PCAP_D_OUT */
|
||||
if (d == PCAP_D_OUT)
|
||||
{
|
||||
snprintf(p->errbuf, sizeof(p->errbuf),
|
||||
"Setting direction to PCAP_D_OUT is not supported on this interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->direction = d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* eof */
|
||||
37
libpcap/pcap-canusb-linux.h
Normal file
37
libpcap/pcap-canusb-linux.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Felix Obenhuber
|
||||
* 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. The name of the author may not 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prototypes for SocketCAN related functions
|
||||
*/
|
||||
pcap_t* canusb_create(const char *device, char *ebuf, int *is_ours);
|
||||
int canusb_findalldevs(pcap_if_t **pdevlist, char* errbuf);
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
#define LINKTYPE_AX25 DLT_AX25
|
||||
#define LINKTYPE_PRONET DLT_PRONET
|
||||
#define LINKTYPE_CHAOS DLT_CHAOS
|
||||
#define LINKTYPE_TOKEN_RING DLT_IEEE802 /* DLT_IEEE802 is used for Token Ring */
|
||||
#define LINKTYPE_IEEE802_5 DLT_IEEE802 /* DLT_IEEE802 is used for 802.5 Token Ring */
|
||||
#define LINKTYPE_ARCNET_BSD DLT_ARCNET /* BSD-style headers */
|
||||
#define LINKTYPE_SLIP DLT_SLIP
|
||||
#define LINKTYPE_PPP DLT_PPP
|
||||
@@ -193,8 +193,8 @@
|
||||
|
||||
#define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */
|
||||
#define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */
|
||||
#define LINKTYPE_PRISM_HEADER 119 /* 802.11+Prism II monitor mode */
|
||||
#define LINKTYPE_AIRONET_HEADER 120 /* FreeBSD Aironet driver stuff */
|
||||
#define LINKTYPE_IEEE802_11_PRISM 119 /* 802.11 plus Prism II monitor mode radio metadata header */
|
||||
#define LINKTYPE_IEEE802_11_AIRONET 120 /* 802.11 plus FreeBSD Aironet driver radio metadata header */
|
||||
|
||||
/*
|
||||
* Reserved for Siemens HiPath HDLC.
|
||||
@@ -212,7 +212,7 @@
|
||||
#define LINKTYPE_PCI_EXP 125 /* PCI Express */
|
||||
#define LINKTYPE_AURORA 126 /* Xilinx Aurora link layer */
|
||||
|
||||
#define LINKTYPE_IEEE802_11_RADIO 127 /* 802.11 plus BSD radio header */
|
||||
#define LINKTYPE_IEEE802_11_RADIOTAP 127 /* 802.11 plus radiotap radio metadata header */
|
||||
|
||||
/*
|
||||
* Reserved for the TZSP encapsulation, as per request from
|
||||
@@ -307,11 +307,8 @@
|
||||
* including radio information:
|
||||
*
|
||||
* http://www.shaftnet.org/~pizza/software/capturefrm.txt
|
||||
*
|
||||
* but could and arguably should also be used by non-AVS Linux
|
||||
* 802.11 drivers; that may happen in the future.
|
||||
*/
|
||||
#define LINKTYPE_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
|
||||
#define LINKTYPE_IEEE802_11_AVS 163 /* 802.11 plus AVS radio metadata header */
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
@@ -322,7 +319,7 @@
|
||||
#define LINKTYPE_JUNIPER_MONITOR 164
|
||||
|
||||
/*
|
||||
* Reserved for BACnet MS/TP.
|
||||
* BACnet MS/TP frames.
|
||||
*/
|
||||
#define LINKTYPE_BACNET_MS_TP 165
|
||||
|
||||
@@ -844,13 +841,98 @@
|
||||
#define LINKTYPE_NETANALYZER_TRANSPARENT 241
|
||||
|
||||
/*
|
||||
* IP-over-Infiniband, as specified by RFC 4391.
|
||||
* IP-over-InfiniBand, as specified by RFC 4391.
|
||||
*
|
||||
* Requested by Petr Sumbera <petr.sumbera@oracle.com>.
|
||||
*/
|
||||
#define LINKTYPE_IPOIB 242
|
||||
|
||||
#define LINKTYPE_MATCHING_MAX 242 /* highest value in the "matching" range */
|
||||
/*
|
||||
* MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
|
||||
*
|
||||
* Requested by Guy Martin <gmsoft@tuxicoman.be>.
|
||||
*/
|
||||
#define LINKTYPE_MPEG_2_TS 243
|
||||
|
||||
/*
|
||||
* ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
|
||||
* used by their ng40 protocol tester.
|
||||
*
|
||||
* Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
|
||||
*/
|
||||
#define LINKTYPE_NG40 244
|
||||
|
||||
/*
|
||||
* Pseudo-header giving adapter number and flags, followed by an NFC
|
||||
* (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
|
||||
* as specified by NFC Forum Logical Link Control Protocol Technical
|
||||
* Specification LLCP 1.1.
|
||||
*
|
||||
* Requested by Mike Wakerly <mikey@google.com>.
|
||||
*/
|
||||
#define LINKTYPE_NFC_LLCP 245
|
||||
|
||||
/*
|
||||
* pfsync output; DLT_PFSYNC is 18, which collides with DLT_CIP in
|
||||
* SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and Mac OS X, and
|
||||
* is 121, which collides with DLT_HHDLC, in FreeBSD. We pick a
|
||||
* shiny new link-layer header type value that doesn't collide with
|
||||
* anything, in the hopes that future pfsync savefiles, if any,
|
||||
* won't require special hacks to distinguish from other savefiles.
|
||||
*
|
||||
*/
|
||||
#define LINKTYPE_PFSYNC 246
|
||||
|
||||
/*
|
||||
* Raw InfiniBand packets, starting with the Local Routing Header.
|
||||
*
|
||||
* Requested by Oren Kladnitsky <orenk@mellanox.com>.
|
||||
*/
|
||||
#define LINKTYPE_INFINIBAND 247
|
||||
|
||||
/*
|
||||
* SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
|
||||
*
|
||||
* Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
|
||||
*/
|
||||
#define LINKTYPE_SCTP 248
|
||||
|
||||
/*
|
||||
* USB packets, beginning with a USBPcap header.
|
||||
*
|
||||
* Requested by Tomasz Mon <desowin@gmail.com>
|
||||
*/
|
||||
#define LINKTYPE_USBPCAP 249
|
||||
|
||||
/*
|
||||
* Schweitzer Engineering Laboratories "RTAC" product serial-line
|
||||
* packets.
|
||||
*
|
||||
* Requested by Chris Bontje <chris_bontje@selinc.com>.
|
||||
*/
|
||||
#define DLT_RTAC_SERIAL 250
|
||||
|
||||
/*
|
||||
* Bluetooth Low Energy air interface link-layer packets.
|
||||
*
|
||||
* Requested by Mike Kershaw <dragorn@kismetwireless.net>.
|
||||
*/
|
||||
#define LINKTYPE_BLUETOOTH_LE_LL 251
|
||||
|
||||
/*
|
||||
* Link-layer header type for upper-protocol layer PDU saves from wireshark.
|
||||
*
|
||||
* the actual contents are determined by two TAGs stored with each
|
||||
* packet:
|
||||
* EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
|
||||
* original packet.
|
||||
*
|
||||
* EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
|
||||
* that can make sense of the data stored.
|
||||
*/
|
||||
#define LINKTYPE_WIRESHARK_UPPER_PDU 252
|
||||
|
||||
#define LINKTYPE_MATCHING_MAX 252 /* highest value in the "matching" range */
|
||||
|
||||
static struct linktype_map {
|
||||
int dlt;
|
||||
@@ -866,11 +948,12 @@ static struct linktype_map {
|
||||
{ DLT_AX25, LINKTYPE_AX25 },
|
||||
{ DLT_PRONET, LINKTYPE_PRONET },
|
||||
{ DLT_CHAOS, LINKTYPE_CHAOS },
|
||||
{ DLT_IEEE802, LINKTYPE_TOKEN_RING },
|
||||
{ DLT_IEEE802, LINKTYPE_IEEE802_5 },
|
||||
{ DLT_ARCNET, LINKTYPE_ARCNET_BSD },
|
||||
{ DLT_SLIP, LINKTYPE_SLIP },
|
||||
{ DLT_PPP, LINKTYPE_PPP },
|
||||
{ DLT_FDDI, LINKTYPE_FDDI },
|
||||
{ DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL },
|
||||
|
||||
/*
|
||||
* These DLT_* codes have different values on different
|
||||
@@ -883,7 +966,6 @@ static struct linktype_map {
|
||||
{ DLT_FR, LINKTYPE_FRELAY },
|
||||
#endif
|
||||
|
||||
{ DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL },
|
||||
{ DLT_ATM_RFC1483, LINKTYPE_ATM_RFC1483 },
|
||||
{ DLT_RAW, LINKTYPE_RAW },
|
||||
{ DLT_SLIP_BSDOS, LINKTYPE_SLIP_BSDOS },
|
||||
@@ -922,6 +1004,12 @@ dlt_to_linktype(int dlt)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Map DLT_PFSYNC, whatever it might be, to LINKTYPE_PFSYNC.
|
||||
*/
|
||||
if (dlt == DLT_PFSYNC)
|
||||
return (LINKTYPE_PFSYNC);
|
||||
|
||||
/*
|
||||
* Map the values in the matching range.
|
||||
*/
|
||||
@@ -949,6 +1037,15 @@ linktype_to_dlt(int linktype)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Map LINKTYPE_PFSYNC to DLT_PFSYNC, whatever it might be.
|
||||
* LINKTYPE_PFSYNC is in the matching range, to make sure
|
||||
* it's as safe from reuse as we can arrange, so we do
|
||||
* this test first.
|
||||
*/
|
||||
if (linktype == LINKTYPE_PFSYNC)
|
||||
return (DLT_PFSYNC);
|
||||
|
||||
/*
|
||||
* Map the values in the matching range.
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,15 @@ struct rtentry; /* declarations in <net/if.h> */
|
||||
|
||||
#include "pcap-dag.h"
|
||||
|
||||
/*
|
||||
* DAG devices have names beginning with "dag", followed by a number
|
||||
* from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number
|
||||
* from 0 to DAG_STREAM_MAX.
|
||||
*/
|
||||
#ifndef DAG_MAX_BOARDS
|
||||
#define DAG_MAX_BOARDS 32
|
||||
#endif
|
||||
|
||||
#define ATM_CELL_SIZE 52
|
||||
#define ATM_HDR_SIZE 4
|
||||
|
||||
@@ -70,6 +79,27 @@ struct sunatm_hdr {
|
||||
unsigned short vci; /* VCI */
|
||||
};
|
||||
|
||||
/*
|
||||
* Private data for capturing on DAG devices.
|
||||
*/
|
||||
struct pcap_dag {
|
||||
struct pcap_stat stat;
|
||||
#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? */
|
||||
};
|
||||
|
||||
typedef struct pcap_dag_node {
|
||||
struct pcap_dag_node *next;
|
||||
pcap_t *p;
|
||||
@@ -82,15 +112,6 @@ static const unsigned short endian_test_word = 0x0100;
|
||||
|
||||
#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
|
||||
|
||||
|
||||
#ifdef DAG_ONLY
|
||||
/* This code is required when compiling for a DAG device only. */
|
||||
|
||||
/* Replace dag function names with pcap equivalent. */
|
||||
#define dag_create pcap_create
|
||||
#define dag_platform_finddevs pcap_platform_finddevs
|
||||
#endif /* DAG_ONLY */
|
||||
|
||||
#define MAX_DAG_PACKET 65536
|
||||
|
||||
static unsigned char TempPkt[MAX_DAG_PACKET];
|
||||
@@ -127,13 +148,15 @@ delete_pcap_dag(pcap_t *p)
|
||||
static void
|
||||
dag_platform_cleanup(pcap_t *p)
|
||||
{
|
||||
|
||||
struct pcap_dag *pd;
|
||||
|
||||
if (p != NULL) {
|
||||
pd = p->priv;
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)
|
||||
if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
|
||||
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
|
||||
|
||||
if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)
|
||||
if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
|
||||
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
|
||||
#else
|
||||
if(dag_stop(p->fd) < 0)
|
||||
@@ -205,7 +228,7 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len)
|
||||
do {
|
||||
|
||||
/* sanity check we have enough bytes */
|
||||
if ( len <= (24 + (hdr_num * 8)) )
|
||||
if ( len < (24 + (hdr_num * 8)) )
|
||||
return hdr_num;
|
||||
|
||||
/* get the header type */
|
||||
@@ -225,13 +248,14 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len)
|
||||
static int
|
||||
dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_dag *pd = p->priv;
|
||||
unsigned int processed = 0;
|
||||
int flags = p->md.dag_offset_flags;
|
||||
int flags = pd->dag_offset_flags;
|
||||
unsigned int nonblocking = flags & DAGF_NONBLOCK;
|
||||
unsigned int num_ext_hdr = 0;
|
||||
|
||||
/* Get the next bufferful of packets (if necessary). */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
|
||||
while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
|
||||
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
@@ -258,23 +282,23 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
* If non-block is specified it will return immediately. The user
|
||||
* is then responsible for efficiency.
|
||||
*/
|
||||
if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) {
|
||||
if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/* dag_offset does not support timeouts */
|
||||
p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
|
||||
pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
|
||||
if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
|
||||
{
|
||||
/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!nonblocking &&
|
||||
p->md.dag_timeout &&
|
||||
(p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
|
||||
pd->dag_timeout &&
|
||||
(pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
|
||||
{
|
||||
/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
|
||||
return 0;
|
||||
@@ -283,16 +307,16 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
}
|
||||
|
||||
/* Process the packets. */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
|
||||
while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
|
||||
|
||||
unsigned short packet_len = 0;
|
||||
int caplen = 0;
|
||||
struct pcap_pkthdr pcap_header;
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
|
||||
dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
|
||||
#else
|
||||
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
|
||||
dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
u_char *dp = ((u_char *)header); /* + dag_record_size; */
|
||||
@@ -317,7 +341,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
|
||||
return -1;
|
||||
}
|
||||
p->md.dag_mem_bottom += rlen;
|
||||
pd->dag_mem_bottom += rlen;
|
||||
|
||||
/* Count lost packets. */
|
||||
switch((header->type & 0x7f)) {
|
||||
@@ -333,10 +357,10 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
|
||||
default:
|
||||
if (header->lctr) {
|
||||
if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
|
||||
p->md.stat.ps_drop = UINT_MAX;
|
||||
if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
|
||||
pd->stat.ps_drop = UINT_MAX;
|
||||
} else {
|
||||
p->md.stat.ps_drop += ntohs(header->lctr);
|
||||
pd->stat.ps_drop += ntohs(header->lctr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,7 +468,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
case TYPE_COLOR_ETH:
|
||||
case TYPE_ETH:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
packet_len -= (pd->dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size - 2;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
@@ -457,7 +481,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
case TYPE_COLOR_HDLC_POS:
|
||||
case TYPE_HDLC_POS:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
packet_len -= (pd->dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
@@ -467,7 +491,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
case TYPE_COLOR_MC_HDLC_POS:
|
||||
case TYPE_MC_HDLC:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
packet_len -= (pd->dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size - 4;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
@@ -548,14 +572,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
pcap_header.len = packet_len;
|
||||
|
||||
/* Count the packet. */
|
||||
p->md.stat.ps_recv++;
|
||||
pd->stat.ps_recv++;
|
||||
|
||||
/* Call the user supplied callback function */
|
||||
callback(user, &pcap_header, dp);
|
||||
|
||||
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
|
||||
processed++;
|
||||
if (processed == cnt && cnt > 0)
|
||||
if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
|
||||
{
|
||||
/* Reached the user-specified limit. */
|
||||
return cnt;
|
||||
@@ -587,6 +611,7 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
|
||||
*/
|
||||
static int dag_activate(pcap_t* handle)
|
||||
{
|
||||
struct pcap_dag *handlep = handle->priv;
|
||||
#if 0
|
||||
char conf[30]; /* dag configure string */
|
||||
#endif
|
||||
@@ -616,13 +641,13 @@ static int dag_activate(pcap_t* handle)
|
||||
}
|
||||
|
||||
/* Parse input name to get dag device and stream number if provided */
|
||||
if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) {
|
||||
if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
device = newDev;
|
||||
|
||||
if (handle->md.dag_stream%2) {
|
||||
if (handlep->dag_stream%2) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
|
||||
goto fail;
|
||||
}
|
||||
@@ -647,7 +672,7 @@ static int dag_activate(pcap_t* handle)
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
/* Open requested stream. Can fail if already locked or on error */
|
||||
if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) {
|
||||
if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
|
||||
goto failclose;
|
||||
}
|
||||
@@ -655,32 +680,39 @@ static int dag_activate(pcap_t* handle)
|
||||
/* Set up default poll parameters for stream
|
||||
* Can be overridden by pcap_set_nonblock()
|
||||
*/
|
||||
if (dag_get_stream_poll(handle->fd, handle->md.dag_stream,
|
||||
if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
|
||||
&mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
|
||||
goto faildetach;
|
||||
}
|
||||
|
||||
/* Amount of data to collect in Bytes before calling callbacks.
|
||||
* Important for efficiency, but can introduce latency
|
||||
* at low packet rates if to_ms not set!
|
||||
*/
|
||||
mindata = 65536;
|
||||
if (handle->opt.immediate) {
|
||||
/* Call callback immediately.
|
||||
* XXX - is this the right way to handle this?
|
||||
*/
|
||||
mindata = 0;
|
||||
} else {
|
||||
/* Amount of data to collect in Bytes before calling callbacks.
|
||||
* Important for efficiency, but can introduce latency
|
||||
* at low packet rates if to_ms not set!
|
||||
*/
|
||||
mindata = 65536;
|
||||
}
|
||||
|
||||
/* Obey md.timeout (was to_ms) if supplied. This is a good idea!
|
||||
/* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
|
||||
* Recommend 10-100ms. Calls will time out even if no data arrived.
|
||||
*/
|
||||
maxwait.tv_sec = handle->md.timeout/1000;
|
||||
maxwait.tv_usec = (handle->md.timeout%1000) * 1000;
|
||||
maxwait.tv_sec = handle->opt.timeout/1000;
|
||||
maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
|
||||
|
||||
if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
|
||||
if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
|
||||
mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
|
||||
goto faildetach;
|
||||
}
|
||||
|
||||
#else
|
||||
if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
|
||||
if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
|
||||
goto failclose;
|
||||
}
|
||||
@@ -710,7 +742,7 @@ static int dag_activate(pcap_t* handle)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) {
|
||||
if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
|
||||
goto faildetach;
|
||||
}
|
||||
@@ -726,8 +758,8 @@ static int dag_activate(pcap_t* handle)
|
||||
* initialized to zero on startup, it won't give you
|
||||
* a compiler warning if you make this mistake!
|
||||
*/
|
||||
handle->md.dag_mem_bottom = 0;
|
||||
handle->md.dag_mem_top = 0;
|
||||
handlep->dag_mem_bottom = 0;
|
||||
handlep->dag_mem_top = 0;
|
||||
|
||||
/*
|
||||
* Find out how many FCS bits we should strip.
|
||||
@@ -736,7 +768,7 @@ static int dag_activate(pcap_t* handle)
|
||||
daginf = dag_info(handle->fd);
|
||||
if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) {
|
||||
/* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */
|
||||
handle->md.dag_fcs_bits = 0;
|
||||
handlep->dag_fcs_bits = 0;
|
||||
|
||||
/* Note that no FCS will be supplied. */
|
||||
handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
|
||||
@@ -744,12 +776,12 @@ static int dag_activate(pcap_t* handle)
|
||||
/*
|
||||
* Start out assuming it's 32 bits.
|
||||
*/
|
||||
handle->md.dag_fcs_bits = 32;
|
||||
handlep->dag_fcs_bits = 32;
|
||||
|
||||
/* Allow an environment variable to override. */
|
||||
if ((s = getenv("ERF_FCS_BITS")) != NULL) {
|
||||
if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
|
||||
handle->md.dag_fcs_bits = n;
|
||||
handlep->dag_fcs_bits = n;
|
||||
} else {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
|
||||
@@ -763,14 +795,14 @@ static int dag_activate(pcap_t* handle)
|
||||
if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
|
||||
/* Yes. Note the number of bytes that will be
|
||||
supplied. */
|
||||
handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16);
|
||||
handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16);
|
||||
|
||||
/* And don't strip them. */
|
||||
handle->md.dag_fcs_bits = 0;
|
||||
handlep->dag_fcs_bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
handle->md.dag_timeout = handle->md.timeout;
|
||||
handlep->dag_timeout = handle->opt.timeout;
|
||||
|
||||
handle->linktype = -1;
|
||||
if (dag_get_datalink(handle) < 0)
|
||||
@@ -801,19 +833,19 @@ static int dag_activate(pcap_t* handle)
|
||||
handle->setnonblock_op = dag_setnonblock;
|
||||
handle->stats_op = dag_stats;
|
||||
handle->cleanup_op = dag_platform_cleanup;
|
||||
handle->md.stat.ps_drop = 0;
|
||||
handle->md.stat.ps_recv = 0;
|
||||
handle->md.stat.ps_ifdrop = 0;
|
||||
handlep->stat.ps_drop = 0;
|
||||
handlep->stat.ps_recv = 0;
|
||||
handlep->stat.ps_ifdrop = 0;
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
failstop:
|
||||
if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) {
|
||||
if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) {
|
||||
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
faildetach:
|
||||
if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0)
|
||||
if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
|
||||
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
|
||||
#else
|
||||
failstop:
|
||||
@@ -835,11 +867,57 @@ fail:
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
pcap_t *dag_create(const char *device, char *ebuf)
|
||||
pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
char *cpend;
|
||||
long devnum;
|
||||
pcap_t *p;
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
long stream = 0;
|
||||
#endif
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like a DAG device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
/* Does it begin with "dag"? */
|
||||
if (strncmp(cp, "dag", 3) != 0) {
|
||||
/* Nope, doesn't begin with "dag" */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
|
||||
cp += 3;
|
||||
devnum = strtol(cp, &cpend, 10);
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
if (*cpend == ':') {
|
||||
/* Followed by a stream number. */
|
||||
stream = strtol(++cpend, &cpend, 10);
|
||||
}
|
||||
#endif
|
||||
if (cpend == cp || *cpend != '\0') {
|
||||
/* Not followed by a number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
|
||||
/* Followed by a non-valid number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
if (stream <0 || stream >= DAG_STREAM_MAX) {
|
||||
/* Followed by a non-valid stream number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -849,13 +927,15 @@ pcap_t *dag_create(const char *device, char *ebuf)
|
||||
|
||||
static int
|
||||
dag_stats(pcap_t *p, struct pcap_stat *ps) {
|
||||
struct pcap_dag *pd = p->priv;
|
||||
|
||||
/* This needs to be filled out correctly. Hopefully a dagapi call will
|
||||
provide all necessary information.
|
||||
*/
|
||||
/*p->md.stat.ps_recv = 0;*/
|
||||
/*p->md.stat.ps_drop = 0;*/
|
||||
/*pd->stat.ps_recv = 0;*/
|
||||
/*pd->stat.ps_drop = 0;*/
|
||||
|
||||
*ps = p->md.stat;
|
||||
*ps = pd->stat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -870,7 +950,7 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) {
|
||||
* open attempts will still be much less than the naive approach.
|
||||
*/
|
||||
int
|
||||
dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
|
||||
dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
|
||||
{
|
||||
char name[12]; /* XXX - pick a size */
|
||||
int ret = 0;
|
||||
@@ -879,8 +959,8 @@ dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
|
||||
int dagstream;
|
||||
int dagfd;
|
||||
|
||||
/* Try all the DAGs 0-31 */
|
||||
for (c = 0; c < 32; c++) {
|
||||
/* Try all the DAGs 0-DAG_MAX_BOARDS */
|
||||
for (c = 0; c < DAG_MAX_BOARDS; c++) {
|
||||
snprintf(name, 12, "dag%d", c);
|
||||
if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
|
||||
{
|
||||
@@ -945,8 +1025,6 @@ dag_setfilter(pcap_t *p, struct bpf_program *fp)
|
||||
if (install_bpf_program(p, fp) < 0)
|
||||
return -1;
|
||||
|
||||
p->md.use_bpf = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -961,11 +1039,13 @@ dag_set_datalink(pcap_t *p, int dlt)
|
||||
static int
|
||||
dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
struct pcap_dag *pd = p->priv;
|
||||
|
||||
/*
|
||||
* Set non-blocking mode on the FD.
|
||||
* XXX - is that necessary? If not, don't bother calling it,
|
||||
* and have a "dag_getnonblock()" function that looks at
|
||||
* "p->md.dag_offset_flags".
|
||||
* "pd->dag_offset_flags".
|
||||
*/
|
||||
if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
|
||||
return (-1);
|
||||
@@ -975,7 +1055,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
struct timeval maxwait;
|
||||
struct timeval poll;
|
||||
|
||||
if (dag_get_stream_poll(p->fd, p->md.dag_stream,
|
||||
if (dag_get_stream_poll(p->fd, pd->dag_stream,
|
||||
&mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
|
||||
return -1;
|
||||
@@ -990,7 +1070,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
else
|
||||
mindata = 65536;
|
||||
|
||||
if (dag_set_stream_poll(p->fd, p->md.dag_stream,
|
||||
if (dag_set_stream_poll(p->fd, pd->dag_stream,
|
||||
mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
|
||||
return -1;
|
||||
@@ -998,9 +1078,9 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
}
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
if (nonblock) {
|
||||
p->md.dag_offset_flags |= DAGF_NONBLOCK;
|
||||
pd->dag_offset_flags |= DAGF_NONBLOCK;
|
||||
} else {
|
||||
p->md.dag_offset_flags &= ~DAGF_NONBLOCK;
|
||||
pd->dag_offset_flags &= ~DAGF_NONBLOCK;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1008,6 +1088,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
static int
|
||||
dag_get_datalink(pcap_t *p)
|
||||
{
|
||||
struct pcap_dag *pd = p->priv;
|
||||
int index=0, dlt_index=0;
|
||||
uint8_t types[255];
|
||||
|
||||
@@ -1022,7 +1103,7 @@ dag_get_datalink(pcap_t *p)
|
||||
|
||||
#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
|
||||
/* Get list of possible ERF types for this card */
|
||||
if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) {
|
||||
if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
|
||||
snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.7 2008-04-04 19:37:45 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
pcap_t *dag_create(const char *, char *);
|
||||
int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
|
||||
pcap_t *dag_create(const char *, char *, int *);
|
||||
int dag_findalldevs(pcap_if_t **devlistp, char *errbuf);
|
||||
|
||||
#ifndef TYPE_AAL5
|
||||
#define TYPE_AAL5 4
|
||||
|
||||
279
libpcap/pcap-dbus.c
Normal file
279
libpcap/pcap-dbus.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Jakub Zawadzki
|
||||
* 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. The name of the author may not 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "pcap-dbus.h"
|
||||
|
||||
/*
|
||||
* Private data for capturing on D-Bus.
|
||||
*/
|
||||
struct pcap_dbus {
|
||||
DBusConnection *conn;
|
||||
u_int packets_read; /* count of packets read */
|
||||
};
|
||||
|
||||
static int
|
||||
dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_dbus *handlep = handle->priv;
|
||||
|
||||
struct pcap_pkthdr pkth;
|
||||
DBusMessage *message;
|
||||
|
||||
char *raw_msg;
|
||||
int raw_msg_len;
|
||||
|
||||
int count = 0;
|
||||
|
||||
message = dbus_connection_pop_message(handlep->conn);
|
||||
|
||||
while (!message) {
|
||||
// XXX handle->opt.timeout = timeout_ms;
|
||||
if (!dbus_connection_read_write(handlep->conn, 100)) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (handle->break_loop) {
|
||||
handle->break_loop = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
message = dbus_connection_pop_message(handlep->conn);
|
||||
}
|
||||
|
||||
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dbus_message_marshal(message, &raw_msg, &raw_msg_len)) {
|
||||
pkth.caplen = pkth.len = raw_msg_len;
|
||||
/* pkth.caplen = min (payload_len, handle->snapshot); */
|
||||
|
||||
gettimeofday(&pkth.ts, NULL);
|
||||
if (handle->fcode.bf_insns == NULL ||
|
||||
bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
|
||||
handlep->packets_read++;
|
||||
callback(user, &pkth, (u_char *)raw_msg);
|
||||
count++;
|
||||
}
|
||||
|
||||
dbus_free(raw_msg);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
dbus_write(pcap_t *handle, const void *buf, size_t size)
|
||||
{
|
||||
/* XXX, not tested */
|
||||
struct pcap_dbus *handlep = handle->priv;
|
||||
|
||||
DBusError error = DBUS_ERROR_INIT;
|
||||
DBusMessage *msg;
|
||||
|
||||
if (!(msg = dbus_message_demarshal(buf, size, &error))) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
|
||||
dbus_error_free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbus_connection_send(handlep->conn, msg, NULL);
|
||||
dbus_connection_flush(handlep->conn);
|
||||
|
||||
dbus_message_unref(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dbus_stats(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
struct pcap_dbus *handlep = handle->priv;
|
||||
|
||||
stats->ps_recv = handlep->packets_read;
|
||||
stats->ps_drop = 0;
|
||||
stats->ps_ifdrop = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_cleanup(pcap_t *handle)
|
||||
{
|
||||
struct pcap_dbus *handlep = handle->priv;
|
||||
|
||||
dbus_connection_unref(handlep->conn);
|
||||
|
||||
pcap_cleanup_live_common(handle);
|
||||
}
|
||||
|
||||
static int
|
||||
dbus_activate(pcap_t *handle)
|
||||
{
|
||||
#define EAVESDROPPING_RULE "eavesdrop=true,"
|
||||
|
||||
static const char *rules[] = {
|
||||
EAVESDROPPING_RULE "type='signal'",
|
||||
EAVESDROPPING_RULE "type='method_call'",
|
||||
EAVESDROPPING_RULE "type='method_return'",
|
||||
EAVESDROPPING_RULE "type='error'",
|
||||
};
|
||||
|
||||
#define N_RULES sizeof(rules)/sizeof(rules[0])
|
||||
|
||||
struct pcap_dbus *handlep = handle->priv;
|
||||
const char *dev = handle->opt.source;
|
||||
|
||||
DBusError error = DBUS_ERROR_INIT;
|
||||
int i;
|
||||
|
||||
if (strcmp(dev, "dbus-system") == 0) {
|
||||
if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
|
||||
dbus_error_free(&error);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
} else if (strcmp(dev, "dbus-session") == 0) {
|
||||
if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
|
||||
dbus_error_free(&error);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
} else if (strncmp(dev, "dbus://", 7) == 0) {
|
||||
const char *addr = dev + 7;
|
||||
|
||||
if (!(handlep->conn = dbus_connection_open(addr, &error))) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
|
||||
dbus_error_free(&error);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
if (!dbus_bus_register(handlep->conn, &error)) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
|
||||
dbus_error_free(&error);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.source);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize some components of the pcap structure. */
|
||||
handle->bufsize = 0;
|
||||
handle->offset = 0;
|
||||
handle->linktype = DLT_DBUS;
|
||||
handle->read_op = dbus_read;
|
||||
handle->inject_op = dbus_write;
|
||||
handle->setfilter_op = install_bpf_program; /* XXX, later add support for dbus_bus_add_match() */
|
||||
handle->setdirection_op = NULL;
|
||||
handle->set_datalink_op = NULL; /* can't change data link type */
|
||||
handle->getnonblock_op = pcap_getnonblock_fd;
|
||||
handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
handle->stats_op = dbus_stats;
|
||||
|
||||
handle->selectable_fd = handle->fd = -1;
|
||||
|
||||
if (handle->opt.rfmon) {
|
||||
/*
|
||||
* Monitor mode doesn't apply to dbus connections.
|
||||
*/
|
||||
dbus_cleanup(handle);
|
||||
return PCAP_ERROR_RFMON_NOTSUP;
|
||||
}
|
||||
|
||||
/* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */
|
||||
if (handle->opt.buffer_size != 0)
|
||||
dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size);
|
||||
|
||||
for (i = 0; i < N_RULES; i++) {
|
||||
dbus_bus_add_match(handlep->conn, rules[i], &error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
dbus_error_free(&error);
|
||||
|
||||
/* try without eavesdrop */
|
||||
dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
|
||||
dbus_error_free(&error);
|
||||
dbus_cleanup(handle);
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
dbus_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
if (strcmp(device, "dbus-system") &&
|
||||
strcmp(device, "dbus-session") &&
|
||||
strncmp(device, "dbus://", 7))
|
||||
{
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*is_ours = 1;
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->activate_op = dbus_activate;
|
||||
return (p);
|
||||
}
|
||||
|
||||
int
|
||||
dbus_findalldevs(pcap_if_t **alldevsp, char *err_str)
|
||||
{
|
||||
if (pcap_add_if(alldevsp, "dbus-system", 0, "D-Bus system bus", err_str) < 0)
|
||||
return -1;
|
||||
if (pcap_add_if(alldevsp, "dbus-session", 0, "D-Bus session bus", err_str) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
2
libpcap/pcap-dbus.h
Normal file
2
libpcap/pcap-dbus.h
Normal file
@@ -0,0 +1,2 @@
|
||||
pcap_t *dbus_create(const char *, char *, int *);
|
||||
int dbus_findalldevs(pcap_if_t **devlistp, char *errbuf);
|
||||
@@ -245,6 +245,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
static int
|
||||
pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
|
||||
{
|
||||
#ifdef DL_HP_RAWDLS
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
#if defined(DLIOCRAW)
|
||||
@@ -255,12 +258,12 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
|
||||
return (-1);
|
||||
}
|
||||
#elif defined(DL_HP_RAWDLS)
|
||||
if (p->send_fd < 0) {
|
||||
if (pd->send_fd < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"send: Output FD couldn't be opened");
|
||||
return (-1);
|
||||
}
|
||||
ret = dlrawdatareq(p->send_fd, buf, size);
|
||||
ret = dlrawdatareq(pd->send_fd, buf, size);
|
||||
if (ret == -1) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
|
||||
pcap_strerror(errno));
|
||||
@@ -321,16 +324,23 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
|
||||
static void
|
||||
pcap_cleanup_dlpi(pcap_t *p)
|
||||
{
|
||||
if (p->send_fd >= 0) {
|
||||
close(p->send_fd);
|
||||
p->send_fd = -1;
|
||||
#ifdef DL_HP_RAWDLS
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
|
||||
if (pd->send_fd >= 0) {
|
||||
close(pd->send_fd);
|
||||
pd->send_fd = -1;
|
||||
}
|
||||
#endif
|
||||
pcap_cleanup_live_common(p);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_activate_dlpi(pcap_t *p)
|
||||
{
|
||||
#ifdef DL_HP_RAWDLS
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
#endif
|
||||
register char *cp;
|
||||
int ppa;
|
||||
#ifdef HAVE_SOLARIS
|
||||
@@ -398,13 +408,13 @@ pcap_activate_dlpi(pcap_t *p)
|
||||
* receiving packets on the same descriptor - you need separate
|
||||
* descriptors for sending and receiving, bound to different SAPs.
|
||||
*
|
||||
* If the open fails, we just leave -1 in "p->send_fd" and reject
|
||||
* If the open fails, we just leave -1 in "pd->send_fd" and reject
|
||||
* attempts to send packets, just as if, in pcap-bpf.c, we fail
|
||||
* to open the BPF device for reading and writing, we just try
|
||||
* to open it for reading only and, if that succeeds, just let
|
||||
* the send attempts fail.
|
||||
*/
|
||||
p->send_fd = open(cp, O_RDWR);
|
||||
pd->send_fd = open(cp, O_RDWR);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -513,8 +523,8 @@ pcap_activate_dlpi(pcap_t *p)
|
||||
if (status < 0)
|
||||
goto bad;
|
||||
#ifdef DL_HP_RAWDLS
|
||||
if (p->send_fd >= 0) {
|
||||
if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0)
|
||||
if (pd->send_fd >= 0) {
|
||||
if (dl_doattach(pd->send_fd, ppa, p->errbuf) < 0)
|
||||
goto bad;
|
||||
}
|
||||
#endif
|
||||
@@ -570,13 +580,13 @@ pcap_activate_dlpi(pcap_t *p)
|
||||
*/
|
||||
if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
|
||||
goto bad;
|
||||
if (p->send_fd >= 0) {
|
||||
if (pd->send_fd >= 0) {
|
||||
/*
|
||||
** XXX - if this fails, just close send_fd and
|
||||
** set it to -1, so that you can't send but can
|
||||
** still receive?
|
||||
*/
|
||||
if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
|
||||
if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
|
||||
goto bad;
|
||||
}
|
||||
#else /* neither AIX nor HP-UX */
|
||||
@@ -669,13 +679,13 @@ pcap_activate_dlpi(pcap_t *p)
|
||||
** binding it anyway, just to keep the HP-UX 9/10.20 or later
|
||||
** code together.
|
||||
*/
|
||||
if (p->send_fd >= 0) {
|
||||
if (pd->send_fd >= 0) {
|
||||
/*
|
||||
** XXX - if this fails, just close send_fd and
|
||||
** set it to -1, so that you can't send but can
|
||||
** still receive?
|
||||
*/
|
||||
if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
|
||||
if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
|
||||
goto bad;
|
||||
}
|
||||
#endif
|
||||
@@ -729,7 +739,7 @@ pcap_activate_dlpi(pcap_t *p)
|
||||
#endif
|
||||
|
||||
/* Push and configure bufmod. */
|
||||
if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0)
|
||||
if (pcap_conf_bufmod(p, ss) != 0)
|
||||
goto bad;
|
||||
#endif
|
||||
|
||||
@@ -1693,15 +1703,21 @@ dlpi_kread(register int fd, register off_t addr,
|
||||
#endif
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
#ifdef DL_HP_RAWDLS
|
||||
struct pcap_dlpi *pd;
|
||||
#endif
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->send_fd = -1; /* it hasn't been opened yet */
|
||||
#ifdef DL_HP_RAWDLS
|
||||
pd = p->priv;
|
||||
pd->send_fd = -1; /* it hasn't been opened yet */
|
||||
#endif
|
||||
|
||||
p->activate_op = pcap_activate_dlpi;
|
||||
return (p);
|
||||
|
||||
@@ -143,11 +143,19 @@ static struct device *get_device (int fd)
|
||||
return handle_to_device [fd-1];
|
||||
}
|
||||
|
||||
pcap_t *pcap_create (const char *device, char *ebuf)
|
||||
/*
|
||||
* Private data for capturing on MS-DOS.
|
||||
*/
|
||||
struct pcap_dos {
|
||||
void (*wait_proc)(void); /* call proc while waiting */
|
||||
struct pcap_stat stat;
|
||||
};
|
||||
|
||||
pcap_t *pcap_create_interface (const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -161,6 +169,8 @@ pcap_t *pcap_create (const char *device, char *ebuf)
|
||||
*/
|
||||
static int pcap_activate_dos (pcap_t *pcap)
|
||||
{
|
||||
struct pcap_dos *pcapd = pcap->priv;
|
||||
|
||||
if (pcap->opt.rfmon) {
|
||||
/*
|
||||
* No monitor mode on DOS.
|
||||
@@ -210,15 +220,16 @@ static int pcap_activate_dos (pcap_t *pcap)
|
||||
static int
|
||||
pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
|
||||
{
|
||||
struct pcap_dos *pd = p->priv;
|
||||
struct pcap_pkthdr pcap;
|
||||
struct timeval now, expiry;
|
||||
struct timeval now, expiry = { 0,0 };
|
||||
BYTE *rx_buf;
|
||||
int rx_len = 0;
|
||||
|
||||
if (p->md.timeout > 0)
|
||||
if (p->opt.timeout > 0)
|
||||
{
|
||||
gettimeofday2 (&now, NULL);
|
||||
expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout;
|
||||
expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
|
||||
expiry.tv_sec = now.tv_sec;
|
||||
while (expiry.tv_usec >= 1000000L)
|
||||
{
|
||||
@@ -287,10 +298,10 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* If not to wait for a packet or pcap_close() called from
|
||||
/* If not to wait for a packet or pcap_cleanup_dos() called from
|
||||
* e.g. SIGINT handler, exit loop now.
|
||||
*/
|
||||
if (p->md.timeout <= 0 || (volatile int)p->fd <= 0)
|
||||
if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
|
||||
break;
|
||||
|
||||
gettimeofday2 (&now, NULL);
|
||||
@@ -308,7 +319,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
|
||||
|
||||
if (rx_len < 0) /* receive error */
|
||||
{
|
||||
p->md.stat.ps_drop++;
|
||||
pd->stat.ps_drop++;
|
||||
#ifdef USE_32BIT_DRIVERS
|
||||
if (pcap_pkt_debug > 1)
|
||||
printk ("pkt-err %s\n", pktInfo.error);
|
||||
@@ -321,9 +332,10 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
|
||||
static int
|
||||
pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
|
||||
{
|
||||
struct pcap_dos *pd = p->priv;
|
||||
int rc, num = 0;
|
||||
|
||||
while (num <= cnt || (cnt < 0))
|
||||
while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
|
||||
{
|
||||
if (p->fd <= 0)
|
||||
return (-1);
|
||||
@@ -343,6 +355,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
|
||||
static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct net_device_stats *stats;
|
||||
struct pcap_dos *pd;
|
||||
struct device *dev = p ? get_device(p->fd) : NULL;
|
||||
|
||||
if (!dev)
|
||||
@@ -359,12 +372,13 @@ static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
|
||||
|
||||
FLUSHK();
|
||||
|
||||
p->md.stat.ps_recv = stats->rx_packets;
|
||||
p->md.stat.ps_drop += stats->rx_missed_errors;
|
||||
p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */
|
||||
pd = p->priv;
|
||||
pd->stat.ps_recv = stats->rx_packets;
|
||||
pd->stat.ps_drop += stats->rx_missed_errors;
|
||||
pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
|
||||
stats->rx_errors; /* HW errors */
|
||||
if (ps)
|
||||
*ps = p->md.stat;
|
||||
*ps = pd->stat;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -428,10 +442,13 @@ u_long pcap_filter_packets (void)
|
||||
*/
|
||||
static void pcap_cleanup_dos (pcap_t *p)
|
||||
{
|
||||
struct pcap_dos *pd;
|
||||
|
||||
if (p && !exc_occured)
|
||||
{
|
||||
pd = p->priv;
|
||||
if (pcap_stats(p,NULL) < 0)
|
||||
p->md.stat.ps_drop = 0;
|
||||
pd->stat.ps_drop = 0;
|
||||
if (!get_device(p->fd))
|
||||
return;
|
||||
|
||||
@@ -590,10 +607,12 @@ void pcap_assert (const char *what, const char *file, unsigned line)
|
||||
*/
|
||||
void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
|
||||
{
|
||||
struct pcap_dos *pd;
|
||||
if (p)
|
||||
{
|
||||
p->wait_proc = yield;
|
||||
p->md.timeout = wait;
|
||||
pd = p->priv;
|
||||
pd->wait_proc = yield;
|
||||
p->opt.timeout = wait;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ Primitives usually consist of an
|
||||
There are three
|
||||
different kinds of qualifier:
|
||||
.IP \fItype\fP
|
||||
.I type
|
||||
qualifiers say what kind of thing the id name or number refers to.
|
||||
Possible types are
|
||||
.BR host ,
|
||||
@@ -58,6 +59,7 @@ qualifier,
|
||||
.B host
|
||||
is assumed.
|
||||
.IP \fIdir\fP
|
||||
.I dir
|
||||
qualifiers specify a particular transfer direction to and/or from
|
||||
.IR id .
|
||||
Possible directions are
|
||||
@@ -93,6 +95,7 @@ and
|
||||
.B outbound
|
||||
qualifiers can be used to specify a desired direction.
|
||||
.IP \fIproto\fP
|
||||
.I proto
|
||||
qualifiers restrict the match to a particular protocol.
|
||||
Possible
|
||||
protos are:
|
||||
@@ -159,7 +162,7 @@ True if the IPv4/v6 destination field of the packet is \fIhost\fP,
|
||||
which may be either an address or a name.
|
||||
.IP "\fBsrc host \fIhost\fR"
|
||||
True if the IPv4/v6 source field of the packet is \fIhost\fP.
|
||||
.IP "\fBhost \fIhost\fP
|
||||
.IP "\fBhost \fIhost\fP"
|
||||
True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
|
||||
.IP
|
||||
Any of the above host expressions can be prepended with the keywords,
|
||||
@@ -177,17 +180,17 @@ which is equivalent to:
|
||||
.in -.5i
|
||||
If \fIhost\fR is a name with multiple IP addresses, each address will
|
||||
be checked for a match.
|
||||
.IP "\fBether dst \fIehost\fP
|
||||
.IP "\fBether dst \fIehost\fP"
|
||||
True if the Ethernet destination address is \fIehost\fP.
|
||||
\fIEhost\fP
|
||||
may be either a name from /etc/ethers or a number (see
|
||||
.IR ethers (3N)
|
||||
for numeric format).
|
||||
.IP "\fBether src \fIehost\fP
|
||||
.IP "\fBether src \fIehost\fP"
|
||||
True if the Ethernet source address is \fIehost\fP.
|
||||
.IP "\fBether host \fIehost\fP
|
||||
.IP "\fBether host \fIehost\fP"
|
||||
True if either the Ethernet source or destination address is \fIehost\fP.
|
||||
.IP "\fBgateway\fP \fIhost\fP
|
||||
.IP "\fBgateway\fP \fIhost\fP"
|
||||
True if the packet used \fIhost\fP as a gateway.
|
||||
I.e., the Ethernet
|
||||
source or destination address was \fIhost\fP but neither the IP source
|
||||
@@ -302,6 +305,18 @@ Note that this primitive does not chase the protocol header chain.
|
||||
.IP "\fBip6 proto \fIprotocol\fR"
|
||||
True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
|
||||
Note that this primitive does not chase the protocol header chain.
|
||||
.IP "\fBproto \fIprotocol\fR"
|
||||
True if the packet is an IPv4 or IPv6 packet of protocol type
|
||||
\fIprotocol\fP. Note that this primitive does not chase the protocol
|
||||
header chain.
|
||||
.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBproto \fIp\fR\fB
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
.IP "\fBip6 protochain \fIprotocol\fR"
|
||||
True if the packet is IPv6 packet,
|
||||
and contains protocol header with type \fIprotocol\fR
|
||||
@@ -321,6 +336,10 @@ cannot be optimized by the BPF optimizer code, so this can be somewhat
|
||||
slow.
|
||||
.IP "\fBip protochain \fIprotocol\fR"
|
||||
Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
|
||||
.IP "\fBprotochain \fIprotocol\fR"
|
||||
True if the packet is an IPv4 or IPv6 packet of protocol type
|
||||
\fIprotocol\fP. Note that this primitive chases the protocol
|
||||
header chain.
|
||||
.IP "\fBether broadcast\fR"
|
||||
True if the packet is an Ethernet broadcast packet.
|
||||
The \fIether\fP
|
||||
@@ -402,6 +421,25 @@ the filter checks for the IPX etype in an Ethernet frame, the IPX
|
||||
DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
|
||||
IPX, and the IPX etype in a SNAP frame.
|
||||
.RE
|
||||
.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBether proto \fIp\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBether proto \fIp\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
Note that not all applications using
|
||||
.BR pcap (3PCAP)
|
||||
currently know how to parse these protocols.
|
||||
.IP "\fBdecnet src \fIhost\fR"
|
||||
True if the DECNET source address is
|
||||
.IR host ,
|
||||
@@ -503,25 +541,6 @@ True if the fourth IEEE 802.11 address, if present, is
|
||||
.IR ehost .
|
||||
The fourth address field is only used for
|
||||
WDS (Wireless Distribution System) frames.
|
||||
.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBether proto \fIp\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBether proto \fIp\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
Note that not all applications using
|
||||
.BR pcap (3)
|
||||
currently know how to parse these protocols.
|
||||
.IP "\fBtype \fIwlan_type\fR"
|
||||
True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
|
||||
Valid \fIwlan_type\fRs are:
|
||||
@@ -638,9 +657,11 @@ any outer label.
|
||||
.IP \fBpppoed\fP
|
||||
True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
|
||||
type 0x8863).
|
||||
.IP \fBpppoes\fP
|
||||
.IP "\fBpppoes \fI[session_id]\fR"
|
||||
True if the packet is a PPP-over-Ethernet Session packet (Ethernet
|
||||
type 0x8864).
|
||||
If \fI[session_id]\fR is specified, only true if the packet has the specified
|
||||
\fIsession_id\fR.
|
||||
Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
|
||||
changes the decoding offsets for the remainder of \fIexpression\fR on
|
||||
the assumption that the packet is a PPPoE session packet.
|
||||
@@ -648,18 +669,10 @@ the assumption that the packet is a PPPoE session packet.
|
||||
For example:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBpppoes && ip\fR
|
||||
\fBpppoes 0x27 && ip\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
filters IPv4 protocols encapsulated in PPPoE.
|
||||
.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
|
||||
Abbreviations for:
|
||||
.in +.5i
|
||||
.nf
|
||||
\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR
|
||||
.fi
|
||||
.in -.5i
|
||||
where \fIp\fR is one of the above protocols.
|
||||
filters IPv4 protocols encapsulated in PPPoE session id 0x27.
|
||||
.IP "\fBiso proto \fIprotocol\fR"
|
||||
True if the packet is an OSI packet of protocol type \fIprotocol\fP.
|
||||
\fIProtocol\fP can be a number or one of the names
|
||||
@@ -674,11 +687,11 @@ Abbreviations for:
|
||||
where \fIp\fR is one of the above protocols.
|
||||
.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
|
||||
Abbreviations for IS-IS PDU types.
|
||||
.IP "\fBvpi\fP \fIn\fR
|
||||
.IP "\fBvpi\fP \fIn\fR"
|
||||
True if the packet is an ATM packet, for SunATM on Solaris, with a
|
||||
virtual path identifier of
|
||||
.IR n .
|
||||
.IP "\fBvci\fP \fIn\fR
|
||||
.IP "\fBvci\fP \fIn\fR"
|
||||
True if the packet is an ATM packet, for SunATM on Solaris, with a
|
||||
virtual channel identifier of
|
||||
.IR n .
|
||||
@@ -918,27 +931,6 @@ icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
|
||||
.RE
|
||||
.SH "SEE ALSO"
|
||||
pcap(3PCAP)
|
||||
.SH AUTHORS
|
||||
The original authors are:
|
||||
.LP
|
||||
Van Jacobson,
|
||||
Craig Leres and
|
||||
Steven McCanne, all of the
|
||||
Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
|
||||
.LP
|
||||
It is currently being maintained by tcpdump.org.
|
||||
.LP
|
||||
The current version of libpcap is available via http:
|
||||
.LP
|
||||
.RS
|
||||
.I http://www.tcpdump.org/
|
||||
.RE
|
||||
.LP
|
||||
The original distribution is available via anonymous ftp:
|
||||
.LP
|
||||
.RS
|
||||
.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z
|
||||
.RE
|
||||
.SH BUGS
|
||||
Please send problems, bugs, questions, desirable enhancements, etc. to:
|
||||
.LP
|
||||
|
||||
@@ -42,10 +42,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDLPI
|
||||
#include <libdlpi.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Packet32.h>
|
||||
extern CRITICAL_SECTION g_PcapCompileCriticalSection;
|
||||
@@ -56,10 +52,6 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection;
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SNF_API
|
||||
#include <snf.h>
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
|
||||
|
||||
/*
|
||||
@@ -92,139 +84,17 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection;
|
||||
|
||||
#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 (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
|
||||
int swapped;
|
||||
size_t hdrsize;
|
||||
swapped_type_t lengths_swapped;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
|
||||
u_int tsresol; /* time stamp resolution */
|
||||
u_int tsscale; /* scaling factor for resolution -> microseconds */
|
||||
u_int64_t tsoffset; /* time stamp offset */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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_do_on_close; /* stuff we must do 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 */
|
||||
char *mondevice; /* mac80211 monitor device we created */
|
||||
u_char *mmapbuf; /* memory-mapped region pointer */
|
||||
size_t mmapbuflen; /* size of region */
|
||||
u_int tp_version; /* version of tpacket_hdr for mmaped ring */
|
||||
u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
|
||||
u_char *oneshot_buffer; /* buffer for copy of packet */
|
||||
long proc_dropped; /* packets reported dropped by /proc/net/dev */
|
||||
#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_SNF_API
|
||||
snf_handle_t snf_handle; /* opaque device handle */
|
||||
snf_ring_t snf_ring; /* opaque device ring handle */
|
||||
int snf_timeout;
|
||||
int snf_boardnum;
|
||||
#endif /*HAVE_SNF_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 do when we close.
|
||||
*/
|
||||
#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */
|
||||
#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */
|
||||
#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */
|
||||
|
||||
struct pcap_opt {
|
||||
int buffer_size;
|
||||
char *source;
|
||||
int timeout; /* timeout for buffering */
|
||||
int buffer_size;
|
||||
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 <sys/param.h> /* 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 *);
|
||||
@@ -239,10 +109,25 @@ typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
|
||||
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 Adapter *(*getadapter_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 {
|
||||
/*
|
||||
* Method to call to read packets on a live capture.
|
||||
*/
|
||||
read_op_t read_op;
|
||||
|
||||
/*
|
||||
* Method to call to read to read packets from a savefile.
|
||||
*/
|
||||
int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
|
||||
|
||||
#ifdef WIN32
|
||||
ADAPTER *adapter;
|
||||
LPPACKET Packet;
|
||||
@@ -250,34 +135,8 @@ struct pcap {
|
||||
#else
|
||||
int fd;
|
||||
int selectable_fd;
|
||||
int send_fd;
|
||||
#endif /* WIN32 */
|
||||
|
||||
#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 */
|
||||
int tzoff; /* timezone offset */
|
||||
int offset; /* offset for proper alignment */
|
||||
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 */
|
||||
|
||||
#ifdef PCAP_FDDIPAD
|
||||
int fddipad;
|
||||
#endif
|
||||
|
||||
#ifdef MSDOS
|
||||
void (*wait_proc)(void); /* call proc while waiting */
|
||||
#endif
|
||||
|
||||
struct pcap_sf sf;
|
||||
struct pcap_md md;
|
||||
struct pcap_opt opt;
|
||||
|
||||
/*
|
||||
* Read buffer.
|
||||
*/
|
||||
@@ -286,6 +145,34 @@ struct pcap {
|
||||
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;
|
||||
|
||||
int snapshot;
|
||||
int linktype; /* Network linktype */
|
||||
int linktype_ext; /* Extended information stored in the linktype field of a file */
|
||||
int tzoff; /* timezone offset */
|
||||
int offset; /* offset for proper alignment */
|
||||
int activated; /* true if the capture is really started */
|
||||
int oldstyle; /* if we're opening with pcap_open_live() */
|
||||
|
||||
struct pcap_opt opt;
|
||||
|
||||
/*
|
||||
* Place holder for pcap_next().
|
||||
*/
|
||||
@@ -295,11 +182,25 @@ struct pcap {
|
||||
pcap_direction_t direction;
|
||||
|
||||
/*
|
||||
* Methods.
|
||||
* 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;
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@@ -321,21 +222,9 @@ struct pcap {
|
||||
setbuff_op_t setbuff_op;
|
||||
setmode_op_t setmode_op;
|
||||
setmintocopy_op_t setmintocopy_op;
|
||||
getadapter_op_t getadapter_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;
|
||||
int tstamp_type_count;
|
||||
u_int *tstamp_type_list;
|
||||
|
||||
struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -374,12 +263,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 {
|
||||
@@ -446,6 +336,12 @@ extern int snprintf (char *, size_t, const char *, ...);
|
||||
extern int 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.
|
||||
*/
|
||||
@@ -454,7 +350,19 @@ 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(const char *, 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 *);
|
||||
@@ -465,12 +373,16 @@ 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..
|
||||
* "pcap_findalldevs_interfaces()" finds interfaces using the
|
||||
* "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
|
||||
*
|
||||
* "pcap_add_if()" adds an interface to the list of interfaces.
|
||||
* "pcap_platform_finddevs()" is a platform-dependent routine to
|
||||
* add devices not found by the "standard" mechanisms.
|
||||
*
|
||||
* "pcap_add_if()" adds an interface to the list of interfaces, for
|
||||
* use by various "find interfaces" routines.
|
||||
*/
|
||||
int pcap_findalldevs_interfaces(pcap_if_t **, char *);
|
||||
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,
|
||||
@@ -480,6 +392,28 @@ struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
|
||||
int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
|
||||
const char *, char *);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
#endif
|
||||
|
||||
@@ -52,7 +52,6 @@ static const char rcsid[] _U_ =
|
||||
static int dlpromiscon(pcap_t *, bpf_u_int32);
|
||||
static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
|
||||
static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
|
||||
static void pcap_close_libdlpi(pcap_t *);
|
||||
static void pcap_libdlpi_err(const char *, const char *, int, char *);
|
||||
static void pcap_cleanup_libdlpi(pcap_t *);
|
||||
|
||||
@@ -101,6 +100,7 @@ list_interfaces(const char *linkname, void *arg)
|
||||
static int
|
||||
pcap_activate_libdlpi(pcap_t *p)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
int retv;
|
||||
dlpi_handle_t dh;
|
||||
dlpi_info_t dlinfo;
|
||||
@@ -122,7 +122,7 @@ pcap_activate_libdlpi(pcap_t *p)
|
||||
p->errbuf);
|
||||
return (err);
|
||||
}
|
||||
p->dlpi_hd = dh;
|
||||
pd->dlpi_hd = dh;
|
||||
|
||||
if (p->opt.rfmon) {
|
||||
/*
|
||||
@@ -134,7 +134,7 @@ pcap_activate_libdlpi(pcap_t *p)
|
||||
}
|
||||
|
||||
/* Bind with DLPI_ANY_SAP. */
|
||||
if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
|
||||
if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
|
||||
goto bad;
|
||||
}
|
||||
@@ -181,7 +181,7 @@ pcap_activate_libdlpi(pcap_t *p)
|
||||
}
|
||||
|
||||
/* Determine link type. */
|
||||
if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
|
||||
if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
|
||||
goto bad;
|
||||
}
|
||||
@@ -189,10 +189,10 @@ pcap_activate_libdlpi(pcap_t *p)
|
||||
if (pcap_process_mactype(p, dlinfo.di_mactype) != 0)
|
||||
goto bad;
|
||||
|
||||
p->fd = dlpi_fd(p->dlpi_hd);
|
||||
p->fd = dlpi_fd(pd->dlpi_hd);
|
||||
|
||||
/* Push and configure bufmod. */
|
||||
if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0)
|
||||
if (pcap_conf_bufmod(p, p->snapshot) != 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
@@ -235,9 +235,11 @@ bad:
|
||||
static int
|
||||
dlpromiscon(pcap_t *p, bpf_u_int32 level)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
int retv;
|
||||
int err;
|
||||
|
||||
retv = dlpi_promiscon(p->hd, level);
|
||||
retv = dlpi_promiscon(pd->dlpi_hd, level);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
if (retv == DL_SYSERR &&
|
||||
(errno == EPERM || errno == EACCES))
|
||||
@@ -299,6 +301,7 @@ done:
|
||||
static int
|
||||
pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
int len;
|
||||
u_char *bufp;
|
||||
size_t msglen;
|
||||
@@ -324,7 +327,7 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
|
||||
msglen = p->bufsize;
|
||||
bufp = p->buffer + p->offset;
|
||||
|
||||
retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp,
|
||||
retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
|
||||
&msglen, -1, NULL);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
/*
|
||||
@@ -336,7 +339,7 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
|
||||
len = 0;
|
||||
continue;
|
||||
}
|
||||
pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd),
|
||||
pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd),
|
||||
"dlpi_recv", retv, p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
@@ -350,11 +353,12 @@ process_pkts:
|
||||
static int
|
||||
pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
|
||||
{
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
int retv;
|
||||
|
||||
retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL);
|
||||
retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv,
|
||||
pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv,
|
||||
p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
@@ -372,9 +376,11 @@ pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
|
||||
static void
|
||||
pcap_cleanup_libdlpi(pcap_t *p)
|
||||
{
|
||||
if (p->dlpi_hd != NULL) {
|
||||
dlpi_close(p->dlpi_hd);
|
||||
p->dlpi_hd = NULL;
|
||||
struct pcap_dlpi *pd = p->priv;
|
||||
|
||||
if (pd->dlpi_hd != NULL) {
|
||||
dlpi_close(pd->dlpi_hd);
|
||||
pd->dlpi_hd = NULL;
|
||||
p->fd = -1;
|
||||
}
|
||||
pcap_cleanup_live_common(p);
|
||||
@@ -391,11 +397,11 @@ pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
||||
1883
libpcap/pcap-linux.c
1883
libpcap/pcap-linux.c
File diff suppressed because it is too large
Load Diff
@@ -51,18 +51,42 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_log.h>
|
||||
#include <linux/netfilter/nfnetlink_queue.h>
|
||||
|
||||
/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue.
|
||||
* It took me quite some time to debug ;/
|
||||
*
|
||||
* Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages,
|
||||
* and in nfqueue we need to send verdict reply after recving packet.
|
||||
*
|
||||
* In tcpdump you can disable dropping privilages with -Z root
|
||||
*/
|
||||
|
||||
#include "pcap-netfilter-linux.h"
|
||||
|
||||
#define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
|
||||
|
||||
#define NFLOG_IFACE "nflog"
|
||||
#define NFQUEUE_IFACE "nfqueue"
|
||||
|
||||
typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t;
|
||||
|
||||
/*
|
||||
* Private data for capturing on Linux netfilter sockets.
|
||||
*/
|
||||
struct pcap_netfilter {
|
||||
u_int packets_read; /* count of packets read with recvfrom() */
|
||||
};
|
||||
|
||||
static int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict);
|
||||
|
||||
static int
|
||||
nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_netfilter *handlep = handle->priv;
|
||||
const unsigned char *buf;
|
||||
int count = 0;
|
||||
int len;
|
||||
@@ -85,6 +109,7 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char
|
||||
while (len >= NLMSG_SPACE(0)) {
|
||||
const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
|
||||
u_int32_t msg_len;
|
||||
nftype_t type = OTHER;
|
||||
|
||||
if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
|
||||
@@ -93,10 +118,19 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char
|
||||
|
||||
if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
|
||||
NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
|
||||
{
|
||||
type = NFLOG;
|
||||
|
||||
if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
|
||||
NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
|
||||
type = NFQUEUE;
|
||||
|
||||
if (type != OTHER) {
|
||||
const unsigned char *payload = NULL;
|
||||
struct pcap_pkthdr pkth;
|
||||
|
||||
const struct nfgenmsg *nfg;
|
||||
int id = 0;
|
||||
|
||||
if (handle->linktype != DLT_NFLOG) {
|
||||
const struct nfattr *payload_attr = NULL;
|
||||
|
||||
@@ -105,15 +139,32 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char
|
||||
return -1;
|
||||
}
|
||||
|
||||
nfg = NLMSG_DATA(nlh);
|
||||
if (nlh->nlmsg_len > HDR_LENGTH) {
|
||||
struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
|
||||
struct nfattr *attr = NFM_NFA(nfg);
|
||||
int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);
|
||||
|
||||
while (NFA_OK(attr, attr_len)) {
|
||||
switch (NFA_TYPE(attr)) {
|
||||
case NFULA_PAYLOAD:
|
||||
payload_attr = attr;
|
||||
break;
|
||||
if (type == NFQUEUE) {
|
||||
switch (NFA_TYPE(attr)) {
|
||||
case NFQA_PACKET_HDR:
|
||||
{
|
||||
const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr);
|
||||
|
||||
id = ntohl(pkt_hdr->packet_id);
|
||||
break;
|
||||
}
|
||||
case NFQA_PAYLOAD:
|
||||
payload_attr = attr;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (type == NFLOG) {
|
||||
switch (NFA_TYPE(attr)) {
|
||||
case NFULA_PAYLOAD:
|
||||
payload_attr = attr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
attr = NFA_NEXT(attr, attr_len);
|
||||
}
|
||||
@@ -136,11 +187,16 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char
|
||||
if (handle->fcode.bf_insns == NULL ||
|
||||
bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
|
||||
{
|
||||
handle->md.packets_read++;
|
||||
handlep->packets_read++;
|
||||
callback(user, &pkth, payload);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == NFQUEUE) {
|
||||
/* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
|
||||
nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
|
||||
}
|
||||
}
|
||||
|
||||
msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
@@ -163,7 +219,9 @@ netfilter_set_datalink(pcap_t *handle, int dlt)
|
||||
static int
|
||||
netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
stats->ps_recv = handle->md.packets_read;
|
||||
struct pcap_netfilter *handlep = handle->priv;
|
||||
|
||||
stats->ps_recv = handlep->packets_read;
|
||||
stats->ps_drop = 0;
|
||||
stats->ps_ifdrop = 0;
|
||||
return 0;
|
||||
@@ -183,7 +241,7 @@ struct my_nfattr {
|
||||
};
|
||||
|
||||
static int
|
||||
nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
|
||||
netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
|
||||
{
|
||||
char buf[1024] __attribute__ ((aligned));
|
||||
|
||||
@@ -198,8 +256,8 @@ nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, c
|
||||
++seq_id;
|
||||
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
|
||||
nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_type = msg_type;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | (ack ? NLM_F_ACK : 0);
|
||||
nlh->nlmsg_pid = 0; /* to kernel */
|
||||
nlh->nlmsg_seq = seq_id;
|
||||
|
||||
@@ -222,6 +280,9 @@ nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, c
|
||||
if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1)
|
||||
return -1;
|
||||
|
||||
if (!ack)
|
||||
return 0;
|
||||
|
||||
/* waiting for reply loop */
|
||||
do {
|
||||
socklen_t addrlen = sizeof(snl);
|
||||
@@ -260,6 +321,12 @@ nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, c
|
||||
return -1; /* never here */
|
||||
}
|
||||
|
||||
static int
|
||||
nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
|
||||
{
|
||||
return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa);
|
||||
}
|
||||
|
||||
static int
|
||||
nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int8_t family)
|
||||
{
|
||||
@@ -292,20 +359,79 @@ nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_m
|
||||
}
|
||||
|
||||
static int
|
||||
nflog_activate(pcap_t* handle)
|
||||
nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict)
|
||||
{
|
||||
struct nfqnl_msg_verdict_hdr msg;
|
||||
struct my_nfattr nfa;
|
||||
|
||||
msg.id = htonl(id);
|
||||
msg.verdict = htonl(verdict);
|
||||
|
||||
nfa.data = &msg;
|
||||
nfa.nfa_type = NFQA_VERDICT_HDR;
|
||||
nfa.nfa_len = sizeof(msg);
|
||||
|
||||
return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT, 0, AF_UNSPEC, group_id, &nfa);
|
||||
}
|
||||
|
||||
static int
|
||||
nfqueue_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
|
||||
{
|
||||
return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa);
|
||||
}
|
||||
|
||||
static int
|
||||
nfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int16_t pf)
|
||||
{
|
||||
struct nfqnl_msg_config_cmd msg;
|
||||
struct my_nfattr nfa;
|
||||
|
||||
msg.command = cmd;
|
||||
msg.pf = htons(pf);
|
||||
|
||||
nfa.data = &msg;
|
||||
nfa.nfa_type = NFQA_CFG_CMD;
|
||||
nfa.nfa_len = sizeof(msg);
|
||||
|
||||
return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
|
||||
}
|
||||
|
||||
static int
|
||||
nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
|
||||
{
|
||||
struct nfqnl_msg_config_params msg;
|
||||
struct my_nfattr nfa;
|
||||
|
||||
msg.copy_range = htonl(copy_range);
|
||||
msg.copy_mode = copy_mode;
|
||||
|
||||
nfa.data = &msg;
|
||||
nfa.nfa_type = NFQA_CFG_PARAMS;
|
||||
nfa.nfa_len = sizeof(msg);
|
||||
|
||||
return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
|
||||
}
|
||||
|
||||
static int
|
||||
netfilter_activate(pcap_t* handle)
|
||||
{
|
||||
const char *dev = handle->opt.source;
|
||||
unsigned short groups[32];
|
||||
int group_count = 0;
|
||||
nftype_t type = OTHER;
|
||||
int i;
|
||||
|
||||
if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) {
|
||||
dev += strlen(NFLOG_IFACE);
|
||||
|
||||
/* nflog:30,33,42 looks nice, allow it */
|
||||
if (*dev == ':')
|
||||
dev++;
|
||||
if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) {
|
||||
dev += strlen(NFLOG_IFACE);
|
||||
type = NFLOG;
|
||||
|
||||
} else if (strncmp(dev, NFQUEUE_IFACE, strlen(NFQUEUE_IFACE)) == 0) {
|
||||
dev += strlen(NFQUEUE_IFACE);
|
||||
type = NFQUEUE;
|
||||
}
|
||||
|
||||
if (type != OTHER && *dev == ':') {
|
||||
dev++;
|
||||
while (*dev) {
|
||||
long int group_id;
|
||||
char *end_dev;
|
||||
@@ -335,7 +461,7 @@ nflog_activate(pcap_t* handle)
|
||||
}
|
||||
}
|
||||
|
||||
if (*dev) {
|
||||
if (type == OTHER || *dev) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"Can't get netfilter group(s) index from %s",
|
||||
handle->opt.source);
|
||||
@@ -351,12 +477,10 @@ nflog_activate(pcap_t* handle)
|
||||
/* Initialize some components of the pcap structure. */
|
||||
handle->bufsize = 128 + handle->snapshot;
|
||||
handle->offset = 0;
|
||||
handle->linktype = DLT_NFLOG;
|
||||
handle->read_op = nflog_read_linux;
|
||||
handle->read_op = netfilter_read_linux;
|
||||
handle->inject_op = netfilter_inject_linux;
|
||||
handle->setfilter_op = install_bpf_program; /* no kernel filtering */
|
||||
handle->setdirection_op = NULL;
|
||||
handle->set_datalink_op = NULL;
|
||||
handle->set_datalink_op = netfilter_set_datalink;
|
||||
handle->getnonblock_op = pcap_getnonblock_fd;
|
||||
handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
@@ -369,12 +493,17 @@ nflog_activate(pcap_t* handle)
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
|
||||
if (handle->dlt_list != NULL) {
|
||||
handle->dlt_list[0] = DLT_NFLOG;
|
||||
handle->dlt_list[1] = DLT_IPV4;
|
||||
handle->dlt_count = 2;
|
||||
}
|
||||
if (type == NFLOG) {
|
||||
handle->linktype = DLT_NFLOG;
|
||||
handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
|
||||
if (handle->dlt_list != NULL) {
|
||||
handle->dlt_list[0] = DLT_NFLOG;
|
||||
handle->dlt_list[1] = DLT_IPV4;
|
||||
handle->dlt_count = 2;
|
||||
}
|
||||
|
||||
} else
|
||||
handle->linktype = DLT_IPV4;
|
||||
|
||||
handle->buffer = malloc(handle->bufsize);
|
||||
if (!handle->buffer) {
|
||||
@@ -382,27 +511,53 @@ nflog_activate(pcap_t* handle)
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
/* Bind socket to the nflog groups */
|
||||
for (i = 0; i < group_count; i++) {
|
||||
if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
|
||||
if (type == NFLOG) {
|
||||
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
|
||||
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
/* Bind socket to the nflog groups */
|
||||
for (i = 0; i < group_count; i++) {
|
||||
if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
/* Bind socket to the nfqueue groups */
|
||||
for (i = 0; i < group_count; i++) {
|
||||
if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno));
|
||||
goto close_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->opt.rfmon) {
|
||||
@@ -432,28 +587,57 @@ close_fail:
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
nflog_create(const char *device, char *ebuf)
|
||||
netfilter_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like an netfilter device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
|
||||
/* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */
|
||||
if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0)
|
||||
cp += sizeof NFLOG_IFACE - 1;
|
||||
else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0)
|
||||
cp += sizeof NFQUEUE_IFACE - 1;
|
||||
else {
|
||||
/* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Yes - is that either the end of the name, or is it followed
|
||||
* by a colon?
|
||||
*/
|
||||
if (*cp != ':' && *cp != '\0') {
|
||||
/* Nope */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->activate_op = nflog_activate;
|
||||
p->activate_op = netfilter_activate;
|
||||
return (p);
|
||||
}
|
||||
|
||||
int
|
||||
netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str)
|
||||
{
|
||||
pcap_if_t *found_dev = *alldevsp;
|
||||
int sock;
|
||||
|
||||
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
|
||||
if (sock < 0) {
|
||||
/* if netlink is not supported this this is not fatal */
|
||||
if (errno == EAFNOSUPPORT)
|
||||
/* if netlink is not supported this is not fatal */
|
||||
if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
|
||||
return 0;
|
||||
snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
|
||||
errno, pcap_strerror(errno));
|
||||
@@ -461,8 +645,9 @@ netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
}
|
||||
close(sock);
|
||||
|
||||
if (pcap_add_if(&found_dev, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0)
|
||||
if (pcap_add_if(alldevsp, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0)
|
||||
return -1;
|
||||
if (pcap_add_if(alldevsp, NFQUEUE_IFACE, 0, "Linux netfilter queue (NFQUEUE) interface", err_str) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
/*
|
||||
* Prototypes for netlink-related functions
|
||||
*/
|
||||
int netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *nflog_create(const char *device, char *ebuf);
|
||||
int netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *netfilter_create(const char *device, char *ebuf, int *is_ours);
|
||||
|
||||
@@ -71,9 +71,17 @@ static const char rcsid[] _U_ =
|
||||
/* Forwards */
|
||||
static int nit_setflags(int, int, int, char *);
|
||||
|
||||
/*
|
||||
* Private data for capturing on NIT devices.
|
||||
*/
|
||||
struct pcap_nit {
|
||||
struct pcap_stat stat;
|
||||
};
|
||||
|
||||
static int
|
||||
pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct pcap_nit *pn = p->priv;
|
||||
|
||||
/*
|
||||
* "ps_recv" counts packets handed to the filter, not packets
|
||||
@@ -91,13 +99,14 @@ pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
|
||||
* kernel by libpcap or packets not yet read from libpcap by the
|
||||
* application.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
*ps = pn->stat;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_nit *pn = p->priv;
|
||||
register int cc, n;
|
||||
register u_char *bp, *cp, *ep;
|
||||
register struct nit_hdr *nh;
|
||||
@@ -156,7 +165,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
case NIT_NOMBUF:
|
||||
case NIT_NOCLUSTER:
|
||||
case NIT_NOSPACE:
|
||||
p->md.stat.ps_drop = nh->nh_dropped;
|
||||
pn->stat.ps_drop = nh->nh_dropped;
|
||||
continue;
|
||||
|
||||
case NIT_SEQNO:
|
||||
@@ -167,7 +176,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
"bad nit state %d", nh->nh_state);
|
||||
return (-1);
|
||||
}
|
||||
++p->md.stat.ps_recv;
|
||||
++pn->stat.ps_recv;
|
||||
bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
|
||||
sizeof(int) - 1) & ~(sizeof(int) - 1));
|
||||
|
||||
@@ -180,7 +189,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
h.len = nh->nh_wirelen;
|
||||
h.caplen = caplen;
|
||||
(*callback)(user, &h, cp);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
p->cc = ep - bp;
|
||||
p->bp = bp;
|
||||
return (n);
|
||||
@@ -209,28 +218,42 @@ pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
|
||||
}
|
||||
|
||||
static int
|
||||
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
|
||||
nit_setflags(pcap_t *p)
|
||||
{
|
||||
struct nit_ioc nioc;
|
||||
|
||||
memset(&nioc, 0, sizeof(nioc));
|
||||
nioc.nioc_bufspace = BUFSPACE;
|
||||
nioc.nioc_chunksize = CHUNKSIZE;
|
||||
nioc.nioc_typetomatch = NT_ALLTYPES;
|
||||
nioc.nioc_snaplen = p->snapshot;
|
||||
nioc.nioc_bufalign = sizeof(int);
|
||||
nioc.nioc_bufoffset = 0;
|
||||
|
||||
if (to_ms != 0) {
|
||||
nioc.nioc_flags |= NF_TIMEOUT;
|
||||
nioc.nioc_timeout.tv_sec = to_ms / 1000;
|
||||
nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
|
||||
if (p->opt.buffer_size != 0)
|
||||
nioc.nioc_bufspace = p->opt.buffer_size;
|
||||
else {
|
||||
/* Default buffer size */
|
||||
nioc.nioc_bufspace = BUFSPACE;
|
||||
}
|
||||
if (promisc)
|
||||
|
||||
if (p->opt.immediate) {
|
||||
/*
|
||||
* XXX - will this cause packets to be delivered immediately?
|
||||
* XXX - given that this is for SunOS prior to 4.0, do
|
||||
* we care?
|
||||
*/
|
||||
nioc.nioc_chunksize = 0;
|
||||
} else
|
||||
nioc.nioc_chunksize = CHUNKSIZE;
|
||||
if (p->opt.timeout != 0) {
|
||||
nioc.nioc_flags |= NF_TIMEOUT;
|
||||
nioc.nioc_timeout.tv_sec = p->opt.timeout / 1000;
|
||||
nioc.nioc_timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
}
|
||||
if (p->opt.promisc)
|
||||
nioc.nioc_flags |= NF_PROMISC;
|
||||
|
||||
if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
|
||||
if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@@ -273,7 +296,8 @@ pcap_activate_nit(pcap_t *p)
|
||||
"bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf);
|
||||
if (nit_setflags(p) < 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* NIT supports only ethernets.
|
||||
@@ -328,11 +352,11 @@ pcap_activate_nit(pcap_t *p)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_nit));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ static const char rcsid[] _U_ =
|
||||
static char nosup[] = "live packet capture not supported on this system";
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
(void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
|
||||
return (NULL);
|
||||
|
||||
@@ -74,6 +74,24 @@ struct rtentry;
|
||||
#include "os-proto.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FDDI packets are padded to make everything line up on a nice boundary.
|
||||
*/
|
||||
#define PCAP_FDDIPAD 3
|
||||
|
||||
/*
|
||||
* Private data for capturing on Ultrix and DEC OSF/1^WDigital UNIX^W^W
|
||||
* Tru64 UNIX packetfilter devices.
|
||||
*/
|
||||
struct pcap_pf {
|
||||
int filtering_in_kernel; /* 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 */
|
||||
};
|
||||
|
||||
static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
|
||||
|
||||
/*
|
||||
@@ -87,15 +105,14 @@ static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
|
||||
static int
|
||||
pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_pf *pf = pc->priv;
|
||||
register u_char *p, *bp;
|
||||
register int cc, n, buflen, inc;
|
||||
register struct enstamp *sp;
|
||||
#ifdef LBL_ALIGN
|
||||
struct enstamp stamp;
|
||||
#endif
|
||||
#ifdef PCAP_FDDIPAD
|
||||
register int pad;
|
||||
#endif
|
||||
|
||||
again:
|
||||
cc = pc->cc;
|
||||
@@ -126,9 +143,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
|
||||
* Loop through each packet.
|
||||
*/
|
||||
n = 0;
|
||||
#ifdef PCAP_FDDIPAD
|
||||
pad = pc->fddipad;
|
||||
#endif
|
||||
while (cc > 0) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
@@ -177,42 +192,34 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
|
||||
inc = ENALIGN(buflen + sp->ens_stamplen);
|
||||
cc -= inc;
|
||||
bp += inc;
|
||||
pc->md.TotPkts++;
|
||||
pc->md.TotDrops += sp->ens_dropped;
|
||||
pc->md.TotMissed = sp->ens_ifoverflows;
|
||||
if (pc->md.OrigMissed < 0)
|
||||
pc->md.OrigMissed = pc->md.TotMissed;
|
||||
pf->TotPkts++;
|
||||
pf->TotDrops += sp->ens_dropped;
|
||||
pf->TotMissed = sp->ens_ifoverflows;
|
||||
if (pf->OrigMissed < 0)
|
||||
pf->OrigMissed = pf->TotMissed;
|
||||
|
||||
/*
|
||||
* Short-circuit evaluation: if using BPF filter
|
||||
* in kernel, no need to do it now - we already know
|
||||
* the packet passed the filter.
|
||||
*
|
||||
#ifdef PCAP_FDDIPAD
|
||||
* Note: the filter code was generated assuming
|
||||
* that pc->fddipad was the amount of padding
|
||||
* before the header, as that's what's required
|
||||
* in the kernel, so we run the filter before
|
||||
* skipping that padding.
|
||||
#endif
|
||||
*/
|
||||
if (pc->md.use_bpf ||
|
||||
if (pf->filtering_in_kernel ||
|
||||
bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
|
||||
struct pcap_pkthdr h;
|
||||
pc->md.TotAccepted++;
|
||||
pf->TotAccepted++;
|
||||
h.ts = sp->ens_tstamp;
|
||||
#ifdef PCAP_FDDIPAD
|
||||
h.len = sp->ens_count - pad;
|
||||
#else
|
||||
h.len = sp->ens_count;
|
||||
#endif
|
||||
#ifdef PCAP_FDDIPAD
|
||||
p += pad;
|
||||
buflen -= pad;
|
||||
#endif
|
||||
h.caplen = buflen;
|
||||
(*callback)(user, &h, p);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
pc->cc = cc;
|
||||
pc->bp = bp;
|
||||
return (n);
|
||||
@@ -240,6 +247,7 @@ pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
|
||||
static int
|
||||
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct pcap_pf *pf = p->priv;
|
||||
|
||||
/*
|
||||
* If packet filtering is being done in the kernel:
|
||||
@@ -277,9 +285,9 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
|
||||
* the kernel by libpcap, but they may include packets not
|
||||
* yet read from libpcap by the application.
|
||||
*/
|
||||
ps->ps_recv = p->md.TotAccepted;
|
||||
ps->ps_drop = p->md.TotDrops;
|
||||
ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
|
||||
ps->ps_recv = pf->TotAccepted;
|
||||
ps->ps_drop = pf->TotDrops;
|
||||
ps->ps_ifdrop = pf->TotMissed - pf->OrigMissed;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -294,6 +302,7 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
|
||||
static int
|
||||
pcap_activate_pf(pcap_t *p)
|
||||
{
|
||||
struct pcap_pf *pf = p->priv;
|
||||
short enmode;
|
||||
int backlog = -1; /* request the most */
|
||||
struct enfilter Filter;
|
||||
@@ -327,8 +336,10 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
|
||||
p->opt.source, pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
p->md.OrigMissed = -1;
|
||||
enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
|
||||
pf->OrigMissed = -1;
|
||||
enmode = ENTSTAMP|ENNONEXCL;
|
||||
if (!p->opt.immediate)
|
||||
enmode |= ENBATCH;
|
||||
if (p->opt.promisc)
|
||||
enmode |= ENPROMISC;
|
||||
if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
|
||||
@@ -436,7 +447,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
|
||||
goto bad;
|
||||
}
|
||||
/* set truncation */
|
||||
#ifdef PCAP_FDDIPAD
|
||||
if (p->linktype == DLT_FDDI) {
|
||||
p->fddipad = PCAP_FDDIPAD;
|
||||
|
||||
@@ -444,7 +454,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
|
||||
p->snapshot += PCAP_FDDIPAD;
|
||||
} else
|
||||
p->fddipad = 0;
|
||||
#endif
|
||||
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
|
||||
pcap_strerror(errno));
|
||||
@@ -460,10 +469,10 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (p->md.timeout != 0) {
|
||||
if (p->opt.timeout != 0) {
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = p->md.timeout / 1000;
|
||||
timeout.tv_usec = (p->md.timeout * 1000) % 1000000;
|
||||
timeout.tv_sec = p->opt.timeout / 1000;
|
||||
timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
|
||||
pcap_strerror(errno));
|
||||
@@ -499,11 +508,11 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -520,6 +529,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
static int
|
||||
pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
|
||||
{
|
||||
struct pcap_pf *pf = p->priv;
|
||||
struct bpf_version bv;
|
||||
|
||||
/*
|
||||
@@ -561,7 +571,7 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
|
||||
* a window to annoy the user.
|
||||
*/
|
||||
fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
|
||||
p->md.use_bpf = 1;
|
||||
pf->filtering_in_kernel = 1;
|
||||
|
||||
/*
|
||||
* Discard any previously-received packets,
|
||||
@@ -599,6 +609,6 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
|
||||
* a warning of some sort.
|
||||
*/
|
||||
fprintf(stderr, "tcpdump: Filtering in user process\n");
|
||||
p->md.use_bpf = 0;
|
||||
pf->filtering_in_kernel = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -55,16 +55,24 @@ Link-layer header type
|
||||
.RE
|
||||
.PP
|
||||
All fields in the per-file header are in the byte order of the host
|
||||
writing the file. The first field in the per-file header is a 4-byte
|
||||
magic number, with the value 0xa1b2c3d4. The magic number, when read by
|
||||
a host with the same byte order as the host that wrote the file, will
|
||||
have the value 0xa1b2c3d4, and, when read by a host with the opposite
|
||||
byte order as the host that wrote the file, will have the value
|
||||
writing the file. Normally, the first field in the per-file header is a
|
||||
4-byte magic number, with the value 0xa1b2c3d4. The magic number, when
|
||||
read by a host with the same byte order as the host that wrote the file,
|
||||
will have the value 0xa1b2c3d4, and, when read by a host with the
|
||||
opposite byte order as the host that wrote the file, will have the value
|
||||
0xd4c3b2a1. That allows software reading the file to determine whether
|
||||
the byte order of the host that wrote the file is the same as the byte
|
||||
order of the host on which the file is being read, and thus whether the
|
||||
values in the per-file and per-packet headers need to be byte-swapped.
|
||||
.PP
|
||||
If the magic number has the value 0xa1b23c4d (with the two nibbles of
|
||||
the two lower-order bytes of the magic number swapped), which would be
|
||||
read as 0xa1b23c4d by a host with the same byte order as the host that
|
||||
wrote the file and as 0x4d3cb2a1 by a host with the opposite byte order
|
||||
as the host that wrote the file, the file format is the same as for
|
||||
regular files, except that the time stamps for packets are given in
|
||||
seconds and nanoseconds rather than seconds and microseconds.
|
||||
.PP
|
||||
Following this are:
|
||||
.IP
|
||||
A 2-byte file format major version number; the current version number is
|
||||
@@ -104,7 +112,7 @@ box;
|
||||
c.
|
||||
Time stamp, seconds value
|
||||
_
|
||||
Time stamp, microseconds value
|
||||
Time stamp, microseconds or nanoseconds value
|
||||
_
|
||||
Length of captured packet data
|
||||
_
|
||||
@@ -117,11 +125,12 @@ writing the file. The per-packet header begins with a time stamp giving
|
||||
the approximate time the packet was captured; the time stamp consists of
|
||||
a 4-byte value, giving the time in seconds since January 1, 1970,
|
||||
00:00:00 UTC, followed by a 4-byte value, giving the time in
|
||||
microseconds since that second. Following that are a 4-byte value
|
||||
giving the number of bytes of captured data that follow the per-packet
|
||||
header and a 4-byte value giving the number of bytes that would have
|
||||
been present had the packet not been truncated by the snapshot length.
|
||||
The two lengths will be equal if the number of bytes of packet data are
|
||||
less than or equal to the snapshot length.
|
||||
microseconds or nanoseconds since that second, depending on the magic
|
||||
number in the file header. Following that are a 4-byte value giving the
|
||||
number of bytes of captured data that follow the per-packet header and a
|
||||
4-byte value giving the number of bytes that would have been present had
|
||||
the packet not been truncated by the snapshot length. The two lengths
|
||||
will be equal if the number of bytes of packet data are less than or
|
||||
equal to the snapshot length.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
|
||||
|
||||
@@ -38,27 +38,25 @@ static const char rcsid[] _U_ =
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SEPTEL_API
|
||||
#include <msg.h>
|
||||
#include <ss7_inc.h>
|
||||
#include <sysgct.h>
|
||||
#include <pack.h>
|
||||
#include <system.h>
|
||||
#endif /* HAVE_SEPTEL_API */
|
||||
|
||||
#ifdef SEPTEL_ONLY
|
||||
/* This code is required when compiling for a Septel device only. */
|
||||
#include "pcap-septel.h"
|
||||
|
||||
/* Replace septel function names with pcap equivalent. */
|
||||
#define septel_create pcap_create
|
||||
#define septel_platform_finddevs pcap_platform_finddevs
|
||||
#endif /* SEPTEL_ONLY */
|
||||
|
||||
static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
|
||||
static int septel_stats(pcap_t *p, struct pcap_stat *ps);
|
||||
static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
|
||||
|
||||
/*
|
||||
* Private data for capturing on Septel devices.
|
||||
*/
|
||||
struct pcap_septel {
|
||||
struct pcap_stat stat;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read at most max_packets from the capture queue and call the callback
|
||||
* for each of them. Returns the number of packets handled, -1 if an
|
||||
@@ -66,6 +64,7 @@ static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
|
||||
*/
|
||||
static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
|
||||
|
||||
struct pcap_septel *ps = p->priv;
|
||||
HDR *h;
|
||||
MSG *m;
|
||||
int processed = 0 ;
|
||||
@@ -163,7 +162,7 @@ loop:
|
||||
pcap_header.len = packet_len;
|
||||
|
||||
/* Count the packet. */
|
||||
p->md.stat.ps_recv++;
|
||||
ps->stat.ps_recv++;
|
||||
|
||||
/* Call the user supplied callback function */
|
||||
callback(user, &pcap_header, dp);
|
||||
@@ -221,10 +220,24 @@ static pcap_t *septel_activate(pcap_t* handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcap_t *septel_create(const char *device, char *ebuf) {
|
||||
pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) {
|
||||
const char *cp;
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like the Septel device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
if (strcmp(cp, "septel") != 0) {
|
||||
/* Nope, it's not "septel" */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -233,17 +246,18 @@ pcap_t *septel_create(const char *device, char *ebuf) {
|
||||
}
|
||||
|
||||
static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
|
||||
/*p->md.stat.ps_recv = 0;*/
|
||||
/*p->md.stat.ps_drop = 0;*/
|
||||
struct pcap_septel *handlep = p->priv;
|
||||
/*handlep->stat.ps_recv = 0;*/
|
||||
/*handlep->stat.ps_drop = 0;*/
|
||||
|
||||
*ps = p->md.stat;
|
||||
*ps = handlep->stat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
septel_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
|
||||
septel_findalldevs(pcap_if_t **devlistp, char *errbuf)
|
||||
{
|
||||
unsigned char *p;
|
||||
const char description[512]= "Intel/Septel device";
|
||||
@@ -277,8 +291,6 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->md.use_bpf = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -286,5 +298,6 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
|
||||
static int
|
||||
septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
return (0);
|
||||
fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.2 2008-04-04 19:37:45 guy Exp $
|
||||
*/
|
||||
|
||||
pcap_t *septel_create(const char *device, char *ebuf);
|
||||
|
||||
pcap_t *septel_create(const char *device, char *ebuf, int *is_ours);
|
||||
int septel_findalldevs(pcap_if_t **devlistp, char *errbuf);
|
||||
|
||||
@@ -55,40 +55,37 @@
|
||||
#define LIVE 1
|
||||
|
||||
typedef struct iface {
|
||||
struct iface *next; /* a pointer to the next interface */
|
||||
char *name; /* this interface's name on Wireshark */
|
||||
char *IOPname; /* this interface's name on an IOP */
|
||||
uint32_t iftype; /* the type of interface (DLT values) */
|
||||
struct iface *next; /* a pointer to the next interface */
|
||||
char *name; /* this interface's name */
|
||||
char *IOPname; /* this interface's name on an IOP */
|
||||
uint32_t iftype; /* the type of interface (DLT values) */
|
||||
} iface_t;
|
||||
|
||||
typedef struct unit {
|
||||
char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
|
||||
int fd; /* the connection to this unit (if it exists) */
|
||||
int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
|
||||
int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
|
||||
struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
|
||||
int chassis;
|
||||
int geoslot;
|
||||
iface_t *iface; /* a pointer to a linked list of interface structures */
|
||||
char *imsg; /* a pointer to an inbound message */
|
||||
int len; /* the current size of the inbound message */
|
||||
char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
|
||||
int fd; /* the connection to this unit (if it exists) */
|
||||
int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
|
||||
int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
|
||||
struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
|
||||
int chassis;
|
||||
int geoslot;
|
||||
iface_t *iface; /* a pointer to a linked list of interface structures */
|
||||
char *imsg; /* a pointer to an inbound message */
|
||||
int len; /* the current size of the inbound message */
|
||||
} unit_t;
|
||||
|
||||
static char *errorString;
|
||||
static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */
|
||||
static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
|
||||
static fd_set working_set;
|
||||
static int max_fs;
|
||||
static char static_buf[32];
|
||||
static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
|
||||
static int max_fs;
|
||||
|
||||
pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
|
||||
pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
|
||||
|
||||
static void dump_interface_list(void) {
|
||||
pcap_if_t *iff;
|
||||
pcap_addr_t *addr;
|
||||
int longest_name_len = 0;
|
||||
int longest_name_len = 0;
|
||||
char *n, *d, *f;
|
||||
int if_number = 0;
|
||||
int if_number = 0;
|
||||
|
||||
iff = acn_if_list;
|
||||
while (iff) {
|
||||
@@ -214,6 +211,9 @@ static void empty_unit(int chassis, int geoslot) {
|
||||
empty_unit_iface(u);
|
||||
if (u->imsg) { /* then if an inbound message buffer exists */
|
||||
u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */
|
||||
if (u->imsg == NULL) { /* oops, realloc call failed */
|
||||
fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,9 +311,17 @@ static int open_with_IOP(unit_t *u, int flag) {
|
||||
|
||||
if (u->serv_addr == NULL) {
|
||||
u->serv_addr = malloc(sizeof(struct sockaddr_in));
|
||||
|
||||
/* since we called malloc(), lets check to see if we actually got the memory */
|
||||
if (u->serv_addr == NULL) { /* oops, we didn't get the memory requested */
|
||||
fprintf(stderr, "malloc() request for u->serv_addr failed, value of errno is: %d\n", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
ip = u->ip;
|
||||
bzero((char *)u->serv_addr, sizeof(struct sockaddr_in));
|
||||
/* bzero() is deprecated, replaced with memset() */
|
||||
memset((char *)u->serv_addr, 0, sizeof(struct sockaddr_in));
|
||||
u->serv_addr->sin_family = AF_INET;
|
||||
u->serv_addr->sin_addr.s_addr = inet_addr(ip);
|
||||
u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT);
|
||||
@@ -394,18 +402,16 @@ static void acn_freealldevs(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static char *nonUnified_port_num(unit_t *u, int IOPportnum) {
|
||||
static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
|
||||
|
||||
sprintf(static_buf, "%d_%d", u->chassis, u->geoslot);
|
||||
return static_buf;
|
||||
snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
|
||||
}
|
||||
|
||||
static char *unified_port_num(unit_t *u, int IOPportnum) {
|
||||
static void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) {
|
||||
int portnum;
|
||||
|
||||
portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
|
||||
sprintf(static_buf, "%d", portnum);
|
||||
return static_buf;
|
||||
snprintf(buf, bufsize, "%s_%d", proto, portnum);
|
||||
}
|
||||
|
||||
static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
|
||||
@@ -417,36 +423,64 @@ static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 if
|
||||
int IOPportnum = 0;
|
||||
|
||||
iface = malloc(sizeof(iface_t)); /* get memory for a structure */
|
||||
bzero((char *)iface, sizeof(iface_t));
|
||||
if (iface == NULL) { /* oops, we didn't get the memory requested */
|
||||
fprintf(stderr, "Error...couldn't allocate memory for interface structure...value of errno is: %d\n", errno);
|
||||
return NULL;
|
||||
}
|
||||
memset((char *)iface, 0, sizeof(iface_t)); /* bzero is deprecated(), replaced with memset() */
|
||||
|
||||
iface->iftype = iftype; /* remember the interface type of this interface */
|
||||
|
||||
name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */
|
||||
if (name == NULL) { /* oops, we didn't get the memory requested */
|
||||
fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(name, IOPname); /* and copy it in */
|
||||
iface->IOPname = name; /* and stick it into the structure */
|
||||
|
||||
if (strncmp(IOPname, "lo", 2) == 0) {
|
||||
IOPportnum = atoi(&IOPname[2]);
|
||||
switch (iftype) {
|
||||
case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break;
|
||||
default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
|
||||
case DLT_EN10MB:
|
||||
nonUnified_IOP_port_name(buf, sizeof buf, "lo", u);
|
||||
break;
|
||||
default:
|
||||
unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
|
||||
break;
|
||||
}
|
||||
} else if (strncmp(IOPname, "eth", 3) == 0) {
|
||||
IOPportnum = atoi(&IOPname[3]);
|
||||
switch (iftype) {
|
||||
case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break;
|
||||
default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
|
||||
case DLT_EN10MB:
|
||||
nonUnified_IOP_port_name(buf, sizeof buf, "eth", u);
|
||||
break;
|
||||
default:
|
||||
unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
|
||||
break;
|
||||
}
|
||||
} else if (strncmp(IOPname, "wan", 3) == 0) {
|
||||
IOPportnum = atoi(&IOPname[3]);
|
||||
switch (iftype) {
|
||||
case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break;
|
||||
default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
|
||||
case DLT_SITA:
|
||||
unified_IOP_port_name(buf, sizeof buf, "wan", u, IOPportnum);
|
||||
break;
|
||||
default:
|
||||
unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error... invalid IOP name %s\n", IOPname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */
|
||||
name = malloc(strlen(buf) + 1); /* get memory for that name */
|
||||
if (name == NULL) { /* oops, we didn't get the memory requested */
|
||||
fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(name, buf); /* and copy it in */
|
||||
iface->name = name; /* and stick it into the structure */
|
||||
|
||||
@@ -548,7 +582,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)iff, sizeof(pcap_if_t));
|
||||
memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */
|
||||
if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */
|
||||
if (prev_iff) prev_iff->next = iff; /* insert a forward link */
|
||||
|
||||
@@ -588,7 +622,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)addr, sizeof(pcap_addr_t));
|
||||
+ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
|
||||
if (iff->addresses == 0) iff->addresses = addr;
|
||||
if (prev_addr) prev_addr->next = addr; /* insert a forward link */
|
||||
if (*ptr) { /* if there is a count for the address */
|
||||
@@ -596,7 +630,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)s, sizeof(struct sockaddr_in));
|
||||
memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */
|
||||
addr->addr = (struct sockaddr *)s;
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */
|
||||
@@ -608,7 +642,9 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)s, sizeof(struct sockaddr_in));
|
||||
/* bzero() is deprecated, replaced with memset() */
|
||||
memset((char *)s, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
addr->netmask = (struct sockaddr *)s;
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
|
||||
@@ -620,7 +656,9 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)s, sizeof(struct sockaddr_in));
|
||||
/* bzero() is deprecated, replaced with memset() */
|
||||
memset((char *)s, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
addr->broadaddr = (struct sockaddr *)s;
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
|
||||
@@ -632,7 +670,9 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bzero((char *)s, sizeof(struct sockaddr_in));
|
||||
/* bzero() is deprecated, replaced with memset() */
|
||||
memset((char *)s, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
addr->dstaddr = (struct sockaddr *)s;
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
|
||||
@@ -683,6 +723,8 @@ static void wait_for_all_answers(void) {
|
||||
|
||||
while (1) {
|
||||
int flag = 0;
|
||||
fd_set working_set;
|
||||
|
||||
for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */
|
||||
if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */
|
||||
}
|
||||
@@ -776,7 +818,7 @@ static int acn_open_live(const char *name, char *errbuf, int *linktype) { /* re
|
||||
iface_t *p;
|
||||
pcap_if_t *alldevsp;
|
||||
|
||||
pcap_findalldevs(&alldevsp, errbuf);
|
||||
pcap_findalldevs_interfaces(&alldevsp, errbuf);
|
||||
for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
|
||||
for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
|
||||
u = &units[chassis][geoslot];
|
||||
@@ -900,7 +942,7 @@ static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback,
|
||||
struct pcap_pkthdr pcap_header;
|
||||
|
||||
//printf("pcap_read_acn()\n"); // fulko
|
||||
acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */
|
||||
acn_start_monitor(handle->fd, handle->snapshot, handle->opt.timeout, handle->opt.promisc, handle->direction); /* maybe tell him to start monitoring */
|
||||
//printf("pcap_read_acn() after start monitor\n"); // fulko
|
||||
|
||||
handle->bp = packet_header;
|
||||
@@ -945,7 +987,6 @@ static int pcap_activate_sita(pcap_t *handle) {
|
||||
&handle->linktype);
|
||||
if (fd == -1)
|
||||
return PCAP_ERROR;
|
||||
handle->md.clear_promisc = handle->md.promisc;
|
||||
handle->fd = fd;
|
||||
handle->bufsize = handle->snapshot;
|
||||
|
||||
@@ -968,10 +1009,10 @@ static int pcap_activate_sita(pcap_t *handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcap_t *pcap_create(const char *device, char *ebuf) {
|
||||
pcap_t *pcap_create_interface(const char *device, char *ebuf) {
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, 0);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
||||
@@ -15,13 +15,20 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "snf.h"
|
||||
#include "pcap-int.h"
|
||||
#include <snf.h>
|
||||
|
||||
#ifdef SNF_ONLY
|
||||
#define snf_create pcap_create
|
||||
#define snf_platform_finddevs pcap_platform_finddevs
|
||||
#endif
|
||||
#include "pcap-int.h"
|
||||
#include "pcap-snf.h"
|
||||
|
||||
/*
|
||||
* Private data for capturing on SNF devices.
|
||||
*/
|
||||
struct pcap_snf {
|
||||
snf_handle_t snf_handle; /* opaque device handle */
|
||||
snf_ring_t snf_ring; /* opaque device ring handle */
|
||||
int snf_timeout;
|
||||
int snf_boardnum;
|
||||
};
|
||||
|
||||
static int
|
||||
snf_set_datalink(pcap_t *p, int dlt)
|
||||
@@ -36,7 +43,7 @@ snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
|
||||
struct snf_ring_stats stats;
|
||||
int rc;
|
||||
|
||||
if ((rc = snf_ring_getstats(p->md.snf_ring, &stats))) {
|
||||
if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
|
||||
pcap_strerror(rc));
|
||||
return -1;
|
||||
@@ -50,30 +57,36 @@ snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
|
||||
static void
|
||||
snf_platform_cleanup(pcap_t *p)
|
||||
{
|
||||
struct pcap_snf *ps = p->priv;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
snf_ring_close(p->md.snf_ring);
|
||||
snf_close(p->md.snf_handle);
|
||||
snf_ring_close(ps->snf_ring);
|
||||
snf_close(ps->snf_handle);
|
||||
pcap_cleanup_live_common(p);
|
||||
}
|
||||
|
||||
static int
|
||||
snf_getnonblock(pcap_t *p, char *errbuf)
|
||||
{
|
||||
return (p->md.snf_timeout == 0);
|
||||
struct pcap_snf *ps = p->priv;
|
||||
|
||||
return (ps->snf_timeout == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
struct pcap_snf *ps = p->priv;
|
||||
|
||||
if (nonblock)
|
||||
p->md.snf_timeout = 0;
|
||||
ps->snf_timeout = 0;
|
||||
else {
|
||||
if (p->md.timeout <= 0)
|
||||
p->md.snf_timeout = -1; /* forever */
|
||||
if (p->opt.timeout <= 0)
|
||||
ps->snf_timeout = -1; /* forever */
|
||||
else
|
||||
p->md.snf_timeout = p->md.timeout;
|
||||
ps->snf_timeout = p->opt.timeout;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -96,6 +109,7 @@ snf_timestamp_to_timeval(const int64_t ts_nanosec)
|
||||
static int
|
||||
snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_snf *ps = p->priv;
|
||||
struct pcap_pkthdr hdr;
|
||||
int i, flags, err, caplen, n;
|
||||
struct snf_recv_req req;
|
||||
@@ -104,7 +118,7 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
return -1;
|
||||
|
||||
n = 0;
|
||||
while (n < cnt || cnt < 0) {
|
||||
while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
*/
|
||||
@@ -117,7 +131,7 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
}
|
||||
}
|
||||
|
||||
err = snf_ring_recv(p->md.snf_ring, p->md.snf_timeout, &req);
|
||||
err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req);
|
||||
|
||||
if (err) {
|
||||
if (err == EBUSY || err == EAGAIN)
|
||||
@@ -163,8 +177,6 @@ snf_setfilter(pcap_t *p, struct bpf_program *fp)
|
||||
if (install_bpf_program(p, fp) < 0)
|
||||
return -1;
|
||||
|
||||
p->md.use_bpf = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -179,6 +191,7 @@ snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
|
||||
static int
|
||||
snf_activate(pcap_t* p)
|
||||
{
|
||||
struct pcap_snf *ps = p->priv;
|
||||
char *device = p->opt.source;
|
||||
const char *nr = NULL;
|
||||
int err;
|
||||
@@ -197,31 +210,31 @@ snf_activate(pcap_t* p)
|
||||
else
|
||||
nr = NULL;
|
||||
|
||||
err = snf_open(p->md.snf_boardnum,
|
||||
err = snf_open(ps->snf_boardnum,
|
||||
0, /* let SNF API parse SNF_NUM_RINGS, if set */
|
||||
NULL, /* default RSS, or use SNF_RSS_FLAGS env */
|
||||
0, /* default to SNF_DATARING_SIZE from env */
|
||||
flags, /* may want pshared */
|
||||
&p->md.snf_handle);
|
||||
&ps->snf_handle);
|
||||
if (err != 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"snf_open failed: %s", pcap_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snf_ring_open(p->md.snf_handle, &p->md.snf_ring);
|
||||
err = snf_ring_open(ps->snf_handle, &ps->snf_ring);
|
||||
if (err != 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"snf_ring_open failed: %s", pcap_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p->md.timeout <= 0)
|
||||
p->md.snf_timeout = -1;
|
||||
if (p->opt.timeout <= 0)
|
||||
ps->snf_timeout = -1;
|
||||
else
|
||||
p->md.snf_timeout = p->md.timeout;
|
||||
ps->snf_timeout = p->opt.timeout;
|
||||
|
||||
err = snf_start(p->md.snf_handle);
|
||||
err = snf_start(ps->snf_handle);
|
||||
if (err != 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"snf_start failed: %s", pcap_strerror(err));
|
||||
@@ -242,14 +255,11 @@ snf_activate(pcap_t* p)
|
||||
p->setnonblock_op = snf_setnonblock;
|
||||
p->stats_op = snf_pcap_stats;
|
||||
p->cleanup_op = snf_platform_cleanup;
|
||||
p->md.stat.ps_recv = 0;
|
||||
p->md.stat.ps_drop = 0;
|
||||
p->md.stat.ps_ifdrop = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
|
||||
snf_findalldevs(pcap_if_t **devlistp, char *errbuf)
|
||||
{
|
||||
/*
|
||||
* There are no platform-specific devices since each device
|
||||
@@ -259,22 +269,29 @@ snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
snf_create(const char *device, char *ebuf)
|
||||
snf_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
pcap_t *p;
|
||||
int boardnum = -1;
|
||||
struct snf_ifaddrs *ifaddrs, *ifa;
|
||||
size_t devlen;
|
||||
struct pcap_snf *ps;
|
||||
|
||||
if (snf_init(SNF_VERSION_API))
|
||||
if (snf_init(SNF_VERSION_API)) {
|
||||
/* Can't initialize the API, so no SNF devices */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Match a given interface name to our list of interface names, from
|
||||
* which we can obtain the intended board number
|
||||
*/
|
||||
if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
|
||||
if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) {
|
||||
/* Can't get SNF addresses */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
devlen = strlen(device) + 1;
|
||||
ifa = ifaddrs;
|
||||
while (ifa) {
|
||||
@@ -292,15 +309,22 @@ snf_create(const char *device, char *ebuf)
|
||||
* and "snf10gX" where X is the board number.
|
||||
*/
|
||||
if (sscanf(device, "snf10g%d", &boardnum) != 1 &&
|
||||
sscanf(device, "snf%d", &boardnum) != 1)
|
||||
sscanf(device, "snf%d", &boardnum) != 1) {
|
||||
/* Nope, not a supported name */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
ps = p->priv;
|
||||
|
||||
p->activate_op = snf_activate;
|
||||
p->md.snf_boardnum = boardnum;
|
||||
ps->snf_boardnum = boardnum;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
pcap_t *snf_create(const char *, char *);
|
||||
int snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
|
||||
pcap_t *snf_create(const char *, char *, int *);
|
||||
int snf_findalldevs(pcap_if_t **devlistp, char *errbuf);
|
||||
|
||||
@@ -84,9 +84,17 @@ static const char rcsid[] _U_ =
|
||||
/* Forwards */
|
||||
static int nit_setflags(int, int, int, char *);
|
||||
|
||||
/*
|
||||
* Private data for capturing on STREAMS NIT devices.
|
||||
*/
|
||||
struct pcap_snit {
|
||||
struct pcap_stat stat;
|
||||
};
|
||||
|
||||
static int
|
||||
pcap_stats_snit(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct pcap_snit *psn = p->priv;
|
||||
|
||||
/*
|
||||
* "ps_recv" counts packets handed to the filter, not packets
|
||||
@@ -105,13 +113,14 @@ pcap_stats_snit(pcap_t *p, struct pcap_stat *ps)
|
||||
* kernel by libpcap or packets not yet read from libpcap by the
|
||||
* application.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
*ps = psn->stat;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_snit *psn = p->priv;
|
||||
register int cc, n;
|
||||
register u_char *bp, *cp, *ep;
|
||||
register struct nit_bufhdr *hdrp;
|
||||
@@ -160,7 +169,7 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
}
|
||||
}
|
||||
|
||||
++p->md.stat.ps_recv;
|
||||
++psn->stat.ps_recv;
|
||||
cp = bp;
|
||||
|
||||
/* get past NIT buffer */
|
||||
@@ -172,7 +181,7 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
cp += sizeof(*ntp);
|
||||
|
||||
ndp = (struct nit_ifdrops *)cp;
|
||||
p->md.stat.ps_drop = ndp->nh_drops;
|
||||
psn->stat.ps_drop = ndp->nh_drops;
|
||||
cp += sizeof *ndp;
|
||||
|
||||
/* get past packet len */
|
||||
@@ -192,7 +201,7 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
h.len = nlp->nh_pktlen;
|
||||
h.caplen = caplen;
|
||||
(*callback)(user, &h, cp);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
p->cc = ep - bp;
|
||||
p->bp = bp;
|
||||
return (n);
|
||||
@@ -227,33 +236,48 @@ pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
|
||||
}
|
||||
|
||||
static int
|
||||
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
|
||||
nit_setflags(pcap_t *p)
|
||||
{
|
||||
bpf_u_int32 flags;
|
||||
struct strioctl si;
|
||||
u_int zero = 0;
|
||||
struct timeval timeout;
|
||||
|
||||
if (p->opt.immediate) {
|
||||
/*
|
||||
* Set the chunk size to zero, so that chunks get sent
|
||||
* up immediately.
|
||||
*/
|
||||
si.ic_cmd = NIOCSCHUNK;
|
||||
si.ic_len = sizeof(zero);
|
||||
si.ic_dp = (char *)&zero;
|
||||
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
si.ic_timout = INFTIM;
|
||||
if (to_ms != 0) {
|
||||
timeout.tv_sec = to_ms / 1000;
|
||||
timeout.tv_usec = (to_ms * 1000) % 1000000;
|
||||
if (p->opt.timeout != 0) {
|
||||
timeout.tv_sec = p->opt.timeout / 1000;
|
||||
timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
|
||||
si.ic_cmd = NIOCSTIME;
|
||||
si.ic_len = sizeof(timeout);
|
||||
si.ic_dp = (char *)&timeout;
|
||||
if (ioctl(fd, I_STR, (char *)&si) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
|
||||
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
|
||||
if (promisc)
|
||||
if (p->opt.promisc)
|
||||
flags |= NI_PROMISC;
|
||||
si.ic_cmd = NIOCSFLAGS;
|
||||
si.ic_len = sizeof(flags);
|
||||
si.ic_dp = (char *)&flags;
|
||||
if (ioctl(fd, I_STR, (char *)&si) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
|
||||
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@@ -349,7 +373,7 @@ pcap_activate_snit(pcap_t *p)
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0)
|
||||
if (nit_setflags(p) < 0)
|
||||
goto bad;
|
||||
|
||||
(void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
|
||||
@@ -407,11 +431,11 @@ pcap_activate_snit(pcap_t *p)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_snit));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
||||
@@ -58,9 +58,17 @@ static const char rcsid[] _U_ =
|
||||
#include "os-proto.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private data for capturing on snoop devices.
|
||||
*/
|
||||
struct pcap_snoop {
|
||||
struct pcap_stat stat;
|
||||
};
|
||||
|
||||
static int
|
||||
pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_snoop *psn = p->priv;
|
||||
int cc;
|
||||
register struct snoopheader *sh;
|
||||
register u_int datalen;
|
||||
@@ -124,7 +132,7 @@ again:
|
||||
if (p->fcode.bf_insns == NULL ||
|
||||
bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
|
||||
struct pcap_pkthdr h;
|
||||
++p->md.stat.ps_recv;
|
||||
++psn->stat.ps_recv;
|
||||
h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
|
||||
h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
|
||||
h.len = datalen;
|
||||
@@ -156,6 +164,7 @@ pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
|
||||
static int
|
||||
pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
struct pcap_snoop *psn = p->priv;
|
||||
register struct rawstats *rs;
|
||||
struct rawstats rawstats;
|
||||
|
||||
@@ -180,7 +189,7 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
|
||||
* rather than just this socket? If not, why does it have
|
||||
* both Snoop and Drain statistics?
|
||||
*/
|
||||
p->md.stat.ps_drop =
|
||||
psn->stat.ps_drop =
|
||||
rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
|
||||
rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
|
||||
|
||||
@@ -189,7 +198,7 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
|
||||
* As filtering is done in userland, this does not include
|
||||
* packets dropped because we ran out of buffer space.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
*ps = psn->stat;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -394,11 +403,11 @@ pcap_activate_snoop(pcap_t *p)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_snoop));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
||||
@@ -121,6 +121,16 @@ struct mon_bin_mfetch {
|
||||
#define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */
|
||||
#define MON_BIN_ERROR 0x8
|
||||
|
||||
/*
|
||||
* Private data for capturing on Linux USB.
|
||||
*/
|
||||
struct pcap_usb_linux {
|
||||
u_char *mmapbuf; /* memory-mapped region pointer */
|
||||
size_t mmapbuflen; /* size of region */
|
||||
int bus_index;
|
||||
u_int packets_read;
|
||||
};
|
||||
|
||||
/* forward declaration */
|
||||
static int usb_activate(pcap_t *);
|
||||
static int usb_stats_linux(pcap_t *, struct pcap_stat *);
|
||||
@@ -148,7 +158,7 @@ usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
|
||||
}
|
||||
|
||||
int
|
||||
usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
|
||||
{
|
||||
struct dirent* data;
|
||||
int ret = 0;
|
||||
@@ -204,14 +214,15 @@ usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
|
||||
static
|
||||
int usb_mmap(pcap_t* handle)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
|
||||
if (len < 0)
|
||||
return 0;
|
||||
|
||||
handle->md.mmapbuflen = len;
|
||||
handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ,
|
||||
handlep->mmapbuflen = len;
|
||||
handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
|
||||
MAP_SHARED, handle->fd, 0);
|
||||
return handle->md.mmapbuf != MAP_FAILED;
|
||||
return handlep->mmapbuf != MAP_FAILED;
|
||||
}
|
||||
|
||||
#define CTRL_TIMEOUT (5*1000) /* milliseconds */
|
||||
@@ -284,11 +295,41 @@ probe_devices(int bus)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
usb_create(const char *device, char *ebuf)
|
||||
usb_create(const char *device, char *ebuf, int *is_ours)
|
||||
{
|
||||
const char *cp;
|
||||
char *cpend;
|
||||
long devnum;
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_create_common(device, ebuf);
|
||||
/* Does this look like a USB monitoring device? */
|
||||
cp = strrchr(device, '/');
|
||||
if (cp == NULL)
|
||||
cp = device;
|
||||
/* Does it begin with USB_IFACE? */
|
||||
if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) {
|
||||
/* Nope, doesn't begin with USB_IFACE */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Yes - is USB_IFACE followed by a number? */
|
||||
cp += sizeof USB_IFACE - 1;
|
||||
devnum = strtol(cp, &cpend, 10);
|
||||
if (cpend == cp || *cpend != '\0') {
|
||||
/* Not followed by a number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (devnum < 0) {
|
||||
/* Followed by a non-valid number. */
|
||||
*is_ours = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OK, it's probably ours. */
|
||||
*is_ours = 1;
|
||||
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -299,6 +340,7 @@ usb_create(const char *device, char *ebuf)
|
||||
static int
|
||||
usb_activate(pcap_t* handle)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
char full_path[USB_LINE_LEN];
|
||||
|
||||
/* Initialize some components of the pcap structure. */
|
||||
@@ -314,7 +356,7 @@ usb_activate(pcap_t* handle)
|
||||
handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
|
||||
/*get usb bus index from device name */
|
||||
if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1)
|
||||
if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1)
|
||||
{
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"Can't get USB bus index from %s", handle->opt.source);
|
||||
@@ -322,7 +364,7 @@ usb_activate(pcap_t* handle)
|
||||
}
|
||||
|
||||
/*now select the read method: try to open binary interface */
|
||||
snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);
|
||||
snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
|
||||
handle->fd = open(full_path, O_RDONLY, 0);
|
||||
if (handle->fd >= 0)
|
||||
{
|
||||
@@ -340,7 +382,7 @@ usb_activate(pcap_t* handle)
|
||||
handle->stats_op = usb_stats_linux_bin;
|
||||
handle->read_op = usb_read_linux_mmap;
|
||||
handle->cleanup_op = usb_cleanup_linux_mmap;
|
||||
probe_devices(handle->md.ifindex);
|
||||
probe_devices(handlep->bus_index);
|
||||
|
||||
/*
|
||||
* "handle->fd" is a real file, so "select()" and
|
||||
@@ -353,11 +395,11 @@ usb_activate(pcap_t* handle)
|
||||
/* can't mmap, use plain binary interface access */
|
||||
handle->stats_op = usb_stats_linux_bin;
|
||||
handle->read_op = usb_read_linux_bin;
|
||||
probe_devices(handle->md.ifindex);
|
||||
probe_devices(handlep->bus_index);
|
||||
}
|
||||
else {
|
||||
/*Binary interface not available, try open text interface */
|
||||
snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex);
|
||||
snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
|
||||
handle->fd = open(full_path, O_RDONLY, 0);
|
||||
if (handle->fd < 0)
|
||||
{
|
||||
@@ -367,7 +409,7 @@ usb_activate(pcap_t* handle)
|
||||
* Not found at the new location; try
|
||||
* the old location.
|
||||
*/
|
||||
snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex);
|
||||
snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
|
||||
handle->fd = open(full_path, O_RDONLY, 0);
|
||||
}
|
||||
if (handle->fd < 0) {
|
||||
@@ -426,6 +468,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
|
||||
* /usr/src/linux/Documentation/usb/usbmon.txt
|
||||
* for message format
|
||||
*/
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
unsigned timestamp;
|
||||
int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
|
||||
char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
|
||||
@@ -470,7 +513,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
|
||||
}
|
||||
uhdr->id = tag;
|
||||
uhdr->device_address = dev_addr;
|
||||
uhdr->bus_id = handle->md.ifindex;
|
||||
uhdr->bus_id = handlep->bus_index;
|
||||
uhdr->status = 0;
|
||||
string += cnt;
|
||||
|
||||
@@ -609,7 +652,7 @@ got:
|
||||
if (handle->fcode.bf_insns == NULL ||
|
||||
bpf_filter(handle->fcode.bf_insns, handle->buffer,
|
||||
pkth.len, pkth.caplen)) {
|
||||
handle->md.packets_read++;
|
||||
handlep->packets_read++;
|
||||
callback(user, &pkth, handle->buffer);
|
||||
return 1;
|
||||
}
|
||||
@@ -627,13 +670,14 @@ usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
|
||||
static int
|
||||
usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
int dummy, ret, consumed, cnt;
|
||||
char string[USB_LINE_LEN];
|
||||
char token[USB_LINE_LEN];
|
||||
char * ptr = string;
|
||||
int fd;
|
||||
|
||||
snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex);
|
||||
snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
|
||||
fd = open(string, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
@@ -643,7 +687,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
* Not found at the new location; try the old
|
||||
* location.
|
||||
*/
|
||||
snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex);
|
||||
snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
|
||||
fd = open(string, O_RDONLY, 0);
|
||||
}
|
||||
if (fd < 0) {
|
||||
@@ -694,7 +738,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
|
||||
ptr += cnt;
|
||||
}
|
||||
|
||||
stats->ps_recv = handle->md.packets_read;
|
||||
stats->ps_recv = handlep->packets_read;
|
||||
stats->ps_ifdrop = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -710,6 +754,7 @@ usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
|
||||
static int
|
||||
usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
int ret;
|
||||
struct mon_bin_stats st;
|
||||
ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
|
||||
@@ -720,7 +765,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
|
||||
return -1;
|
||||
}
|
||||
|
||||
stats->ps_recv = handle->md.packets_read + st.queued;
|
||||
stats->ps_recv = handlep->packets_read + st.queued;
|
||||
stats->ps_drop = st.dropped;
|
||||
stats->ps_ifdrop = 0;
|
||||
return 0;
|
||||
@@ -733,6 +778,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
|
||||
static int
|
||||
usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
struct mon_bin_get info;
|
||||
int ret;
|
||||
struct pcap_pkthdr pkth;
|
||||
@@ -775,7 +821,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
|
||||
if (handle->fcode.bf_insns == NULL ||
|
||||
bpf_filter(handle->fcode.bf_insns, handle->buffer,
|
||||
pkth.len, pkth.caplen)) {
|
||||
handle->md.packets_read++;
|
||||
handlep->packets_read++;
|
||||
callback(user, &pkth, handle->buffer);
|
||||
return 1;
|
||||
}
|
||||
@@ -791,6 +837,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
|
||||
static int
|
||||
usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
struct mon_bin_mfetch fetch;
|
||||
int32_t vec[VEC_SIZE];
|
||||
struct pcap_pkthdr pkth;
|
||||
@@ -836,7 +883,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
|
||||
nflush = fetch.nfetch;
|
||||
for (i=0; i<fetch.nfetch; ++i) {
|
||||
/* discard filler */
|
||||
hdr = (pcap_usb_header*) &handle->md.mmapbuf[vec[i]];
|
||||
hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
|
||||
if (hdr->event_type == '@')
|
||||
continue;
|
||||
|
||||
@@ -855,14 +902,14 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
|
||||
if (handle->fcode.bf_insns == NULL ||
|
||||
bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
|
||||
pkth.len, pkth.caplen)) {
|
||||
handle->md.packets_read++;
|
||||
handlep->packets_read++;
|
||||
callback(user, &pkth, (u_char*) hdr);
|
||||
packets++;
|
||||
}
|
||||
}
|
||||
|
||||
/* with max_packets <= 0 we stop afer the first chunk*/
|
||||
if ((max_packets <= 0) || (packets == max_packets))
|
||||
/* with max_packets specifying "unlimited" we stop afer the first chunk*/
|
||||
if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -874,10 +921,12 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
|
||||
static void
|
||||
usb_cleanup_linux_mmap(pcap_t* handle)
|
||||
{
|
||||
struct pcap_usb_linux *handlep = handle->priv;
|
||||
|
||||
/* if we have a memory-mapped buffer, unmap it */
|
||||
if (handle->md.mmapbuf != NULL) {
|
||||
munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
|
||||
handle->md.mmapbuf = NULL;
|
||||
if (handlep->mmapbuf != NULL) {
|
||||
munmap(handlep->mmapbuf, handlep->mmapbuflen);
|
||||
handlep->mmapbuf = NULL;
|
||||
}
|
||||
pcap_cleanup_live_common(handle);
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
/*
|
||||
* Prototypes for USB-related functions
|
||||
*/
|
||||
int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *usb_create(const char *device, char *ebuf);
|
||||
int usb_findalldevs(pcap_if_t **alldevsp, char *err_str);
|
||||
pcap_t *usb_create(const char *device, char *ebuf, int *is_ours);
|
||||
|
||||
@@ -71,6 +71,17 @@ static int pcap_setnonblock_win32(pcap_t *, int, char *);
|
||||
/* Equivalent to ntohs(), but a lot faster under Windows */
|
||||
#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
|
||||
|
||||
/*
|
||||
* Private data for capturing on WinPcap devices.
|
||||
*/
|
||||
struct pcap_win {
|
||||
int nonblock;
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
int dag_fcs_bits; /* Number of checksum bits from link layer */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Header that the WinPcap driver associates to the packets.
|
||||
* Once was in bpf.h
|
||||
@@ -165,6 +176,13 @@ pcap_setmintocopy_win32(pcap_t *p, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*return the Adapter for a pcap_t*/
|
||||
static Adapter *
|
||||
pcap_getadapter_win32(pcap_t *p)
|
||||
{
|
||||
return p->adapter;
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
@@ -238,7 +256,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
*/
|
||||
(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
|
||||
bp += Packet_WORDALIGN(caplen + hdrlen);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
p->bp = bp;
|
||||
p->cc = ep - bp;
|
||||
return (n);
|
||||
@@ -253,6 +271,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
static int
|
||||
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
struct pcap_win *pw = p->priv;
|
||||
u_char *dp = NULL;
|
||||
int packet_len = 0, caplen = 0;
|
||||
struct pcap_pkthdr pcap_header;
|
||||
@@ -295,7 +314,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
break;
|
||||
|
||||
/* Increase the number of captured packets */
|
||||
p->md.stat.ps_recv++;
|
||||
pw->stat.ps_recv++;
|
||||
|
||||
/* Find the beginning of the packet */
|
||||
dp = ((u_char *)header) + dag_record_size;
|
||||
@@ -312,7 +331,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
|
||||
case TYPE_ETH:
|
||||
swt = SWAPS(header->wlen);
|
||||
packet_len = swt - (p->md.dag_fcs_bits);
|
||||
packet_len = swt - (pw->dag_fcs_bits);
|
||||
caplen = erf_record_len - dag_record_size - 2;
|
||||
if (caplen > packet_len)
|
||||
{
|
||||
@@ -324,7 +343,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
|
||||
case TYPE_HDLC_POS:
|
||||
swt = SWAPS(header->wlen);
|
||||
packet_len = swt - (p->md.dag_fcs_bits);
|
||||
packet_len = swt - (pw->dag_fcs_bits);
|
||||
caplen = erf_record_len - dag_record_size;
|
||||
if (caplen > packet_len)
|
||||
{
|
||||
@@ -397,7 +416,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
header = (dag_record_t*)((char*)header + erf_record_len);
|
||||
|
||||
/* Stop if the number of packets requested by user has been reached*/
|
||||
if (++n >= cnt && cnt > 0)
|
||||
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
|
||||
{
|
||||
p->bp = (char*)header;
|
||||
p->cc = endofbuf - (char*)header;
|
||||
@@ -457,6 +476,7 @@ pcap_cleanup_win32(pcap_t *p)
|
||||
static int
|
||||
pcap_activate_win32(pcap_t *p)
|
||||
{
|
||||
struct pcap_win *pw = p->priv;
|
||||
NetType type;
|
||||
|
||||
if (p->opt.rfmon) {
|
||||
@@ -622,11 +642,23 @@ pcap_activate_win32(pcap_t *p)
|
||||
|
||||
PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
|
||||
|
||||
/* tell the driver to copy the buffer only if it contains at least 16K */
|
||||
if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
|
||||
if (p-opt.immediate)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
/* tell the driver to copy the buffer as soon as data arrives */
|
||||
if(PacketSetMinToCopy(p->adapter,0)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tell the driver to copy the buffer only if it contains at least 16K */
|
||||
if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -672,13 +704,13 @@ pcap_activate_win32(pcap_t *p)
|
||||
|
||||
/* Set the length of the FCS associated to any packet. This value
|
||||
* will be subtracted to the packet length */
|
||||
p->md.dag_fcs_bits = p->adapter->DagFcsLen;
|
||||
pw->dag_fcs_bits = p->adapter->DagFcsLen;
|
||||
}
|
||||
#else
|
||||
goto bad;
|
||||
#endif /* HAVE_DAG_API */
|
||||
|
||||
PacketSetReadTimeout(p->adapter, p->md.timeout);
|
||||
PacketSetReadTimeout(p->adapter, p->opt.timeout);
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
|
||||
@@ -706,6 +738,7 @@ pcap_activate_win32(pcap_t *p)
|
||||
p->setbuff_op = pcap_setbuff_win32;
|
||||
p->setmode_op = pcap_setmode_win32;
|
||||
p->setmintocopy_op = pcap_setmintocopy_win32;
|
||||
p->getadapter_op = pcap_getadapter_win32;
|
||||
p->cleanup_op = pcap_cleanup_win32;
|
||||
|
||||
return (0);
|
||||
@@ -715,7 +748,7 @@ bad:
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
pcap_create_interface(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
@@ -743,12 +776,12 @@ pcap_create(const char *device, char *ebuf)
|
||||
}
|
||||
|
||||
snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
|
||||
p = pcap_create_common(deviceAscii, ebuf);
|
||||
p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win));
|
||||
free(deviceAscii);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pcap_create_common(device, ebuf);
|
||||
p = pcap_create_common(device, ebuf, sizeof (struct pcap_win));
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
@@ -801,25 +834,26 @@ pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->md.use_bpf = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_getnonblock_win32(pcap_t *p, char *errbuf)
|
||||
{
|
||||
struct pcap_win *pw = p->priv;
|
||||
|
||||
/*
|
||||
* XXX - if there were a PacketGetReadTimeout() call, we
|
||||
* would use it, and return 1 if the timeout is -1
|
||||
* and 0 otherwise.
|
||||
*/
|
||||
return (p->nonblock);
|
||||
return (pw->nonblock);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
struct pcap_win *pw = p->priv;
|
||||
int newtimeout;
|
||||
|
||||
if (nonblock) {
|
||||
@@ -833,14 +867,14 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
|
||||
* (Note that this may be -1, in which case we're not
|
||||
* really leaving non-blocking mode.)
|
||||
*/
|
||||
newtimeout = p->md.timeout;
|
||||
newtimeout = p->opt.timeout;
|
||||
}
|
||||
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"PacketSetReadTimeout: %s", pcap_win32strerror());
|
||||
return (-1);
|
||||
}
|
||||
p->nonblock = (newtimeout == -1);
|
||||
pw->nonblock = (newtimeout == -1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.TH PCAP 3PCAP "4 April 2008"
|
||||
.TH PCAP 3PCAP "1 July 2013"
|
||||
.SH NAME
|
||||
pcap \- Packet Capture library
|
||||
.SH SYNOPSIS
|
||||
@@ -174,9 +174,11 @@ arbitrarily long period of time.
|
||||
.IP
|
||||
Not all platforms support a read timeout; on platforms that
|
||||
don't, the read timeout is ignored. A zero value for the timeout,
|
||||
on platforms that support a read timeout,
|
||||
will cause a read to wait forever to allow enough packets to
|
||||
arrive, with no timeout.
|
||||
on platforms that support a read timeout, has platform-dependent
|
||||
behavior that could cause a read to wait for an unlimited amount
|
||||
of time until the capture buffer fills up or could cause a read timeout
|
||||
of 1 millisecond to be used. We recommend that a value of zero not be
|
||||
used.
|
||||
.IP
|
||||
.BR NOTE :
|
||||
the read timeout cannot be used to cause calls that read
|
||||
@@ -309,6 +311,19 @@ handle, call
|
||||
lists the values it returns and describes the packet formats that
|
||||
correspond to those values.
|
||||
.PP
|
||||
Do
|
||||
.B NOT
|
||||
assume that the packets for a given capture or ``savefile`` will have
|
||||
any given link-layer header type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet. For example, the "any" device on Linux will have a
|
||||
link-layer header type of
|
||||
.B DLT_LINUX_SLL
|
||||
even if all devices on the system at the time the "any" device is opened
|
||||
have some other data link type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet.
|
||||
.PP
|
||||
To obtain the
|
||||
.B "FILE\ *"
|
||||
corresponding to a
|
||||
@@ -510,20 +525,13 @@ number of bytes available from the capture, if the length of the packet
|
||||
is larger than the maximum number of bytes to capture).
|
||||
.RE
|
||||
.PP
|
||||
.BR pcap_next_ex ()
|
||||
supplies that pointer through a pointer argument.
|
||||
.BR pcap_next ()
|
||||
is passed an argument that points to a
|
||||
.I struct pcap_pkthdr
|
||||
structure, and fills it in.
|
||||
.PP
|
||||
The callback is also supplied a
|
||||
.I const u_char
|
||||
pointer to the first
|
||||
.B caplen
|
||||
(as given in the
|
||||
.I struct pcap_pkthdr
|
||||
a pointer to which is passed to the callback routine)
|
||||
mentioned above)
|
||||
bytes of data from the packet. This won't necessarily be the entire
|
||||
packet; to capture the entire packet, you will have to provide a value
|
||||
for
|
||||
@@ -534,10 +542,28 @@ that is sufficiently large to get all of the packet's data - a value of
|
||||
65535 should be sufficient on most if not all networks). When reading
|
||||
from a ``savefile'', the snapshot length specified when the capture was
|
||||
performed will limit the amount of packet data available.
|
||||
.PP
|
||||
.BR pcap_next ()
|
||||
returns that pointer;
|
||||
is passed an argument that points to a
|
||||
.I struct pcap_pkthdr
|
||||
structure, and fills it in with the time stamp and length values for the
|
||||
packet. It returns a
|
||||
.I const u_char
|
||||
to the first
|
||||
.B caplen
|
||||
bytes of the packet on success, and NULL on error.
|
||||
.PP
|
||||
.BR pcap_next_ex ()
|
||||
supplies that pointer through a pointer argument.
|
||||
is passed two pointer arguments, one of which points to a
|
||||
.IR struct pcap_pkthdr *
|
||||
and one of which points to a
|
||||
.IR "const u_char" *.
|
||||
It sets the first pointer to point to a
|
||||
.I struct pcap_pkthdr
|
||||
structure with the time stamp and length values for the packet, and sets
|
||||
the second pointer to point to the first
|
||||
.B caplen
|
||||
bytes of the packet.
|
||||
.PP
|
||||
To force the loop in
|
||||
.BR pcap_dispatch ()
|
||||
|
||||
511
libpcap/pcap.c
511
libpcap/pcap.c
@@ -74,17 +74,56 @@ static const char rcsid[] _U_ =
|
||||
#include "pcap-int.h"
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
#include <dagnew.h>
|
||||
#include <dagapi.h>
|
||||
#include "pcap-dag.h"
|
||||
#endif /* HAVE_DAG_API */
|
||||
|
||||
#ifdef HAVE_SEPTEL_API
|
||||
#include "pcap-septel.h"
|
||||
#endif /* HAVE_SEPTEL_API */
|
||||
|
||||
#ifdef HAVE_SNF_API
|
||||
#include "pcap-snf.h"
|
||||
#endif /* HAVE_SNF_API */
|
||||
|
||||
#ifdef PCAP_SUPPORT_USB
|
||||
#include "pcap-usb-linux.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCAP_SUPPORT_BT
|
||||
#include "pcap-bt-linux.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCAP_SUPPORT_CAN
|
||||
#include "pcap-can-linux.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCAP_SUPPORT_CANUSB
|
||||
#include "pcap-canusb-linux.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCAP_SUPPORT_NETFILTER
|
||||
#include "pcap-netfilter-linux.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCAP_SUPPORT_DBUS
|
||||
#include "pcap-dbus.h"
|
||||
#endif
|
||||
|
||||
int
|
||||
pcap_not_initialized(pcap_t *pcap)
|
||||
pcap_not_initialized(pcap_t *pcap _U_)
|
||||
{
|
||||
/* this means 'not initialized' */
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
Adapter *
|
||||
pcap_no_adapter(pcap_t *pcap _U_)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
|
||||
* a PCAP_ERROR value on an error.
|
||||
@@ -159,7 +198,7 @@ pcap_free_tstamp_types(int *tstamp_type_list)
|
||||
* packet data cannot be guaranteed to be available after the callback
|
||||
* returns, so that a copy must be made.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
|
||||
{
|
||||
struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
|
||||
@@ -195,7 +234,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
|
||||
/* Saves a pointer to the packet headers */
|
||||
*pkt_header= &p->pcap_header;
|
||||
|
||||
if (p->sf.rfile != NULL) {
|
||||
if (p->rfile != NULL) {
|
||||
int status;
|
||||
|
||||
/* We are on an offline capture */
|
||||
@@ -232,6 +271,176 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
|
||||
return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
|
||||
}
|
||||
|
||||
#if defined(DAG_ONLY)
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
return (dag_findalldevs(alldevsp, errbuf));
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *source, char *errbuf)
|
||||
{
|
||||
return (dag_create(source, errbuf));
|
||||
}
|
||||
#elif defined(SEPTEL_ONLY)
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
return (septel_findalldevs(alldevsp, errbuf));
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *source, char *errbuf)
|
||||
{
|
||||
return (septel_create(source, errbuf));
|
||||
}
|
||||
#elif defined(SNF_ONLY)
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
return (snf_findalldevs(alldevsp, errbuf));
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *source, char *errbuf)
|
||||
{
|
||||
return (snf_create(source, errbuf));
|
||||
}
|
||||
#else /* regular pcap */
|
||||
struct capture_source_type {
|
||||
int (*findalldevs_op)(pcap_if_t **, char *);
|
||||
pcap_t *(*create_op)(const char *, char *, int *);
|
||||
} capture_source_types[] = {
|
||||
#ifdef HAVE_DAG_API
|
||||
{ dag_findalldevs, dag_create },
|
||||
#endif
|
||||
#ifdef HAVE_SEPTEL_API
|
||||
{ septel_findalldevs, septel_create },
|
||||
#endif
|
||||
#ifdef HAVE_SNF_API
|
||||
{ snf_findalldevs, snf_create },
|
||||
#endif
|
||||
#ifdef PCAP_SUPPORT_BT
|
||||
{ bt_findalldevs, bt_create },
|
||||
#endif
|
||||
#if PCAP_SUPPORT_CANUSB
|
||||
{ canusb_findalldevs, canusb_create },
|
||||
#endif
|
||||
#ifdef PCAP_SUPPORT_CAN
|
||||
{ can_findalldevs, can_create },
|
||||
#endif
|
||||
#ifdef PCAP_SUPPORT_USB
|
||||
{ usb_findalldevs, usb_create },
|
||||
#endif
|
||||
#ifdef PCAP_SUPPORT_NETFILTER
|
||||
{ netfilter_findalldevs, netfilter_create },
|
||||
#endif
|
||||
#ifdef PCAP_SUPPORT_DBUS
|
||||
{ dbus_findalldevs, dbus_create },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Get a list of all capture sources that are up and that we can open.
|
||||
* Returns -1 on error, 0 otherwise.
|
||||
* The list, as returned through "alldevsp", may be null if no interfaces
|
||||
* were up and could be opened.
|
||||
*/
|
||||
int
|
||||
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Get the list of regular interfaces first.
|
||||
*/
|
||||
if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
|
||||
return (-1); /* failure */
|
||||
|
||||
/*
|
||||
* Add any interfaces that need a platform-specific mechanism
|
||||
* to find.
|
||||
*/
|
||||
if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
|
||||
/*
|
||||
* We had an error; free the list we've been
|
||||
* constructing.
|
||||
*/
|
||||
if (*alldevsp != NULL) {
|
||||
pcap_freealldevs(*alldevsp);
|
||||
*alldevsp = NULL;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask each of the non-local-network-interface capture
|
||||
* source types what interfaces they have.
|
||||
*/
|
||||
for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
|
||||
if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) {
|
||||
/*
|
||||
* We had an error; free the list we've been
|
||||
* constructing.
|
||||
*/
|
||||
if (*alldevsp != NULL) {
|
||||
pcap_freealldevs(*alldevsp);
|
||||
*alldevsp = NULL;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *source, char *errbuf)
|
||||
{
|
||||
size_t i;
|
||||
int is_theirs;
|
||||
pcap_t *p;
|
||||
|
||||
/*
|
||||
* A null source name is equivalent to the "any" device -
|
||||
* which might not be supported on this platform, but
|
||||
* this means that you'll get a "not supported" error
|
||||
* rather than, say, a crash when we try to dereference
|
||||
* the null pointer.
|
||||
*/
|
||||
if (source == NULL)
|
||||
source = "any";
|
||||
|
||||
/*
|
||||
* Try each of the non-local-network-interface capture
|
||||
* source types until we find one that works for this
|
||||
* device or run out of types.
|
||||
*/
|
||||
for (i = 0; capture_source_types[i].create_op != NULL; i++) {
|
||||
is_theirs = 0;
|
||||
p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
|
||||
if (is_theirs) {
|
||||
/*
|
||||
* The device name refers to a device of the
|
||||
* type in question; either it succeeded,
|
||||
* in which case p refers to a pcap_t to
|
||||
* later activate for the device, or it
|
||||
* failed, in which case p is null and we
|
||||
* should return that to report the failure
|
||||
* to create.
|
||||
*/
|
||||
return (p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, try it as a regular network interface.
|
||||
*/
|
||||
return (pcap_create_interface(source, errbuf));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
initialize_ops(pcap_t *p)
|
||||
{
|
||||
@@ -252,6 +461,7 @@ initialize_ops(pcap_t *p)
|
||||
p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
|
||||
p->setmode_op = (setmode_op_t)pcap_not_initialized;
|
||||
p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
|
||||
p->getadapter_op = pcap_no_adapter;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -262,30 +472,65 @@ initialize_ops(pcap_t *p)
|
||||
p->cleanup_op = pcap_cleanup_live_common;
|
||||
|
||||
/*
|
||||
* In most cases, the standard one-short callback can
|
||||
* In most cases, the standard one-shot callback can
|
||||
* be used for pcap_next()/pcap_next_ex().
|
||||
*/
|
||||
p->oneshot_callback = pcap_oneshot;
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create_common(const char *source, char *ebuf)
|
||||
static pcap_t *
|
||||
pcap_alloc_pcap_t(char *ebuf, size_t size)
|
||||
{
|
||||
char *chunk;
|
||||
pcap_t *p;
|
||||
|
||||
p = malloc(sizeof(*p));
|
||||
if (p == NULL) {
|
||||
/*
|
||||
* Allocate a chunk of memory big enough for a pcap_t
|
||||
* plus a structure following it of size "size". The
|
||||
* structure following it is a private data structure
|
||||
* for the routines that handle this pcap_t.
|
||||
*/
|
||||
chunk = malloc(sizeof (pcap_t) + size);
|
||||
if (chunk == NULL) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
|
||||
pcap_strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
memset(chunk, 0, sizeof (pcap_t) + size);
|
||||
|
||||
/*
|
||||
* Get a pointer to the pcap_t at the beginning.
|
||||
*/
|
||||
p = (pcap_t *)chunk;
|
||||
|
||||
#ifndef WIN32
|
||||
p->fd = -1; /* not opened yet */
|
||||
p->selectable_fd = -1;
|
||||
p->send_fd = -1;
|
||||
#endif
|
||||
|
||||
if (size == 0) {
|
||||
/* No private data was requested. */
|
||||
p->priv = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Set the pointer to the private data; that's the structure
|
||||
* of size "size" following the pcap_t.
|
||||
*/
|
||||
p->priv = (void *)(chunk + sizeof (pcap_t));
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create_common(const char *source, char *ebuf, size_t size)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_alloc_pcap_t(ebuf, size);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->opt.source = strdup(source);
|
||||
if (p->opt.source == NULL) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
|
||||
@@ -305,11 +550,14 @@ pcap_create_common(const char *source, char *ebuf)
|
||||
initialize_ops(p);
|
||||
|
||||
/* put in some defaults*/
|
||||
pcap_set_timeout(p, 0);
|
||||
pcap_set_snaplen(p, 65535); /* max packet size */
|
||||
pcap_set_snaplen(p, 65535); /* max packet size */
|
||||
p->opt.timeout = 0; /* no timeout specified */
|
||||
p->opt.buffer_size = 0; /* use the platform's default */
|
||||
p->opt.promisc = 0;
|
||||
p->opt.buffer_size = 0;
|
||||
p->opt.rfmon = 0;
|
||||
p->opt.immediate = 0;
|
||||
p->opt.tstamp_type = -1; /* default to not setting time stamp type */
|
||||
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
|
||||
return (p);
|
||||
}
|
||||
|
||||
@@ -356,7 +604,7 @@ pcap_set_timeout(pcap_t *p, int timeout_ms)
|
||||
{
|
||||
if (pcap_check_activated(p))
|
||||
return (PCAP_ERROR_ACTIVATED);
|
||||
p->md.timeout = timeout_ms;
|
||||
p->opt.timeout = timeout_ms;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -369,32 +617,44 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
|
||||
return (PCAP_ERROR_ACTIVATED);
|
||||
|
||||
/*
|
||||
* If p->tstamp_type_count is 0, we don't support setting
|
||||
* the time stamp type at all.
|
||||
* If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
|
||||
* the default time stamp type is PCAP_TSTAMP_HOST.
|
||||
*/
|
||||
if (p->tstamp_type_count == 0)
|
||||
return (PCAP_ERROR_CANTSET_TSTAMP_TYPE);
|
||||
|
||||
/*
|
||||
* Check whether we claim to support this type of time stamp.
|
||||
*/
|
||||
for (i = 0; i < p->tstamp_type_count; i++) {
|
||||
if (p->tstamp_type_list[i] == tstamp_type) {
|
||||
/*
|
||||
* Yes.
|
||||
*/
|
||||
if (p->tstamp_type_count == 0) {
|
||||
if (tstamp_type == PCAP_TSTAMP_HOST) {
|
||||
p->opt.tstamp_type = tstamp_type;
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check whether we claim to support this type of time stamp.
|
||||
*/
|
||||
for (i = 0; i < p->tstamp_type_count; i++) {
|
||||
if (p->tstamp_type_list[i] == tstamp_type) {
|
||||
/*
|
||||
* Yes.
|
||||
*/
|
||||
p->opt.tstamp_type = tstamp_type;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No. We support setting the time stamp type, but not to this
|
||||
* particular value.
|
||||
* We don't support this type of time stamp.
|
||||
*/
|
||||
return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_set_immediate_mode(pcap_t *p, int immediate)
|
||||
{
|
||||
if (pcap_check_activated(p))
|
||||
return (PCAP_ERROR_ACTIVATED);
|
||||
p->opt.immediate = immediate;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_set_buffer_size(pcap_t *p, int buffer_size)
|
||||
{
|
||||
@@ -404,6 +664,54 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pcap_check_activated(p))
|
||||
return (PCAP_ERROR_ACTIVATED);
|
||||
|
||||
/*
|
||||
* If p->tstamp_precision_count is 0, we only support setting
|
||||
* the time stamp precision to microsecond precision; every
|
||||
* pcap module *MUST* support microsecond precision, even if
|
||||
* it does so by converting the native precision to
|
||||
* microseconds.
|
||||
*/
|
||||
if (p->tstamp_precision_count == 0) {
|
||||
if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
|
||||
p->opt.tstamp_precision = tstamp_precision;
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check whether we claim to support this precision of
|
||||
* time stamp.
|
||||
*/
|
||||
for (i = 0; i < p->tstamp_precision_count; i++) {
|
||||
if (p->tstamp_precision_list[i] == tstamp_precision) {
|
||||
/*
|
||||
* Yes.
|
||||
*/
|
||||
p->opt.tstamp_precision = tstamp_precision;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't support this time stamp precision.
|
||||
*/
|
||||
return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_get_tstamp_precision(pcap_t *p)
|
||||
{
|
||||
return (p->opt.tstamp_precision);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_activate(pcap_t *p)
|
||||
{
|
||||
@@ -491,6 +799,27 @@ fail:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_offline_common(char *ebuf, size_t size)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
p = pcap_alloc_pcap_t(ebuf, size);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
|
||||
p->opt.source = strdup("(savefile)");
|
||||
if (p->opt.source == NULL) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
|
||||
pcap_strerror(errno));
|
||||
free(p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
@@ -513,7 +842,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
register int n;
|
||||
|
||||
for (;;) {
|
||||
if (p->sf.rfile != NULL) {
|
||||
if (p->rfile != NULL) {
|
||||
/*
|
||||
* 0 means EOF, so don't loop if we get 0.
|
||||
*/
|
||||
@@ -529,7 +858,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
}
|
||||
if (n <= 0)
|
||||
return (n);
|
||||
if (cnt > 0) {
|
||||
if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
|
||||
cnt -= n;
|
||||
if (cnt <= 0)
|
||||
return (0);
|
||||
@@ -549,18 +878,24 @@ pcap_breakloop(pcap_t *p)
|
||||
int
|
||||
pcap_datalink(pcap_t *p)
|
||||
{
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->linktype);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_datalink_ext(pcap_t *p)
|
||||
{
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->linktype_ext);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
|
||||
{
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
if (p->dlt_count == 0) {
|
||||
/*
|
||||
* We couldn't fetch the list of DLTs, which means
|
||||
@@ -572,7 +907,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
|
||||
if (*dlt_buffer == NULL) {
|
||||
(void)snprintf(p->errbuf, sizeof(p->errbuf),
|
||||
"malloc: %s", pcap_strerror(errno));
|
||||
return (-1);
|
||||
return (PCAP_ERROR);
|
||||
}
|
||||
**dlt_buffer = p->linktype;
|
||||
return (1);
|
||||
@@ -581,7 +916,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
|
||||
if (*dlt_buffer == NULL) {
|
||||
(void)snprintf(p->errbuf, sizeof(p->errbuf),
|
||||
"malloc: %s", pcap_strerror(errno));
|
||||
return (-1);
|
||||
return (PCAP_ERROR);
|
||||
}
|
||||
(void)memcpy(*dlt_buffer, p->dlt_list,
|
||||
sizeof(**dlt_buffer) * p->dlt_count);
|
||||
@@ -786,6 +1121,7 @@ static struct dlt_choice dlt_choices[] = {
|
||||
DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
|
||||
DLT_CHOICE(DLT_LTALK, "Localtalk"),
|
||||
DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
|
||||
DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
|
||||
DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
|
||||
DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
|
||||
DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
|
||||
@@ -808,6 +1144,7 @@ static struct dlt_choice dlt_choices[] = {
|
||||
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
|
||||
DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
|
||||
DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
|
||||
DLT_CHOICE(DLT_BACNET_MS_TP, "BACnet MS/TP"),
|
||||
DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
|
||||
DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
|
||||
DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
|
||||
@@ -865,6 +1202,7 @@ static struct dlt_choice dlt_choices[] = {
|
||||
DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
|
||||
DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
|
||||
DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
|
||||
DLT_CHOICE(DLT_DBUS, "D-Bus"),
|
||||
DLT_CHOICE_SENTINEL
|
||||
};
|
||||
|
||||
@@ -959,31 +1297,39 @@ pcap_tstamp_type_val_to_description(int tstamp_type)
|
||||
int
|
||||
pcap_snapshot(pcap_t *p)
|
||||
{
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->snapshot);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_is_swapped(pcap_t *p)
|
||||
{
|
||||
return (p->sf.swapped);
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->swapped);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_major_version(pcap_t *p)
|
||||
{
|
||||
return (p->sf.version_major);
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->version_major);
|
||||
}
|
||||
|
||||
int
|
||||
pcap_minor_version(pcap_t *p)
|
||||
{
|
||||
return (p->sf.version_minor);
|
||||
if (!p->activated)
|
||||
return (PCAP_ERROR_NOT_ACTIVATED);
|
||||
return (p->version_minor);
|
||||
}
|
||||
|
||||
FILE *
|
||||
pcap_file(pcap_t *p)
|
||||
{
|
||||
return (p->sf.rfile);
|
||||
return (p->rfile);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -995,7 +1341,7 @@ pcap_fileno(pcap_t *p)
|
||||
if (p->adapter != NULL)
|
||||
return ((int)(DWORD)p->adapter->hFile);
|
||||
else
|
||||
return (-1);
|
||||
return (PCAP_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1022,7 +1368,18 @@ pcap_geterr(pcap_t *p)
|
||||
int
|
||||
pcap_getnonblock(pcap_t *p, char *errbuf)
|
||||
{
|
||||
return (p->getnonblock_op(p, errbuf));
|
||||
int ret;
|
||||
|
||||
ret = p->getnonblock_op(p, errbuf);
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* In case somebody depended on the bug wherein
|
||||
* the error message was put into p->errbuf
|
||||
* by pcap_getnonblock_fd().
|
||||
*/
|
||||
strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1040,7 +1397,7 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
|
||||
|
||||
fdflags = fcntl(p->fd, F_GETFL, 0);
|
||||
if (fdflags == -1) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@@ -1054,7 +1411,18 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
|
||||
int
|
||||
pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||
{
|
||||
return (p->setnonblock_op(p, nonblock, errbuf));
|
||||
int ret;
|
||||
|
||||
ret = p->setnonblock_op(p, nonblock, errbuf);
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* In case somebody depended on the bug wherein
|
||||
* the error message was put into p->errbuf
|
||||
* by pcap_setnonblock_fd().
|
||||
*/
|
||||
strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if !defined(WIN32) && !defined(MSDOS)
|
||||
@@ -1071,7 +1439,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
|
||||
|
||||
fdflags = fcntl(p->fd, F_GETFL, 0);
|
||||
if (fdflags == -1) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@@ -1080,7 +1448,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
|
||||
else
|
||||
fdflags &= ~O_NONBLOCK;
|
||||
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@@ -1172,6 +1540,9 @@ pcap_statustostr(int errnum)
|
||||
|
||||
case PCAP_ERROR_PROMISC_PERM_DENIED:
|
||||
return ("You don't have permission to capture in promiscuous mode on that device");
|
||||
|
||||
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
|
||||
return ("That device doesn't support that time stamp precision");
|
||||
}
|
||||
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
|
||||
return(ebuf);
|
||||
@@ -1269,6 +1640,12 @@ pcap_setmintocopy(pcap_t *p, int size)
|
||||
return (p->setmintocopy_op(p, size));
|
||||
}
|
||||
|
||||
Adapter *
|
||||
pcap_get_adapter(pcap_t *p)
|
||||
{
|
||||
return (p->getadapter_op(p));
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_setmintocopy_dead(pcap_t *p, int size)
|
||||
{
|
||||
@@ -1336,7 +1713,7 @@ pcap_do_addexit(pcap_t *p)
|
||||
void
|
||||
pcap_add_to_pcaps_to_close(pcap_t *p)
|
||||
{
|
||||
p->md.next = pcaps_to_close;
|
||||
p->next = pcaps_to_close;
|
||||
pcaps_to_close = p;
|
||||
}
|
||||
|
||||
@@ -1346,7 +1723,7 @@ pcap_remove_from_pcaps_to_close(pcap_t *p)
|
||||
pcap_t *pc, *prevpc;
|
||||
|
||||
for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
|
||||
prevpc = pc, pc = pc->md.next) {
|
||||
prevpc = pc, pc = pc->next) {
|
||||
if (pc == p) {
|
||||
/*
|
||||
* Found it. Remove it from the list.
|
||||
@@ -1355,12 +1732,12 @@ pcap_remove_from_pcaps_to_close(pcap_t *p)
|
||||
/*
|
||||
* It was at the head of the list.
|
||||
*/
|
||||
pcaps_to_close = pc->md.next;
|
||||
pcaps_to_close = pc->next;
|
||||
} else {
|
||||
/*
|
||||
* It was in the middle of the list.
|
||||
*/
|
||||
prevpc->md.next = pc->md.next;
|
||||
prevpc->next = pc->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1384,6 +1761,11 @@ pcap_cleanup_live_common(pcap_t *p)
|
||||
p->tstamp_type_list = NULL;
|
||||
p->tstamp_type_count = 0;
|
||||
}
|
||||
if (p->tstamp_precision_list != NULL) {
|
||||
free(p->tstamp_precision_list);
|
||||
p->tstamp_precision_list = NULL;
|
||||
p->tstamp_precision_count = 0;
|
||||
}
|
||||
pcap_freecode(&p->fcode);
|
||||
#if !defined(WIN32) && !defined(MSDOS)
|
||||
if (p->fd >= 0) {
|
||||
@@ -1391,7 +1773,6 @@ pcap_cleanup_live_common(pcap_t *p)
|
||||
p->fd = -1;
|
||||
}
|
||||
p->selectable_fd = -1;
|
||||
p->send_fd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1402,16 +1783,26 @@ pcap_cleanup_dead(pcap_t *p _U_)
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_dead(int linktype, int snaplen)
|
||||
pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
switch (precision) {
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_MICRO:
|
||||
case PCAP_TSTAMP_PRECISION_NANO:
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
p = malloc(sizeof(*p));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
memset (p, 0, sizeof(*p));
|
||||
p->snapshot = snaplen;
|
||||
p->linktype = linktype;
|
||||
p->opt.tstamp_precision = precision;
|
||||
p->stats_op = pcap_stats_dead;
|
||||
#ifdef WIN32
|
||||
p->setbuff_op = pcap_setbuff_dead;
|
||||
@@ -1423,6 +1814,13 @@ pcap_open_dead(int linktype, int snaplen)
|
||||
return (p);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_dead(int linktype, int snaplen)
|
||||
{
|
||||
return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
|
||||
PCAP_TSTAMP_PRECISION_MICRO));
|
||||
}
|
||||
|
||||
/*
|
||||
* API compatible with WinPcap's "send a packet" routine - returns -1
|
||||
* on error, 0 otherwise.
|
||||
@@ -1463,10 +1861,10 @@ pcap_close(pcap_t *p)
|
||||
* the packet doesn't pass and non-zero if the packet does pass.
|
||||
*/
|
||||
int
|
||||
pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h,
|
||||
pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
|
||||
const u_char *pkt)
|
||||
{
|
||||
struct bpf_insn *fcode = fp->bf_insns;
|
||||
const struct bpf_insn *fcode = fp->bf_insns;
|
||||
|
||||
if (fcode != NULL)
|
||||
return (bpf_filter(fcode, pkt, h->len, h->caplen));
|
||||
@@ -1528,6 +1926,8 @@ pcap_lib_version(void)
|
||||
strlen(pcap_version_string);
|
||||
full_pcap_version_string =
|
||||
malloc(full_pcap_version_string_len);
|
||||
if (full_pcap_version_string == NULL)
|
||||
return (NULL);
|
||||
sprintf(full_pcap_version_string,
|
||||
pcap_version_string_fmt, wpcap_version_string,
|
||||
pcap_version_string);
|
||||
@@ -1545,7 +1945,8 @@ pcap_lib_version(void)
|
||||
strlen(packet_version_string) +
|
||||
strlen(pcap_version_string);
|
||||
full_pcap_version_string = malloc(full_pcap_version_string_len);
|
||||
|
||||
if (full_pcap_version_string == NULL)
|
||||
return (NULL);
|
||||
sprintf(full_pcap_version_string,
|
||||
pcap_version_string_packet_dll_fmt,
|
||||
wpcap_version_string, packet_version_string,
|
||||
@@ -1574,6 +1975,8 @@ pcap_lib_version (void)
|
||||
sizeof dospfx + strlen(pcap_version_string);
|
||||
full_pcap_version_string =
|
||||
malloc(full_pcap_version_string_len);
|
||||
if (full_pcap_version_string == NULL)
|
||||
return (NULL);
|
||||
strcpy(full_pcap_version_string, dospfx);
|
||||
strcat(full_pcap_version_string, pcap_version_string);
|
||||
}
|
||||
|
||||
@@ -177,11 +177,37 @@ struct bpf_program {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 17 is used for DLT_OLD_PFLOG in OpenBSD;
|
||||
* OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
|
||||
* 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
|
||||
* 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
|
||||
*
|
||||
* It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
|
||||
* as 117 so that pflog captures would use a link-layer header type
|
||||
* value that didn't collide with any other values. On all
|
||||
* platforms other than OpenBSD, we defined DLT_PFLOG as 117,
|
||||
* and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
|
||||
*
|
||||
* OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
|
||||
*
|
||||
* Don't use 17 for anything else.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
|
||||
* Mac OS X; don't use it for anything else. (FreeBSD uses 121,
|
||||
* which collides with DLT_HHDLC, even though it doesn't use 18
|
||||
* for anything and doesn't appear to have ever used it for anything.)
|
||||
*
|
||||
* We define it as 18 on those platforms; it is, unfortunately, used
|
||||
* for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
|
||||
* in general. As the packet format for it, like that for
|
||||
* DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
|
||||
* we don't support printing it in tcpdump except on OSes that
|
||||
* have the relevant header files, so it's not that useful on
|
||||
* other platforms.
|
||||
*/
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||
#define DLT_PFSYNC 18
|
||||
#endif
|
||||
|
||||
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
|
||||
|
||||
/*
|
||||
@@ -312,15 +338,8 @@ struct bpf_program {
|
||||
#define DLT_IPFILTER 116
|
||||
|
||||
/*
|
||||
* OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
|
||||
* in SuSE 6.3, so we can't use 17 for it in capture-file headers.
|
||||
*
|
||||
* XXX: is there a conflict with DLT_PFSYNC 18 as well?
|
||||
* OpenBSD DLT_PFLOG.
|
||||
*/
|
||||
#ifdef __OpenBSD__
|
||||
#define DLT_OLD_PFLOG 17
|
||||
#define DLT_PFSYNC 18
|
||||
#endif
|
||||
#define DLT_PFLOG 117
|
||||
|
||||
/*
|
||||
@@ -342,9 +361,48 @@ struct bpf_program {
|
||||
#define DLT_AIRONET_HEADER 120
|
||||
|
||||
/*
|
||||
* Reserved for Siemens HiPath HDLC.
|
||||
* Sigh.
|
||||
*
|
||||
* This was reserved for Siemens HiPath HDLC on 2002-01-25, as
|
||||
* requested by Tomas Kukosa.
|
||||
*
|
||||
* On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
|
||||
* assigned 121 as DLT_PFSYNC. Its libpcap does DLT_ <-> LINKTYPE_
|
||||
* mapping, so it probably supports capturing on the pfsync device
|
||||
* but not saving the captured data to a pcap file.
|
||||
*
|
||||
* OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
|
||||
* their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
|
||||
* use 18 in pcap files as well.
|
||||
*
|
||||
* NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their
|
||||
* libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry
|
||||
* for DLT_PFSYNC, so it might not be able to write out dump files
|
||||
* with 18 as the link-layer header type. (Earlier versions might
|
||||
* not have done mapping, in which case they'd work the same way
|
||||
* OpenBSD does.)
|
||||
*
|
||||
* Mac OS X defines it as 18, but doesn't appear to use it as of
|
||||
* Mac OS X 10.7.3. Its libpcap does DLT_ <-> LINKTYPE_ mapping.
|
||||
*
|
||||
* We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on
|
||||
* all other platforms. We'll define DLT_HHDLC as 121 on everything
|
||||
* except for FreeBSD; anybody who wants to compile, on FreeBSD, code
|
||||
* that uses DLT_HHDLC is out of luck.
|
||||
*
|
||||
* We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map
|
||||
* it, so that savefiles won't use 121 for PFSYNC - they'll all
|
||||
* use 18. Code that uses pcap_datalink() to determine the link-layer
|
||||
* header type of a savefile won't, when built and run on FreeBSD,
|
||||
* be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC
|
||||
* capture files; code that doesn't, such as the code in Wireshark,
|
||||
* will be able to distinguish between them.
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
#define DLT_PFSYNC 121
|
||||
#else
|
||||
#define DLT_HHDLC 121
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is for RFC 2625 IP-over-Fibre Channel.
|
||||
@@ -542,7 +600,7 @@ struct bpf_program {
|
||||
#define DLT_JUNIPER_MONITOR 164
|
||||
|
||||
/*
|
||||
* Reserved for BACnet MS/TP.
|
||||
* BACnet MS/TP frames.
|
||||
*/
|
||||
#define DLT_BACNET_MS_TP 165
|
||||
|
||||
@@ -1075,13 +1133,98 @@ struct bpf_program {
|
||||
#define DLT_NETANALYZER_TRANSPARENT 241
|
||||
|
||||
/*
|
||||
* IP-over-Infiniband, as specified by RFC 4391.
|
||||
* IP-over-InfiniBand, as specified by RFC 4391.
|
||||
*
|
||||
* Requested by Petr Sumbera <petr.sumbera@oracle.com>.
|
||||
*/
|
||||
#define DLT_IPOIB 242
|
||||
|
||||
#define DLT_MATCHING_MAX 242 /* highest value in the "matching" range */
|
||||
/*
|
||||
* MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
|
||||
*
|
||||
* Requested by Guy Martin <gmsoft@tuxicoman.be>.
|
||||
*/
|
||||
#define DLT_MPEG_2_TS 243
|
||||
|
||||
/*
|
||||
* ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
|
||||
* used by their ng40 protocol tester.
|
||||
*
|
||||
* Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
|
||||
*/
|
||||
#define DLT_NG40 244
|
||||
|
||||
/*
|
||||
* Pseudo-header giving adapter number and flags, followed by an NFC
|
||||
* (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
|
||||
* as specified by NFC Forum Logical Link Control Protocol Technical
|
||||
* Specification LLCP 1.1.
|
||||
*
|
||||
* Requested by Mike Wakerly <mikey@google.com>.
|
||||
*/
|
||||
#define DLT_NFC_LLCP 245
|
||||
|
||||
/*
|
||||
* 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
|
||||
*
|
||||
* DLT_PFSYNC has different values on different platforms, and all of
|
||||
* them collide with something used elsewhere. On platforms that
|
||||
* don't already define it, define it as 245.
|
||||
*/
|
||||
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
|
||||
#define DLT_PFSYNC 246
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Raw InfiniBand packets, starting with the Local Routing Header.
|
||||
*
|
||||
* Requested by Oren Kladnitsky <orenk@mellanox.com>.
|
||||
*/
|
||||
#define DLT_INFINIBAND 247
|
||||
|
||||
/*
|
||||
* SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
|
||||
*
|
||||
* Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
|
||||
*/
|
||||
#define DLT_SCTP 248
|
||||
|
||||
/*
|
||||
* USB packets, beginning with a USBPcap header.
|
||||
*
|
||||
* Requested by Tomasz Mon <desowin@gmail.com>
|
||||
*/
|
||||
#define DLT_USBPCAP 249
|
||||
|
||||
/*
|
||||
* Schweitzer Engineering Laboratories "RTAC" product serial-line
|
||||
* packets.
|
||||
*
|
||||
* Requested by Chris Bontje <chris_bontje@selinc.com>.
|
||||
*/
|
||||
#define DLT_RTAC_SERIAL 250
|
||||
|
||||
/*
|
||||
* Bluetooth Low Energy air interface link-layer packets.
|
||||
*
|
||||
* Requested by Mike Kershaw <dragorn@kismetwireless.net>.
|
||||
*/
|
||||
#define DLT_BLUETOOTH_LE_LL 251
|
||||
|
||||
/*
|
||||
* DLT type for upper-protocol layer PDU saves from wireshark.
|
||||
*
|
||||
* the actual contents are determined by two TAGs stored with each
|
||||
* packet:
|
||||
* EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
|
||||
* original packet.
|
||||
*
|
||||
* EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
|
||||
* that can make sense of the data stored.
|
||||
*/
|
||||
#define DLT_WIRESHARK_UPPER_PDU 252
|
||||
|
||||
#define DLT_MATCHING_MAX 252 /* highest value in the "matching" range */
|
||||
|
||||
/*
|
||||
* DLT and savefile link type values are split into a class and
|
||||
|
||||
@@ -113,12 +113,13 @@ typedef struct pcap_addr pcap_addr_t;
|
||||
* the old file header as well as files with the new file 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_file_header {
|
||||
bpf_u_int32 magic;
|
||||
@@ -253,6 +254,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
|
||||
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
|
||||
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
|
||||
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
|
||||
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
|
||||
|
||||
/*
|
||||
* Warning codes for the pcap API.
|
||||
@@ -279,7 +281,10 @@ int pcap_can_set_rfmon(pcap_t *);
|
||||
int pcap_set_rfmon(pcap_t *, int);
|
||||
int pcap_set_timeout(pcap_t *, int);
|
||||
int pcap_set_tstamp_type(pcap_t *, int);
|
||||
int pcap_set_immediate_mode(pcap_t *, int);
|
||||
int pcap_set_buffer_size(pcap_t *, int);
|
||||
int pcap_set_tstamp_precision(pcap_t *, int);
|
||||
int pcap_get_tstamp_precision(pcap_t *);
|
||||
int pcap_activate(pcap_t *);
|
||||
|
||||
int pcap_list_tstamp_types(pcap_t *, int **);
|
||||
@@ -332,18 +337,34 @@ const char *pcap_tstamp_type_val_to_description(int);
|
||||
#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */
|
||||
#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */
|
||||
|
||||
/*
|
||||
* Time stamp resolution types.
|
||||
* Not all systems and interfaces will necessarily support all of these
|
||||
* resolutions when doing live captures; all of them can be requested
|
||||
* when reading a savefile.
|
||||
*/
|
||||
#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */
|
||||
#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */
|
||||
|
||||
pcap_t *pcap_open_live(const char *, int, int, int, char *);
|
||||
pcap_t *pcap_open_dead(int, int);
|
||||
pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int);
|
||||
pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
|
||||
pcap_t *pcap_open_offline(const char *, char *);
|
||||
#if defined(WIN32)
|
||||
pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
|
||||
pcap_t *pcap_hopen_offline(intptr_t, char *);
|
||||
#if !defined(LIBPCAP_EXPORTS)
|
||||
#define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
|
||||
pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b)
|
||||
#define pcap_fopen_offline(f,b) \
|
||||
pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
|
||||
#else /*LIBPCAP_EXPORTS*/
|
||||
static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
|
||||
static pcap_t *pcap_fopen_offline(FILE *, char *);
|
||||
#endif
|
||||
#else /*WIN32*/
|
||||
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
|
||||
pcap_t *pcap_fopen_offline(FILE *, char *);
|
||||
#endif /*WIN32*/
|
||||
|
||||
@@ -370,8 +391,8 @@ int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
|
||||
int pcap_compile_nopcap(int, int, struct bpf_program *,
|
||||
const char *, int, bpf_u_int32);
|
||||
void pcap_freecode(struct bpf_program *);
|
||||
int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
|
||||
const u_char *);
|
||||
int pcap_offline_filter(const struct bpf_program *,
|
||||
const struct pcap_pkthdr *, const u_char *);
|
||||
int pcap_datalink(pcap_t *);
|
||||
int pcap_datalink_ext(pcap_t *);
|
||||
int pcap_list_datalinks(pcap_t *, int **);
|
||||
@@ -425,6 +446,7 @@ void bpf_dump(const struct bpf_program *, int);
|
||||
int pcap_setbuff(pcap_t *p, int dim);
|
||||
int pcap_setmode(pcap_t *p, int mode);
|
||||
int pcap_setmintocopy(pcap_t *p, int size);
|
||||
Adapter *pcap_get_adapter(pcap_t *p);
|
||||
|
||||
#ifdef WPCAP
|
||||
/* Include file with the wpcap-specific extensions */
|
||||
|
||||
@@ -58,20 +58,15 @@ if the signal interrupted a call reading packets in a live capture,
|
||||
when your signal handler returns after calling pcap_breakloop(), the
|
||||
call will be restarted, and the loop will not terminate until more
|
||||
packets arrive and the call completes.
|
||||
.ft R
|
||||
.PP
|
||||
.ft B
|
||||
Note also that, in a multi-threaded application, if one thread is
|
||||
blocked in
|
||||
.BR pcap_dispatch() ,
|
||||
.BR pcap_loop() ,
|
||||
.BR pcap_next() ,
|
||||
or
|
||||
.BR pcap_next_ex() ,
|
||||
a call to
|
||||
.B pcap_breakloop()
|
||||
in a different thread will not unblock that thread; you will need to use
|
||||
whatever mechanism the OS provides for breaking a thread out of blocking
|
||||
calls in order to unblock the thread, such as thread cancellation in
|
||||
systems that support POSIX threads.
|
||||
blocked in pcap_dispatch(), pcap_loop(), pcap_next(), or pcap_next_ex(),
|
||||
a call to pcap_breakloop() in a different thread will not unblock that
|
||||
thread; you will need to use whatever mechanism the OS provides for
|
||||
breaking a thread out of blocking calls in order to unblock the thread,
|
||||
such as thread cancellation in systems that support POSIX threads.
|
||||
.ft R
|
||||
.PP
|
||||
Note that
|
||||
|
||||
@@ -37,5 +37,34 @@ int pcap_datalink(pcap_t *p);
|
||||
returns the link-layer header type for the live capture or ``savefile''
|
||||
specified by
|
||||
.IR p .
|
||||
.PP
|
||||
It must not be called on a pcap descriptor created by
|
||||
.B pcap_create()
|
||||
that has not yet been activated by
|
||||
.BR pcap_activate() .
|
||||
.PP
|
||||
.I http://www.tcpdump.org/linktypes.html
|
||||
lists the values
|
||||
.B pcap_datalink()
|
||||
can return and describes the packet formats that
|
||||
correspond to those values.
|
||||
.PP
|
||||
Do
|
||||
.B NOT
|
||||
assume that the packets for a given capture or ``savefile`` will have
|
||||
any given link-layer header type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet. For example, the "any" device on Linux will have a
|
||||
link-layer header type of
|
||||
.B DLT_LINUX_SLL
|
||||
even if all devices on the system at the time the "any" device is opened
|
||||
have some other data link type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_datalink()
|
||||
returns the link-layer header type on success and
|
||||
.B PCAP_ERROR_NOT_ACTIVATED
|
||||
if called on a capture handle that has been created but not activated.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
|
||||
|
||||
@@ -37,8 +37,12 @@ const char *pcap_datalink_val_to_description(int dlt);
|
||||
.SH DESCRIPTION
|
||||
.B pcap_datalink_val_to_name()
|
||||
translates a link-layer header type value to the corresponding
|
||||
link-layer header type name. NULL is returned on failure.
|
||||
link-layer header type name.
|
||||
.B NULL
|
||||
is returned on failure.
|
||||
.PP
|
||||
.B pcap_datalink_val_to_description()
|
||||
translates a link-layer header type value to a short description of that
|
||||
link-layer header type. NULL is returned on failure.
|
||||
link-layer header type.
|
||||
.B NULL
|
||||
is returned on failure.
|
||||
|
||||
52
libpcap/pcap_get_tstamp_precision.3pcap.in
Normal file
52
libpcap/pcap_get_tstamp_precision.3pcap.in
Normal file
@@ -0,0 +1,52 @@
|
||||
.\"Copyright (c) 2013, Michal Sekletar
|
||||
.\"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. The names of the authors may not 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.
|
||||
|
||||
.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "27 August 2013"
|
||||
.SH NAME
|
||||
pcap_get_tstamp_precision \- get the time stamp precision returned in
|
||||
captures
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
#include <pcap/pcap.h>
|
||||
.ft
|
||||
.LP
|
||||
.ft B
|
||||
int pcap_get_tstamp_precision(pcap_t *p);
|
||||
.ft
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.B pcap_get_tstamp_precision()
|
||||
returns the precision of the time stamp returned in packet captures on the pcap
|
||||
descriptor.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_get_tstamp_precision()
|
||||
returns
|
||||
.B PCAP_TSTAMP_PRECISION_MICRO
|
||||
or
|
||||
.BR PCAP_TSTAMP_PRECISION_NANO ,
|
||||
which indicates
|
||||
that pcap captures contains time stamps in microseconds or nanoseconds
|
||||
respectively.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP),
|
||||
pcap_set_tstamp_precision(3PCAP),
|
||||
pcap-tstamp(@MAN_MISC_INFO@)
|
||||
@@ -34,9 +34,20 @@ int pcap_is_swapped(pcap_t *p);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.B pcap_is_swapped()
|
||||
returns true if
|
||||
returns true (1) if
|
||||
.I p
|
||||
refers to a ``savefile'' that uses a different byte order
|
||||
than the current system. For a live capture, it always returns false.
|
||||
than the current system. For a live capture, it always returns false
|
||||
(0).
|
||||
.PP
|
||||
It must not be called on a pcap descriptor created by
|
||||
.B pcap_create()
|
||||
that has not yet been activated by
|
||||
.BR pcap_activate() .
|
||||
.SH RETURN VALUE
|
||||
.B pcap_datalink()
|
||||
returns true (1) or false (0) on success and
|
||||
.B PCAP_ERROR_NOT_ACTIVATED
|
||||
if called on a capture handle that has been created but not activated.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP)
|
||||
|
||||
@@ -47,11 +47,22 @@ The caller is responsible for freeing the array with
|
||||
.BR pcap_free_datalinks() ,
|
||||
which frees the list of link-layer header types pointed to by
|
||||
.IR dlt_list .
|
||||
.LP
|
||||
It must not be called on a pcap descriptor created by
|
||||
.B pcap_create()
|
||||
that has not yet been activated by
|
||||
.BR pcap_activate() .
|
||||
.SH RETURN VALUE
|
||||
.B pcap_list_datalinks()
|
||||
returns the number of link-layer header types in the array on success
|
||||
and \-1 on failure.
|
||||
If \-1 is returned,
|
||||
returns the number of link-layer header types in the array on success,
|
||||
.B PCAP_ERROR_NOT_ACTIVATED
|
||||
if called on a capture handle that has been created but not activated,
|
||||
and
|
||||
.B PCAP_ERROR
|
||||
(\-1) on other errors.
|
||||
If
|
||||
.B PCAP_ERROR
|
||||
is returned,
|
||||
.B pcap_geterr()
|
||||
or
|
||||
.B pcap_perror()
|
||||
|
||||
@@ -84,7 +84,7 @@ processed when reading a ``savefile''.
|
||||
\fIcnt\fP
|
||||
was 0 was undefined; different platforms and devices behaved
|
||||
differently, so code that must work with older versions of libpcap
|
||||
should use \-1, nor 0, as the value of
|
||||
should use \-1, not 0, as the value of
|
||||
\fIcnt\fP.)
|
||||
.ft R
|
||||
.PP
|
||||
@@ -115,12 +115,48 @@ and the packet data are not to be freed by the callback routine, and are
|
||||
not guaranteed to be valid after the callback routine returns; if the
|
||||
code needs them to be valid after the callback, it must make a copy of
|
||||
them.
|
||||
.PP
|
||||
The bytes of data from the packet begin with a link-layer header. The
|
||||
format of the link-layer header is indicated by the return value of the
|
||||
.B pcap_datalink()
|
||||
routine when handed the
|
||||
.B pcap_t
|
||||
value also passed to
|
||||
.B pcap_loop()
|
||||
or
|
||||
.BR pcap_dispatch() .
|
||||
.I http://www.tcpdump.org/linktypes.html
|
||||
lists the values
|
||||
.B pcap_datalink()
|
||||
can return and describes the packet formats that
|
||||
correspond to those values. The value it returns will be valid for all
|
||||
packets received unless and until
|
||||
.B pcap_set_datalink()
|
||||
is called; after a successful call to
|
||||
.BR pcap_set_datalink() ,
|
||||
all subsequent packets will have a link-layer header of the type
|
||||
specified by the link-layer header type value passed to
|
||||
.BR pcap_set_datalink() .
|
||||
.PP
|
||||
Do
|
||||
.B NOT
|
||||
assume that the packets for a given capture or ``savefile`` will have
|
||||
any given link-layer header type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet. For example, the "any" device on Linux will have a
|
||||
link-layer header type of
|
||||
.B DLT_LINUX_SLL
|
||||
even if all devices on the system at the time the "any" device is opened
|
||||
have some other data link type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_loop()
|
||||
returns 0 if
|
||||
.I cnt
|
||||
is exhausted, \-1 if an error occurs, or \-2 if the loop terminated due
|
||||
to a call to
|
||||
is exhausted or if, when reading from a ``savefile'', no more packets
|
||||
are available. It returns \-1 if an error occurs or \-2 if the loop
|
||||
terminated due to a call to
|
||||
.B pcap_breakloop()
|
||||
before any packets were processed.
|
||||
It does
|
||||
@@ -154,4 +190,5 @@ may be called with
|
||||
.I p
|
||||
as an argument to fetch or display the error text.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP)
|
||||
pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP),
|
||||
pcap_datalink(3PCAP)
|
||||
|
||||
@@ -77,6 +77,41 @@ The
|
||||
structure pointed to by
|
||||
.I h
|
||||
is filled in with the appropriate values for the packet.
|
||||
.PP
|
||||
The bytes of data from the packet begin with a link-layer header. The
|
||||
format of the link-layer header is indicated by the return value of the
|
||||
.B pcap_datalink()
|
||||
routine when handed the
|
||||
.B pcap_t
|
||||
value also passed to
|
||||
.B pcap_loop()
|
||||
or
|
||||
.BR pcap_dispatch() .
|
||||
.I http://www.tcpdump.org/linktypes.html
|
||||
lists the values
|
||||
.B pcap_datalink()
|
||||
can return and describes the packet formats that
|
||||
correspond to those values. The value it returns will be valid for all
|
||||
packets received unless and until
|
||||
.B pcap_set_datalink()
|
||||
is called; after a successful call to
|
||||
.BR pcap_set_datalink() ,
|
||||
all subsequent packets will have a link-layer header of the type
|
||||
specified by the link-layer header type value passed to
|
||||
.BR pcap_set_datalink() .
|
||||
.PP
|
||||
Do
|
||||
.B NOT
|
||||
assume that the packets for a given capture or ``savefile`` will have
|
||||
any given link-layer header type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet. For example, the "any" device on Linux will have a
|
||||
link-layer header type of
|
||||
.B DLT_LINUX_SLL
|
||||
even if all devices on the system at the time the "any" device is opened
|
||||
have some other data link type, such as
|
||||
.B DLT_EN10MB
|
||||
for Ethernet.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_next_ex()
|
||||
returns 1 if the packet was read without problems, 0
|
||||
@@ -104,4 +139,5 @@ non-blocking mode and no packets were available to be read), or if no
|
||||
more packets are available in a ``savefile.'' Unfortunately, there is
|
||||
no way to determine whether an error occurred or not.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP)
|
||||
pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP),
|
||||
pcap_datalink(3PCAP)
|
||||
|
||||
@@ -29,7 +29,7 @@ pcap_offline_filter \- check whether a filter matches a packet
|
||||
.ft
|
||||
.LP
|
||||
.ft B
|
||||
int pcap_offline_filter(struct bpf_program *fp,
|
||||
int pcap_offline_filter(const struct bpf_program *fp,
|
||||
.ti +8
|
||||
const struct pcap_pkthdr *h, const u_char *pkt)
|
||||
.ft
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.TH PCAP_OPEN_DEAD 3PCAP "5 April 2008"
|
||||
.TH PCAP_OPEN_DEAD 3PCAP "1 July 2013"
|
||||
.SH NAME
|
||||
pcap_open_dead \- open a fake pcap_t for compiling filters or opening a
|
||||
capture for output
|
||||
pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
|
||||
pcap_t for compiling filters or opening a capture for output
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
@@ -31,15 +31,27 @@ capture for output
|
||||
.LP
|
||||
.ft B
|
||||
pcap_t *pcap_open_dead(int linktype, int snaplen);
|
||||
pcap_t *pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
|
||||
u_int precision);
|
||||
.ft
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.B pcap_open_dead()
|
||||
is used for creating a
|
||||
and
|
||||
.B pcap_open_dead_with_tstamp_precision()
|
||||
are used for creating a
|
||||
.B pcap_t
|
||||
structure to use when calling the other functions in libpcap. It is
|
||||
typically used when just using libpcap for compiling BPF code.
|
||||
typically used when just using libpcap for compiling BPF code; it can
|
||||
also be used if using
|
||||
.BR pcap_dump_open() ,
|
||||
.BR pcap_dump() ,
|
||||
and
|
||||
.B pcap_dump_close()
|
||||
to write a savefile if there is no
|
||||
.B pcap_t
|
||||
that supplies the packets to be written.
|
||||
.PP
|
||||
.I linktype
|
||||
specifies the link-layer type for the
|
||||
@@ -48,5 +60,22 @@ specifies the link-layer type for the
|
||||
.I snaplen
|
||||
specifies the snapshot length for the
|
||||
.BR pcap_t .
|
||||
.PP
|
||||
When
|
||||
.BR pcap_open_dead_with_tstamp_precision() ,
|
||||
is used to create a
|
||||
.B pcap_t
|
||||
for use with
|
||||
.BR pcap_dump_open() ,
|
||||
.I precision
|
||||
specifies the time stamp precision for packets;
|
||||
.B PCAP_TSTAMP_PRECISION_MICRO
|
||||
should be specified if the packets to be written have time stamps in
|
||||
seconds and microseconds, and
|
||||
.B PCAP_TSTAMP_PRECISION_NANO
|
||||
should be specified if the packets to be written have time stamps in
|
||||
seconds and nanoseconds. Its value does not affect
|
||||
.BR pcap_compile() .
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
|
||||
pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
|
||||
pcap-linktype(@MAN_MISC_INFO@)
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.TH PCAP_OPEN_OFFLINE 3PCAP "5 April 2008"
|
||||
.TH PCAP_OPEN_OFFLINE 3PCAP "1 July 2013"
|
||||
.SH NAME
|
||||
pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading
|
||||
pcap_open_offline, pcap_open_offline_with_tstamp_precision,
|
||||
pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
@@ -35,12 +36,18 @@ char errbuf[PCAP_ERRBUF_SIZE];
|
||||
.LP
|
||||
.ft B
|
||||
pcap_t *pcap_open_offline(const char *fname, char *errbuf);
|
||||
pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname,
|
||||
u_int precision, char *errbuf);
|
||||
pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
|
||||
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp,
|
||||
u_int precision, char *errbuf);
|
||||
.ft
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.B pcap_open_offline()
|
||||
is called to open a ``savefile'' for reading.
|
||||
and
|
||||
.B pcap_open_offline_with_tstamp_precision()
|
||||
are called to open a ``savefile'' for reading.
|
||||
.PP
|
||||
.I fname
|
||||
specifies the name of the file to open. The file can have the pcap file
|
||||
@@ -55,15 +62,37 @@ be read.
|
||||
The name "-" in a synonym for
|
||||
.BR stdin .
|
||||
.PP
|
||||
.B pcap_open_offline_with_tstamp_precision()
|
||||
takes an additional
|
||||
.I precision
|
||||
argument specifying the time stamp precision desired;
|
||||
if
|
||||
.B PCAP_TSTAMP_PRECISION_MICRO
|
||||
is specified, packet time stamps will be supplied in seconds and
|
||||
microseconds,
|
||||
and if
|
||||
.B PCAP_TSTAMP_PRECISION_NANO
|
||||
is specified, packet time stamps will be supplied in seconds and
|
||||
nanoseconds. If the time stamps in the file do not have the same
|
||||
precision as the requested precision, they will be scaled up or down as
|
||||
necessary before being supplied.
|
||||
.PP
|
||||
Alternatively, you may call
|
||||
.B pcap_fopen_offline()
|
||||
or
|
||||
.B pcap_fopen_offline_with_tstamp_precision()
|
||||
to read dumped data from an existing open stream
|
||||
.IR fp .
|
||||
.B pcap_fopen_offline_with_tstamp_precision() takes an additional
|
||||
.I precision
|
||||
argument as described above.
|
||||
Note that on Windows, that stream should be opened in binary mode.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_open_offline()
|
||||
.BR pcap_open_offline() ,
|
||||
.BR pcap_open_offline_with_tstamp_precision() ,
|
||||
.BR pcap_fopen_offline() ,
|
||||
and
|
||||
.B pcap_fopen_offline()
|
||||
.B pcap_fopen_offline_with_tstamp_precision()
|
||||
return a
|
||||
.I pcap_t *
|
||||
on success and
|
||||
|
||||
47
libpcap/pcap_set_immediate_mode.3pcap
Normal file
47
libpcap/pcap_set_immediate_mode.3pcap
Normal file
@@ -0,0 +1,47 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1994, 1996, 1997
|
||||
.\" 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.
|
||||
.\"
|
||||
.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "8 May 2013"
|
||||
.SH NAME
|
||||
pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
|
||||
handle
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
#include <pcap/pcap.h>
|
||||
.LP
|
||||
.ft B
|
||||
int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
|
||||
.ft
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.B pcap_set_immediate_mode()
|
||||
sets whether immediate mode should be set on a capture handle when
|
||||
the handle is activated.
|
||||
If
|
||||
.I immediate_mode
|
||||
is non-zero, immediate mode will be set, otherwise it will not be set.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_set_immediate_mode()
|
||||
returns 0 on success or
|
||||
.B PCAP_ERROR_ACTIVATED
|
||||
if called on a capture handle that has been activated.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
|
||||
@@ -38,6 +38,9 @@ sets the read timeout that will be used on a capture handle when
|
||||
the handle is activated to
|
||||
.IR to_ms ,
|
||||
which is in units of milliseconds.
|
||||
.LP
|
||||
The behavior, if the timeout isn't specified, is undefined. We
|
||||
recommend always setting the timeout to a non-zero value.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_set_timeout()
|
||||
returns 0 on success or
|
||||
|
||||
61
libpcap/pcap_set_tstamp_precision.3pcap.in
Normal file
61
libpcap/pcap_set_tstamp_precision.3pcap.in
Normal file
@@ -0,0 +1,61 @@
|
||||
.\"Copyright (c) 2013, Michal Sekletar
|
||||
.\"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. The names of the authors may not 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.
|
||||
|
||||
.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "27 August 2013"
|
||||
.SH NAME
|
||||
pcap_set_tstamp_precision \- set the time stamp precision returned in
|
||||
captures
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
#include <pcap/pcap.h>
|
||||
.ft
|
||||
.LP
|
||||
.ft B
|
||||
int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision);
|
||||
.ft
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.B pcap_set_tstamp_precision()
|
||||
sets the precision of the time stamp desired for packets captured on the pcap
|
||||
descriptor to the type specified by
|
||||
.IR tstamp_precision .
|
||||
It must be called on a pcap descriptor created by
|
||||
.B pcap_create()
|
||||
that has not yet been activated by
|
||||
.BR pcap_activate() .
|
||||
Two time stamp precisions are supported, microseconds and nanoseconds. One can
|
||||
use options
|
||||
.B PCAP_TSTAMP_PRECISION_MICRO and
|
||||
.B PCAP_TSTAMP_PRECISION_NANO
|
||||
to request desired precision. By default, time stamps are in microseconds.
|
||||
.SH RETURN VALUE
|
||||
.B pcap_set_tstamp_type()
|
||||
returns 0 on success if the specified time stamp precision is expected to be
|
||||
supported by the operating system,
|
||||
.B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
|
||||
if operating system does not support requested time stamp precision,
|
||||
.B PCAP_ERROR_ACTIVATED
|
||||
if called on a capture handle that has been activated.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP),
|
||||
pcap_get_tstamp_precision(3PCAP),
|
||||
pcap-tstamp(@MAN_MISC_INFO@)
|
||||
@@ -40,5 +40,15 @@ or
|
||||
.B pcap_open_live()
|
||||
was called, for a live capture, or the snapshot length from the capture
|
||||
file, for a ``savefile''.
|
||||
.PP
|
||||
It must not be called on a pcap descriptor created by
|
||||
.B pcap_create()
|
||||
that has not yet been activated by
|
||||
.BR pcap_activate() .
|
||||
.SH RETURN VALUE
|
||||
.B pcap_snapshot()
|
||||
returns the snapshot length on success and
|
||||
.B PCAP_ERROR_NOT_ACTIVATED
|
||||
if called on a capture handle that has been created but not activated.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP)
|
||||
|
||||
@@ -36,10 +36,14 @@ const char *pcap_tstamp_type_val_to_description(int tstamp_type);
|
||||
.SH DESCRIPTION
|
||||
.B pcap_tstamp_type_val_to_name()
|
||||
translates a time stamp type value to the corresponding time stamp type
|
||||
name. NULL is returned on failure.
|
||||
name.
|
||||
.B NULL
|
||||
is returned on failure.
|
||||
.PP
|
||||
.B pcap_tstamp_type_val_to_description()
|
||||
translates a time stamp type value to a short description of that time
|
||||
stamp type. NULL is returned on failure.
|
||||
stamp type.
|
||||
.B NULL
|
||||
is returned on failure.
|
||||
.SH SEE ALSO
|
||||
pcap(3PCAP), pcap_tstamp_type_name_to_val(3PCAP)
|
||||
|
||||
@@ -160,18 +160,19 @@ sf_setdirection(pcap_t *p, pcap_direction_t d)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sf_cleanup(pcap_t *p)
|
||||
{
|
||||
if (p->sf.rfile != stdin)
|
||||
(void)fclose(p->sf.rfile);
|
||||
if (p->rfile != stdin)
|
||||
(void)fclose(p->rfile);
|
||||
if (p->buffer != NULL)
|
||||
free(p->buffer);
|
||||
pcap_freecode(&p->fcode);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_offline(const char *fname, char *errbuf)
|
||||
pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
|
||||
char *errbuf)
|
||||
{
|
||||
FILE *fp;
|
||||
pcap_t *p;
|
||||
@@ -199,7 +200,7 @@ pcap_open_offline(const char *fname, char *errbuf)
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
p = pcap_fopen_offline(fp, errbuf);
|
||||
p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
|
||||
if (p == NULL) {
|
||||
if (fp != stdin)
|
||||
fclose(fp);
|
||||
@@ -207,8 +208,16 @@ pcap_open_offline(const char *fname, char *errbuf)
|
||||
return (p);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_offline(const char *fname, char *errbuf)
|
||||
{
|
||||
return (pcap_open_offline_with_tstamp_precision(fname,
|
||||
PCAP_TSTAMP_PRECISION_MICRO, errbuf));
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
|
||||
pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
|
||||
char *errbuf)
|
||||
{
|
||||
int fd;
|
||||
FILE *file;
|
||||
@@ -227,11 +236,18 @@ pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pcap_fopen_offline(file, errbuf);
|
||||
return pcap_fopen_offline_with_tstamp_precision(file, precision,
|
||||
errbuf);
|
||||
}
|
||||
|
||||
pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
|
||||
{
|
||||
return pcap_hopen_offline_with_tstamp_precision(osfd,
|
||||
PCAP_TSTAMP_PRECISION_MICRO, errbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
|
||||
static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
|
||||
pcap_check_header,
|
||||
pcap_ng_check_header
|
||||
};
|
||||
@@ -242,16 +258,14 @@ static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
|
||||
static
|
||||
#endif
|
||||
pcap_t *
|
||||
pcap_fopen_offline(FILE *fp, char *errbuf)
|
||||
pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
|
||||
char *errbuf)
|
||||
{
|
||||
register pcap_t *p;
|
||||
bpf_u_int32 magic;
|
||||
size_t amt_read;
|
||||
u_int i;
|
||||
|
||||
p = pcap_create_common("(savefile)", errbuf);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Read the first 4 bytes of the file; the network analyzer dump
|
||||
@@ -272,26 +286,23 @@ pcap_fopen_offline(FILE *fp, char *errbuf)
|
||||
(unsigned long)sizeof(magic),
|
||||
(unsigned long)amt_read);
|
||||
}
|
||||
goto bad;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try all file types.
|
||||
*/
|
||||
for (i = 0; i < N_FILE_TYPES; i++) {
|
||||
switch ((*check_headers[i])(p, magic, fp, errbuf)) {
|
||||
|
||||
case -1:
|
||||
p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
|
||||
if (p != NULL) {
|
||||
/* Yup, that's it. */
|
||||
goto found;
|
||||
}
|
||||
if (err) {
|
||||
/*
|
||||
* Error trying to read the header.
|
||||
*/
|
||||
goto bad;
|
||||
|
||||
case 1:
|
||||
/*
|
||||
* Yup, that's it.
|
||||
*/
|
||||
goto found;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,15 +310,13 @@ pcap_fopen_offline(FILE *fp, char *errbuf)
|
||||
* Well, who knows what this mess is....
|
||||
*/
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
|
||||
goto bad;
|
||||
return (NULL);
|
||||
|
||||
found:
|
||||
p->sf.rfile = fp;
|
||||
p->rfile = fp;
|
||||
|
||||
#ifdef PCAP_FDDIPAD
|
||||
/* Padding only needed for live capture fcode */
|
||||
p->fddipad = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(WIN32) && !defined(MSDOS)
|
||||
/*
|
||||
@@ -333,13 +342,26 @@ found:
|
||||
p->setmode_op = sf_setmode;
|
||||
p->setmintocopy_op = sf_setmintocopy;
|
||||
#endif
|
||||
p->cleanup_op = sf_cleanup;
|
||||
|
||||
/*
|
||||
* For offline captures, the standard one-shot callback can
|
||||
* be used for pcap_next()/pcap_next_ex().
|
||||
*/
|
||||
p->oneshot_callback = pcap_oneshot;
|
||||
|
||||
p->activated = 1;
|
||||
|
||||
return (p);
|
||||
bad:
|
||||
free(p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static
|
||||
#endif
|
||||
pcap_t *
|
||||
pcap_fopen_offline(FILE *fp, char *errbuf)
|
||||
{
|
||||
return (pcap_fopen_offline_with_tstamp_precision(fp,
|
||||
PCAP_TSTAMP_PRECISION_MICRO, errbuf));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -375,7 +397,7 @@ pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
return (n);
|
||||
}
|
||||
|
||||
status = p->sf.next_packet_op(p, &h, &data);
|
||||
status = p->next_packet_op(p, &h, &data);
|
||||
if (status) {
|
||||
if (status == 1)
|
||||
return (0);
|
||||
|
||||
4573
libpcap/scanner.c
4573
libpcap/scanner.c
File diff suppressed because it is too large
Load Diff
@@ -209,20 +209,8 @@ vrrp return VRRP;
|
||||
carp return CARP;
|
||||
radio return RADIO;
|
||||
|
||||
ip6 {
|
||||
#ifdef INET6
|
||||
return IPV6;
|
||||
#else
|
||||
bpf_error("%s not supported", yytext);
|
||||
#endif
|
||||
}
|
||||
icmp6 {
|
||||
#ifdef INET6
|
||||
return ICMPV6;
|
||||
#else
|
||||
bpf_error("%s not supported", yytext);
|
||||
#endif
|
||||
}
|
||||
ip6 return IPV6;
|
||||
icmp6 return ICMPV6;
|
||||
ah return AH;
|
||||
esp return ESP;
|
||||
|
||||
@@ -326,10 +314,17 @@ fisu return FISU;
|
||||
lssu return LSSU;
|
||||
lsu return LSSU;
|
||||
msu return MSU;
|
||||
hfisu return HFISU;
|
||||
hlssu return HLSSU;
|
||||
hmsu return HMSU;
|
||||
sio return SIO;
|
||||
opc return OPC;
|
||||
dpc return DPC;
|
||||
sls return SLS;
|
||||
hsio return HSIO;
|
||||
hopc return HOPC;
|
||||
hdpc return HDPC;
|
||||
hsls return HSLS;
|
||||
|
||||
[ \r\n\t] ;
|
||||
[+\-*/:\[\]!<>()&|=] return yytext[0];
|
||||
@@ -340,8 +335,12 @@ sls return SLS;
|
||||
"<<" return LSH;
|
||||
">>" return RSH;
|
||||
${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1);
|
||||
if (yylval.e == NULL)
|
||||
bpf_error("malloc");
|
||||
return AID; }
|
||||
{MAC} { yylval.e = pcap_ether_aton((char *)yytext);
|
||||
if (yylval.e == NULL)
|
||||
bpf_error("malloc");
|
||||
return EID; }
|
||||
{N} { yylval.i = stoi((char *)yytext); return NUM; }
|
||||
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
|
||||
|
||||
@@ -201,6 +201,29 @@ struct block_cursor {
|
||||
bpf_u_int32 block_type;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PASS_THROUGH,
|
||||
SCALE_UP,
|
||||
SCALE_DOWN
|
||||
} tstamp_scale_type_t;
|
||||
|
||||
/*
|
||||
* Per-interface information.
|
||||
*/
|
||||
struct pcap_ng_if {
|
||||
u_int tsresol; /* time stamp resolution */
|
||||
u_int64_t tsoffset; /* time stamp offset */
|
||||
tstamp_scale_type_t scale_type; /* how to scale */
|
||||
};
|
||||
|
||||
struct pcap_ng_sf {
|
||||
u_int user_tsresol; /* time stamp resolution requested by the user */
|
||||
bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
|
||||
bpf_u_int32 ifaces_size; /* size of arrary below */
|
||||
struct pcap_ng_if *ifaces; /* array of interface information */
|
||||
};
|
||||
|
||||
static void pcap_ng_cleanup(pcap_t *p);
|
||||
static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
|
||||
u_char **data);
|
||||
|
||||
@@ -239,7 +262,7 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
|
||||
if (status <= 0)
|
||||
return (status); /* error or EOF */
|
||||
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
bhdr.block_type = SWAPLONG(bhdr.block_type);
|
||||
bhdr.total_length = SWAPLONG(bhdr.total_length);
|
||||
}
|
||||
@@ -346,7 +369,7 @@ get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
opthdr->option_code = SWAPSHORT(opthdr->option_code);
|
||||
opthdr->option_length = SWAPSHORT(opthdr->option_length);
|
||||
}
|
||||
@@ -481,7 +504,7 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
|
||||
}
|
||||
saw_tsoffset = 1;
|
||||
memcpy(tsoffset, optvalue, sizeof(*tsoffset));
|
||||
if (p->sf.swapped)
|
||||
if (p->swapped)
|
||||
*tsoffset = SWAPLL(*tsoffset);
|
||||
break;
|
||||
|
||||
@@ -494,22 +517,151 @@ done:
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
|
||||
{
|
||||
struct pcap_ng_sf *ps;
|
||||
u_int tsresol;
|
||||
u_int64_t tsoffset;
|
||||
|
||||
ps = p->priv;
|
||||
|
||||
/*
|
||||
* Count this interface.
|
||||
*/
|
||||
ps->ifcount++;
|
||||
|
||||
/*
|
||||
* Grow the array of per-interface information as necessary.
|
||||
*/
|
||||
if (ps->ifcount > ps->ifaces_size) {
|
||||
/*
|
||||
* We need to grow the array.
|
||||
*/
|
||||
if (ps->ifaces == NULL) {
|
||||
/*
|
||||
* It's currently empty.
|
||||
*/
|
||||
ps->ifaces_size = 1;
|
||||
ps->ifaces = malloc(sizeof (struct pcap_ng_if));
|
||||
} else {
|
||||
/*
|
||||
* It's not currently empty; double its size.
|
||||
* (Perhaps overkill once we have a lot of interfaces.)
|
||||
*/
|
||||
ps->ifaces_size *= 2;
|
||||
ps->ifaces = realloc(ps->ifaces, ps->ifaces_size * sizeof (struct pcap_ng_if));
|
||||
}
|
||||
if (ps->ifaces == NULL) {
|
||||
/*
|
||||
* We ran out of memory.
|
||||
* Give up.
|
||||
*/
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"out of memory for per-interface information (%u interfaces)",
|
||||
ps->ifcount);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the default time stamp resolution and offset.
|
||||
*/
|
||||
tsresol = 1000000; /* microsecond resolution */
|
||||
tsoffset = 0; /* absolute timestamps */
|
||||
|
||||
/*
|
||||
* Now look for various time stamp options, so we know
|
||||
* how to interpret the time stamps for this interface.
|
||||
*/
|
||||
if (process_idb_options(p, cursor, &tsresol, &tsoffset, errbuf) == -1)
|
||||
return (0);
|
||||
|
||||
ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
|
||||
ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
|
||||
|
||||
/*
|
||||
* Determine whether we're scaling up or down or not
|
||||
* at all for this interface.
|
||||
*/
|
||||
switch (p->opt.tstamp_precision) {
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_MICRO:
|
||||
if (tsresol == 1000000) {
|
||||
/*
|
||||
* The resolution is 1 microsecond,
|
||||
* so we don't have to do scaling.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
|
||||
} else if (tsresol > 1000000) {
|
||||
/*
|
||||
* The resolution is greater than
|
||||
* 1 microsecond, so we have to
|
||||
* scale the timestamps down.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
|
||||
} else {
|
||||
/*
|
||||
* The resolution is less than 1
|
||||
* microsecond, so we have to scale
|
||||
* the timestamps up.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_NANO:
|
||||
if (tsresol == 1000000000) {
|
||||
/*
|
||||
* The resolution is 1 nanosecond,
|
||||
* so we don't have to do scaling.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
|
||||
} else if (tsresol > 1000000000) {
|
||||
/*
|
||||
* The resolution is greater than
|
||||
* 1 nanosecond, so we have to
|
||||
* scale the timestamps down.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
|
||||
} else {
|
||||
/*
|
||||
* The resolution is less than 1
|
||||
* nanosecond, so we have to scale
|
||||
* the timestamps up.
|
||||
*/
|
||||
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether this is a pcap-ng savefile and, if it is, extract the
|
||||
* relevant information from the header.
|
||||
*/
|
||||
int
|
||||
pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
pcap_t *
|
||||
pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
int *err)
|
||||
{
|
||||
size_t amt_read;
|
||||
bpf_u_int32 total_length;
|
||||
bpf_u_int32 byte_order_magic;
|
||||
struct block_header *bhdrp;
|
||||
struct section_header_block *shbp;
|
||||
pcap_t *p;
|
||||
int swapped = 0;
|
||||
struct pcap_ng_sf *ps;
|
||||
int status;
|
||||
struct block_cursor cursor;
|
||||
struct interface_description_block *idbp;
|
||||
|
||||
/*
|
||||
* Assume no read errors.
|
||||
*/
|
||||
*err = 0;
|
||||
|
||||
/*
|
||||
* Check whether the first 4 bytes of the file are the block
|
||||
* type for a pcap-ng savefile.
|
||||
@@ -524,7 +676,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
* this as possibly being a pcap-ng file transferred
|
||||
* between UN*X and Windows in text file format?
|
||||
*/
|
||||
return (0); /* nope */
|
||||
return (NULL); /* nope */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -544,14 +696,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1); /* fail */
|
||||
*err = 1;
|
||||
return (NULL); /* fail */
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly a weird short text file, so just say
|
||||
* "not pcap-ng".
|
||||
*/
|
||||
return (0);
|
||||
return (NULL);
|
||||
}
|
||||
amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
|
||||
if (amt_read < sizeof(byte_order_magic)) {
|
||||
@@ -559,14 +712,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
return (-1); /* fail */
|
||||
*err = 1;
|
||||
return (NULL); /* fail */
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly a weird short text file, so just say
|
||||
* "not pcap-ng".
|
||||
*/
|
||||
return (0);
|
||||
return (NULL);
|
||||
}
|
||||
if (byte_order_magic != BYTE_ORDER_MAGIC) {
|
||||
byte_order_magic = SWAPLONG(byte_order_magic);
|
||||
@@ -574,9 +728,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
/*
|
||||
* Not a pcap-ng file.
|
||||
*/
|
||||
return (0);
|
||||
return (NULL);
|
||||
}
|
||||
p->sf.swapped = 1;
|
||||
swapped = 1;
|
||||
total_length = SWAPLONG(total_length);
|
||||
}
|
||||
|
||||
@@ -588,9 +742,46 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
"Section Header Block in pcap-ng dump file has a length of %u < %lu",
|
||||
total_length,
|
||||
(unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
|
||||
return (-1);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, this is a good pcap-ng file.
|
||||
* Allocate a pcap_t for it.
|
||||
*/
|
||||
p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
|
||||
if (p == NULL) {
|
||||
/* Allocation failed. */
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
p->swapped = swapped;
|
||||
ps = p->priv;
|
||||
|
||||
/*
|
||||
* What precision does the user want?
|
||||
*/
|
||||
switch (precision) {
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_MICRO:
|
||||
ps->user_tsresol = 1000000;
|
||||
break;
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_NANO:
|
||||
ps->user_tsresol = 1000000000;
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"unknown time stamp resolution %u", precision);
|
||||
free(p);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
p->opt.tstamp_precision = precision;
|
||||
|
||||
/*
|
||||
* Allocate a buffer into which to read blocks. We default to
|
||||
* the maximum of:
|
||||
@@ -609,7 +800,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
p->buffer = malloc(p->bufsize);
|
||||
if (p->buffer == NULL) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
|
||||
return (-1);
|
||||
free(p);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -627,7 +820,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
1, errbuf) == -1)
|
||||
goto fail;
|
||||
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/*
|
||||
* Byte-swap the fields we've read.
|
||||
*/
|
||||
@@ -644,15 +837,13 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
shbp->major_version);
|
||||
goto fail;
|
||||
}
|
||||
p->sf.version_major = shbp->major_version;
|
||||
p->sf.version_minor = shbp->minor_version;
|
||||
p->version_major = shbp->major_version;
|
||||
p->version_minor = shbp->minor_version;
|
||||
|
||||
/*
|
||||
* Set the default time stamp resolution and offset.
|
||||
* Save the time stamp resolution the user requested.
|
||||
*/
|
||||
p->sf.tsresol = 1000000; /* microsecond resolution */
|
||||
p->sf.tsscale = 1; /* multiply by 1 to scale to microseconds */
|
||||
p->sf.tsoffset = 0; /* absolute timestamps */
|
||||
p->opt.tstamp_precision = precision;
|
||||
|
||||
/*
|
||||
* Now start looking for an Interface Description Block.
|
||||
@@ -664,7 +855,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
status = read_block(fp, p, &cursor, errbuf);
|
||||
if (status == 0) {
|
||||
/* EOF - no IDB in this file */
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"the capture file has no Interface Description Blocks");
|
||||
goto fail;
|
||||
}
|
||||
@@ -685,42 +876,16 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
idbp->linktype = SWAPSHORT(idbp->linktype);
|
||||
idbp->snaplen = SWAPLONG(idbp->snaplen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count this interface.
|
||||
* Try to add this interface.
|
||||
*/
|
||||
p->sf.ifcount++;
|
||||
|
||||
/*
|
||||
* Now look for various time stamp options, so
|
||||
* we know how to interpret the time stamps.
|
||||
*/
|
||||
if (process_idb_options(p, &cursor, &p->sf.tsresol,
|
||||
&p->sf.tsoffset, errbuf) == -1)
|
||||
if (!add_interface(p, &cursor, errbuf))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Compute the scaling factor to convert the
|
||||
* sub-second part of the time stamp to
|
||||
* microseconds.
|
||||
*/
|
||||
if (p->sf.tsresol > 1000000) {
|
||||
/*
|
||||
* Higher than microsecond resolution;
|
||||
* scale down to microseconds.
|
||||
*/
|
||||
p->sf.tsscale = (p->sf.tsresol / 1000000);
|
||||
} else {
|
||||
/*
|
||||
* Lower than microsecond resolution;
|
||||
* scale up to microseconds.
|
||||
*/
|
||||
p->sf.tsscale = (1000000 / p->sf.tsresol);
|
||||
}
|
||||
goto done;
|
||||
|
||||
case BT_EPB:
|
||||
@@ -731,7 +896,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
* not valid, as we don't know what link-layer
|
||||
* encapsulation the packet has.
|
||||
*/
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"the capture file has a packet block before any Interface Description Blocks");
|
||||
goto fail;
|
||||
|
||||
@@ -749,13 +914,26 @@ done:
|
||||
p->linktype = linktype_to_dlt(idbp->linktype);
|
||||
p->linktype_ext = 0;
|
||||
|
||||
p->sf.next_packet_op = pcap_ng_next_packet;
|
||||
p->next_packet_op = pcap_ng_next_packet;
|
||||
p->cleanup_op = pcap_ng_cleanup;
|
||||
|
||||
return (1);
|
||||
return (p);
|
||||
|
||||
fail:
|
||||
free(ps->ifaces);
|
||||
free(p->buffer);
|
||||
return (-1);
|
||||
free(p);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pcap_ng_cleanup(pcap_t *p)
|
||||
{
|
||||
struct pcap_ng_sf *ps = p->priv;
|
||||
|
||||
free(ps->ifaces);
|
||||
sf_cleanup(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -766,6 +944,7 @@ fail:
|
||||
static int
|
||||
pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
{
|
||||
struct pcap_ng_sf *ps = p->priv;
|
||||
struct block_cursor cursor;
|
||||
int status;
|
||||
struct enhanced_packet_block *epbp;
|
||||
@@ -774,9 +953,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
bpf_u_int32 interface_id = 0xFFFFFFFF;
|
||||
struct interface_description_block *idbp;
|
||||
struct section_header_block *shbp;
|
||||
FILE *fp = p->sf.rfile;
|
||||
u_int tsresol;
|
||||
u_int64_t tsoffset;
|
||||
FILE *fp = p->rfile;
|
||||
u_int64_t t, sec, frac;
|
||||
|
||||
/*
|
||||
@@ -808,7 +985,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/* these were written in opposite byte order */
|
||||
interface_id = SWAPLONG(epbp->interface_id);
|
||||
hdr->caplen = SWAPLONG(epbp->caplen);
|
||||
@@ -843,7 +1020,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/* these were written in opposite byte order */
|
||||
hdr->len = SWAPLONG(spbp->len);
|
||||
} else
|
||||
@@ -873,7 +1050,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/* these were written in opposite byte order */
|
||||
interface_id = SWAPSHORT(pbp->interface_id);
|
||||
hdr->caplen = SWAPLONG(pbp->caplen);
|
||||
@@ -902,7 +1079,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
/*
|
||||
* Byte-swap it if necessary.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
idbp->linktype = SWAPSHORT(idbp->linktype);
|
||||
idbp->snaplen = SWAPLONG(idbp->snaplen);
|
||||
}
|
||||
@@ -929,37 +1106,10 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
}
|
||||
|
||||
/*
|
||||
* Count this interface.
|
||||
* Try to add this interface.
|
||||
*/
|
||||
p->sf.ifcount++;
|
||||
|
||||
/*
|
||||
* Set the default time stamp resolution and offset.
|
||||
*/
|
||||
tsresol = 1000000; /* microsecond resolution */
|
||||
tsoffset = 0; /* absolute timestamps */
|
||||
|
||||
/*
|
||||
* Now look for various time stamp options, to
|
||||
* make sure they're the same.
|
||||
*
|
||||
* XXX - we could, in theory, handle multiple
|
||||
* different resolutions and offsets, but we
|
||||
* don't do so for now.
|
||||
*/
|
||||
if (process_idb_options(p, &cursor, &tsresol, &tsoffset,
|
||||
p->errbuf) == -1)
|
||||
if (!add_interface(p, &cursor, p->errbuf))
|
||||
return (-1);
|
||||
if (tsresol != p->sf.tsresol) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"an interface has a time stamp resolution different from the time stamp resolution of the first interface");
|
||||
return (-1);
|
||||
}
|
||||
if (tsoffset != p->sf.tsoffset) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"an interface has a time stamp offset different from the time stamp offset of the first interface");
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case BT_SHB:
|
||||
@@ -977,7 +1127,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
* the same as that of the previous section.
|
||||
* We'll check for that later.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
shbp->byte_order_magic =
|
||||
SWAPLONG(shbp->byte_order_magic);
|
||||
shbp->major_version =
|
||||
@@ -1034,7 +1184,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
* any IDBs, we'll fail when we see a packet
|
||||
* block.)
|
||||
*/
|
||||
p->sf.ifcount = 0;
|
||||
ps->ifcount = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1049,7 +1199,7 @@ found:
|
||||
/*
|
||||
* Is the interface ID an interface we know?
|
||||
*/
|
||||
if (interface_id >= p->sf.ifcount) {
|
||||
if (interface_id >= ps->ifcount) {
|
||||
/*
|
||||
* Yes. Fail.
|
||||
*/
|
||||
@@ -1062,20 +1212,52 @@ found:
|
||||
/*
|
||||
* Convert the time stamp to a struct timeval.
|
||||
*/
|
||||
sec = t / p->sf.tsresol + p->sf.tsoffset;
|
||||
frac = t % p->sf.tsresol;
|
||||
if (p->sf.tsresol > 1000000) {
|
||||
sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
|
||||
frac = t % ps->ifaces[interface_id].tsresol;
|
||||
switch (ps->ifaces[interface_id].scale_type) {
|
||||
|
||||
case PASS_THROUGH:
|
||||
/*
|
||||
* Higher than microsecond resolution; scale down to
|
||||
* microseconds.
|
||||
* The interface resolution is what the user wants,
|
||||
* so we're done.
|
||||
*/
|
||||
frac /= p->sf.tsscale;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case SCALE_UP:
|
||||
/*
|
||||
* Lower than microsecond resolution; scale up to
|
||||
* microseconds.
|
||||
* The interface resolution is less than what the user
|
||||
* wants; scale up to that resolution.
|
||||
*
|
||||
* XXX - if ps->ifaces[interface_id].tsresol is a power
|
||||
* of 10, we could just multiply by the quotient of
|
||||
* ps->ifaces[interface_id].tsresol and ps->user_tsresol,
|
||||
* as we know that's an integer. That runs less risk of
|
||||
* overflow.
|
||||
*
|
||||
* Is there something clever we could do if
|
||||
* ps->ifaces[interface_id].tsresol is a power of 2?
|
||||
*/
|
||||
frac *= p->sf.tsscale;
|
||||
frac *= ps->ifaces[interface_id].tsresol;
|
||||
frac /= ps->user_tsresol;
|
||||
break;
|
||||
|
||||
case SCALE_DOWN:
|
||||
/*
|
||||
* The interface resolution is greater than what the user
|
||||
* wants; scale down to that resolution.
|
||||
*
|
||||
* XXX - if ps->ifaces[interface_id].tsresol is a power
|
||||
* of 10, we could just divide by the quotient of
|
||||
* ps->user_tsresol and ps->ifaces[interface_id].tsresol,
|
||||
* as we know that's an integer. That runs less risk of
|
||||
* overflow.
|
||||
*
|
||||
* Is there something clever we could do if
|
||||
* ps->ifaces[interface_id].tsresol is a power of 2?
|
||||
*/
|
||||
frac *= ps->user_tsresol;
|
||||
frac /= ps->ifaces[interface_id].tsresol;
|
||||
break;
|
||||
}
|
||||
hdr->ts.tv_sec = sec;
|
||||
hdr->ts.tv_usec = frac;
|
||||
@@ -1087,7 +1269,7 @@ found:
|
||||
if (*data == NULL)
|
||||
return (-1);
|
||||
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/*
|
||||
* Convert pseudo-headers from the byte order of
|
||||
* the host on which the file was saved to our
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef sf_pcap_ng_h
|
||||
#define sf_pcap_ng_h
|
||||
|
||||
extern int pcap_ng_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
|
||||
extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp,
|
||||
u_int precision, char *errbuf, int *err);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -122,26 +122,58 @@ static const char rcsid[] _U_ =
|
||||
|
||||
static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
|
||||
|
||||
/*
|
||||
* Private data for reading pcap savefiles.
|
||||
*/
|
||||
typedef enum {
|
||||
NOT_SWAPPED,
|
||||
SWAPPED,
|
||||
MAYBE_SWAPPED
|
||||
} swapped_type_t;
|
||||
|
||||
typedef enum {
|
||||
PASS_THROUGH,
|
||||
SCALE_UP,
|
||||
SCALE_DOWN
|
||||
} tstamp_scale_type_t;
|
||||
|
||||
struct pcap_sf {
|
||||
size_t hdrsize;
|
||||
swapped_type_t lengths_swapped;
|
||||
tstamp_scale_type_t scale_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* Check whether this is a pcap savefile and, if it is, extract the
|
||||
* relevant information from the header.
|
||||
*/
|
||||
int
|
||||
pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
pcap_t *
|
||||
pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
int *err)
|
||||
{
|
||||
struct pcap_file_header hdr;
|
||||
size_t amt_read;
|
||||
pcap_t *p;
|
||||
int swapped = 0;
|
||||
struct pcap_sf *ps;
|
||||
|
||||
/*
|
||||
* Assume no read errors.
|
||||
*/
|
||||
*err = 0;
|
||||
|
||||
/*
|
||||
* Check whether the first 4 bytes of the file are the magic
|
||||
* number for a pcap savefile, or for a byte-swapped pcap
|
||||
* savefile.
|
||||
*/
|
||||
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
|
||||
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
|
||||
magic != NSEC_TCPDUMP_MAGIC) {
|
||||
magic = SWAPLONG(magic);
|
||||
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
|
||||
return (0); /* nope */
|
||||
p->sf.swapped = 1;
|
||||
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
|
||||
magic != NSEC_TCPDUMP_MAGIC)
|
||||
return (NULL); /* nope */
|
||||
swapped = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -162,13 +194,14 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
(unsigned long)sizeof(hdr),
|
||||
(unsigned long)amt_read);
|
||||
}
|
||||
return (-1);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a byte-swapped capture file, byte-swap the header.
|
||||
*/
|
||||
if (p->sf.swapped) {
|
||||
if (swapped) {
|
||||
hdr.version_major = SWAPSHORT(hdr.version_major);
|
||||
hdr.version_minor = SWAPSHORT(hdr.version_minor);
|
||||
hdr.thiszone = SWAPLONG(hdr.thiszone);
|
||||
@@ -180,16 +213,81 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
if (hdr.version_major < PCAP_VERSION_MAJOR) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"archaic pcap savefile format");
|
||||
return (-1);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
p->sf.version_major = hdr.version_major;
|
||||
p->sf.version_minor = hdr.version_minor;
|
||||
|
||||
/*
|
||||
* OK, this is a good pcap file.
|
||||
* Allocate a pcap_t for it.
|
||||
*/
|
||||
p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
|
||||
if (p == NULL) {
|
||||
/* Allocation failed. */
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
p->swapped = swapped;
|
||||
p->version_major = hdr.version_major;
|
||||
p->version_minor = hdr.version_minor;
|
||||
p->tzoff = hdr.thiszone;
|
||||
p->snapshot = hdr.snaplen;
|
||||
p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
|
||||
p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
|
||||
|
||||
p->sf.next_packet_op = pcap_next_packet;
|
||||
p->next_packet_op = pcap_next_packet;
|
||||
|
||||
ps = p->priv;
|
||||
|
||||
p->opt.tstamp_precision = precision;
|
||||
|
||||
/*
|
||||
* Will we need to scale the timestamps to match what the
|
||||
* user wants?
|
||||
*/
|
||||
switch (precision) {
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_MICRO:
|
||||
if (magic == NSEC_TCPDUMP_MAGIC) {
|
||||
/*
|
||||
* The file has nanoseconds, the user
|
||||
* wants microseconds; scale the
|
||||
* precision down.
|
||||
*/
|
||||
ps->scale_type = SCALE_DOWN;
|
||||
} else {
|
||||
/*
|
||||
* The file has microseconds, the
|
||||
* user wants microseconds; nothing to do.
|
||||
*/
|
||||
ps->scale_type = PASS_THROUGH;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCAP_TSTAMP_PRECISION_NANO:
|
||||
if (magic == NSEC_TCPDUMP_MAGIC) {
|
||||
/*
|
||||
* The file has nanoseconds, the
|
||||
* user wants nanoseconds; nothing to do.
|
||||
*/
|
||||
ps->scale_type = PASS_THROUGH;
|
||||
} else {
|
||||
/*
|
||||
* The file has microoseconds, the user
|
||||
* wants nanoseconds; scale the
|
||||
* precision up.
|
||||
*/
|
||||
ps->scale_type = SCALE_UP;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"unknown time stamp resolution %u", precision);
|
||||
free(p);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We interchanged the caplen and len fields at version 2.3,
|
||||
@@ -205,19 +303,19 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
|
||||
case 2:
|
||||
if (hdr.version_minor < 3)
|
||||
p->sf.lengths_swapped = SWAPPED;
|
||||
ps->lengths_swapped = SWAPPED;
|
||||
else if (hdr.version_minor == 3)
|
||||
p->sf.lengths_swapped = MAYBE_SWAPPED;
|
||||
ps->lengths_swapped = MAYBE_SWAPPED;
|
||||
else
|
||||
p->sf.lengths_swapped = NOT_SWAPPED;
|
||||
ps->lengths_swapped = NOT_SWAPPED;
|
||||
break;
|
||||
|
||||
case 543:
|
||||
p->sf.lengths_swapped = SWAPPED;
|
||||
ps->lengths_swapped = SWAPPED;
|
||||
break;
|
||||
|
||||
default:
|
||||
p->sf.lengths_swapped = NOT_SWAPPED;
|
||||
ps->lengths_swapped = NOT_SWAPPED;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -239,7 +337,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
* data ourselves and read from that buffer in order to
|
||||
* make that work.
|
||||
*/
|
||||
p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
|
||||
ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
|
||||
|
||||
if (p->linktype == DLT_EN10MB) {
|
||||
/*
|
||||
@@ -265,7 +363,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
p->snapshot += 14;
|
||||
}
|
||||
} else
|
||||
p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr);
|
||||
ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
|
||||
|
||||
/*
|
||||
* Allocate a buffer for the packet data.
|
||||
@@ -280,10 +378,14 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
p->buffer = malloc(p->bufsize);
|
||||
if (p->buffer == NULL) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
|
||||
return (-1);
|
||||
free(p);
|
||||
*err = 1;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (1);
|
||||
p->cleanup_op = sf_cleanup;
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -294,8 +396,9 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
|
||||
static int
|
||||
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
{
|
||||
struct pcap_sf *ps = p->priv;
|
||||
struct pcap_sf_patched_pkthdr sf_hdr;
|
||||
FILE *fp = p->sf.rfile;
|
||||
FILE *fp = p->rfile;
|
||||
size_t amt_read;
|
||||
bpf_u_int32 t;
|
||||
|
||||
@@ -306,8 +409,8 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
* unpatched libpcap we only read as many bytes as the regular
|
||||
* header has.
|
||||
*/
|
||||
amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp);
|
||||
if (amt_read != p->sf.hdrsize) {
|
||||
amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
|
||||
if (amt_read != ps->hdrsize) {
|
||||
if (ferror(fp)) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
@@ -317,7 +420,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
if (amt_read != 0) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"truncated dump file; tried to read %lu header bytes, only got %lu",
|
||||
(unsigned long)p->sf.hdrsize,
|
||||
(unsigned long)ps->hdrsize,
|
||||
(unsigned long)amt_read);
|
||||
return (-1);
|
||||
}
|
||||
@@ -326,7 +429,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
}
|
||||
}
|
||||
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/* these were written in opposite byte order */
|
||||
hdr->caplen = SWAPLONG(sf_hdr.caplen);
|
||||
hdr->len = SWAPLONG(sf_hdr.len);
|
||||
@@ -338,8 +441,34 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
|
||||
hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
|
||||
}
|
||||
|
||||
switch (ps->scale_type) {
|
||||
|
||||
case PASS_THROUGH:
|
||||
/*
|
||||
* Just pass the time stamp through.
|
||||
*/
|
||||
break;
|
||||
|
||||
case SCALE_UP:
|
||||
/*
|
||||
* File has microseconds, user wants nanoseconds; convert
|
||||
* it.
|
||||
*/
|
||||
hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
|
||||
break;
|
||||
|
||||
case SCALE_DOWN:
|
||||
/*
|
||||
* File has nanoseconds, user wants microseconds; convert
|
||||
* it.
|
||||
*/
|
||||
hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Swap the caplen and len fields, if necessary. */
|
||||
switch (p->sf.lengths_swapped) {
|
||||
switch (ps->lengths_swapped) {
|
||||
|
||||
case NOT_SWAPPED:
|
||||
break;
|
||||
@@ -430,7 +559,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
}
|
||||
*data = p->buffer;
|
||||
|
||||
if (p->sf.swapped) {
|
||||
if (p->swapped) {
|
||||
/*
|
||||
* Convert pseudo-headers from the byte order of
|
||||
* the host on which the file was saved to our
|
||||
@@ -452,11 +581,11 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
}
|
||||
|
||||
static int
|
||||
sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
|
||||
sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen)
|
||||
{
|
||||
struct pcap_file_header hdr;
|
||||
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
hdr.version_minor = PCAP_VERSION_MINOR;
|
||||
|
||||
@@ -507,7 +636,7 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
|
||||
else
|
||||
setbuf(f, NULL);
|
||||
#endif
|
||||
if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
|
||||
if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
if (f != stdout)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#ifndef sf_pcap_h
|
||||
#define sf_pcap_h
|
||||
|
||||
extern int pcap_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
|
||||
extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp,
|
||||
u_int precision, char *errbuf, int *err);
|
||||
|
||||
#endif
|
||||
|
||||
408
libpcap/tests/valgrindtest.c
Normal file
408
libpcap/tests/valgrindtest.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
|
||||
* 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 lint
|
||||
static const char copyright[] _U_ =
|
||||
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005-08-08 17:50:13 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
/* BSD-flavored OS - use BPF */
|
||||
#define USE_BPF
|
||||
#elif defined(linux)
|
||||
/* Linux - use socket filters */
|
||||
#define USE_SOCKET_FILTERS
|
||||
#else
|
||||
#error "Unknown platform or platform that doesn't support Valgrind"
|
||||
#endif
|
||||
|
||||
#if defined(USE_BPF)
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
/*
|
||||
* Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
|
||||
* native OS version, as we're going to be doing our own ioctls to
|
||||
* make sure that, in the uninitialized-data tests, the filters aren't
|
||||
* checked by libpcap before being handed to BPF.
|
||||
*/
|
||||
#define PCAP_DONT_INCLUDE_PCAP_BPF_H
|
||||
|
||||
#elif defined(USE_SOCKET_FILTERS)
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <pcap.h>
|
||||
#ifndef HAVE___ATTRIBUTE__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
static char *program_name;
|
||||
|
||||
/* Forwards */
|
||||
static void usage(void) __attribute__((noreturn));
|
||||
static void error(const char *, ...)
|
||||
__attribute__((noreturn, format (printf, 1, 2)));
|
||||
static void warning(const char *, ...)
|
||||
__attribute__((format (printf, 1, 2)));
|
||||
|
||||
extern int optind;
|
||||
extern int opterr;
|
||||
extern char *optarg;
|
||||
|
||||
/*
|
||||
* On Windows, we need to open the file in binary mode, so that
|
||||
* we get all the bytes specified by the size we get from "fstat()".
|
||||
* On UNIX, that's not necessary. O_BINARY is defined on Windows;
|
||||
* we define it as 0 if it's not defined, so it does nothing.
|
||||
*/
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
static char *
|
||||
read_infile(char *fname)
|
||||
{
|
||||
register int i, fd, cc;
|
||||
register char *cp;
|
||||
struct stat buf;
|
||||
|
||||
fd = open(fname, O_RDONLY|O_BINARY);
|
||||
if (fd < 0)
|
||||
error("can't open %s: %s", fname, pcap_strerror(errno));
|
||||
|
||||
if (fstat(fd, &buf) < 0)
|
||||
error("can't stat %s: %s", fname, pcap_strerror(errno));
|
||||
|
||||
cp = malloc((u_int)buf.st_size + 1);
|
||||
if (cp == NULL)
|
||||
error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
|
||||
fname, pcap_strerror(errno));
|
||||
cc = read(fd, cp, (u_int)buf.st_size);
|
||||
if (cc < 0)
|
||||
error("read %s: %s", fname, pcap_strerror(errno));
|
||||
if (cc != buf.st_size)
|
||||
error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
|
||||
|
||||
close(fd);
|
||||
/* replace "# comment" with spaces */
|
||||
for (i = 0; i < cc; i++) {
|
||||
if (cp[i] == '#')
|
||||
while (i < cc && cp[i] != '\n')
|
||||
cp[i++] = ' ';
|
||||
}
|
||||
cp[cc] = '\0';
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/* VARARGS */
|
||||
static void
|
||||
error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
(void)fprintf(stderr, "%s: ", program_name);
|
||||
va_start(ap, fmt);
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
if (*fmt) {
|
||||
fmt += strlen(fmt);
|
||||
if (fmt[-1] != '\n')
|
||||
(void)fputc('\n', stderr);
|
||||
}
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* VARARGS */
|
||||
static void
|
||||
warning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
(void)fprintf(stderr, "%s: WARNING: ", program_name);
|
||||
va_start(ap, fmt);
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
if (*fmt) {
|
||||
fmt += strlen(fmt);
|
||||
if (fmt[-1] != '\n')
|
||||
(void)fputc('\n', stderr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy arg vector into a new buffer, concatenating arguments with spaces.
|
||||
*/
|
||||
static char *
|
||||
copy_argv(register char **argv)
|
||||
{
|
||||
register char **p;
|
||||
register u_int len = 0;
|
||||
char *buf;
|
||||
char *src, *dst;
|
||||
|
||||
p = argv;
|
||||
if (*p == 0)
|
||||
return 0;
|
||||
|
||||
while (*p)
|
||||
len += strlen(*p++) + 1;
|
||||
|
||||
buf = (char *)malloc(len);
|
||||
if (buf == NULL)
|
||||
error("copy_argv: malloc");
|
||||
|
||||
p = argv;
|
||||
dst = buf;
|
||||
while ((src = *p++) != NULL) {
|
||||
while ((*dst++ = *src++) != '\0')
|
||||
;
|
||||
dst[-1] = ' ';
|
||||
}
|
||||
dst[-1] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define INSN_COUNT 17
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *cp, *device;
|
||||
int op;
|
||||
int dorfmon, useactivate;
|
||||
char ebuf[PCAP_ERRBUF_SIZE];
|
||||
char *infile;
|
||||
char *cmdbuf;
|
||||
pcap_t *pd;
|
||||
int status = 0;
|
||||
int pcap_fd;
|
||||
#if defined(USE_BPF)
|
||||
struct bpf_program bad_fcode;
|
||||
struct bpf_insn uninitialized[INSN_COUNT];
|
||||
#elif defined(USE_SOCKET_FILTERS)
|
||||
struct sock_fprog bad_fcode;
|
||||
struct sock_filter uninitialized[INSN_COUNT];
|
||||
#endif
|
||||
struct bpf_program fcode;
|
||||
|
||||
device = NULL;
|
||||
dorfmon = 0;
|
||||
useactivate = 0;
|
||||
infile = NULL;
|
||||
|
||||
if ((cp = strrchr(argv[0], '/')) != NULL)
|
||||
program_name = cp + 1;
|
||||
else
|
||||
program_name = argv[0];
|
||||
|
||||
opterr = 0;
|
||||
while ((op = getopt(argc, argv, "aF:i:I")) != -1) {
|
||||
switch (op) {
|
||||
|
||||
case 'a':
|
||||
useactivate = 1;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
infile = optarg;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
device = optarg;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
dorfmon = 1;
|
||||
useactivate = 1; /* required for rfmon */
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
if (device == NULL) {
|
||||
/*
|
||||
* No interface specified; get whatever pcap_lookupdev()
|
||||
* finds.
|
||||
*/
|
||||
device = pcap_lookupdev(ebuf);
|
||||
if (device == NULL) {
|
||||
error("couldn't find interface to use: %s",
|
||||
ebuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (infile != NULL) {
|
||||
/*
|
||||
* Filter specified with "-F" and a file containing
|
||||
* a filter.
|
||||
*/
|
||||
cmdbuf = read_infile(infile);
|
||||
} else {
|
||||
if (optind < argc) {
|
||||
/*
|
||||
* Filter specified with arguments on the
|
||||
* command line.
|
||||
*/
|
||||
cmdbuf = copy_argv(&argv[optind+1]);
|
||||
} else {
|
||||
/*
|
||||
* No filter specified; use an empty string, which
|
||||
* compiles to an "accept all" filter.
|
||||
*/
|
||||
cmdbuf = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (useactivate) {
|
||||
pd = pcap_create(device, ebuf);
|
||||
if (pd == NULL)
|
||||
error("%s: pcap_create() failed: %s", device, ebuf);
|
||||
status = pcap_set_snaplen(pd, 65535);
|
||||
if (status != 0)
|
||||
error("%s: pcap_set_snaplen failed: %s",
|
||||
device, pcap_statustostr(status));
|
||||
status = pcap_set_promisc(pd, 1);
|
||||
if (status != 0)
|
||||
error("%s: pcap_set_promisc failed: %s",
|
||||
device, pcap_statustostr(status));
|
||||
if (dorfmon) {
|
||||
status = pcap_set_rfmon(pd, 1);
|
||||
if (status != 0)
|
||||
error("%s: pcap_set_rfmon failed: %s",
|
||||
device, pcap_statustostr(status));
|
||||
}
|
||||
status = pcap_set_timeout(pd, 1000);
|
||||
if (status != 0)
|
||||
error("%s: pcap_set_timeout failed: %s",
|
||||
device, pcap_statustostr(status));
|
||||
status = pcap_activate(pd);
|
||||
if (status < 0) {
|
||||
/*
|
||||
* pcap_activate() failed.
|
||||
*/
|
||||
error("%s: %s\n(%s)", device,
|
||||
pcap_statustostr(status), pcap_geterr(pd));
|
||||
} else if (status > 0) {
|
||||
/*
|
||||
* pcap_activate() succeeded, but it's warning us
|
||||
* of a problem it had.
|
||||
*/
|
||||
warning("%s: %s\n(%s)", device,
|
||||
pcap_statustostr(status), pcap_geterr(pd));
|
||||
}
|
||||
} else {
|
||||
*ebuf = '\0';
|
||||
pd = pcap_open_live(device, 65535, 1, 1000, ebuf);
|
||||
if (pd == NULL)
|
||||
error("%s", ebuf);
|
||||
else if (*ebuf)
|
||||
warning("%s", ebuf);
|
||||
}
|
||||
|
||||
pcap_fd = pcap_fileno(pd);
|
||||
|
||||
/*
|
||||
* Try setting a filter with an uninitialized bpf_program
|
||||
* structure. This should cause valgrind to report a
|
||||
* problem.
|
||||
*
|
||||
* We don't check for errors, because it could get an
|
||||
* error due to a bad pointer or count.
|
||||
*/
|
||||
#if defined(USE_BPF)
|
||||
ioctl(pcap_fd, BIOCSETF, &bad_fcode);
|
||||
#elif defined(USE_SOCKET_FILTERS)
|
||||
setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
|
||||
sizeof(bad_fcode));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Try setting a filter with an initialized bpf_program
|
||||
* structure that points to an uninitialized program.
|
||||
* That should also cause valgrind to report a problem.
|
||||
*
|
||||
* We don't check for errors, because it could get an
|
||||
* error due to a bad pointer or count.
|
||||
*/
|
||||
#if defined(USE_BPF)
|
||||
bad_fcode.bf_len = INSN_COUNT;
|
||||
bad_fcode.bf_insns = uninitialized;
|
||||
ioctl(pcap_fd, BIOCSETF, &bad_fcode);
|
||||
#elif defined(USE_SOCKET_FILTERS)
|
||||
bad_fcode.len = INSN_COUNT;
|
||||
bad_fcode.filter = uninitialized;
|
||||
setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
|
||||
sizeof(bad_fcode));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now compile a filter and set the filter with that.
|
||||
* That should *not* cause valgrind to report a
|
||||
* problem.
|
||||
*/
|
||||
if (pcap_compile(pd, &fcode, cmdbuf, 1, 0) < 0)
|
||||
error("can't compile filter: %s", pcap_geterr(pd));
|
||||
if (pcap_setfilter(pd, &fcode) < 0)
|
||||
error("can't set filter: %s", pcap_geterr(pd));
|
||||
|
||||
pcap_close(pd);
|
||||
exit(status < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s, with %s\n", program_name,
|
||||
pcap_lib_version());
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-aI] [ -F file ] [ -I interface ] [ expression ]\n",
|
||||
program_name);
|
||||
exit(1);
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
/* A Bison parser, made by GNU Bison 2.5. */
|
||||
/* A Bison parser, made by GNU Bison 3.0.2. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
@@ -26,129 +26,144 @@
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
#ifndef YY_PCAP_Y_TAB_H_INCLUDED
|
||||
# define YY_PCAP_Y_TAB_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int pcap_debug;
|
||||
#endif
|
||||
|
||||
/* Tokens. */
|
||||
/* Token type. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
DST = 258,
|
||||
SRC = 259,
|
||||
HOST = 260,
|
||||
GATEWAY = 261,
|
||||
NET = 262,
|
||||
NETMASK = 263,
|
||||
PORT = 264,
|
||||
PORTRANGE = 265,
|
||||
LESS = 266,
|
||||
GREATER = 267,
|
||||
PROTO = 268,
|
||||
PROTOCHAIN = 269,
|
||||
CBYTE = 270,
|
||||
ARP = 271,
|
||||
RARP = 272,
|
||||
IP = 273,
|
||||
SCTP = 274,
|
||||
TCP = 275,
|
||||
UDP = 276,
|
||||
ICMP = 277,
|
||||
IGMP = 278,
|
||||
IGRP = 279,
|
||||
PIM = 280,
|
||||
VRRP = 281,
|
||||
CARP = 282,
|
||||
ATALK = 283,
|
||||
AARP = 284,
|
||||
DECNET = 285,
|
||||
LAT = 286,
|
||||
SCA = 287,
|
||||
MOPRC = 288,
|
||||
MOPDL = 289,
|
||||
TK_BROADCAST = 290,
|
||||
TK_MULTICAST = 291,
|
||||
NUM = 292,
|
||||
INBOUND = 293,
|
||||
OUTBOUND = 294,
|
||||
PF_IFNAME = 295,
|
||||
PF_RSET = 296,
|
||||
PF_RNR = 297,
|
||||
PF_SRNR = 298,
|
||||
PF_REASON = 299,
|
||||
PF_ACTION = 300,
|
||||
TYPE = 301,
|
||||
SUBTYPE = 302,
|
||||
DIR = 303,
|
||||
ADDR1 = 304,
|
||||
ADDR2 = 305,
|
||||
ADDR3 = 306,
|
||||
ADDR4 = 307,
|
||||
RA = 308,
|
||||
TA = 309,
|
||||
LINK = 310,
|
||||
GEQ = 311,
|
||||
LEQ = 312,
|
||||
NEQ = 313,
|
||||
ID = 314,
|
||||
EID = 315,
|
||||
HID = 316,
|
||||
HID6 = 317,
|
||||
AID = 318,
|
||||
LSH = 319,
|
||||
RSH = 320,
|
||||
LEN = 321,
|
||||
IPV6 = 322,
|
||||
ICMPV6 = 323,
|
||||
AH = 324,
|
||||
ESP = 325,
|
||||
VLAN = 326,
|
||||
MPLS = 327,
|
||||
PPPOED = 328,
|
||||
PPPOES = 329,
|
||||
ISO = 330,
|
||||
ESIS = 331,
|
||||
CLNP = 332,
|
||||
ISIS = 333,
|
||||
L1 = 334,
|
||||
L2 = 335,
|
||||
IIH = 336,
|
||||
LSP = 337,
|
||||
SNP = 338,
|
||||
CSNP = 339,
|
||||
PSNP = 340,
|
||||
STP = 341,
|
||||
IPX = 342,
|
||||
NETBEUI = 343,
|
||||
LANE = 344,
|
||||
LLC = 345,
|
||||
METAC = 346,
|
||||
BCC = 347,
|
||||
SC = 348,
|
||||
ILMIC = 349,
|
||||
OAMF4EC = 350,
|
||||
OAMF4SC = 351,
|
||||
OAM = 352,
|
||||
OAMF4 = 353,
|
||||
CONNECTMSG = 354,
|
||||
METACONNECT = 355,
|
||||
VPI = 356,
|
||||
VCI = 357,
|
||||
RADIO = 358,
|
||||
FISU = 359,
|
||||
LSSU = 360,
|
||||
MSU = 361,
|
||||
SIO = 362,
|
||||
OPC = 363,
|
||||
DPC = 364,
|
||||
SLS = 365,
|
||||
AND = 366,
|
||||
OR = 367,
|
||||
UMINUS = 368
|
||||
};
|
||||
enum yytokentype
|
||||
{
|
||||
DST = 258,
|
||||
SRC = 259,
|
||||
HOST = 260,
|
||||
GATEWAY = 261,
|
||||
NET = 262,
|
||||
NETMASK = 263,
|
||||
PORT = 264,
|
||||
PORTRANGE = 265,
|
||||
LESS = 266,
|
||||
GREATER = 267,
|
||||
PROTO = 268,
|
||||
PROTOCHAIN = 269,
|
||||
CBYTE = 270,
|
||||
ARP = 271,
|
||||
RARP = 272,
|
||||
IP = 273,
|
||||
SCTP = 274,
|
||||
TCP = 275,
|
||||
UDP = 276,
|
||||
ICMP = 277,
|
||||
IGMP = 278,
|
||||
IGRP = 279,
|
||||
PIM = 280,
|
||||
VRRP = 281,
|
||||
CARP = 282,
|
||||
ATALK = 283,
|
||||
AARP = 284,
|
||||
DECNET = 285,
|
||||
LAT = 286,
|
||||
SCA = 287,
|
||||
MOPRC = 288,
|
||||
MOPDL = 289,
|
||||
TK_BROADCAST = 290,
|
||||
TK_MULTICAST = 291,
|
||||
NUM = 292,
|
||||
INBOUND = 293,
|
||||
OUTBOUND = 294,
|
||||
PF_IFNAME = 295,
|
||||
PF_RSET = 296,
|
||||
PF_RNR = 297,
|
||||
PF_SRNR = 298,
|
||||
PF_REASON = 299,
|
||||
PF_ACTION = 300,
|
||||
TYPE = 301,
|
||||
SUBTYPE = 302,
|
||||
DIR = 303,
|
||||
ADDR1 = 304,
|
||||
ADDR2 = 305,
|
||||
ADDR3 = 306,
|
||||
ADDR4 = 307,
|
||||
RA = 308,
|
||||
TA = 309,
|
||||
LINK = 310,
|
||||
GEQ = 311,
|
||||
LEQ = 312,
|
||||
NEQ = 313,
|
||||
ID = 314,
|
||||
EID = 315,
|
||||
HID = 316,
|
||||
HID6 = 317,
|
||||
AID = 318,
|
||||
LSH = 319,
|
||||
RSH = 320,
|
||||
LEN = 321,
|
||||
IPV6 = 322,
|
||||
ICMPV6 = 323,
|
||||
AH = 324,
|
||||
ESP = 325,
|
||||
VLAN = 326,
|
||||
MPLS = 327,
|
||||
PPPOED = 328,
|
||||
PPPOES = 329,
|
||||
ISO = 330,
|
||||
ESIS = 331,
|
||||
CLNP = 332,
|
||||
ISIS = 333,
|
||||
L1 = 334,
|
||||
L2 = 335,
|
||||
IIH = 336,
|
||||
LSP = 337,
|
||||
SNP = 338,
|
||||
CSNP = 339,
|
||||
PSNP = 340,
|
||||
STP = 341,
|
||||
IPX = 342,
|
||||
NETBEUI = 343,
|
||||
LANE = 344,
|
||||
LLC = 345,
|
||||
METAC = 346,
|
||||
BCC = 347,
|
||||
SC = 348,
|
||||
ILMIC = 349,
|
||||
OAMF4EC = 350,
|
||||
OAMF4SC = 351,
|
||||
OAM = 352,
|
||||
OAMF4 = 353,
|
||||
CONNECTMSG = 354,
|
||||
METACONNECT = 355,
|
||||
VPI = 356,
|
||||
VCI = 357,
|
||||
RADIO = 358,
|
||||
FISU = 359,
|
||||
LSSU = 360,
|
||||
MSU = 361,
|
||||
HFISU = 362,
|
||||
HLSSU = 363,
|
||||
HMSU = 364,
|
||||
SIO = 365,
|
||||
OPC = 366,
|
||||
DPC = 367,
|
||||
SLS = 368,
|
||||
HSIO = 369,
|
||||
HOPC = 370,
|
||||
HDPC = 371,
|
||||
HSLS = 372,
|
||||
OR = 373,
|
||||
AND = 374,
|
||||
UMINUS = 375
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define DST 258
|
||||
@@ -255,23 +270,27 @@
|
||||
#define FISU 359
|
||||
#define LSSU 360
|
||||
#define MSU 361
|
||||
#define SIO 362
|
||||
#define OPC 363
|
||||
#define DPC 364
|
||||
#define SLS 365
|
||||
#define AND 366
|
||||
#define OR 367
|
||||
#define UMINUS 368
|
||||
|
||||
|
||||
|
||||
#define HFISU 362
|
||||
#define HLSSU 363
|
||||
#define HMSU 364
|
||||
#define SIO 365
|
||||
#define OPC 366
|
||||
#define DPC 367
|
||||
#define SLS 368
|
||||
#define HSIO 369
|
||||
#define HOPC 370
|
||||
#define HDPC 371
|
||||
#define HSLS 372
|
||||
#define OR 373
|
||||
#define AND 374
|
||||
#define UMINUS 375
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 242 "grammar.y"
|
||||
#line 242 "grammar.y" /* yacc.c:1909 */
|
||||
|
||||
int i;
|
||||
bpf_u_int32 h;
|
||||
@@ -287,16 +306,15 @@ typedef union YYSTYPE
|
||||
} blk;
|
||||
struct block *rblk;
|
||||
|
||||
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 294 "y.tab.h"
|
||||
} YYSTYPE;
|
||||
#line 310 "y.tab.h" /* yacc.c:1909 */
|
||||
};
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
|
||||
extern YYSTYPE pcap_lval;
|
||||
|
||||
int pcap_parse (void);
|
||||
|
||||
#endif /* !YY_PCAP_Y_TAB_H_INCLUDED */
|
||||
|
||||
@@ -27,12 +27,6 @@ o Look into moving our Mac building/testing system into a virtual
|
||||
developers can access it and nobody has to keep a stack of Mac Minis
|
||||
in their closet.
|
||||
|
||||
o We should probably update our included libpcap. We currently
|
||||
include version 1.2.1 (we upgraded to that in April 2012) while the
|
||||
latest version on tcpdump.org is 1.5.2. We make minor changes to
|
||||
libpcap that we ship, and instructions for upgrading are in
|
||||
libpcap/NMAP_MODIFICATIONS.
|
||||
|
||||
o The XML version of Nmap lists and describes the six port states
|
||||
recognized by Nmap near the top of the "Port Scanning Basics"
|
||||
section. That can be seen in the HTML rendering at
|
||||
@@ -826,6 +820,12 @@ o random tip database
|
||||
|
||||
DONE:
|
||||
|
||||
o We should probably update our included libpcap. We currently
|
||||
include version 1.2.1 (we upgraded to that in April 2012) while the
|
||||
latest version on tcpdump.org is 1.5.3. We make minor changes to
|
||||
libpcap that we ship, and instructions for upgrading are in
|
||||
libpcap/NMAP_MODIFICATIONS.
|
||||
|
||||
o Investigate report of Nmap ARP discovery using the wrong target MAC
|
||||
address field in ARP requests (it is correct in the ethernet frame
|
||||
itself). See this thread: http://seclists.org/nmap-dev/2011/q3/547
|
||||
|
||||
Reference in New Issue
Block a user