diff options
Diffstat (limited to 'wiretap')
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, µ) != 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, µ) != 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__ */ |