From 25e9d9025668dc638fcd171e43bbf9cd2895ea31 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 25 Apr 2009 03:30:10 +0000 Subject: [PATCH] pcap: update to version 1.0.0, add extension for changing the desired protocol for the internal raw socket (useful for reducing the cpu overhead of capture) SVN-Revision: 15398 --- package/libpcap/Makefile | 36 +- ...-lib.patch => 100-debian_shared_lib.patch} | 108 ++-- .../patches/101-cross-compile-fix.patch | 11 - .../patches/101-debian_fix_any_intf.patch | 149 ++++++ package/libpcap/patches/102-alt-ether.patch | 38 -- package/libpcap/patches/102-fix_install.patch | 11 + .../libpcap/patches/103-flex_workaround.patch | 4 +- .../libpcap/patches/104-no_rej_files.patch | 469 ------------------ .../patches/105-space_optimization.patch | 102 ++-- .../libpcap/patches/106-protocol_api.patch | 141 ++++++ 10 files changed, 464 insertions(+), 605 deletions(-) rename package/libpcap/patches/{100-shared-lib.patch => 100-debian_shared_lib.patch} (56%) delete mode 100644 package/libpcap/patches/101-cross-compile-fix.patch create mode 100644 package/libpcap/patches/101-debian_fix_any_intf.patch delete mode 100644 package/libpcap/patches/102-alt-ether.patch create mode 100644 package/libpcap/patches/102-fix_install.patch delete mode 100644 package/libpcap/patches/104-no_rej_files.patch create mode 100644 package/libpcap/patches/106-protocol_api.patch diff --git a/package/libpcap/Makefile b/package/libpcap/Makefile index 7414195d95..bc6417d0e5 100644 --- a/package/libpcap/Makefile +++ b/package/libpcap/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libpcap -PKG_VERSION:=0.9.8 +PKG_VERSION:=1.0.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.tcpdump.org/release/ -PKG_MD5SUM:=5208f24d0328ee7c20b52c43eaa9aa0e +PKG_MD5SUM:=9ad1358c5dec48456405eac197a46d3d include $(INCLUDE_DIR)/package.mk @@ -29,6 +29,21 @@ define Package/libpcap/description packet capture. endef +define Package/libpcap/config + config PCAP_HAS_USB + bool "Include USB support" + depends PACKAGE_libpcap + depends PACKAGE_kmod-usb-core + default n + + config PCAP_HAS_BT + bool "Include bluetooth support" + depends PACKAGE_libpcap + depends PACKAGE_kmod-bluetooth + default n + +endef + TARGET_CFLAGS += \ -ffunction-sections -fdata-sections @@ -38,9 +53,15 @@ CONFIGURE_ARGS += \ --disable-yydebug \ --enable-ipv6 \ --with-build-cc="$(HOSTCC)" \ - --with-pcap=linux + --with-pcap=linux \ + --without-septel \ + --without-dag define Build/Compile + rm -rf $(PKG_INSTALL_DIR) + $(if $(CONFIG_PCAP_HAS_USB),,$(SED) '/^#define PCAP_SUPPORT_USB/D' $(PKG_BUILD_DIR)/config.h) + $(if $(CONFIG_PCAP_HAS_USB),,$(SED) 's/pcap-usb-linux.c *//' $(PKG_BUILD_DIR)/Makefile) + $(if $(CONFIG_PCAP_HAS_BT),,$(SED) '/^#define PCAP_SUPPORT_BT/D' $(PKG_BUILD_DIR)/config.h) $(MAKE) -C $(PKG_BUILD_DIR) \ CCOPT="$(TARGET_CFLAGS) -I$(BUILD_DIR)/linux/include" \ DESTDIR="$(PKG_INSTALL_DIR)" \ @@ -48,11 +69,12 @@ define Build/Compile endef define Build/InstallDev - mkdir -p $(1)/usr/include - $(CP) $(PKG_INSTALL_DIR)/usr/include/pcap{,-bpf,-namedb}.h \ + mkdir -p $(1)/usr/include $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/pcap* \ $(1)/usr/include/ - mkdir -p $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcap.{a,so*} \ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libpcap.{a,so*} \ $(1)/usr/lib/ endef diff --git a/package/libpcap/patches/100-shared-lib.patch b/package/libpcap/patches/100-debian_shared_lib.patch similarity index 56% rename from package/libpcap/patches/100-shared-lib.patch rename to package/libpcap/patches/100-debian_shared_lib.patch index aae77f8e72..76d3729ef9 100644 --- a/package/libpcap/patches/100-shared-lib.patch +++ b/package/libpcap/patches/100-debian_shared_lib.patch @@ -1,22 +1,29 @@ +Debian-specific modifications to the upstream Makefile.in to +build a shared library. +--- + Makefile.in | 45 ++++++++++++++++++++++++++++++++++++++++++--- + configure | 2 +- + configure.in | 2 +- + 3 files changed, 44 insertions(+), 5 deletions(-) + --- a/Makefile.in +++ b/Makefile.in -@@ -37,6 +37,15 @@ +@@ -40,6 +40,14 @@ mandir = @mandir@ srcdir = @srcdir@ VPATH = @srcdir@ +# some defines for shared library compilation -+MAJ=0.9 -+MIN=8 -+VERSION=$(MAJ).$(MIN) ++MAJ=1.0 ++LIBVERSION=$(MAJ).0 +LIBNAME=pcap +LIBRARY=lib$(LIBNAME).a +SOLIBRARY=lib$(LIBNAME).so -+SHAREDLIB=$(SOLIBRARY).$(VERSION) ++SHAREDLIB=$(SOLIBRARY).$(LIBVERSION) + # # You shouldn't need to edit anything below. # -@@ -52,6 +61,7 @@ +@@ -56,6 +64,7 @@ PROG=libpcap # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) @@ -24,41 +31,49 @@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ -@@ -72,7 +82,12 @@ +@@ -75,7 +84,11 @@ YACC = @V_YACC@ + # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ - $(CC) $(CFLAGS) -c $(srcdir)/$*.c +- $(CC) $(CFLAGS) -c $(srcdir)/$*.c + $(CC) $(CFLAGS) -c -o $@ $(srcdir)/$*.c - ++ +%_pic.o: %.c + @rm -f $@ + $(CC) -fPIC $(CFLAGS) -c -o $@ $(srcdir)/$*.c -+ - PSRC = pcap-@V_PCAP@.c + + PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ FSRC = fad-@V_FINDALLDEVS@.c - SSRC = @SSRC@ -@@ -86,6 +101,7 @@ +@@ -90,6 +103,7 @@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $( # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) +OBJ_PIC = $(PSRC:.c=_pic.o) $(FSRC:.c=_pic.o) $(CSRC:.c=_pic.o) $(SSRC:.c=_pic.o) $(GENSRC:.c=_pic.o) - HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \ - ethertype.h gencode.h gnuc.h - GENHDR = \ -@@ -97,15 +113,23 @@ + HDR = \ + acconfig.h \ + arcnet.h \ +@@ -122,7 +136,8 @@ TAGHDR = \ TAGFILES = \ $(SRC) $(HDR) $(TAGHDR) -CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c -+CLEANFILES = $(OBJ) $(OBJ_PIC) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c libpcap.so* ++CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c \ ++ $(OBJ_PIC) libpcap.so* + + MAN1 = pcap-config.1 + +@@ -311,7 +326,7 @@ EXTRA_DIST = \ + Win32/Src/inet_net.c \ + Win32/Src/inet_pton.c --all: libpcap.a -+all: libpcap.a $(SHAREDLIB) +-all: libpcap.a pcap-config ++all: libpcap.a pcap-config $(SHAREDLIB) libpcap.a: $(OBJ) @rm -f $@ - ar rc $@ $(OBJ) $(LIBS) - $(RANLIB) $@ +@@ -344,6 +359,13 @@ libpcap.dylib: $(OBJ) + -compatibility_version 1 \ + -current_version `sed 's/[^0-9.].*$$//' $(srcdir)/VERSION` +$(SHAREDLIB): $(OBJ_PIC) + -@rm -f $@ @@ -67,53 +82,76 @@ + ln -s $(SHAREDLIB) $(SOLIBRARY).$(MAJ) + ln -s $(SOLIBRARY).$(MAJ) $(SOLIBRARY) + -+ - shared: libpcap.$(DYEXT) - - # -@@ -131,6 +155,10 @@ + scanner.c: $(srcdir)/scanner.l + @rm -f $@ + ./runlex.sh $(LEX) -o$@ $< +@@ -351,6 +373,9 @@ scanner.c: $(srcdir)/scanner.l scanner.o: scanner.c tokdefs.h $(CC) $(CFLAGS) -c scanner.c +scanner_pic.o: scanner.c tokdefs.h + $(CC) -fPIC $(CFLAGS) -o $@ -c scanner.c -+ + pcap.o: version.h tokdefs.h: grammar.c -@@ -144,9 +172,16 @@ +@@ -364,9 +389,17 @@ grammar.o: grammar.c @rm -f $@ $(CC) $(CFLAGS) -Dyylval=pcap_lval -c grammar.c +grammar_pic.o: grammar.c + @rm -f $@ -+ $(CC) -fPIC $(CFLAGS) -Dyylval=pcap_lval -o $@ -c grammar.c ++ $(CC) -fPIC $(CFLAGS) -Dyylval=pcap_lval -o $@ -c grammar.c + version.o: version.c $(CC) $(CFLAGS) -c version.c +version_pic.o: version.c + $(CC) -fPIC $(CFLAGS) -c version.c -o $@ ++ + snprintf.o: $(srcdir)/missing/snprintf.c $(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c -@@ -172,10 +207,17 @@ +@@ -392,6 +425,9 @@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filt bpf_filter.o: bpf_filter.c $(CC) $(CFLAGS) -c bpf_filter.c +bpf_filter_pic.o: bpf_filter.c + $(CC) -fPIC $(CFLAGS) -c bpf_filter.c -o $@ + -+ - install: libpcap.a - [ -d $(DESTDIR)$(libdir) ] || \ + # + # Generate the pcap-config script. + # +@@ -418,6 +454,9 @@ install: libpcap.a pcap-config (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir)) $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a + $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a + $(INSTALL_DATA) $(SHAREDLIB) $(DESTDIR)$(libdir)/ + ln -sf $(SHAREDLIB) $(DESTDIR)$(libdir)/$(SOLIBRARY).$(MAJ) + ln -sf $(SOLIBRARY).$(MAJ) $(DESTDIR)$(libdir)/$(SOLIBRARY) - $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a [ -d $(DESTDIR)$(includedir) ] || \ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir)) + [ -d $(DESTDIR)$(includedir)/pcap ] || \ +--- a/configure ++++ b/configure +@@ -8658,7 +8658,7 @@ irix*) + ;; + + linux*) +- V_CCOPT="$V_CCOPT -fPIC" ++ V_CCOPT="$V_CCOPT" + ;; + + osf*) +--- a/configure.in ++++ b/configure.in +@@ -943,7 +943,7 @@ irix*) + ;; + + linux*) +- V_CCOPT="$V_CCOPT -fPIC" ++ V_CCOPT="$V_CCOPT" + ;; + + osf*) diff --git a/package/libpcap/patches/101-cross-compile-fix.patch b/package/libpcap/patches/101-cross-compile-fix.patch deleted file mode 100644 index 2f166c8491..0000000000 --- a/package/libpcap/patches/101-cross-compile-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/Makefile.in -+++ b/Makefile.in -@@ -119,7 +119,7 @@ - - libpcap.a: $(OBJ) - @rm -f $@ -- ar rc $@ $(OBJ) $(LIBS) -+ $(AR) rc $@ $(OBJ) $(LIBS) - $(RANLIB) $@ - - $(SHAREDLIB): $(OBJ_PIC) diff --git a/package/libpcap/patches/101-debian_fix_any_intf.patch b/package/libpcap/patches/101-debian_fix_any_intf.patch new file mode 100644 index 0000000000..8da6ef2237 --- /dev/null +++ b/package/libpcap/patches/101-debian_fix_any_intf.patch @@ -0,0 +1,149 @@ +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -297,6 +297,12 @@ pcap_create(const char *device, char *eb + { + pcap_t *handle; + ++ /* ++ * A null device name is equivalent to the "any" device. ++ */ ++ if (device == NULL) ++ device = "any"; ++ + #ifdef HAVE_DAG_API + if (strstr(device, "dag")) { + return dag_create(device, ebuf); +@@ -338,10 +344,9 @@ pcap_can_set_rfmon_linux(pcap_t *p) + struct iwreq ireq; + #endif + +- if (p->opt.source == NULL) { ++ if (strcmp(p->opt.source, "any") == 0) { + /* +- * This is equivalent to the "any" device, and we don't +- * support monitor mode on it. ++ * Monitor mode makes no sense on the "any" device. + */ + return 0; + } +@@ -518,12 +523,11 @@ pcap_activate_linux(pcap_t *handle) + handle->stats_op = pcap_stats_linux; + + /* +- * NULL and "any" are special devices which give us the hint to +- * monitor all devices. ++ * The "any" device is a special device which causes us not ++ * to bind to a particular device and thus to look at all ++ * devices. + */ +- if (!device || strcmp(device, "any") == 0) { +- device = NULL; +- handle->md.device = strdup("any"); ++ if (strcmp(device, "any") == 0) { + if (handle->opt.promisc) { + handle->opt.promisc = 0; + /* Just a warning. */ +@@ -531,10 +535,9 @@ pcap_activate_linux(pcap_t *handle) + "Promiscuous mode not supported on the \"any\" device"); + status = PCAP_WARNING_PROMISC_NOTSUP; + } ++ } + +- } else +- handle->md.device = strdup(device); +- ++ handle->md.device = strdup(device); + if (handle->md.device == NULL) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", + pcap_strerror(errno) ); +@@ -1657,19 +1660,21 @@ static int + activate_new(pcap_t *handle) + { + #ifdef HAVE_PF_PACKET_SOCKETS ++ const char *device = handle->opt.source; ++ int is_any_device = (strcmp(device, "any") == 0); + int sock_fd = -1, arptype, val; + int err = 0; + struct packet_mreq mr; +- const char* device = handle->opt.source; + + /* +- * Open a socket with protocol family packet. If a device is +- * given we try to open it in raw mode otherwise we use +- * the cooked interface. +- */ +- sock_fd = device ? +- socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) +- : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); ++ * Open a socket with protocol family packet. If the ++ * "any" device was specified, we open a SOCK_DGRAM ++ * socket for the cooked interface, otherwise we first ++ * try a SOCK_RAW socket for the raw interface. ++ */ ++ sock_fd = is_any_device ? ++ socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : ++ socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + + if (sock_fd == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", +@@ -1704,7 +1709,7 @@ activate_new(pcap_t *handle) + * to cooked mode if we have an unknown interface type + * or a type we know doesn't work well in raw mode. + */ +- if (device) { ++ if (!is_any_device) { + /* Assume for now we don't need cooked mode. */ + handle->md.cooked = 0; + +@@ -1819,15 +1824,23 @@ activate_new(pcap_t *handle) + } + } else { + /* +- * This is cooked mode. ++ * The "any" device. ++ */ ++ if (handle->opt.rfmon) { ++ /* ++ * It doesn't support monitor mode. ++ */ ++ return PCAP_ERROR_RFMON_NOTSUP; ++ } ++ ++ /* ++ * It uses cooked mode. + */ + handle->md.cooked = 1; + handle->linktype = DLT_LINUX_SLL; + + /* + * We're not bound to a device. +- * XXX - true? Or true only if we're using +- * the "any" device? + * For now, we're using this as an indication + * that we can't transmit; stop doing that only + * if we figure out how to transmit in cooked +@@ -1852,10 +1865,13 @@ activate_new(pcap_t *handle) + + /* + * Hmm, how can we set promiscuous mode on all interfaces? +- * I am not sure if that is possible at all. ++ * I am not sure if that is possible at all. For now, we ++ * silently ignore attempts to turn promiscuous mode on ++ * for the "any" device (so you don't have to explicitly ++ * disable it in programs such as tcpdump). + */ + +- if (device && handle->opt.promisc) { ++ if (!is_any_device && handle->opt.promisc) { + memset(&mr, 0, sizeof(mr)); + mr.mr_ifindex = handle->md.ifindex; + mr.mr_type = PACKET_MR_PROMISC; +@@ -3118,7 +3134,7 @@ activate_old(pcap_t *handle) + + /* Bind to the given device */ + +- if (!device) { ++ if (strcmp(device, "any") == 0) { + strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems", + PCAP_ERRBUF_SIZE); + return PCAP_ERROR; diff --git a/package/libpcap/patches/102-alt-ether.patch b/package/libpcap/patches/102-alt-ether.patch deleted file mode 100644 index e9cc15ff36..0000000000 --- a/package/libpcap/patches/102-alt-ether.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/nametoaddr.c -+++ b/nametoaddr.c -@@ -410,7 +410,7 @@ - e = ep = (u_char *)malloc(6); - - while (*s) { -- if (*s == ':') -+ if (*s == ':' || *s == '.') - s += 1; - d = xdtoi(*s++); - if (isxdigit((unsigned char)*s)) { ---- a/scanner.l -+++ b/scanner.l -@@ -80,6 +80,7 @@ - N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) - B ([0-9A-Fa-f][0-9A-Fa-f]?) - W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?) -+X [0-9A-Fa-f] - - %a 18400 - %o 21500 -@@ -310,7 +311,7 @@ - {N} { yylval.i = stoi((char *)yytext); return NUM; } - ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { - yylval.s = sdup((char *)yytext); return HID; } --{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); -+({B}:{B}:{B}:{B}:{B}:{B})|({B}\.{B}\.{B}\.{B}\.{B}\.{B}) { yylval.e = pcap_ether_aton((char *)yytext); - return EID; } - {V6} { - #ifdef INET6 -@@ -328,6 +329,7 @@ - #endif /*INET6*/ - } - {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } -+{X}{12} { yylval.e = pcap_ether_aton((char *)yytext); return EID;} - icmptype { yylval.i = 0; return NUM; } - icmpcode { yylval.i = 1; return NUM; } - icmp-echoreply { yylval.i = 0; return NUM; } diff --git a/package/libpcap/patches/102-fix_install.patch b/package/libpcap/patches/102-fix_install.patch new file mode 100644 index 0000000000..5264fb2f68 --- /dev/null +++ b/package/libpcap/patches/102-fix_install.patch @@ -0,0 +1,11 @@ +--- a/Makefile.in ++++ b/Makefile.in +@@ -484,6 +484,8 @@ install: libpcap.a pcap-config + $(DESTDIR)$(includedir)/pcap-bpf.h + $(INSTALL_DATA) $(srcdir)/pcap-namedb.h \ + $(DESTDIR)$(includedir)/pcap-namedb.h ++ [ -d $(DESTDIR)$(bindir) ] || \ ++ (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir)) + $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config + for i in $(MAN1); do \ + $(INSTALL_DATA) $(srcdir)/$$i \ diff --git a/package/libpcap/patches/103-flex_workaround.patch b/package/libpcap/patches/103-flex_workaround.patch index 014c624d4a..5d0334272a 100644 --- a/package/libpcap/patches/103-flex_workaround.patch +++ b/package/libpcap/patches/103-flex_workaround.patch @@ -3,7 +3,7 @@ --- a/Makefile.in +++ b/Makefile.in -@@ -53,7 +53,7 @@ +@@ -55,7 +55,7 @@ SHAREDLIB=$(SOLIBRARY).$(LIBVERSION) CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. @V_INCLS@ @@ -11,4 +11,4 @@ +DEFS = -D_BSD_SOURCE @DEFS@ @V_DEFS@ LIBS = @V_LIBS@ DAGLIBS = @DAGLIBS@ - DYEXT = @DYEXT@ + DEPLIBS = @DEPLIBS@ diff --git a/package/libpcap/patches/104-no_rej_files.patch b/package/libpcap/patches/104-no_rej_files.patch deleted file mode 100644 index 0775705faf..0000000000 --- a/package/libpcap/patches/104-no_rej_files.patch +++ /dev/null @@ -1,469 +0,0 @@ -diff -urN libpcap-0.9.8/gencode.c.rej libpcap-0.9.8.new/gencode.c.rej ---- libpcap-0.9.8/gencode.c.rej 2007-07-10 21:38:15.000000000 +0200 -+++ libpcap-0.9.8.new/gencode.c.rej 1970-01-01 01:00:00.000000000 +0100 -@@ -1,465 +0,0 @@ --*************** --*** 24,29 **** -- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; -- #endif -- -- #ifdef HAVE_CONFIG_H -- #include "config.h" -- #endif ----- 24,31 ---- -- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; -- #endif -- --+ #define ENABLE_WLAN_FILTERING_PATCH --+ -- #ifdef HAVE_CONFIG_H -- #include "config.h" -- #endif --*************** --*** 144,150 **** -- OR_NET, /* relative to the network-layer header */ -- OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ -- OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ --- OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ -- }; -- -- /* ----- 146,153 ---- -- OR_NET, /* relative to the network-layer header */ -- OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ -- OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ --+ OR_TRAN_IPV6, /* relative to the transport-layer header, with IPv6 network layer */ --+ OR_LINK_AFTER_WIRELESS_HDR /* After the 802.11 variable length header */ -- }; -- -- /* --*************** --*** 199,204 **** -- static struct block *gen_linktype(int); -- static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); -- static struct block *gen_llc_linktype(int); -- static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); -- #ifdef INET6 -- static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); ----- 202,208 ---- -- static struct block *gen_linktype(int); -- static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); -- static struct block *gen_llc_linktype(int); --+ static struct block *gen_802_11_llc_linktype(int); -- static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); -- #ifdef INET6 -- static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); --*************** --*** 242,247 **** -- static struct slist *xfer_to_a(struct arth *); -- static struct block *gen_mac_multicast(int); -- static struct block *gen_len(int, int); -- -- static struct block *gen_ppi_dlt_check(); -- static struct block *gen_msg_abbrev(int type); ----- 246,252 ---- -- static struct slist *xfer_to_a(struct arth *); -- static struct block *gen_mac_multicast(int); -- static struct block *gen_len(int, int); --+ static struct block *gen_check_802_11_data_frame(); -- -- static struct block *gen_ppi_dlt_check(); -- static struct block *gen_msg_abbrev(int type); --*************** --*** 1345,1350 **** -- return s; -- } -- -- -- /* -- * Load a value relative to the beginning of the specified header. ----- 1350,1487 ---- -- return s; -- } -- --+ /* --+ * Load a value relative to the beginning of the link-layer header after the 802.11 --+ * header, i.e. LLC_SNAP. --+ * The link-layer header doesn't necessarily begin at the beginning --+ * of the packet data; there might be a variable-length prefix containing --+ * radio information. --+ */ --+ static struct slist * --+ gen_load_ll_after_802_11_rel(offset, size) --+ u_int offset, size; --+ { --+ struct slist *s, *s_load_fc; --+ struct slist *sjset_qos; --+ struct slist *s_load; --+ struct slist *s_ld_a_2; --+ struct slist *s_add_a_x; --+ struct slist *s_a_to_x; --+ struct slist *sjset_data_frame_1; --+ struct slist *sjset_data_frame_2; --+ struct slist *s_load_x_0; --+ --+ /* --+ * This code is not compatible with the optimizer, as --+ * we are generating jmp instructions within a normal --+ * slist of instructions --+ * --+ */ --+ no_optimize = 1; --+ --+ s = gen_llprefixlen(); --+ --+ /* --+ * If "s" is non-null, it has code to arrange that the X register --+ * contains the length of the prefix preceding the link-layer --+ * header. --+ * --+ * Otherwise, the length of the prefix preceding the link-layer --+ * header is "off_ll". --+ */ --+ if (s != NULL) { --+ /* --+ * There's a variable-length prefix preceding the --+ * link-layer header. "s" points to a list of statements --+ * that put the length of that prefix into the X register. --+ * do an indirect load, to use the X register as an offset. --+ */ --+ --+ /* --+ * Load the Frame Control field --+ */ --+ s_load_fc = new_stmt(BPF_LD|BPF_IND|BPF_B); --+ s_load_fc->s.k = 0; --+ } else { --+ /* --+ * There is no variable-length header preceding the --+ * link-layer header; add in off_ll, which, if there's --+ * a fixed-length header preceding the link-layer header, --+ * is the length of that header. --+ */ --+ --+ /* --+ * We need to load the Frame control directly, and --+ * then load X with a fake 0, i.e. the length of the --+ * non-existing prepended header --+ */ --+ --+ /* --+ * TODO GV: I'm not sure if 0 is the right constant in this --+ * case. If the link layer has a fixed length prepended header, --+ * that should be the value that we put here --+ */ --+ --+ /* Load 0 into X */ --+ s_load_x_0 = new_stmt(BPF_LDX|BPF_IMM); --+ s_load_x_0->s.k = 0; --+ --+ /* --+ * TODO GV: I'm not sure if 0 is the right constant in this --+ * case. If the link layer has a fixed length prepended header, --+ * that should be the value that we put here --+ */ --+ --+ /* --+ * load the Frame Control with absolute access --+ */ --+ s_load_fc = new_stmt(BPF_LD|BPF_ABS|BPF_B); --+ s_load_fc->s.k = 0; --+ s = s_load_x_0; --+ } --+ --+ /* --+ * Generate the common instructions to check if it's a data frame --+ * and if so compute the 802.11 header length --+ */ --+ sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); // b3 should be 1 --+ sjset_data_frame_1->s.k = 0x8; --+ --+ sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); // b2 should be 0 --+ sjset_data_frame_2->s.k = 0x04; --+ --+ sjset_qos = new_stmt(JMP(BPF_JSET)); --+ sjset_qos->s.k = 0x80; //QOS bit --+ --+ s_ld_a_2 = new_stmt(BPF_LD|BPF_IMM); --+ s_ld_a_2->s.k = 2; --+ --+ s_add_a_x = new_stmt(BPF_ALU|BPF_ADD|BPF_X); --+ s_a_to_x = new_stmt(BPF_MISC|BPF_TAX); --+ --+ s_load = new_stmt(BPF_LD|BPF_IND|size); --+ s_load->s.k = offset; --+ --+ sjset_data_frame_1->s.jt = sjset_data_frame_2; --+ sjset_data_frame_1->s.jf = s_load; --+ --+ sjset_data_frame_2->s.jt = s_load; --+ sjset_data_frame_2->s.jf = sjset_qos; --+ --+ sjset_qos->s.jt = s_ld_a_2; --+ sjset_qos->s.jf = s_load; --+ --+ sappend(s, s_load_fc); --+ sappend(s_load_fc, sjset_data_frame_1); --+ sappend(sjset_data_frame_1, sjset_data_frame_2); --+ sappend(sjset_data_frame_2, sjset_qos); --+ sappend(sjset_qos, s_ld_a_2); --+ sappend(s_ld_a_2, s_add_a_x); --+ sappend(s_add_a_x,s_a_to_x); --+ sappend(s_a_to_x, s_load); --+ --+ return s; --+ } -- -- /* -- * Load a value relative to the beginning of the specified header. --*************** --*** 1367,1372 **** -- s = gen_load_llrel(offset, size); -- break; -- -- case OR_NET: -- s = gen_load_llrel(off_nl + offset, size); -- break; ----- 1504,1525 ---- -- s = gen_load_llrel(offset, size); -- break; -- --+ #ifdef ENABLE_WLAN_FILTERING_PATCH --+ --+ case OR_LINK_AFTER_WIRELESS_HDR: --+ if (linktype != DLT_IEEE802_11_RADIO --+ && linktype != DLT_PPI --+ && linktype != DLT_IEEE802_11 --+ && linktype != DLT_PRISM_HEADER --+ && linktype != DLT_IEEE802_11_RADIO_AVS) --+ { --+ abort(); --+ return NULL; --+ } --+ s = gen_load_ll_after_802_11_rel(offset + 24, size); --+ break; --+ #endif /* ENABLE_WLAN_FILTERING_PATCH */ --+ -- case OR_NET: -- s = gen_load_llrel(off_nl + offset, size); -- break; --*************** --*** 2163,2173 **** -- break; -- -- case DLT_PPI: -- case DLT_FDDI: -- case DLT_IEEE802: --- case DLT_IEEE802_11: -- case DLT_IEEE802_11_RADIO_AVS: --- case DLT_IEEE802_11_RADIO: -- case DLT_PRISM_HEADER: -- case DLT_ATM_RFC1483: -- case DLT_ATM_CLIP: ----- 2316,2332 ---- -- break; -- -- case DLT_PPI: --+ case DLT_IEEE802_11_RADIO: --+ case DLT_IEEE802_11: --+ #ifdef ENABLE_WLAN_FILTERING_PATCH --+ return gen_802_11_llc_linktype(proto); --+ /*NOTREACHED*/ --+ break; --+ #endif /* ENABLE_WLAN_FILTERING_PATCH */ --+ -- case DLT_FDDI: -- case DLT_IEEE802: -- case DLT_IEEE802_11_RADIO_AVS: -- case DLT_PRISM_HEADER: -- case DLT_ATM_RFC1483: -- case DLT_ATM_CLIP: --*************** --*** 2711,2716 **** -- } -- } -- -- static struct block * -- gen_hostop(addr, mask, dir, proto, src_off, dst_off) -- bpf_u_int32 addr; ----- 2870,2982 ---- -- } -- } -- --+ /* --+ * Generate code to match a particular packet type, for link-layer types --+ * using 802.2 LLC headers. --+ * --+ * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used --+ * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. --+ * --+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP --+ * value, if <= ETHERMTU. We use that to determine whether to --+ * match the DSAP or both DSAP and LSAP or to check the OUI and --+ * protocol ID in a SNAP header. --+ */ --+ static struct block * --+ gen_802_11_llc_linktype(proto) --+ int proto; --+ { --+ struct block *b_check_data_frame; --+ struct block *b_check_linktype; --+ --+ b_check_data_frame = gen_check_802_11_data_frame(); --+ --+ /* --+ * XXX - generate the code that discards non data frames --+ */ --+ switch (proto) { --+ --+ case LLCSAP_IP: --+ case LLCSAP_ISONS: --+ case LLCSAP_NETBEUI: --+ /* --+ * XXX - should we check both the DSAP and the --+ * SSAP, like this, or should we check just the --+ * DSAP, as we do for other types <= ETHERMTU --+ * (i.e., other SAP values)? --+ */ --+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_H, (bpf_u_int32) --+ ((proto << 8) | proto)); --+ break; --+ --+ case LLCSAP_IPX: --+ /* --+ * XXX - are there ever SNAP frames for IPX on --+ * non-Ethernet 802.x networks? --+ */ --+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, --+ (bpf_int32)LLCSAP_IPX); --+ --+ break; --+ --+ #if 0 --+ case ETHERTYPE_ATALK: --+ /* --+ * 802.2-encapsulated ETHERTYPE_ATALK packets are --+ * SNAP packets with an organization code of --+ * 0x080007 (Apple, for Appletalk) and a protocol --+ * type of ETHERTYPE_ATALK (Appletalk). --+ * --+ * XXX - check for an organization code of --+ * encapsulated Ethernet as well? --+ */ --+ return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); --+ #endif --+ default: --+ /* --+ * XXX - we don't have to check for IPX 802.3 --+ * here, but should we check for the IPX Ethertype? --+ */ --+ if (proto <= ETHERMTU) { --+ /* --+ * This is an LLC SAP value, so check --+ * the DSAP. --+ */ --+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, --+ (bpf_int32)proto); --+ } else { --+ /* --+ * This is an Ethernet type; we assume that it's --+ * unlikely that it'll appear in the right place --+ * at random, and therefore check only the --+ * location that would hold the Ethernet type --+ * in a SNAP frame with an organization code of --+ * 0x000000 (encapsulated Ethernet). --+ * --+ * XXX - if we were to check for the SNAP DSAP and --+ * LSAP, as per XXX, and were also to check for an --+ * organization code of 0x000000 (encapsulated --+ * Ethernet), we'd do --+ * --+ * return gen_snap(0x000000, proto, --+ * off_linktype); --+ * --+ * here; for now, we don't, as per the above. --+ * I don't know whether it's worth the extra CPU --+ * time to do the right check or not. --+ */ --+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0+6, BPF_H, --+ (bpf_int32)proto); --+ } --+ } --+ --+ gen_and(b_check_data_frame, b_check_linktype); --+ return b_check_linktype; --+ --+ } --+ --+ --+ -- static struct block * -- gen_hostop(addr, mask, dir, proto, src_off, dst_off) -- bpf_u_int32 addr; --*************** --*** 2925,2930 **** -- register struct block *b0, *b1, *b2; -- register struct slist *s; -- -- switch (dir) { -- case Q_SRC: -- /* ----- 3191,3207 ---- -- register struct block *b0, *b1, *b2; -- register struct slist *s; -- --+ #ifdef ENABLE_WLAN_FILTERING_PATCH --+ /* --+ * TODO GV 20070613 --+ * We need to disable the optimizer because the optimizer is buggy --+ * and wipes out some LD instructions generated by the below --+ * code to validate the Frame Control bits --+ * --+ */ --+ no_optimize = 1; --+ #endif /* ENABLE_WLAN_FILTERING_PATCH */ --+ -- switch (dir) { -- case Q_SRC: -- /* --*************** --*** 4713,4718 **** -- #endif -- } -- -- -- /* -- * Generate code that checks whether the packet is a packet for protocol ----- 4990,5021 ---- -- #endif -- } -- --+ static struct block * --+ gen_check_802_11_data_frame() --+ { --+ struct slist *s; --+ struct block *b0, *b1; --+ /* --+ * Now check for a data frame. --+ * I.e, check "link[0] & 0x08". --+ */ --+ s = gen_load_a(OR_LINK, 0, BPF_B); --+ b0 = new_block(JMP(BPF_JSET)); --+ b0->s.k = 0x08; --+ b0->stmts = s; --+ --+ s = gen_load_a(OR_LINK, 0, BPF_B); --+ b1 = new_block(JMP(BPF_JSET)); --+ b1->s.k = 0x04; --+ b1->stmts = s; --+ gen_not(b1); --+ --+ --+ gen_and(b1, b0); --+ --+ return b0; --+ } --+ -- -- /* -- * Generate code that checks whether the packet is a packet for protocol diff --git a/package/libpcap/patches/105-space_optimization.patch b/package/libpcap/patches/105-space_optimization.patch index 17265cd665..29c293b623 100644 --- a/package/libpcap/patches/105-space_optimization.patch +++ b/package/libpcap/patches/105-space_optimization.patch @@ -1,6 +1,6 @@ --- a/gencode.c +++ b/gencode.c -@@ -429,20 +429,6 @@ pcap_compile_nopcap(int snaplen_arg, int +@@ -439,20 +439,6 @@ pcap_compile_nopcap(int snaplen_arg, int } /* @@ -21,48 +21,9 @@ * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates * which of the jt and jf fields has been resolved and which is a pointer * back to another unresolved block (or nil). At least one of the fields ---- a/optimize.c -+++ b/optimize.c -@@ -2263,36 +2263,6 @@ icode_to_fcode(root, lenp) - return fp; - } - --/* -- * Make a copy of a BPF program and put it in the "fcode" member of -- * a "pcap_t". -- * -- * If we fail to allocate memory for the copy, fill in the "errbuf" -- * member of the "pcap_t" with an error message, and return -1; -- * otherwise, return 0. -- */ --int --install_bpf_program(pcap_t *p, struct bpf_program *fp) --{ -- size_t prog_size; -- -- /* -- * Free up any already installed program. -- */ -- pcap_freecode(&p->fcode); -- -- prog_size = sizeof(*fp->bf_insns) * fp->bf_len; -- p->fcode.bf_len = fp->bf_len; -- p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); -- if (p->fcode.bf_insns == NULL) { -- snprintf(p->errbuf, sizeof(p->errbuf), -- "malloc: %s", pcap_strerror(errno)); -- return (-1); -- } -- memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); -- return (0); --} -- - #ifdef BDEBUG - static void - opt_dump(root) --- a/pcap.c +++ b/pcap.c -@@ -463,6 +463,52 @@ static const u_char charmap[] = { +@@ -698,6 +698,59 @@ static const u_char charmap[] = { (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377', }; @@ -80,7 +41,6 @@ + } +} + -+ +/* + * Make a copy of a BPF program and put it in the "fcode" member of + * a "pcap_t". @@ -95,6 +55,15 @@ + size_t prog_size; + + /* ++ * Validate the program. ++ */ ++ if (!bpf_validate(fp->bf_insns, fp->bf_len)) { ++ snprintf(p->errbuf, sizeof(p->errbuf), ++ "BPF program is not valid"); ++ return (-1); ++ } ++ ++ /* + * Free up any already installed program. + */ + pcap_freecode(&p->fcode); @@ -110,8 +79,55 @@ + memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); + return (0); +} -+ + int pcap_strcasecmp(const char *s1, const char *s2) { +--- a/optimize.c ++++ b/optimize.c +@@ -2278,45 +2278,6 @@ icode_to_fcode(root, lenp) + return fp; + } + +-/* +- * Make a copy of a BPF program and put it in the "fcode" member of +- * a "pcap_t". +- * +- * If we fail to allocate memory for the copy, fill in the "errbuf" +- * member of the "pcap_t" with an error message, and return -1; +- * otherwise, return 0. +- */ +-int +-install_bpf_program(pcap_t *p, struct bpf_program *fp) +-{ +- size_t prog_size; +- +- /* +- * Validate the program. +- */ +- if (!bpf_validate(fp->bf_insns, fp->bf_len)) { +- snprintf(p->errbuf, sizeof(p->errbuf), +- "BPF program is not valid"); +- return (-1); +- } +- +- /* +- * Free up any already installed program. +- */ +- pcap_freecode(&p->fcode); +- +- prog_size = sizeof(*fp->bf_insns) * fp->bf_len; +- p->fcode.bf_len = fp->bf_len; +- p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); +- if (p->fcode.bf_insns == NULL) { +- snprintf(p->errbuf, sizeof(p->errbuf), +- "malloc: %s", pcap_strerror(errno)); +- return (-1); +- } +- memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); +- return (0); +-} +- + #ifdef BDEBUG + static void + opt_dump(root) diff --git a/package/libpcap/patches/106-protocol_api.patch b/package/libpcap/patches/106-protocol_api.patch new file mode 100644 index 0000000000..09e3e880ac --- /dev/null +++ b/package/libpcap/patches/106-protocol_api.patch @@ -0,0 +1,141 @@ +--- a/pcap-int.h ++++ b/pcap-int.h +@@ -187,6 +187,7 @@ struct pcap_opt { + char *source; + int promisc; + int rfmon; ++ int proto; /* protocol for packet socket (linux) */ + }; + + /* +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -273,7 +273,7 @@ static int iface_get_id(int fd, const ch + static int iface_get_mtu(int fd, const char *device, char *ebuf); + static int iface_get_arptype(int fd, const char *device, char *ebuf); + #ifdef HAVE_PF_PACKET_SOCKETS +-static int iface_bind(int fd, int ifindex, char *ebuf); ++static int iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto); + static int has_wext(int sock_fd, const char *device, char *ebuf); + static int enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, + const char *device); +@@ -362,7 +362,7 @@ pcap_can_set_rfmon_linux(pcap_t *p) + * (We assume that if we have Wireless Extensions support + * we also have PF_PACKET support.) + */ +- sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); ++ sock_fd = socket(PF_PACKET, SOCK_RAW, handle->opt.proto); + if (sock_fd == -1) { + (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); +@@ -522,6 +522,9 @@ pcap_activate_linux(pcap_t *handle) + handle->read_op = pcap_read_linux; + handle->stats_op = pcap_stats_linux; + ++ if (handle->opt.proto < 0) ++ handle->opt.proto = (int) htons(ETH_P_ALL); ++ + /* + * The "any" device is a special device which causes us not + * to bind to a particular device and thus to look at all +@@ -1673,8 +1676,8 @@ activate_new(pcap_t *handle) + * try a SOCK_RAW socket for the raw interface. + */ + sock_fd = is_any_device ? +- socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : +- socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); ++ socket(PF_PACKET, SOCK_DGRAM, handle->opt.proto) : ++ socket(PF_PACKET, SOCK_RAW, handle->opt.proto); + + if (sock_fd == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", +@@ -1763,7 +1766,7 @@ activate_new(pcap_t *handle) + return PCAP_ERROR; + } + sock_fd = socket(PF_PACKET, SOCK_DGRAM, +- htons(ETH_P_ALL)); ++ handle->opt.proto); + if (sock_fd == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); +@@ -1815,7 +1818,7 @@ activate_new(pcap_t *handle) + } + + if ((err = iface_bind(sock_fd, handle->md.ifindex, +- handle->errbuf)) != 1) { ++ handle->errbuf, handle->opt.proto)) != 1) { + close(sock_fd); + if (err < 0) + return err; +@@ -2440,7 +2443,7 @@ iface_get_id(int fd, const char *device, + * or a PCAP_ERROR_ value on a hard error. + */ + static int +-iface_bind(int fd, int ifindex, char *ebuf) ++iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto) + { + struct sockaddr_ll sll; + int err; +@@ -2449,7 +2452,7 @@ iface_bind(int fd, int ifindex, char *eb + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_ifindex = ifindex; +- sll.sll_protocol = htons(ETH_P_ALL); ++ sll.sll_protocol = proto; + + if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { + if (errno == ENETDOWN) { +@@ -3119,7 +3122,7 @@ activate_old(pcap_t *handle) + + /* Open the socket */ + +- handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); ++ handle->fd = socket(PF_INET, SOCK_PACKET, handle->opt.proto); + if (handle->fd == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); +--- a/pcap.c ++++ b/pcap.c +@@ -152,6 +152,8 @@ pcap_create_common(const char *source, c + pcap_set_snaplen(p, 65535); /* max packet size */ + p->opt.promisc = 0; + p->opt.buffer_size = 0; ++ p->opt.proto = -1; ++ + return (p); + } + +@@ -212,6 +214,15 @@ pcap_set_buffer_size(pcap_t *p, int buff + } + + int ++pcap_set_protocol(pcap_t *p, unsigned short proto) ++{ ++ if (pcap_check_activated(p)) ++ return PCAP_ERROR_ACTIVATED; ++ p->opt.proto = proto; ++ return 0; ++} ++ ++int + pcap_activate(pcap_t *p) + { + int status; +--- a/pcap/pcap.h ++++ b/pcap/pcap.h +@@ -61,6 +61,7 @@ extern "C" { + #define PCAP_VERSION_MINOR 4 + + #define PCAP_ERRBUF_SIZE 256 ++#define HAS_PROTO_EXTENSION + + /* + * Compatibility for systems that have a bpf.h that +@@ -263,6 +264,7 @@ int pcap_can_set_rfmon(pcap_t *); + int pcap_set_rfmon(pcap_t *, int); + int pcap_set_timeout(pcap_t *, int); + int pcap_set_buffer_size(pcap_t *, int); ++int pcap_set_protocol(pcap_t *, unsigned short); + int pcap_activate(pcap_t *); + + pcap_t *pcap_open_live(const char *, int, int, int, char *); -- 2.30.2