diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2012-10-21 16:00:07 +0200 |
---|---|---|
committer | Thomas Bogendoerfer <tbogendoerfer@suse.de> | 2021-01-18 14:06:15 +0100 |
commit | 139d79d0b53424dfe015b2152b5c71b616f4ea3a (patch) | |
tree | 142c46d25279ed185fb875f254a78202ee8a23d8 | |
parent | a73f23d445e1c92f42d8b20abdc78f122b55ea72 (diff) | |
download | tme-139d79d0b53424dfe015b2152b5c71b616f4ea3a.tar.gz |
added tap support
-rwxr-xr-x | configure | 38 | ||||
-rw-r--r-- | configure.in | 3 | ||||
-rw-r--r-- | host/Makefile.am | 2 | ||||
-rw-r--r-- | host/Makefile.in | 2 | ||||
-rw-r--r-- | host/net/Makefile.am | 14 | ||||
-rw-r--r-- | host/net/Makefile.in | 658 | ||||
-rw-r--r-- | host/net/net-tap.c | 751 |
7 files changed, 1451 insertions, 17 deletions
@@ -7325,10 +7325,17 @@ rm -f conftest* fi +ac_fn_c_check_header_mongrel "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_if_tun_h" = x""yes; then : + tme_raw_type=tap +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for raw Ethernet access method" >&5 $as_echo_n "checking for raw Ethernet access method... " >&6; } case "x$tme_raw_type" in xbpf) TME_HOSTS="${TME_HOSTS} bsd" ;; +xtap) TME_HOSTS="${TME_HOSTS} net" ;; x) tme_raw_type=none ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tme_raw_type" >&5 @@ -9217,13 +9224,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:9220: $ac_compile\"" >&5) + (eval echo "\"\$as_me:9227: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:9223: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:9230: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:9226: output\"" >&5) + (eval echo "\"\$as_me:9233: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -10428,7 +10435,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 10431 "configure"' > conftest.$ac_ext + echo '#line 10438 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -11684,11 +11691,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11687: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11694: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11691: \$? = $ac_status" >&5 + echo "$as_me:11698: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12023,11 +12030,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12026: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12033: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12030: \$? = $ac_status" >&5 + echo "$as_me:12037: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12128,11 +12135,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12131: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12138: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12135: \$? = $ac_status" >&5 + echo "$as_me:12142: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12183,11 +12190,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12186: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12193: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12190: \$? = $ac_status" >&5 + echo "$as_me:12197: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14567,7 +14574,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 14570 "configure" +#line 14577 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14663,7 +14670,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 14666 "configure" +#line 14673 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14935,7 +14942,7 @@ fi ac_config_commands="$ac_config_commands default-1" -ac_config_files="$ac_config_files Makefile tme/Makefile tme/ic/Makefile tme/machine/Makefile tme/generic/Makefile tme/scsi/Makefile tme/host/Makefile tme/bus/Makefile libtme/Makefile libtme/host/Makefile libtme/host/x86/Makefile ic/Makefile ic/m68k/Makefile ic/ieee754/Makefile ic/sparc/Makefile ic/stp22xx/Makefile machine/Makefile machine/sun/Makefile machine/sun2/Makefile machine/sun3/Makefile machine/sun4/Makefile machine/sun4u/Makefile host/Makefile host/posix/Makefile host/bsd/Makefile host/gtk/Makefile bus/Makefile bus/multibus/Makefile bus/sbus/Makefile serial/Makefile scsi/Makefile generic/Makefile tmesh/Makefile tools/Makefile" +ac_config_files="$ac_config_files Makefile tme/Makefile tme/ic/Makefile tme/machine/Makefile tme/generic/Makefile tme/scsi/Makefile tme/host/Makefile tme/bus/Makefile libtme/Makefile libtme/host/Makefile libtme/host/x86/Makefile ic/Makefile ic/m68k/Makefile ic/ieee754/Makefile ic/sparc/Makefile ic/stp22xx/Makefile machine/Makefile machine/sun/Makefile machine/sun2/Makefile machine/sun3/Makefile machine/sun4/Makefile machine/sun4u/Makefile host/Makefile host/posix/Makefile host/bsd/Makefile host/gtk/Makefile host/net/Makefile bus/Makefile bus/multibus/Makefile bus/sbus/Makefile serial/Makefile scsi/Makefile generic/Makefile tmesh/Makefile tools/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -15953,6 +15960,7 @@ do "host/posix/Makefile") CONFIG_FILES="$CONFIG_FILES host/posix/Makefile" ;; "host/bsd/Makefile") CONFIG_FILES="$CONFIG_FILES host/bsd/Makefile" ;; "host/gtk/Makefile") CONFIG_FILES="$CONFIG_FILES host/gtk/Makefile" ;; + "host/net/Makefile") CONFIG_FILES="$CONFIG_FILES host/net/Makefile" ;; "bus/Makefile") CONFIG_FILES="$CONFIG_FILES bus/Makefile" ;; "bus/multibus/Makefile") CONFIG_FILES="$CONFIG_FILES bus/multibus/Makefile" ;; "bus/sbus/Makefile") CONFIG_FILES="$CONFIG_FILES bus/sbus/Makefile" ;; diff --git a/configure.in b/configure.in index 6041d5b..a06761a 100644 --- a/configure.in +++ b/configure.in @@ -172,9 +172,11 @@ AC_CHECK_HEADER(net/bpf.h, found_BIOCSHDRCMPLT #endif ], [tme_raw_type=bpf])]) +AC_CHECK_HEADER(linux/if_tun.h, [tme_raw_type=tap]) AC_MSG_CHECKING([for raw Ethernet access method]) case "x$tme_raw_type" in xbpf) TME_HOSTS="${TME_HOSTS} bsd" ;; +xtap) TME_HOSTS="${TME_HOSTS} net" ;; x) tme_raw_type=none ;; esac AC_MSG_RESULT($tme_raw_type) @@ -853,6 +855,7 @@ AC_OUTPUT(Makefile host/posix/Makefile host/bsd/Makefile host/gtk/Makefile + host/net/Makefile bus/Makefile bus/multibus/Makefile bus/sbus/Makefile diff --git a/host/Makefile.am b/host/Makefile.am index 015d51e..76b4161 100644 --- a/host/Makefile.am +++ b/host/Makefile.am @@ -3,4 +3,4 @@ AUTOMAKE_OPTIONS = 1.4 gnu SUBDIRS = @TME_HOSTS@ -DIST_SUBDIRS = posix bsd gtk +DIST_SUBDIRS = posix bsd gtk net diff --git a/host/Makefile.in b/host/Makefile.in index aa0ded6..f3cb896 100644 --- a/host/Makefile.in +++ b/host/Makefile.in @@ -230,7 +230,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = 1.4 gnu SUBDIRS = @TME_HOSTS@ -DIST_SUBDIRS = posix bsd gtk +DIST_SUBDIRS = posix bsd gtk net all: all-recursive .SUFFIXES: diff --git a/host/net/Makefile.am b/host/net/Makefile.am new file mode 100644 index 0000000..17ca725 --- /dev/null +++ b/host/net/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in +# Makefile.am for The Machine Emulator host/net: + +AUTOMAKE_OPTIONS = 1.4 gnu + +INCLUDES = -I$(top_srcdir) -I$(srcdir) -I. -D_TME_IMPL + +pkglib_LTLIBRARIES = tme_host_net.la +tme_host_net_la_SOURCES = net-tap.c +tme_host_net_la_LDFLAGS = -module -version-info 0:0:0 +tme_host_net_la_LIBADD = $(top_builddir)/libtme/libtme.la \ + $(top_builddir)/generic/libtme-generic.la + +include $(top_srcdir)/modules diff --git a/host/net/Makefile.in b/host/net/Makefile.in new file mode 100644 index 0000000..33acb6f --- /dev/null +++ b/host/net/Makefile.in @@ -0,0 +1,658 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for The Machine Emulator host/net: + +# $Id: modules,v 1.1 2003/05/16 21:48:04 fredette Exp $ + +# Copyright (c) 2003 Matt Fredette +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Matt Fredette. +# 4. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/modules +subdir = host/net +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +tme_host_net_la_DEPENDENCIES = $(top_builddir)/libtme/libtme.la \ + $(top_builddir)/generic/libtme-generic.la +am_tme_host_net_la_OBJECTS = net-tap.lo +tme_host_net_la_OBJECTS = $(am_tme_host_net_la_OBJECTS) +tme_host_net_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(tme_host_net_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(tme_host_net_la_SOURCES) +DIST_SOURCES = $(tme_host_net_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAGS_NO_STRICT_ALIASING = @CFLAGS_NO_STRICT_ALIASING@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEC_LT_LDFLAGS = @EXEC_LT_LDFLAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_LDFLAGS = @LT_LDFLAGS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TME_BUS_SUBDIRS = @TME_BUS_SUBDIRS@ +TME_FB_XLAT_DST = @TME_FB_XLAT_DST@ +TME_FB_XLAT_SRC = @TME_FB_XLAT_SRC@ +TME_HOSTS = @TME_HOSTS@ +TME_ICS = @TME_ICS@ +TME_IC_SUBDIRS = @TME_IC_SUBDIRS@ +TME_MACHINE_SUBDIRS = @TME_MACHINE_SUBDIRS@ +TME_PREOPEN = @TME_PREOPEN@ +TME_SERIALS = @TME_SERIALS@ +TME_SERIAL_SUBDIRS = @TME_SERIAL_SUBDIRS@ +VERSION = @VERSION@ +XMKMF = @XMKMF@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = 1.4 gnu +INCLUDES = -I$(top_srcdir) -I$(srcdir) -I. -D_TME_IMPL +pkglib_LTLIBRARIES = tme_host_net.la +tme_host_net_la_SOURCES = net-tap.c +tme_host_net_la_LDFLAGS = -module -version-info 0:0:0 +tme_host_net_la_LIBADD = $(top_builddir)/libtme/libtme.la \ + $(top_builddir)/generic/libtme-generic.la + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/modules $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu host/net/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu host/net/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +tme_host_net.la: $(tme_host_net_la_OBJECTS) $(tme_host_net_la_DEPENDENCIES) + $(tme_host_net_la_LINK) -rpath $(pkglibdir) $(tme_host_net_la_OBJECTS) $(tme_host_net_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net-tap.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) all-local +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + + +# this automake include file must be included in all directories that +# build modules. it updates the modules index that will be installed +# along with all of the modules, and also handles some static building +# details. this is done with an all-local target: +all-local: +# +# first, all source files in the current directory are searched for +# element "new" function declarations. these declarations provide +# enough information to determine the published module name, the +# libtool module name, and "submodule" name. this information is +# appended to a tme-plugins.txt file, which will be installed in +# $(pkglibdir). +# +# the choice of $(top_builddir)/tme/tme-plugins.txt is important. +# when debugging, the person doing the debugging is expected to have +# the good sense to set LTDL_LIBRARY_PATH to $(top_builddir), so +# module.c will correctly use the uninstalled plugins list for all +# "tme/" modules. +# +# this is abuse of the $(top_builddir)/tme directory, yes, since +# this directory was originally just for include files and to make +# #include <tme/FOO.h> work right when building: + @echo updating tme modules list.. + @grep TME_ELEMENT_NEW_DECL $(srcdir)/*.c | \ + sed -e 's%.*TME_ELEMENT_NEW_DECL(\(.*\)).*%\1%' \ + >> $(top_builddir)/tme/tme-plugins.txt + @grep TME_ELEMENT_SUB_NEW_DECL $(srcdir)/*.c | \ + sed -e 's%.*TME_ELEMENT_SUB_NEW_DECL(\(.*\),\(.*\)).*%\1_\2 \1 \2%' \ + >> $(top_builddir)/tme/tme-plugins.txt + @grep TME_ELEMENT_X_NEW_DECL $(srcdir)/*.c | \ + sed -e 's%.*TME_ELEMENT_X_NEW_DECL(\(.*\),\(.*\),\(.*\)).*%\1\3 \1\2 \3%' \ + >> $(top_builddir)/tme/tme-plugins.txt +# +# next, when building statically, either for debugging purposes or +# because we're on a weak platform, we have to use libtool's "preopen" +# mechanism. +# +# this means at least specifying all of the modules that could +# potentially be lt_dlopen'ed on any main program's link command line, +# using libtool's -dlpreopen option. +# +# so we append suitable -dlpreopen options for all modules built in +# this directory to a file, in this case +# $(top_builddir)/tme-preopen.txt. when building statically, +# configure.in will then substitute @TME_PREOPEN@ with: +# +# `cat $(top_builddir)/tme-preopen.txt` +# +# else it will substitute the empty string. when linking programs, +# @TME_PREOPEN@ is then used on the program's link command line. +# +# additionally, libtool, at least through version 1.5, has a +# limitation in that the pseudo-library (the .la file) must be present +# even for a preloaded module. if we aren't debugging, everything is +# installed, so this is not a problem. +# +# however, if we are debugging, nothing is installed, so we have to do +# something to make sure that the .la files can be found. +# +# the person doing the debugging is already expected to set +# LTDL_LIBRARY_PATH to the top of the build directory, so that +# module.c can find the uninstalled tme-plugins.txt file, and libtool +# will want to look in this directory for .la files, so we simply copy +# all of the .la files into that same directory: + @if test "x$(pkglib_LTLIBRARIES)" != x; then \ + for module in $(pkglib_LTLIBRARIES); do \ + echo $$module ; \ + echo -dlpreopen ../$(subdir)/$$module >> $(top_builddir)/tme-preopen.txt ; \ + cp $$module $(top_builddir)/tme ; \ + done ; \ + fi + +# 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. +.NOEXPORT: diff --git a/host/net/net-tap.c b/host/net/net-tap.c new file mode 100644 index 0000000..0e1b3cc --- /dev/null +++ b/host/net/net-tap.c @@ -0,0 +1,751 @@ +/* $Id: $ */ + +/* host/net/net-tap.c - TUN/TAP Ethernet support: */ + +/* + * Copyright (c) 2012 Thomas Bogendörfer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Matt Fredette. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <tme/common.h> +_TME_RCSID("$Id: $"); + +/* includes: */ +#include <tme/generic/ethernet.h> +#include <tme/threads.h> +#include <tme/misc.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#if defined(HAVE_SYS_SOCKIO_H) +#include <sys/sockio.h> +#elif defined(HAVE_SYS_SOCKETIO_H) +#include <sys/socketio.h> +#endif /* HAVE_SYS_SOCKETIO_H */ +#include <sys/ioctl.h> +#ifdef HAVE_IOCTLS_H +#include <ioctls.h> +#endif /* HAVE_IOCTLS_H */ +#ifdef HAVE_NET_IF_ETHER_H +#include <net/if_ether.h> +#endif /* HAVE_NET_IF_ETHER_H */ +#ifdef HAVE_NET_ETHERNET_H +#include <net/ethernet.h> +#endif /* HAVE_NET_ETHERNET_H */ +#include <netinet/ip.h> +#ifdef HAVE_NET_IF_DL_H +#include <net/if_dl.h> +#endif /* HAVE_NET_IF_DL_H */ +#include <arpa/inet.h> + +/* FIXME: Linux specific part, needs to be adapted */ +#include <net/if.h> +#include <linux/if_tun.h> + +/* macros: */ + +/* ARP and RARP opcodes: */ +#define TME_NET_ARP_OPCODE_REQUEST (0x0001) +#define TME_NET_ARP_OPCODE_REPLY (0x0002) +#define TME_NET_ARP_OPCODE_REV_REQUEST (0x0003) +#define TME_NET_ARP_OPCODE_REV_REPLY (0x0004) + +/* the callout flags: */ +#define TME_NET_TAP_CALLOUT_CHECK (0) +#define TME_NET_TAP_CALLOUT_RUNNING TME_BIT(0) +#define TME_NET_TAP_CALLOUTS_MASK (-2) +#define TME_NET_TAP_CALLOUT_CTRL TME_BIT(1) +#define TME_NET_TAP_CALLOUT_READ TME_BIT(2) + +/* structures: */ + +/* our internal data structure: */ +struct tme_net_tap { + + /* backpointer to our element: */ + struct tme_element *tme_net_tap_element; + + /* our mutex: */ + tme_mutex_t tme_net_tap_mutex; + + /* our reader condition: */ + tme_cond_t tme_net_tap_cond_reader; + + /* the callout flags: */ + unsigned int tme_net_tap_callout_flags; + + /* our Ethernet connection: */ + struct tme_ethernet_connection *tme_net_tap_eth_connection; + + /* the BPF file descriptor: */ + int tme_net_tap_fd; + + /* the size of the packet buffer for the interface: */ + size_t tme_net_tap_buffer_size; + + /* the packet buffer for the interface: */ + tme_uint8_t *tme_net_tap_buffer; + + /* the next offset within the packet buffer, and the end of the data + in the packet buffer: */ + size_t tme_net_tap_buffer_offset; + size_t tme_net_tap_buffer_end; + + /* timestamp for buffer receive */ + struct timeval tme_net_tap_rx_tstamp; + + /* when nonzero, the packet delay time, in microseconds: */ + unsigned long tme_net_tap_delay_time; + + /* all packets received on or before this time can be released: */ + struct timeval tme_net_tap_delay_release; + + /* when nonzero, the packet delay sleep time, in microseconds: */ + unsigned long tme_net_tap_delay_sleep; + + /* when nonzero, the packet delay is sleeping: */ + int tme_net_tap_delay_sleeping; +}; + +static int +_tme_net_tap_alloc(char *dev, int flags) { + + struct ifreq ifr; + int fd, err; + char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + /* open the clone device */ + if( (fd = open(clonedev, O_RDWR)) < 0 ) { + return fd; + } + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + + +/* the bpf callout function. it must be called with the mutex locked: */ +static void +_tme_net_tap_callout(struct tme_net_tap *bpf, int new_callouts) +{ + struct tme_ethernet_connection *conn_eth; + int callouts, later_callouts; + unsigned int ctrl; + int rc; + int status; + tme_ethernet_fid_t frame_id; + struct tme_ethernet_frame_chunk frame_chunk_buffer; + tme_uint8_t frame[TME_ETHERNET_FRAME_MAX]; + + /* add in any new callouts: */ + bpf->tme_net_tap_callout_flags |= new_callouts; + + /* if this function is already running in another thread, simply + return now. the other thread will do our work: */ + if (bpf->tme_net_tap_callout_flags & TME_NET_TAP_CALLOUT_RUNNING) { + return; + } + + /* callouts are now running: */ + bpf->tme_net_tap_callout_flags |= TME_NET_TAP_CALLOUT_RUNNING; + + /* assume that we won't need any later callouts: */ + later_callouts = 0; + + /* loop while callouts are needed: */ + for (; (callouts = bpf->tme_net_tap_callout_flags) & TME_NET_TAP_CALLOUTS_MASK; ) { + + tme_log(&bpf->tme_net_tap_element->tme_element_log_handle, 1, TME_OK, + (&bpf->tme_net_tap_element->tme_element_log_handle, + _("callout %x"), callouts)); + /* clear the needed callouts: */ + bpf->tme_net_tap_callout_flags = callouts & ~TME_NET_TAP_CALLOUTS_MASK; + callouts &= TME_NET_TAP_CALLOUTS_MASK; + + /* get our Ethernet connection: */ + conn_eth = bpf->tme_net_tap_eth_connection; + + /* if we need to call out new control information: */ + if (callouts & TME_NET_TAP_CALLOUT_CTRL) { + + /* form the new ctrl: */ + ctrl = 0; + if (bpf->tme_net_tap_buffer_offset + < bpf->tme_net_tap_buffer_end) { + ctrl |= TME_ETHERNET_CTRL_OK_READ; + } + + /* unlock the mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + /* do the callout: */ + rc = (conn_eth != NULL + ? ((*conn_eth->tme_ethernet_connection_ctrl) + (conn_eth, + ctrl)) + : TME_OK); + + /* lock the mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* if the callout was unsuccessful, remember that at some later + time this callout should be attempted again: */ + if (rc != TME_OK) { + later_callouts |= TME_NET_TAP_CALLOUT_CTRL; + } + } + + /* if the Ethernet is readable: */ + if (callouts & TME_NET_TAP_CALLOUT_READ) { + + /* unlock the mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + /* make a frame chunk to receive this frame: */ + frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL; + frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = frame; + frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count + = sizeof(frame); + + /* do the callout: */ + rc = (conn_eth == NULL + ? TME_OK + : ((*conn_eth->tme_ethernet_connection_read) + (conn_eth, + &frame_id, + &frame_chunk_buffer, + TME_ETHERNET_READ_NEXT))); + + /* lock the mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* if the read was successful: */ + if (rc > 0) { + + /* check the size of the frame: */ + assert(rc <= sizeof(frame)); + + /* do the write: */ + status = tme_thread_write(bpf->tme_net_tap_fd, frame, rc); + + /* writes must succeed: */ + assert (status == rc); + + /* mark that we need to loop to callout to read more frames: */ + bpf->tme_net_tap_callout_flags |= TME_NET_TAP_CALLOUT_READ; + } + + /* otherwise, the read failed. convention dictates that we + forget that the connection was readable, which we already + have done by clearing the CALLOUT_READ flag: */ + } + + } + /* put in any later callouts, and clear that callouts are running: */ + bpf->tme_net_tap_callout_flags = later_callouts; +} + +/* the BPF reader thread: */ +static void +_tme_net_tap_th_reader(struct tme_net_tap *bpf) +{ + ssize_t buffer_end; + unsigned long sleep_usec; + + /* lock the mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* loop forever: */ + for (;;) { + + /* if the delay sleeping flag is set: */ + if (bpf->tme_net_tap_delay_sleeping) { + + /* clear the delay sleeping flag: */ + bpf->tme_net_tap_delay_sleeping = FALSE; + + /* call out that we can be read again: */ + _tme_net_tap_callout(bpf, TME_NET_TAP_CALLOUT_CTRL); + } + + /* if a delay has been requested: */ + sleep_usec = bpf->tme_net_tap_delay_sleep; + if (sleep_usec > 0) { + + /* clear the delay sleep time: */ + bpf->tme_net_tap_delay_sleep = 0; + + /* set the delay sleeping flag: */ + bpf->tme_net_tap_delay_sleeping = TRUE; + + /* unlock our mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + /* sleep for the delay sleep time: */ + tme_thread_sleep_yield(0, sleep_usec); + + /* lock our mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + continue; + } + + /* if the buffer is not empty, wait until either it is, + or we're asked to do a delay: */ + if (bpf->tme_net_tap_buffer_offset + < bpf->tme_net_tap_buffer_end) { + tme_cond_wait_yield(&bpf->tme_net_tap_cond_reader, + &bpf->tme_net_tap_mutex); + continue; + } + + /* unlock the mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + /* read the BPF socket: */ + tme_log(&bpf->tme_net_tap_element->tme_element_log_handle, 1, TME_OK, + (&bpf->tme_net_tap_element->tme_element_log_handle, + _("calling read"))); + buffer_end = + tme_thread_read_yield(bpf->tme_net_tap_fd, + bpf->tme_net_tap_buffer, + bpf->tme_net_tap_buffer_size); + + /* lock the mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* if the read failed: */ + if (buffer_end <= 0) { + tme_log(&bpf->tme_net_tap_element->tme_element_log_handle, 1, errno, + (&bpf->tme_net_tap_element->tme_element_log_handle, + _("failed to read packets"))); + continue; + } + if (buffer_end < 64) buffer_end = 64; + + gettimeofday(&bpf->tme_net_tap_rx_tstamp, NULL); + + /* the read succeeded: */ + tme_log(&bpf->tme_net_tap_element->tme_element_log_handle, 1, TME_OK, + (&bpf->tme_net_tap_element->tme_element_log_handle, + _("read %ld bytes of packets"), (long) buffer_end)); + bpf->tme_net_tap_buffer_offset = 0; + bpf->tme_net_tap_buffer_end = buffer_end; + + /* call out that we can be read again: */ + _tme_net_tap_callout(bpf, TME_NET_TAP_CALLOUT_CTRL); + } + /* NOTREACHED */ +} + +/* this is called when the ethernet configuration changes: */ +static int +_tme_net_tap_config(struct tme_ethernet_connection *conn_eth, + struct tme_ethernet_config *config) +{ + return (TME_OK); +} + +/* this is called when control lines change: */ +static int +_tme_net_tap_ctrl(struct tme_ethernet_connection *conn_eth, + unsigned int ctrl) +{ + struct tme_net_tap *bpf; + int new_callouts; + + /* recover our data structures: */ + bpf = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private; + + /* assume that we won't need any new callouts: */ + new_callouts = 0; + + /* lock the mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* if this connection is readable, call out a read: */ + if (ctrl & TME_ETHERNET_CTRL_OK_READ) { + new_callouts |= TME_NET_TAP_CALLOUT_READ; + } + + /* make any new callouts: */ + _tme_net_tap_callout(bpf, new_callouts); + + /* unlock the mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + return (TME_OK); +} + +/* this is called to read a frame: */ +static int +_tme_net_tap_read(struct tme_ethernet_connection *conn_eth, + tme_ethernet_fid_t *_frame_id, + struct tme_ethernet_frame_chunk *frame_chunks, + unsigned int flags) +{ + struct tme_net_tap *bpf; + struct tme_ethernet_frame_chunk frame_chunk_buffer; + unsigned int count; + int rc; + + /* recover our data structure: */ + bpf = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private; + + /* lock our mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* assume that we won't be able to return a packet: */ + rc = -ENOENT; + + /* loop until we have a good captured packet or until we + exhaust the buffer: */ + for (;;) { + + /* if this packet isn't big enough to even have an Ethernet header: */ + if (bpf->tme_net_tap_buffer_offset + sizeof(struct tme_ethernet_header) + >= bpf->tme_net_tap_buffer_end) { + if (bpf->tme_net_tap_buffer_offset != bpf->tme_net_tap_buffer_end) { + tme_log(&bpf->tme_net_tap_element->tme_element_log_handle, 1, TME_OK, + (&bpf->tme_net_tap_element->tme_element_log_handle, + _("flushed short packet"))); + bpf->tme_net_tap_buffer_offset = bpf->tme_net_tap_buffer_end; + } + break; + } + + /* if packets need to be delayed: */ + if (bpf->tme_net_tap_delay_time > 0) { + + /* if the current release time is before this packet's time: */ + if ((bpf->tme_net_tap_delay_release.tv_sec + < bpf->tme_net_tap_rx_tstamp.tv_sec) + || ((bpf->tme_net_tap_delay_release.tv_sec + == bpf->tme_net_tap_rx_tstamp.tv_sec) + && (bpf->tme_net_tap_delay_release.tv_usec + < bpf->tme_net_tap_rx_tstamp.tv_usec))) { + + /* update the current release time, by taking the current time + and subtracting the delay time: */ + gettimeofday(&bpf->tme_net_tap_delay_release, NULL); + if (bpf->tme_net_tap_delay_release.tv_usec < bpf->tme_net_tap_delay_time) { + bpf->tme_net_tap_delay_release.tv_usec += 1000000UL; + bpf->tme_net_tap_delay_release.tv_sec--; + } + bpf->tme_net_tap_delay_release.tv_usec -= bpf->tme_net_tap_delay_time; + } + + /* if the current release time is still before this packet's + time: */ + if ((bpf->tme_net_tap_delay_release.tv_sec + < bpf->tme_net_tap_rx_tstamp.tv_sec) + || ((bpf->tme_net_tap_delay_release.tv_sec + == bpf->tme_net_tap_rx_tstamp.tv_sec) + && (bpf->tme_net_tap_delay_release.tv_usec + < bpf->tme_net_tap_rx_tstamp.tv_usec))) { + + /* set the sleep time: */ + assert ((bpf->tme_net_tap_delay_release.tv_sec + == bpf->tme_net_tap_rx_tstamp.tv_sec) + || ((bpf->tme_net_tap_delay_release.tv_sec + 1) + == bpf->tme_net_tap_rx_tstamp.tv_sec)); + bpf->tme_net_tap_delay_sleep + = (((bpf->tme_net_tap_delay_release.tv_sec + == bpf->tme_net_tap_rx_tstamp.tv_sec) + ? 0 + : 1000000UL) + + bpf->tme_net_tap_rx_tstamp.tv_usec + - bpf->tme_net_tap_delay_release.tv_usec); + + /* rewind the buffer pointer: */ + bpf->tme_net_tap_buffer_offset = 0; + + /* stop now: */ + break; + } + } + + /* form the single frame chunk: */ + frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL; + frame_chunk_buffer.tme_ethernet_frame_chunk_bytes + = bpf->tme_net_tap_buffer; + frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count + = bpf->tme_net_tap_buffer_end; + + /* copy out the frame: */ + count = tme_ethernet_chunks_copy(frame_chunks, &frame_chunk_buffer); + + /* if this is a peek: */ + if (flags & TME_ETHERNET_READ_PEEK) { + + /* rewind the buffer pointer: */ + bpf->tme_net_tap_buffer_offset = 0; + } + + /* otherwise, this isn't a peek: */ + else { + + /* update the buffer pointer: */ + bpf->tme_net_tap_buffer_offset = bpf->tme_net_tap_buffer_end; + } + + /* success: */ + rc = count; + break; + } + + /* if the buffer is empty, or if we failed to read a packet, + wake up the reader: */ + if ((bpf->tme_net_tap_buffer_offset + >= bpf->tme_net_tap_buffer_end) + || rc <= 0) { + tme_cond_notify(&bpf->tme_net_tap_cond_reader, TRUE); + } + + /* unlock our mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + + /* done: */ + return (rc); +} + +/* this makes a new Ethernet connection: */ +static int +_tme_net_tap_connection_make(struct tme_connection *conn, unsigned int state) +{ + struct tme_net_tap *bpf; + struct tme_ethernet_connection *conn_eth; + struct tme_ethernet_connection *conn_eth_other; + + /* recover our data structures: */ + bpf = conn->tme_connection_element->tme_element_private; + conn_eth = (struct tme_ethernet_connection *) conn; + conn_eth_other = (struct tme_ethernet_connection *) conn->tme_connection_other; + + /* both sides must be Ethernet connections: */ + assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET); + assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET); + + /* we're always set up to answer calls across the connection, so we + only have to do work when the connection has gone full, namely + taking the other side of the connection: */ + if (state == TME_CONNECTION_FULL) { + + /* lock our mutex: */ + tme_mutex_lock(&bpf->tme_net_tap_mutex); + + /* save our connection: */ + bpf->tme_net_tap_eth_connection = conn_eth_other; + + /* unlock our mutex: */ + tme_mutex_unlock(&bpf->tme_net_tap_mutex); + } + + return (TME_OK); +} + +/* this breaks a connection: */ +static int +_tme_net_tap_connection_break(struct tme_connection *conn, unsigned int state) +{ + abort(); +} + +/* this makes a new connection side for a BPF: */ +static int +_tme_net_tap_connections_new(struct tme_element *element, + const char * const *args, + struct tme_connection **_conns, + char **_output) +{ + struct tme_net_tap *bpf; + struct tme_ethernet_connection *conn_eth; + struct tme_connection *conn; + + /* recover our data structure: */ + bpf = (struct tme_net_tap *) element->tme_element_private; + + /* if we already have an Ethernet connection, do nothing: */ + if (bpf->tme_net_tap_eth_connection != NULL) { + return (TME_OK); + } + + /* allocate the new Ethernet connection: */ + conn_eth = tme_new0(struct tme_ethernet_connection, 1); + conn = &conn_eth->tme_ethernet_connection; + + /* fill in the generic connection: */ + conn->tme_connection_next = *_conns; + conn->tme_connection_type = TME_CONNECTION_ETHERNET; + conn->tme_connection_score = tme_ethernet_connection_score; + conn->tme_connection_make = _tme_net_tap_connection_make; + conn->tme_connection_break = _tme_net_tap_connection_break; + + /* fill in the Ethernet connection: */ + conn_eth->tme_ethernet_connection_config = _tme_net_tap_config; + conn_eth->tme_ethernet_connection_ctrl = _tme_net_tap_ctrl; + conn_eth->tme_ethernet_connection_read = _tme_net_tap_read; + + /* return the connection side possibility: */ + *_conns = conn; + + /* done: */ + return (TME_OK); +} + +/* the new BPF function: */ +TME_ELEMENT_SUB_NEW_DECL(tme_host_net,tap) { + struct tme_net_tap *bpf; + int tap_fd; + int saved_errno; + u_int packet_buffer_size = 1536; + char tap_name[IFNAMSIZ]; + unsigned long delay_time; + int arg_i; + int usage; + + /* check our arguments: */ + usage = 0; + tap_name[0] = 0; + delay_time = 0; + arg_i = 1; + for (;;) { + + /* the interface we're supposed to use: */ + if (TME_ARG_IS(args[arg_i + 0], "interface") + && args[arg_i + 1] != NULL) { + strncpy(tap_name, args[arg_i + 1], sizeof tap_name -1); + arg_i += 2; + } + + /* a delay time in microseconds: */ + else if (TME_ARG_IS(args[arg_i + 0], "delay") + && (delay_time = tme_misc_unumber_parse(args[arg_i + 1], 0)) > 0) { + arg_i += 2; + } + + /* if we ran out of arguments: */ + else if (args[arg_i + 0] == NULL) { + break; + } + + /* otherwise this is a bad argument: */ + else { + tme_output_append_error(_output, + "%s %s", + args[arg_i], + _("unexpected")); + usage = TRUE; + break; + } + } + + if (usage) { + tme_output_append_error(_output, + "%s %s [ interface %s ] [ delay %s ]", + _("usage:"), + args[0], + _("INTERFACE"), + _("MICROSECONDS")); + return (EINVAL); + } + + if ((tap_fd = _tme_net_tap_alloc(tap_name, IFF_TAP | IFF_NO_PI)) < 0) { + /* we failed to open this device. */ + saved_errno = errno; + tme_log(&element->tme_element_log_handle, 1, saved_errno, + (&element->tme_element_log_handle, + "%s", tap_name)); + + return (saved_errno); + } + tme_log(&element->tme_element_log_handle, 1, TME_OK, + (&element->tme_element_log_handle, + "opened %s", + tap_name)); + + /* start our data structure: */ + bpf = tme_new0(struct tme_net_tap, 1); + bpf->tme_net_tap_element = element; + bpf->tme_net_tap_fd = tap_fd; + bpf->tme_net_tap_buffer_size = packet_buffer_size; + bpf->tme_net_tap_buffer = tme_new(tme_uint8_t, packet_buffer_size); + bpf->tme_net_tap_delay_time = delay_time; + + /* start the threads: */ + tme_mutex_init(&bpf->tme_net_tap_mutex); + tme_cond_init(&bpf->tme_net_tap_cond_reader); + tme_thread_create((tme_thread_t) _tme_net_tap_th_reader, bpf); + + /* fill the element: */ + element->tme_element_private = bpf; + element->tme_element_connections_new = _tme_net_tap_connections_new; + + return (TME_OK); +} |