aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>1999-03-01 18:57:07 +0000
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>1999-03-01 18:57:07 +0000
commita7ebb03c33aa39c3d73452cfd10667057588b585 (patch)
tree16651cda09bd216cf1ecee07363ef4ce546aeaad /wiretap
parentad80a6d73fae2ebfa76a2ecdaf9ffd11bef61b7d (diff)
Added display filters to wiretap.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@198 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/ChangeLog8
-rw-r--r--wiretap/Makefile.am68
-rw-r--r--wiretap/Makefile.in170
-rw-r--r--wiretap/README20
-rw-r--r--wiretap/aclocal.m4196
-rw-r--r--wiretap/bpf-engine.c319
-rw-r--r--wiretap/bpf-engine.h120
-rw-r--r--wiretap/bpf.c372
-rw-r--r--wiretap/bpf.h22
-rw-r--r--wiretap/config.h.in3
-rwxr-xr-xwiretap/configure369
-rw-r--r--wiretap/configure.in14
-rw-r--r--wiretap/ct-compile.c487
-rw-r--r--wiretap/ct-compile.h104
-rw-r--r--wiretap/ct-grammar.y149
-rw-r--r--wiretap/ct-main.c24
-rw-r--r--wiretap/ct-scanner.l74
-rw-r--r--wiretap/file.c17
-rw-r--r--wiretap/filter-eth38
-rw-r--r--wiretap/filter-tr57
-rw-r--r--wiretap/glib-new.c92
-rw-r--r--wiretap/glib-new.h26
-rw-r--r--wiretap/iptrace.c7
-rw-r--r--wiretap/lanalyzer.c15
-rw-r--r--wiretap/libpcap.c13
-rw-r--r--wiretap/netmon.c13
-rw-r--r--wiretap/netxray.c59
-rw-r--r--wiretap/ngsniffer.c23
-rw-r--r--wiretap/rt-compile.c82
-rw-r--r--wiretap/rt-compile.h29
-rw-r--r--wiretap/rt-global.h23
-rw-r--r--wiretap/rt-grammar-skel.y134
-rw-r--r--wiretap/rt-scanner-skel.l161
-rw-r--r--wiretap/snoop.c13
-rw-r--r--wiretap/wiretap.c297
-rw-r--r--wiretap/wtap.c42
-rw-r--r--wiretap/wtap.h59
37 files changed, 3562 insertions, 157 deletions
diff --git a/wiretap/ChangeLog b/wiretap/ChangeLog
index f7a9bf4a8a..761f2c22ec 100644
--- a/wiretap/ChangeLog
+++ b/wiretap/ChangeLog
@@ -1,3 +1,9 @@
+March 1, 1999
+ Added first code for display filters.
+
+February 20, 1999
+ Guy added the netxray file format.
+
January 27, 1999
Added token-ring support in netmon.c
@@ -5,7 +11,7 @@ January 19, 1999
Changed number of arguments of wtap_open_offline().
January 14, 1999
- Guy added support for reading MicroSoft Network Monitor files.
+ Guy added support for reading Microsoft Network Monitor files.
January 7, 1999
Made all filetypes provide a per-packet encapsulation type, and
diff --git a/wiretap/Makefile.am b/wiretap/Makefile.am
index 2baa634d49..c67e73a102 100644
--- a/wiretap/Makefile.am
+++ b/wiretap/Makefile.am
@@ -1,14 +1,27 @@
+bin_PROGRAMS = wiretap filterc
noinst_LIBRARIES = @LIBWIRETAP_A@
EXTRA_LIBRARIES = libwiretap.a
-CLEANFILES = libwiretap.a
+CLEANFILES = \
+ libwiretap.a \
+ filterc \
+ *~ \
+ ct-grammar.c \
+ ct-scanner.c \
+ ct-tokdefs.h \
+ rt-grammar.c \
+ rt-grammar.y \
+ rt-scanner.c \
+ rt-scanner.l \
+ rt-tokdefs.h
libwiretap_a_SOURCES = \
+ bpf.c \
+ bpf-engine.c \
buffer.c \
buffer.h \
config.h \
- debug.h \
file.c \
iptrace.c \
iptrace.h \
@@ -22,7 +35,58 @@ libwiretap_a_SOURCES = \
netxray.h \
ngsniffer.c \
ngsniffer.h \
+ rt-compile.c \
+ rt-grammar.c \
+ rt-scanner.c \
snoop.c \
snoop.h \
wtap.c \
wtap.h
+
+filterc_SOURCES = \
+ ct-compile.c \
+ ct-grammar.c \
+ ct-main.c \
+ ct-scanner.c \
+ glib-new.c
+
+FILTERS = \
+ filter-eth \
+ filter-tr
+
+CT_YACC=bison -y
+CT_LEX=flex -i
+RT_YACC=bison -y -p wtap_
+RT_LEX=flex -i -Pwtap_
+
+ct-grammar.c : ct-grammar.y
+ @rm -f $@ ct-tokdefs.h
+ $(CT_YACC) -d $<
+ mv y.tab.c ct-grammar.c
+ mv y.tab.h ct-tokdefs.h
+
+ct-scanner.c : ct-scanner.l
+ @rm -f $@
+ $(CT_LEX) -t $< > $@
+
+rt-scanner.l : rt-scanner-skel.l filterc
+ cat $(FILTERS) | ./filterc > /dev/null
+
+rt-scanner.c : rt-scanner.l rt-grammar.c
+ @rm -f $@
+ $(RT_LEX) -t $< > $@
+
+rt-grammar.y : rt-grammar-skel.y filterc
+ cat $(FILTERS) | ./filterc > /dev/null
+
+rt-grammar.c : rt-grammar.y
+ @rm -f $@ rt-tokdefs.h
+ $(RT_YACC) -d $<
+ mv y.tab.c rt-grammar.c
+ mv y.tab.h rt-tokdefs.h
+
+wiretap_SOURCES = \
+ wiretap.c \
+ glib-new.c
+
+wiretap_LDADD = libwiretap.a
diff --git a/wiretap/Makefile.in b/wiretap/Makefile.in
index 9b84a97eff..2087eaf724 100644
--- a/wiretap/Makefile.in
+++ b/wiretap/Makefile.in
@@ -58,6 +58,9 @@ NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_CONFIG = @GLIB_CONFIG@
+GLIB_LIBS = @GLIB_LIBS@
GTK_CFLAGS = @GTK_CFLAGS@
GTK_CONFIG = @GTK_CONFIG@
GTK_LIBS = @GTK_LIBS@
@@ -67,17 +70,30 @@ PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+bin_PROGRAMS = wiretap filterc
noinst_LIBRARIES = @LIBWIRETAP_A@
EXTRA_LIBRARIES = libwiretap.a
-CLEANFILES = libwiretap.a
+CLEANFILES = \
+ libwiretap.a \
+ filterc \
+ *~ \
+ ct-grammar.c \
+ ct-scanner.c \
+ ct-tokdefs.h \
+ rt-grammar.c \
+ rt-grammar.y \
+ rt-scanner.c \
+ rt-scanner.l \
+ rt-tokdefs.h
libwiretap_a_SOURCES = \
+ bpf.c \
+ bpf-engine.c \
buffer.c \
buffer.h \
config.h \
- debug.h \
file.c \
iptrace.c \
iptrace.h \
@@ -91,10 +107,35 @@ libwiretap_a_SOURCES = \
netxray.h \
ngsniffer.c \
ngsniffer.h \
+ rt-compile.c \
+ rt-grammar.c \
+ rt-scanner.c \
snoop.c \
snoop.h \
wtap.c \
wtap.h
+
+filterc_SOURCES = \
+ ct-compile.c \
+ ct-grammar.c \
+ ct-main.c \
+ ct-scanner.c \
+ glib-new.c
+
+FILTERS = \
+ filter-eth \
+ filter-tr
+
+CT_YACC=bison -y
+CT_LEX=flex -i
+RT_YACC=bison -y -p wtap_
+RT_LEX=flex -i -Pwtap_
+
+wiretap_SOURCES = \
+ wiretap.c \
+ glib-new.c
+
+wiretap_LDADD = libwiretap.a
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
CONFIG_HEADER = config.h
@@ -107,9 +148,20 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libwiretap_a_LIBADD =
-libwiretap_a_OBJECTS = buffer.o file.o iptrace.o lanalyzer.o libpcap.o \
-netmon.o netxray.o ngsniffer.o snoop.o wtap.o
+libwiretap_a_OBJECTS = bpf.o bpf-engine.o buffer.o file.o iptrace.o \
+lanalyzer.o libpcap.o netmon.o netxray.o ngsniffer.o rt-compile.o \
+rt-grammar.o rt-scanner.o snoop.o wtap.o
AR = ar
+PROGRAMS = $(bin_PROGRAMS)
+
+wiretap_OBJECTS = wiretap.o glib-new.o
+wiretap_DEPENDENCIES = libwiretap.a
+wiretap_LDFLAGS =
+filterc_OBJECTS = ct-compile.o ct-grammar.o ct-main.o ct-scanner.o \
+glib-new.o
+filterc_LDADD = $(LDADD)
+filterc_DEPENDENCIES =
+filterc_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
@@ -122,13 +174,16 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
-DEP_FILES = .deps/buffer.P .deps/file.P .deps/iptrace.P \
+DEP_FILES = .deps/bpf-engine.P .deps/bpf.P .deps/buffer.P \
+.deps/ct-compile.P .deps/ct-grammar.P .deps/ct-main.P \
+.deps/ct-scanner.P .deps/file.P .deps/glib-new.P .deps/iptrace.P \
.deps/lanalyzer.P .deps/libpcap.P .deps/netmon.P .deps/netxray.P \
-.deps/ngsniffer.P .deps/snoop.P .deps/wtap.P
-SOURCES = $(libwiretap_a_SOURCES)
-OBJECTS = $(libwiretap_a_OBJECTS)
+.deps/ngsniffer.P .deps/rt-compile.P .deps/rt-grammar.P \
+.deps/rt-scanner.P .deps/snoop.P .deps/wiretap.P .deps/wtap.P
+SOURCES = $(libwiretap_a_SOURCES) $(wiretap_SOURCES) $(filterc_SOURCES)
+OBJECTS = $(libwiretap_a_OBJECTS) $(wiretap_OBJECTS) $(filterc_OBJECTS)
-all: Makefile $(LIBRARIES) config.h
+all: Makefile $(LIBRARIES) $(PROGRAMS) config.h
.SUFFIXES:
.SUFFIXES: .S .c .o .s
@@ -198,6 +253,39 @@ libwiretap.a: $(libwiretap_a_OBJECTS) $(libwiretap_a_DEPENDENCIES)
$(AR) cru libwiretap.a $(libwiretap_a_OBJECTS) $(libwiretap_a_LIBADD)
$(RANLIB) libwiretap.a
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ done
+
+wiretap: $(wiretap_OBJECTS) $(wiretap_DEPENDENCIES)
+ @rm -f wiretap
+ $(LINK) $(wiretap_LDFLAGS) $(wiretap_OBJECTS) $(wiretap_LDADD) $(LIBS)
+
+filterc: $(filterc_OBJECTS) $(filterc_DEPENDENCIES)
+ @rm -f filterc
+ $(LINK) $(filterc_LDFLAGS) $(filterc_OBJECTS) $(filterc_LDADD) $(LIBS)
+
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
@@ -299,7 +387,7 @@ dvi:
check: all
$(MAKE)
installcheck:
-install-exec:
+install-exec: install-binPROGRAMS
@$(NORMAL_INSTALL)
install-data:
@@ -308,11 +396,12 @@ install-data:
install: install-exec install-data all
@:
-uninstall:
+uninstall: uninstall-binPROGRAMS
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
+ $(mkinstalldirs) $(DATADIR)$(bindir)
mostlyclean-generic:
@@ -330,20 +419,21 @@ maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-hdr mostlyclean-noinstLIBRARIES \
- mostlyclean-compile mostlyclean-tags mostlyclean-depend \
- mostlyclean-generic
+ mostlyclean-compile mostlyclean-binPROGRAMS \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
-clean: clean-hdr clean-noinstLIBRARIES clean-compile clean-tags \
- clean-depend clean-generic mostlyclean
+clean: clean-hdr clean-noinstLIBRARIES clean-compile clean-binPROGRAMS \
+ clean-tags clean-depend clean-generic mostlyclean
distclean: distclean-hdr distclean-noinstLIBRARIES distclean-compile \
- distclean-tags distclean-depend distclean-generic clean
+ distclean-binPROGRAMS distclean-tags distclean-depend \
+ distclean-generic clean
-rm -f config.status
maintainer-clean: maintainer-clean-hdr maintainer-clean-noinstLIBRARIES \
- maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-depend maintainer-clean-generic \
- distclean
+ maintainer-clean-compile maintainer-clean-binPROGRAMS \
+ maintainer-clean-tags maintainer-clean-depend \
+ maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-rm -f config.status
@@ -352,13 +442,41 @@ maintainer-clean: maintainer-clean-hdr maintainer-clean-noinstLIBRARIES \
mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir mostlyclean-depend \
-distclean-depend clean-depend maintainer-clean-depend info dvi \
-installcheck install-exec install-data install uninstall all \
-installdirs mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
-
+maintainer-clean-compile mostlyclean-binPROGRAMS distclean-binPROGRAMS \
+clean-binPROGRAMS maintainer-clean-binPROGRAMS uninstall-binPROGRAMS \
+install-binPROGRAMS tags mostlyclean-tags distclean-tags clean-tags \
+maintainer-clean-tags distdir mostlyclean-depend distclean-depend \
+clean-depend maintainer-clean-depend info dvi installcheck install-exec \
+install-data install uninstall all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+ct-grammar.c : ct-grammar.y
+ @rm -f $@ ct-tokdefs.h
+ $(CT_YACC) -d $<
+ mv y.tab.c ct-grammar.c
+ mv y.tab.h ct-tokdefs.h
+
+ct-scanner.c : ct-scanner.l
+ @rm -f $@
+ $(CT_LEX) -t $< > $@
+
+rt-scanner.l : rt-scanner-skel.l filterc
+ cat $(FILTERS) | ./filterc > /dev/null
+
+rt-scanner.c : rt-scanner.l rt-grammar.c
+ @rm -f $@
+ $(RT_LEX) -t $< > $@
+
+rt-grammar.y : rt-grammar-skel.y filterc
+ cat $(FILTERS) | ./filterc > /dev/null
+
+rt-grammar.c : rt-grammar.y
+ @rm -f $@ rt-tokdefs.h
+ $(RT_YACC) -d $<
+ mv y.tab.c rt-grammar.c
+ mv y.tab.h rt-tokdefs.h
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/wiretap/README b/wiretap/README
index c84235b6e8..197e089c81 100644
--- a/wiretap/README
+++ b/wiretap/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.10 1999/02/20 08:12:20 guy Exp $
+$Id: README,v 1.11 1999/03/01 18:57:02 gram Exp $
Wiretap is a library that is being developed as a future replacement for
libpcap, the current standard Unix library for packet capturing. Libpcap is
@@ -32,8 +32,16 @@ SunOS has NIT and Solaris has DLPI, which both use the CMU/Stanford
packet-filter psuedomachine. RMON has another type of packet-filter syntax
which we could support.
-Currently, only #2 is available. Wiretap doesn't even do any filtering yet. It
-can only be used to read packet capture files.
+Wiretap is very good at reading may file formats, as per #2
+above. Display filters are now appearing in wiretap, but they are
+still basic. Development is continuing on the BPF compiler, so display
+filters will continue to be enhanced. Wiretap can't capture packets yet,
+but once it can, it will have the ability to do capture-filtering via
+BPF, either through BPF kernel facilities or through a user-space BPF
+implementation. BPF is my first target, but the filter compiler will
+be generic enough so that as per #6, other packet-filtering engines can
+be used.
+
File Formats
============
@@ -77,7 +85,7 @@ Network Monitor
---------------
Microsoft's Network Monitor file format is supported, at least under Ethernet
and token-ring. If you have capture files of other datalink types, please send
-them to Guy Harris <guy@netapp.com>.
+them to Guy Harris.
"snoop"
-------
@@ -103,5 +111,5 @@ read, and the packet time stamp isn't correctly computed. Network
Associates' Windows Sniffer Pro appears to use a variant of that format;
it's supported to the same extent.
-Gilbert Ramirez
-<gram@verdict.uthscsa.edu>
+Gilbert Ramirez <gram@verdict.uthscsa.edu>
+Guy Harris <guy@netapp.com>
diff --git a/wiretap/aclocal.m4 b/wiretap/aclocal.m4
index c009d8039e..ca9393269f 100644
--- a/wiretap/aclocal.m4
+++ b/wiretap/aclocal.m4
@@ -308,3 +308,199 @@ main ()
rm -f conf.gtktest
])
+# Configure paths for GLIB
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or
+dnl gthread is specified in MODULES, pass to glib-config
+dnl
+AC_DEFUN(AM_PATH_GLIB,
+[dnl
+dnl Get the cflags and libraries from the glib-config script
+dnl
+AC_ARG_WITH(glib-prefix,[ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)],
+ glib_config_prefix="$withval", glib_config_prefix="")
+AC_ARG_WITH(glib-exec-prefix,[ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)],
+ glib_config_exec_prefix="$withval", glib_config_exec_prefix="")
+AC_ARG_ENABLE(glibtest, [ --disable-glibtest Do not try to compile and run a test GLIB program],
+ , enable_glibtest=yes)
+
+ if test x$glib_config_exec_prefix != x ; then
+ glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+ fi
+ fi
+ if test x$glib_config_prefix != x ; then
+ glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+ fi
+ fi
+
+ for module in . $4
+ do
+ case "$module" in
+ gmodule)
+ glib_config_args="$glib_config_args gmodule"
+ ;;
+ gthread)
+ glib_config_args="$glib_config_args gthread"
+ ;;
+ esac
+ done
+
+ AC_PATH_PROG(GLIB_CONFIG, glib-config, no)
+ min_glib_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+ no_glib=""
+ if test "$GLIB_CONFIG" = "no" ; then
+ no_glib=yes
+ else
+ GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+ GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+ glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_glibtest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of glib-config to some extent
+dnl
+ rm -f conf.glibtest
+ AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.glibtest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_glib_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_glib_version");
+ exit(1);
+ }
+
+ if ((glib_major_version != $glib_config_major_version) ||
+ (glib_minor_version != $glib_config_minor_version) ||
+ (glib_micro_version != $glib_config_micro_version))
+ {
+ printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+ $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf ("*** was found! If glib-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+ printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+ else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+ (glib_minor_version != GLIB_MINOR_VERSION) ||
+ (glib_micro_version != GLIB_MICRO_VERSION))
+ {
+ printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+ GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ }
+ else
+ {
+ if ((glib_major_version > major) ||
+ ((glib_major_version == major) && (glib_minor_version > minor)) ||
+ ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+ printf("*** correct copy of glib-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_glib" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GLIB_CONFIG" = "no" ; then
+ echo "*** The glib-config script installed by GLIB could not be found"
+ echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+ echo "*** full path to glib-config."
+ else
+ if test -f conf.glibtest ; then
+ :
+ else
+ echo "*** Could not run GLIB test program, checking why..."
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$LIBS $GLIB_LIBS"
+ AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+ echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+ echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+ echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GLIB_CFLAGS=""
+ GLIB_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+ rm -f conf.glibtest
+])
diff --git a/wiretap/bpf-engine.c b/wiretap/bpf-engine.c
new file mode 100644
index 0000000000..ae81c24243
--- /dev/null
+++ b/wiretap/bpf-engine.c
@@ -0,0 +1,319 @@
+/* bpf-engine.c
+ * ------------
+ * The BPF engine used for offline ("display") filters in wiretap.
+ * The code is taken from the Linux Socket Filter, and only slightly
+ * modified for use in wiretap.
+ *
+ * Gilbert Ramirez <gram@verdict.uthscsa.edu>
+ */
+
+/*
+ * Linux Socket Filter - Kernel level socket filtering
+ *
+ * Author:
+ * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *
+ * Based on the design of:
+ * - The Berkeley Packet Filter
+ *
+ * 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
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <netinet/in.h>
+#include <glib.h>
+#include "wtap.h"
+#include "bpf-engine.h"
+
+
+/*
+ * Decode and apply filter instructions to the skb->data.
+ * Return length to keep, 0 for none. skb is the data we are
+ * filtering, filter is the array of filter instructions, and
+ * len is the number of filter blocks in the array.
+ */
+
+int bpf_run_filter(unsigned char *data, int len, struct bpf_instruction *filter, int flen)
+{
+ struct bpf_instruction *fentry; /* We walk down these */
+ guint32 A = 0; /* Accumulator */
+ guint32 X = 0; /* Index Register */
+ guint32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */
+ int k;
+ int pc;
+ int *t;
+
+ /*
+ * Process array of filter instructions.
+ */
+
+ for(pc = 0; pc < flen; pc++)
+ {
+ fentry = &filter[pc];
+ if(fentry->code & BPF_X)
+ t=&X;
+ else
+ t=&fentry->k;
+
+ switch(fentry->code)
+ {
+ case BPF_ALU|BPF_ADD|BPF_X:
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += *t;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= *t;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= *t;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ case BPF_ALU|BPF_DIV|BPF_K:
+ if(*t == 0)
+ return (0);
+ A /= *t;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= *t;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= *t;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= *t;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= *t;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ A = -A;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ pc += fentry->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? fentry->jt : fentry->jf;
+ continue;
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = fentry->k;
+ if(k + sizeof(long) > len)
+ return (0);
+ A = pntohl(&data[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = fentry->k;
+ if(k + sizeof(short) > len)
+ return (0);
+ A = pntohs(&data[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = fentry->k;
+ if(k >= len)
+ return (0);
+ A = data[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = len;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = len;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + fentry->k;
+ if(k + sizeof(guint32) > len)
+ return (0);
+ A = pntohl(&data[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + fentry->k;
+ if(k + sizeof(guint16) > len)
+ return (0);
+ A = pntohs(&data[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + fentry->k;
+ if(k >= len)
+ return (0);
+ A = data[k];
+ continue;
+
+ case BPF_LDX|BPF_B|BPF_MSH:
+ /*
+ * Hack for BPF to handle TOS etc
+ */
+ k = fentry->k;
+ if(k >= len)
+ return (0);
+ X = (data[fentry->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = fentry->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = fentry->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[fentry->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[fentry->k];
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+ case BPF_RET|BPF_K:
+ return ((unsigned int)fentry->k);
+
+ case BPF_RET|BPF_A:
+ return ((unsigned int)A);
+
+ case BPF_ST:
+ mem[fentry->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[fentry->k] = X;
+ continue;
+
+
+
+ default:
+ /* Invalid instruction counts as RET */
+ return (0);
+ }
+ }
+
+ g_error("Filter ruleset ran off the end.\n");
+ return (0);
+}
+
+/*
+ * Check the user's filter code. If we let some ugly
+ * filter code slip through kaboom!
+ */
+
+int bpf_chk_filter(struct bpf_instruction *filter, int flen)
+{
+ struct bpf_instruction *ftest;
+ int pc;
+
+ /*
+ * Check the filter code now.
+ */
+ for(pc = 0; pc < flen; pc++)
+ {
+ /*
+ * All jumps are forward as they are not signed
+ */
+
+ ftest = &filter[pc];
+ if(BPF_CLASS(ftest->code) == BPF_JMP)
+ {
+ /*
+ * But they mustn't jump off the end.
+ */
+ if(BPF_OP(ftest->code) == BPF_JA)
+ {
+ if(pc + ftest->k + 1>= (unsigned)flen)
+ return (-1);
+ }
+ else
+ {
+ /*
+ * For conditionals both must be safe
+ */
+ if(pc + ftest->jt +1 >= flen || pc + ftest->jf +1 >= flen)
+ return (-1);
+ }
+ }
+
+ /*
+ * Check that memory operations use valid addresses.
+ */
+
+ if(ftest->k <0 || ftest->k >= BPF_MEMWORDS)
+ {
+ /*
+ * But it might not be a memory operation...
+ */
+
+ if (BPF_CLASS(ftest->code) == BPF_ST)
+ return -1;
+ if((BPF_CLASS(ftest->code) == BPF_LD) &&
+ (BPF_MODE(ftest->code) == BPF_MEM))
+ return (-1);
+ }
+ }
+
+ /*
+ * The program must end with a return. We don't care where they
+ * jumped within the script (its always forwards) but in the
+ * end they _will_ hit this.
+ */
+
+ return (BPF_CLASS(filter[flen - 1].code) == BPF_RET)?0:-1;
+}
+
diff --git a/wiretap/bpf-engine.h b/wiretap/bpf-engine.h
new file mode 100644
index 0000000000..24f87ae30a
--- /dev/null
+++ b/wiretap/bpf-engine.h
@@ -0,0 +1,120 @@
+/* bpf-engine.h
+ * ------------
+ * The BPF engine used for offline ("display") filters in wiretap.
+ * The code is taken from the Linux Socket Filter, and only slightly
+ * modified for use in wiretap.
+ *
+ * Gilbert Ramirez <gram@verdict.uthscsa.edu>
+ */
+
+/*
+ * Linux Socket Filter - Kernel level socket filtering
+ *
+ * Author:
+ * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *
+ * Based on the design of:
+ * - The Berkeley Packet Filter
+ *
+ * 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
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Linux Socket Filter Data Structures
+ */
+
+/*
+ * Current version of the filter code architecture.
+ */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/* each BPF instruction is a block of 8 bytes */
+struct bpf_instruction {
+ guint16 code; /* Actual filter code */
+ guint8 jt; /* Jump true */
+ guint8 jf; /* Jump false */
+ guint32 k; /* Generic multiuse field */
+
+};
+
+struct bpf_code_unit {
+ int line_label;
+ struct bpf_instruction bpf;
+};
+
+int bpf_run_filter(unsigned char *data, int len, struct bpf_instruction *filter, int flen);
+int bpf_chk_filter(struct bpf_instruction *filter, int flen);
+
+/*
+ * Instruction classes
+ */
+
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+#define BPF_MAXINSNS 512
+
+/*
+ * Macros for filter block array initializers.
+ */
+#define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words for: BPF_ST and BPF_STX
+ */
+#define BPF_MEMWORDS 16
+
diff --git a/wiretap/bpf.c b/wiretap/bpf.c
new file mode 100644
index 0000000000..59033f93a0
--- /dev/null
+++ b/wiretap/bpf.c
@@ -0,0 +1,372 @@
+/*
+ * bpf.c
+ * -----
+ * Creates and handles the BPF code produced by wiretap.
+ *
+ * Gilbert Ramirez
+ */
+
+#ifndef __G_LIB_H__
+#include <glib.h>
+#endif
+
+#include <netinet/in.h>
+
+#include "wtap.h"
+#include "rt-compile.h"
+#include "rt-global.h"
+#include "bpf-engine.h"
+#include "bpf.h"
+
+
+static GList *bpf_code_just_parsed = NULL;
+static struct bpf_instruction *bpf_record = NULL;
+
+static int
+bpf_clean_jump(GList *L, int i_this, int jmp, int num_bpf_instructions,
+ int i_ret_success, int i_ret_failure);
+static void
+bpf_pass1(GList *L);
+
+static GList*
+bpf_mk_bytecmp(int ftype, int rel_opcode, guint8 *bytes);
+
+static void
+bpf_optimize(GList *L);
+
+static int
+bpf_attach(wtap *wth);
+
+static void
+bpf_attach_record(gpointer bpf_code, gpointer junk);
+
+static int
+offline_attach(wtap *wth);
+
+
+/* sets function pointers in rt-grammar.y to point to the BPF-related
+ * functions */
+void
+wtap_filter_bpf_init(void)
+{
+ mk_bytecmp = bpf_mk_bytecmp;
+ mk_optimize = bpf_optimize;
+ mk_attach = bpf_attach;
+}
+
+/* almost the same as bpf_init... */
+void
+wtap_filter_offline_init(wtap *wth)
+{
+ int fi; /* filter index */
+
+ mk_bytecmp = bpf_mk_bytecmp;
+ mk_optimize = bpf_optimize;
+ mk_attach = offline_attach;
+
+ wtap_filter_offline_clear(wth);
+
+ /* make the offline filter array */
+ wth->filter.offline = g_malloc(sizeof(int*) * WTAP_NUM_ENCAP_TYPES);
+ wth->filter_type = WTAP_FILTER_OFFLINE;
+ wth->offline_filter_lengths = g_malloc(sizeof(int) * WTAP_NUM_ENCAP_TYPES);
+
+ for (fi = 0; fi < WTAP_NUM_ENCAP_TYPES; fi++) {
+ wth->filter.offline[fi] = NULL;
+ }
+}
+
+/* Removes an offline filter from a wtap struct, and frees memory used
+ * by that filter */
+void
+wtap_filter_offline_clear(wtap *wth)
+{
+ int fi; /* filter index */
+
+ if (wth->filter.offline) {
+ for (fi = 0; fi < WTAP_NUM_ENCAP_TYPES; fi++) {
+ if (wth->filter.offline[fi])
+ g_free(wth->filter.offline[fi]);
+ }
+ g_free(wth->filter.offline);
+ g_free(wth->offline_filter_lengths);
+ }
+ wth->filter_type = WTAP_FILTER_NONE;
+}
+
+/* Allocate a new bpf_code_unit structure and initialize the BPF instruction
+ * codes to the values passed by the caller. */
+static struct bpf_code_unit *
+bpf_code_unit_alloc(guint8 label, guint16 code, guint8 jt, guint8 jf, guint32 k)
+{
+ struct bpf_code_unit *bpf;
+
+ bpf = g_malloc(sizeof(struct bpf_code_unit));
+ bpf->line_label = label;
+ bpf->bpf.code = code;
+ bpf->bpf.jt = jt;
+ bpf->bpf.jf = jf;
+ bpf->bpf.k = k;
+
+ /*g_print("{ %d { 0x%02x, %d, %d, 0x%08x }},\n",
+ label, code, jt, jf, k);*/
+ return bpf;
+}
+
+
+/* Finds ftype in the bytecmp_table, the relation, and the n-string
+byte array, and creates BPF that will check those bytes */
+static GList*
+bpf_mk_bytecmp(int ftype, int rel_opcode, guint8 *bytes)
+{
+ GList *L;
+ struct bpf_code_unit *bpf;
+ int len_to_cmp, offset, endpoint, label;
+ bytecmp_info *b;
+
+ L = g_list_alloc();
+
+ /* find the field in the table */
+ b = lookup_bytecmp(ftype);
+
+ /* How many bytes do we have to compare, and where? */
+ len_to_cmp = b->length;
+ offset = b->offset;
+ endpoint = len_to_cmp + offset;
+ /*g_print("len_to_cmp=%d, offset=%d, endpoint=%d\n",
+ len_to_cmp, offset, endpoint);
+ g_print("bytes: (%d) %02X:%02X:%02X\n",
+ bytes[0], bytes[1], bytes[2], bytes[3]);*/
+
+ label = NEXT_BLOCK;
+ /* loop until we have written instructions to compare
+ all bytes */
+ while (len_to_cmp) {
+
+ if (len_to_cmp >= 4) {
+ bpf = bpf_code_unit_alloc(label,
+ BPF_LD|BPF_W|BPF_ABS,
+ 0, 0, endpoint - 4);
+ g_list_append(L, bpf);
+ label = NO_LABEL;
+
+ endpoint -= 4;
+ bpf = bpf_code_unit_alloc(NO_LABEL,
+ BPF_JMP|BPF_JEQ,
+ (len_to_cmp == 4 ? END_OF_PROGRAM_SUCCESS : 0),
+ NEXT_BLOCK,
+ htonl(*(guint32*)&bytes[len_to_cmp-3]));
+ g_list_append(L, bpf);
+
+ len_to_cmp -= 4;
+ }
+ else if (len_to_cmp == 3) {
+ bpf = bpf_code_unit_alloc(label,
+ BPF_LD|BPF_W|BPF_ABS,
+ 0, 0, endpoint - 3);
+ g_list_append(L, bpf);
+ label = NO_LABEL;
+ endpoint -= 3;
+
+ bpf = bpf_code_unit_alloc(NO_LABEL,
+ BPF_ALU|BPF_AND,
+ 0, 0,
+ htonl(0xffffff));
+ g_list_append(L, bpf);
+
+ bpf = bpf_code_unit_alloc(NO_LABEL,
+ BPF_JMP|BPF_JEQ,
+ (len_to_cmp == 3 ? END_OF_PROGRAM_SUCCESS : 0),
+ NEXT_BLOCK,
+ htonl(*(guint32*)&bytes[len_to_cmp-2]) & 0xffffff00);
+ g_list_append(L, bpf);
+
+ len_to_cmp -= 3;
+ }
+ else if (len_to_cmp == 2) {
+ bpf = bpf_code_unit_alloc(label,
+ BPF_LD|BPF_H|BPF_ABS,
+ 0, 0, endpoint - 2);
+ g_list_append(L, bpf);
+ label = NO_LABEL;
+
+ endpoint -= 2;
+ bpf = bpf_code_unit_alloc(NO_LABEL,
+ BPF_JMP|BPF_JEQ,
+ (len_to_cmp == 2 ? END_OF_PROGRAM_SUCCESS : 0),
+ NEXT_BLOCK,
+ (guint32)htons(*(guint16*)&bytes[len_to_cmp-1]));
+ g_list_append(L, bpf);
+
+ len_to_cmp -= 2;
+ }
+ else if (len_to_cmp == 1) {
+ bpf = bpf_code_unit_alloc(label,
+ BPF_LD|BPF_B|BPF_ABS,
+ 0, 0, endpoint - 1);
+ g_list_append(L, bpf);
+ label = NO_LABEL;
+
+ endpoint--;
+ bpf = bpf_code_unit_alloc(NO_LABEL,
+ BPF_JMP|BPF_JEQ,
+ END_OF_PROGRAM_SUCCESS, NEXT_BLOCK,
+ bytes[len_to_cmp]);
+ g_list_append(L, bpf);
+ len_to_cmp--;
+ }
+ }
+
+
+ L = g_list_remove(L, 0);
+ return L;
+}
+
+
+static void
+bpf_optimize(GList *L)
+{
+ bpf_pass1(L);
+ bpf_code_just_parsed = L;
+}
+
+/* after the BPF code is constructed from the parser, this step is run. During
+ * pass1 we:
+ *
+ * 1. Clean up the jump variables
+ */
+static void
+bpf_pass1(GList *L)
+{
+ struct bpf_code_unit *bpf;
+ int num_bpf_instructions;
+ int i_ret_success;
+ int i_ret_failure;
+ int i;
+
+ /* Attach a SUCCESS return to the end of the BPF code */
+ bpf = bpf_code_unit_alloc(END_OF_PROGRAM_SUCCESS, BPF_RET, 0, 0, 0xffff);
+ g_list_append(L, bpf);
+
+ /* Attach a FAILURE return to the end of the BPF code */
+ bpf = bpf_code_unit_alloc(END_OF_PROGRAM_FAILURE, BPF_RET, 0, 0, 0);
+ g_list_append(L, bpf);
+
+ num_bpf_instructions = g_list_length(L);
+ i_ret_success = num_bpf_instructions - 2;
+ i_ret_failure = num_bpf_instructions - 1;
+
+ for(i = 0; i < num_bpf_instructions; i++) {
+ bpf = (struct bpf_code_unit*) g_list_nth_data(L, i);
+ if (!bpf)
+ continue;
+
+ /* Check for Jump to end failure/success */
+ if (bpf->bpf.code & BPF_JMP) {
+
+ bpf->bpf.jt = bpf_clean_jump(L, i, bpf->bpf.jt, num_bpf_instructions,
+ i_ret_success, i_ret_failure);
+
+ bpf->bpf.jf = bpf_clean_jump(L, i, bpf->bpf.jf, num_bpf_instructions,
+ i_ret_success, i_ret_failure);
+ }
+ }
+}
+
+static int
+bpf_clean_jump(GList *L, int i_this, int jmp, int num_bpf_instructions,
+ int i_ret_success, int i_ret_failure)
+{
+ int i;
+ struct bpf_code_unit *bpf;
+
+ switch(jmp) {
+ case END_OF_PROGRAM_SUCCESS:
+ return i_ret_success - i_this - 1;
+
+ case END_OF_PROGRAM_FAILURE:
+ return i_ret_failure - i_this - 1;
+
+ case NEXT_BLOCK:
+ for (i = i_this + 1; i < num_bpf_instructions; i++) {
+ bpf = (struct bpf_code_unit*) g_list_nth_data(L, i);
+ if (!bpf)
+ continue;
+ if (bpf->line_label == NEXT_BLOCK) {
+ return i - i_this - 1;
+ }
+ }
+ /* failed to find NEXT_BLOCK.... chose FAILURE */
+ return i_ret_failure - i_this - 1;
+
+ /* default: nothing */
+ }
+ return jmp;
+}
+
+
+
+/* Takes code from bpf_code_just_parsed and attaches it to wth
+ * returns 1 if sucessfull, 0 if not */
+static int bpf_attach(wtap *wth)
+{
+ if (wth->filter.bpf)
+ g_free(wth->filter.bpf);
+
+ /* filter_length will be number of bpf_block records */
+ wth->filter_length = g_list_length(bpf_code_just_parsed) - 1;
+
+ wth->filter.bpf = g_malloc(wth->filter_length *
+ sizeof(struct bpf_instruction));
+ wth->filter_type = WTAP_FILTER_BPF;
+
+ bpf_record = wth->filter.bpf;
+
+ g_list_foreach(bpf_code_just_parsed, bpf_attach_record, NULL);
+
+ if (bpf_chk_filter(wth->filter.bpf, wth->filter_length) == 0)
+ return 1;
+ else
+ return 0;
+
+}
+
+void bpf_attach_record(gpointer bpf_code, gpointer junk)
+{
+ struct bpf_code_unit *bpf_c = (struct bpf_code_unit*) bpf_code;
+
+ struct bpf_instruction *bpf_i;
+
+ if (!bpf_c)
+ return;
+
+ bpf_i = &(bpf_c->bpf);
+ memcpy(bpf_record, bpf_i, sizeof(struct bpf_instruction));
+ bpf_record++;
+}
+
+
+/* Takes code from bpf_code_just_parsed and attachs it to wth.
+ * returns 1 if sucessfull, 0 if not */
+static int offline_attach(wtap *wth)
+{
+ /* filter_length will be number of bpf_instruction records */
+ wth->offline_filter_lengths[comp_encap_type] =
+ g_list_length(bpf_code_just_parsed);
+
+ /* Make space for this filter */
+ wth->filter.offline[comp_encap_type] =
+ g_malloc(wth->offline_filter_lengths[comp_encap_type]
+ * sizeof(struct bpf_instruction));
+
+ bpf_record = wth->filter.offline[comp_encap_type];
+
+ g_list_foreach(bpf_code_just_parsed, bpf_attach_record, NULL);
+
+ if (bpf_chk_filter(wth->filter.offline[comp_encap_type],
+ wth->offline_filter_lengths[comp_encap_type]) == 0)
+ return 1;
+ else
+ return 0;
+}
+
diff --git a/wiretap/bpf.h b/wiretap/bpf.h
new file mode 100644
index 0000000000..81b8572873
--- /dev/null
+++ b/wiretap/bpf.h
@@ -0,0 +1,22 @@
+
+/* we limit the number of BPF records a jmp can take by using a few of the
+ * jmp values as special identifiers during the compilation process. Many
+ * pieces of code need to jump to the end of the entire BPF block, returing
+ * either a successful value or a failure value (either the number of bytes
+ * to read, or 0). The code creator uses these 4 variables to represent
+ * the retval of failure or success, then the code cleaner fills in the
+ * true value for these variables.
+ */
+#define NO_LABEL 255
+#define END_OF_PROGRAM_FAILURE 254
+#define END_OF_PROGRAM_SUCCESS 253
+#define NEXT_BLOCK 252
+
+void
+wtap_filter_bpf_init(void);
+
+void
+wtap_filter_offline_init(wtap *wth);
+
+void
+wtap_filter_offline_clear(wtap *wth);
diff --git a/wiretap/config.h.in b/wiretap/config.h.in
index 8b6879568d..1d115ea3c2 100644
--- a/wiretap/config.h.in
+++ b/wiretap/config.h.in
@@ -9,3 +9,6 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+
+/* Define if you are using glib 1.0 (or below) */
+#undef HAVE_GLIB10
diff --git a/wiretap/configure b/wiretap/configure
index 8b2c0eca1a..059a511142 100755
--- a/wiretap/configure
+++ b/wiretap/configure
@@ -12,6 +12,12 @@ ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
+ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)"
+ac_help="$ac_help
+ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)"
+ac_help="$ac_help
+ --disable-glibtest Do not try to compile and run a test GLIB program"
+ac_help="$ac_help
--with-gtk-prefix=PFX Prefix where GTK is installed (optional)"
ac_help="$ac_help
--with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)"
@@ -557,7 +563,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:561: checking for a BSD compatible install" >&5
+echo "configure:567: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -610,7 +616,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:614: checking whether build environment is sane" >&5
+echo "configure:620: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
@@ -667,7 +673,7 @@ test "$program_suffix" != NONE &&
test "$program_transform_name" = "" && program_transform_name="s,x,x,"
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:671: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:677: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -713,7 +719,7 @@ EOF
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:717: checking for working aclocal" >&5
+echo "configure:723: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -726,7 +732,7 @@ else
fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:730: checking for working autoconf" >&5
+echo "configure:736: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -739,7 +745,7 @@ else
fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:743: checking for working automake" >&5
+echo "configure:749: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -752,7 +758,7 @@ else
fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:756: checking for working autoheader" >&5
+echo "configure:762: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -765,7 +771,7 @@ else
fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:769: checking for working makeinfo" >&5
+echo "configure:775: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -785,7 +791,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:789: checking for $ac_word" >&5
+echo "configure:795: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -814,7 +820,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:818: checking for $ac_word" >&5
+echo "configure:824: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -862,7 +868,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:866: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:872: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -872,11 +878,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
-#line 876 "configure"
+#line 882 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:880: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:886: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -896,12 +902,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:900: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:906: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:905: checking whether we are using GNU C" >&5
+echo "configure:911: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -910,7 +916,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:914: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:920: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -925,7 +931,7 @@ if test $ac_cv_prog_gcc = yes; then
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:929: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:935: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -955,7 +961,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:959: checking for $ac_word" >&5
+echo "configure:965: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -984,7 +990,7 @@ fi
# If we're running gcc, add '-Wall' to CFLAGS.
echo $ac_n "checking to see if we can add '-Wall' to CFLAGS""... $ac_c" 1>&6
-echo "configure:988: checking to see if we can add '-Wall' to CFLAGS" >&5
+echo "configure:994: checking to see if we can add '-Wall' to CFLAGS" >&5
if test x$GCC != x ; then
CFLAGS="-Wall $CFLAGS"
echo "$ac_t""yes" 1>&6
@@ -992,8 +998,275 @@ else
echo "$ac_t""no" 1>&6
fi
-# GTK checks (copied from ethereal)
-# Check whether --with-gtk-prefix or --without-gtk-prefix was given.
+# Checks for glib first, or gtk+ if not present
+# Check whether --with-glib-prefix or --without-glib-prefix was given.
+if test "${with_glib_prefix+set}" = set; then
+ withval="$with_glib_prefix"
+ glib_config_prefix="$withval"
+else
+ glib_config_prefix=""
+fi
+
+# Check whether --with-glib-exec-prefix or --without-glib-exec-prefix was given.
+if test "${with_glib_exec_prefix+set}" = set; then
+ withval="$with_glib_exec_prefix"
+ glib_config_exec_prefix="$withval"
+else
+ glib_config_exec_prefix=""
+fi
+
+# Check whether --enable-glibtest or --disable-glibtest was given.
+if test "${enable_glibtest+set}" = set; then
+ enableval="$enable_glibtest"
+ :
+else
+ enable_glibtest=yes
+fi
+
+
+ if test x$glib_config_exec_prefix != x ; then
+ glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+ fi
+ fi
+ if test x$glib_config_prefix != x ; then
+ glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+ fi
+ fi
+
+ for module in .
+ do
+ case "$module" in
+ gmodule)
+ glib_config_args="$glib_config_args gmodule"
+ ;;
+ gthread)
+ glib_config_args="$glib_config_args gthread"
+ ;;
+ esac
+ done
+
+ # Extract the first word of "glib-config", so it can be a program name with args.
+set dummy glib-config; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1056: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GLIB_CONFIG'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GLIB_CONFIG" in
+ /*)
+ ac_cv_path_GLIB_CONFIG="$GLIB_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GLIB_CONFIG="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GLIB_CONFIG" && ac_cv_path_GLIB_CONFIG="no"
+ ;;
+esac
+fi
+GLIB_CONFIG="$ac_cv_path_GLIB_CONFIG"
+if test -n "$GLIB_CONFIG"; then
+ echo "$ac_t""$GLIB_CONFIG" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ min_glib_version=1.1.0
+ echo $ac_n "checking for GLIB - version >= $min_glib_version""... $ac_c" 1>&6
+echo "configure:1087: checking for GLIB - version >= $min_glib_version" >&5
+ no_glib=""
+ if test "$GLIB_CONFIG" = "no" ; then
+ no_glib=yes
+ else
+ GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+ GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+ glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+ glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+ glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+ if test "x$enable_glibtest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$GLIB_LIBS $LIBS"
+ rm -f conf.glibtest
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1110 "configure"
+#include "confdefs.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.glibtest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_glib_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_glib_version");
+ exit(1);
+ }
+
+ if ((glib_major_version != $glib_config_major_version) ||
+ (glib_minor_version != $glib_config_minor_version) ||
+ (glib_micro_version != $glib_config_micro_version))
+ {
+ printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+ $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf ("*** was found! If glib-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+ printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+ else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+ (glib_minor_version != GLIB_MINOR_VERSION) ||
+ (glib_micro_version != GLIB_MICRO_VERSION))
+ {
+ printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+ GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ }
+ else
+ {
+ if ((glib_major_version > major) ||
+ ((glib_major_version == major) && (glib_minor_version > minor)) ||
+ ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+ printf("*** correct copy of glib-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+
+EOF
+if { (eval echo configure:1186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ no_glib=yes
+fi
+rm -fr conftest*
+fi
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_glib" = x ; then
+ echo "$ac_t""yes" 1>&6
+ CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS"
+ else
+ echo "$ac_t""no" 1>&6
+ if test "$GLIB_CONFIG" = "no" ; then
+ echo "*** The glib-config script installed by GLIB could not be found"
+ echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+ echo "*** full path to glib-config."
+ else
+ if test -f conf.glibtest ; then
+ :
+ else
+ echo "*** Could not run GLIB test program, checking why..."
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$LIBS $GLIB_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 1220 "configure"
+#include "confdefs.h"
+
+#include <glib.h>
+#include <stdio.h>
+
+int main() {
+ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version));
+; return 0; }
+EOF
+if { (eval echo configure:1230: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+ echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+ echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+ echo "*** may want to edit the glib-config script: $GLIB_CONFIG"
+fi
+rm -f conftest*
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GLIB_CFLAGS=""
+ GLIB_LIBS=""
+ echo "configure: warning: GLIB 1.1.x or above not found." 1>&2
+ fi
+
+
+ rm -f conf.glibtest
+
+
+if test "x$GLIB_CFLAGS" = x ; then
+ # Check whether --with-gtk-prefix or --without-gtk-prefix was given.
if test "${with_gtk_prefix+set}" = set; then
withval="$with_gtk_prefix"
gtk_config_prefix="$withval"
@@ -1034,7 +1307,7 @@ fi
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1038: checking for $ac_word" >&5
+echo "configure:1311: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1065,7 +1338,7 @@ fi
min_gtk_version=1.0.0
echo $ac_n "checking for GTK - version >= $min_gtk_version""... $ac_c" 1>&6
-echo "configure:1069: checking for GTK - version >= $min_gtk_version" >&5
+echo "configure:1342: checking for GTK - version >= $min_gtk_version" >&5
no_gtk=""
if test "$GTK_CONFIG" = "no" ; then
no_gtk=yes
@@ -1088,7 +1361,7 @@ echo "configure:1069: checking for GTK - version >= $min_gtk_version" >&5
echo $ac_n "cross compiling; assumed OK... $ac_c"
else
cat > conftest.$ac_ext <<EOF
-#line 1092 "configure"
+#line 1365 "configure"
#include "confdefs.h"
#include <gtk/gtk.h>
@@ -1154,7 +1427,7 @@ main ()
}
EOF
-if { (eval echo configure:1158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1431: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1188,7 +1461,7 @@ fi
CFLAGS="$CFLAGS $GTK_CFLAGS"
LIBS="$LIBS $GTK_LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1192 "configure"
+#line 1465 "configure"
#include "confdefs.h"
#include <gtk/gtk.h>
@@ -1198,7 +1471,7 @@ int main() {
return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version));
; return 0; }
EOF
-if { (eval echo configure:1202: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding GTK or finding the wrong"
@@ -1230,16 +1503,21 @@ rm -f conftest*
fi
GTK_CFLAGS=""
GTK_LIBS=""
- { echo "configure: error: GTK+ distribution not found." 1>&2; exit 1; }
+ { echo "configure: error: GTK+ library not found." 1>&2; exit 1; }
fi
rm -f conf.gtktest
+ cat >> confdefs.h <<\EOF
+#define HAVE_GLIB10 1
+EOF
+
+fi
# Wiretap check (copied and modified from ethereal)
echo $ac_n "checking whether to include wiretap library""... $ac_c" 1>&6
-echo "configure:1243: checking whether to include wiretap library" >&5
+echo "configure:1521: checking whether to include wiretap library" >&5
# Check whether --with-wiretap or --without-wiretap was given.
if test "${with_wiretap+set}" = set; then
withval="$with_wiretap"
@@ -1261,7 +1539,7 @@ fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1265: checking how to run the C preprocessor" >&5
+echo "configure:1543: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -1276,13 +1554,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1280 "configure"
+#line 1558 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1286: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1564: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@@ -1293,13 +1571,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1297 "configure"
+#line 1575 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1303: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1581: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@@ -1322,12 +1600,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1326: checking for ANSI C header files" >&5
+echo "configure:1604: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1331 "configure"
+#line 1609 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1335,7 +1613,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1339: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1617: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1352,7 +1630,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1356 "configure"
+#line 1634 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1370,7 +1648,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1374 "configure"
+#line 1652 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1391,7 +1669,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 1395 "configure"
+#line 1673 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1402,7 +1680,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:1406: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1684: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1429,17 +1707,17 @@ for ac_hdr in unistd.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1433: checking for $ac_hdr" >&5
+echo "configure:1711: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1438 "configure"
+#line 1716 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1443: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1721: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1610,6 +1888,9 @@ s%@MAKEINFO@%$MAKEINFO%g
s%@SET_MAKE@%$SET_MAKE%g
s%@CC@%$CC%g
s%@RANLIB@%$RANLIB%g
+s%@GLIB_CONFIG@%$GLIB_CONFIG%g
+s%@GLIB_CFLAGS@%$GLIB_CFLAGS%g
+s%@GLIB_LIBS@%$GLIB_LIBS%g
s%@GTK_CONFIG@%$GTK_CONFIG%g
s%@GTK_CFLAGS@%$GTK_CFLAGS%g
s%@GTK_LIBS@%$GTK_LIBS%g
diff --git a/wiretap/configure.in b/wiretap/configure.in
index b0acfdcfd3..cb9c10ba63 100644
--- a/wiretap/configure.in
+++ b/wiretap/configure.in
@@ -1,4 +1,4 @@
-# $Id: configure.in,v 1.6 1999/01/13 04:14:29 gerald Exp $
+# $Id: configure.in,v 1.7 1999/03/01 18:57:03 gram Exp $
dnl Process this file with autoconf to produce a configure script.
AC_INIT(wtap.c)
AM_INIT_AUTOMAKE(libwtap.a, 0.0.0)
@@ -17,9 +17,15 @@ else
AC_MSG_RESULT(no)
fi
-# GTK checks (copied from ethereal)
-AM_PATH_GTK(1.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$LIBS $GTK_LIBS",
- AC_MSG_ERROR(GTK+ distribution not found.))
+# Checks for glib first, or gtk+ if not present
+AM_PATH_GLIB(1.1.0, CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS",
+ AC_MSG_WARN(GLIB 1.1.x or above not found.))
+
+if test "x$GLIB_CFLAGS" = x ; then
+ AM_PATH_GTK(1.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$LIBS $GTK_LIBS",
+ AC_MSG_ERROR(GTK+ library not found.))
+ AC_DEFINE(HAVE_GLIB10)
+fi
# Wiretap check (copied and modified from ethereal)
AC_MSG_CHECKING(whether to include wiretap library)
diff --git a/wiretap/ct-compile.c b/wiretap/ct-compile.c
new file mode 100644
index 0000000000..eea612b9e8
--- /dev/null
+++ b/wiretap/ct-compile.c
@@ -0,0 +1,487 @@
+/* ct-compile.c
+ ------------
+ Compile-time filter-compiler for Wiretap
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "ct-compile.h"
+
+#ifdef HAVE_GLIB10
+#include "glib-new.h"
+#endif
+
+#define LINE_SIZE 1024
+
+GHashTable *field_hash;
+GHashTable *protocol_hash;
+char *protocol_name = NULL;
+int rt_iteration;
+
+extern struct field_info working_field; /* in ct-grammar.y */
+
+char *ftype_text[] = {
+ "NONE",
+ "BOOLEAN",
+ "ETHER",
+ "IPv4ADDR",
+ "UINT8",
+ "UINT16",
+ "UINT32",
+ "BYTE"
+};
+
+char *ctype_text[] = {
+ "NONE",
+ "ANDMASK",
+ "BYTECMP",
+ "EITHEROF"
+};
+
+static
+int many_list_subtype(struct field_info *val);
+
+/* Called by main() to initialize the global variables that ct-compile.c
+ * worries about. */
+void compiler_init(void)
+{
+ field_hash = g_hash_table_new(g_str_hash, g_str_equal);
+ protocol_hash = g_hash_table_new(g_str_hash, g_str_equal);
+ field_info_init(&working_field);
+}
+
+/* takes a pointer to a field_info struct that the parser built,
+ * makes a copy of the struct, and adds it to our list of fields */
+void field_info_add(struct field_info *fi, char *protocol)
+{
+ struct field_info *new_fi;
+
+ /* Make a duplicate of the field_info struct, destroying
+ * the pointers of the old struct in the process. */
+ new_fi = g_memdup(fi, sizeof(struct field_info));
+ new_fi->name = fi->name;
+ new_fi->short_name = fi->short_name;
+ new_fi->description = fi->description;
+ new_fi->many_list = fi->many_list;
+ new_fi->aliases = fi->aliases;
+ fi->name = NULL;
+ fi->short_name = NULL;
+ fi->description = NULL;
+ fi->many_list = NULL;
+ fi->aliases = NULL;
+
+ /* Find the parent */
+ new_fi->parent = g_hash_table_lookup(protocol_hash, protocol);
+ if (!new_fi)
+ g_print("Cannot find parent protocol %s for field %s\n",
+ protocol, new_fi->name);
+
+ g_hash_table_insert(field_hash, new_fi->name, new_fi);
+
+ g_print("field_info_add added %s (%s) \n\t"
+ "ftype=%s, off=%d, len=%d, val=%d, ctype=%s\n",
+ new_fi->name,
+ new_fi->description,
+ ftype_text[new_fi->field_type], new_fi->offset,
+ new_fi->length, new_fi->value,
+ ctype_text[new_fi->computation_type]);
+}
+
+/* initialize a field_info struct */
+void field_info_init(struct field_info *fi)
+{
+ /* put NULLs in the fields that field_info_zero assumes
+ * that a non-NULL value corresponds to allocated memory. */
+ fi->name = NULL;
+ fi->description = NULL;
+ fi->aliases = NULL;
+ fi->many_list = NULL;
+
+ field_info_zero(fi);
+}
+
+/* zero out the values of an existing field_info struct */
+void field_info_zero(struct field_info *fi)
+{
+ if (fi->name)
+ free(fi->name);
+ if (fi->short_name)
+ free(fi->short_name);
+ if (fi->description)
+ free(fi->description);
+
+ fi->field_type = 0;
+ fi->computation_type = CTYPE_NONE;
+ fi->offset = 0;
+ fi->length = 0;
+ fi->value = 0;
+ fi->parent = NULL;
+
+ if (fi->aliases)
+ g_slist_free(fi->aliases);
+ if (fi->many_list)
+ g_slist_free(fi->many_list);
+
+ fi->aliases = g_slist_alloc();
+ fi->many_list = g_slist_alloc();
+}
+
+void show_aliases(gpointer alias, gpointer field)
+{
+ if (alias)
+ g_print("%s ", ((GString*)alias)->str);
+
+}
+/* add alias(es) to this field */
+void field_info_add_alias(char *field_name, GSList *aliases)
+{
+ struct field_info *fi;
+
+ fi = g_hash_table_lookup(field_hash, field_name);
+
+ if (!fi) {
+ g_print("Could not find field %s to alias.\n", field_name);
+ return;
+ }
+
+ g_slist_concat(fi->aliases, aliases);
+ g_print("(%s) added aliases: ", fi->name);
+ g_slist_foreach(fi->aliases, show_aliases, NULL);
+ g_print("\n");
+}
+
+/* Given a list of GStrings of field_names, return a list of field_info
+ * pointers */
+GSList* field_info_list(GSList *field_names, char *protocol)
+{
+ GSList *new_list;
+ char *protocol_dot;
+
+ protocol_dot = g_strjoin("", protocol, ".", NULL);
+ g_slist_foreach(field_names, field_info_list_func1, protocol_dot);
+
+ new_list = g_slist_alloc();
+ g_slist_foreach(field_names, field_info_list_func2, new_list);
+
+ return new_list;
+}
+
+void field_info_list_func1(gpointer node, gpointer protocol)
+{
+ if(node)
+ g_string_prepend((GString*)node, (char*)protocol);
+}
+
+
+void field_info_list_func2(gpointer node, gpointer new_list)
+{
+ if (node)
+ g_slist_append(new_list,
+ g_hash_table_lookup(field_hash,
+ ((GString*)node)->str));
+/* if (node)
+ g_print("info_list added %s\n", ((GString*)node)->str);*/
+}
+
+
+/* add a protocol to the hash */
+void protocol_layer_add(char *name, char *description)
+{
+ struct protocol_layer *new_pr;
+
+ new_pr = g_malloc(sizeof(struct protocol_layer));
+
+ new_pr->name = g_strdup(name);
+ new_pr->description = g_strdup(description);
+
+ g_hash_table_insert(protocol_hash, new_pr->name, new_pr);
+
+ g_print("protocol_layer_add added %s (%s)\n",
+ new_pr->name,
+ new_pr->description);
+}
+
+/* Creates rt-scanner.l from rt-scanner-skel.l */
+void write_rt_lex(void)
+{
+ char buf[LINE_SIZE];
+ FILE *in, *out;
+
+ if (!(in = fopen("rt-scanner-skel.l", "r"))) {
+ g_error("Could not open rt-scanner-skel.l for reading.");
+ exit(1);
+ }
+
+ if (!(out = fopen("rt-scanner.l", "w"))) {
+ g_error("Could not open rt-scanner.l for writing.");
+ exit(1);
+ }
+
+ while(fgets(buf, LINE_SIZE, in)) {
+ if (strcmp(buf, "/* ct-compile: lex tokens */\n") == 0) {
+ write_rt_lex_tokens(out);
+ continue;
+ }
+ else {
+ fprintf(out, "%s", buf);
+ }
+ }
+ fclose(in);
+ fclose(out);
+}
+
+
+void write_rt_lex_tokens(FILE *out)
+{
+ g_hash_table_foreach(field_hash, rt_lex_tokens, out);
+}
+
+void rt_lex_tokens(gpointer key, gpointer value, gpointer out)
+{
+ char *upcase;
+
+ if (!value) {
+ g_print("key %s has no value.\n", (char*)key);
+ return;
+ }
+
+ protocol_name = ((struct field_info*) value)->parent->name;
+ if (((struct field_info*) value)->aliases) {
+ g_slist_foreach(((struct field_info*) value)->aliases,
+ rt_lex_tokens_aliases, out);
+ }
+ upcase = rt_lex_token_upcase(((struct field_info*)value)->name);
+ fprintf((FILE*)out, "%s\\.%s\t return %s;\n", protocol_name,
+ ((struct field_info*) value)->short_name,
+ upcase);
+
+ free(upcase);
+}
+
+char* rt_lex_token_upcase(char *text)
+{
+ char *new_text;
+ char *p;
+ new_text = g_strdup(text);
+ g_strup(new_text);
+
+ /* s/\./_/g */
+ for (p = new_text; *p; p++) {
+ if (*p == '.') {
+ *p = '_';
+ }
+ }
+ return new_text;
+}
+
+
+void rt_lex_tokens_aliases(gpointer node, gpointer out)
+{
+ if (node) {
+ fprintf((FILE*)out, "%s\\.%s\t|\n",
+ protocol_name,
+ ((GString*) node)->str);
+ }
+}
+
+/* Creates rt-grammar.y from rt-grammar-skel.y */
+void write_rt_yacc(void)
+{
+ char buf[LINE_SIZE];
+ FILE *in, *out;
+
+ if (!(in = fopen("rt-grammar-skel.y", "r"))) {
+ g_error("Could not open rt-grammar-skel.y for reading.");
+ exit(1);
+ }
+
+ if (!(out = fopen("rt-grammar.y", "w"))) {
+ g_error("Could not open rt-scanner.l for writing.");
+ exit(1);
+ }
+
+ while(fgets(buf, LINE_SIZE, in)) {
+ if (strcmp(buf, "/* ct-compile: bytecmp_table */\n") == 0) {
+ write_rt_bytecmp_table(out);
+ continue;
+ }
+ else if (strcmp(buf, "/* ct-compile: eitherof_table */\n") == 0) {
+ write_rt_eitherof_table(out);
+ continue;
+ }
+ else if (strcmp(buf, "/* ct-compile: yacc tokens */\n") == 0) {
+ write_rt_yacc_tokens(out);
+ continue;
+ }
+ else if (strcmp(buf, "/* ct-compile: bytecmp_lval */\n") == 0) {
+ write_rt_bytecmp_lval(out);
+ continue;
+ }
+ else {
+ fprintf(out, "%s", buf);
+ }
+ }
+ fclose(in);
+ fclose(out);
+}
+
+/* ------------------------- BYTECMP_TABLE -------------------- */
+void write_rt_bytecmp_table(FILE *out)
+{
+ fprintf(out, "bytecmp_info bytecmp_table[] = {\n");
+ g_hash_table_foreach(field_hash, rt_bytecmp_table, out);
+ fprintf(out, "\t{ 0, 0, 0, 0 }\n};\n");
+}
+
+void rt_bytecmp_table(gpointer key, gpointer value, gpointer out)
+{
+ char *upcase;
+ struct field_info *val = (struct field_info*) value;
+
+ if (!val) {
+ g_print("key %s has no value.\n", (char*)key);
+ return;
+ }
+
+ /* return now if we're not dealing with a bytecmp field */
+ if (val->computation_type == CTYPE_EITHEROF) {
+ if (many_list_subtype(val) != CTYPE_BYTECMP)
+ return;
+ }
+ else if (val->computation_type != CTYPE_BYTECMP) {
+ return;
+ }
+
+ upcase = rt_lex_token_upcase(((struct field_info*)value)->name);
+ fprintf((FILE*)out, "\t{ %s, %d, %d, %d },\n",
+ upcase, val->computation_type, val->offset, val->length);
+ free(upcase);
+}
+
+static
+int many_list_subtype(struct field_info *val)
+{
+ struct field_info *fi;
+ gchar *field1;
+
+ if (!val->many_list)
+ return 0;
+
+ field1 = ((GString*)g_slist_nth_data(val->many_list, 1))->str;
+ fi = g_hash_table_lookup(field_hash, field1);
+
+ if (!fi)
+ return 0;
+
+ return fi->computation_type;;
+}
+
+/* ------------------- EITHEROF_TABLE ------------------------ */
+void write_rt_eitherof_table(FILE *out)
+{
+ fprintf(out, "eitherof_info eitherof_table[] = {\n");
+ g_hash_table_foreach(field_hash, rt_eitherof_table, out);
+ fprintf(out, "\t{ 0, 0, 0, 0 }\n};\n");
+}
+
+void rt_eitherof_table(gpointer key, gpointer value, gpointer out)
+{
+ char *upcase_field, *upcase_field1, *upcase_field2;
+ struct field_info *val = (struct field_info*) value;
+
+ if (!val) {
+ g_print("key %s has no value.\n", (char*)key);
+ return;
+ }
+
+ if (val->computation_type != CTYPE_EITHEROF) {
+ return;
+ }
+
+ upcase_field = rt_lex_token_upcase(((struct field_info*)value)->name);
+ g_print("EITHEROF checking %s\n", upcase_field);
+ if (val->many_list) {
+ g_print("getting fields\n");
+ upcase_field1 = ((GString*)g_slist_nth_data(val->many_list, 1))->str;
+ g_print("got field1 %s\n", upcase_field1);
+ upcase_field2 = ((GString*)g_slist_nth_data(val->many_list, 2))->str;
+ g_print("got field2 %s\n", upcase_field2);
+ upcase_field1 = rt_lex_token_upcase(upcase_field1);
+ g_print("got field1 %s\n", upcase_field1);
+ upcase_field2 = rt_lex_token_upcase(upcase_field2);
+ g_print("got field2 %s\n", upcase_field2);
+ }
+ else
+ return;
+
+ fprintf((FILE*)out, "\t{ %s, %d, %s, %s },\n",
+ upcase_field, val->computation_type,
+ upcase_field1, upcase_field2);
+ free(upcase_field);
+ free(upcase_field1);
+ free(upcase_field2);
+}
+
+/* ---------------------- YACC_TOKENS ---------------------------- */
+void write_rt_yacc_tokens(FILE *out)
+{
+ g_hash_table_foreach(field_hash, rt_yacc_tokens, out);
+}
+
+void rt_yacc_tokens(gpointer key, gpointer value, gpointer out)
+{
+ char *upcase;
+ struct field_info *val = (struct field_info*) value;
+
+ if (!val) {
+ g_print("key %s has no value.\n", (char*)key);
+ return;
+ }
+
+ upcase = rt_lex_token_upcase(((struct field_info*)value)->name);
+ fprintf((FILE*)out, "%%token <d>\t%s\n", upcase);
+ free(upcase);
+}
+
+/* ------------------------ BYTECMP_LVAL -------------------------- */
+void write_rt_bytecmp_lval(FILE *out)
+{
+ rt_iteration = 0;
+ g_hash_table_foreach(field_hash, rt_bytecmp_lval, out);
+ fprintf(out, "\t;\n");
+}
+
+void rt_bytecmp_lval(gpointer key, gpointer value, gpointer out)
+{
+ char *upcase;
+ struct field_info *val = (struct field_info*) value;
+
+ if (!val) {
+ g_print("key %s has no value.\n", (char*)key);
+ return;
+ }
+
+ if (val->computation_type == CTYPE_EITHEROF) {
+ if (many_list_subtype(val) != CTYPE_BYTECMP)
+ return;
+ }
+ else if (val->computation_type != CTYPE_BYTECMP) {
+ return;
+ }
+
+ if (rt_iteration == 0) {
+ fprintf(out, "bytecmp_lval:\t");
+ }
+ else {
+ fprintf(out,"\t|\t");
+ }
+
+ upcase = rt_lex_token_upcase(((struct field_info*)value)->name);
+ fprintf((FILE*)out, "\t%s { $$ = %s; }\n",
+ upcase, upcase);
+ free(upcase);
+ rt_iteration++;
+}
diff --git a/wiretap/ct-compile.h b/wiretap/ct-compile.h
new file mode 100644
index 0000000000..72f50b6843
--- /dev/null
+++ b/wiretap/ct-compile.h
@@ -0,0 +1,104 @@
+/* ct-compile.h
+ ------------
+ Compile-time filter-compiler for Wiretap
+
+*/
+
+#ifndef __G_LIB_H__
+#include <glib.h>
+#endif
+
+/* field type IDs */
+#define FTYPE_BOOLEAN 1
+#define FTYPE_ETHER 2
+#define FTYPE_IPv4ADDR 3
+#define FTYPE_UINT8 4
+#define FTYPE_UINT16 5
+#define FTYPE_UINT32 6
+#define FTYPE_BYTE 7
+
+/* field lengths */
+#define FLEN_BOOLEAN 1
+#define FLEN_ETHER 6
+#define FLEN_IPv4ADDR 4
+#define FLEN_UINT8 1
+#define FLEN_UINT16 2
+#define FLEN_UINT32 4
+/* FLEN_BYTE doesn't get a fixed length, of course */
+
+/* computation types */
+#define CTYPE_NONE 0
+#define CTYPE_ANDMASK 1
+#define CTYPE_BYTECMP 2
+#define CTYPE_EITHEROF 3
+
+/* Protocol-layer information */
+struct protocol_layer {
+ char *name;
+ char *description;
+ GSList *parents;
+};
+
+/* Fields */
+struct field_info {
+ char *name;
+ char *short_name;
+ char *description;
+ int field_type;
+ int computation_type;
+ int offset;
+ int value;
+ int length;
+
+ GSList *aliases;
+ GSList *many_list;
+
+ struct protocol_layer *parent;
+};
+
+/* Add a field-info struct to the compiler's list of fields */
+void field_info_add(struct field_info *fi, char *protocol);
+
+/* Initialize values in a field_info struct. This can only be run once per
+ * structure, as it would cause a memory leak if used multiple times. */
+void field_info_init(struct field_info *fi);
+
+/* Zero-out the values in a field_info struct. This can be used more than once
+ * per structure, as it avoids a memory leak. But call field_info_init the
+ * first time, and field_info_zero for all other times */
+void field_info_zero(struct field_info *fi);
+
+/* add alias(es) to this field */
+void field_info_add_alias(char *field_name, GSList *aliases);
+
+/* add a protocol to the hash */
+void protocol_layer_add(char *name, char *description);
+
+/* Given a list of GStrings of field names, returns a list of pointers
+ * to field_info structs */
+GSList* field_info_list(GSList *field_names, char *protocol);
+
+/* used by field_info_list() */
+void field_info_list_func1(gpointer node, gpointer protocol);
+void field_info_list_func2(gpointer node, gpointer new_list);
+
+void compiler_init(void);
+void write_rt_lex(void);
+void write_rt_lex_tokens(FILE *out);
+void rt_lex_tokens(gpointer key, gpointer value, gpointer out);
+void rt_lex_tokens_aliases(gpointer node, gpointer out);
+char* rt_lex_token_upcase(char *text);
+
+void write_rt_yacc(void);
+void write_rt_bytecmp_table(FILE *out);
+void rt_bytecmp_table(gpointer key, gpointer value, gpointer out);
+void write_rt_eitherof_table(FILE *out);
+void rt_eitherof_table(gpointer key, gpointer value, gpointer out);
+void write_rt_yacc_tokens(FILE *out);
+void rt_yacc_tokens(gpointer key, gpointer value, gpointer out);
+void write_rt_bytecmp_lval(FILE *out);
+void rt_bytecmp_lval(gpointer key, gpointer value, gpointer out);
+
+int yylex(void);
+int yyparse(void);
+void yyerror(char *string);
diff --git a/wiretap/ct-grammar.y b/wiretap/ct-grammar.y
new file mode 100644
index 0000000000..5841e5c737
--- /dev/null
+++ b/wiretap/ct-grammar.y
@@ -0,0 +1,149 @@
+%{
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ct-compile.h"
+
+#include "config.h"
+
+#ifdef HAVE_GLIB10
+#include "glib-new.h"
+#endif
+
+struct field_info working_field;
+gchar *current_protocol = NULL;
+char *full_field_name = NULL;
+
+%}
+
+%union {
+ gint d;
+ GString *s;
+ GSList *a;
+}
+
+%type <s> sentence protocol
+%type <a> parents text_list
+
+%token <s> TEXT PROTOCOL PARENTS QUOTED
+%token <d> NUMBER BOOLEAN ETHER UINT8 UINT16 UINT32 BYTE
+%token FIELD ALIAS
+%token AND_MASK BYTE_OFFSET EITHER_OF
+
+%%
+
+paragraph: /* EMPTY */
+ | paragraph sentence
+ ;
+
+sentence: protocol
+{
+ if (current_protocol)
+ free(current_protocol);
+ current_protocol = g_strdup($1->str);
+}
+ | parents
+{
+ g_print("sentence Got parents %d\n", g_slist_length($1));
+}
+ | alias { }
+ | field { }
+ ;
+
+protocol: PROTOCOL TEXT QUOTED ';'
+{
+ protocol_layer_add($2->str, $3->str);
+ $$ = $2;
+}
+ ;
+
+parents: PARENTS text_list ';'
+{
+ $$ = $2;
+ g_slist_free($2);
+}
+ ;
+
+alias: ALIAS TEXT text_list ';'
+{
+ full_field_name = g_strjoin(".", current_protocol, $2->str, NULL);
+ field_info_add_alias(full_field_name, $3);
+ g_free(full_field_name);
+}
+
+
+field: FIELD TEXT QUOTED ',' field_type ',' field_location ';'
+{
+ working_field.name = g_strjoin(".", current_protocol, $2->str, NULL);
+ working_field.short_name = g_strdup($2->str);
+ working_field.description = g_strdup($3->str);
+
+ field_info_add(&working_field, current_protocol);
+ field_info_zero(&working_field);
+}
+
+
+field_type: BOOLEAN
+{
+ working_field.field_type = FTYPE_BOOLEAN;
+ working_field.length = FLEN_BOOLEAN;
+}
+ | ETHER
+{
+ working_field.field_type = FTYPE_ETHER;
+ working_field.length = FLEN_ETHER;
+}
+ | UINT8
+{
+ working_field.field_type = FTYPE_UINT8;
+ working_field.length = FLEN_UINT8;
+}
+ | UINT16
+{
+ working_field.field_type = FTYPE_UINT16;
+ working_field.length = FLEN_UINT16;
+}
+ | UINT32
+{
+ working_field.field_type = FTYPE_UINT32;
+ working_field.length = FLEN_UINT32;
+}
+ | BYTE '[' NUMBER ']'
+{
+ working_field.field_type = FTYPE_BYTE;
+ working_field.length = $3;
+}
+ ;
+
+field_location: AND_MASK '(' NUMBER '@' NUMBER ')'
+{
+ working_field.computation_type = CTYPE_ANDMASK;
+ working_field.value = $3;
+ working_field.offset = $5;
+}
+ | BYTE_OFFSET '(' NUMBER ')'
+{
+ working_field.computation_type = CTYPE_BYTECMP;
+ working_field.offset = $3;
+}
+ | EITHER_OF '(' text_list ')'
+{
+ working_field.computation_type = CTYPE_EITHEROF;
+ working_field.many_list = field_info_list($3, current_protocol);
+ g_slist_free($3);
+}
+
+ ;
+
+text_list: TEXT
+{
+ $$ = g_slist_alloc();
+ g_slist_append($$, $1);
+}
+ | text_list ',' TEXT
+{
+ $$ = $1;
+ g_slist_append($$, $3);
+}
+
+ ;
diff --git a/wiretap/ct-main.c b/wiretap/ct-main.c
new file mode 100644
index 0000000000..bb709e16fc
--- /dev/null
+++ b/wiretap/ct-main.c
@@ -0,0 +1,24 @@
+/* ct-main.c
+ * ---------
+ * Wiretap filter compilter
+ */
+
+
+#include <stdio.h>
+
+#include "ct-compile.h"
+
+
+int main(void)
+{
+ FILE *yyin;
+
+ yyin = stdin;
+
+ compiler_init();
+ yyparse();
+ write_rt_lex();
+ write_rt_yacc();
+
+ return 0;
+}
diff --git a/wiretap/ct-scanner.l b/wiretap/ct-scanner.l
new file mode 100644
index 0000000000..9da70d828e
--- /dev/null
+++ b/wiretap/ct-scanner.l
@@ -0,0 +1,74 @@
+%{
+#include <glib.h>
+#include <stdio.h>
+#include "ct-tokdefs.h"
+int lex_line_number = 1;
+%}
+
+N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B [0-9A-Fa-f][0-9A-Fa-f]?
+W [A-Za-z_]
+quoted \"[^"\n]*["\n]
+
+%%
+
+\n lex_line_number++;
+[\t ]+ /* eat whitespace */
+#.* /* one-line shell-style comments */
+
+{quoted} {
+ yylval.s = g_string_new(yytext + 1);
+ g_string_truncate(yylval.s, strlen(yytext) - 2);
+/* g_print("lex made QUOTED (%s)\n", yylval.s->str);*/
+ return QUOTED;
+}
+
+";" return ';';
+"," return ',';
+"(" return '(';
+")" return ')';
+"@" return '@';
+"[" return '[';
+"]" return ']';
+
+protocol return PROTOCOL;
+parents return PARENTS;
+field return FIELD;
+alias return ALIAS;
+
+boolean return BOOLEAN;
+ether return ETHER;
+uint8 return UINT8;
+uint16 return UINT16;
+uint32 return UINT32;
+byte return BYTE;
+
+and_mask return AND_MASK;
+byte_offset return BYTE_OFFSET;
+either_of return EITHER_OF;
+
+
+{N} {
+ yylval.d = atoi(yytext);
+ return NUMBER;
+}
+
+{W}+ {
+ yylval.s = g_string_new(yytext);
+/* g_print("lex made TEXT (%s)\n", yylval.s->str);*/
+ return TEXT;
+ }
+
+%%
+
+int
+yywrap()
+{
+ return 1;
+}
+
+void yyerror(char *string)
+{
+ fprintf(stderr,"%s on line %d\n",string, lex_line_number);
+ exit(0);
+}
diff --git a/wiretap/file.c b/wiretap/file.c
index 4003fc6868..5a13761002 100644
--- a/wiretap/file.c
+++ b/wiretap/file.c
@@ -1,6 +1,6 @@
/* file.c
*
- * $Id: file.c,v 1.8 1999/02/20 06:49:26 guy Exp $
+ * $Id: file.c,v 1.9 1999/03/01 18:57:04 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -25,6 +25,7 @@
#include <string.h>
#include <stdlib.h>
#include "wtap.h"
+#include "buffer.h"
#include "lanalyzer.h"
#include "ngsniffer.h"
#include "libpcap.h"
@@ -50,7 +51,14 @@ wtap* wtap_open_offline(char *filename)
return NULL;
}
- /* Try all my file types */
+ /* initialization */
+ wth->file_encap = WTAP_ENCAP_NONE;
+ wth->filter.offline = NULL;
+ wth->filter_type = WTAP_FILTER_NONE;
+ wth->filter_length = 0;
+ wth->offline_filter_lengths = NULL;
+
+ /* Try all file types */
/* WTAP_FILE_PCAP */
if ((wth->file_type = libpcap_open(wth)) != WTAP_FILE_UNKNOWN) {
@@ -89,8 +97,7 @@ wtap* wtap_open_offline(char *filename)
return wth;
success:
- buffer_init(&wth->frame_buffer, 1500);
- wth->frame_number = 0;
- wth->file_byte_offset = 0;
+ wth->frame_buffer = g_malloc(sizeof(struct Buffer));
+ buffer_init(wth->frame_buffer, 1500);
return wth;
}
diff --git a/wiretap/filter-eth b/wiretap/filter-eth
new file mode 100644
index 0000000000..4bed0033cd
--- /dev/null
+++ b/wiretap/filter-eth
@@ -0,0 +1,38 @@
+# filter-eth
+#
+# Ethernet Filter
+#
+
+protocol eth "Ethernet";
+#length variable;
+parents none;
+
+field src "Source Hardware Address",
+ ether,
+ byte_offset(6);
+
+field dst "Destination Hardware Address",
+ ether,
+ byte_offset(0);
+
+field srcvendor "Vendor of Source Hardware Address",
+ byte[3],
+ byte_offset(6);
+
+field dstvendor "Vendor of Destination Hardware Address",
+ byte[3],
+ byte_offset(0);
+
+alias src srcaddr;
+alias dst dest, dstaddr, destaddr;
+
+field addr "Hardware Address",
+ ether,
+ either_of(src, dst);
+
+alias addr hwaddr;
+
+field vendor "Hardware Vendor",
+ byte[3],
+ either_of(srcvendor, dstvendor);
+
diff --git a/wiretap/filter-tr b/wiretap/filter-tr
new file mode 100644
index 0000000000..bfc704754e
--- /dev/null
+++ b/wiretap/filter-tr
@@ -0,0 +1,57 @@
+# filter-tr
+#
+# Token-Ring Filter
+#
+
+protocol tr "Token-Ring";
+#length variable;
+parents none;
+
+field sr "Source-Routed Flag",
+ boolean,
+ and_mask(127 @ 8);
+
+field src "Source Hardware Address",
+ ether,
+ byte_offset(8);
+
+field dst "Destination Hardware Address",
+ ether,
+ byte_offset(2);
+
+field srcvendor "Vendor of Source Hardware Address",
+ byte[3],
+ byte_offset(8);
+
+field dstvendor "Vendor of Destination Hardware Address",
+ byte[3],
+ byte_offset(2);
+
+field _next "Next protocol layer",
+ uint8,
+ and_mask(192 @ 1);
+
+alias src srcaddr;
+alias dst dest, dstaddr, destaddr;
+alias dstvendor destvendor;
+
+field addr "Hardware Address",
+ ether,
+ either_of(src, dst);
+
+alias addr hwaddr;
+
+field vendor "Hardware Vendor",
+ byte[3],
+ either_of(srcvendor, dstvendor);
+
+
+#next_protocol {
+# 64 : trmac
+# 128 : llc
+#}
+
+#next_offset {
+# ldx
+# df
+#}
diff --git a/wiretap/glib-new.c b/wiretap/glib-new.c
new file mode 100644
index 0000000000..5b88f1d8da
--- /dev/null
+++ b/wiretap/glib-new.c
@@ -0,0 +1,92 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#ifdef HAVE_GLIB10
+
+#include <glib.h>
+#include <stdarg.h>
+#include <string.h>
+
+gpointer
+g_memdup (const gpointer mem,
+ guint byte_size)
+{
+ gpointer new_mem;
+
+ if (mem)
+ {
+ new_mem = g_malloc (byte_size);
+ memcpy (new_mem, mem, byte_size);
+ }
+ else
+ new_mem = NULL;
+
+ return new_mem;
+}
+
+gchar*
+g_strjoin (const gchar *separator,
+ ...)
+{
+ gchar *string, *s;
+ va_list args;
+ guint len;
+ guint separator_len;
+
+ if(separator == NULL)
+ separator = "";
+
+ separator_len = strlen (separator);
+
+ va_start(args, separator);
+
+ s = va_arg(args, gchar *);
+
+ if(s) {
+ len = strlen(s) + 1;
+
+ while((s = va_arg(args, gchar*)))
+ {
+ len += separator_len + strlen(s);
+ }
+ va_end(args);
+
+ string = g_new (gchar, len);
+
+ va_start(args, separator);
+
+ *string = 0;
+ s = va_arg(args, gchar*);
+ strcat (string, s);
+
+ while((s = va_arg(args, gchar*)))
+ {
+ strcat(string, separator);
+ strcat(string, s);
+ }
+
+ } else
+ string = g_strdup("");
+
+ va_end(args);
+
+ return string;
+}
+#endif
diff --git a/wiretap/glib-new.h b/wiretap/glib-new.h
new file mode 100644
index 0000000000..f6ddb14088
--- /dev/null
+++ b/wiretap/glib-new.h
@@ -0,0 +1,26 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+gpointer
+g_memdup (const gpointer mem,
+ guint byte_size);
+
+gchar*
+g_strjoin (const gchar *separator,
+ ...);
diff --git a/wiretap/iptrace.c b/wiretap/iptrace.c
index 02445c3257..a8244ed3f2 100644
--- a/wiretap/iptrace.c
+++ b/wiretap/iptrace.c
@@ -1,6 +1,6 @@
/* iptrace.c
*
- * $Id: iptrace.c,v 1.2 1999/01/07 16:15:35 gram Exp $
+ * $Id: iptrace.c,v 1.3 1999/03/01 18:57:04 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -24,6 +24,7 @@
#include <time.h>
#include <string.h>
#include "wtap.h"
+#include "buffer.h"
#include "iptrace.h"
int iptrace_open(wtap *wth)
@@ -70,9 +71,9 @@ int iptrace_read(wtap *wth)
packet_size = pntohs(&header[2]) - 32;
/* Read the packet data */
- buffer_assure_space(&wth->frame_buffer, packet_size);
+ buffer_assure_space(wth->frame_buffer, packet_size);
data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
diff --git a/wiretap/lanalyzer.c b/wiretap/lanalyzer.c
index f8e2dd556d..fcf3fc6414 100644
--- a/wiretap/lanalyzer.c
+++ b/wiretap/lanalyzer.c
@@ -1,6 +1,6 @@
/* lanalyzer.c
*
- * $Id: lanalyzer.c,v 1.8 1999/01/29 17:06:56 gram Exp $
+ * $Id: lanalyzer.c,v 1.9 1999/03/01 18:57:05 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <time.h>
#include "wtap.h"
+#include "buffer.h"
#include "lanalyzer.h"
int lanalyzer_open(wtap *wth)
@@ -111,13 +112,13 @@ int lanalyzer_open(wtap *wth)
board_type = pletohs(&summary[188]);
switch (board_type) {
case 226:
- wth->encapsulation = WTAP_ENCAP_ETHERNET;
+ wth->file_encap = WTAP_ENCAP_ETHERNET;
break;
case 227:
- wth->encapsulation = WTAP_ENCAP_TR;
+ wth->file_encap = WTAP_ENCAP_TR;
break;
default:
- wth->encapsulation = WTAP_ENCAP_NONE;
+ wth->file_encap = WTAP_ENCAP_NONE;
}
break;
@@ -183,9 +184,9 @@ int lanalyzer_read(wtap *wth)
}
/* Read the packet data */
- buffer_assure_space(&wth->frame_buffer, packet_size);
+ buffer_assure_space(wth->frame_buffer, packet_size);
data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
@@ -214,7 +215,7 @@ int lanalyzer_read(wtap *wth)
wth->phdr.len = true_size - 4;
wth->phdr.caplen = packet_size;
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
return data_offset;
}
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c
index bb9d0361c9..d57d18ec79 100644
--- a/wiretap/libpcap.c
+++ b/wiretap/libpcap.c
@@ -1,6 +1,6 @@
/* libpcap.c
*
- * $Id: libpcap.c,v 1.3 1999/01/07 16:15:36 gram Exp $
+ * $Id: libpcap.c,v 1.4 1999/03/01 18:57:05 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -21,6 +21,7 @@
*
*/
#include "wtap.h"
+#include "buffer.h"
#include "libpcap.h"
/* See source to the "libpcap" library for information on the "libpcap"
@@ -133,10 +134,8 @@ int libpcap_open(wtap *wth)
wth->capture.pcap->version_major = hdr.version_major;
wth->capture.pcap->version_minor = hdr.version_minor;
wth->subtype_read = libpcap_read;
- wth->encapsulation = pcap_encap[hdr.network];
+ wth->file_encap = pcap_encap[hdr.network];
wth->snapshot_length = hdr.snaplen;
- /*wth->frame_number = 0;*/
- /*wth->file_byte_offset = 0x10b;*/
return WTAP_FILE_PCAP;
}
@@ -188,9 +187,9 @@ int libpcap_read(wtap *wth)
}
packet_size = hdr.incl_len;
- buffer_assure_space(&wth->frame_buffer, packet_size);
+ buffer_assure_space(wth->frame_buffer, packet_size);
data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
@@ -207,7 +206,7 @@ int libpcap_read(wtap *wth)
wth->phdr.ts.tv_usec = hdr.ts_usec;
wth->phdr.caplen = packet_size;
wth->phdr.len = hdr.orig_len;
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
return data_offset;
}
diff --git a/wiretap/netmon.c b/wiretap/netmon.c
index ef62603dd6..8e53a8dbc5 100644
--- a/wiretap/netmon.c
+++ b/wiretap/netmon.c
@@ -1,6 +1,6 @@
/* netmon.c
*
- * $Id: netmon.c,v 1.4 1999/02/20 06:46:33 guy Exp $
+ * $Id: netmon.c,v 1.5 1999/03/01 18:57:05 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -23,6 +23,7 @@
#include <netinet/in.h>
#include <time.h>
#include "wtap.h"
+#include "buffer.h"
#include "netmon.h"
/* The file at
@@ -117,7 +118,7 @@ int netmon_open(wtap *wth)
/* This is a netmon file */
wth->capture.netmon = g_malloc(sizeof(netmon_t));
wth->subtype_read = netmon_read;
- wth->encapsulation = netmon_encap[hdr.network];
+ wth->file_encap = netmon_encap[hdr.network];
wth->snapshot_length = 16384; /* XXX - not available in header */
/*
* Convert the time stamp to a "time_t" and a number of
@@ -153,8 +154,6 @@ int netmon_open(wtap *wth)
* more packets to read.
*/
wth->capture.netmon->end_offset = pletohl(&hdr.frametableoffset);
- /*wth->frame_number = 0;*/
- /*wth->file_byte_offset = 0x10b;*/
/* Seek to the beginning of the data records. */
fseek(wth->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET);
@@ -191,8 +190,8 @@ int netmon_read(wtap *wth)
data_offset += sizeof hdr;
packet_size = pletohs(&hdr.incl_len);
- buffer_assure_space(&wth->frame_buffer, packet_size);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ buffer_assure_space(wth->frame_buffer, packet_size);
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
@@ -212,7 +211,7 @@ int netmon_read(wtap *wth)
wth->phdr.ts.tv_usec = msecs*1000;
wth->phdr.caplen = packet_size;
wth->phdr.len = pletohs(&hdr.orig_len);
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
return data_offset;
}
diff --git a/wiretap/netxray.c b/wiretap/netxray.c
index 35fcacc7b0..741a80b00b 100644
--- a/wiretap/netxray.c
+++ b/wiretap/netxray.c
@@ -1,6 +1,6 @@
/* netxray.c
*
- * $Id: netxray.c,v 1.1 1999/02/20 06:49:26 guy Exp $
+ * $Id: netxray.c,v 1.2 1999/03/01 18:57:06 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -25,6 +25,7 @@
#include <time.h>
#include "wtap.h"
#include "netxray.h"
+#include "buffer.h"
/* Capture file header, *including* magic number, is padded to 128 bytes. */
#define CAPTUREFILE_HEADER_SIZE 128
@@ -37,7 +38,12 @@ static const char netxray_magic[] = { /* magic header */
/* NetXRay file header (minus magic number). */
struct netxray_hdr {
char version[8]; /* version number */
- guint32 xxx[10]; /* unknown */
+ guint32 xxx[3]; /* unknown */
+ guint32 start_offset; /* offset of first packet in capture */
+ guint32 end_offset; /* offset after last packet in capture */
+ guint32 xxy[3]; /* unknown */
+ guint16 network; /* datalink type */
+ guint8 xxz[6];
guint32 timelo; /* lower 32 bits of time stamp */
guint32 timehi; /* upper 32 bits of time stamp */
/*
@@ -69,8 +75,13 @@ int netxray_open(wtap *wth)
int bytes_read;
char magic[sizeof netxray_magic];
struct netxray_hdr hdr;
- double timeunit;
- double t;
+ double timeunit;
+ double t;
+ static const int netxray_encap[] = {
+ WTAP_ENCAP_ETHERNET,
+ WTAP_ENCAP_TR
+ };
+ #define NUM_NETXRAY_ENCAPS (sizeof netxray_encap / sizeof netxray_encap[0])
/* Read in the string that should be at the start of a NetXRay
* file */
@@ -102,10 +113,16 @@ int netxray_open(wtap *wth)
return WTAP_FILE_UNKNOWN;
}
+ hdr.network = pletohs(&hdr.network);
+ if (hdr.network >= NUM_NETXRAY_ENCAPS) {
+ g_error("netxray: network type %d unknown", hdr.network);
+ return WTAP_FILE_UNKNOWN;
+ }
+
/* This is a netxray file */
wth->capture.netxray = g_malloc(sizeof(netxray_t));
wth->subtype_read = netxray_read;
- wth->encapsulation = WTAP_ENCAP_ETHERNET; /* XXX - where is it? */
+ wth->file_encap = netxray_encap[hdr.network];
wth->snapshot_length = 16384; /* XXX - not available in header */
wth->capture.netxray->timeunit = timeunit;
t = (double)pletohl(&hdr.timelo)
@@ -115,8 +132,14 @@ int netxray_open(wtap *wth)
/*wth->frame_number = 0;*/
/*wth->file_byte_offset = 0x10b;*/
+ /* Remember the offset after the last packet in the capture (which
+ * isn't necessarily the last packet in the file), as it appears
+ * there's sometimes crud after it. */
+ wth->capture.netxray->wrapped = 0;
+ wth->capture.netxray->end_offset = pletohl(&hdr.end_offset);
+
/* Seek to the beginning of the data records. */
- fseek(wth->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET);
+ fseek(wth->fh, pletohl(&hdr.start_offset), SEEK_SET);
return WTAP_FILE_NETXRAY;
}
@@ -130,6 +153,13 @@ int netxray_read(wtap *wth)
int data_offset;
double t;
+reread:
+ /* Have we reached the end of the packet data? */
+ data_offset = ftell(wth->fh);
+ if (data_offset == wth->capture.netxray->end_offset) {
+ /* Yes. */
+ return 0;
+ }
/* Read record header. */
bytes_read = fread(&hdr, 1, sizeof hdr, wth->fh);
if (bytes_read != sizeof hdr) {
@@ -138,14 +168,23 @@ int netxray_read(wtap *wth)
bytes_read);
return -1;
}
+
+ /* We're at EOF. Wrap? */
+ if (!wth->capture.netxray->wrapped) {
+ /* Yes. Remember that we did. */
+ wth->capture.netxray->wrapped = 1;
+ fseek(wth->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET);
+ goto reread;
+ }
+
+ /* We've already wrapped - don't wrap again. */
return 0;
}
data_offset += sizeof hdr;
packet_size = pletohs(&hdr.incl_len);
- buffer_assure_space(&wth->frame_buffer, packet_size);
- data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ buffer_assure_space(wth->frame_buffer, packet_size);
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
@@ -169,7 +208,7 @@ int netxray_read(wtap *wth)
*1.0e6);
wth->phdr.caplen = packet_size;
wth->phdr.len = pletohs(&hdr.orig_len);
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
return data_offset;
}
diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c
index 6b74696d93..d3480b4053 100644
--- a/wiretap/ngsniffer.c
+++ b/wiretap/ngsniffer.c
@@ -1,6 +1,6 @@
/* ngsniffer.c
*
- * $Id: ngsniffer.c,v 1.11 1999/01/07 16:15:36 gram Exp $
+ * $Id: ngsniffer.c,v 1.12 1999/03/01 18:57:06 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -59,6 +59,7 @@
#include <stdlib.h>
#include <time.h>
#include "wtap.h"
+#include "buffer.h"
#include "ngsniffer.h"
/*
@@ -290,8 +291,6 @@ int ngsniffer_open(wtap *wth)
wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
wth->subtype_read = ngsniffer_read;
wth->snapshot_length = 16384; /* not available in header, only in frame */
- /*wth->frame_number = 0;*/
- /*wth->file_byte_offset = 0x10b;*/
/*
* Read the first record, which the manual says is a version
@@ -317,7 +316,7 @@ int ngsniffer_open(wtap *wth)
/* Make sure this is an uncompressed Sniffer file */
if (version.format != 1) {
- g_message("ngsniffer: This Sniffer file type is not supported");
+ g_message("ngsniffer: Compressed Sniffer files are not supported");
free(wth->capture.ngsniffer);
return WTAP_FILE_UNKNOWN;
}
@@ -329,7 +328,7 @@ int ngsniffer_open(wtap *wth)
return WTAP_FILE_UNKNOWN;
}
else {
- wth->encapsulation = sniffer_encap[version.network];
+ wth->file_encap = sniffer_encap[version.network];
}
/* Get time unit */
@@ -404,8 +403,8 @@ int ngsniffer_open(wtap *wth)
* anyway; the only place you lose is with FORE
* SPANS.
*/
- wth->encapsulation = get_atm_linktype(wth);
- if (wth->encapsulation == -1) {
+ wth->file_encap = get_atm_linktype(wth);
+ if (wth->file_encap == -1) {
/*
* Oops, we couldn't find a link type we can
* handle.
@@ -675,7 +674,7 @@ int ngsniffer_read(wtap *wth)
linktype = linktype_for_packet(
frame4.atm_info.AppTrafType,
frame4.atm_info.AppHLType);
- if (wth->encapsulation != linktype)
+ if (wth->file_encap != linktype)
break;
/*
@@ -714,7 +713,7 @@ found:
* leaves an Ethernet/802.3 header for Ethernet/802.3, and
* leaves a pad byte and an 802.5 frame control byte for 802.5.
*/
- if (wth->capture.ngsniffer->is_atm && wth->encapsulation != WTAP_ENCAP_ATM_RFC1483) {
+ if (wth->capture.ngsniffer->is_atm && wth->file_encap != WTAP_ENCAP_ATM_RFC1483) {
if (length <= ATM_LANE_HEADER_LEN)
return -1;
fseek(wth->fh, ATM_LANE_HEADER_LEN, SEEK_CUR);
@@ -726,9 +725,9 @@ found:
/*
* Read the packet data.
*/
- buffer_assure_space(&wth->frame_buffer, length);
+ buffer_assure_space(wth->frame_buffer, length);
data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
length, wth->fh);
if (bytes_read != length) {
@@ -746,6 +745,6 @@ found:
wth->phdr.ts.tv_sec = (long)t;
wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec))
*1.0e6);
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
return data_offset;
}
diff --git a/wiretap/rt-compile.c b/wiretap/rt-compile.c
new file mode 100644
index 0000000000..f1c225f3cf
--- /dev/null
+++ b/wiretap/rt-compile.c
@@ -0,0 +1,82 @@
+/*
+ * rt-compile.c
+ * ------------
+ *
+ */
+
+#include <glib.h>
+#include "wtap.h"
+#include "bpf.h"
+#include "rt-compile.h"
+#include "rt-global.h"
+
+int (*mk_attach)
+ (wtap *wth);
+
+/* Takes a string representing a display filter, compiles it, and
+if the filter compiles successfully, attaches the filter to the wtap handle.
+The tricky part comes from the fact that some display filters are
+datalink-type-independent (they refer to layers 3 and above of the OSI
+protocol stack), whereas others are datalink-type-dependent. Furthermore, some
+trace files supported by wiretap can handle more than one datalink type.
+
+We rely on the user to use the proper logic for multiple datalink types. For
+example, if the user has a trace file with ethernet and token-ring packets,
+and wants to filter on the MAC-layer broadcast address, he should write:
+
+ (eth.dst eq ff:ff:ff:ff:ff:ff or tr.dst eq ff:ff:ff:ff:ff:ff)
+
+That is, "eth.dst eq ...." fails for a token-ring interface, and
+"tr.dst eq ...." fails for an ethernet device. A logical "or" is needed
+to find MAC-level broadcast addresses in both datalink types. */
+
+int wtap_offline_filter(wtap *wth, char *filter)
+{
+ int encap_type;
+
+ if (!filter)
+ return 0;
+
+ /* temporary hack */
+ if (filter[0] == 0) {
+ wtap_filter_offline_clear(wth);
+ return 0;
+ }
+
+ /* we use the BPF engine for offline filters */
+ wtap_filter_offline_init(wth);
+ wth->filter_text = g_strdup(filter);
+
+ /* if the file format we are using has a per-file encapsulation
+ * type, then we can go ahead and compile the display filter for
+ * that datalink type. Otherwise, we'll guess ethernet.
+ */
+ if (wth->file_encap != WTAP_ENCAP_NONE)
+ encap_type = wth->file_encap;
+ else
+ encap_type = WTAP_ENCAP_ETHERNET;
+
+ if (!wtap_offline_filter_compile(wth, encap_type)) {
+ wtap_filter_offline_clear(wth);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* this function is called from within wiretap to recompile the same display
+ * filter for a different datalink type. This is needed for trace files that
+ * have more than one encapsulation type in the same file
+ */
+int wtap_offline_filter_compile(wtap *wth, int encap_type)
+{
+ comp_encap_type = encap_type;
+ filter_parsed = 0;
+ lex_init(wth->filter_text);
+ wtap_parse();
+
+ if (!filter_parsed)
+ return 0;
+
+ return mk_attach(wth);
+}
diff --git a/wiretap/rt-compile.h b/wiretap/rt-compile.h
new file mode 100644
index 0000000000..d383ea130a
--- /dev/null
+++ b/wiretap/rt-compile.h
@@ -0,0 +1,29 @@
+
+#ifndef __WTAP_H_
+#include "wtap.h"
+#endif
+
+/* Holds info for fields defined as bytecmp. */
+typedef struct {
+ int ftype;
+ int ctype;
+ int offset;
+ int length;
+} bytecmp_info;
+
+
+/* Holds info for fields defined as either_of */
+typedef struct {
+ int ftype;
+ int ctype;
+ int field1;
+ int field2;
+} eitherof_info;
+
+int wtap_lex(void);
+int wtap_parse(void);
+void wtap_error(char *string);
+
+void lex_init(char *);
+
+int wtap_offline_filter_compile(wtap *wth, int encap_type);
diff --git a/wiretap/rt-global.h b/wiretap/rt-global.h
new file mode 100644
index 0000000000..952acc939a
--- /dev/null
+++ b/wiretap/rt-global.h
@@ -0,0 +1,23 @@
+
+
+extern GList* (*mk_bytecmp)
+ (int ftype, int rel_opcode, guint8 *bytes);
+
+extern void (*mk_optimize)
+ (GList *L);
+
+
+/* for those modules that are interested in mk_attach,
+ * wtap.h will have already been included.
+ */
+#ifdef __WTAP_H__
+extern int (*mk_attach)
+ (wtap *wth);
+#endif
+
+extern bytecmp_info bytecmp_table[];
+extern int comp_encap_type;
+extern int filter_parsed;
+
+bytecmp_info* lookup_bytecmp(int ftype);
+eitherof_info* lookup_eitherof(int ftype);
diff --git a/wiretap/rt-grammar-skel.y b/wiretap/rt-grammar-skel.y
new file mode 100644
index 0000000000..b14d7b31f1
--- /dev/null
+++ b/wiretap/rt-grammar-skel.y
@@ -0,0 +1,134 @@
+%{
+
+#ifndef __G_LIB_H__
+#include <glib.h>
+#endif
+
+#include "rt-compile.h"
+#include "rt-global.h"
+#include "ct-compile.h"
+
+GList* (*mk_bytecmp) (int ftype, int rel_opcode, guint8 *bytes);
+void (*mk_optimize) (GList *L);
+
+/* The encapsulation type for which we are compiling the filter */
+int comp_encap_type;
+int filter_parsed = 0;
+
+bytecmp_info *bytecmp;
+eitherof_info *either;
+GList *L1, *L2;
+
+/* ct-compile: bytecmp_table */
+/*bytecmp_info bytecmp_table[] = {
+ { ETH_TYPE, 12, 2 },
+ { TR_DST, 2, 6 },
+ { TR_SRC, 8, 6 },
+ { ETH_DSTVENDOR, 0, 3 },
+ { 0, 0, 0 }
+};*/
+
+/* ct-compile: eitherof_table */
+/*eitherof_table[] = {
+ { TR_VENDOR, CTYPE_BYTECMP, TR_SRCVENDOR, TR_DSTVENDOR },
+ { TR_ADDR, CTYPE_BYTECMP, TR_SRCADDR, TR_DSTADDR }
+};
+*/
+%}
+
+%union {
+ gint d;
+ guint8 *b;
+ GString *s;
+ GList *L;
+}
+
+%type <d> bytecmp_lval
+%type <L> sentence bytecmp_relation
+%type <d> bytecmp_test;
+
+%token <b> BYTES
+%token <s> QUOTED TEXT
+%token <d> NUMBER
+%token <d> EQ NE
+
+/* ct-compile: yacc tokens */
+
+%%
+
+paragraph: /* EMPTY */
+ | paragraph sentence { mk_optimize($2); filter_parsed = 1; }
+ ;
+
+sentence: bytecmp_relation { $$ = $1 }
+ ;
+
+
+bytecmp_relation: bytecmp_lval bytecmp_test BYTES
+{
+ bytecmp = lookup_bytecmp($1);
+ if (bytecmp->ctype == CTYPE_EITHEROF) {
+ either = lookup_eitherof($1);
+ L1 = mk_bytecmp(either->field1, $2, $3);
+ L2 = mk_bytecmp(either->field2, $2, $3);
+ $$ = g_list_concat(L1, L2);
+ }
+ else {
+ $$ = mk_bytecmp($1, $2, $3);
+ }
+}
+ ;
+
+/* ct-compile: bytecmp_lval */
+/*bytecmp_lval: TR_DST { $$ = TR_DST; }
+ | TR_SRC { $$ = TR_SRC; }
+ | TR_SRCVENDOR { $$ = TR_SRCVENDOR; }
+ | TR_DSTVENDOR { $$ = TR_DSTVENDOR; }
+ ;*/
+
+bytecmp_test: EQ { $$ = EQ; }
+ | NE { $$ = NE; }
+ ;
+
+%%
+
+bytecmp_info*
+lookup_bytecmp(int ftype)
+{
+ bytecmp_info *b = &bytecmp_table[0];
+ bytecmp_info *ret_val = NULL;
+
+ /* find the field in the table */
+ while (b->ftype != 0) {
+ if (b->ftype == ftype) {
+ ret_val = b;
+ break;
+ }
+ else {
+ b++;
+ }
+ }
+
+ return ret_val;
+}
+
+
+eitherof_info*
+lookup_eitherof(int ftype)
+{
+ eitherof_info *e = &eitherof_table[0];
+ eitherof_info *ret_val = NULL;
+
+ /* find the field in the table */
+ while (e->ftype != 0) {
+ if (e->ftype == ftype) {
+ ret_val = e;
+ break;
+ }
+ else {
+ e++;
+ }
+ }
+
+ return ret_val;
+}
diff --git a/wiretap/rt-scanner-skel.l b/wiretap/rt-scanner-skel.l
new file mode 100644
index 0000000000..311d85a0c5
--- /dev/null
+++ b/wiretap/rt-scanner-skel.l
@@ -0,0 +1,161 @@
+%{
+#include <glib.h>
+#include "rt-tokdefs.h"
+guint8* parse_bytes(char *text);
+enum nibble_t { high, low };
+static char *in_buffer;
+
+/* from libpcap */
+#ifdef FLEX_SCANNER
+#define YY_NO_UNPUT
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max)\
+ {\
+ char *src = in_buffer;\
+ int i;\
+\
+ if (*src == 0)\
+ result = YY_NULL;\
+ else {\
+ for (i = 0; *src && i < max; ++i)\
+ buf[i] = *src++;\
+ in_buffer += i;\
+ result = i;\
+ }\
+ }
+#else
+#undef getc
+#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++)
+#endif
+
+
+%}
+
+N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B [0-9A-Fa-f][0-9A-Fa-f]?([-:.]?[0-9A-Fa-f][0-9A-Fa-f]?)*
+W [A-Za-z_]
+quoted \"[^"\n]*["\n]
+
+%%
+
+[\n\t ]+ /* eat whitespace */
+
+{quoted} {
+ wtap_lval.s = g_string_new(wtap_text + 1);
+ g_string_truncate(wtap_lval.s, strlen(wtap_text) - 2);
+ return QUOTED;
+}
+
+";" return ';';
+"," return ',';
+"(" return '(';
+")" return ')';
+"@" return '@';
+
+/* ct-compile: lex tokens */
+
+eq return EQ;
+ne return NE;
+
+{B} {
+ wtap_lval.b = parse_bytes(wtap_text);
+ return BYTES;
+}
+
+{N} {
+ wtap_lval.d = atoi(wtap_text);
+ return NUMBER;
+}
+
+{W}+ {
+ wtap_lval.s = g_string_new(wtap_text);
+ return TEXT;
+ }
+
+%%
+
+guint8*
+parse_bytes(char *text)
+{
+ guint8 buffer[256];
+ guint8 index = 0;
+ char *cp;
+ char character;
+ guint8 byte_val=0;
+ gchar *dup_ptr;
+ enum nibble_t nibble = high;
+
+ for (cp = text; (*cp != '\x0') && index < 256; cp++) {
+ character = *cp;
+
+ if (nibble == high) {
+ /* assumes ASCII, not EBCDIC */
+ if (character >= '0' && character <= '9') {
+ byte_val = (character - '0') << 4;
+ }
+ else if (character >= 'A' && character <= 'F') {
+ byte_val = (character - 'A' + 10) << 4;
+ }
+ else if (character >= 'a' && character <= 'f') {
+ byte_val = (character - 'a' + 10) << 4;
+ }
+ else {
+ continue;
+ }
+ nibble = low;
+ continue;
+ }
+ else {
+ /* assumes ASCII, not EBCDIC */
+ if (character >= '0' && character <= '9') {
+ byte_val += (character - '0');
+ }
+ else if (character >= 'A' && character <= 'F') {
+ byte_val += (character - 'A' + 10);
+ }
+ else if (character >= 'a' && character <= 'f') {
+ byte_val += (character - 'a' + 10);
+ }
+ else {
+ byte_val >>= 4;
+ }
+ nibble = high;
+
+ buffer[index] = byte_val;
+ index++;
+ }
+
+ }
+
+ /* did we finish mid-nibble? */
+ if (nibble == low) {
+ buffer[index] = byte_val >> 4;
+ index++;
+ }
+
+ dup_ptr = g_malloc(index + 1);
+ dup_ptr[0] = index;
+ memcpy(dup_ptr + 1, buffer, index);
+ return dup_ptr;
+}
+
+
+void wtap_error(char *string)
+{
+ g_error("%s\n",string);
+ exit(0);
+}
+
+/* from libpcap */
+void
+lex_init(char *buf)
+{
+ in_buffer = buf;
+}
+
+int
+yywrap()
+{
+ return 1;
+}
+
diff --git a/wiretap/snoop.c b/wiretap/snoop.c
index 12130e57bc..55e9dc3ba0 100644
--- a/wiretap/snoop.c
+++ b/wiretap/snoop.c
@@ -1,6 +1,6 @@
/* snoop.c
*
- * $Id: snoop.c,v 1.3 1999/02/20 06:46:57 guy Exp $
+ * $Id: snoop.c,v 1.4 1999/03/01 18:57:07 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -21,6 +21,7 @@
*
*/
#include "wtap.h"
+#include "buffer.h"
#include "snoop.h"
#include <netinet/in.h>
@@ -98,10 +99,8 @@ int snoop_open(wtap *wth)
/* This is a snoop file */
wth->subtype_read = snoop_read;
- wth->encapsulation = snoop_encap[hdr.network];
+ wth->file_encap = snoop_encap[hdr.network];
wth->snapshot_length = 16384; /* XXX - not available in header */
- /*wth->frame_number = 0;*/
- /*wth->file_byte_offset = 0x10b;*/
return WTAP_FILE_SNOOP;
}
@@ -126,9 +125,9 @@ int snoop_read(wtap *wth)
}
packet_size = ntohl(hdr.incl_len);
- buffer_assure_space(&wth->frame_buffer, packet_size);
+ buffer_assure_space(wth->frame_buffer, packet_size);
data_offset = ftell(wth->fh);
- bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
+ bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
packet_size, wth->fh);
if (bytes_read != packet_size) {
@@ -145,7 +144,7 @@ int snoop_read(wtap *wth)
wth->phdr.ts.tv_usec = ntohl(hdr.ts_usec);
wth->phdr.caplen = packet_size;
wth->phdr.len = ntohl(hdr.orig_len);
- wth->phdr.pkt_encap = wth->encapsulation;
+ wth->phdr.pkt_encap = wth->file_encap;
/* Skip over the padding. */
fseek(wth->fh, ntohl(hdr.rec_len) - (sizeof hdr + packet_size),
diff --git a/wiretap/wiretap.c b/wiretap/wiretap.c
new file mode 100644
index 0000000000..0df269f34f
--- /dev/null
+++ b/wiretap/wiretap.c
@@ -0,0 +1,297 @@
+
+#include <stdio.h>
+#include <glib.h>
+#include "wtap.h"
+#include "bpf-engine.h"
+#include "glib-new.h"
+
+void bpf_dump(wtap *wth);
+char *bpf_image(struct bpf_instruction *p, int n);
+
+int main(int argc, char **argv)
+{
+ wtap *wth;
+ char *fsyntax = "";
+ int i;
+
+ if (argc <= 1) {
+ fprintf(stderr, "usage: wiretap filter\n");
+ exit(-1);
+ }
+
+ for (i = 1; i < argc; i++) {
+ fsyntax = g_strjoin(" ", fsyntax, argv[i], NULL);
+ }
+
+ wth = wtap_open_offline("/home/gram/prj/sniff/test.trace");
+ wtap_offline_filter(wth, fsyntax);
+/* wtap_offline_filter_compile(wth, WTAP_ENCAP_ETHERNET);*/
+ bpf_dump(wth);
+
+ return 0;
+}
+
+void
+bpf_dump(wtap *wth)
+{
+ struct bpf_instruction *fentry;
+ int flen;
+ int i;
+
+ fentry = wth->filter.offline[WTAP_ENCAP_ETHERNET];
+ flen = wth->offline_filter_lengths[WTAP_ENCAP_ETHERNET];
+
+ /* this loop is from tcpdump's bpf_dump.c */
+ for (i = 0; i < flen; ++fentry, ++i) {
+ puts(bpf_image(fentry, i));
+ }
+}
+
+/* this entire function is from libpcap's bpf_image.c */
+char *
+bpf_image(struct bpf_instruction *p, int n)
+{
+ int v;
+ char *fmt, *op;
+ static char image[256];
+ char operand[64];
+
+ v = p->k;
+ switch (p->code) {
+
+ default:
+ op = "unimp";
+ fmt = "0x%x";
+ v = p->code;
+ break;
+
+ case BPF_RET|BPF_K:
+ op = "ret";
+ fmt = "#%d";
+ break;
+
+ case BPF_RET|BPF_A:
+ op = "ret";
+ fmt = "";
+ break;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ op = "ld";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ op = "ldh";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ op = "ldb";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ op = "ld";
+ fmt = "#pktlen";
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ op = "ld";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ op = "ldh";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ op = "ldb";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_IMM:
+ op = "ld";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ op = "ldx";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ op = "ldxb";
+ fmt = "4*([%d]&0xf)";
+ break;
+
+ case BPF_LD|BPF_MEM:
+ op = "ld";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ op = "ldx";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_ST:
+ op = "st";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_STX:
+ op = "stx";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_JMP|BPF_JA:
+ op = "ja";
+ fmt = "%d";
+ v = n + 1 + p->k;
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ op = "jgt";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ op = "jge";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ op = "jeq";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ op = "jset";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ op = "jgt";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ op = "jge";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ op = "jeq";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ op = "jset";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ op = "add";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ op = "sub";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ op = "mul";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ op = "div";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ op = "and";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ op = "or";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ op = "lsh";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ op = "rsh";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ op = "add";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ op = "sub";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ op = "mul";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ op = "div";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ op = "and";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ op = "or";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ op = "lsh";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ op = "rsh";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ op = "neg";
+ fmt = "";
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ op = "tax";
+ fmt = "";
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ op = "txa";
+ fmt = "";
+ break;
+ }
+ (void)sprintf(operand, fmt, v);
+ (void)sprintf(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);
+ return image;
+}
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 28f34b50e9..e002d18e01 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -1,6 +1,6 @@
/* wtap.c
*
- * $Id: wtap.c,v 1.6 1999/02/12 16:26:09 gram Exp $
+ * $Id: wtap.c,v 1.7 1999/03/01 18:57:07 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -22,6 +22,9 @@
*/
#include "wtap.h"
+#include "buffer.h"
+#include "bpf-engine.h"
+#include "rt-compile.h"
FILE* wtap_file(wtap *wth)
{
@@ -58,6 +61,10 @@ void wtap_close(wtap *wth)
g_free(wth->capture.ngsniffer);
break;
+ case WTAP_FILE_NETMON:
+ g_free(wth->capture.netmon);
+ break;
+
/* default:
nothing */
}
@@ -67,13 +74,36 @@ void wtap_close(wtap *wth)
void wtap_loop(wtap *wth, int count, wtap_handler callback, u_char* user)
{
- int i = 0;
int data_offset;
+ int ret;
+ int pkt_encap;
while ((data_offset = wth->subtype_read(wth)) > 0) {
- i++;
- /*g_message("Parsing packet %d", i);*/
- callback(user, &wth->phdr, data_offset,
- buffer_start_ptr(&wth->frame_buffer));
+ /* offline filter? */
+ if (wth->filter_type == WTAP_FILTER_OFFLINE) {
+ pkt_encap = wth->phdr.pkt_encap;
+
+ /* do we have a compiled filter for this
+ * encapsulation type? */
+ if (!wth->filter.offline[pkt_encap])
+ wtap_offline_filter_compile(wth, pkt_encap);
+
+ /* run the filter */
+ ret = bpf_run_filter(
+ buffer_start_ptr(wth->frame_buffer),
+ wth->phdr.caplen,
+ wth->filter.offline[pkt_encap],
+ wth->offline_filter_lengths[pkt_encap]
+ );
+
+ /* if the packet made it through the filter,
+ * send the data to the user */
+ if (ret > 0)
+ callback(user, &wth->phdr, data_offset,
+ buffer_start_ptr(wth->frame_buffer));
+ }
+ else
+ callback(user, &wth->phdr, data_offset,
+ buffer_start_ptr(wth->frame_buffer));
}
}
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 12c2c32caa..26efe06fa2 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1,6 +1,6 @@
/* wtap.h
*
- * $Id: wtap.h,v 1.13 1999/02/20 06:49:26 guy Exp $
+ * $Id: wtap.h,v 1.14 1999/03/01 18:57:07 gram Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -21,6 +21,9 @@
*
*/
+#ifndef __WTAP_H__
+#define __WTAP_H__
+
/* Encapsulation types. Choose names that truly reflect
* what is contained in the packet trace file. */
#define WTAP_ENCAP_NONE 0
@@ -33,6 +36,9 @@
#define WTAP_ENCAP_ARCNET 7
#define WTAP_ENCAP_ATM_RFC1483 8
+/* last WTAP_ENCAP_ value + 1 */
+#define WTAP_NUM_ENCAP_TYPES 9
+
/* File types that can be read by wiretap */
#define WTAP_FILE_UNKNOWN 0
#define WTAP_FILE_WTAP 1
@@ -44,11 +50,18 @@
#define WTAP_FILE_NETMON 8
#define WTAP_FILE_NETXRAY 9
+/* Filter types that wiretap can create. An 'offline' filter is really
+ * a BPF filter, but it is treated specially because wiretap might not know
+ * in advance the datalink type(s) needed.
+ */
+#define WTAP_FILTER_NONE 0
+#define WTAP_FILTER_OFFLINE 1
+#define WTAP_FILTER_BPF 2
+
#include <sys/types.h>
#include <sys/time.h>
#include <glib.h>
#include <stdio.h>
-#include <buffer.h>
typedef struct {
double timeunit;
@@ -81,6 +94,8 @@ typedef struct {
typedef struct {
double timeunit;
double starttime;
+ int wrapped;
+ int end_offset;
} netxray_t;
struct wtap_pkthdr {
@@ -94,14 +109,15 @@ typedef void (*wtap_handler)(u_char*, const struct wtap_pkthdr*,
int, const u_char *);
struct wtap;
+struct bpf_instruction;
+struct Buffer;
+
typedef int (*subtype_func)(struct wtap*);
typedef struct wtap {
FILE* fh;
- int file_type;
- int snapshot_length;
- unsigned long frame_number;
- unsigned long file_byte_offset;
- Buffer frame_buffer;
+ int file_type;
+ int snapshot_length;
+ struct Buffer *frame_buffer;
struct wtap_pkthdr phdr;
union {
@@ -112,13 +128,28 @@ typedef struct wtap {
netxray_t *netxray;
} capture;
- subtype_func subtype_read;
- int encapsulation;
+ subtype_func subtype_read;
+ int file_encap; /* per-file, for those
+ file formats that have
+ per-file encapsulation
+ types */
+ union {
+ struct bpf_instruction *bpf;
+ struct bpf_instruction **offline;
+ } filter;
+
+ gchar *filter_text;
+ int filter_type;
+ int filter_length; /* length in bytes or records,
+ depending upon filter_type */
+
+ int *offline_filter_lengths;
} wtap;
wtap* wtap_open_offline(char *filename);
void wtap_loop(wtap *wth, int, wtap_handler, u_char*);
+int wtap_offline_filter(wtap *wth, char *filter);
FILE* wtap_file(wtap *wth);
int wtap_snapshot_length(wtap *wth); /* per file */
@@ -131,22 +162,30 @@ void wtap_close(wtap *wth);
* The pletoh[sl] versions return the little-endian representation.
*/
+#ifndef pntohs
#define pntohs(p) ((guint16) \
((guint16)*((guint8 *)p+0)<<8| \
(guint16)*((guint8 *)p+1)<<0))
+#endif
+#ifndef pntohl
#define pntohl(p) ((guint32)*((guint8 *)p+0)<<24| \
(guint32)*((guint8 *)p+1)<<16| \
(guint32)*((guint8 *)p+2)<<8| \
(guint32)*((guint8 *)p+3)<<0)
+#endif
+#ifndef pletohs
#define pletohs(p) ((guint16) \
((guint16)*((guint8 *)p+1)<<8| \
(guint16)*((guint8 *)p+0)<<0))
+#endif
+#ifndef plethol
#define pletohl(p) ((guint32)*((guint8 *)p+3)<<24| \
(guint32)*((guint8 *)p+2)<<16| \
(guint32)*((guint8 *)p+1)<<8| \
(guint32)*((guint8 *)p+0)<<0)
+#endif
-
+#endif /* __WTAP_H__ */