core-4.6/0000775000175000017500000000000012220631510007306 500000000000000core-4.6/bootstrap.sh0000775000175000017500000000270411713016476011623 00000000000000#!/bin/sh # # (c)2010-2012 the Boeing Company # # author: Jeff Ahrenholz # # Bootstrap the autoconf system. # if [ x$1 = x ]; then # PASS echo "Bootstrapping the autoconf system..." # echo " These autotools programs should be installed for this script to work:" # echo " aclocal, libtoolize, autoheader, automake, autoconf" echo "(Messages below about copying and installing files are normal.)" elif [ x$1 = xclean ]; then # clean - take out the trash echo "Cleaning up the autoconf mess..." rm -rf autom4te.cache config BSDmakefile exit 0; else # help text echo "usage: $0 [clean]" echo -n " Use this script to bootstrap the autoconf build system prior to " echo "running the " echo " ./configure script." exit 1; fi # try to keep everything nice and tidy in ./config if ! [ -d "config" ]; then mkdir config fi # on FreeBSD, discourage use of make UNAME=`uname` if [ x${UNAME} = xFreeBSD ]; then echo "all:" > BSDmakefile echo ' @echo "Please use GNU make instead by typing:"' >> BSDmakefile echo ' @echo " gmake"' >> BSDmakefile echo ' @echo ""' >> BSDmakefile fi # bootstrapping echo "(1/4) Running aclocal..." && aclocal -I config \ && echo "(2/4) Running autoheader..." && autoheader \ && echo "(3/4) Running automake..." \ && automake --add-missing --copy --foreign \ && echo "(4/4) Running autoconf..." && autoconf \ && echo "" \ && echo "You are now ready to run \"./configure\"." core-4.6/aclocal.m40000664000175000017500000014017112220631417011100 00000000000000# generated automatically by aclocal 1.11.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, # Inc. # This file 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. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, [m4_warning([this file was generated for autoconf 2.68. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # 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. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software # Foundation, Inc. # # This file 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. # serial 1 # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.11.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.11.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file 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. # serial 1 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, # 2010, 2011 Free Software Foundation, Inc. # # This file 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. # serial 12 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file 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. # serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, # Inc. # # This file 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. # serial 1 # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file 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. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file 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. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, # Inc. # # This file 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. # serial 1 # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software # Foundation, Inc. # # This file 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. # serial 5 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, # 2011 Free Software Foundation, Inc. # # This file 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. # serial 2 # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT(yes)], [AC_MSG_ERROR(too old)]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(0,0,prefix='$am_py_prefix'))" 2>/dev/null` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(1,0,prefix='$am_py_exec_prefix'))" 2>/dev/null` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file 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. # serial 1 # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file 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. # serial 1 # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. # # This file 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. # serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. # # This file 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. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR core-4.6/configure0000775000175000017500000070250012220631421011142 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for core 4.6. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: core-dev@pf.itd.nrl.navy.mil about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='core' PACKAGE_TARNAME='core' PACKAGE_VERSION='4.6' PACKAGE_STRING='core 4.6' PACKAGE_BUGREPORT='core-dev@pf.itd.nrl.navy.mil' PACKAGE_URL='' ac_unique_file="daemon/src/version.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS HELP2MAN WANT_SUSE_FALSE WANT_SUSE_TRUE WANT_SYSTEMD_FALSE WANT_SYSTEMD_TRUE WANT_INITD_FALSE WANT_INITD_TRUE WANT_NETNS_FALSE WANT_NETNS_TRUE WANT_PYTHON_FALSE WANT_PYTHON_TRUE WANT_DOCS_FALSE WANT_DOCS_TRUE WANT_BSD_FALSE WANT_BSD_TRUE WANT_DAEMON_FALSE WANT_DAEMON_TRUE WANT_GUI_FALSE WANT_GUI_TRUE with_startup PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG libev_LIBS libev_CFLAGS gmake ARCH LIBOBJS EGREP GREP CPP help2man convert umount_path mount_path vimage_path ngctl_path ifconfig_path tc_path ip_path ebtables_path sysctl_path brctl_path pkgpyexecdir pyexecdir pkgpythondir pythondir PYTHON_PLATFORM PYTHON_EXEC_PREFIX PYTHON_PREFIX PYTHON_VERSION PYTHON RANLIB am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC CORE_STATE_DIR enable_daemon enable_gui CORE_GUI_CONF_DIR CORE_DATA_DIR CORE_CONF_DIR BINDIR SBINDIR CORE_LIB_DIR LIB_DIR COREDPY_VERSION CORE_VERSION_DATE CORE_VERSION am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_guiconfdir enable_gui enable_daemon enable_dependency_tracking with_startup ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS PYTHON CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR libev_CFLAGS libev_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures core 4.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/core] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of core 4.6:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-gui=ARG build and install the GUI (default is yes) --enable-daemon=ARG build and install the daemon with Python modules (default is yes) --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-guiconfdir=dir specify GUI configuration directory --with-startup=option option=systemd,suse,none to install systemd/SUSE init scripts Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory PYTHON the Python interpreter CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path libev_CFLAGS C compiler flags for libev, overriding pkg-config libev_LIBS linker flags for libev, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF core configure 4.6 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------------- ## ## Report this to core-dev@pf.itd.nrl.navy.mil ## ## ------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 $as_echo_n "checking for int$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_intX_t # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 $as_echo_n "checking for uint$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_uintX_t # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by core $as_me 4.6, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu VERSION=$PACKAGE_VERSION CORE_VERSION=$PACKAGE_VERSION CORE_VERSION_DATE=20130925 COREDPY_VERSION=$PACKAGE_VERSION # # autoconf and automake initialization # ac_aux_dir= for ac_dir in config "$srcdir"/config; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ac_config_headers="$ac_config_headers config.h" am__api_version='1.11' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='core' VERSION='4.6' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # # some of the following directory variables are not expanded at configure-time, # so we have special checks to expand them # # CORE GUI files in LIBDIR # AC_PREFIX_DEFAULT is /usr/local, but not expanded yet if test "x$prefix" = "xNONE" ; then prefix="/usr/local" fi if test "$libdir" = "\${exec_prefix}/lib" ; then libdir="${prefix}/lib" fi # this can be /usr/lib or /usr/lib64 LIB_DIR="${libdir}" # don't let the Tcl files install to /usr/lib64/core CORE_LIB_DIR="${prefix}/lib/core" SBINDIR="${prefix}/sbin" BINDIR="${prefix}/bin" # CORE daemon configuration file (core.conf) in CORE_CONF_DIR if test "$sysconfdir" = "\${prefix}/etc" ; then sysconfdir="/etc" CORE_CONF_DIR="/etc/core" else CORE_CONF_DIR="$sysconfdir/core" fi if test "$datarootdir" = "\${prefix}/share" ; then datarootdir="${prefix}/share" fi CORE_DATA_DIR="$datarootdir/core" # CORE GUI configuration files and preferences in CORE_GUI_CONF_DIR # scenario files in ~/.core/configs/ #AC_ARG_VAR(CORE_GUI_CONF_DIR, [GUI configuration directory.]) # Check whether --with-guiconfdir was given. if test "${with_guiconfdir+set}" = set; then : withval=$with_guiconfdir; CORE_GUI_CONF_DIR="$with_guiconfdir" else CORE_GUI_CONF_DIR="\${HOME}/.core" fi # Check whether --enable-gui was given. if test "${enable_gui+set}" = set; then : enableval=$enable_gui; else enable_gui=yes fi # Check whether --enable-daemon was given. if test "${enable_daemon+set}" = set; then : enableval=$enable_daemon; else enable_daemon=yes fi if test "x$enable_daemon" = "xno"; then want_python=no want_bsd=no want_linux_netns=no fi # CORE state files if test "$localstatedir" = "\${prefix}/var" ; then # use /var instead of /usr/local/var (/usr/local/var/log isn't standard) CORE_STATE_DIR="/var" else CORE_STATE_DIR="$localstatedir" fi # default compiler flags # _GNU_SOURCE is defined to get c99 defines for lrint() CFLAGS="$CFLAGS -O3 -Werror -Wall -D_GNU_SOURCE" # debug flags #CFLAGS="$CFLAGS -g -Werror -Wall -D_GNU_SOURCE" # Checks for programs. for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version >= 2.6" >&5 $as_echo_n "checking whether $PYTHON version >= 2.6... " >&6; } prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.6'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else as_fn_error $? "too old" "$LINENO" 5 fi am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.6" >&5 $as_echo_n "checking for a Python interpreter with version >= 2.6... " >&6; } if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else for am_cv_pathless_PYTHON in python python2 python3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.6'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 $as_echo "$am_cv_pathless_PYTHON" >&6; } # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. set dummy $am_cv_pathless_PYTHON; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 $as_echo "$PYTHON" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi am_display_PYTHON=$am_cv_pathless_PYTHON fi if test "$PYTHON" = :; then want_python=no else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 $as_echo_n "checking for $am_display_PYTHON version... " >&6; } if ${am_cv_python_version+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 $as_echo "$am_cv_python_version" >&6; } PYTHON_VERSION=$am_cv_python_version PYTHON_PREFIX='${prefix}' PYTHON_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 $as_echo_n "checking for $am_display_PYTHON platform... " >&6; } if ${am_cv_python_platform+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 $as_echo "$am_cv_python_platform" >&6; } PYTHON_PLATFORM=$am_cv_python_platform { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 $as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } if ${am_cv_python_pythondir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(0,0,prefix='$am_py_prefix'))" 2>/dev/null` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 $as_echo "$am_cv_python_pythondir" >&6; } pythondir=$am_cv_python_pythondir pkgpythondir=\${pythondir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 $as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } if ${am_cv_python_pyexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(1,0,prefix='$am_py_exec_prefix'))" 2>/dev/null` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 $as_echo "$am_cv_python_pyexecdir" >&6; } pyexecdir=$am_cv_python_pyexecdir pkgpyexecdir=\${pyexecdir}/$PACKAGE want_python=yes fi SEARCHPATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin" # # daemon dependencies # if test "x$enable_daemon" = "xyes" ; then # Extract the first word of "brctl", so it can be a program name with args. set dummy brctl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_brctl_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$brctl_path"; then ac_cv_prog_brctl_path="$brctl_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_brctl_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_brctl_path" && ac_cv_prog_brctl_path="no" fi fi brctl_path=$ac_cv_prog_brctl_path if test -n "$brctl_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $brctl_path" >&5 $as_echo "$brctl_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "sysctl", so it can be a program name with args. set dummy sysctl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_sysctl_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$sysctl_path"; then ac_cv_prog_sysctl_path="$sysctl_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_sysctl_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_sysctl_path" && ac_cv_prog_sysctl_path="no" fi fi sysctl_path=$ac_cv_prog_sysctl_path if test -n "$sysctl_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sysctl_path" >&5 $as_echo "$sysctl_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ebtables", so it can be a program name with args. set dummy ebtables; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ebtables_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ebtables_path"; then ac_cv_prog_ebtables_path="$ebtables_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ebtables_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ebtables_path" && ac_cv_prog_ebtables_path="no" fi fi ebtables_path=$ac_cv_prog_ebtables_path if test -n "$ebtables_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ebtables_path" >&5 $as_echo "$ebtables_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ip", so it can be a program name with args. set dummy ip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ip_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ip_path"; then ac_cv_prog_ip_path="$ip_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ip_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ip_path" && ac_cv_prog_ip_path="no" fi fi ip_path=$ac_cv_prog_ip_path if test -n "$ip_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ip_path" >&5 $as_echo "$ip_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "tc", so it can be a program name with args. set dummy tc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_tc_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$tc_path"; then ac_cv_prog_tc_path="$tc_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_tc_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_tc_path" && ac_cv_prog_tc_path="no" fi fi tc_path=$ac_cv_prog_tc_path if test -n "$tc_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tc_path" >&5 $as_echo "$tc_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ifconfig", so it can be a program name with args. set dummy ifconfig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ifconfig_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ifconfig_path"; then ac_cv_prog_ifconfig_path="$ifconfig_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ifconfig_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ifconfig_path" && ac_cv_prog_ifconfig_path="no" fi fi ifconfig_path=$ac_cv_prog_ifconfig_path if test -n "$ifconfig_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ifconfig_path" >&5 $as_echo "$ifconfig_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ngctl", so it can be a program name with args. set dummy ngctl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ngctl_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ngctl_path"; then ac_cv_prog_ngctl_path="$ngctl_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ngctl_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ngctl_path" && ac_cv_prog_ngctl_path="no" fi fi ngctl_path=$ac_cv_prog_ngctl_path if test -n "$ngctl_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ngctl_path" >&5 $as_echo "$ngctl_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "vimage", so it can be a program name with args. set dummy vimage; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_vimage_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$vimage_path"; then ac_cv_prog_vimage_path="$vimage_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_vimage_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_vimage_path" && ac_cv_prog_vimage_path="no" fi fi vimage_path=$ac_cv_prog_vimage_path if test -n "$vimage_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vimage_path" >&5 $as_echo "$vimage_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "mount", so it can be a program name with args. set dummy mount; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_mount_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$mount_path"; then ac_cv_prog_mount_path="$mount_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_mount_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_mount_path" && ac_cv_prog_mount_path="no" fi fi mount_path=$ac_cv_prog_mount_path if test -n "$mount_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mount_path" >&5 $as_echo "$mount_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "umount", so it can be a program name with args. set dummy umount; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_umount_path+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$umount_path"; then ac_cv_prog_umount_path="$umount_path" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_umount_path="$as_dir" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_umount_path" && ac_cv_prog_umount_path="no" fi fi umount_path=$ac_cv_prog_umount_path if test -n "$umount_path"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $umount_path" >&5 $as_echo "$umount_path" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "convert", so it can be a program name with args. set dummy convert; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_convert+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$convert"; then ac_cv_prog_convert="$convert" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_convert="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_convert" && ac_cv_prog_convert="no" fi fi convert=$ac_cv_prog_convert if test -n "$convert"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $convert" >&5 $as_echo "$convert" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi #AC_CHECK_PROG(dia, dia, yes, no) # Extract the first word of "help2man", so it can be a program name with args. set dummy help2man; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_help2man+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$help2man"; then ac_cv_prog_help2man="$help2man" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $SEARCHPATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_help2man="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_help2man" && ac_cv_prog_help2man="no" fi fi help2man=$ac_cv_prog_help2man if test -n "$help2man"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $help2man" >&5 $as_echo "$help2man" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$convert" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not locate ImageMagick convert." >&5 $as_echo "$as_me: WARNING: Could not locate ImageMagick convert." >&2;} #want_docs_missing="convert" fi #if test "x$dia" = "xno" ; then # AC_MSG_WARN([Could not locate dia.]) # want_docs_missing="dia" #fi if test "x$help2man" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not locate help2man." >&5 $as_echo "$as_me: WARNING: Could not locate help2man." >&2;} want_docs_missing="$want_docs_missing help2man" fi if test "x$want_docs_missing" = "x" ; then want_docs=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built." >&5 $as_echo "$as_me: WARNING: Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built." >&2;} want_docs=no fi #AC_PATH_PROGS(tcl_path, [tclsh tclsh8.5 tclsh8.4], no) #if test "x$tcl_path" = "xno" ; then # AC_MSG_ERROR([Could not locate tclsh. Please install Tcl/Tk.]) #fi #AC_PATH_PROGS(wish_path, [wish wish8.5 wish8.4], no) #if test "x$wish_path" = "xno" ; then # AC_MSG_ERROR([Could not locate wish. Please install Tcl/Tk.]) #fi if test "x$enable_daemon" = "xyes" ; then # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NgMkSockNode in -lnetgraph" >&5 $as_echo_n "checking for NgMkSockNode in -lnetgraph... " >&6; } if ${ac_cv_lib_netgraph_NgMkSockNode+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetgraph $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char NgMkSockNode (); int main () { return NgMkSockNode (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_netgraph_NgMkSockNode=yes else ac_cv_lib_netgraph_NgMkSockNode=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netgraph_NgMkSockNode" >&5 $as_echo "$ac_cv_lib_netgraph_NgMkSockNode" >&6; } if test "x$ac_cv_lib_netgraph_NgMkSockNode" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNETGRAPH 1 _ACEOF LIBS="-lnetgraph $LIBS" fi # Checks for header files. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in arpa/inet.h fcntl.h limits.h stdint.h stdlib.h string.h sys/ioctl.h sys/mount.h sys/socket.h sys/time.h termios.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" case $ac_cv_c_int32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" if test "x$ac_cv_type_ssize_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) $as_echo "#define _UINT32_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) $as_echo "#define _UINT8_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint8_t $ac_cv_c_uint8_t _ACEOF ;; esac # Checks for library functions. for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in atexit dup2 gettimeofday memset socket strerror uname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done fi # simple architecture detection if test `uname -m` = "x86_64"; then ARCH=amd64 else ARCH=i386 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: using architecture $ARCH" >&5 $as_echo "using architecture $ARCH" >&6; } # Host-specific detection want_linux_netns=no want_bsd=no if test `uname -s` = "FreeBSD"; then want_bsd=yes for ac_prog in do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_gmake+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$gmake"; then ac_cv_prog_gmake="$gmake" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_gmake="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi gmake=$ac_cv_prog_gmake if test -n "$gmake"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gmake" >&5 $as_echo "$gmake" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$gmake" && break done # FreeBSD fix for linking libev port below CFLAGS="$CFLAGS -L/usr/local/lib" else want_linux_netns=yes fi if test "x$want_python" = "xno"; then want_bsd=no want_linux_netns=no fi if test "x$want_python" = "xyes"; then CFLAGS_save=$CFLAGS CPPFLAGS_save=$CPPFLAGS if test "x$PYTHON_INCLUDE_DIR" = "x"; then PYTHON_INCLUDE_DIR=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc()"` fi CFLAGS="-I$PYTHON_INCLUDE_DIR" CPPFLAGS="-I$PYTHON_INCLUDE_DIR" for ac_header in Python.h do : ac_fn_c_check_header_mongrel "$LINENO" "Python.h" "ac_cv_header_Python_h" "$ac_includes_default" if test "x$ac_cv_header_Python_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PYTHON_H 1 _ACEOF else as_fn_error $? "Python bindings require Python development headers (try installing your 'python-devel' or 'python-dev' package)" "$LINENO" 5 fi done CFLAGS=$CFLAGS_save CPPFLAGS=$CPPFLAGS_save if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libev" >&5 $as_echo_n "checking for libev... " >&6; } if test -n "$libev_CFLAGS"; then pkg_cv_libev_CFLAGS="$libev_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libev\""; } >&5 ($PKG_CONFIG --exists --print-errors "libev") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libev_CFLAGS=`$PKG_CONFIG --cflags "libev" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$libev_LIBS"; then pkg_cv_libev_LIBS="$libev_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libev\""; } >&5 ($PKG_CONFIG --exists --print-errors "libev") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libev_LIBS=`$PKG_CONFIG --libs "libev" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then libev_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libev" 2>&1` else libev_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libev" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$libev_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: did not find libev using pkconfig..." >&5 $as_echo "did not find libev using pkconfig..." >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_set_allocator in -lev" >&5 $as_echo_n "checking for ev_set_allocator in -lev... " >&6; } if ${ac_cv_lib_ev_ev_set_allocator+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lev $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ev_set_allocator (); int main () { return ev_set_allocator (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ev_ev_set_allocator=yes else ac_cv_lib_ev_ev_set_allocator=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_set_allocator" >&5 $as_echo "$ac_cv_lib_ev_ev_set_allocator" >&6; } if test "x$ac_cv_lib_ev_ev_set_allocator" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: found libev OK" >&5 $as_echo "found libev OK" >&6; } libev_LIBS=-lev else as_fn_error $? "Python bindings require libev (try installing your 'libev-devel' or 'libev-dev' package)" "$LINENO" 5 fi elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: did not find libev using pkconfig..." >&5 $as_echo "did not find libev using pkconfig..." >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_set_allocator in -lev" >&5 $as_echo_n "checking for ev_set_allocator in -lev... " >&6; } if ${ac_cv_lib_ev_ev_set_allocator+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lev $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ev_set_allocator (); int main () { return ev_set_allocator (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ev_ev_set_allocator=yes else ac_cv_lib_ev_ev_set_allocator=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_set_allocator" >&5 $as_echo "$ac_cv_lib_ev_ev_set_allocator" >&6; } if test "x$ac_cv_lib_ev_ev_set_allocator" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: found libev OK" >&5 $as_echo "found libev OK" >&6; } libev_LIBS=-lev else as_fn_error $? "Python bindings require libev (try installing your 'libev-devel' or 'libev-dev' package)" "$LINENO" 5 fi else libev_CFLAGS=$pkg_cv_libev_CFLAGS libev_LIBS=$pkg_cv_libev_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: found libev using pkgconfig OK" >&5 $as_echo "found libev using pkgconfig OK" >&6; } fi else # Namespace support requires Python support want_linux_netns=no fi progs_missing="" if test "x$want_linux_netns" = "xyes"; then if test "x$brctl_path" = "xno" ; then progs_missing="${progs_missing}brctl " brctl_path="/usr/sbin" as_fn_error $? "Could not locate brctl (from bridge-utils package)." "$LINENO" 5 fi if test "x$ebtables_path" = "xno" ; then progs_missing="${progs_missing}ebtables " ebtables_path="/sbin" as_fn_error $? "Could not locate ebtables (from ebtables package)." "$LINENO" 5 fi if test "x$ip_path" = "xno" ; then progs_missing="${progs_missing}ip " ip_path="/sbin" as_fn_error $? "Could not locate ip (from iproute package)." "$LINENO" 5 fi if test "x$tc_path" = "xno" ; then progs_missing="${progs_missing}tc " tc_path="/sbin" as_fn_error $? "Could not locate tc (from iproute package)." "$LINENO" 5 fi fi if test "x$want_bsd" = "xyes"; then if test "x$ifconfig_path" = "xno" ; then as_fn_error $? "Could not locate the 'ifconfig' utility." "$LINENO" 5 fi if test "x$ngctl_path" = "xno" ; then as_fn_error $? "Could not locate the 'ngctl' utility." "$LINENO" 5 fi if test "x$vimage_path" = "xno" ; then as_fn_error $? "Could not locate the 'vimage' utility." "$LINENO" 5 fi fi # Check whether --with-startup was given. if test "${with_startup+set}" = set; then : withval=$with_startup; with_startup=$with_startup else with_startup=initd fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: using startup option $with_startup" >&5 $as_echo "using startup option $with_startup" >&6; } # Variable substitutions if test x$enable_gui = xyes; then WANT_GUI_TRUE= WANT_GUI_FALSE='#' else WANT_GUI_TRUE='#' WANT_GUI_FALSE= fi if test x$enable_daemon = xyes; then WANT_DAEMON_TRUE= WANT_DAEMON_FALSE='#' else WANT_DAEMON_TRUE='#' WANT_DAEMON_FALSE= fi if test x$want_bsd = xyes; then WANT_BSD_TRUE= WANT_BSD_FALSE='#' else WANT_BSD_TRUE='#' WANT_BSD_FALSE= fi if test x$want_docs = xyes; then WANT_DOCS_TRUE= WANT_DOCS_FALSE='#' else WANT_DOCS_TRUE='#' WANT_DOCS_FALSE= fi if test x$want_python = xyes; then WANT_PYTHON_TRUE= WANT_PYTHON_FALSE='#' else WANT_PYTHON_TRUE='#' WANT_PYTHON_FALSE= fi if test x$want_linux_netns = xyes; then WANT_NETNS_TRUE= WANT_NETNS_FALSE='#' else WANT_NETNS_TRUE='#' WANT_NETNS_FALSE= fi if test x$with_startup = xinitd; then WANT_INITD_TRUE= WANT_INITD_FALSE='#' else WANT_INITD_TRUE='#' WANT_INITD_FALSE= fi if test x$with_startup = xsystemd; then WANT_SYSTEMD_TRUE= WANT_SYSTEMD_FALSE='#' else WANT_SYSTEMD_TRUE='#' WANT_SYSTEMD_FALSE= fi if test x$with_startup = xsuse; then WANT_SUSE_TRUE= WANT_SUSE_FALSE='#' else WANT_SUSE_TRUE='#' WANT_SUSE_FALSE= fi if test $cross_compiling = no; then HELP2MAN=${HELP2MAN-"${am_missing_run}help2man"} else HELP2MAN=: fi # Output files ac_config_files="$ac_config_files Makefile gui/core-gui gui/version.tcl gui/Makefile gui/icons/Makefile scripts/Makefile scripts/perf/Makefile scripts/xen/Makefile doc/Makefile doc/conf.py doc/man/Makefile doc/figures/Makefile daemon/Makefile daemon/src/Makefile daemon/src/version.h daemon/core/constants.py daemon/ns3/Makefile daemon/ns3/corens3/constants.py daemon/doc/Makefile daemon/doc/conf.py packaging/deb/core-daemon.install packaging/deb/core-gui.install packaging/rpm/core.spec" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_GUI_TRUE}" && test -z "${WANT_GUI_FALSE}"; then as_fn_error $? "conditional \"WANT_GUI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_DAEMON_TRUE}" && test -z "${WANT_DAEMON_FALSE}"; then as_fn_error $? "conditional \"WANT_DAEMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_BSD_TRUE}" && test -z "${WANT_BSD_FALSE}"; then as_fn_error $? "conditional \"WANT_BSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_DOCS_TRUE}" && test -z "${WANT_DOCS_FALSE}"; then as_fn_error $? "conditional \"WANT_DOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_PYTHON_TRUE}" && test -z "${WANT_PYTHON_FALSE}"; then as_fn_error $? "conditional \"WANT_PYTHON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_NETNS_TRUE}" && test -z "${WANT_NETNS_FALSE}"; then as_fn_error $? "conditional \"WANT_NETNS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_INITD_TRUE}" && test -z "${WANT_INITD_FALSE}"; then as_fn_error $? "conditional \"WANT_INITD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_SYSTEMD_TRUE}" && test -z "${WANT_SYSTEMD_FALSE}"; then as_fn_error $? "conditional \"WANT_SYSTEMD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_SUSE_TRUE}" && test -z "${WANT_SUSE_FALSE}"; then as_fn_error $? "conditional \"WANT_SUSE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by core $as_me 4.6, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ core config.status 4.6 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "gui/core-gui") CONFIG_FILES="$CONFIG_FILES gui/core-gui" ;; "gui/version.tcl") CONFIG_FILES="$CONFIG_FILES gui/version.tcl" ;; "gui/Makefile") CONFIG_FILES="$CONFIG_FILES gui/Makefile" ;; "gui/icons/Makefile") CONFIG_FILES="$CONFIG_FILES gui/icons/Makefile" ;; "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; "scripts/perf/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/perf/Makefile" ;; "scripts/xen/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/xen/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/conf.py") CONFIG_FILES="$CONFIG_FILES doc/conf.py" ;; "doc/man/Makefile") CONFIG_FILES="$CONFIG_FILES doc/man/Makefile" ;; "doc/figures/Makefile") CONFIG_FILES="$CONFIG_FILES doc/figures/Makefile" ;; "daemon/Makefile") CONFIG_FILES="$CONFIG_FILES daemon/Makefile" ;; "daemon/src/Makefile") CONFIG_FILES="$CONFIG_FILES daemon/src/Makefile" ;; "daemon/src/version.h") CONFIG_FILES="$CONFIG_FILES daemon/src/version.h" ;; "daemon/core/constants.py") CONFIG_FILES="$CONFIG_FILES daemon/core/constants.py" ;; "daemon/ns3/Makefile") CONFIG_FILES="$CONFIG_FILES daemon/ns3/Makefile" ;; "daemon/ns3/corens3/constants.py") CONFIG_FILES="$CONFIG_FILES daemon/ns3/corens3/constants.py" ;; "daemon/doc/Makefile") CONFIG_FILES="$CONFIG_FILES daemon/doc/Makefile" ;; "daemon/doc/conf.py") CONFIG_FILES="$CONFIG_FILES daemon/doc/conf.py" ;; "packaging/deb/core-daemon.install") CONFIG_FILES="$CONFIG_FILES packaging/deb/core-daemon.install" ;; "packaging/deb/core-gui.install") CONFIG_FILES="$CONFIG_FILES packaging/deb/core-gui.install" ;; "packaging/rpm/core.spec") CONFIG_FILES="$CONFIG_FILES packaging/rpm/core.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # Summary text echo \ "------------------------------------------------------------------------ ${PACKAGE_STRING} Configuration: Host System Type: ${host} C Compiler and flags: ${CC} ${CFLAGS} Install prefix: ${prefix} Build GUI: ${enable_gui} GUI path: ${CORE_LIB_DIR} GUI config: ${CORE_GUI_CONF_DIR} Daemon path: ${SBINDIR} Daemon config: ${CORE_CONF_DIR} Python modules: ${pythondir} Logs: ${CORE_STATE_DIR}/log Features to build: Python bindings: ${want_python} Linux Namespaces emulation: ${want_linux_netns} FreeBSD Jails emulation: ${want_bsd} Documentation: ${want_docs} ------------------------------------------------------------------------" if test "x${want_bsd}" = "xyes" ; then # TODO: more sophisticated checks of gmake vs make echo ">>> NOTE: on FreeBSD you should use 'gmake' instead of 'make' ------------------------------------------------------------------------" fi if test "x${want_linux_netns}" = "xyes" ; then echo "On this platform you should run core-gui as a normal user. ------------------------------------------------------------------------" fi if test "x${progs_missing}" != "x" ; then echo ">>> NOTE: the following programs could not be found:" echo " $progs_missing ------------------------------------------------------------------------" fi core-4.6/kernel/0000775000175000017500000000000012220631372010574 500000000000000core-4.6/kernel/core-kernel-3.0/0000775000175000017500000000000012220631372013300 500000000000000core-4.6/kernel/core-kernel-3.0/patches/0000775000175000017500000000000012220631372014727 500000000000000core-4.6/kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch0000664000175000017500000000335412021412002021540 00000000000000commit 0542b69e2c57fc9668ce6a03155bea6e1f557901 Author: dpward Date: Wed Aug 31 06:05:27 2011 +0000 net: Make flow cache namespace-aware flow_cache_lookup will return a cached object (or null pointer) that the resolver (i.e. xfrm_policy_lookup) previously found for another namespace using the same key/family/dir. Instead, make the namespace part of what identifies entries in the cache. As before, flow_entry_valid will return 0 for entries where the namespace has been deleted, and they will be removed from the cache the next time flow_cache_gc_task is run. Reported-by: Andrew Dickinson Signed-off-by: David Ward Signed-off-by: David S. Miller diff --git a/net/core/flow.c b/net/core/flow.c index bf32c33..47b6d26 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -30,6 +30,7 @@ struct flow_cache_entry { struct hlist_node hlist; struct list_head gc_list; } u; + struct net *net; u16 family; u8 dir; u32 genid; @@ -232,7 +233,8 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, hash = flow_hash_code(fc, fcp, key); hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) { - if (tfle->family == family && + if (tfle->net == net && + tfle->family == family && tfle->dir == dir && flow_key_compare(key, &tfle->key) == 0) { fle = tfle; @@ -246,6 +248,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); if (fle) { + fle->net = net; fle->family = family; fle->dir = dir; memcpy(&fle->key, key, sizeof(*key)); core-4.6/kernel/core-kernel-3.0/patches/00-linux-3.0.nfnetlink_queue.patch0000664000175000017500000002267412021412002022732 00000000000000From 4b819adab7892f61a96bab1e36e5d9a74018432b Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Tue, 3 Jan 2012 14:39:04 -0800 Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per netns. This allows subsystems to create per-netns entries. Signed-off-by: Tom Goff --- include/linux/netfilter.h | 5 ---- include/net/net_namespace.h | 3 ++ net/netfilter/core.c | 35 +++++++++++++++++++++++------- net/netfilter/nf_log.c | 33 +++++++++++++++++++++++++--- net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++--- net/netfilter/nfnetlink_log.c | 44 ++++++++++++++++++++++++++----------- net/netfilter/nfnetlink_queue.c | 45 ++++++++++++++++++++++++++------------ 7 files changed, 148 insertions(+), 48 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 857f502..b4e02fb 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #endif } -#ifdef CONFIG_PROC_FS -#include -extern struct proc_dir_entry *proc_net_netfilter; -#endif - #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 3bb6fa0..cf126ef 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -84,6 +84,9 @@ struct net { struct netns_dccp dccp; #endif #ifdef CONFIG_NETFILTER +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_net_netfilter; +#endif struct netns_xt xt; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index afca6c7..9d9b103 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) EXPORT_SYMBOL(nf_conntrack_destroy); #endif /* CONFIG_NF_CONNTRACK */ +static int __net_init netfilter_net_init(struct net *net) +{ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; -EXPORT_SYMBOL(proc_net_netfilter); + net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", + net->proc_net); + if (!net->proc_net_netfilter) { + pr_err("%s: cannot create netfilter proc entry\n", __func__); + return -ENOMEM; + } #endif + return 0; +} + +static void __net_exit netfilter_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_remove(net, "netfilter"); +#endif +} + +static struct pernet_operations netfilter_net_ops = { + .init = netfilter_net_init, + .exit = netfilter_net_exit, +}; + void __init netfilter_init(void) { int i, h; + + if (register_pernet_subsys(&netfilter_net_ops)) + panic("%s: failed to register per netns operations", __func__); + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } -#ifdef CONFIG_PROC_FS - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); - if (!proc_net_netfilter) - panic("cannot create netfilter proc entry"); -#endif - if (netfilter_queue_init() < 0) panic("cannot initialize nf_queue"); if (netfilter_log_init() < 0) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index ce0c406..ccc15d6 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void) } #endif /* CONFIG_SYSCTL */ -int __init netfilter_log_init(void) +static int __net_init netfilter_log_net_init(struct net *net) { - int i, r; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + net->proc_net_netfilter, &nflog_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit netfilter_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_log", net->proc_net_netfilter); #endif +} + +static struct pernet_operations netfilter_log_net_ops = { + .init = netfilter_log_net_init, + .exit = netfilter_log_net_exit, +}; + +int __init netfilter_log_init(void) +{ + int i, r; + + r = register_pernet_subsys(&netfilter_log_net_ops); + if (r) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return r; + } /* Errors will trigger panic, unroll on error is unnecessary. */ r = netfilter_log_sysctl_init(); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 99ffd28..ecb84a3 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = { }; #endif /* PROC_FS */ - -int __init netfilter_queue_init(void) +static int __net_init netfilter_queue_net_init(struct net *net) { #ifdef CONFIG_PROC_FS if (!proc_create("nf_queue", S_IRUGO, - proc_net_netfilter, &nfqueue_file_ops)) - return -1; + net->proc_net_netfilter, &nfqueue_file_ops)) + return -ENOMEM; #endif + return 0; } +static void __net_exit netfilter_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations netfilter_queue_net_ops = { + .init = netfilter_queue_net_init, + .exit = netfilter_queue_net_exit, +}; + +int __init netfilter_queue_init(void) +{ + int err; + + err = register_pernet_subsys(&netfilter_queue_net_ops); + if (err) + pr_err("%s: cannot initialize per netns operations\n", + __func__); + + return err; +} diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 66b2c54..e4c3c1e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_log_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_log", 0440, + net->proc_net_netfilter, &nful_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_log_net_ops = { + .init = nfnetlink_log_net_init, + .exit = nfnetlink_log_net_exit, +}; + static int __init nfnetlink_log_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_log_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void) goto cleanup_subsys; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) - goto cleanup_logger; -#endif return status; -#ifdef CONFIG_PROC_FS -cleanup_logger: - nf_log_unregister(&nfulnl_logger); -#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: @@ -996,9 +1017,6 @@ cleanup_netlink_notifier: static void __exit nfnetlink_log_fini(void) { nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index a80b0cb..b615da5 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_queue_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_queue", 0440, + net->proc_net_netfilter, &nfqnl_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_queue_net_ops = { + .init = nfnetlink_queue_net_init, + .exit = nfnetlink_queue_net_exit, +}; + static int __init nfnetlink_queue_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_queue_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void) goto cleanup_netlink_notifier; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) - goto cleanup_subsys; -#endif - register_netdevice_notifier(&nfqnl_dev_notifier); return status; -#ifdef CONFIG_PROC_FS -cleanup_subsys: - nfnetlink_subsys_unregister(&nfqnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; @@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handlers(&nfqh); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- 1.7.5.4 core-4.6/kernel/core-kernel-3.0/patches/01-linux-3.0.nfnetlink_queue.patch0000664000175000017500000003557012021412002022732 00000000000000From dd504f32d24e9f239d429204c43a5c500c9853c6 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Tue, 3 Jan 2012 15:52:32 -0800 Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. Make nfnetlink_queue network namespace aware including a per-netns /proc/net/netfilter/nfnetlink_queue file. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 6 ++ include/net/netfilter/nf_queue.h | 3 +- include/net/netns/nfqnl.h | 14 ++++ net/ipv4/netfilter/ip_queue.c | 6 ++- net/ipv6/netfilter/ip6_queue.c | 6 ++- net/netfilter/nf_queue.c | 12 +++- net/netfilter/nfnetlink_queue.c | 138 +++++++++++++++++++------------------- 7 files changed, 112 insertions(+), 73 deletions(-) create mode 100644 include/net/netns/nfqnl.h diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index cf126ef..4b6f04a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -21,6 +21,9 @@ #include #endif #include +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) +#include +#endif struct proc_dir_entry; struct net_device; @@ -93,6 +96,9 @@ struct net { #endif struct sock *nfnl; struct sock *nfnl_stash; +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) + struct netns_nfqnl nfqnl; +#endif #endif #ifdef CONFIG_WEXT_CORE struct sk_buff_head wext_nlevents; diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 252fd10..3e5bde8 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -19,7 +19,8 @@ struct nf_queue_entry { /* Packet queuing */ struct nf_queue_handler { - int (*outfn)(struct nf_queue_entry *entry, + int (*outfn)(struct net *net, + struct nf_queue_entry *entry, unsigned int queuenum); char *name; }; diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h new file mode 100644 index 0000000..0fe7fbe --- /dev/null +++ b/include/net/netns/nfqnl.h @@ -0,0 +1,14 @@ +#ifndef __NETNS_NFQNL_H +#define __NETNS_NFQNL_H + +#include +#include + +#define NFQNL_INSTANCE_BUCKETS 16 + +struct netns_nfqnl { + spinlock_t instances_lock; + struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; +}; + +#endif /* __NETNS_NFQNL_H */ diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index e59aabd..f3c43e5 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -225,7 +225,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e63c397..322c511 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -225,7 +225,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ecb84a3..9490bd5 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, #endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; + struct net *net; + + if (indev) + net = dev_net(indev); + else if (skb->sk) + net = sock_net(skb->sk); + else if (outdev) + net = dev_net(outdev); + else + return status; /* QUEUE == DROP if no one is waiting, to be safe. */ rcu_read_lock(); @@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, #endif skb_dst_force(skb); afinfo->saveroute(skb, entry); - status = qh->outfn(entry, queuenum); + status = qh->outfn(net, entry, queuenum); rcu_read_unlock(); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b615da5..48ea6f4 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -64,24 +64,19 @@ struct nfqnl_instance { typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -static DEFINE_SPINLOCK(instances_lock); - -#define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; - static inline u_int8_t instance_hashfn(u_int16_t queue_num) { - return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; + return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct net *net, u_int16_t queue_num) { struct hlist_head *head; struct hlist_node *pos; struct nfqnl_instance *inst; - head = &instance_table[instance_hashfn(queue_num)]; + head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int pid) +instance_create(struct net *net, u_int16_t queue_num, int pid) { struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&net->nfqnl.instances_lock); + if (instance_lookup(net, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return ERR_PTR(err); } @@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct net *net, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + spin_lock(&net->nfqnl.instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); } static inline void @@ -390,7 +385,8 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { struct sk_buff *nskb; struct nfqnl_instance *queue; @@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) __be32 *packet_id_ptr; /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(net, queuenum); if (!queue) { err = -ESRCH; goto err_out; @@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) *packet_id_ptr = htonl(entry->id); /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; rcu_read_lock(); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &net->nfqnl.instance_table[i]; hlist_for_each_entry_rcu(inst, tmp, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, int i; /* destroy all instances for this pid */ - spin_lock(&instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + spin_lock(&n->net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &n->net->nfqnl.instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((n->net == &init_net) && - (n->pid == inst->peer_pid)) + if (n->pid == inst->peer_pid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&n->net->nfqnl.instances_lock); } return NOTIFY_DONE; } @@ -715,9 +710,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, unsigned int verdict; struct nf_queue_entry *entry; int err; + struct net *net = sock_net(ctnl); rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) { err = -ENODEV; goto err_out_unlock; @@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); if (nfqa[NFQA_CFG_CMD]) { cmd = nla_data(nfqa[NFQA_CFG_CMD]); @@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto err_out_unlock; @@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).pid); + queue = instance_create(net, queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(net, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct net *net, struct iter_state *st) { - struct iter_state *st = seq->private; - if (!st) return NULL; - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { + if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) + return net->nfqnl.instance_table[st->bucket].first; } return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct net *net, struct iter_state *st, + struct hlist_node *h) { - struct iter_state *st = seq->private; - h = h->next; while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) + if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + h = net->nfqnl.instance_table[st->bucket].first; } return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct net *net, struct iter_state *st, + loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(net, st); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(net, st, head))) pos--; return pos ? NULL : head; } static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) { - spin_lock(&instances_lock); - return get_idx(seq, *pos); + struct net *net = seq_file_net(seq); + spin_lock(&net->nfqnl.instances_lock); + return get_idx(net, seq->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s, v); + return get_next(seq_file_net(s), s->private, v); } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) { - spin_unlock(&instances_lock); + struct net *net = seq_file_net(s); + spin_unlock(&net->nfqnl.instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nfqnl_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nfqnl_file_ops = { @@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ static int __net_init nfnetlink_queue_net_init(struct net *net) { + int i; + + spin_lock_init(&net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); + #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_queue", 0440, net->proc_net_netfilter, &nfqnl_file_ops)) @@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { static int __init nfnetlink_queue_init(void) { - int i, status; + int status; status = register_pernet_subsys(&nfnetlink_queue_net_ops); if (status) { @@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void) return status; } - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); - netlink_register_notifier(&nfqnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfqnl_subsys); if (status < 0) { -- 1.7.5.4 core-4.6/kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch0000664000175000017500000000300412021412002021146 00000000000000commit 7da7dfcb787d77929c15d5b7127c816ee16f1ede Author: Tom Goff Date: Fri Dec 16 17:39:00 2011 -0800 Make network device ifindex sequential per network namespace. diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 3bb6fa0..2fd53da 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -62,6 +62,8 @@ struct net { struct sock *rtnl; /* rtnetlink socket */ struct sock *genl_sock; + int ifindex; + struct list_head dev_base_head; struct hlist_head *dev_name_head; struct hlist_head *dev_index_head; diff --git a/net/core/dev.c b/net/core/dev.c index 6ba50a1..ba95aa5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5260,12 +5260,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) */ static int dev_new_index(struct net *net) { - static int ifindex; for (;;) { - if (++ifindex <= 0) - ifindex = 1; - if (!__dev_get_by_index(net, ifindex)) - return ifindex; + if (++net->ifindex <= 0) + net->ifindex = 1; + if (!__dev_get_by_index(net, net->ifindex)) + return net->ifindex; } } @@ -6277,8 +6276,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Actually switch the network namespace */ dev_net_set(dev, net); - /* If there is an ifindex conflict assign a new one */ - if (__dev_get_by_index(net, dev->ifindex)) { + /* Assign a new ifindex */ + { int iflink = (dev->iflink == dev->ifindex); dev->ifindex = dev_new_index(net); if (iflink) core-4.6/kernel/core-kernel-3.0/Makefile0000664000175000017500000000313312021412002014642 00000000000000VERSION := 3.0.0 TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 SUBVERSION := -core REVISION := 1.0 PATCHDIR := patches PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) CONFIG := config.core DEPDEBS := linux-source kernel-package po-debconf gettext CONCURRENCY_LEVEL := 8 MAINTAINER ?= Tom Goff EMAIL ?= thomas.goff@boeing.com MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ --append-to-version $(SUBVERSION) --revision $(REVISION) .PHONY: build build: debcheck defaultconfig patch export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && \ if [ -f ../$(CONFIG) ]; then \ cat ../$(CONFIG) >> .config; \ fi && \ fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch .PHONY: debcheck debcheck: for d in $(DEPDEBS); do \ if ! dpkg-query -s $$d > /dev/null 2>&1; then \ echo ERROR: build dependency not installed: $$d >&2; \ exit 1; \ fi; \ done .PHONY: defaultconfig defaultconfig: linux-source-$(VERSION) export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure .PHONY: patch patch: linux-source-$(VERSION) patch-stamp patch-stamp: $(PATCHES) for p in $^; do \ if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ echo ERROR: applying patch failed: $$p >&2; \ exit 1; \ fi; \ done touch patch-stamp linux-source-$(VERSION): $(TARBALL) tar -xjf $^ .PHONY: clean clean: rm -rf linux-source-$(VERSION) patch-stamp core-4.6/kernel/core-kernel-3.0/config.core0000664000175000017500000000003112021412002015313 00000000000000CONFIG_XFRM_STATISTICS=y core-4.6/kernel/core-kernel-3.0/README.txt0000664000175000017500000000077112021412002014705 00000000000000Author: Tom Goff The Makefile is basically a wrapper around the make-kpkg command that simplifies building kernel packages. Running make will do some basic dependency checks then build architecture appropriate kernel packages that include changes from the patches directory. The nfnetlink patch is what virtualizes the netfilter queue mechanism; the flow-cache patch allows using IPsec between network namespaces; the ifindex patch virtualizes network interface index numbers. core-4.6/kernel/core-kernel-3.2/0000775000175000017500000000000012220631372013302 500000000000000core-4.6/kernel/core-kernel-3.2/patches/0000775000175000017500000000000012220631372014731 500000000000000core-4.6/kernel/core-kernel-3.2/patches/01-linux-3.2.nfnetlink_queue.patch0000664000175000017500000003753612021412002022742 00000000000000From f8179877a37f37631d831de6381f22fd643b4ea0 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Thu, 26 Jul 2012 23:58:38 -0700 Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. Make nfnetlink_queue network namespace aware including a per-netns /proc/net/netfilter/nfnetlink_queue file. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 6 ++ include/net/netfilter/nf_queue.h | 3 +- include/net/netns/nfqnl.h | 14 ++++ net/ipv4/netfilter/ip_queue.c | 6 +- net/ipv6/netfilter/ip6_queue.c | 6 +- net/netfilter/nf_queue.c | 12 +++- net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++------------------- 7 files changed, 111 insertions(+), 72 deletions(-) create mode 100644 include/net/netns/nfqnl.h diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index cf126ef..4b6f04a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -21,6 +21,9 @@ #include #endif #include +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) +#include +#endif struct proc_dir_entry; struct net_device; @@ -93,6 +96,9 @@ struct net { #endif struct sock *nfnl; struct sock *nfnl_stash; +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) + struct netns_nfqnl nfqnl; +#endif #endif #ifdef CONFIG_WEXT_CORE struct sk_buff_head wext_nlevents; diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 252fd10..3e5bde8 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -19,7 +19,8 @@ struct nf_queue_entry { /* Packet queuing */ struct nf_queue_handler { - int (*outfn)(struct nf_queue_entry *entry, + int (*outfn)(struct net *net, + struct nf_queue_entry *entry, unsigned int queuenum); char *name; }; diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h new file mode 100644 index 0000000..0fe7fbe --- /dev/null +++ b/include/net/netns/nfqnl.h @@ -0,0 +1,14 @@ +#ifndef __NETNS_NFQNL_H +#define __NETNS_NFQNL_H + +#include +#include + +#define NFQNL_INSTANCE_BUCKETS 16 + +struct netns_nfqnl { + spinlock_t instances_lock; + struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; +}; + +#endif /* __NETNS_NFQNL_H */ diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index e59aabd..f3c43e5 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -225,7 +225,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e63c397..322c511 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -225,7 +225,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 470ec3a..6894ecc 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, #endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; + struct net *net; + + if (indev) + net = dev_net(indev); + else if (skb->sk) + net = sock_net(skb->sk); + else if (outdev) + net = dev_net(outdev); + else + return status; /* QUEUE == DROP if no one is waiting, to be safe. */ rcu_read_lock(); @@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, #endif skb_dst_force(skb); afinfo->saveroute(skb, entry); - status = qh->outfn(entry, queuenum); + status = qh->outfn(net, entry, queuenum); rcu_read_unlock(); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b615da5..11725a0 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -64,24 +64,19 @@ struct nfqnl_instance { typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -static DEFINE_SPINLOCK(instances_lock); - -#define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; - static inline u_int8_t instance_hashfn(u_int16_t queue_num) { - return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; + return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct net *net, u_int16_t queue_num) { struct hlist_head *head; struct hlist_node *pos; struct nfqnl_instance *inst; - head = &instance_table[instance_hashfn(queue_num)]; + head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int pid) +instance_create(struct net *net, u_int16_t queue_num, int pid) { struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&net->nfqnl.instances_lock); + if (instance_lookup(net, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return ERR_PTR(err); } @@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct net *net, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + spin_lock(&net->nfqnl.instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); } static inline void @@ -390,7 +385,8 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { struct sk_buff *nskb; struct nfqnl_instance *queue; @@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) __be32 *packet_id_ptr; /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(net, queuenum); if (!queue) { err = -ESRCH; goto err_out; @@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) *packet_id_ptr = htonl(entry->id); /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; rcu_read_lock(); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &net->nfqnl.instance_table[i]; hlist_for_each_entry_rcu(inst, tmp, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, int i; /* destroy all instances for this pid */ - spin_lock(&instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + spin_lock(&n->net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &n->net->nfqnl.instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((n->net == &init_net) && - (n->pid == inst->peer_pid)) + if (n->pid == inst->peer_pid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&n->net->nfqnl.instances_lock); } return NOTIFY_DONE; } @@ -622,11 +615,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { [NFQA_MARK] = { .type = NLA_U32 }, }; -static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) +static struct nfqnl_instance *verdict_instance_lookup(struct net *net, + u16 queue_num, int nlpid) { struct nfqnl_instance *queue; - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) return ERR_PTR(-ENODEV); @@ -670,7 +664,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, LIST_HEAD(batch_list); u16 queue_num = ntohs(nfmsg->res_id); - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); + queue = verdict_instance_lookup(sock_net(ctnl), queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -715,11 +710,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; unsigned int verdict; struct nf_queue_entry *entry; + struct net *net = sock_net(ctnl); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); + queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); if (nfqa[NFQA_CFG_CMD]) { cmd = nla_data(nfqa[NFQA_CFG_CMD]); @@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto err_out_unlock; @@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).pid); + queue = instance_create(net, queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(net, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct net *net, struct iter_state *st) { - struct iter_state *st = seq->private; - if (!st) return NULL; - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { + if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) + return net->nfqnl.instance_table[st->bucket].first; } return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct net *net, struct iter_state *st, + struct hlist_node *h) { - struct iter_state *st = seq->private; - h = h->next; while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) + if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + h = net->nfqnl.instance_table[st->bucket].first; } return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct net *net, struct iter_state *st, + loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(net, st); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(net, st, head))) pos--; return pos ? NULL : head; } static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) { - spin_lock(&instances_lock); - return get_idx(seq, *pos); + struct net *net = seq_file_net(seq); + spin_lock(&net->nfqnl.instances_lock); + return get_idx(net, seq->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s, v); + return get_next(seq_file_net(s), s->private, v); } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) { - spin_unlock(&instances_lock); + struct net *net = seq_file_net(s); + spin_unlock(&net->nfqnl.instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nfqnl_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nfqnl_file_ops = { @@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ static int __net_init nfnetlink_queue_net_init(struct net *net) { + int i; + + spin_lock_init(&net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); + #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_queue", 0440, net->proc_net_netfilter, &nfqnl_file_ops)) @@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { static int __init nfnetlink_queue_init(void) { - int i, status; + int status; status = register_pernet_subsys(&nfnetlink_queue_net_ops); if (status) { @@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void) return status; } - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); - netlink_register_notifier(&nfqnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfqnl_subsys); if (status < 0) { -- 1.7.9.5 core-4.6/kernel/core-kernel-3.2/patches/00-linux-3.2.nfnetlink_queue.patch0000664000175000017500000002270212021412002022726 00000000000000From 67765faf27ec646bcc008bd34d12e48a7466dcdd Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Thu, 26 Jul 2012 23:57:06 -0700 Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per netns. This allows subsystems to create per-netns entries. Signed-off-by: Tom Goff --- include/linux/netfilter.h | 5 ----- include/net/net_namespace.h | 3 +++ net/netfilter/core.c | 35 +++++++++++++++++++++++------- net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++---- net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++---- net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++----------- net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------ 7 files changed, 148 insertions(+), 48 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 857f502..b4e02fb 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #endif } -#ifdef CONFIG_PROC_FS -#include -extern struct proc_dir_entry *proc_net_netfilter; -#endif - #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 3bb6fa0..cf126ef 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -84,6 +84,9 @@ struct net { struct netns_dccp dccp; #endif #ifdef CONFIG_NETFILTER +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_net_netfilter; +#endif struct netns_xt xt; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index afca6c7..9d9b103 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) EXPORT_SYMBOL(nf_conntrack_destroy); #endif /* CONFIG_NF_CONNTRACK */ +static int __net_init netfilter_net_init(struct net *net) +{ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; -EXPORT_SYMBOL(proc_net_netfilter); + net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", + net->proc_net); + if (!net->proc_net_netfilter) { + pr_err("%s: cannot create netfilter proc entry\n", __func__); + return -ENOMEM; + } #endif + return 0; +} + +static void __net_exit netfilter_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_remove(net, "netfilter"); +#endif +} + +static struct pernet_operations netfilter_net_ops = { + .init = netfilter_net_init, + .exit = netfilter_net_exit, +}; + void __init netfilter_init(void) { int i, h; + + if (register_pernet_subsys(&netfilter_net_ops)) + panic("%s: failed to register per netns operations", __func__); + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } -#ifdef CONFIG_PROC_FS - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); - if (!proc_net_netfilter) - panic("cannot create netfilter proc entry"); -#endif - if (netfilter_queue_init() < 0) panic("cannot initialize nf_queue"); if (netfilter_log_init() < 0) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 957374a..c546ad7 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void) } #endif /* CONFIG_SYSCTL */ -int __init netfilter_log_init(void) +static int __net_init netfilter_log_net_init(struct net *net) { - int i, r; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + net->proc_net_netfilter, &nflog_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit netfilter_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_log", net->proc_net_netfilter); #endif +} + +static struct pernet_operations netfilter_log_net_ops = { + .init = netfilter_log_net_init, + .exit = netfilter_log_net_exit, +}; + +int __init netfilter_log_init(void) +{ + int i, r; + + r = register_pernet_subsys(&netfilter_log_net_ops); + if (r) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return r; + } /* Errors will trigger panic, unroll on error is unnecessary. */ r = netfilter_log_sysctl_init(); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index b3a7db6..470ec3a 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = { }; #endif /* PROC_FS */ - -int __init netfilter_queue_init(void) +static int __net_init netfilter_queue_net_init(struct net *net) { #ifdef CONFIG_PROC_FS if (!proc_create("nf_queue", S_IRUGO, - proc_net_netfilter, &nfqueue_file_ops)) - return -1; + net->proc_net_netfilter, &nfqueue_file_ops)) + return -ENOMEM; #endif + return 0; } +static void __net_exit netfilter_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations netfilter_queue_net_ops = { + .init = netfilter_queue_net_init, + .exit = netfilter_queue_net_exit, +}; + +int __init netfilter_queue_init(void) +{ + int err; + + err = register_pernet_subsys(&netfilter_queue_net_ops); + if (err) + pr_err("%s: cannot initialize per netns operations\n", + __func__); + + return err; +} diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 66b2c54..e4c3c1e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_log_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_log", 0440, + net->proc_net_netfilter, &nful_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_log_net_ops = { + .init = nfnetlink_log_net_init, + .exit = nfnetlink_log_net_exit, +}; + static int __init nfnetlink_log_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_log_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void) goto cleanup_subsys; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) - goto cleanup_logger; -#endif return status; -#ifdef CONFIG_PROC_FS -cleanup_logger: - nf_log_unregister(&nfulnl_logger); -#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: @@ -996,9 +1017,6 @@ cleanup_netlink_notifier: static void __exit nfnetlink_log_fini(void) { nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index a80b0cb..b615da5 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_queue_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_queue", 0440, + net->proc_net_netfilter, &nfqnl_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_queue_net_ops = { + .init = nfnetlink_queue_net_init, + .exit = nfnetlink_queue_net_exit, +}; + static int __init nfnetlink_queue_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_queue_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void) goto cleanup_netlink_notifier; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) - goto cleanup_subsys; -#endif - register_netdevice_notifier(&nfqnl_dev_notifier); return status; -#ifdef CONFIG_PROC_FS -cleanup_subsys: - nfnetlink_subsys_unregister(&nfqnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; @@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handlers(&nfqh); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- 1.7.9.5 core-4.6/kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch0000664000175000017500000000336312021412002021162 00000000000000From 918e253ebaa3d28c54ff64b596a0afc8779d106a Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Fri, 27 Jul 2012 00:02:50 -0700 Subject: [PATCH] Make network device ifindex sequential per network namespace. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 2 ++ net/core/dev.c | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 4b6f04a..266e747 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -65,6 +65,8 @@ struct net { struct sock *rtnl; /* rtnetlink socket */ struct sock *genl_sock; + int ifindex; + struct list_head dev_base_head; struct hlist_head *dev_name_head; struct hlist_head *dev_index_head; diff --git a/net/core/dev.c b/net/core/dev.c index 1cbddc9..d7f5711 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5236,12 +5236,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) */ static int dev_new_index(struct net *net) { - static int ifindex; for (;;) { - if (++ifindex <= 0) - ifindex = 1; - if (!__dev_get_by_index(net, ifindex)) - return ifindex; + if (++net->ifindex <= 0) + net->ifindex = 1; + if (!__dev_get_by_index(net, net->ifindex)) + return net->ifindex; } } @@ -6253,8 +6252,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Actually switch the network namespace */ dev_net_set(dev, net); - /* If there is an ifindex conflict assign a new one */ - if (__dev_get_by_index(net, dev->ifindex)) { + /* Assign a new ifindex */ + { int iflink = (dev->iflink == dev->ifindex); dev->ifindex = dev_new_index(net); if (iflink) -- 1.7.9.5 core-4.6/kernel/core-kernel-3.2/Makefile0000664000175000017500000000313312021412002014644 00000000000000VERSION := 3.2.0 TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 SUBVERSION := -core REVISION := 1.0 PATCHDIR := patches PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) CONFIG := config.core DEPDEBS := linux-source kernel-package po-debconf gettext CONCURRENCY_LEVEL := 8 MAINTAINER ?= Tom Goff EMAIL ?= thomas.goff@boeing.com MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ --append-to-version $(SUBVERSION) --revision $(REVISION) .PHONY: build build: debcheck defaultconfig patch export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && \ if [ -f ../$(CONFIG) ]; then \ cat ../$(CONFIG) >> .config; \ fi && \ fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch .PHONY: debcheck debcheck: for d in $(DEPDEBS); do \ if ! dpkg-query -s $$d > /dev/null 2>&1; then \ echo ERROR: build dependency not installed: $$d >&2; \ exit 1; \ fi; \ done .PHONY: defaultconfig defaultconfig: linux-source-$(VERSION) export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure .PHONY: patch patch: linux-source-$(VERSION) patch-stamp patch-stamp: $(PATCHES) for p in $^; do \ if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ echo ERROR: applying patch failed: $$p >&2; \ exit 1; \ fi; \ done touch patch-stamp linux-source-$(VERSION): $(TARBALL) tar -xjf $^ .PHONY: clean clean: rm -rf linux-source-$(VERSION) patch-stamp core-4.6/kernel/core-kernel-3.2/config.core0000664000175000017500000000003112021412002015315 00000000000000CONFIG_XFRM_STATISTICS=y core-4.6/kernel/core-kernel-3.2/README.txt0000664000175000017500000000066612021412002014712 00000000000000Author: Tom Goff The Makefile is basically a wrapper around the make-kpkg command that simplifies building kernel packages. Running make will do some basic dependency checks then build architecture appropriate kernel packages that include changes from the patches directory. The nfnetlink patch is what virtualizes the netfilter queue mechanism; the ifindex patch virtualizes network interface index numbers. core-4.6/kernel/freebsd/0000775000175000017500000000000012220631372012206 500000000000000core-4.6/kernel/freebsd/vimage_7-CORE.diff0000664000175000017500000026216512021411051015205 00000000000000diff -ur sys.20081015/netinet/ip_mroute.c sys/netinet/ip_mroute.c --- sys.20081015/netinet/ip_mroute.c 2008-08-16 16:29:19.000000000 -0700 +++ sys/netinet/ip_mroute.c 2008-11-05 16:30:04.000000000 -0800 @@ -99,6 +99,7 @@ #include #include #ifdef INET6 +#include #include #include #include @@ -112,21 +113,30 @@ * Control debugging code for rsvp and multicast routing code. * Can only set them with the debugger. */ +#ifndef VIMAGE static u_int rsvpdebug; /* non-zero enables debugging */ static u_int mrtdebug; /* any set of the flags below */ +#endif /* !VIMAGE */ #define DEBUG_MFC 0x02 #define DEBUG_FORWARD 0x04 #define DEBUG_EXPIRE 0x08 #define DEBUG_XMIT 0x10 #define DEBUG_PIM 0x20 +#ifndef VIMAGE #define VIFI_INVALID ((vifi_t) -1) +#endif /* !VIMAGE */ #define M_HASCL(m) ((m)->m_flags & M_EXT) static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables"); +static int vnet_mroute_iattach(const void *); +static int vnet_mroute_idetach(const void *); + +VNET_MOD_DECLARE(MROUTE, mroute, vnet_mroute_iattach, vnet_mroute_idetach, INET, NULL) + /* * Locking. We use two locks: one for the virtual interface table and * one for the forwarding table. These locks may be nested in which case @@ -140,48 +150,59 @@ * */ +#ifndef VIMAGE static struct mrtstat mrtstat; -SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW, - &mrtstat, mrtstat, +#endif /* !VIMAGE */ +SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_ip, OID_AUTO, mrtstat, + CTLFLAG_RW, mrtstat, mrtstat, "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)"); - +#ifndef VIMAGE static struct mfc *mfctable[MFCTBLSIZ]; -SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, mfctable, CTLFLAG_RD, - &mfctable, sizeof(mfctable), "S,*mfc[MFCTBLSIZ]", +SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO, + mfctable, CTLFLAG_RD, mfctable, sizeof(mfctable), sysctl_handle_opaque, + "S,*mfc[MFCTBLSIZ]", "Multicast Forwarding Table (struct *mfc[MFCTBLSIZ], netinet/ip_mroute.h)"); static struct mtx mrouter_mtx; -#define MROUTER_LOCK() mtx_lock(&mrouter_mtx) -#define MROUTER_UNLOCK() mtx_unlock(&mrouter_mtx) -#define MROUTER_LOCK_ASSERT() mtx_assert(&mrouter_mtx, MA_OWNED) +#endif /* !VIMAGE */ +#define MROUTER_LOCK() mtx_lock(&V_mrouter_mtx) +#define MROUTER_UNLOCK() mtx_unlock(&V_mrouter_mtx) +#define MROUTER_LOCK_ASSERT() mtx_assert(&V_mrouter_mtx, MA_OWNED) #define MROUTER_LOCK_INIT() \ - mtx_init(&mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF) -#define MROUTER_LOCK_DESTROY() mtx_destroy(&mrouter_mtx) + mtx_init(&V_mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF) +#define MROUTER_LOCK_DESTROY() mtx_destroy(&V_mrouter_mtx) +#ifndef VIMAGE static struct mtx mfc_mtx; -#define MFC_LOCK() mtx_lock(&mfc_mtx) -#define MFC_UNLOCK() mtx_unlock(&mfc_mtx) -#define MFC_LOCK_ASSERT() mtx_assert(&mfc_mtx, MA_OWNED) -#define MFC_LOCK_INIT() mtx_init(&mfc_mtx, "mroute mfc table", NULL, MTX_DEF) -#define MFC_LOCK_DESTROY() mtx_destroy(&mfc_mtx) +#endif /* !VIMAGE */ +#define MFC_LOCK() mtx_lock(&V_mfc_mtx) +#define MFC_UNLOCK() mtx_unlock(&V_mfc_mtx) +#define MFC_LOCK_ASSERT() mtx_assert(&V_mfc_mtx, MA_OWNED) +#define MFC_LOCK_INIT() mtx_init(&V_mfc_mtx, "mroute mfc table", NULL, MTX_DEF) +#define MFC_LOCK_DESTROY() mtx_destroy(&V_mfc_mtx) +#ifndef VIMAGE static struct vif viftable[MAXVIFS]; -SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD, - &viftable, sizeof(viftable), "S,vif[MAXVIFS]", +SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO, viftable, + CTLFLAG_RD, viftable, sizeof(viftable), sysctl_handle_opaque, + "S,vif[MAXVIFS]", "Multicast Virtual Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)"); static struct mtx vif_mtx; -#define VIF_LOCK() mtx_lock(&vif_mtx) -#define VIF_UNLOCK() mtx_unlock(&vif_mtx) -#define VIF_LOCK_ASSERT() mtx_assert(&vif_mtx, MA_OWNED) -#define VIF_LOCK_INIT() mtx_init(&vif_mtx, "mroute vif table", NULL, MTX_DEF) -#define VIF_LOCK_DESTROY() mtx_destroy(&vif_mtx) +#endif /* !VIMAGE */ +#define VIF_LOCK() mtx_lock(&V_vif_mtx) +#define VIF_UNLOCK() mtx_unlock(&V_vif_mtx) +#define VIF_LOCK_ASSERT() mtx_assert(&V_vif_mtx, MA_OWNED) +#define VIF_LOCK_INIT() mtx_init(&V_vif_mtx, "mroute vif table", NULL, MTX_DEF) +#define VIF_LOCK_DESTROY() mtx_destroy(&V_vif_mtx) +#ifndef VIMAGE static u_char nexpire[MFCTBLSIZ]; static eventhandler_tag if_detach_event_tag = NULL; static struct callout expire_upcalls_ch; +#endif /* !VIMAGE */ #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ #define UPCALL_EXPIRE 6 /* number of timeouts */ @@ -196,25 +217,31 @@ * Pending timeouts are stored in a hash table, the key being the * expiration time. Periodically, the entries are analysed and processed. */ +#ifndef VIMAGE #define BW_METER_BUCKETS 1024 static struct bw_meter *bw_meter_timers[BW_METER_BUCKETS]; -static struct callout bw_meter_ch; +static struct callout V_bw_meter_ch; +#endif /* !VIMAGE */ #define BW_METER_PERIOD (hz) /* periodical handling of bw meters */ /* * Pending upcalls are stored in a vector which is flushed when * full, or periodically */ +#ifndef VIMAGE static struct bw_upcall bw_upcalls[BW_UPCALLS_MAX]; static u_int bw_upcalls_n; /* # of pending upcalls */ static struct callout bw_upcalls_ch; +#endif /* !VIMAGE */ #define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */ +#ifndef VIMAGE static struct pimstat pimstat; +#endif /* !VIMAGE */ SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); -SYSCTL_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD, - &pimstat, pimstat, +SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_pim, PIMCTL_STATS, stats, + CTLFLAG_RD, pimstat, pimstat, "PIM Statistics (struct pimstat, netinet/pim_var.h)"); static u_long pim_squelch_wholepkt = 0; @@ -222,6 +249,7 @@ &pim_squelch_wholepkt, 0, "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified"); + extern struct domain inetdomain; struct protosw in_pim_protosw = { .pr_type = SOCK_RAW, @@ -291,13 +319,17 @@ 0 /* flags */ }; +#ifndef VIMAGE static struct ifnet multicast_register_if; static vifi_t reg_vif_num = VIFI_INVALID; +#endif /* !VIMAGE */ /* * Private variables. */ +#ifndef VIMAGE static vifi_t numvifs; +#endif /* !VIMAGE */ static u_long X_ip_mcast_src(int vifi); static int X_ip_mforward(struct ip *ip, struct ifnet *ifp, @@ -337,7 +369,7 @@ static void bw_upcalls_send(void); static void schedule_bw_meter(struct bw_meter *x, struct timeval *nowp); static void unschedule_bw_meter(struct bw_meter *x); -static void bw_meter_process(void); +static void bw_meter_process(struct vnet *vnet); static void expire_bw_upcalls_send(void *); static void expire_bw_meter_process(void *); @@ -352,7 +384,9 @@ /* * whether or not special PIM assert processing is enabled. */ +#ifndef VIMAGE static int pim_assert; +#endif /* !VIMAGE */ /* * Rate limit for assert notification messages, in usec */ @@ -367,7 +401,9 @@ MRT_MFC_FLAGS_BORDER_VIF | MRT_MFC_RP | MRT_MFC_BW_UPCALL); +#ifndef VIMAGE static uint32_t mrt_api_config = 0; +#endif /* !VIMAGE */ /* * Hash function for a source, group entry @@ -383,11 +419,12 @@ static struct mfc * mfc_find(in_addr_t o, in_addr_t g) { + INIT_VNET_MROUTE(curvnet); struct mfc *rt; MFC_LOCK_ASSERT(); - for (rt = mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next) + for (rt = V_mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next) if ((rt->mfc_origin.s_addr == o) && (rt->mfc_mcastgrp.s_addr == g) && (rt->mfc_stall == NULL)) break; @@ -424,7 +461,8 @@ static int X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) { - INIT_VNET_INET(curvnet); + INIT_VNET_INET(so->so_vnet); + INIT_VNET_MROUTE(so->so_vnet); int error, optval; vifi_t vifi; struct vifctl vifc; @@ -468,7 +506,7 @@ * select data size depending on API version. */ if (sopt->sopt_name == MRT_ADD_MFC && - mrt_api_config & MRT_API_FLAGS_ALL) { + V_mrt_api_config & MRT_API_FLAGS_ALL) { error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2), sizeof(struct mfcctl2)); } else { @@ -525,6 +563,7 @@ static int X_ip_mrouter_get(struct socket *so, struct sockopt *sopt) { + INIT_VNET_MROUTE(so->so_vnet); int error; static int version = 0x0305; /* !!! why is this here? XXX */ @@ -534,7 +573,7 @@ break; case MRT_ASSERT: - error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); + error = sooptcopyout(sopt, &V_pim_assert, sizeof V_pim_assert); break; case MRT_API_SUPPORT: @@ -542,7 +581,7 @@ break; case MRT_API_CONFIG: - error = sooptcopyout(sopt, &mrt_api_config, sizeof mrt_api_config); + error = sooptcopyout(sopt, &V_mrt_api_config, sizeof V_mrt_api_config); break; default: @@ -590,6 +629,7 @@ static int get_sg_cnt(struct sioc_sg_req *req) { + INIT_VNET_MROUTE(curvnet); struct mfc *rt; MFC_LOCK(); @@ -612,18 +652,19 @@ static int get_vif_cnt(struct sioc_vif_req *req) { + INIT_VNET_MROUTE(curvnet); vifi_t vifi = req->vifi; VIF_LOCK(); - if (vifi >= numvifs) { + if (vifi >= V_numvifs) { VIF_UNLOCK(); return EINVAL; } - req->icount = viftable[vifi].v_pkt_in; - req->ocount = viftable[vifi].v_pkt_out; - req->ibytes = viftable[vifi].v_bytes_in; - req->obytes = viftable[vifi].v_bytes_out; + req->icount = V_viftable[vifi].v_pkt_in; + req->ocount = V_viftable[vifi].v_pkt_out; + req->ibytes = V_viftable[vifi].v_bytes_in; + req->obytes = V_viftable[vifi].v_bytes_out; VIF_UNLOCK(); return 0; @@ -632,24 +673,30 @@ static void ip_mrouter_reset(void) { - bzero((caddr_t)mfctable, sizeof(mfctable)); - bzero((caddr_t)nexpire, sizeof(nexpire)); - - pim_assert = 0; - mrt_api_config = 0; - - callout_init(&expire_upcalls_ch, CALLOUT_MPSAFE); - - bw_upcalls_n = 0; - bzero((caddr_t)bw_meter_timers, sizeof(bw_meter_timers)); - callout_init(&bw_upcalls_ch, CALLOUT_MPSAFE); - callout_init(&bw_meter_ch, CALLOUT_MPSAFE); + INIT_VNET_MROUTE(curvnet); + bzero((caddr_t)V_mfctable, sizeof(V_mfctable)); + bzero((caddr_t)V_nexpire, sizeof(V_nexpire)); + if (V_reg_vif_num != VIFI_INVALID) + IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); + bzero(&V_multicast_register_if, sizeof(V_multicast_register_if)); + + V_reg_vif_num = VIFI_INVALID; + V_pim_assert = 0; + V_mrt_api_config = 0; + + callout_init(&V_expire_upcalls_ch, CALLOUT_MPSAFE); + + V_bw_upcalls_n = 0; + bzero((caddr_t)V_bw_meter_timers, sizeof(V_bw_meter_timers)); + callout_init(&V_bw_upcalls_ch, CALLOUT_MPSAFE); + callout_init(&V_bw_meter_ch, CALLOUT_MPSAFE); } static void if_detached_event(void *arg __unused, struct ifnet *ifp) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); vifi_t vifi; int i; struct mfc *mfc; @@ -676,12 +723,12 @@ */ VIF_LOCK(); MFC_LOCK(); - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_ifp != ifp) + for (vifi = 0; vifi < V_numvifs; vifi++) { + if (V_viftable[vifi].v_ifp != ifp) continue; for (i = 0; i < MFCTBLSIZ; i++) { - ppmfc = &mfctable[i]; - for (mfc = mfctable[i]; mfc != NULL; ) { + ppmfc = &V_mfctable[i]; + for (mfc = V_mfctable[i]; mfc != NULL; ) { nmfc = mfc->mfc_next; if (mfc->mfc_parent == vifi) { for (pq = mfc->mfc_stall; pq != NULL; ) { @@ -713,9 +760,10 @@ static int ip_mrouter_init(struct socket *so, int version) { - INIT_VNET_INET(curvnet); + INIT_VNET_INET(so->so_vnet); + INIT_VNET_MROUTE(so->so_vnet); - if (mrtdebug) + if (V_mrtdebug) log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n", so->so_type, so->so_proto->pr_protocol); @@ -732,24 +780,25 @@ return EADDRINUSE; } - if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, + V_if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, if_detached_event, NULL, EVENTHANDLER_PRI_ANY); - if (if_detach_event_tag == NULL) { + if (V_if_detach_event_tag == NULL) { MROUTER_UNLOCK(); return (ENOMEM); } - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL); - - callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD, - expire_bw_upcalls_send, NULL); - callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL); + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, + expire_upcalls, (void *)so->so_vnet); + callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, + expire_bw_upcalls_send, (void *)so->so_vnet); + callout_reset(&V_bw_meter_ch, BW_METER_PERIOD, + expire_bw_meter_process, (void *)so->so_vnet); V_ip_mrouter = so; MROUTER_UNLOCK(); - if (mrtdebug) + if (V_mrtdebug) log(LOG_DEBUG, "ip_mrouter_init\n"); return 0; @@ -762,6 +811,7 @@ X_ip_mrouter_done(void) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); vifi_t vifi; int i; struct ifnet *ifp; @@ -780,41 +830,41 @@ * Detach/disable hooks to the reset of the system. */ V_ip_mrouter = NULL; - mrt_api_config = 0; + V_mrt_api_config = 0; VIF_LOCK(); /* * For each phyint in use, disable promiscuous reception of all IP * multicasts. */ - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_lcl_addr.s_addr != 0 && - !(viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { + for (vifi = 0; vifi < V_numvifs; vifi++) { + if (V_viftable[vifi].v_lcl_addr.s_addr != 0 && + !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr); so->sin_len = sizeof(struct sockaddr_in); so->sin_family = AF_INET; so->sin_addr.s_addr = INADDR_ANY; - ifp = viftable[vifi].v_ifp; + ifp = V_viftable[vifi].v_ifp; if_allmulti(ifp, 0); } } - bzero((caddr_t)viftable, sizeof(viftable)); - numvifs = 0; - pim_assert = 0; + bzero((caddr_t)V_viftable, sizeof(V_viftable)); + V_numvifs = 0; + V_pim_assert = 0; VIF_UNLOCK(); - EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag); + EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_if_detach_event_tag); /* * Free all multicast forwarding cache entries. */ - callout_stop(&expire_upcalls_ch); - callout_stop(&bw_upcalls_ch); - callout_stop(&bw_meter_ch); + callout_stop(&V_expire_upcalls_ch); + callout_stop(&V_bw_upcalls_ch); + callout_stop(&V_bw_meter_ch); MFC_LOCK(); for (i = 0; i < MFCTBLSIZ; i++) { - for (rt = mfctable[i]; rt != NULL; ) { + for (rt = V_mfctable[i]; rt != NULL; ) { struct mfc *nr = rt->mfc_next; for (rte = rt->mfc_stall; rte != NULL; ) { @@ -829,17 +879,19 @@ rt = nr; } } - bzero((caddr_t)mfctable, sizeof(mfctable)); - bzero((caddr_t)nexpire, sizeof(nexpire)); - bw_upcalls_n = 0; - bzero(bw_meter_timers, sizeof(bw_meter_timers)); + bzero((caddr_t)V_mfctable, sizeof(V_mfctable)); + bzero((caddr_t)V_nexpire, sizeof(V_nexpire)); + V_bw_upcalls_n = 0; + bzero(V_bw_meter_timers, sizeof(V_bw_meter_timers)); MFC_UNLOCK(); - reg_vif_num = VIFI_INVALID; + if (V_reg_vif_num != VIFI_INVALID) + IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); + V_reg_vif_num = VIFI_INVALID; MROUTER_UNLOCK(); - if (mrtdebug) + if (V_mrtdebug) log(LOG_DEBUG, "ip_mrouter_done\n"); return 0; @@ -851,10 +903,11 @@ static int set_assert(int i) { + INIT_VNET_MROUTE(curvnet); if ((i != 1) && (i != 0)) return EINVAL; - pim_assert = i; + V_pim_assert = i; return 0; } @@ -865,6 +918,7 @@ int set_api_config(uint32_t *apival) { + INIT_VNET_MROUTE(curvnet); int i; /* @@ -874,23 +928,23 @@ * - pim_assert is not enabled * - the MFC table is empty */ - if (numvifs > 0) { + if (V_numvifs > 0) { *apival = 0; return EPERM; } - if (pim_assert) { + if (V_pim_assert) { *apival = 0; return EPERM; } for (i = 0; i < MFCTBLSIZ; i++) { - if (mfctable[i] != NULL) { + if (V_mfctable[i] != NULL) { *apival = 0; return EPERM; } } - mrt_api_config = *apival & mrt_api_support; - *apival = mrt_api_config; + V_mrt_api_config = *apival & mrt_api_support; + *apival = V_mrt_api_config; return 0; } @@ -901,7 +955,8 @@ static int add_vif(struct vifctl *vifcp) { - struct vif *vifp = viftable + vifcp->vifc_vifi; + INIT_VNET_MROUTE(curvnet); + struct vif *vifp = V_viftable + vifcp->vifc_vifi; struct sockaddr_in sin = {sizeof sin, AF_INET}; struct ifaddr *ifa; struct ifnet *ifp; @@ -950,14 +1005,19 @@ VIF_UNLOCK(); return EOPNOTSUPP; } else if (vifcp->vifc_flags & VIFF_REGISTER) { - ifp = &multicast_register_if; - if (mrtdebug) + ifp = &V_multicast_register_if; + if (V_mrtdebug) log(LOG_DEBUG, "Adding a register vif, ifp: %p\n", - (void *)&multicast_register_if); - if (reg_vif_num == VIFI_INVALID) { - if_initname(&multicast_register_if, "register_vif", 0); - multicast_register_if.if_flags = IFF_LOOPBACK; - reg_vif_num = vifcp->vifc_vifi; + (void *)&V_multicast_register_if); + if (V_reg_vif_num == VIFI_INVALID) { + if_initname(&V_multicast_register_if, "register_vif", 0); + V_multicast_register_if.if_flags = IFF_LOOPBACK; + V_reg_vif_num = vifcp->vifc_vifi; + IF_ADDR_LOCK_INIT(&V_multicast_register_if); +#ifdef VIMAGE + V_multicast_register_if.if_vnet = curvnet; + V_multicast_register_if.if_home_vnet = curvnet; +#endif /* VIMAGE */ } } else { /* Make sure the interface supports multicast */ if ((ifp->if_flags & IFF_MULTICAST) == 0) { @@ -988,11 +1048,11 @@ bzero(&vifp->v_route, sizeof(vifp->v_route)); /* Adjust numvifs up if the vifi is higher than numvifs */ - if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; + if (V_numvifs <= vifcp->vifc_vifi) V_numvifs = vifcp->vifc_vifi + 1; VIF_UNLOCK(); - if (mrtdebug) + if (V_mrtdebug) log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x\n", vifcp->vifc_vifi, (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr), @@ -1009,14 +1069,15 @@ static int del_vif_locked(vifi_t vifi) { + INIT_VNET_MROUTE(curvnet); struct vif *vifp; VIF_LOCK_ASSERT(); - if (vifi >= numvifs) { + if (vifi >= V_numvifs) { return EINVAL; } - vifp = &viftable[vifi]; + vifp = &V_viftable[vifi]; if (vifp->v_lcl_addr.s_addr == INADDR_ANY) { return EADDRNOTAVAIL; } @@ -1024,19 +1085,22 @@ if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) if_allmulti(vifp->v_ifp, 0); - if (vifp->v_flags & VIFF_REGISTER) - reg_vif_num = VIFI_INVALID; + if (vifp->v_flags & VIFF_REGISTER) { + if (V_reg_vif_num != VIFI_INVALID) + IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); + V_reg_vif_num = VIFI_INVALID; + } bzero((caddr_t)vifp, sizeof (*vifp)); - if (mrtdebug) - log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs); + if (V_mrtdebug) + log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, V_numvifs); /* Adjust numvifs down */ - for (vifi = numvifs; vifi > 0; vifi--) - if (viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY) + for (vifi = V_numvifs; vifi > 0; vifi--) + if (V_viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY) break; - numvifs = vifi; + V_numvifs = vifi; return 0; } @@ -1044,6 +1108,7 @@ static int del_vif(vifi_t vifi) { + INIT_VNET_MROUTE(curvnet); int cc; VIF_LOCK(); @@ -1059,16 +1124,17 @@ static void update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp) { + INIT_VNET_MROUTE(curvnet); int i; rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < numvifs; i++) { + for (i = 0; i < V_numvifs; i++) { rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - rt->mfc_flags[i] = mfccp->mfcc_flags[i] & mrt_api_config & + rt->mfc_flags[i] = mfccp->mfcc_flags[i] & V_mrt_api_config & MRT_MFC_FLAGS_ALL; } /* set the RP address */ - if (mrt_api_config & MRT_MFC_RP) + if (V_mrt_api_config & MRT_MFC_RP) rt->mfc_rp = mfccp->mfcc_rp; else rt->mfc_rp.s_addr = INADDR_ANY; @@ -1099,6 +1165,7 @@ static int add_mfc(struct mfcctl2 *mfccp) { + INIT_VNET_MROUTE(curvnet); struct mfc *rt; u_long hash; struct rtdetq *rte; @@ -1111,7 +1178,7 @@ /* If an entry already exists, just update the fields */ if (rt) { - if (mrtdebug & DEBUG_MFC) + if (V_mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n", (u_long)ntohl(mfccp->mfcc_origin.s_addr), (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), @@ -1127,7 +1194,7 @@ * Find the entry for which the upcall was made and update */ hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); - for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { + for (rt = V_mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && @@ -1140,7 +1207,7 @@ (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, (void *)rt->mfc_stall); - if (mrtdebug & DEBUG_MFC) + if (V_mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n", (u_long)ntohl(mfccp->mfcc_origin.s_addr), (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), @@ -1149,7 +1216,7 @@ init_mfc_params(rt, mfccp); rt->mfc_expire = 0; /* Don't clean this guy up */ - nexpire[hash]--; + V_nexpire[hash]--; /* free packets Qed at the end of this entry */ for (rte = rt->mfc_stall; rte != NULL; ) { @@ -1168,18 +1235,18 @@ * It is possible that an entry is being inserted without an upcall */ if (nstl == 0) { - if (mrtdebug & DEBUG_MFC) + if (V_mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n", hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent); - for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { + for (rt = V_mfctable[hash]; rt != NULL; rt = rt->mfc_next) { if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { init_mfc_params(rt, mfccp); if (rt->mfc_expire) - nexpire[hash]--; + V_nexpire[hash]--; rt->mfc_expire = 0; break; /* XXX */ } @@ -1198,8 +1265,8 @@ rt->mfc_bw_meter = NULL; /* insert new entry at head of hash chain */ - rt->mfc_next = mfctable[hash]; - mfctable[hash] = rt; + rt->mfc_next = V_mfctable[hash]; + V_mfctable[hash] = rt; } } MFC_UNLOCK(); @@ -1213,6 +1280,7 @@ static int del_mfc(struct mfcctl2 *mfccp) { + INIT_VNET_MROUTE(curvnet); struct in_addr origin; struct in_addr mcastgrp; struct mfc *rt; @@ -1223,14 +1291,14 @@ origin = mfccp->mfcc_origin; mcastgrp = mfccp->mfcc_mcastgrp; - if (mrtdebug & DEBUG_MFC) + if (V_mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n", (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); MFC_LOCK(); hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); - for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next) + for (nptr = &V_mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next) if (origin.s_addr == rt->mfc_origin.s_addr && mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && rt->mfc_stall == NULL) @@ -1294,11 +1362,12 @@ struct ip_moptions *imo) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); struct mfc *rt; int error; vifi_t vifi; - if (mrtdebug & DEBUG_FORWARD) + if (V_mrtdebug & DEBUG_FORWARD) log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n", (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), (void *)ifp); @@ -1326,11 +1395,11 @@ VIF_LOCK(); MFC_LOCK(); - if (imo && ((vifi = imo->imo_multicast_vif) < numvifs)) { + if (imo && ((vifi = imo->imo_multicast_vif) < V_numvifs)) { if (ip->ip_ttl < MAXTTL) ip->ip_ttl++; /* compensate for -1 in *_send routines */ - if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { - struct vif *vifp = viftable + vifi; + if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) { + struct vif *vifp = V_viftable + vifi; printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s)\n", (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr), @@ -1343,7 +1412,7 @@ VIF_UNLOCK(); return error; } - if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { + if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) { printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr)); if (!imo) @@ -1363,7 +1432,7 @@ /* * Determine forwarding vifs from the forwarding cache table */ - ++mrtstat.mrts_mfc_lookups; + ++V_mrtstat.mrts_mfc_lookups; rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr); /* Entry exists, so forward if necessary */ @@ -1383,10 +1452,10 @@ u_long hash; int hlen = ip->ip_hl << 2; - ++mrtstat.mrts_mfc_misses; + ++V_mrtstat.mrts_mfc_misses; - mrtstat.mrts_no_route++; - if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) + V_mrtstat.mrts_no_route++; + if (V_mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n", (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr)); @@ -1414,7 +1483,7 @@ /* is there an upcall waiting for this flow ? */ hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); - for (rt = mfctable[hash]; rt; rt = rt->mfc_next) { + for (rt = V_mfctable[hash]; rt; rt = rt->mfc_next) { if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && (rt->mfc_stall != NULL)) @@ -1431,9 +1500,9 @@ * Locate the vifi for the incoming interface for this packet. * If none found, drop packet. */ - for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++) + for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; vifi++) ; - if (vifi >= numvifs) /* vif not found, drop packet */ + if (vifi >= V_numvifs) /* vif not found, drop packet */ goto non_fatal; /* no upcall, so make a new entry */ @@ -1455,12 +1524,12 @@ im->im_mbz = 0; im->im_vif = vifi; - mrtstat.mrts_upcalls++; + V_mrtstat.mrts_upcalls++; k_igmpsrc.sin_addr = ip->ip_src; if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); - ++mrtstat.mrts_upq_sockfull; + ++V_mrtstat.mrts_upq_sockfull; fail1: free(rt, M_MRTABLE); fail: @@ -1475,8 +1544,8 @@ rt->mfc_origin.s_addr = ip->ip_src.s_addr; rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; rt->mfc_expire = UPCALL_EXPIRE; - nexpire[hash]++; - for (i = 0; i < numvifs; i++) { + V_nexpire[hash]++; + for (i = 0; i < V_numvifs; i++) { rt->mfc_ttls[i] = 0; rt->mfc_flags[i] = 0; } @@ -1487,8 +1556,8 @@ rt->mfc_bw_meter = NULL; /* link into table */ - rt->mfc_next = mfctable[hash]; - mfctable[hash] = rt; + rt->mfc_next = V_mfctable[hash]; + V_mfctable[hash] = rt; rt->mfc_stall = rte; } else { @@ -1505,7 +1574,7 @@ npkts++; if (npkts > MAX_UPQ) { - mrtstat.mrts_upq_ovflw++; + V_mrtstat.mrts_upq_ovflw++; non_fatal: free(rte, M_MRTABLE); m_freem(mb0); @@ -1535,15 +1604,16 @@ static void expire_upcalls(void *unused) { + INIT_VNET_MROUTE( ((struct vnet *)unused) ); struct rtdetq *rte; struct mfc *mfc, **nptr; int i; MFC_LOCK(); for (i = 0; i < MFCTBLSIZ; i++) { - if (nexpire[i] == 0) + if (V_nexpire[i] == 0) continue; - nptr = &mfctable[i]; + nptr = &V_mfctable[i]; for (mfc = *nptr; mfc != NULL; mfc = *nptr) { /* * Skip real cache entries @@ -1552,7 +1622,7 @@ */ if (mfc->mfc_stall != NULL && mfc->mfc_expire != 0 && --mfc->mfc_expire == 0) { - if (mrtdebug & DEBUG_EXPIRE) + if (V_mrtdebug & DEBUG_EXPIRE) log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n", (u_long)ntohl(mfc->mfc_origin.s_addr), (u_long)ntohl(mfc->mfc_mcastgrp.s_addr)); @@ -1567,8 +1637,8 @@ free(rte, M_MRTABLE); rte = n; } - ++mrtstat.mrts_cache_cleanups; - nexpire[i]--; + ++V_mrtstat.mrts_cache_cleanups; + V_nexpire[i]--; /* * free the bw_meter entries @@ -1587,9 +1657,8 @@ } } } + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, unused); MFC_UNLOCK(); - - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL); } /* @@ -1599,6 +1668,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); struct ip *ip = mtod(m, struct ip *); vifi_t vifi; int plen = ip->ip_len; @@ -1610,11 +1680,11 @@ * * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) */ - if (xmt_vif < numvifs) { - if (viftable[xmt_vif].v_flags & VIFF_REGISTER) - pim_register_send(ip, viftable + xmt_vif, m, rt); + if (xmt_vif < V_numvifs) { + if (V_viftable[xmt_vif].v_flags & VIFF_REGISTER) + pim_register_send(ip, V_viftable + xmt_vif, m, rt); else - phyint_send(ip, viftable + xmt_vif, m); + phyint_send(ip, V_viftable + xmt_vif, m); return 1; } @@ -1622,12 +1692,12 @@ * Don't forward if it didn't arrive from the parent vif for its origin. */ vifi = rt->mfc_parent; - if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { + if ((vifi >= V_numvifs) || (V_viftable[vifi].v_ifp != ifp)) { /* came in the wrong interface */ - if (mrtdebug & DEBUG_FORWARD) + if (V_mrtdebug & DEBUG_FORWARD) log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n", - (void *)ifp, vifi, (void *)viftable[vifi].v_ifp); - ++mrtstat.mrts_wrong_if; + (void *)ifp, vifi, (void *)V_viftable[vifi].v_ifp); + ++V_mrtstat.mrts_wrong_if; ++rt->mfc_wrong_if; /* * If we are doing PIM assert processing, send a message @@ -1637,17 +1707,18 @@ * can complete the SPT switch, regardless of the type * of the iif (broadcast media, GRE tunnel, etc). */ - if (pim_assert && (vifi < numvifs) && viftable[vifi].v_ifp) { + if (V_pim_assert && (vifi < V_numvifs) && V_viftable[vifi].v_ifp) { struct timeval now; u_long delta; - if (ifp == &multicast_register_if) - pimstat.pims_rcv_registers_wrongiif++; + if (ifp == &V_multicast_register_if) + V_pimstat.pims_rcv_registers_wrongiif++; /* Get vifi for the incoming packet */ - for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++) + for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; + vifi++) ; - if (vifi >= numvifs) + if (vifi >= V_numvifs) return 0; /* The iif is not found: ignore the packet. */ if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_DISABLE_WRONGVIF) @@ -1675,13 +1746,13 @@ im->im_mbz = 0; im->im_vif = vifi; - mrtstat.mrts_upcalls++; + V_mrtstat.mrts_upcalls++; k_igmpsrc.sin_addr = im->im_src; if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); - ++mrtstat.mrts_upq_sockfull; + ++V_mrtstat.mrts_upq_sockfull; return ENOBUFS; } } @@ -1690,12 +1761,12 @@ } /* If I sourced this packet, it counts as output, else it was input. */ - if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { - viftable[vifi].v_pkt_out++; - viftable[vifi].v_bytes_out += plen; + if (ip->ip_src.s_addr == V_viftable[vifi].v_lcl_addr.s_addr) { + V_viftable[vifi].v_pkt_out++; + V_viftable[vifi].v_bytes_out += plen; } else { - viftable[vifi].v_pkt_in++; - viftable[vifi].v_bytes_in += plen; + V_viftable[vifi].v_pkt_in++; + V_viftable[vifi].v_bytes_in += plen; } rt->mfc_pkt_cnt++; rt->mfc_byte_cnt += plen; @@ -1706,14 +1777,14 @@ * - the ttl exceeds the vif's threshold * - there are group members downstream on interface */ - for (vifi = 0; vifi < numvifs; vifi++) + for (vifi = 0; vifi < V_numvifs; vifi++) if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) { - viftable[vifi].v_pkt_out++; - viftable[vifi].v_bytes_out += plen; - if (viftable[vifi].v_flags & VIFF_REGISTER) - pim_register_send(ip, viftable + vifi, m, rt); + V_viftable[vifi].v_pkt_out++; + V_viftable[vifi].v_bytes_out += plen; + if (V_viftable[vifi].v_flags & VIFF_REGISTER) + pim_register_send(ip, V_viftable + vifi, m, rt); else - phyint_send(ip, viftable + vifi, m); + phyint_send(ip, V_viftable + vifi, m); } /* @@ -1738,8 +1809,9 @@ static int X_legal_vif_num(int vif) { + INIT_VNET_MROUTE(curvnet); /* XXX unlocked, matter? */ - return (vif >= 0 && vif < numvifs); + return (vif >= 0 && vif < V_numvifs); } /* @@ -1748,9 +1820,10 @@ static u_long X_ip_mcast_src(int vifi) { + INIT_VNET_MROUTE(curvnet); /* XXX unlocked, matter? */ - if (vifi >= 0 && vifi < numvifs) - return viftable[vifi].v_lcl_addr.s_addr; + if (vifi >= 0 && vifi < V_numvifs) + return V_viftable[vifi].v_lcl_addr.s_addr; else return INADDR_ANY; } @@ -1780,6 +1853,7 @@ static void send_packet(struct vif *vifp, struct mbuf *m) { + INIT_VNET_MROUTE(curvnet); struct ip_moptions imo; struct in_multi *imm[2]; int error; @@ -1801,16 +1875,17 @@ * the loopback interface, thus preventing looping. */ error = ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, &imo, NULL); - if (mrtdebug & DEBUG_XMIT) { + if (V_mrtdebug & DEBUG_XMIT) { log(LOG_DEBUG, "phyint_send on vif %td err %d\n", - vifp - viftable, error); + vifp - V_viftable, error); } } static int X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt) { - INIT_VNET_INET(curvnet); + INIT_VNET_INET(so->so_vnet); + INIT_VNET_MROUTE(so->so_vnet); int error, vifi; if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) @@ -1822,39 +1897,39 @@ VIF_LOCK(); - if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */ + if (vifi < 0 || vifi >= V_numvifs) { /* Error if vif is invalid */ VIF_UNLOCK(); return EADDRNOTAVAIL; } if (sopt->sopt_name == IP_RSVP_VIF_ON) { /* Check if socket is available. */ - if (viftable[vifi].v_rsvpd != NULL) { + if (V_viftable[vifi].v_rsvpd != NULL) { VIF_UNLOCK(); return EADDRINUSE; } - viftable[vifi].v_rsvpd = so; + V_viftable[vifi].v_rsvpd = so; /* This may seem silly, but we need to be sure we don't over-increment * the RSVP counter, in case something slips up. */ - if (!viftable[vifi].v_rsvp_on) { - viftable[vifi].v_rsvp_on = 1; + if (!V_viftable[vifi].v_rsvp_on) { + V_viftable[vifi].v_rsvp_on = 1; V_rsvp_on++; } } else { /* must be VIF_OFF */ /* * XXX as an additional consistency check, one could make sure - * that viftable[vifi].v_rsvpd == so, otherwise passing so as + * that V_viftable[vifi].v_rsvpd == so, otherwise passing so as * first parameter is pretty useless. */ - viftable[vifi].v_rsvpd = NULL; + V_viftable[vifi].v_rsvpd = NULL; /* * This may seem silly, but we need to be sure we don't over-decrement * the RSVP counter, in case something slips up. */ - if (viftable[vifi].v_rsvp_on) { - viftable[vifi].v_rsvp_on = 0; + if (V_viftable[vifi].v_rsvp_on) { + V_viftable[vifi].v_rsvp_on = 0; V_rsvp_on--; } } @@ -1865,7 +1940,8 @@ static void X_ip_rsvp_force_done(struct socket *so) { - INIT_VNET_INET(curvnet); + INIT_VNET_INET(so->so_vnet); + INIT_VNET_MROUTE(so->so_vnet); int vifi; /* Don't bother if it is not the right type of socket. */ @@ -1877,14 +1953,14 @@ /* The socket may be attached to more than one vif...this * is perfectly legal. */ - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_rsvpd == so) { - viftable[vifi].v_rsvpd = NULL; + for (vifi = 0; vifi < V_numvifs; vifi++) { + if (V_viftable[vifi].v_rsvpd == so) { + V_viftable[vifi].v_rsvpd = NULL; /* This may seem silly, but we need to be sure we don't * over-decrement the RSVP counter, in case something slips up. */ - if (viftable[vifi].v_rsvp_on) { - viftable[vifi].v_rsvp_on = 0; + if (V_viftable[vifi].v_rsvp_on) { + V_viftable[vifi].v_rsvp_on = 0; V_rsvp_on--; } } @@ -1897,12 +1973,13 @@ X_rsvp_input(struct mbuf *m, int off) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); int vifi; struct ip *ip = mtod(m, struct ip *); struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; struct ifnet *ifp; - if (rsvpdebug) + if (V_rsvpdebug) printf("rsvp_input: rsvp_on %d\n", V_rsvp_on); /* Can still get packets with rsvp_on = 0 if there is a local member @@ -1914,7 +1991,7 @@ return; } - if (rsvpdebug) + if (V_rsvpdebug) printf("rsvp_input: check vifs\n"); #ifdef DIAGNOSTIC @@ -1925,14 +2002,14 @@ VIF_LOCK(); /* Find which vif the packet arrived on. */ - for (vifi = 0; vifi < numvifs; vifi++) - if (viftable[vifi].v_ifp == ifp) + for (vifi = 0; vifi < V_numvifs; vifi++) + if (V_viftable[vifi].v_ifp == ifp) break; - if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) { + if (vifi == V_numvifs || V_viftable[vifi].v_rsvpd == NULL) { /* * Drop the lock here to avoid holding it across rip_input. - * This could make rsvpdebug printfs wrong. If you care, + * This could make V_rsvpdebug printfs wrong. If you care, * record the state of stuff before dropping the lock. */ VIF_UNLOCK(); @@ -1942,13 +2019,13 @@ * is no specific socket for this vif. */ if (V_ip_rsvpd != NULL) { - if (rsvpdebug) + if (V_rsvpdebug) printf("rsvp_input: Sending packet up old-style socket\n"); rip_input(m, off); /* xxx */ } else { - if (rsvpdebug && vifi == numvifs) + if (V_rsvpdebug && vifi == V_numvifs) printf("rsvp_input: Can't find vif for packet.\n"); - else if (rsvpdebug && viftable[vifi].v_rsvpd == NULL) + else if (V_rsvpdebug && V_viftable[vifi].v_rsvpd == NULL) printf("rsvp_input: No socket defined for vif %d\n",vifi); m_freem(m); } @@ -1956,15 +2033,15 @@ } rsvp_src.sin_addr = ip->ip_src; - if (rsvpdebug && m) + if (V_rsvpdebug && m) printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", - m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); + m->m_len,sbspace(&(V_viftable[vifi].v_rsvpd->so_rcv))); - if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { - if (rsvpdebug) + if (socket_send(V_viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { + if (V_rsvpdebug) printf("rsvp_input: Failed to append to socket\n"); } else { - if (rsvpdebug) + if (V_rsvpdebug) printf("rsvp_input: send packet up\n"); } VIF_UNLOCK(); @@ -2004,6 +2081,7 @@ static int add_bw_upcall(struct bw_upcall *req) { + INIT_VNET_MROUTE(curvnet); struct mfc *mfc; struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC, BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC }; @@ -2011,7 +2089,7 @@ struct bw_meter *x; uint32_t flags; - if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) + if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL)) return EOPNOTSUPP; /* Test if the flags are valid */ @@ -2096,10 +2174,11 @@ static int del_bw_upcall(struct bw_upcall *req) { + INIT_VNET_MROUTE(curvnet); struct mfc *mfc; struct bw_meter *x; - if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) + if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL)) return EOPNOTSUPP; MFC_LOCK(); @@ -2252,6 +2331,7 @@ static void bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp) { + INIT_VNET_MROUTE(curvnet); struct timeval delta; struct bw_upcall *u; @@ -2266,13 +2346,13 @@ /* * If there are too many pending upcalls, deliver them now */ - if (bw_upcalls_n >= BW_UPCALLS_MAX) + if (V_bw_upcalls_n >= BW_UPCALLS_MAX) bw_upcalls_send(); /* * Set the bw_upcall entry */ - u = &bw_upcalls[bw_upcalls_n++]; + u = &V_bw_upcalls[V_bw_upcalls_n++]; u->bu_src = x->bm_mfc->mfc_origin; u->bu_dst = x->bm_mfc->mfc_mcastgrp; u->bu_threshold.b_time = x->bm_threshold.b_time; @@ -2299,8 +2379,9 @@ bw_upcalls_send(void) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); struct mbuf *m; - int len = bw_upcalls_n * sizeof(bw_upcalls[0]); + int len = V_bw_upcalls_n * sizeof(V_bw_upcalls[0]); struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; static struct igmpmsg igmpmsg = { 0, /* unused1 */ 0, /* unused2 */ @@ -2313,10 +2394,10 @@ MFC_LOCK_ASSERT(); - if (bw_upcalls_n == 0) + if (V_bw_upcalls_n == 0) return; /* No pending upcalls */ - bw_upcalls_n = 0; + V_bw_upcalls_n = 0; /* * Allocate a new mbuf, initialize it with the header and @@ -2330,16 +2411,16 @@ m->m_len = m->m_pkthdr.len = 0; m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg); - m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&bw_upcalls[0]); + m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&V_bw_upcalls[0]); /* * Send the upcalls * XXX do we need to set the address in k_igmpsrc ? */ - mrtstat.mrts_upcalls++; + V_mrtstat.mrts_upcalls++; if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) { log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n"); - ++mrtstat.mrts_upq_sockfull; + ++V_mrtstat.mrts_upq_sockfull; } } @@ -2364,6 +2445,7 @@ static void schedule_bw_meter(struct bw_meter *x, struct timeval *nowp) { + INIT_VNET_MROUTE(curvnet); int time_hash; MFC_LOCK_ASSERT(); @@ -2383,8 +2465,8 @@ * Compute the timeout hash value and insert the entry */ BW_METER_TIMEHASH(x, time_hash); - x->bm_time_next = bw_meter_timers[time_hash]; - bw_meter_timers[time_hash] = x; + x->bm_time_next = V_bw_meter_timers[time_hash]; + V_bw_meter_timers[time_hash] = x; x->bm_time_hash = time_hash; } @@ -2395,6 +2477,7 @@ static void unschedule_bw_meter(struct bw_meter *x) { + INIT_VNET_MROUTE(curvnet); int time_hash; struct bw_meter *prev, *tmp; @@ -2410,7 +2493,7 @@ if (time_hash >= BW_METER_BUCKETS) return; /* Entry was not scheduled */ - for (prev = NULL, tmp = bw_meter_timers[time_hash]; + for (prev = NULL, tmp = V_bw_meter_timers[time_hash]; tmp != NULL; prev = tmp, tmp = tmp->bm_time_next) if (tmp == x) break; @@ -2421,7 +2504,7 @@ if (prev != NULL) prev->bm_time_next = x->bm_time_next; else - bw_meter_timers[time_hash] = x->bm_time_next; + V_bw_meter_timers[time_hash] = x->bm_time_next; x->bm_time_next = NULL; x->bm_time_hash = BW_METER_BUCKETS; @@ -2438,8 +2521,9 @@ * looking at. */ static void -bw_meter_process() +bw_meter_process(struct vnet *vnet) { + INIT_VNET_MROUTE(vnet); static uint32_t last_tv_sec; /* last time we processed this */ uint32_t loops; @@ -2456,6 +2540,7 @@ loops = BW_METER_BUCKETS; MFC_LOCK(); + CURVNET_SET(vnet); /* * Process all bins of bw_meter entries from the one after the last * processed to the current one. On entry, i points to the last bucket @@ -2468,8 +2553,8 @@ i = 0; /* Disconnect the list of bw_meter entries from the bin */ - tmp_list = bw_meter_timers[i]; - bw_meter_timers[i] = NULL; + tmp_list = V_bw_meter_timers[i]; + V_bw_meter_timers[i] = NULL; /* Process the list of bw_meter entries */ while (tmp_list != NULL) { @@ -2492,8 +2577,8 @@ if (++time_hash >= BW_METER_BUCKETS) time_hash = 0; } - x->bm_time_next = bw_meter_timers[time_hash]; - bw_meter_timers[time_hash] = x; + x->bm_time_next = V_bw_meter_timers[time_hash]; + V_bw_meter_timers[time_hash] = x; x->bm_time_hash = time_hash; continue; @@ -2520,6 +2605,7 @@ /* Send all upcalls that are pending delivery */ bw_upcalls_send(); + CURVNET_RESTORE(); MFC_UNLOCK(); } @@ -2529,12 +2615,14 @@ static void expire_bw_upcalls_send(void *unused) { + INIT_VNET_MROUTE( (struct vnet *)unused ); MFC_LOCK(); + CURVNET_SET( (struct vnet*)unused ); bw_upcalls_send(); + callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, + expire_bw_upcalls_send, unused); + CURVNET_RESTORE(); MFC_UNLOCK(); - - callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD, - expire_bw_upcalls_send, NULL); } /* @@ -2544,10 +2632,12 @@ static void expire_bw_meter_process(void *unused) { - if (mrt_api_config & MRT_MFC_BW_UPCALL) - bw_meter_process(); + INIT_VNET_MROUTE( (struct vnet *)unused ); + if (V_mrt_api_config & MRT_MFC_BW_UPCALL) + bw_meter_process( (struct vnet *)unused ); - callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL); + callout_reset(&V_bw_meter_ch, BW_METER_PERIOD, + expire_bw_meter_process, unused); } /* @@ -2562,16 +2652,17 @@ pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m, struct mfc *rt) { + INIT_VNET_MROUTE(curvnet); struct mbuf *mb_copy, *mm; - if (mrtdebug & DEBUG_PIM) + if (V_mrtdebug & DEBUG_PIM) log(LOG_DEBUG, "pim_register_send: "); /* * Do not send IGMP_WHOLEPKT notifications to userland, if the * rendezvous point was unspecified, and we were told not to. */ - if (pim_squelch_wholepkt != 0 && (mrt_api_config & MRT_MFC_RP) && + if (pim_squelch_wholepkt != 0 && (V_mrt_api_config & MRT_MFC_RP) && (rt->mfc_rp.s_addr == INADDR_ANY)) return 0; @@ -2589,7 +2680,7 @@ mm = m_pullup(mm, sizeof(struct ip)); if (mm != NULL) { ip = mtod(mm, struct ip *); - if ((mrt_api_config & MRT_MFC_RP) && + if ((V_mrt_api_config & MRT_MFC_RP) && (rt->mfc_rp.s_addr != INADDR_ANY)) { pim_register_send_rp(ip, vifp, mm, rt); } else { @@ -2660,6 +2751,7 @@ struct mbuf *mb_copy, struct mfc *rt) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); struct mbuf *mb_first; int len = ntohs(ip->ip_len); struct igmpmsg *im; @@ -2684,25 +2776,25 @@ im = mtod(mb_first, struct igmpmsg *); im->im_msgtype = IGMPMSG_WHOLEPKT; im->im_mbz = 0; - im->im_vif = vifp - viftable; + im->im_vif = vifp - V_viftable; im->im_src = ip->ip_src; im->im_dst = ip->ip_dst; k_igmpsrc.sin_addr = ip->ip_src; - mrtstat.mrts_upcalls++; + V_mrtstat.mrts_upcalls++; if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) { - if (mrtdebug & DEBUG_PIM) + if (V_mrtdebug & DEBUG_PIM) log(LOG_WARNING, "mcast: pim_register_send_upcall: ip_mrouter socket queue full"); - ++mrtstat.mrts_upq_sockfull; + ++V_mrtstat.mrts_upq_sockfull; return ENOBUFS; } /* Keep statistics */ - pimstat.pims_snd_registers_msgs++; - pimstat.pims_snd_registers_bytes += len; + V_pimstat.pims_snd_registers_msgs++; + V_pimstat.pims_snd_registers_bytes += len; return 0; } @@ -2715,6 +2807,7 @@ struct mfc *rt) { INIT_VNET_INET(curvnet); + INIT_VNET_MROUTE(curvnet); struct mbuf *mb_first; struct ip *ip_outer; struct pim_encap_pimhdr *pimhdr; @@ -2723,7 +2816,7 @@ VIF_LOCK_ASSERT(); - if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) { + if ((vifi >= V_numvifs) || (V_viftable[vifi].v_lcl_addr.s_addr == 0)) { m_freem(mb_copy); return EADDRNOTAVAIL; /* The iif vif is invalid */ } @@ -2749,7 +2842,7 @@ *ip_outer = pim_encap_iphdr; ip_outer->ip_id = ip_newid(); ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr); - ip_outer->ip_src = viftable[vifi].v_lcl_addr; + ip_outer->ip_src = V_viftable[vifi].v_lcl_addr; ip_outer->ip_dst = rt->mfc_rp; /* * Copy the inner header TOS to the outer header, and take care of the @@ -2762,7 +2855,7 @@ + sizeof(pim_encap_iphdr)); *pimhdr = pim_encap_pimhdr; /* If the iif crosses a border, set the Border-bit */ - if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config) + if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & V_mrt_api_config) pimhdr->flags |= htonl(PIM_BORDER_REGISTER); mb_first->m_data += sizeof(pim_encap_iphdr); @@ -2772,8 +2865,8 @@ send_packet(vifp, mb_first); /* Keep statistics */ - pimstat.pims_snd_registers_msgs++; - pimstat.pims_snd_registers_bytes += len; + V_pimstat.pims_snd_registers_msgs++; + V_pimstat.pims_snd_registers_bytes += len; return 0; } @@ -2807,6 +2900,7 @@ void pim_input(struct mbuf *m, int off) { + INIT_VNET_MROUTE(curvnet); struct ip *ip = mtod(m, struct ip *); struct pim *pim; int minlen; @@ -2815,14 +2909,14 @@ int iphlen = off; /* Keep statistics */ - pimstat.pims_rcv_total_msgs++; - pimstat.pims_rcv_total_bytes += datalen; + V_pimstat.pims_rcv_total_msgs++; + V_pimstat.pims_rcv_total_bytes += datalen; /* * Validate lengths */ if (datalen < PIM_MINLEN) { - pimstat.pims_rcv_tooshort++; + V_pimstat.pims_rcv_tooshort++; log(LOG_ERR, "pim_input: packet size too small %d from %lx\n", datalen, (u_long)ip->ip_src.s_addr); m_freem(m); @@ -2866,8 +2960,8 @@ if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) { /* do nothing, checksum okay */ } else if (in_cksum(m, datalen)) { - pimstat.pims_rcv_badsum++; - if (mrtdebug & DEBUG_PIM) + V_pimstat.pims_rcv_badsum++; + if (V_mrtdebug & DEBUG_PIM) log(LOG_DEBUG, "pim_input: invalid checksum"); m_freem(m); return; @@ -2875,7 +2969,7 @@ /* PIM version check */ if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) { - pimstat.pims_rcv_badversion++; + V_pimstat.pims_rcv_badversion++; log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n", PIM_VT_V(pim->pim_vt), PIM_VERSION); m_freem(m); @@ -2899,24 +2993,24 @@ struct ifnet *vifp; VIF_LOCK(); - if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) { + if ((V_reg_vif_num >= V_numvifs) || (V_reg_vif_num == VIFI_INVALID)) { VIF_UNLOCK(); - if (mrtdebug & DEBUG_PIM) + if (V_mrtdebug & DEBUG_PIM) log(LOG_DEBUG, - "pim_input: register vif not set: %d\n", reg_vif_num); + "pim_input: register vif not set: %d\n", V_reg_vif_num); m_freem(m); return; } /* XXX need refcnt? */ - vifp = viftable[reg_vif_num].v_ifp; + vifp = V_viftable[V_reg_vif_num].v_ifp; VIF_UNLOCK(); /* * Validate length */ if (datalen < PIM_REG_MINLEN) { - pimstat.pims_rcv_tooshort++; - pimstat.pims_rcv_badregisters++; + V_pimstat.pims_rcv_tooshort++; + V_pimstat.pims_rcv_badregisters++; log(LOG_ERR, "pim_input: register packet size too small %d from %lx\n", datalen, (u_long)ip->ip_src.s_addr); @@ -2927,7 +3021,7 @@ reghdr = (u_int32_t *)(pim + 1); encap_ip = (struct ip *)(reghdr + 1); - if (mrtdebug & DEBUG_PIM) { + if (V_mrtdebug & DEBUG_PIM) { log(LOG_DEBUG, "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n", (u_long)ntohl(encap_ip->ip_src.s_addr), @@ -2937,8 +3031,8 @@ /* verify the version number of the inner packet */ if (encap_ip->ip_v != IPVERSION) { - pimstat.pims_rcv_badregisters++; - if (mrtdebug & DEBUG_PIM) { + V_pimstat.pims_rcv_badregisters++; + if (V_mrtdebug & DEBUG_PIM) { log(LOG_DEBUG, "pim_input: invalid IP version (%d) " "of the inner packet\n", encap_ip->ip_v); } @@ -2948,8 +3042,8 @@ /* verify the inner packet is destined to a mcast group */ if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) { - pimstat.pims_rcv_badregisters++; - if (mrtdebug & DEBUG_PIM) + V_pimstat.pims_rcv_badregisters++; + if (V_mrtdebug & DEBUG_PIM) log(LOG_DEBUG, "pim_input: inner packet of register is not " "multicast %lx\n", @@ -3000,21 +3094,21 @@ /* Keep statistics */ /* XXX: registers_bytes include only the encap. mcast pkt */ - pimstat.pims_rcv_registers_msgs++; - pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len); + V_pimstat.pims_rcv_registers_msgs++; + V_pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len); /* * forward the inner ip packet; point m_data at the inner ip. */ m_adj(m, iphlen + PIM_MINLEN); - if (mrtdebug & DEBUG_PIM) { + if (V_mrtdebug & DEBUG_PIM) { log(LOG_DEBUG, "pim_input: forwarding decapsulated register: " "src %lx, dst %lx, vif %d\n", (u_long)ntohl(encap_ip->ip_src.s_addr), (u_long)ntohl(encap_ip->ip_dst.s_addr), - reg_vif_num); + V_reg_vif_num); } /* NB: vifp was collected above; can it change on us? */ if_simloop(vifp, m, dst.sin_family, 0); @@ -3037,6 +3131,41 @@ return; } +#ifdef VIMAGE +/* initialization for multicast routing state */ +static int +vnet_mroute_iattach(unused) + const void *unused; +{ + INIT_VNET_MROUTE(curvnet); + + V_reg_vif_num = VIFI_INVALID; + MROUTER_LOCK_INIT(); + MFC_LOCK_INIT(); + VIF_LOCK_INIT(); + ip_mrouter_reset(); + return 0; +} + +/* de-initialization for multicast routing state */ +static int +vnet_mroute_idetach(unused) + const void *unused; +{ + INIT_VNET_MROUTE(curvnet); + + X_ip_mrouter_done(); +#ifdef INET6 + X_ip6_mrouter_done(); +#endif + + VIF_LOCK_DESTROY(); + MFC_LOCK_DESTROY(); + MROUTER_LOCK_DESTROY(); + return 0; +} +#endif /* VIMAGE */ + /* * XXX: This is common code for dealing with initialization for both * the IPv4 and IPv6 multicast forwarding paths. It could do with cleanup. @@ -3045,12 +3174,15 @@ ip_mroute_modevent(module_t mod, int type, void *unused) { INIT_VNET_INET(curvnet); + INIT_VNET_INET6(curvnet); + INIT_VNET_MROUTE(curvnet); switch (type) { case MOD_LOAD: - MROUTER_LOCK_INIT(); - MFC_LOCK_INIT(); - VIF_LOCK_INIT(); - ip_mrouter_reset(); +#ifdef VIMAGE + vnet_mod_register(&vnet_mroute_modinfo); +#else + vnet_mroute_iattach(NULL); +#endif TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt", &pim_squelch_wholepkt); @@ -3113,17 +3245,21 @@ */ if (V_ip_mrouter #ifdef INET6 - || ip6_mrouter + || V_ip6_mrouter #endif ) return EINVAL; +#ifdef VIMAGE + vnet_mod_deregister(&vnet_mroute_modinfo); +#else + vnet_mroute_idetach(NULL) +#endif #ifdef INET6 if (pim6_encap_cookie) { encap_detach(pim6_encap_cookie); pim6_encap_cookie = NULL; } - X_ip6_mrouter_done(); ip6_mforward = NULL; ip6_mrouter_done = NULL; ip6_mrouter_get = NULL; @@ -3135,7 +3271,6 @@ encap_detach(pim_encap_cookie); pim_encap_cookie = NULL; } - X_ip_mrouter_done(); ip_mcast_src = NULL; ip_mforward = NULL; ip_mrouter_done = NULL; @@ -3148,10 +3283,6 @@ legal_vif_num = NULL; mrt_ioctl = NULL; rsvp_input_p = NULL; - - VIF_LOCK_DESTROY(); - MFC_LOCK_DESTROY(); - MROUTER_LOCK_DESTROY(); break; default: diff -ur sys.20081015/netinet/ip_mroute.h sys/netinet/ip_mroute.h --- sys.20081015/netinet/ip_mroute.h 2008-08-16 16:29:19.000000000 -0700 +++ sys/netinet/ip_mroute.h 2008-11-05 13:21:08.000000000 -0800 @@ -52,6 +52,10 @@ * bandwidth metering and signaling. */ +#ifdef VIMAGE +#include /* struct pimstat */ +#endif + /* * Multicast Routing set/getsockopt commands. @@ -80,6 +84,9 @@ typedef u_long vifbitmap_t; typedef u_short vifi_t; /* type of a vif index */ #define ALL_VIFS (vifi_t)-1 +#ifdef VIMAGE +#define VIFI_INVALID ((vifi_t) -1) +#endif /* VIMAGE */ #define VIFM_SET(n, m) ((m) |= (1 << (n))) #define VIFM_CLR(n, m) ((m) &= ~(1 << (n))) @@ -205,6 +212,10 @@ #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC 3 #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC 0 +#ifdef VIMAGE +#define BW_METER_BUCKETS 1024 +#endif /* VIMAGE */ + /* * The kernel's multicast routing statistics. */ @@ -361,6 +372,62 @@ extern int (*ip_mrouter_done)(void); extern int (*mrt_ioctl)(int, caddr_t, int); +#ifdef VIMAGE +struct vnet_mroute { + /* from ip_mroute.c */ + u_int _rsvpdebug; + u_int _mrtdebug; + struct mrtstat _mrtstat; + struct mfc *_mfctable[MFCTBLSIZ]; + struct mtx _mrouter_mtx; + struct mtx _mfc_mtx; + struct vif _viftable[MAXVIFS]; + struct mtx _vif_mtx; + u_char _nexpire[MFCTBLSIZ]; + eventhandler_tag _if_detach_event_tag; + struct callout _expire_upcalls_ch; + struct bw_meter *_bw_meter_timers[BW_METER_BUCKETS]; + struct callout _bw_meter_ch; + struct bw_upcall _bw_upcalls[BW_UPCALLS_MAX]; + u_int _bw_upcalls_n; + struct callout _bw_upcalls_ch; + struct pimstat _pimstat; + struct ifnet _multicast_register_if; + vifi_t _reg_vif_num; + vifi_t _numvifs; + int _pim_assert; + uint32_t _mrt_api_config; +}; +#endif /* VIMAGE */ + +#define INIT_VNET_MROUTE(vnet) \ + INIT_FROM_VNET(vnet, VNET_MOD_MROUTE, struct vnet_mroute, vnet_mroute) + +#define VNET_MROUTE(sym) VSYM(vnet_mroute, sym) + +#define V_rsvpdebug VNET_MROUTE(rsvpdebug) +#define V_mrtdebug VNET_MROUTE(mrtdebug) +#define V_mrtstat VNET_MROUTE(mrtstat) +#define V_mfctable VNET_MROUTE(mfctable) +#define V_mrouter_mtx VNET_MROUTE(mrouter_mtx) +#define V_mfc_mtx VNET_MROUTE(mfc_mtx) +#define V_viftable VNET_MROUTE(viftable) +#define V_vif_mtx VNET_MROUTE(vif_mtx) +#define V_nexpire VNET_MROUTE(nexpire) +#define V_if_detach_event_tag VNET_MROUTE(if_detach_event_tag) +#define V_expire_upcalls_ch VNET_MROUTE(expire_upcalls_ch) +#define V_bw_meter_timers VNET_MROUTE(bw_meter_timers) +#define V_bw_meter_ch VNET_MROUTE(bw_meter_ch) +#define V_bw_upcalls VNET_MROUTE(bw_upcalls) +#define V_bw_upcalls_n VNET_MROUTE(bw_upcalls_n) +#define V_bw_upcalls_ch VNET_MROUTE(bw_upcalls_ch) +#define V_pimstat VNET_MROUTE(pimstat) +#define V_multicast_register_if VNET_MROUTE(multicast_register_if) +#define V_reg_vif_num VNET_MROUTE(reg_vif_num) +#define V_numvifs VNET_MROUTE(numvifs) +#define V_pim_assert VNET_MROUTE(pim_assert) +#define V_mrt_api_config VNET_MROUTE(mrt_api_config) + #endif /* _KERNEL */ #endif /* _NETINET_IP_MROUTE_H_ */ diff -ur sys.20081015/netinet/pim_var.h sys/netinet/pim_var.h --- sys.20081015/netinet/pim_var.h 2007-11-19 06:49:11.000000000 -0800 +++ sys/netinet/pim_var.h 2008-10-28 20:01:22.000000000 -0700 @@ -73,7 +73,9 @@ #ifdef _KERNEL void pim_input(struct mbuf *, int); +#ifdef SYSCTL_DECL SYSCTL_DECL(_net_inet_pim); #endif +#endif #endif /* _NETINET_PIM_VAR_H_ */ diff -ur sys.20081015/netinet/vinet.h sys/netinet/vinet.h --- sys.20081015/netinet/vinet.h 2007-11-19 09:09:38.000000000 -0800 +++ sys/netinet/vinet.h 2008-11-03 16:04:36.000000000 -0800 @@ -53,6 +53,9 @@ #include #include #include +#include +#include +#include struct vnet_inet { struct in_ifaddrhashhead *_in_ifaddrhashtbl; diff -ur sys.20081015/netinet6/ip6_input.c sys/netinet6/ip6_input.c --- sys.20081015/netinet6/ip6_input.c 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/ip6_input.c 2008-10-28 20:01:22.000000000 -0700 @@ -192,6 +192,20 @@ nd6_init(); frag6_init(); + V_ip6_mrouter_ver = 0; + V_ip6_mrouter = NULL; + bzero(&V_mrt6stat, sizeof(V_mrt6stat)); + bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); + bzero((caddr_t)V_n6expire, sizeof(V_n6expire)); + bzero((caddr_t)V_mif6table, sizeof(V_mif6table)); + V_mrt6debug = 0; + V_multicast_register_if6 = NULL; + V_nummifs = 0; + V_reg_mif_num = (mifi_t)-1; + bzero(&V_pim6stat, sizeof(V_pim6stat)); + V_pim6 = 0; + bzero((caddr_t)V_upcall_data, sizeof(V_upcall_data)); + #ifdef VIMAGE /* Skip global initialization stuff for non-default instances. */ if (!IS_DEFAULT_VNET(curvnet)) @@ -507,7 +521,7 @@ IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); if (in6m) ours = 1; - else if (!ip6_mrouter) { + else if (!V_ip6_mrouter) { V_ip6stat.ip6s_notmember++; V_ip6stat.ip6s_cantforward++; in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); @@ -768,7 +782,7 @@ * ip6_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. */ - if (ip6_mrouter && ip6_mforward && + if (V_ip6_mrouter && ip6_mforward && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { V_ip6stat.ip6s_cantforward++; m_freem(m); diff -ur sys.20081015/netinet6/ip6_mroute.c sys/netinet6/ip6_mroute.c --- sys.20081015/netinet6/ip6_mroute.c 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/ip6_mroute.c 2008-11-05 14:34:10.000000000 -0800 @@ -160,14 +160,17 @@ SYSCTL_DECL(_net_inet6_ip6); SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); +#ifndef VIMAGE static struct mrt6stat mrt6stat; -SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW, - &mrt6stat, mrt6stat, +#endif /* !VIMAGE */ +SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_ip6, OID_AUTO, mrt6stat, + CTLFLAG_RW, mrt6stat, mrt6stat, "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)"); #define NO_RTE_FOUND 0x1 #define RTE_FOUND 0x2 +#ifndef VIMAGE static struct mf6c *mf6ctable[MF6CTBLSIZ]; SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD, &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]", @@ -180,6 +183,7 @@ SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD, &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]", "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)"); +#endif /* !VIMAGE */ #ifdef MRT6DEBUG #ifndef VIMAGE @@ -199,7 +203,9 @@ #ifdef INET #ifdef MROUTING +#ifndef VIMAGE extern struct socket *ip_mrouter; +#endif /* !VIMAGE */ #endif #endif @@ -214,19 +220,23 @@ * only exist as a placeholder for multicast source * verification. */ +#ifndef VIMAGE static struct ifnet *multicast_register_if6; +#endif /* !VIMAGE */ #define ENCAP_HOPS 64 /* * Private variables. */ +#ifndef VIMAGE static mifi_t nummifs = 0; static mifi_t reg_mif_num = (mifi_t)-1; static struct pim6stat pim6stat; -SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD, - &pim6stat, pim6stat, +#endif /* !VIMAGE */ +SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_pim, PIM6CTL_STATS, stats, + CTLFLAG_RD, pim6stat, pim6stat, "PIM Statistics (struct pim6stat, netinet6/pim_var.h)"); #ifndef VIMAGE @@ -245,9 +255,9 @@ * Find a route for a given origin IPv6 address and Multicast group address. */ #define MF6CFIND(o, g, rt) do { \ - struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \ + struct mf6c *_rt = V_mf6ctable[MF6CHASH(o,g)]; \ rt = NULL; \ - mrt6stat.mrt6s_mfc_lookups++; \ + V_mrt6stat.mrt6s_mfc_lookups++; \ while (_rt) { \ if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \ IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \ @@ -258,7 +268,7 @@ _rt = _rt->mf6c_next; \ } \ if (rt == NULL) { \ - mrt6stat.mrt6s_mfc_misses++; \ + V_mrt6stat.mrt6s_mfc_misses++; \ } \ } while (/*CONSTCOND*/ 0) @@ -291,7 +301,9 @@ #ifdef UPCALL_TIMING #define UPCALL_MAX 50 +#ifndef VIMAGE static u_long upcall_data[UPCALL_MAX + 1]; +#endif /* !VIMAGE */ static void collate(); #endif /* UPCALL_TIMING */ @@ -303,7 +315,9 @@ static int add_m6fc(struct mf6cctl *); static int del_m6fc(struct mf6cctl *); -static struct callout expire_upcalls_ch; +#ifndef VIMAGE +static struct callout expire_upcalls_ch6; +#endif /* !VIMAGE */ int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m); int X_ip6_mrouter_done(void); @@ -311,19 +325,21 @@ int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt); int X_mrt6_ioctl(int cmd, caddr_t data); + /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ int X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) { + INIT_VNET_INET6(so->so_vnet); int error = 0; int optval; struct mif6ctl mifc; struct mf6cctl mfcc; mifi_t mifi; - if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT) + if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT) return (EACCES); switch (sopt->sopt_name) { @@ -385,10 +401,10 @@ int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) { - INIT_VNET_INET6(curvnet); + INIT_VNET_INET6(so->so_vnet); int error = 0; - if (so != ip6_mrouter) + if (so != V_ip6_mrouter) return (EACCES); switch (sopt->sopt_name) { @@ -421,6 +437,7 @@ static int get_sg_cnt(struct sioc_sg_req6 *req) { + INIT_VNET_INET6(curvnet); struct mf6c *rt; int s; @@ -446,15 +463,16 @@ static int get_mif6_cnt(struct sioc_mif_req6 *req) { + INIT_VNET_INET6(curvnet); mifi_t mifi = req->mifi; - if (mifi >= nummifs) + if (mifi >= V_nummifs) return (EINVAL); - req->icount = mif6table[mifi].m6_pkt_in; - req->ocount = mif6table[mifi].m6_pkt_out; - req->ibytes = mif6table[mifi].m6_bytes_in; - req->obytes = mif6table[mifi].m6_bytes_out; + req->icount = V_mif6table[mifi].m6_pkt_in; + req->ocount = V_mif6table[mifi].m6_pkt_out; + req->ibytes = V_mif6table[mifi].m6_bytes_in; + req->obytes = V_mif6table[mifi].m6_bytes_out; return (0); } @@ -477,9 +495,11 @@ static int ip6_mrouter_init(struct socket *so, int v, int cmd) { - INIT_VNET_INET6(curvnet); + INIT_VNET_INET6(so->so_vnet); V_ip6_mrouter_ver = 0; + V_nummifs = 0; + V_reg_mif_num = (mifi_t)-1; #ifdef MRT6DEBUG V_mrt6debug = 0; @@ -497,20 +517,20 @@ if (v != 1) return (ENOPROTOOPT); - if (ip6_mrouter != NULL) + if (V_ip6_mrouter != NULL) return (EADDRINUSE); - ip6_mrouter = so; + V_ip6_mrouter = so; V_ip6_mrouter_ver = cmd; - bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); - bzero((caddr_t)n6expire, sizeof(n6expire)); + bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); + bzero((caddr_t)V_n6expire, sizeof(V_n6expire)); V_pim6 = 0;/* used for stubbing out/in pim stuff */ - callout_init(&expire_upcalls_ch, 0); - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, - expire_upcalls, NULL); + callout_init(&V_expire_upcalls_ch6, 0); + callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT, + expire_upcalls, (void *)so->so_vnet); #ifdef MRT6DEBUG if (V_mrt6debug) @@ -547,29 +567,29 @@ * XXX: there may be an interface in which the IPv4 multicast * daemon is not interested... */ - if (!ip_mrouter) + if (!V_ip_mrouter) #endif #endif { - for (mifi = 0; mifi < nummifs; mifi++) { - if (mif6table[mifi].m6_ifp && - !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { - if_allmulti(mif6table[mifi].m6_ifp, 0); + for (mifi = 0; mifi < V_nummifs; mifi++) { + if (V_mif6table[mifi].m6_ifp && + !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) { + if_allmulti(V_mif6table[mifi].m6_ifp, 0); } } } - bzero((caddr_t)mif6table, sizeof(mif6table)); - nummifs = 0; + bzero((caddr_t)V_mif6table, sizeof(V_mif6table)); + V_nummifs = 0; V_pim6 = 0; /* used to stub out/in pim specific code */ - callout_stop(&expire_upcalls_ch); + callout_stop(&V_expire_upcalls_ch6); /* * Free all multicast forwarding cache entries. */ for (i = 0; i < MF6CTBLSIZ; i++) { - rt = mf6ctable[i]; + rt = V_mf6ctable[i]; while (rt) { struct mf6c *frt; @@ -586,19 +606,19 @@ } } - bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); + bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); /* * Reset register interface */ - if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) { - if_detach(multicast_register_if6); - if_free(multicast_register_if6); - reg_mif_num = (mifi_t)-1; - multicast_register_if6 = NULL; + if (V_reg_mif_num != (mifi_t)-1 && V_multicast_register_if6 != NULL) { + if_detach(V_multicast_register_if6); + if_free(V_multicast_register_if6); + V_reg_mif_num = (mifi_t)-1; + V_multicast_register_if6 = NULL; } - ip6_mrouter = NULL; + V_ip6_mrouter = NULL; V_ip6_mrouter_ver = 0; splx(s); @@ -620,13 +640,14 @@ add_m6if(struct mif6ctl *mifcp) { INIT_VNET_NET(curvnet); + INIT_VNET_INET6(curvnet); struct mif6 *mifp; struct ifnet *ifp; int error, s; if (mifcp->mif6c_mifi >= MAXMIFS) return (EINVAL); - mifp = mif6table + mifcp->mif6c_mifi; + mifp = V_mif6table + mifcp->mif6c_mifi; if (mifp->m6_ifp) return (EADDRINUSE); /* XXX: is it appropriate? */ if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) @@ -634,14 +655,14 @@ ifp = ifnet_byindex(mifcp->mif6c_pifi); if (mifcp->mif6c_flags & MIFF_REGISTER) { - if (reg_mif_num == (mifi_t)-1) { + if (V_reg_mif_num == (mifi_t)-1) { ifp = if_alloc(IFT_OTHER); if_initname(ifp, "register_mif", 0); ifp->if_flags |= IFF_LOOPBACK; if_attach(ifp); - multicast_register_if6 = ifp; - reg_mif_num = mifcp->mif6c_mifi; + V_multicast_register_if6 = ifp; + V_reg_mif_num = mifcp->mif6c_mifi; /* * it is impossible to guess the ifindex of the * register interface. So mif6c_pifi is automatically @@ -649,7 +670,7 @@ */ mifcp->mif6c_pifi = ifp->if_index; } else { - ifp = multicast_register_if6; + ifp = V_multicast_register_if6; } } /* if REGISTER */ @@ -676,9 +697,9 @@ mifp->m6_bytes_out = 0; splx(s); - /* Adjust nummifs up if the mifi is higher than nummifs */ - if (nummifs <= mifcp->mif6c_mifi) - nummifs = mifcp->mif6c_mifi + 1; + /* Adjust V_nummifs up if the mifi is higher than V_nummifs */ + if (V_nummifs <= mifcp->mif6c_mifi) + V_nummifs = mifcp->mif6c_mifi + 1; #ifdef MRT6DEBUG if (V_mrt6debug) @@ -697,12 +718,13 @@ static int del_m6if(mifi_t *mifip) { - struct mif6 *mifp = mif6table + *mifip; + INIT_VNET_INET6(curvnet); + struct mif6 *mifp = V_mif6table + *mifip; mifi_t mifi; struct ifnet *ifp; int s; - if (*mifip >= nummifs) + if (*mifip >= V_nummifs) return (EINVAL); if (mifp->m6_ifp == NULL) return (EINVAL); @@ -718,28 +740,28 @@ if_allmulti(ifp, 0); } else { - if (reg_mif_num != (mifi_t)-1 && - multicast_register_if6 != NULL) { - if_detach(multicast_register_if6); - if_free(multicast_register_if6); - reg_mif_num = (mifi_t)-1; - multicast_register_if6 = NULL; + if (V_reg_mif_num != (mifi_t)-1 && + V_multicast_register_if6 != NULL) { + if_detach(V_multicast_register_if6); + if_free(V_multicast_register_if6); + V_reg_mif_num = (mifi_t)-1; + V_multicast_register_if6 = NULL; } } bzero((caddr_t)mifp, sizeof(*mifp)); - /* Adjust nummifs down */ - for (mifi = nummifs; mifi > 0; mifi--) - if (mif6table[mifi - 1].m6_ifp) + /* Adjust V_nummifs down */ + for (mifi = V_nummifs; mifi > 0; mifi--) + if (V_mif6table[mifi - 1].m6_ifp) break; - nummifs = mifi; + V_nummifs = mifi; splx(s); #ifdef MRT6DEBUG if (V_mrt6debug) - log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs); + log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, V_nummifs); #endif return (0); @@ -787,7 +809,7 @@ s = splnet(); hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr, mfccp->mf6cc_mcastgrp.sin6_addr); - for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { + for (rt = V_mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, &mfccp->mf6cc_origin.sin6_addr) && IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, @@ -825,7 +847,7 @@ rt->mf6c_wrong_if = 0; rt->mf6c_expire = 0; /* Don't clean this guy up */ - n6expire[hash]--; + V_n6expire[hash]--; /* free packets Qed at the end of this entry */ for (rte = rt->mf6c_stall; rte != NULL; ) { @@ -856,7 +878,7 @@ mfccp->mf6cc_parent); #endif - for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { + for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, &mfccp->mf6cc_origin.sin6_addr)&& @@ -873,7 +895,7 @@ rt->mf6c_wrong_if = 0; if (rt->mf6c_expire) - n6expire[hash]--; + V_n6expire[hash]--; rt->mf6c_expire = 0; } } @@ -899,8 +921,8 @@ rt->mf6c_stall = NULL; /* link into table */ - rt->mf6c_next = mf6ctable[hash]; - mf6ctable[hash] = rt; + rt->mf6c_next = V_mf6ctable[hash]; + V_mf6ctable[hash] = rt; } } splx(s); @@ -914,6 +936,7 @@ static void collate(struct timeval *t) { + INIT_VNET_INET6(curvnet); u_long d; struct timeval tp; u_long delta; @@ -928,7 +951,7 @@ if (d > UPCALL_MAX) d = UPCALL_MAX; - ++upcall_data[d]; + ++V_upcall_data[d]; } } #endif /* UPCALL_TIMING */ @@ -962,7 +985,7 @@ s = splnet(); - nptr = &mf6ctable[hash]; + nptr = &V_mf6ctable[hash]; while ((rt = *nptr) != NULL) { if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr, &rt->mf6c_origin.sin6_addr) && @@ -1097,7 +1120,7 @@ GET_TIME(tp); #endif /* UPCALL_TIMING */ - mrt6stat.mrt6s_no_route++; + V_mrt6stat.mrt6s_no_route++; #ifdef MRT6DEBUG if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC)) log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n", @@ -1131,7 +1154,7 @@ /* is there an upcall waiting for this packet? */ hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst); - for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { + for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &rt->mf6c_origin.sin6_addr) && IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, @@ -1205,8 +1228,8 @@ "getting the iif info in the kernel\n"); #endif - for (mifp = mif6table, mifi = 0; - mifi < nummifs && mifp->m6_ifp != ifp; + for (mifp = V_mif6table, mifi = 0; + mifi < V_nummifs && mifp->m6_ifp != ifp; mifp++, mifi++) ; @@ -1221,10 +1244,10 @@ break; } - if (socket_send(ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { log(LOG_WARNING, "ip6_mforward: ip6_mrouter " "socket queue full\n"); - mrt6stat.mrt6s_upq_sockfull++; + V_mrt6stat.mrt6s_upq_sockfull++; free(rte, M_MRTABLE6); m_freem(mb0); free(rt, M_MRTABLE6); @@ -1232,7 +1255,7 @@ return (ENOBUFS); } - mrt6stat.mrt6s_upcalls++; + V_mrt6stat.mrt6s_upcalls++; /* insert new entry at head of hash chain */ bzero(rt, sizeof(*rt)); @@ -1243,12 +1266,12 @@ rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6); rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst; rt->mf6c_expire = UPCALL_EXPIRE; - n6expire[hash]++; + V_n6expire[hash]++; rt->mf6c_parent = MF6C_INCOMPLETE_PARENT; /* link into table */ - rt->mf6c_next = mf6ctable[hash]; - mf6ctable[hash] = rt; + rt->mf6c_next = V_mf6ctable[hash]; + V_mf6ctable[hash] = rt; /* Add this entry to the end of the queue */ rt->mf6c_stall = rte; } else { @@ -1258,7 +1281,7 @@ for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next) if (++npkts > MAX_UPQ6) { - mrt6stat.mrt6s_upq_ovflw++; + V_mrt6stat.mrt6s_upq_ovflw++; free(rte, M_MRTABLE6); m_freem(mb0); splx(s); @@ -1289,7 +1312,7 @@ static void expire_upcalls(void *unused) { - INIT_VNET_INET6(curvnet); + INIT_VNET_INET6( (struct vnet*)unused ); struct rtdetq *rte; struct mf6c *mfc, **nptr; int i; @@ -1297,9 +1320,9 @@ s = splnet(); for (i = 0; i < MF6CTBLSIZ; i++) { - if (n6expire[i] == 0) + if (V_n6expire[i] == 0) continue; - nptr = &mf6ctable[i]; + nptr = &V_mf6ctable[i]; while ((mfc = *nptr) != NULL) { rte = mfc->mf6c_stall; /* @@ -1329,8 +1352,8 @@ free(rte, M_MRTABLE6); rte = n; } while (rte != NULL); - mrt6stat.mrt6s_cache_cleanups++; - n6expire[i]--; + V_mrt6stat.mrt6s_cache_cleanups++; + V_n6expire[i]--; *nptr = mfc->mf6c_next; free(mfc, M_MRTABLE6); @@ -1339,9 +1362,9 @@ } } } + callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT, + expire_upcalls, unused); splx(s); - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, - expire_upcalls, NULL); } /* @@ -1377,16 +1400,16 @@ * for its origin. */ mifi = rt->mf6c_parent; - if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) { + if ((mifi >= V_nummifs) || (V_mif6table[mifi].m6_ifp != ifp)) { /* came in the wrong interface */ #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_FORWARD) log(LOG_DEBUG, "wrong if: ifid %d mifi %d mififid %x\n", ifp->if_index, mifi, - mif6table[mifi].m6_ifp->if_index); + V_mif6table[mifi].m6_ifp->if_index); #endif - mrt6stat.mrt6s_wrong_if++; + V_mrt6stat.mrt6s_wrong_if++; rt->mf6c_wrong_if++; /* * If we are doing PIM processing, and we are forwarding @@ -1394,7 +1417,7 @@ * routing daemon. */ /* have to make sure this is a valid mif */ - if (mifi < nummifs && mif6table[mifi].m6_ifp) + if (mifi < V_nummifs && V_mif6table[mifi].m6_ifp) if (V_pim6 && (m->m_flags & M_LOOP) == 0) { /* * Check the M_LOOP flag to avoid an @@ -1440,8 +1463,8 @@ return (EINVAL); } - for (mifp = mif6table, iif = 0; - iif < nummifs && mifp && + for (mifp = V_mif6table, iif = 0; + iif < V_nummifs && mifp && mifp->m6_ifp != ifp; mifp++, iif++) ; @@ -1459,14 +1482,14 @@ break; } - mrt6stat.mrt6s_upcalls++; + V_mrt6stat.mrt6s_upcalls++; - if (socket_send(ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { #ifdef MRT6DEBUG if (V_mrt6debug) log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n"); #endif - ++mrt6stat.mrt6s_upq_sockfull; + ++V_mrt6stat.mrt6s_upq_sockfull; return (ENOBUFS); } /* if socket Q full */ } /* if PIM */ @@ -1476,11 +1499,11 @@ /* If I sourced this packet, it counts as output, else it was input. */ if (m->m_pkthdr.rcvif == NULL) { /* XXX: is rcvif really NULL when output?? */ - mif6table[mifi].m6_pkt_out++; - mif6table[mifi].m6_bytes_out += plen; + V_mif6table[mifi].m6_pkt_out++; + V_mif6table[mifi].m6_bytes_out += plen; } else { - mif6table[mifi].m6_pkt_in++; - mif6table[mifi].m6_bytes_in += plen; + V_mif6table[mifi].m6_pkt_in++; + V_mif6table[mifi].m6_bytes_in += plen; } rt->mf6c_pkt_cnt++; rt->mf6c_byte_cnt += plen; @@ -1496,7 +1519,7 @@ V_ip6stat.ip6s_badscope++; return (error); } - for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) { + for (mifp = V_mif6table, mifi = 0; mifi < V_nummifs; mifp++, mifi++) { if (IF_ISSET(mifi, &rt->mf6c_ifset)) { /* * check if the outgoing packet is going to break @@ -1504,12 +1527,12 @@ * XXX For packets through PIM register tunnel * interface, we believe a routing daemon. */ - if (!(mif6table[rt->mf6c_parent].m6_flags & + if (!(V_mif6table[rt->mf6c_parent].m6_flags & MIFF_REGISTER) && - !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { - if (in6_setscope(&src0, mif6table[mifi].m6_ifp, + !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) { + if (in6_setscope(&src0, V_mif6table[mifi].m6_ifp, &oszone) || - in6_setscope(&dst0, mif6table[mifi].m6_ifp, + in6_setscope(&dst0, V_mif6table[mifi].m6_ifp, &odzone) || iszone != oszone || idzone != odzone) { @@ -1575,7 +1598,7 @@ #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_XMIT) log(LOG_DEBUG, "phyint_send on mif %d err %d\n", - mifp - mif6table, error); + mifp - V_mif6table, error); #endif splx(s); return; @@ -1611,7 +1634,7 @@ #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_XMIT) log(LOG_DEBUG, "phyint_send on mif %d err %d\n", - mifp - mif6table, error); + mifp - V_mif6table, error); #endif } else { /* @@ -1659,7 +1682,7 @@ ip6_sprintf(ip6bufd, &ip6->ip6_dst)); } #endif - ++pim6stat.pim6s_snd_registers; + ++V_pim6stat.pim6s_snd_registers; /* Make a copy of the packet to send to the user level process */ MGETHDR(mm, M_DONTWAIT, MT_HEADER); @@ -1691,18 +1714,18 @@ im6->im6_msgtype = MRT6MSG_WHOLEPKT; im6->im6_mbz = 0; - im6->im6_mif = mif - mif6table; + im6->im6_mif = mif - V_mif6table; /* iif info is not given for reg. encap.n */ - mrt6stat.mrt6s_upcalls++; + V_mrt6stat.mrt6s_upcalls++; - if (socket_send(ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { #ifdef MRT6DEBUG if (V_mrt6debug) log(LOG_WARNING, "register_send: ip6_mrouter socket queue full\n"); #endif - ++mrt6stat.mrt6s_upq_sockfull; + ++V_mrt6stat.mrt6s_upq_sockfull; return (ENOBUFS); } return (0); @@ -1726,7 +1749,7 @@ int minlen; int off = *offp; - ++pim6stat.pim6s_rcv_total; + ++V_pim6stat.pim6s_rcv_total; ip6 = mtod(m, struct ip6_hdr *); pimlen = m->m_pkthdr.len - *offp; @@ -1735,7 +1758,7 @@ * Validate lengths */ if (pimlen < PIM_MINLEN) { - ++pim6stat.pim6s_rcv_tooshort; + ++V_pim6stat.pim6s_rcv_tooshort; #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_PIM) log(LOG_DEBUG,"pim6_input: PIM packet too short\n"); @@ -1768,7 +1791,7 @@ #else IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen); if (pim == NULL) { - pim6stat.pim6s_rcv_tooshort++; + V_pim6stat.pim6s_rcv_tooshort++; return (IPPROTO_DONE); } #endif @@ -1788,7 +1811,7 @@ cksumlen = pimlen; if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) { - ++pim6stat.pim6s_rcv_badsum; + ++V_pim6stat.pim6s_rcv_badsum; #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_PIM) log(LOG_DEBUG, @@ -1802,7 +1825,7 @@ /* PIM version check */ if (pim->pim_ver != PIM_VERSION) { - ++pim6stat.pim6s_rcv_badversion; + ++V_pim6stat.pim6s_rcv_badversion; #ifdef MRT6DEBUG log(LOG_ERR, "pim6_input: incorrect version %d, expecting %d\n", @@ -1828,14 +1851,14 @@ char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; #endif - ++pim6stat.pim6s_rcv_registers; + ++V_pim6stat.pim6s_rcv_registers; - if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) { + if ((V_reg_mif_num >= V_nummifs) || (V_reg_mif_num == (mifi_t) -1)) { #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_PIM) log(LOG_DEBUG, "pim6_input: register mif not set: %d\n", - reg_mif_num); + V_reg_mif_num); #endif m_freem(m); return (IPPROTO_DONE); @@ -1850,8 +1873,8 @@ * Validate length */ if (pimlen < PIM6_REG_MINLEN) { - ++pim6stat.pim6s_rcv_tooshort; - ++pim6stat.pim6s_rcv_badregisters; + ++V_pim6stat.pim6s_rcv_tooshort; + ++V_pim6stat.pim6s_rcv_badregisters; #ifdef MRT6DEBUG log(LOG_ERR, "pim6_input: register packet size too " @@ -1875,7 +1898,7 @@ /* verify the version number of the inner packet */ if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { - ++pim6stat.pim6s_rcv_badregisters; + ++V_pim6stat.pim6s_rcv_badregisters; #ifdef MRT6DEBUG log(LOG_DEBUG, "pim6_input: invalid IP version (%d) " "of the inner packet\n", @@ -1887,7 +1910,7 @@ /* verify the inner packet is destined to a mcast group */ if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) { - ++pim6stat.pim6s_rcv_badregisters; + ++V_pim6stat.pim6s_rcv_badregisters; #ifdef MRT6DEBUG if (V_mrt6debug & DEBUG_PIM) log(LOG_DEBUG, @@ -1924,11 +1947,11 @@ "src %s, dst %s, mif %d\n", ip6_sprintf(ip6bufs, &eip6->ip6_src), ip6_sprintf(ip6bufd, &eip6->ip6_dst), - reg_mif_num); + V_reg_mif_num); } #endif - rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m, + rc = if_simloop(V_mif6table[V_reg_mif_num].m6_ifp, m, dst.sin6_family, 0); /* prepare the register head to send to the mrouting daemon */ diff -ur sys.20081015/netinet6/ip6_mroute.h sys/netinet6/ip6_mroute.h --- sys.20081015/netinet6/ip6_mroute.h 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/ip6_mroute.h 2008-11-05 13:21:56.000000000 -0800 @@ -266,6 +266,7 @@ extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt); extern int (*ip6_mrouter_done)(void); extern int (*mrt6_ioctl)(int, caddr_t); + #endif /* _KERNEL */ #endif /* !_NETINET6_IP6_MROUTE_H_ */ diff -ur sys.20081015/netinet6/ip6_output.c sys/netinet6/ip6_output.c --- sys.20081015/netinet6/ip6_output.c 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/ip6_output.c 2008-10-28 20:01:22.000000000 -0700 @@ -744,7 +744,7 @@ * above, will be forwarded by the ip6_input() routine, * if necessary. */ - if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { + if (V_ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { /* * XXX: ip6_mforward expects that rcvif is NULL * when it is called from the originating path. diff -ur sys.20081015/netinet6/ip6_var.h sys/netinet6/ip6_var.h --- sys.20081015/netinet6/ip6_var.h 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/ip6_var.h 2008-10-28 20:01:22.000000000 -0700 @@ -292,8 +292,8 @@ extern int ip6_v6only; #endif -extern struct socket *ip6_mrouter; /* multicast routing daemon */ #ifndef VIMAGE +extern struct socket *ip6_mrouter; /* multicast routing daemon */ extern int ip6_sendredirects; /* send IP redirects when forwarding? */ extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */ extern int ip6_maxfrags; /* Maximum fragments in reassembly queue */ diff -ur sys.20081015/netinet6/mld6.c sys/netinet6/mld6.c --- sys.20081015/netinet6/mld6.c 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/mld6.c 2008-10-28 20:01:22.000000000 -0700 @@ -518,7 +518,7 @@ * Request loopback of the report if we are acting as a multicast * router, so that the process-level routing daemon can hear it. */ - im6o.im6o_multicast_loop = (ip6_mrouter != NULL); + im6o.im6o_multicast_loop = (V_ip6_mrouter != NULL); /* increment output statictics */ V_icmp6stat.icp6s_outhist[type]++; diff -ur sys.20081015/netinet6/raw_ip6.c sys/netinet6/raw_ip6.c --- sys.20081015/netinet6/raw_ip6.c 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/raw_ip6.c 2008-10-28 20:01:22.000000000 -0700 @@ -129,7 +129,9 @@ /* * Hooks for multicast forwarding. */ +#ifndef VIMAGE struct socket *ip6_mrouter = NULL; +#endif int (*ip6_mrouter_set)(struct socket *, struct sockopt *); int (*ip6_mrouter_get)(struct socket *, struct sockopt *); int (*ip6_mrouter_done)(void); @@ -599,12 +601,13 @@ rip6_detach(struct socket *so) { INIT_VNET_INET(so->so_vnet); + INIT_VNET_INET6(so->so_vnet); struct inpcb *inp; inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); - if (so == ip6_mrouter && ip6_mrouter_done) + if (so == V_ip6_mrouter && ip6_mrouter_done) ip6_mrouter_done(); /* xxx: RSVP */ INP_INFO_WLOCK(&V_ripcbinfo); diff -ur sys.20081015/netinet6/vinet6.h sys/netinet6/vinet6.h --- sys.20081015/netinet6/vinet6.h 2008-10-15 08:25:28.000000000 -0700 +++ sys/netinet6/vinet6.h 2008-10-29 12:58:52.000000000 -0700 @@ -43,6 +43,8 @@ #include #include #include +#include +#include /* struct pim6stat */ #define INIT_VNET_INET6(vnet) \ INIT_FROM_VNET(vnet, VNET_MOD_INET6, \ @@ -95,6 +97,7 @@ //int _icmp6_nodeinfo; int _ip6_forwarding; + struct socket * _ip6_mrouter; int _ip6_sendredirects; int _ip6_defhlim; int _ip6_defmcasthlim; @@ -149,14 +152,25 @@ u_int32_t _ip6_temp_preferred_lifetime; u_int32_t _ip6_temp_valid_lifetime; - int _ip6_mrouter_ver; - int _pim6; - u_int _mrt6debug; - int _ip6_temp_regen_advance; int _ip6_use_defzone; struct ip6_pktopts _ip6_opts; + + /* from ip6_mroute.c */ + int _ip6_mrouter_ver; /* = 0; */ + struct mrt6stat _mrt6stat; + struct mf6c * _mf6ctable[MF6CTBLSIZ]; + u_char _n6expire[MF6CTBLSIZ]; + struct mif6 _mif6table[MAXMIFS]; + u_int _mrt6debug; + struct ifnet * _multicast_register_if6; + mifi_t _nummifs; /* = 0; */ + mifi_t _reg_mif_num; /* = (mifi_t)-1; */ + struct pim6stat _pim6stat; + int _pim6; + u_long _upcall_data[51]; + struct callout _expire_upcalls_ch6; }; #endif @@ -206,6 +220,7 @@ //#define V_icmp6_nodeinfo VNET_INET6(icmp6_nodeinfo) #define V_ip6_forwarding VNET_INET6(ip6_forwarding) +#define V_ip6_mrouter VNET_INET6(ip6_mrouter) #define V_ip6_sendredirects VNET_INET6(ip6_sendredirects) #define V_ip6_defhlim VNET_INET6(ip6_defhlim) #define V_ip6_defmcasthlim VNET_INET6(ip6_defmcasthlim) @@ -260,13 +275,24 @@ #define V_ip6_temp_preferred_lifetime VNET_INET6(ip6_temp_preferred_lifetime) #define V_ip6_temp_valid_lifetime VNET_INET6(ip6_temp_valid_lifetime) -#define V_ip6_mrouter_ver VNET_INET6(ip6_mrouter_ver) -#define V_pim6 VNET_INET6(pim6) -#define V_mrt6debug VNET_INET6(mrt6debug) #define V_ip6_temp_regen_advance VNET_INET6(ip6_temp_regen_advance) #define V_ip6_use_defzone VNET_INET6(ip6_use_defzone) #define V_ip6_opts VNET_INET6(ip6_opts) +#define V_ip6_mrouter_ver VNET_INET6(ip6_mrouter_ver) +#define V_mrt6stat VNET_INET6(mrt6stat) +#define V_mf6ctable VNET_INET6(mf6ctable) +#define V_n6expire VNET_INET6(n6expire) +#define V_mif6table VNET_INET6(mif6table) +#define V_mrt6debug VNET_INET6(mrt6debug) +#define V_multicast_register_if6 VNET_INET6(multicast_register_if6) +#define V_nummifs VNET_INET6(nummifs) +#define V_reg_mif_num VNET_INET6(reg_mif_num) +#define V_pim6stat VNET_INET6(pim6stat) +#define V_pim6 VNET_INET6(pim6) +#define V_upcall_data VNET_INET6(upcall_data) +#define V_expire_upcalls_ch6 VNET_INET6(expire_upcalls_ch6) + #endif /* !_NETINET6_VINET6_H_ */ diff -ur sys.20081015/netipsec/keysock.c sys/netipsec/keysock.c --- sys.20081015/netipsec/keysock.c 2008-10-15 08:25:29.000000000 -0700 +++ sys/netipsec/keysock.c 2008-10-29 07:57:18.000000000 -0700 @@ -429,8 +429,8 @@ kp->kp_promisc = kp->kp_registered = 0; if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count++; - key_cb.any_count++; + V_key_cb.key_count++; + V_key_cb.any_count++; soisconnected(so); so->so_options |= SO_USELOOPBACK; diff -ur sys.20081015/sys/vimage.h sys/sys/vimage.h --- sys.20081015/sys/vimage.h 2008-10-15 08:25:30.000000000 -0700 +++ sys/sys/vimage.h 2008-11-04 13:56:18.000000000 -0800 @@ -77,6 +77,7 @@ #define VNET_MOD_IPX 9 #define VNET_MOD_ATALK 10 #define VNET_MOD_DIVERT 11 +#define VNET_MOD_MROUTE 12 /* stateless modules */ #define VNET_MOD_NG_WORMHOLE 19 #define VNET_MOD_NG_ETHER 20 @@ -103,6 +104,7 @@ #define V_MOD_vnet_pf VNET_MOD_PF #define V_MOD_vnet_gif VNET_MOD_GIF #define V_MOD_vnet_ipsec VNET_MOD_IPSEC +#define V_MOD_vnet_mroute VNET_MOD_MROUTE #define V_MOD_vprocg 0 #define V_MOD_vcpu 0 core-4.6/kernel/freebsd/ng_pipe/0000775000175000017500000000000012220631372013627 500000000000000core-4.6/kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c0000664000175000017500000010336111173131445017120 00000000000000/* * ng_pipe.c * * Copyright (c) 2004 University of Zagreb, Croatia * Copyright (c) 1996-1999 Whistle Communications, Inc. * All rights reserved. * * Subject to the following obligations and disclaimer of warranty, use and * redistribution of this software, in source or object code forms, with or * without modifications are expressly permitted by Whistle Communications * and author; provided, however, that: * 1. Any and all reproductions of the source or object code must include the * copyright notice above and the following disclaimer of warranties; and * 2. No rights are granted, in any manner or form, to use Whistle * Communications, Inc. trademarks, including the mark "WHISTLE * COMMUNICATIONS" on advertising, endorsements, or otherwise except as * such appears in the above copyright notice or in the software. * * THIS SOFTWARE IS BEING PROVIDED BY BOTH AUTHOR AND WHISTLE COMMUNICATIONS * "AS IS", AND TO THE MAXIMUM EXTENT PERMITTED BY LAW, THEY MAKE NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * AUTHOR AND WHISTLE COMMUNICATIONS DO NOT WARRANT, GUARANTEE, OR MAKE * ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. * IN NO EVENT WILL AUTHOR OR WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 AUTHOR OR WHISTLE COMMUNICATIONS IS ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* v 1.15 2004/10/25 */ /* * This node permits simple traffic shaping by emulating bandwidth * and delay, as well as random packet losses. * The node has two hooks, upper and lower. Traffic flowing from upper to * lower hook is referenced as downstream, and vice versa. Parameters for * both directions can be set separately, except for delay. */ /* * TODO: * * - some splimp()s and extra checks are possibly pure paranoia, * if they prove to be redundant they should be removed. * * - update the manpage. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ng_pipe.h" #ifdef XCP #include "xcp_var.h" #endif #ifdef BOEING_WLAN #include "../ng_wlan/ng_wlan.h" #include "../ng_wlan/ng_wlan_tag.h" #endif /* BOEING_WLAN */ typedef void idle_polling_t (void); extern idle_polling_t *idle_polling_h; extern int cpu_idle_hlt; /* Packet header struct */ struct ngp_hdr { TAILQ_ENTRY(ngp_hdr) ngp_link; /* next pkt in queue */ struct timeval when; /* when to dequeue this packet? */ struct mbuf *m; /* ptr to the actual packet data */ #ifdef BOEING_WLAN meta_p meta; /* optional metadata containing link effects from ng_wlan*/ #endif }; TAILQ_HEAD(p_head ,ngp_hdr); /* FIFO queue struct */ struct ngp_fifo { TAILQ_ENTRY(ngp_fifo) fifo_le; /* list of active queues only */ struct p_head packet_head; /* FIFO queue head */ u_int32_t hash; /* flow signature */ struct timeval vtime; /* virtual time, for WFQ */ u_int32_t rr_deficit; /* for DRR */ u_int32_t packets; /* # of packets in this queue */ }; /* Per hook info */ struct hookinfo { hook_p hook; LIST_ENTRY(hookinfo) hook_le; /* all active ng_pipe instances */ TAILQ_HEAD(, ngp_fifo) fifo_head; /* this hooks's FIFO queues */ TAILQ_HEAD(, ngp_hdr) qout_head; /* delay queue head */ struct timeval qin_utime; struct ng_pipe_hookcfg cfg; struct ng_pipe_hookrun run; struct ng_pipe_hookstat stats; #ifdef XCP struct xcp_router_state xcps; #endif uint64_t *ber_p; }; /* Per node info */ struct privdata { node_p node; LIST_ENTRY(privdata) node_le; u_int64_t delay; u_int32_t overhead; u_int32_t header_offset; struct hookinfo lower; struct hookinfo upper; }; typedef struct privdata *sc_p; /* Macro for calculating the virtual time for packet dequeueing in WFQ */ #define FIFO_VTIME_SORT(plen) \ if (hinfo->cfg.wfq && hinfo->cfg.bandwidth) { \ ngp_f->vtime.tv_usec = now->tv_usec + ((uint64_t) (plen) \ + sc->overhead ) * hinfo->run.fifo_queues * \ 8000000 / hinfo->cfg.bandwidth; \ ngp_f->vtime.tv_sec = now->tv_sec + \ ngp_f->vtime.tv_usec / 1000000; \ ngp_f->vtime.tv_usec = ngp_f->vtime.tv_usec % 1000000; \ TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) \ if (ngp_f1->vtime.tv_sec > ngp_f->vtime.tv_sec || \ (ngp_f1->vtime.tv_sec == ngp_f->vtime.tv_sec && \ ngp_f1->vtime.tv_usec > ngp_f->vtime.tv_usec)) \ break; \ if (ngp_f1 == NULL) \ TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ else \ TAILQ_INSERT_BEFORE(ngp_f1, ngp_f, fifo_le); \ } else \ TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ static void parse_cfg(struct ng_pipe_hookcfg *, struct ng_pipe_hookcfg *, struct hookinfo *); static void pipe_dequeue(struct hookinfo *, struct timeval *); static void pipe_scheduler(void); static void pipe_poll(void); static int ngp_modevent(module_t, int, void *); /* linked list of all "pipe" nodes */ LIST_HEAD(pipe_node_head, privdata) node_head; /* linked list of active "pipe" hooks */ LIST_HEAD(pipe_hook_head, hookinfo) hook_head; /* timeout handle for pipe_scheduler */ struct callout_handle ds_handle = { 0 }; /* saved value of cpu_idle_hlt */ static int old_cpu_idle_hlt = 0; /* VM zone for storing ngp_hdr-s */ struct vm_zone *ngp_zone; /* Netgraph methods */ static ng_constructor_t ngp_constructor; static ng_rcvmsg_t ngp_rcvmsg; static ng_shutdown_t ngp_rmnode; static ng_newhook_t ngp_newhook; static ng_rcvdata_t ngp_rcvdata; static ng_disconnect_t ngp_disconnect; /* Parse type for struct ng_pipe_hookstat */ static const struct ng_parse_struct_field ng_pipe_hookstat_type_fields[] = NG_PIPE_HOOKSTAT_INFO; static const struct ng_parse_type ng_pipe_hookstat_type = { &ng_parse_struct_type, &ng_pipe_hookstat_type_fields }; /* Parse type for struct ng_pipe_stats */ static const struct ng_parse_struct_field ng_pipe_stats_type_fields[] = NG_PIPE_STATS_INFO(&ng_pipe_hookstat_type); static const struct ng_parse_type ng_pipe_stats_type = { &ng_parse_struct_type, &ng_pipe_stats_type_fields }; /* Parse type for struct ng_pipe_hookrun */ static const struct ng_parse_struct_field ng_pipe_hookrun_type_fields[] = NG_PIPE_HOOKRUN_INFO; static const struct ng_parse_type ng_pipe_hookrun_type = { &ng_parse_struct_type, &ng_pipe_hookrun_type_fields }; /* Parse type for struct ng_pipe_run */ static const struct ng_parse_struct_field ng_pipe_run_type_fields[] = NG_PIPE_RUN_INFO(&ng_pipe_hookrun_type); static const struct ng_parse_type ng_pipe_run_type = { &ng_parse_struct_type, &ng_pipe_run_type_fields }; /* Parse type for struct ng_pipe_hookcfg */ static const struct ng_parse_struct_field ng_pipe_hookcfg_type_fields[] = NG_PIPE_HOOKCFG_INFO; static const struct ng_parse_type ng_pipe_hookcfg_type = { &ng_parse_struct_type, &ng_pipe_hookcfg_type_fields }; /* Parse type for struct ng_pipe_cfg */ static const struct ng_parse_struct_field ng_pipe_cfg_type_fields[] = NG_PIPE_CFG_INFO(&ng_pipe_hookcfg_type); static const struct ng_parse_type ng_pipe_cfg_type = { &ng_parse_struct_type, &ng_pipe_cfg_type_fields }; /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_pipe_cmds[] = { { NGM_PIPE_COOKIE, NGM_PIPE_GET_STATS, "getstats", NULL, &ng_pipe_stats_type }, { NGM_PIPE_COOKIE, NGM_PIPE_CLR_STATS, "clrstats", NULL, NULL }, { NGM_PIPE_COOKIE, NGM_PIPE_GETCLR_STATS, "getclrstats", NULL, &ng_pipe_stats_type }, { NGM_PIPE_COOKIE, NGM_PIPE_GET_RUN, "getrun", NULL, &ng_pipe_run_type }, { NGM_PIPE_COOKIE, NGM_PIPE_GET_CFG, "getcfg", NULL, &ng_pipe_cfg_type }, { NGM_PIPE_COOKIE, NGM_PIPE_SET_CFG, "setcfg", &ng_pipe_cfg_type, NULL }, { 0 } }; /* Netgraph type descriptor */ static struct ng_type ng_pipe_typestruct = { NG_VERSION, NG_PIPE_NODE_TYPE, ngp_modevent, ngp_constructor, ngp_rcvmsg, ngp_rmnode, ngp_newhook, NULL, NULL, ngp_rcvdata, ngp_rcvdata, ngp_disconnect, ng_pipe_cmds }; NETGRAPH_INIT(pipe, &ng_pipe_typestruct); #ifdef BOEING_WLAN /* generate a random integer between 1 and max */ #define pipe_good_random(max) (1 + (random() % max)) #endif /* * Node constructor */ static int ngp_constructor(node_p *nodep) { sc_p privdata; node_p node; int error = 0; int s; MALLOC(privdata, sc_p, sizeof(*privdata), M_NETGRAPH, M_NOWAIT); if (privdata == NULL) return (ENOMEM); bzero(privdata, sizeof(*privdata)); if ((error = ng_make_node_common(&ng_pipe_typestruct, nodep))) { FREE(privdata, M_NETGRAPH); return (error); } node=*nodep; node->private = privdata; privdata->node = node; /* Add new node to the "all nodes" list */ s=splimp(); LIST_INSERT_HEAD(&node_head, privdata, node_le); splx(s); return (0); } /* * Add a hook */ static int ngp_newhook(node_p node, hook_p hook, const char *name) { const sc_p sc = node->private; struct hookinfo *hinfo; if (strcmp(name, NG_PIPE_HOOK_UPPER) == 0) { bzero(&sc->upper, sizeof(sc->upper)); sc->upper.hook = hook; hook->private = &sc->upper; } else if (strcmp(name, NG_PIPE_HOOK_LOWER) == 0) { bzero(&sc->lower, sizeof(sc->lower)); sc->lower.hook = hook; hook->private = &sc->lower; } else return (EINVAL); /* Load non-zero initial cfg values */ hinfo = (struct hookinfo *) hook->private; hinfo->cfg.qin_size_limit = 50; hinfo->cfg.fifo = 1; hinfo->cfg.droptail = 1; TAILQ_INIT(&hinfo->fifo_head); TAILQ_INIT(&hinfo->qout_head); return (0); } /* * Receive a control message */ static int ngp_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg **rptr) { const sc_p sc = node->private; struct ng_mesg *resp = NULL; int error = 0; switch (msg->header.typecookie) { case NGM_PIPE_COOKIE: switch (msg->header.cmd) { case NGM_PIPE_GET_STATS: case NGM_PIPE_CLR_STATS: case NGM_PIPE_GETCLR_STATS: { struct ng_pipe_stats *stats; if (msg->header.cmd != NGM_PIPE_CLR_STATS) { NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); if (resp == NULL) { error = ENOMEM; goto done; } stats=(struct ng_pipe_stats *)resp->data; bcopy(&sc->upper.stats, &stats->downstream, sizeof(stats->downstream)); bcopy(&sc->lower.stats, &stats->upstream, sizeof(stats->upstream)); } if (msg->header.cmd != NGM_PIPE_GET_STATS) { bzero(&sc->upper.stats, sizeof(sc->upper.stats)); bzero(&sc->lower.stats, sizeof(sc->lower.stats)); } break; } case NGM_PIPE_GET_RUN: { struct ng_pipe_run *run; NG_MKRESPONSE(resp, msg, sizeof(*run), M_NOWAIT); if (resp == NULL) { error = ENOMEM; goto done; } run = (struct ng_pipe_run *)resp->data; bcopy(&sc->upper.run, &run->downstream, sizeof(run->downstream)); bcopy(&sc->lower.run, &run->upstream, sizeof(run->upstream)); break; } case NGM_PIPE_GET_CFG: { struct ng_pipe_cfg *cfg; NG_MKRESPONSE(resp, msg, sizeof(*cfg), M_NOWAIT); if (resp == NULL) { error = ENOMEM; goto done; } cfg = (struct ng_pipe_cfg *)resp->data; bcopy(&sc->upper.cfg, &cfg->downstream, sizeof(cfg->downstream)); bcopy(&sc->lower.cfg, &cfg->upstream, sizeof(cfg->upstream)); cfg->delay = sc->delay; cfg->overhead = sc->overhead; cfg->header_offset = sc->header_offset; if (cfg->upstream.bandwidth == cfg->downstream.bandwidth) { cfg->bandwidth = cfg->upstream.bandwidth; cfg->upstream.bandwidth = 0; cfg->downstream.bandwidth = 0; } else cfg->bandwidth = 0; break; } case NGM_PIPE_SET_CFG: { struct ng_pipe_cfg *cfg; cfg = (struct ng_pipe_cfg *)msg->data; if (msg->header.arglen != sizeof(*cfg)) { error = EINVAL; break; } if (cfg->delay == -1) sc->delay = 0; else if (cfg->delay > 0 && cfg->delay < 10000000) sc->delay = cfg->delay; if (cfg->bandwidth == -1) { sc->upper.cfg.bandwidth = 0; sc->lower.cfg.bandwidth = 0; sc->overhead = 0; } else if (cfg->bandwidth >= 100 && cfg->bandwidth <= 1000000000) { sc->upper.cfg.bandwidth = cfg->bandwidth; sc->lower.cfg.bandwidth = cfg->bandwidth; if (cfg->bandwidth >= 10000000) sc->overhead = 8+4+12; /* Ethernet */ else sc->overhead = 10; /* HDLC */ } if (cfg->overhead == -1) sc->overhead = 0; else if (cfg->overhead > 0 && cfg->overhead < 256) sc->overhead = cfg->overhead; if (cfg->header_offset == -1) sc->header_offset = 0; else if (cfg->header_offset > 0 && cfg->header_offset < 64) sc->header_offset = cfg->header_offset; parse_cfg(&sc->upper.cfg, &cfg->downstream, &sc->upper); parse_cfg(&sc->lower.cfg, &cfg->upstream, &sc->lower); break; } default: error = EINVAL; break; } break; default: error = EINVAL; break; } if (rptr) *rptr = resp; else if (resp) FREE(resp, M_NETGRAPH); done: FREE(msg, M_NETGRAPH); return (error); } static void parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, struct hookinfo *hinfo) { if (new->ber == -1) { current->ber = 0; if (hinfo->ber_p) { FREE(hinfo->ber_p, M_NETGRAPH); hinfo->ber_p = NULL; } } else if (new->ber >= 1 && new->ber <= 1000000000000) { static const uint64_t one = 0x1000000000000; /* = 2^48 */ uint64_t p0, p; uint32_t fsize, i; if (hinfo->ber_p == NULL) MALLOC(hinfo->ber_p, uint64_t *, \ (MAX_FSIZE + MAX_OHSIZE)*sizeof(uint64_t), \ M_NETGRAPH, M_NOWAIT); current->ber = new->ber; /* * For given BER and each frame size N (in bytes) calculate * the probability P_OK that the frame is clean: * * P_OK(BER,N) = (1 - 1/BER)^(N*8) * * We use a 64-bit fixed-point format with decimal point * positioned between bits 47 and 48. */ p0 = one - one / new->ber; p = one; for (fsize = 0; fsize < MAX_FSIZE + MAX_OHSIZE; fsize++) { hinfo->ber_p[fsize] = p; for (i=0; i<8; i++) p = (p*(p0&0xffff)>>48) + \ (p*((p0>>16)&0xffff)>>32) + \ (p*(p0>>32)>>16); } } if (new->qin_size_limit == 0xffff) current->qin_size_limit = 0; else if (new->qin_size_limit >= 5) current->qin_size_limit = new->qin_size_limit; if (new->qout_size_limit == 0xffff) current->qout_size_limit = 0; else if (new->qout_size_limit >= 5) current->qout_size_limit = new->qout_size_limit; if (new->duplicate == -1) current->duplicate = 0; else if (new->duplicate > 0 && new->duplicate <= 50) current->duplicate = new->duplicate; if (new->fifo) { current->fifo = 1; current->wfq = 0; current->drr = 0; } if (new->wfq) { current->fifo = 0; current->wfq = 1; current->drr = 0; } if (new->drr) { current->fifo = 0; current->wfq = 0; /* DRR quantum */ if (new->drr >= 32) current->drr = new->drr; else current->drr = 2048; /* default quantum */ } if (new->droptail) { current->droptail = 1; current->drophead = 0; } if (new->drophead) { current->droptail = 0; current->drophead = 1; } if (new->bandwidth == -1) { current->bandwidth = 0; current->fifo = 1; current->wfq = 0; current->drr = 0; } else if (new->bandwidth >= 100 && new->bandwidth <= 1000000000) current->bandwidth = new->bandwidth; #ifdef XCP init_xcp_state(&hinfo->xcps, 0, current->bandwidth / 1024); #endif } /* * Compute a hash signature for a packet. This function suffers from the * NIH sindrome, so probably it would be wise to look around what other * folks have found out to be a good and efficient IP hash function... */ __inline static int ip_hash(struct mbuf *m, int offset) { u_int64_t i; struct ip *ip = (struct ip *)(mtod(m, u_char *) + offset); struct udphdr *udp = 0; if (m->m_len < sizeof(struct ip) + offset || ip->ip_v != 4 || ip->ip_hl << 2 != sizeof(struct ip)) return 0; if ((m->m_len >= sizeof(struct ip) + sizeof(struct udphdr) + offset) && (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) && !(ntohs(ip->ip_off) & IP_OFFMASK)) udp = (struct udphdr *)((u_char *) ip + sizeof(struct ip)); #if 0 /* an overkill IP hash, but could be too slow */ i = 0; for ( j = (ip->ip_p & 0x1f) + 1; j ; j = j >> 2) { i ^= ((u_int64_t) ip->ip_src.s_addr + ((u_int64_t) ip->ip_dst.s_addr << 7) - ((u_int64_t) ip->ip_src.s_addr << 13) - ((u_int64_t) ip->ip_dst.s_addr << 19) + ((u_int64_t) ip->ip_p << 9)) << j; if (udp) i ^= (((u_int64_t) udp->uh_sport << (ip->ip_p + 5)) - ((u_int64_t) udp->uh_dport << ip->ip_p)) << j; } #else /* a slightly faster yet less reliable version */ i = ((u_int64_t) ip->ip_src.s_addr ^ ((u_int64_t) ip->ip_dst.s_addr << 7) ^ ((u_int64_t) ip->ip_src.s_addr << 13) ^ ((u_int64_t) ip->ip_dst.s_addr << 19) ^ ((u_int64_t) ip->ip_p << 9)); if (udp) i ^= (((u_int64_t) udp->uh_sport << (ip->ip_p + 5)) ^ ((u_int64_t) udp->uh_dport << ip->ip_p)); #endif return (i ^ (i >> 32)); } /* * Receive data on a hook - both in upstream and downstream direction. * We put the frame on the inbound queue, and try to initiate dequeuing * sequence immediately. If inbound queue is full, discard one frame * depending on dropping policy (from the head or from the tail of the * queue). */ static int ngp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) { struct hookinfo *const hinfo = (struct hookinfo *) hook->private; const sc_p sc = hook->node->private; struct timeval uuptime; struct timeval *now = &uuptime; struct ngp_fifo *ngp_f = NULL, *ngp_f1; struct ngp_hdr *ngp_h = NULL; int hash; int s; microuptime(now); s = splimp(); #ifdef BOEING_WLAN if (meta != NULL) { if ((meta->used_len != WLAN_META_SIZE) || (meta->options[0].cookie != NGM_WLAN_COOKIE)) { /* metadata from elsewhere, not queued */ NG_FREE_META(meta); /* sets meta = NULL */ }/* else metadata from ng_wlan, contains tag */ } #else NG_FREE_META(meta); #endif /* * Attach us to the list of active ng_pipes if this one was an empty * one before, and also update the queue service deadline time. */ if (hinfo->run.qin_frames == 0) { struct timeval *when = &hinfo->qin_utime; if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec < now->tv_usec)) { when->tv_sec = now->tv_sec; when->tv_usec = now->tv_usec; } if (hinfo->run.qout_frames == 0) { LIST_INSERT_HEAD(&hook_head, hinfo, hook_le); if (cpu_idle_hlt) { old_cpu_idle_hlt = cpu_idle_hlt; cpu_idle_hlt = 0; } } } /* Populate the packet header */ ngp_h = zalloc(ngp_zone); ngp_h->m = m; #ifdef BOEING_WLAN ngp_h->meta = meta; meta = NULL; /* don't free elsewhere */ #endif if (hinfo->cfg.fifo) hash = 0; /* all packets go into a single FIFO queue */ else hash = ip_hash(m, sc->header_offset); #ifdef XCP if (do_xcp) xcp_forward(m, sc->header_offset, &hinfo->xcps); #endif /* Find the appropriate FIFO queue for the packet and enqueue it*/ TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le) if (hash == ngp_f->hash) break; if (ngp_f == NULL) { ngp_f = zalloc(ngp_zone); TAILQ_INIT(&ngp_f->packet_head); ngp_f->hash = hash; ngp_f->packets = 1; ngp_f->rr_deficit = hinfo->cfg.drr; /* DRR quantum */ hinfo->run.fifo_queues++; TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); FIFO_VTIME_SORT(m->m_pkthdr.len); } else { TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); ngp_f->packets++; } hinfo->run.qin_frames++; hinfo->run.qin_octets += m->m_pkthdr.len; /* Discard a frame if inbound queue limit has been reached */ if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { struct mbuf *m1; int longest = 0; /* Find the longest queue */ TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) if (ngp_f1->packets > longest) { longest = ngp_f1->packets; ngp_f = ngp_f1; } /* Drop a frame from the queue head/tail, depending on cfg */ if (hinfo->cfg.drophead) ngp_h = TAILQ_FIRST(&ngp_f->packet_head); else ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m1 = ngp_h->m; #ifdef BOEING_WLAN NG_FREE_META(ngp_h->meta); #endif /* BOEING_WLAN */ zfree(ngp_zone, ngp_h); hinfo->run.qin_octets -= m1->m_pkthdr.len; hinfo->stats.in_disc_octets += m1->m_pkthdr.len; m_freem(m1); if (--(ngp_f->packets) == 0) { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); zfree(ngp_zone, ngp_f); hinfo->run.fifo_queues--; } hinfo->run.qin_frames--; hinfo->stats.in_disc_frames++; } /* Try to start the dequeuing process immediately */ pipe_dequeue(hinfo, now); splx(s); return (0); } /* * Dequeueing sequence - we basically do the following: * 1) Try to extract the frame from the inbound (bandwidth) queue; * 2) In accordance to BER specified, discard the frame randomly; * 3) If the frame survives BER, prepend it with delay info and move it * to outbound (delay) queue, or send directly to the outbound hook; * 4) Loop to 2) until bandwidth limit is reached, or inbound queue is * flushed completely; * 5) Extract the first frame from the outbound queue, if it's time has come. * Send this frame to the outbound hook; * 6) Loop to 6) until outbound queue is flushed completely, or the next * frame in the queue is not scheduled to be dequeued yet * * This routine must be called at splimp()! */ static void pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { static uint64_t rand, oldrand; const sc_p sc = hinfo->hook->node->private; struct hookinfo *dest; struct ngp_fifo *ngp_f, *ngp_f1; struct ngp_hdr *ngp_h; struct timeval *when; meta_p meta = NULL; int error = 0; struct mbuf *m; #ifdef BOEING_WLAN struct ngp_hdr *ngp_h1 = NULL; struct ng_wlan_tag *tag, wtag; int need_free_meta; #endif /* BOEING_WLAN */ /* Which one is the destination hook? */ if (hinfo == &sc->lower) dest = &sc->upper; else dest = &sc->lower; /* Bandwidth queue processing */ while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { when = &hinfo->qin_utime; if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec > now->tv_usec)) break; ngp_h = TAILQ_FIRST(&ngp_f->packet_head); m = ngp_h->m; #ifdef BOEING_WLAN meta = ngp_h->meta; ngp_h->meta = NULL; /* keep ptr in meta*/ need_free_meta = 0; if (meta != NULL) { need_free_meta = 1; tag = (struct ng_wlan_tag*)meta->options; WLAN_TAG_COPY( (&wtag), tag) /* enforce maximum parameters */ if (wtag.delay > NG_WLAN_MAX_DELAY) wtag.delay = NG_WLAN_MAX_DELAY; if (wtag.duplicate > NG_WLAN_MAX_DUP) wtag.duplicate = NG_WLAN_MAX_DUP; if (wtag.jitter > NG_WLAN_MAX_JITTER) wtag.jitter = NG_WLAN_MAX_JITTER; } else { WLAN_TAG_ZERO( (&wtag) ); } #endif /* BOEING_WLAN */ /* Deficit Round Robin (DRR) processing */ if (hinfo->cfg.drr) { if (ngp_f->rr_deficit >= m->m_pkthdr.len) { ngp_f->rr_deficit -= m->m_pkthdr.len; } else { ngp_f->rr_deficit += hinfo->cfg.drr; TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); TAILQ_INSERT_TAIL(&hinfo->fifo_head, \ ngp_f, fifo_le); /* BOEING_WLAN: need to free meta here? */ continue; } } /* * Either create a duplicate and pass it on, or dequeue * the original packet... */ #ifdef BOEING_WLAN if (wtag.duplicate && pipe_good_random(100) <= wtag.duplicate) { ngp_h = zalloc(ngp_zone); KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); ngp_h->m = m_dup(m, M_NOWAIT); ngp_h->meta = meta; /* reuse the old metadata instead of * allocating another */ need_free_meta = 0; meta = NULL; KASSERT(ngp_h->m != NULL, ("m_dup failed")); m = ngp_h->m; /* Boeing: we are now working with copied mbuf, leaving original in the queue */ } else #endif /* BOEING_WLAN */ if (hinfo->cfg.duplicate && random() % 100 <= hinfo->cfg.duplicate) { if ((m = m_dup(m, M_NOWAIT))) if ((ngp_h = zalloc(ngp_zone))) ngp_h->m = m; if ( m == NULL || ngp_h == NULL ) panic("ng_pipe: m_dup or zalloc failed!"); } else { TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); hinfo->run.qin_frames--; hinfo->run.qin_octets -= m->m_pkthdr.len; ngp_f->packets--; } #ifdef BOEING_WLAN /* free the metadata if it was not re-used for the duplicate */ if (need_free_meta) NG_FREE_META(meta); #endif /* BOEING_WLAN */ /* Calculate the serialization delay */ #ifdef BOEING_WLAN if (wtag.bandwidth) { hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len + sc->overhead ) * 8000000 / wtag.bandwidth; hinfo->qin_utime.tv_sec += hinfo->qin_utime.tv_usec / 1000000; hinfo->qin_utime.tv_usec = hinfo->qin_utime.tv_usec % 1000000; } else #endif /* BOEING_WLAN */ if (hinfo->cfg.bandwidth) { hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len + sc->overhead ) * 8000000 / hinfo->cfg.bandwidth; hinfo->qin_utime.tv_sec += hinfo->qin_utime.tv_usec / 1000000; hinfo->qin_utime.tv_usec = hinfo->qin_utime.tv_usec % 1000000; } when = &ngp_h->when; when->tv_sec = hinfo->qin_utime.tv_sec; when->tv_usec = hinfo->qin_utime.tv_usec; /* Sort / rearrange inbound queues */ if (ngp_f->packets) { if (hinfo->cfg.wfq) { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); FIFO_VTIME_SORT(TAILQ_FIRST(&ngp_f->packet_head)->m->m_pkthdr.len) } } else { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); zfree(ngp_zone, ngp_f); hinfo->run.fifo_queues--; } /* Randomly discard the frame, according to BER setting */ #ifdef BOEING_WLAN /* use specified Packet Error Rate setting for random discard */ if (wtag.per && pipe_good_random(100) <= wtag.per) { hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; zfree(ngp_zone, ngp_h); m_freem(m); continue; } else #endif /* BOEING_WLAN */ if (hinfo->cfg.ber && ( (oldrand = rand) ^ (rand = random())<<17) >= hinfo->ber_p[sc->overhead + m->m_pkthdr.len] ) { hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; zfree(ngp_zone, ngp_h); m_freem(m); continue; } /* Discard frame if outbound queue size limit exceeded */ if (hinfo->cfg.qout_size_limit && hinfo->run.qout_frames>=hinfo->cfg.qout_size_limit) { hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; zfree(ngp_zone, ngp_h); m_freem(m); continue; } #ifdef BOEING_WLAN /* Calculate the propagation delay including jitter */ if (wtag.jitter) { when->tv_usec += pipe_good_random(wtag.jitter); /* overflow handled below... */ } when->tv_usec += wtag.delay ? wtag.delay : sc->delay; #else /* Calculate the propagation delay */ when->tv_usec += sc->delay; #endif /* BOEING_WLAN */ when->tv_sec += when->tv_usec / 1000000; when->tv_usec = when->tv_usec % 1000000; /* Put the frame into the delay queue */ #ifdef BOEING_WLAN /* Because WLAN packets may have varying dequeue times, we need to * perform sorted queueing; the dequeuing process expects packets in * the queue that are sorted by time. */ TAILQ_FOREACH(ngp_h1, &hinfo->qout_head, ngp_link) { if (ngp_h1->when.tv_sec > ngp_h->when.tv_sec || (ngp_h1->when.tv_sec == ngp_h->when.tv_sec && ngp_h1->when.tv_usec > ngp_h->when.tv_usec)) break; } if (ngp_h1 == NULL) TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); else TAILQ_INSERT_BEFORE(ngp_h1, ngp_h, ngp_link); /* The original code below just inserts the packet at the * tail of the queue because the delay time is constant. */ #else /* BOEING_WLAN */ TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); #endif /* BOEING_WLAN */ hinfo->run.qout_frames++; hinfo->run.qout_octets += m->m_pkthdr.len; } /* Delay queue processing */ while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { struct mbuf *m = ngp_h->m; /* BOEING_WLAN: this is why we have sorted the queue input */ when = &ngp_h->when; if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec > now->tv_usec)) break; /* Update outbound queue stats */ hinfo->stats.fwd_frames++; hinfo->stats.fwd_octets += m->m_pkthdr.len; hinfo->run.qout_frames--; hinfo->run.qout_octets -= m->m_pkthdr.len; /* Dequeue/send the packet */ TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); zfree(ngp_zone, ngp_h); #ifdef BOEING_WLAN NG_SEND_DATA_ONLY(error, dest->hook, m); #else NG_SEND_DATA(error, dest->hook, m, meta); #endif /* BOEING_WLAN */ } /* If both queues are empty detach us from the list of active queues */ if (hinfo->run.qin_frames + hinfo->run.qout_frames == 0) LIST_REMOVE(hinfo, hook_le); } /* * This routine is called on every clock tick. We poll all nodes/hooks * for queued frames by calling pipe_dequeue(). */ static void pipe_scheduler(void) { static struct timeval old; struct timeval new; microuptime(&new); if (old.tv_sec > new.tv_sec) printf ("ng_pipe: dsec=%ld\n", old.tv_sec - new.tv_sec); else if (old.tv_sec == new.tv_sec && old.tv_usec > new.tv_usec) printf ("ng_pipe: dusec=%ld\n", old.tv_usec - new.tv_usec); old.tv_sec = new.tv_sec; old.tv_usec = new.tv_usec; pipe_poll(); #ifdef XCP if ( do_xcp ) { sc_p priv; /* Set off any XCP timers hooked to ng_pipe queues */ LIST_FOREACH(priv, &node_head, node_le) { if ( --priv->upper.xcps.ticks_until_Te == 0 ) xcp_Te_timeout(&priv->upper.xcps); if ( --priv->upper.xcps.ticks_until_Tq == 0 ) xcp_Tq_timeout(&priv->upper.xcps); if ( --priv->lower.xcps.ticks_until_Te == 0 ) xcp_Te_timeout(&priv->lower.xcps); if ( --priv->lower.xcps.ticks_until_Tq == 0 ) xcp_Tq_timeout(&priv->lower.xcps); } } #endif /* Reschedule */ ds_handle = timeout((timeout_t *) &pipe_scheduler, NULL, 1); } static void pipe_poll(void) { struct hookinfo *hinfo; int s; struct timeval now; s=splimp(); microuptime(&now); LIST_FOREACH(hinfo, &hook_head, hook_le) pipe_dequeue(hinfo, &now); if (LIST_EMPTY(&hook_head) && cpu_idle_hlt == 0) cpu_idle_hlt = old_cpu_idle_hlt; splx(s); } /* * Shutdown processing * * This is tricky. If we have both a lower and upper hook, then we * probably want to extricate ourselves and leave the two peers * still linked to each other. Otherwise we should just shut down as * a normal node would. We run at splimp() in order to avoid race * condition with pipe_scheduler(). */ static int ngp_rmnode(node_p node) { const sc_p privdata = node->private; int s; s=splimp(); node->flags |= NG_INVALID; if (privdata->lower.hook && privdata->upper.hook) ng_bypass(privdata->lower.hook, privdata->upper.hook); ng_cutlinks(node); ng_unname(node); /* unlink the node from the list */ LIST_REMOVE(privdata, node_le); node->private = NULL; ng_unref(privdata->node); FREE(privdata, M_NETGRAPH); splx(s); return (0); } /* * Hook disconnection */ static int ngp_disconnect(hook_p hook) { struct hookinfo *const hinfo = (struct hookinfo *) hook->private; struct ngp_fifo *ngp_f; struct ngp_hdr *ngp_h; int s, removed = 0; s=splimp(); KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__)); hinfo->hook = NULL; /* Flush all fifo queues associated with the hook */ while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { while ((ngp_h = TAILQ_FIRST(&ngp_f->packet_head))) { TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m_freem(ngp_h->m); #ifdef BOEING_WLAN NG_FREE_META(ngp_h->meta); #endif /* BOEING_WLAN */ zfree(ngp_zone, ngp_h); removed++; } TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); zfree(ngp_zone, ngp_f); } /* Flush the delay queue */ while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); m_freem(ngp_h->m); #ifdef BOEING_WLAN NG_FREE_META(ngp_h->meta); #endif /* BOEING_WLAN */ zfree(ngp_zone, ngp_h); removed++; } /* * Both queues should be empty by now, so detach us from * the list of active queues */ if (removed) LIST_REMOVE(hinfo, hook_le); if (hinfo->run.qin_frames + hinfo->run.qout_frames != removed) printf("Mismatch: queued=%d but removed=%d !?!", hinfo->run.qin_frames + hinfo->run.qout_frames, removed); /* Release the packet loss probability table (BER) */ if (hinfo->ber_p) FREE(hinfo->ber_p, M_NETGRAPH); if (hook->node->numhooks == 0) ng_rmnode(hook->node); splx(s); return (0); } static int ngp_modevent(module_t mod, int type, void *unused) { sc_p priv; int error = 0; int s; switch (type) { case MOD_LOAD: if (ngp_zone) error = EEXIST; else { ngp_zone = zinit("ng_pipe", max(sizeof(struct ngp_hdr), sizeof (struct ngp_fifo)), nmbufs, ZONE_INTERRUPT, 0); if (ngp_zone == NULL) { error = ENOMEM; break; } LIST_INIT(&node_head); LIST_INIT(&hook_head); ds_handle = timeout((timeout_t *) &pipe_scheduler, NULL, 1); idle_polling_h = pipe_poll; } break; case MOD_UNLOAD: LIST_FOREACH(priv, &node_head, node_le) error = EBUSY; if (error == 0) { s = splimp(); idle_polling_h = NULL; untimeout((timeout_t *) &pipe_scheduler, NULL, ds_handle); ds_handle.callout = NULL; zdestroy(ngp_zone); splx (s); } break; default: break; } return (error); } core-4.6/kernel/freebsd/ng_pipe/ng_pipe.c0000664000175000017500000010047211432316115015337 00000000000000/* * Copyright (c) 2004-2008 University of Zagreb * Copyright (c) 2007-2008 FreeBSD Foundation * * This software was developed by the University of Zagreb and the * FreeBSD Foundation under sponsorship by the Stichting NLnet and the * FreeBSD Foundation. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * This node permits simple traffic shaping by emulating bandwidth * and delay, as well as random packet losses. * The node has two hooks, upper and lower. Traffic flowing from upper to * lower hook is referenced as downstream, and vice versa. Parameters for * both directions can be set separately, except for delay. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOEING_WLAN #include "ng_pipe.h" #include "../ng_wlan/ng_wlan.h" #include "../ng_wlan/ng_wlan_tag.h" #else #include #endif /* BOEING_WLAN */ static MALLOC_DEFINE(M_NG_PIPE, "ng_pipe", "ng_pipe"); struct mtx ng_pipe_giant; /* Packet header struct */ struct ngp_hdr { TAILQ_ENTRY(ngp_hdr) ngp_link; /* next pkt in queue */ struct timeval when; /* this packet's due time */ struct mbuf *m; /* ptr to the packet data */ }; TAILQ_HEAD(p_head, ngp_hdr); /* FIFO queue struct */ struct ngp_fifo { TAILQ_ENTRY(ngp_fifo) fifo_le; /* list of active queues only */ struct p_head packet_head; /* FIFO queue head */ u_int32_t hash; /* flow signature */ struct timeval vtime; /* virtual time, for WFQ */ u_int32_t rr_deficit; /* for DRR */ u_int32_t packets; /* # of packets in this queue */ }; /* Per hook info */ struct hookinfo { hook_p hook; int noqueue; /* bypass any processing */ TAILQ_HEAD(, ngp_fifo) fifo_head; /* FIFO queues */ TAILQ_HEAD(, ngp_hdr) qout_head; /* delay queue head */ LIST_ENTRY(hookinfo) active_le; /* active hooks */ struct timeval qin_utime; struct ng_pipe_hookcfg cfg; struct ng_pipe_hookrun run; struct ng_pipe_hookstat stats; uint64_t *ber_p; /* loss_p(BER,psize) map */ }; /* Per node info */ struct node_priv { u_int64_t delay; u_int32_t overhead; u_int32_t header_offset; struct hookinfo lower; struct hookinfo upper; }; typedef struct node_priv *priv_p; /* Macro for calculating the virtual time for packet dequeueing in WFQ */ #define FIFO_VTIME_SORT(plen) \ if (hinfo->cfg.wfq && hinfo->cfg.bandwidth) { \ ngp_f->vtime.tv_usec = now->tv_usec + ((uint64_t) (plen) \ + priv->overhead ) * hinfo->run.fifo_queues * \ 8000000 / hinfo->cfg.bandwidth; \ ngp_f->vtime.tv_sec = now->tv_sec + \ ngp_f->vtime.tv_usec / 1000000; \ ngp_f->vtime.tv_usec = ngp_f->vtime.tv_usec % 1000000; \ TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) \ if (ngp_f1->vtime.tv_sec > ngp_f->vtime.tv_sec || \ (ngp_f1->vtime.tv_sec == ngp_f->vtime.tv_sec && \ ngp_f1->vtime.tv_usec > ngp_f->vtime.tv_usec)) \ break; \ if (ngp_f1 == NULL) \ TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ else \ TAILQ_INSERT_BEFORE(ngp_f1, ngp_f, fifo_le); \ } else \ TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ static void parse_cfg(struct ng_pipe_hookcfg *, struct ng_pipe_hookcfg *, struct hookinfo *, priv_p); static void pipe_dequeue(struct hookinfo *, struct timeval *); static void pipe_scheduler(void *); static void pipe_poll(void); static int ngp_modevent(module_t, int, void *); /* linked list of active "pipe" hooks */ static LIST_HEAD(, hookinfo) active_head; static int active_gen_id = 0; /* timeout handle for pipe_scheduler */ static struct callout polling_timer; /* zone for storing ngp_hdr-s */ static uma_zone_t ngp_zone; /* Netgraph methods */ static ng_constructor_t ngp_constructor; static ng_rcvmsg_t ngp_rcvmsg; static ng_shutdown_t ngp_shutdown; static ng_newhook_t ngp_newhook; static ng_rcvdata_t ngp_rcvdata; static ng_disconnect_t ngp_disconnect; /* Parse type for struct ng_pipe_hookstat */ static const struct ng_parse_struct_field ng_pipe_hookstat_type_fields[] = NG_PIPE_HOOKSTAT_INFO; static const struct ng_parse_type ng_pipe_hookstat_type = { &ng_parse_struct_type, &ng_pipe_hookstat_type_fields }; /* Parse type for struct ng_pipe_stats */ static const struct ng_parse_struct_field ng_pipe_stats_type_fields[] = NG_PIPE_STATS_INFO(&ng_pipe_hookstat_type); static const struct ng_parse_type ng_pipe_stats_type = { &ng_parse_struct_type, &ng_pipe_stats_type_fields }; /* Parse type for struct ng_pipe_hookrun */ static const struct ng_parse_struct_field ng_pipe_hookrun_type_fields[] = NG_PIPE_HOOKRUN_INFO; static const struct ng_parse_type ng_pipe_hookrun_type = { &ng_parse_struct_type, &ng_pipe_hookrun_type_fields }; /* Parse type for struct ng_pipe_run */ static const struct ng_parse_struct_field ng_pipe_run_type_fields[] = NG_PIPE_RUN_INFO(&ng_pipe_hookrun_type); static const struct ng_parse_type ng_pipe_run_type = { &ng_parse_struct_type, &ng_pipe_run_type_fields }; /* Parse type for struct ng_pipe_hookcfg */ static const struct ng_parse_struct_field ng_pipe_hookcfg_type_fields[] = NG_PIPE_HOOKCFG_INFO; static const struct ng_parse_type ng_pipe_hookcfg_type = { &ng_parse_struct_type, &ng_pipe_hookcfg_type_fields }; /* Parse type for struct ng_pipe_cfg */ static const struct ng_parse_struct_field ng_pipe_cfg_type_fields[] = NG_PIPE_CFG_INFO(&ng_pipe_hookcfg_type); static const struct ng_parse_type ng_pipe_cfg_type = { &ng_parse_struct_type, &ng_pipe_cfg_type_fields }; /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ngp_cmds[] = { { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_GET_STATS, .name = "getstats", .respType = &ng_pipe_stats_type }, { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_CLR_STATS, .name = "clrstats" }, { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_GETCLR_STATS, .name = "getclrstats", .respType = &ng_pipe_stats_type }, { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_GET_RUN, .name = "getrun", .respType = &ng_pipe_run_type }, { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_GET_CFG, .name = "getcfg", .respType = &ng_pipe_cfg_type }, { .cookie = NGM_PIPE_COOKIE, .cmd = NGM_PIPE_SET_CFG, .name = "setcfg", .mesgType = &ng_pipe_cfg_type, }, { 0 } }; /* Netgraph type descriptor */ static struct ng_type ng_pipe_typestruct = { .version = NG_ABI_VERSION, .name = NG_PIPE_NODE_TYPE, .mod_event = ngp_modevent, .constructor = ngp_constructor, .shutdown = ngp_shutdown, .rcvmsg = ngp_rcvmsg, .newhook = ngp_newhook, .rcvdata = ngp_rcvdata, .disconnect = ngp_disconnect, .cmdlist = ngp_cmds }; NETGRAPH_INIT(pipe, &ng_pipe_typestruct); /* Node constructor */ static int ngp_constructor(node_p node) { priv_p priv; MALLOC(priv, priv_p, sizeof(*priv), M_NG_PIPE, M_ZERO | M_NOWAIT); if (priv == NULL) return (ENOMEM); NG_NODE_SET_PRIVATE(node, priv); return (0); } /* Add a hook */ static int ngp_newhook(node_p node, hook_p hook, const char *name) { const priv_p priv = NG_NODE_PRIVATE(node); struct hookinfo *hinfo; if (strcmp(name, NG_PIPE_HOOK_UPPER) == 0) { bzero(&priv->upper, sizeof(priv->upper)); priv->upper.hook = hook; NG_HOOK_SET_PRIVATE(hook, &priv->upper); } else if (strcmp(name, NG_PIPE_HOOK_LOWER) == 0) { bzero(&priv->lower, sizeof(priv->lower)); priv->lower.hook = hook; NG_HOOK_SET_PRIVATE(hook, &priv->lower); } else return (EINVAL); /* Load non-zero initial cfg values */ hinfo = NG_HOOK_PRIVATE(hook); hinfo->cfg.qin_size_limit = 50; hinfo->cfg.fifo = 1; hinfo->cfg.droptail = 1; TAILQ_INIT(&hinfo->fifo_head); TAILQ_INIT(&hinfo->qout_head); return (0); } /* Receive a control message */ static int ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *resp = NULL; struct ng_mesg *msg; struct ng_pipe_stats *stats; struct ng_pipe_run *run; struct ng_pipe_cfg *cfg; int error = 0; mtx_lock(&ng_pipe_giant); NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_PIPE_COOKIE: switch (msg->header.cmd) { case NGM_PIPE_GET_STATS: case NGM_PIPE_CLR_STATS: case NGM_PIPE_GETCLR_STATS: if (msg->header.cmd != NGM_PIPE_CLR_STATS) { NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } stats = (struct ng_pipe_stats *)resp->data; bcopy(&priv->upper.stats, &stats->downstream, sizeof(stats->downstream)); bcopy(&priv->lower.stats, &stats->upstream, sizeof(stats->upstream)); } if (msg->header.cmd != NGM_PIPE_GET_STATS) { bzero(&priv->upper.stats, sizeof(priv->upper.stats)); bzero(&priv->lower.stats, sizeof(priv->lower.stats)); } break; case NGM_PIPE_GET_RUN: NG_MKRESPONSE(resp, msg, sizeof(*run), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } run = (struct ng_pipe_run *)resp->data; bcopy(&priv->upper.run, &run->downstream, sizeof(run->downstream)); bcopy(&priv->lower.run, &run->upstream, sizeof(run->upstream)); break; case NGM_PIPE_GET_CFG: NG_MKRESPONSE(resp, msg, sizeof(*cfg), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } cfg = (struct ng_pipe_cfg *)resp->data; bcopy(&priv->upper.cfg, &cfg->downstream, sizeof(cfg->downstream)); bcopy(&priv->lower.cfg, &cfg->upstream, sizeof(cfg->upstream)); cfg->delay = priv->delay; cfg->overhead = priv->overhead; cfg->header_offset = priv->header_offset; if (cfg->upstream.bandwidth == cfg->downstream.bandwidth) { cfg->bandwidth = cfg->upstream.bandwidth; cfg->upstream.bandwidth = 0; cfg->downstream.bandwidth = 0; } else cfg->bandwidth = 0; break; case NGM_PIPE_SET_CFG: cfg = (struct ng_pipe_cfg *)msg->data; if (msg->header.arglen != sizeof(*cfg)) { error = EINVAL; break; } if (cfg->delay == -1) priv->delay = 0; else if (cfg->delay > 0 && cfg->delay < 10000000) priv->delay = cfg->delay; if (cfg->bandwidth == -1) { priv->upper.cfg.bandwidth = 0; priv->lower.cfg.bandwidth = 0; priv->overhead = 0; } else if (cfg->bandwidth >= 100 && cfg->bandwidth <= 1000000000) { priv->upper.cfg.bandwidth = cfg->bandwidth; priv->lower.cfg.bandwidth = cfg->bandwidth; if (cfg->bandwidth >= 10000000) priv->overhead = 8+4+12; /* Ethernet */ else priv->overhead = 10; /* HDLC */ } if (cfg->overhead == -1) priv->overhead = 0; else if (cfg->overhead > 0 && cfg->overhead < 256) priv->overhead = cfg->overhead; if (cfg->header_offset == -1) priv->header_offset = 0; else if (cfg->header_offset > 0 && cfg->header_offset < 64) priv->header_offset = cfg->header_offset; parse_cfg(&priv->upper.cfg, &cfg->downstream, &priv->upper, priv); parse_cfg(&priv->lower.cfg, &cfg->upstream, &priv->lower, priv); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); mtx_unlock(&ng_pipe_giant); return (error); } static void parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, struct hookinfo *hinfo, priv_p priv) { if (new->ber == -1) { current->ber = 0; if (hinfo->ber_p) { FREE(hinfo->ber_p, M_NG_PIPE); hinfo->ber_p = NULL; } } else if (new->ber >= 1 && new->ber <= 1000000000000) { static const uint64_t one = 0x1000000000000; /* = 2^48 */ uint64_t p0, p; uint32_t fsize, i; if (hinfo->ber_p == NULL) MALLOC(hinfo->ber_p, uint64_t *, \ (MAX_FSIZE + MAX_OHSIZE)*sizeof(uint64_t), \ M_NG_PIPE, M_NOWAIT); current->ber = new->ber; /* * For given BER and each frame size N (in bytes) calculate * the probability P_OK that the frame is clean: * * P_OK(BER,N) = (1 - 1/BER)^(N*8) * * We use a 64-bit fixed-point format with decimal point * positioned between bits 47 and 48. */ p0 = one - one / new->ber; p = one; for (fsize = 0; fsize < MAX_FSIZE + MAX_OHSIZE; fsize++) { hinfo->ber_p[fsize] = p; for (i=0; i<8; i++) p = (p*(p0&0xffff)>>48) + \ (p*((p0>>16)&0xffff)>>32) + \ (p*(p0>>32)>>16); } } if (new->qin_size_limit == -1) current->qin_size_limit = 0; else if (new->qin_size_limit >= 5) current->qin_size_limit = new->qin_size_limit; if (new->qout_size_limit == -1) current->qout_size_limit = 0; else if (new->qout_size_limit >= 5) current->qout_size_limit = new->qout_size_limit; if (new->duplicate == -1) current->duplicate = 0; else if (new->duplicate > 0 && new->duplicate <= 50) current->duplicate = new->duplicate; if (new->fifo) { current->fifo = 1; current->wfq = 0; current->drr = 0; } if (new->wfq) { current->fifo = 0; current->wfq = 1; current->drr = 0; } if (new->drr) { current->fifo = 0; current->wfq = 0; /* DRR quantum */ if (new->drr >= 32) current->drr = new->drr; else current->drr = 2048; /* default quantum */ } if (new->droptail) { current->droptail = 1; current->drophead = 0; } if (new->drophead) { current->droptail = 0; current->drophead = 1; } if (new->bandwidth == -1) { current->bandwidth = 0; current->fifo = 1; current->wfq = 0; current->drr = 0; } else if (new->bandwidth >= 100 && new->bandwidth <= 1000000000) current->bandwidth = new->bandwidth; if (current->bandwidth | priv->delay | current->duplicate | current->ber) hinfo->noqueue = 0; else hinfo->noqueue = 1; } /* * Compute a hash signature for a packet. This function suffers from the * NIH sindrome, so probably it would be wise to look around what other * folks have found out to be a good and efficient IP hash function... */ static int ip_hash(struct mbuf *m, int offset) { u_int64_t i; struct ip *ip = (struct ip *)(mtod(m, u_char *) + offset); if (m->m_len < sizeof(struct ip) + offset || ip->ip_v != 4 || ip->ip_hl << 2 != sizeof(struct ip)) return 0; i = ((u_int64_t) ip->ip_src.s_addr ^ ((u_int64_t) ip->ip_src.s_addr << 13) ^ ((u_int64_t) ip->ip_dst.s_addr << 7) ^ ((u_int64_t) ip->ip_dst.s_addr << 19)); return (i ^ (i >> 32)); } /* * Receive data on a hook - both in upstream and downstream direction. * We put the frame on the inbound queue, and try to initiate dequeuing * sequence immediately. If inbound queue is full, discard one frame * depending on dropping policy (from the head or from the tail of the * queue). */ static int ngp_rcvdata(hook_p hook, item_p item) { struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook); const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct timeval uuptime; struct timeval *now = &uuptime; struct ngp_fifo *ngp_f = NULL, *ngp_f1; struct ngp_hdr *ngp_h = NULL; struct mbuf *m; int hash; int error = 0; if (hinfo->noqueue) { struct hookinfo *dest; if (hinfo == &priv->lower) dest = &priv->upper; else dest = &priv->lower; NG_FWD_ITEM_HOOK(error, item, dest->hook); return error; } mtx_lock(&ng_pipe_giant); microuptime(now); /* * Attach us to the list of active ng_pipes if this was an empty * one before, and also update the queue service deadline time. */ if (hinfo->run.qin_frames == 0) { struct timeval *when = &hinfo->qin_utime; if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec < now->tv_usec)) { when->tv_sec = now->tv_sec; when->tv_usec = now->tv_usec; } if (hinfo->run.qout_frames == 0) LIST_INSERT_HEAD(&active_head, hinfo, active_le); } /* Populate the packet header */ ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); KASSERT((ngp_h != NULL), ("ngp_h zalloc failed (1)")); NGI_GET_M(item, m); KASSERT(m != NULL, ("NGI_GET_M failed")); ngp_h->m = m; NG_FREE_ITEM(item); if (hinfo->cfg.fifo) hash = 0; /* all packets go into a single FIFO queue */ else hash = ip_hash(m, priv->header_offset); /* Find the appropriate FIFO queue for the packet and enqueue it*/ TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le) if (hash == ngp_f->hash) break; if (ngp_f == NULL) { ngp_f = uma_zalloc(ngp_zone, M_NOWAIT); KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (2)")); TAILQ_INIT(&ngp_f->packet_head); ngp_f->hash = hash; ngp_f->packets = 1; ngp_f->rr_deficit = hinfo->cfg.drr; /* DRR quantum */ hinfo->run.fifo_queues++; TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); FIFO_VTIME_SORT(m->m_pkthdr.len); } else { TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); ngp_f->packets++; } hinfo->run.qin_frames++; hinfo->run.qin_octets += m->m_pkthdr.len; /* Discard a frame if inbound queue limit has been reached */ if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { struct mbuf *m1; int longest = 0; /* Find the longest queue */ TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) if (ngp_f1->packets > longest) { longest = ngp_f1->packets; ngp_f = ngp_f1; } /* Drop a frame from the queue head/tail, depending on cfg */ if (hinfo->cfg.drophead) ngp_h = TAILQ_FIRST(&ngp_f->packet_head); else ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m1 = ngp_h->m; uma_zfree(ngp_zone, ngp_h); hinfo->run.qin_octets -= m1->m_pkthdr.len; hinfo->stats.in_disc_octets += m1->m_pkthdr.len; m_freem(m1); if (--(ngp_f->packets) == 0) { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); uma_zfree(ngp_zone, ngp_f); hinfo->run.fifo_queues--; } hinfo->run.qin_frames--; hinfo->stats.in_disc_frames++; } else if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { struct mbuf *m1; int longest = 0; /* Find the longest queue */ TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) if (ngp_f1->packets > longest) { longest = ngp_f1->packets; ngp_f = ngp_f1; } /* Drop a frame from the queue head/tail, depending on cfg */ if (hinfo->cfg.drophead) ngp_h = TAILQ_FIRST(&ngp_f->packet_head); else ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m1 = ngp_h->m; uma_zfree(ngp_zone, ngp_h); hinfo->run.qin_octets -= m1->m_pkthdr.len; hinfo->stats.in_disc_octets += m1->m_pkthdr.len; m_freem(m1); if (--(ngp_f->packets) == 0) { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); uma_zfree(ngp_zone, ngp_f); hinfo->run.fifo_queues--; } hinfo->run.qin_frames--; hinfo->stats.in_disc_frames++; } /* * Try to start the dequeuing process immediately. We must * hold the ng_pipe_giant lock here and pipe_dequeue() will * release it */ pipe_dequeue(hinfo, now); return (0); } #ifdef BOEING_WLAN /* generate a random integer between 1 and max */ #define pipe_good_random(max) (1 + (random() % max)) #if 0 /* generate a good random integer between 1 and max */ #define pipe_good_random(max) \ (1 + (int) (max * (random() / (__ULONG_MAX + 1.0)))) #endif #endif /* * Dequeueing sequence - we basically do the following: * 1) Try to extract the frame from the inbound (bandwidth) queue; * 2) In accordance to BER specified, discard the frame randomly; * 3) If the frame survives BER, prepend it with delay info and move it * to outbound (delay) queue; * 4) Loop to 2) until bandwidth quota for this timeslice is reached, or * inbound queue is flushed completely; * 5) Extract the first frame from the outbound queue, if it's time has * come. Queue the frame for transmission on the outbound hook; * 6) Loop to 5) until outbound queue is flushed completely, or the next * frame in the queue is not scheduled to be dequeued yet; * 7) Transimit all frames queued in 5) * * Note: the caller must hold the ng_pipe_giant lock; this function * returns with the lock released. */ static void pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { static uint64_t rand, oldrand; const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hinfo->hook)); struct hookinfo *dest; struct ngp_fifo *ngp_f, *ngp_f1; struct ngp_hdr *ngp_h; struct timeval *when; struct mbuf *q_head = NULL; struct mbuf *q_tail = NULL; struct mbuf *m; int error = 0; #ifdef BOEING_WLAN struct ngp_hdr *ngp_h1 = NULL; struct m_tag *tag = NULL; struct ng_wlan_tag wtag; static int was_lost = 0; #endif /* BOEING_WLAN */ /* Which one is the destination hook? */ if (hinfo == &priv->lower) dest = &priv->upper; else dest = &priv->lower; /* Bandwidth queue processing */ while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { when = &hinfo->qin_utime; if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec > now->tv_usec)) break; ngp_h = TAILQ_FIRST(&ngp_f->packet_head); m = ngp_h->m; #ifdef BOEING_WLAN /* Check the first mbuf tag for WLAN data, and remove it */ tag = m_tag_first(m); if (tag && (tag->m_tag_cookie == NGM_WLAN_COOKIE) && (tag->m_tag_id == NG_TAG_WLAN)) { WLAN_TAG_COPY( (&wtag), tag) /* enforce maximum parameters */ if (wtag.delay > NG_WLAN_MAX_DELAY) wtag.delay = NG_WLAN_MAX_DELAY; if (wtag.duplicate > NG_WLAN_MAX_DUP) wtag.duplicate = NG_WLAN_MAX_DUP; if (wtag.jitter > NG_WLAN_MAX_JITTER) wtag.jitter = NG_WLAN_MAX_JITTER; m_tag_delete(m, tag); } else { WLAN_TAG_ZERO( (&wtag) ); } #endif /* BOEING_WLAN */ /* Deficit Round Robin (DRR) processing */ if (hinfo->cfg.drr) { if (ngp_f->rr_deficit >= m->m_pkthdr.len) { ngp_f->rr_deficit -= m->m_pkthdr.len; } else { ngp_f->rr_deficit += hinfo->cfg.drr; TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); continue; } } /* * Either create a duplicate and pass it on, or dequeue * the original packet... */ #ifdef BOEING_WLAN if (wtag.duplicate && pipe_good_random(100) <= wtag.duplicate) { ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); ngp_h->m = m_dup(m, M_NOWAIT); KASSERT(ngp_h->m != NULL, ("m_dup failed")); m = ngp_h->m; /* Boeing: we are now working with copied mbuf, leaving original in the queue */ } else #endif /* BOEING_WLAN */ if (hinfo->cfg.duplicate && pipe_good_random(100) <= hinfo->cfg.duplicate) {/*Boeing*/ /* random() % 100 <= hinfo->cfg.duplicate) { */ ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); ngp_h->m = m_dup(m, M_NOWAIT); KASSERT(ngp_h->m != NULL, ("m_dup failed")); m = ngp_h->m; /* Boeing: we are now working with copied mbuf, leaving original in the queue */ } else { TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); hinfo->run.qin_frames--; hinfo->run.qin_octets -= m->m_pkthdr.len; ngp_f->packets--; } /* Boeing: now we have valid ngp_h and m pointers */ /* Calculate the serialization delay */ #ifdef BOEING_WLAN if (wtag.bandwidth) { hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len + priv->overhead ) * 8000000 / wtag.bandwidth; hinfo->qin_utime.tv_sec += hinfo->qin_utime.tv_usec / 1000000; hinfo->qin_utime.tv_usec = hinfo->qin_utime.tv_usec % 1000000; } else #endif /* BOEING_WLAN */ if (hinfo->cfg.bandwidth) { hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len + priv->overhead ) * 8000000 / hinfo->cfg.bandwidth; hinfo->qin_utime.tv_sec += hinfo->qin_utime.tv_usec / 1000000; hinfo->qin_utime.tv_usec = hinfo->qin_utime.tv_usec % 1000000; } when = &ngp_h->when; when->tv_sec = hinfo->qin_utime.tv_sec; when->tv_usec = hinfo->qin_utime.tv_usec; /* Sort / rearrange inbound queues */ if (ngp_f->packets) { if (hinfo->cfg.wfq) { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); FIFO_VTIME_SORT(TAILQ_FIRST( &ngp_f->packet_head)->m->m_pkthdr.len) } } else { TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); uma_zfree(ngp_zone, ngp_f); hinfo->run.fifo_queues--; } /* Randomly discard the frame, according to BER setting */ #ifdef BOEING_WLAN /* use specified Packet Error Rate setting for random discard */ if (wtag.per) { u_int16_t burst, test; burst = wtag.burst; if (burst < wtag.per) burst = wtag.per; if (was_lost) { test = burst; } else if ((wtag.per >= 100) || (burst >= 100)) { test = 100; } else { test = wtag.per*(100-burst)/(100-wtag.per); } if (pipe_good_random(100) <= test) { was_lost = 1; hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; uma_zfree(ngp_zone, ngp_h); m_freem(m); continue; } was_lost = 0; } else #endif /* BOEING_WLAN */ if (hinfo->cfg.ber && ((oldrand = rand) ^ (rand = random())<<17) >= hinfo->ber_p[priv->overhead + m->m_pkthdr.len] ) { hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; uma_zfree(ngp_zone, ngp_h); m_freem(m); continue; } /* Discard frame if outbound queue size limit exceeded */ if (hinfo->cfg.qout_size_limit && hinfo->run.qout_frames>=hinfo->cfg.qout_size_limit) { hinfo->stats.out_disc_frames++; hinfo->stats.out_disc_octets += m->m_pkthdr.len; uma_zfree(ngp_zone, ngp_h); m_freem(m); continue; } #ifdef BOEING_WLAN /* Calculate the propagation delay including jitter */ if (wtag.jitter) { when->tv_usec += pipe_good_random(wtag.jitter); /* overflow handled below... */ } when->tv_usec += wtag.delay ? wtag.delay : priv->delay; #else /* Calculate the propagation delay */ when->tv_usec += priv->delay; #endif /* BOEING_WLAN */ when->tv_sec += when->tv_usec / 1000000; when->tv_usec = when->tv_usec % 1000000; /* Put the frame into the delay queue */ #ifdef BOEING_WLAN /* Because WLAN packets may have varying dequeue times, we need to * perform sorted queueing; the dequeuing process expects packets in * the queue that are sorted by time. */ TAILQ_FOREACH(ngp_h1, &hinfo->qout_head, ngp_link) { if (ngp_h1->when.tv_sec > ngp_h->when.tv_sec || (ngp_h1->when.tv_sec == ngp_h->when.tv_sec && ngp_h1->when.tv_usec > ngp_h->when.tv_usec)) break; } if (ngp_h1 == NULL) TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); else TAILQ_INSERT_BEFORE(ngp_h1, ngp_h, ngp_link); /* The original code below just inserts the packet at the * tail of the queue because the delay time is constant. */ #else /* BOEING_WLAN */ TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); #endif /* BOEING_WLAN */ hinfo->run.qout_frames++; hinfo->run.qout_octets += m->m_pkthdr.len; } /* Delay queue processing */ while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { struct mbuf *m = ngp_h->m; /* BOEING_WLAN: this is why we have sorted the queue input */ when = &ngp_h->when; if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec > now->tv_usec)) break; /* Update outbound queue stats */ hinfo->stats.fwd_frames++; hinfo->stats.fwd_octets += m->m_pkthdr.len; hinfo->run.qout_frames--; hinfo->run.qout_octets -= m->m_pkthdr.len; /* Dequeue the packet from qout */ TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); uma_zfree(ngp_zone, ngp_h); /* Enqueue locally for sending downstream */ if (q_head == NULL) q_head = m; if (q_tail) q_tail->m_nextpkt = m; q_tail = m; m->m_nextpkt = NULL; } /* If both queues are empty detach us from the list of active queues */ if (hinfo->run.qin_frames + hinfo->run.qout_frames == 0) { LIST_REMOVE(hinfo, active_le); active_gen_id++; } mtx_unlock(&ng_pipe_giant); while ((m = q_head) != NULL) { q_head = m->m_nextpkt; m->m_nextpkt = NULL; NG_SEND_DATA(error, dest->hook, m, meta); } } /* * This routine is called on every clock tick. We poll all nodes/hooks * for queued frames by calling pipe_dequeue(). */ static void pipe_scheduler(void *arg) { pipe_poll(); /* Reschedule */ callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); } /* * Traverse the list of all active hooks and attempt to dequeue * some packets. Hooks with empty queues are not traversed since * they are not linked into this list. */ static void pipe_poll(void) { struct hookinfo *hinfo; struct timeval now; int old_gen_id = active_gen_id; mtx_lock(&ng_pipe_giant); microuptime(&now); LIST_FOREACH(hinfo, &active_head, active_le) { CURVNET_SET(NG_HOOK_NODE(hinfo->hook)->nd_vnet); pipe_dequeue(hinfo, &now); CURVNET_RESTORE(); mtx_lock(&ng_pipe_giant); if (old_gen_id != active_gen_id) { /* the list was updated; restart traversing */ hinfo = LIST_FIRST(&active_head); if (hinfo == NULL) break; old_gen_id = active_gen_id; continue; } } mtx_unlock(&ng_pipe_giant); } /* * Shutdown processing * * This is tricky. If we have both a lower and upper hook, then we * probably want to extricate ourselves and leave the two peers * still linked to each other. Otherwise we should just shut down as * a normal node would. */ static int ngp_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); if (priv->lower.hook && priv->upper.hook) ng_bypass(priv->lower.hook, priv->upper.hook); else { if (priv->upper.hook != NULL) ng_rmhook_self(priv->upper.hook); if (priv->lower.hook != NULL) ng_rmhook_self(priv->lower.hook); } NG_NODE_UNREF(node); FREE(priv, M_NG_PIPE); return (0); } /* * Hook disconnection */ static int ngp_disconnect(hook_p hook) { struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook); struct ngp_fifo *ngp_f; struct ngp_hdr *ngp_h; int removed = 0; mtx_lock(&ng_pipe_giant); KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__)); hinfo->hook = NULL; /* Flush all fifo queues associated with the hook */ while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { while ((ngp_h = TAILQ_FIRST(&ngp_f->packet_head))) { TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m_freem(ngp_h->m); uma_zfree(ngp_zone, ngp_h); removed++; } TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); uma_zfree(ngp_zone, ngp_f); } /* Flush the delay queue */ while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); m_freem(ngp_h->m); uma_zfree(ngp_zone, ngp_h); removed++; } /* * Both queues should be empty by now, so detach us from * the list of active queues */ if (removed) { LIST_REMOVE(hinfo, active_le); active_gen_id++; } if (hinfo->run.qin_frames + hinfo->run.qout_frames != removed) printf("Mismatch: queued=%d but removed=%d !?!", hinfo->run.qin_frames + hinfo->run.qout_frames, removed); /* Release the packet loss probability table (BER) */ if (hinfo->ber_p) FREE(hinfo->ber_p, M_NG_PIPE); mtx_unlock(&ng_pipe_giant); return (0); } static int ngp_modevent(module_t mod, int type, void *unused) { int error = 0; switch (type) { case MOD_LOAD: ngp_zone = uma_zcreate("ng_pipe", max(sizeof(struct ngp_hdr), sizeof (struct ngp_fifo)), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); if (ngp_zone == NULL) panic("ng_pipe: couldn't allocate descriptor zone"); mtx_init(&ng_pipe_giant, "ng_pipe_giant", NULL, MTX_DEF); LIST_INIT(&active_head); callout_init(&polling_timer, CALLOUT_MPSAFE); callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); break; case MOD_UNLOAD: callout_drain(&polling_timer); uma_zdestroy(ngp_zone); mtx_destroy(&ng_pipe_giant); break; default: error = EOPNOTSUPP; break; } return (error); } core-4.6/kernel/freebsd/ng_pipe/ng_pipe.h0000664000175000017500000001276111173131445015352 00000000000000/* * Copyright (c) 2004, 2007 University of Zagreb * Copyright (c) 2007 FreeBSD Foundation * * This software was developed by the University of Zagreb and the * FreeBSD Foundation under sponsorship by the Stichting NLnet and the * FreeBSD Foundation. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _NETGRAPH_PIPE_H_ #define _NETGRAPH_PIPE_H_ /* Node type name and magic cookie */ #define NG_PIPE_NODE_TYPE "pipe" #define NGM_PIPE_COOKIE 200708191 /* Hook names */ #define NG_PIPE_HOOK_UPPER "upper" #define NG_PIPE_HOOK_LOWER "lower" #define MAX_FSIZE 16384 /* Largest supported frame size, in bytes, for BER */ #define MAX_OHSIZE 256 /* Largest supported dummy-framing size, in bytes */ /* Statistics structure for one hook */ struct ng_pipe_hookstat { u_int64_t fwd_octets; u_int64_t fwd_frames; u_int64_t in_disc_octets; u_int64_t in_disc_frames; u_int64_t out_disc_octets; u_int64_t out_disc_frames; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_HOOKSTAT_INFO { \ { "FwdOctets", &ng_parse_uint64_type }, \ { "FwdFrames", &ng_parse_uint64_type }, \ { "queueDropOctets", &ng_parse_uint64_type }, \ { "queueDropFrames", &ng_parse_uint64_type }, \ { "delayDropOctets", &ng_parse_uint64_type }, \ { "delayDropFrames", &ng_parse_uint64_type }, \ { NULL }, \ } /* Statistics structure returned by NGM_PIPE_GET_STATS */ struct ng_pipe_stats { struct ng_pipe_hookstat downstream; struct ng_pipe_hookstat upstream; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_STATS_INFO(hstype) { \ { "downstream", (hstype) }, \ { "upstream", (hstype) }, \ { NULL }, \ } /* Runtime structure for one hook */ struct ng_pipe_hookrun { u_int32_t fifo_queues; u_int32_t qin_octets; u_int32_t qin_frames; u_int32_t qout_octets; u_int32_t qout_frames; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_HOOKRUN_INFO { \ { "queues", &ng_parse_uint32_type }, \ { "queuedOctets", &ng_parse_uint32_type }, \ { "queuedFrames", &ng_parse_uint32_type }, \ { "delayedOctets", &ng_parse_uint32_type }, \ { "delayedFrames", &ng_parse_uint32_type }, \ { NULL }, \ } /* Runtime structure returned by NGM_PIPE_GET_RUN */ struct ng_pipe_run { struct ng_pipe_hookrun downstream; struct ng_pipe_hookrun upstream; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_RUN_INFO(hstype) { \ { "downstream", (hstype) }, \ { "upstream", (hstype) }, \ { NULL }, \ } /* Config structure for one hook */ struct ng_pipe_hookcfg { u_int64_t bandwidth; u_int64_t ber; u_int32_t qin_size_limit; u_int32_t qout_size_limit; u_int32_t duplicate; u_int32_t fifo; u_int32_t drr; u_int32_t wfq; u_int32_t droptail; u_int32_t drophead; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_HOOKCFG_INFO { \ { "bandwidth", &ng_parse_uint64_type }, \ { "BER", &ng_parse_uint64_type }, \ { "queuelen", &ng_parse_uint32_type }, \ { "delaylen", &ng_parse_uint32_type }, \ { "duplicate", &ng_parse_uint32_type }, \ { "fifo", &ng_parse_uint32_type }, \ { "drr", &ng_parse_uint32_type }, \ { "wfq", &ng_parse_uint32_type }, \ { "droptail", &ng_parse_uint32_type }, \ { "drophead", &ng_parse_uint32_type }, \ { NULL }, \ } /* Config structure returned by NGM_PIPE_GET_CFG */ struct ng_pipe_cfg { u_int64_t bandwidth; u_int64_t delay; u_int32_t header_offset; u_int32_t overhead; struct ng_pipe_hookcfg downstream; struct ng_pipe_hookcfg upstream; }; /* Keep this in sync with the above structure definition */ #define NG_PIPE_CFG_INFO(hstype) { \ { "bandwidth", &ng_parse_uint64_type }, \ { "delay", &ng_parse_uint64_type }, \ { "header_offset", &ng_parse_uint32_type }, \ { "overhead", &ng_parse_uint32_type }, \ { "downstream", (hstype) }, \ { "upstream", (hstype) }, \ { NULL }, \ } /* Netgraph commands */ enum { NGM_PIPE_GET_STATS=1, /* get stats */ NGM_PIPE_CLR_STATS, /* clear stats */ NGM_PIPE_GETCLR_STATS, /* atomically get and clear stats */ NGM_PIPE_GET_RUN, /* get current runtime status */ NGM_PIPE_GET_CFG, /* get configurable parameters */ NGM_PIPE_SET_CFG, /* set configurable parameters */ }; #endif /* _NETGRAPH_PIPE_H_ */ core-4.6/kernel/freebsd/ng_pipe/Makefile0000664000175000017500000000065311622265323015217 00000000000000# # (c)2008 the Boeing Company # # modified ng_pipe node # .if !defined(PLATFORM) #PLATFORM=i386 PLATFORM=amd64 .endif CFLAGS=-DBOEING_WLAN -I/usr/src/sys/${PLATFORM}/compile/CORE KMOD= ng_pipe SRCS= ng_pipe.c #MAN= ng_pipe.4 # FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0" #.if defined(OSTYPE) #.if (${OSTYPE} == "FreeBSD") #CFLAGS+=-DFREEBSD411 #SRCS= ng_pipe_freebsd4.c #.endif #.endif .include core-4.6/kernel/freebsd/ng_pipe/README0000664000175000017500000000163511173131445014436 00000000000000 ng_pipe FreeBSD kernel module See the copyright statement at the top of the source file. Copyright (c) 2004, 2005, 2007 University of Zagreb Copyright (c) 2007 FreeBSD Foundation (c) 2008 the Boeing Company modifications: Jeff Ahrenholz More complete documentation is available in the ng_pipe(4) man page. This version of ng_pipe has been modified as follows: - added burst rate (or burstiness) which is the probability that the next packet will be dropped given an error with the current packet, 0 to 100 - added jitter effect, which randomizes the delay an additional amount from 0 to jitter microseconds - ng_wlan support added, to remove and read mbuf tags containing wlan link effect information - bugfix: random number generation improved from defective modulo algorithm - bugfix: fixed mbuf dangling pointer reference when ng_pipe has both duplicates and errors configured core-4.6/kernel/freebsd/freebsd8-config-CORE0000664000175000017500000000032312021411051015527 00000000000000# this is the FreeBSD 8.x kernel configuration file for CORE include GENERIC ident CORE options VIMAGE nooptions SCTP options IPSEC device crypto options IPFIREWALL options IPFIREWALL_DEFAULT_TO_ACCEPT core-4.6/kernel/freebsd/imunes-8.0-RELEASE.diff0000664000175000017500000002576412021411051015644 00000000000000# This patch is from http://imunes.net/imunes-8.0-RC3.diff # # This patch enables per-node directories, persistent hub/switch nodes, traffic # snooping for wireshark, and disallows vlan interfaces within a jail. diff -drup src-org/sys/kern/vfs_lookup.c src/sys/kern/vfs_lookup.c --- src-org/sys/kern/vfs_lookup.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/kern/vfs_lookup.c 2009-11-11 12:46:02.000000000 +0000 @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_loo #include #endif +#include + #include #include @@ -72,6 +74,19 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, en "unsigned long"); SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); +#ifdef VIMAGE +#define IMUNES_SYMLINK_HACK +#endif + +#ifdef IMUNES_SYMLINK_HACK +static VNET_DEFINE(int, morphing_symlinks); +#define V_morphing_symlinks VNET(morphing_symlinks) + +SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW, + &VNET_NAME(morphing_symlinks), 0, + "Resolve @ to vimage name in symlinks"); +#endif + /* * Allocation zone for namei */ @@ -333,6 +348,44 @@ namei(struct nameidata *ndp) error = ENOENT; break; } +#ifdef IMUNES_SYMLINK_HACK + /* + * If the symbolic link includes a special character '@', + * and V_morphing_symlinks is set, substitute the first + * occurence of '@' with full path to jail / vimage name. + * If the full path includes subhierarchies, s/./\// when + * expanding '@' to jail / vimage name. + * + * XXX revisit buffer length checking. + */ + CURVNET_SET_QUIET(TD_TO_VNET(curthread)); + if (V_morphing_symlinks) { + char *sp = strchr(cp, '@'); + + if (sp) { + char *vname = td->td_ucred->cr_prison->pr_name; + int vnamelen = strlen(vname); + int i; + + if (vnamelen >= auio.uio_resid) { + if (ndp->ni_pathlen > 1) + uma_zfree(namei_zone, cp); + error = ENAMETOOLONG; + CURVNET_RESTORE(); + break; + } + bcopy(sp + 1, sp + vnamelen, + linklen - (sp - cp)); + bcopy(td->td_ucred->cr_prison->pr_name, + sp, vnamelen); + linklen += (vnamelen - 1); + for (i = 0; i < vnamelen; i++) + if (sp[i] == '.') + sp[i] = '/'; + } + } + CURVNET_RESTORE(); +#endif if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { if (ndp->ni_pathlen > 1) uma_zfree(namei_zone, cp); diff -drup src-org/sys/net/bpf.c src/sys/net/bpf.c --- src-org/sys/net/bpf.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/net/bpf.c 2009-11-11 12:46:02.000000000 +0000 @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/net/bpf.c,v #include #include #include +#include #include #include #include @@ -1435,9 +1436,34 @@ bpf_setif(struct bpf_d *d, struct ifreq struct bpf_if *bp; struct ifnet *theywant; +#define XVNET_BPF_SNOOPING +#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) + struct vnet *target_vnet = curvnet; + char *c; + + /* Attempt to attach to an ifnet in a foreign vnet, specified as @ */ + c = rindex(ifr->ifr_name, '@'); + if ( c != NULL ) { + struct prison *target_pr; + + *c++ = 0; + if (!isascii(*c) && !isdigit(*c)) + return ENXIO; + target_pr = prison_find_name(curthread->td_ucred->cr_prison, c); + if (target_pr == NULL) + return ENXIO; + target_vnet = target_pr->pr_vnet; + } + CURVNET_SET_QUIET(target_vnet); +#endif + theywant = ifunit(ifr->ifr_name); - if (theywant == NULL || theywant->if_bpf == NULL) + if (theywant == NULL || theywant->if_bpf == NULL) { +#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) + CURVNET_RESTORE(); +#endif return (ENXIO); + } bp = theywant->if_bpf; @@ -1477,6 +1503,9 @@ bpf_setif(struct bpf_d *d, struct ifreq BPFD_LOCK(d); reset_d(d); BPFD_UNLOCK(d); +#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) + CURVNET_RESTORE(); +#endif return (0); } diff -drup src-org/sys/net/if.c src/sys/net/if.c --- src-org/sys/net/if.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/net/if.c 2009-11-11 12:46:02.000000000 +0000 @@ -813,6 +813,14 @@ if_detach_internal(struct ifnet *ifp, in struct ifnet *iter; int found = 0; + /* + * Detach from any vlan, bridge or lagg ifnets linked to us. + * A small though unlikely window for a race from here to ifp + * unlinking from ifnet list is possible, hence we repeat the + * procedure once again further bellow. XXX. + */ + EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); + IFNET_WLOCK(); TAILQ_FOREACH(iter, &V_ifnet, if_link) if (iter == ifp) { diff -drup src-org/sys/net/if_llatbl.c src/sys/net/if_llatbl.c --- src-org/sys/net/if_llatbl.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/net/if_llatbl.c 2009-11-11 12:53:49.000000000 +0000 @@ -57,11 +57,14 @@ __FBSDID("$FreeBSD: src/sys/net/if_llatb MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); -static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables); +static VNET_DEFINE(SLIST_HEAD(, lltable), lltables); +#define V_lltables VNET(lltables) extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, u_char *); +static void vnet_lltable_init(void); + struct rwlock lltable_rwlock; RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); @@ -75,7 +78,7 @@ lltable_sysctl_dumparp(int af, struct sy int error = 0; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == af) { error = llt->llt_dump(llt, wr); if (error != 0) @@ -157,7 +160,7 @@ lltable_free(struct lltable *llt) KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); LLTABLE_WLOCK(); - SLIST_REMOVE(&lltables, llt, lltable, llt_link); + SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); LLTABLE_WUNLOCK(); for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { @@ -180,7 +183,7 @@ lltable_drain(int af) register int i; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; @@ -202,7 +205,7 @@ lltable_prefix_free(int af, struct socka struct lltable *llt; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; @@ -232,7 +235,7 @@ lltable_init(struct ifnet *ifp, int af) LIST_INIT(&llt->lle_head[i]); LLTABLE_WLOCK(); - SLIST_INSERT_HEAD(&lltables, llt, llt_link); + SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); LLTABLE_WUNLOCK(); return (llt); @@ -302,7 +305,7 @@ lla_rt_output(struct rt_msghdr *rtm, str /* XXX linked list may be too expensive */ LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == dst->sa_family && llt->llt_ifp == ifp) break; @@ -367,3 +370,12 @@ lla_rt_output(struct rt_msghdr *rtm, str return (error); } + +static void +vnet_lltable_init() +{ + + SLIST_INIT(&V_lltables); +} +VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, vnet_lltable_init, NULL); + diff -drup src-org/sys/net/if_vlan.c src/sys/net/if_vlan.c --- src-org/sys/net/if_vlan.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/net/if_vlan.c 2009-11-11 12:46:02.000000000 +0000 @@ -1359,6 +1359,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); if (error) break; +#ifdef VIMAGE + if (ifp->if_home_vnet != ifp->if_vnet) { + error = EPERM; + break; + } +#endif if (vlr.vlr_parent[0] == '\0') { vlan_unconfig(ifp); break; @@ -1386,6 +1392,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd case SIOCGETVLAN: bzero(&vlr, sizeof(vlr)); +#ifdef VIMAGE + if (ifp->if_home_vnet != ifp->if_vnet) { + error = EPERM; + break; + } +#endif VLAN_LOCK(); if (TRUNK(ifv) != NULL) { strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname, diff -drup src-org/sys/netgraph/ng_bridge.c src/sys/netgraph/ng_bridge.c --- src-org/sys/netgraph/ng_bridge.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/netgraph/ng_bridge.c 2009-11-11 12:46:02.000000000 +0000 @@ -105,6 +105,7 @@ struct ng_bridge_private { u_int numBuckets; /* num buckets in table */ u_int hashMask; /* numBuckets - 1 */ int numLinks; /* num connected links */ + int persistent; /* can exist w/o any hooks */ struct callout timer; /* one second periodic timer */ }; typedef struct ng_bridge_private *priv_p; @@ -345,13 +346,13 @@ static int ng_bridge_newhook(node_p node, hook_p hook, const char *name) { const priv_p priv = NG_NODE_PRIVATE(node); + int linkNum = -1; /* Check for a link hook */ if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX, strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) { const char *cp; char *eptr; - u_long linkNum; cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX); if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) @@ -359,6 +360,12 @@ ng_bridge_newhook(node_p node, hook_p ho linkNum = strtoul(cp, &eptr, 10); if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS) return (EINVAL); + } else if (strcmp(name, "anchor") == 0) { + linkNum = 0; + priv->persistent = 1; + } + + if (linkNum >= 0 ) { if (priv->links[linkNum] != NULL) return (EISCONN); priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]), @@ -366,7 +373,7 @@ ng_bridge_newhook(node_p node, hook_p ho if (priv->links[linkNum] == NULL) return (ENOMEM); priv->links[linkNum]->hook = hook; - NG_HOOK_SET_PRIVATE(hook, (void *)linkNum); + NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)linkNum); priv->numLinks++; return (0); } @@ -799,7 +806,8 @@ ng_bridge_disconnect(hook_p hook) /* If no more hooks, go away */ if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) - && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { + && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) + && !priv->persistent) { ng_rmnode_self(NG_HOOK_NODE(hook)); } return (0); diff -drup src-org/sys/netgraph/ng_hub.c src/sys/netgraph/ng_hub.c --- src-org/sys/netgraph/ng_hub.c 2009-10-25 01:10:29.000000000 +0000 +++ src/sys/netgraph/ng_hub.c 2009-11-11 12:46:02.000000000 +0000 @@ -37,6 +37,7 @@ #include static ng_constructor_t ng_hub_constructor; +static ng_newhook_t ng_hub_newhook; static ng_rcvdata_t ng_hub_rcvdata; static ng_disconnect_t ng_hub_disconnect; @@ -44,6 +45,7 @@ static struct ng_type ng_hub_typestruct .version = NG_ABI_VERSION, .name = NG_HUB_NODE_TYPE, .constructor = ng_hub_constructor, + .newhook = ng_hub_newhook, .rcvdata = ng_hub_rcvdata, .disconnect = ng_hub_disconnect, }; @@ -57,6 +59,14 @@ ng_hub_constructor(node_p node) return (0); } +static int +ng_hub_newhook(node_p node, hook_p hook, const char *name) +{ + if (strcmp(name, "anchor") == 0) + node->nd_private = (void *) 1; + return (0); +} + static int ng_hub_rcvdata(hook_p hook, item_p item) { @@ -94,7 +104,7 @@ ng_hub_disconnect(hook_p hook) { if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && - NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) + NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !hook->hk_node->nd_private) ng_rmnode_self(NG_HOOK_NODE(hook)); return (0); } core-4.6/kernel/freebsd/symlinks-8.1-RELEASE.diff0000664000175000017500000000404412021411051016202 00000000000000Index: sys/kern/vfs_lookup.c =========================================================================== --- sys/kern/vfs_lookup.c 2010/06/17 19:18:00 #3 +++ sys/kern/vfs_lookup.c 2010/06/17 19:18:00 @@ -59,6 +59,8 @@ #include #endif +#include + #include #include @@ -72,6 +74,19 @@ "unsigned long"); SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); +#ifdef VIMAGE +#define IMUNES_SYMLINK_HACK +#endif + +#ifdef IMUNES_SYMLINK_HACK +static VNET_DEFINE(int, morphing_symlinks); +#define V_morphing_symlinks VNET(morphing_symlinks) + +SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW, + &VNET_NAME(morphing_symlinks), 0, + "Resolve @ to vimage name in symlinks"); +#endif + /* * Allocation zone for namei */ @@ -333,6 +348,44 @@ error = ENOENT; break; } +#ifdef IMUNES_SYMLINK_HACK + /* + * If the symbolic link includes a special character '@', + * and V_morphing_symlinks is set, substitute the first + * occurence of '@' with full path to jail / vimage name. + * If the full path includes subhierarchies, s/./\// when + * expanding '@' to jail / vimage name. + * + * XXX revisit buffer length checking. + */ + CURVNET_SET_QUIET(TD_TO_VNET(curthread)); + if (V_morphing_symlinks) { + char *sp = strchr(cp, '@'); + + if (sp) { + char *vname = td->td_ucred->cr_prison->pr_name; + int vnamelen = strlen(vname); + int i; + + if (vnamelen >= auio.uio_resid) { + if (ndp->ni_pathlen > 1) + uma_zfree(namei_zone, cp); + error = ENAMETOOLONG; + CURVNET_RESTORE(); + break; + } + bcopy(sp + 1, sp + vnamelen, + linklen - (sp - cp)); + bcopy(td->td_ucred->cr_prison->pr_name, + sp, vnamelen); + linklen += (vnamelen - 1); + for (i = 0; i < vnamelen; i++) + if (sp[i] == '.') + sp[i] = '/'; + } + } + CURVNET_RESTORE(); +#endif if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { if (ndp->ni_pathlen > 1) uma_zfree(namei_zone, cp); core-4.6/kernel/freebsd/ng_wlan/0000775000175000017500000000000012220631372013633 500000000000000core-4.6/kernel/freebsd/ng_wlan/ng_wlan_tag.h0000664000175000017500000000321111622252141016177 00000000000000/* * Copyright (c) 2006-2011 the Boeing Company * All rights reserved. * * author: Jeff Ahrenholz */ #define NG_TAG_WLAN 0x01 #ifdef FREEBSD411 #define WLAN_META_SIZE (sizeof(struct ng_meta))+(sizeof(struct ng_wlan_tag)) #define WLAN_META_PRIORITY 0x01 #define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct meta_field_header)) #else #define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct m_tag)) #endif #define NG_WLAN_MAX_DELAY 2000000 /* 2,000,000us = 2s */ #define NG_WLAN_MAX_BW 1000000000 /* 1,000,000,000bps = 1000M */ #define NG_WLAN_MAX_PER 100 /* 100% */ #define NG_WLAN_MAX_DUP 50 /* 50% */ #define NG_WLAN_MAX_JITTER NG_WLAN_MAX_DELAY #define NG_WLAN_MAX_BURST NG_WLAN_MAX_PER /* Tag data that is prepended to packets passing through the WLAN node. */ struct ng_wlan_tag { #ifdef FREEBSD411 struct meta_field_header meta_hdr; #else struct m_tag tag; #endif u_int64_t delay; u_int64_t bandwidth; u_int16_t per; u_int16_t duplicate; u_int32_t jitter; u_int16_t burst; }; #define TAG_HAS_DATA(t) (t->delay || t->bandwidth || t->per || t->duplicate \ || t->jitter || t->burst ) #define WLAN_TAG_ZERO(t) do { \ t->delay = 0; \ t->bandwidth = 0; \ t->per = 0; \ t->duplicate = 0; \ t->jitter = 0; \ t->burst = 0; \ } while(0); #define WLAN_TAG_COPY(a, b) do { \ a->delay = ((struct ng_wlan_tag*)b)->delay; \ a->bandwidth = ((struct ng_wlan_tag*)b)->bandwidth; \ a->per = ((struct ng_wlan_tag*)b)->per; \ a->duplicate = ((struct ng_wlan_tag*)b)->duplicate; \ a->jitter = ((struct ng_wlan_tag*)b)->jitter; \ a->burst = ((struct ng_wlan_tag*)b)->burst; \ } while(0); core-4.6/kernel/freebsd/ng_wlan/Makefile0000664000175000017500000000061711622265323015223 00000000000000# # (c)2006-2011 the Boeing Company # # ng_wlan # .if !defined(PLATFORM) #PLATFORM=i386 PLATFORM=amd64 .endif CFLAGS+=-I/usr/src/sys/${PLATFORM}/compile/CORE -DMULTICAST_LOOKUPS # FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0" #.if defined(OSTYPE) #.if (${OSTYPE} == "FreeBSD") #CFLAGS+=-DFREEBSD411 #.endif #.endif KMOD= ng_wlan SRCS= ng_wlan.c #MAN= ng_wlan.4 .include core-4.6/kernel/freebsd/ng_wlan/ng_wlan.c0000664000175000017500000010400711622252141015344 00000000000000/* * Copyright (c) 2006-2011 the Boeing Company * ng_wlan is based on ng_hub, which is: * Copyright (c) 2004 Ruslan Ermilov * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #ifdef MULTICAST_LOOKUPS #include /* in.h */ #include /* IN_MULTICAST(), etc */ #include /* struct ip */ #include /* struct ether_header */ #endif /* MULTICAST_LOOKUPS */ #include #include #include /* #include */ #include "ng_wlan.h" #include "ng_wlan_tag.h" #ifdef NG_SEPARATE_MALLOC MALLOC_DEFINE(M_NETGRAPH_WLAN, "netgraph_wlan", "netgraph WLAN node "); #else #define M_NETGRAPH_WLAN M_NETGRAPH #endif #ifdef WLAN_GIANT_LOCK struct mtx ng_wlan_giant; #endif #ifdef MULTICAST_LOOKUPS #define mtod_off(m,off,t) ((t)(mtod((m),caddr_t)+(off))) #define IP_MCAST_HDR_OFFSET ETHER_HDR_LEN #define IP_MCAST_MIN_LEN (IP_MCAST_HDR_OFFSET + sizeof(struct ip)) #endif /* MULTICAST_LOOKUPS */ /* * WLAN node data types */ /* Hash table entry for wlan connectivity */ struct ng_wlan_hent { ng_ID_t l_id; ng_ID_t g_id; int linked; u_int64_t delay; u_int64_t bandwidth; u_int16_t per; u_int16_t duplicate; u_int32_t jitter; u_int16_t burst; SLIST_ENTRY(ng_wlan_hent) next; }; /* Hash table bucket declaration */ /* struct ng_wlan_bucket { struct ng_wlan_hent *slh_first; };*/ SLIST_HEAD(ng_wlan_bucket, ng_wlan_hent); #define MIN_BUCKETS 256 #define HASH(a, b) ( ((a << 16) + b) % MIN_BUCKETS ) #define IS_PEER_KSOCKET(h) \ (NG_PEER_NODE(h) != NULL && \ NG_PEER_NODE(h)->nd_type->name[0] == 'k' && \ NG_PEER_NODE(h)->nd_type->name[1] == 's') /* WLAN node private data */ struct ng_wlan_private { struct ng_wlan_bucket *tab; #ifndef FREEBSD411 struct mtx ng_wlan_tab_lock; #ifdef MULTICAST_LOOKUPS struct ng_wlan_mcast_bucket *mcast_tab; struct mtx ng_wlan_mcast_tab_lock; int multicast_enabled; #endif #endif /* !FREEBSD411 */ int persistent; u_int16_t mer; /* multicast error rate */ u_int16_t mburst; /* multicast burst rate */ }; typedef struct ng_wlan_private *priv_p; /* * Local function declarations */ static int ng_wlan_lookup(node_p node, hook_p hook1, hook_p hook2, struct ng_wlan_tag *tag); static int ng_wlan_unlink(node_p node, ng_ID_t node1, ng_ID_t node2); static int ng_wlan_link(node_p node, ng_ID_t node1, ng_ID_t node2, struct ng_wlan_set_data *data); #ifdef MULTICAST_LOOKUPS static int ng_wlan_mcast_lookup(node_p node, hook_p hook1, hook_p hook2, u_int32_t group, u_int32_t source); static int ng_wlan_mcast_link(node_p node, ng_ID_t node1, ng_ID_t node2, u_int32_t group, u_int32_t source, int unlink); /* Hash table entry for multicast connectivity */ struct ng_wlan_mcast_hent { ng_ID_t l_id; ng_ID_t g_id; u_int32_t group; u_int32_t source; int linked; SLIST_ENTRY(ng_wlan_mcast_hent) next; }; SLIST_HEAD(ng_wlan_mcast_bucket, ng_wlan_mcast_hent); #define MCAST_HASH(a, b, g) ( (((a << 16) + b) & g) % MIN_BUCKETS ) #endif /* MULTICAST_LOOKUPS */ /* * Netgraph node methods */ #ifndef FREEBSD411 static int ng_wlan_modevent(module_t mod, int type, void *unused); #endif static ng_constructor_t ng_wlan_constructor; static ng_rcvmsg_t ng_wlan_rcvmsg; static ng_shutdown_t ng_wlan_rmnode; static ng_newhook_t ng_wlan_newhook; static ng_rcvdata_t ng_wlan_rcvdata; #ifndef FREEBSD411 static ng_rcvdata_t ng_wlan_rcvdata_ks; #endif static ng_disconnect_t ng_wlan_disconnect; /* Parse types */ static const struct ng_parse_struct_field ng_wlan_link_type_fields[] = NG_WLAN_CONFIG_TYPE_INFO; static const struct ng_parse_type ng_wlan_link_type = { &ng_parse_struct_type, &ng_wlan_link_type_fields }; static const struct ng_parse_struct_field ng_wlan_set_type_fields[] = NG_WLAN_SET_DATA_TYPE_INFO; static const struct ng_parse_type ng_wlan_set_type = { &ng_parse_struct_type, &ng_wlan_set_type_fields }; static const struct ng_parse_struct_field ng_wlan_mer_type_fields[] = NG_WLAN_MER_TYPE_INFO; static const struct ng_parse_type ng_wlan_mer_type = { &ng_parse_struct_type, &ng_wlan_mer_type_fields }; #ifdef MULTICAST_LOOKUPS static const struct ng_parse_struct_field ng_wlan_multicast_set_type_fields[] = NG_WLAN_MULTICAST_SET_DATA_TYPE_INFO; static const struct ng_parse_type ng_wlan_multicast_set_type = { &ng_parse_struct_type, &ng_wlan_multicast_set_type_fields }; #endif /* MULTICAST_LOOKUPS */ /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_wlan_cmdlist[] = { { NGM_WLAN_COOKIE, NGM_WLAN_LINK_NODES, "link", &ng_wlan_link_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_UNLINK_NODES, "unlink", &ng_wlan_link_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_NODES_SET, "set", &ng_wlan_set_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_NODES_UNSET, "unset", &ng_wlan_link_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_NODES_GET, "get", &ng_wlan_link_type, &ng_wlan_set_type }, { NGM_WLAN_COOKIE, NGM_WLAN_MER, "mer", &ng_wlan_mer_type, NULL }, #ifdef MULTICAST_LOOKUPS { NGM_WLAN_COOKIE, NGM_WLAN_MULTICAST_SET, "mcastset", &ng_wlan_multicast_set_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_MULTICAST_UNSET, "mcastunset", &ng_wlan_multicast_set_type, NULL }, { NGM_WLAN_COOKIE, NGM_WLAN_MULTICAST_GET, "mcastget", &ng_wlan_multicast_set_type, &ng_wlan_multicast_set_type }, #endif /* MULTICAST_LOOKUPS */ { 0 } }; /* * Netgraph node type descriptor */ static struct ng_type ng_wlan_typestruct = { .version = NG_ABI_VERSION, .name = NG_WLAN_NODE_TYPE, #ifndef FREEBSD411 .mod_event = ng_wlan_modevent, #endif .constructor = ng_wlan_constructor, .rcvmsg = ng_wlan_rcvmsg, .shutdown = ng_wlan_rmnode, .newhook = ng_wlan_newhook, .rcvdata = ng_wlan_rcvdata, .disconnect = ng_wlan_disconnect, .cmdlist = ng_wlan_cmdlist, }; NETGRAPH_INIT(wlan, &ng_wlan_typestruct); #ifndef FREEBSD411 /* * Function implementations */ static int ng_wlan_modevent(module_t mod, int type, void *unused) { int error = 0; switch (type) { case MOD_LOAD: #ifdef WLAN_GIANT_LOCK mtx_init(&ng_wlan_giant, "ng_wlan_giant", NULL, MTX_DEF); #endif break; case MOD_UNLOAD: #ifdef WLAN_GIANT_LOCK mtx_destroy(&ng_wlan_giant); #endif break; default: error = EOPNOTSUPP; break; } return (error); } #endif /* !FREEBSD411 */ #ifdef FREEBSD411 static int ng_wlan_constructor(node_p *nodep) #else static int ng_wlan_constructor(node_p node) #endif { priv_p priv; #ifdef FREEBSD411 int error=0; #endif /* initialize the hash table */ MALLOC( priv, priv_p, sizeof(struct ng_wlan_private), M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); if (priv == NULL) return (ENOMEM); MALLOC( priv->tab, struct ng_wlan_bucket *, MIN_BUCKETS * sizeof(struct ng_wlan_bucket), M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); if (priv->tab == NULL) { FREE(priv, M_NETGRAPH_WLAN); return (ENOMEM); } #ifdef FREEBSD411 /* Call the generic node constructor. */ if ((error=ng_make_node_common(&ng_wlan_typestruct, nodep))) { FREE(priv->tab, M_NETGRAPH_WLAN); FREE(priv, M_NETGRAPH_WLAN); return(error); } NG_NODE_SET_PRIVATE(*nodep, priv); #else /* FREEBSD411 */ #ifdef MULTICAST_LOOKUPS priv->multicast_enabled = 0; /* turned off, until ng_wlan_mcast_link()*/ /* initialize multicast hash table */ MALLOC( priv->mcast_tab, struct ng_wlan_mcast_bucket *, MIN_BUCKETS * sizeof(struct ng_wlan_mcast_bucket), M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); if (priv->mcast_tab == NULL) { FREE(priv->tab, M_NETGRAPH_WLAN); FREE(priv, M_NETGRAPH_WLAN); return (ENOMEM); } mtx_init(&priv->ng_wlan_mcast_tab_lock, "ng_wlan_mcast_tab_lock", NULL, MTX_DEF); #endif /* MULTICAST_LOOKUPS */ mtx_init(&priv->ng_wlan_tab_lock, "ng_wlan_tab_lock", NULL, MTX_DEF); NG_NODE_SET_PRIVATE(node, priv); #endif /* FREEBSD411 */ return (0); } static int ng_wlan_newhook(node_p node, hook_p hook, const char *name) { const priv_p priv = NG_NODE_PRIVATE(node); /* ksocket hooks "ks0", "ks1", etc. get special receive function */ if (name[0] == 'k' && name[1] == 's') { #ifndef FREEBSD411 NG_HOOK_SET_RCVDATA(hook, ng_wlan_rcvdata_ks); #endif return 0; } if (strcmp(name, "anchor") == 0) { if (priv->persistent) return(EISCONN); priv->persistent = 1; } return 0; } /* * Receive a control message. */ #ifdef FREEBSD411 static int ng_wlan_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg **rptr) #else static int ng_wlan_rcvmsg(node_p node, item_p item, hook_p lasthook) #endif { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *resp = NULL; int error = 0; struct ng_wlan_config *nodes; struct ng_wlan_set_data *set_data; struct ng_wlan_tag tag; u_int32_t node1, node2; struct ng_hook h1, h2; struct ng_node n1, n2; #ifndef FREEBSD411 struct ng_mesg *msg; #ifdef MULTICAST_LOOKUPS struct ng_wlan_multicast_set_data *mcsd; u_int32_t group, src; int unlink; #endif /* MULTICAST_LOOKUPS */ #endif #ifndef FREEBSD411 #ifdef WLAN_GIANT_LOCK mtx_lock(&ng_wlan_giant); #else mtx_lock(&priv->ng_wlan_tab_lock); #ifdef MULTICAST_LOOKUPS mtx_lock(&priv->ng_wlan_mcast_tab_lock); #endif /* MULTICAST_LOOKUPS */ #endif NGI_GET_MSG(item, msg); #endif /* !FREEBSD411 */ switch (msg->header.typecookie) { case NGM_WLAN_COOKIE: switch (msg->header.cmd) { /* all of these messages take (node1=a,node2=b) param */ case NGM_WLAN_LINK_NODES: case NGM_WLAN_UNLINK_NODES: case NGM_WLAN_NODES_UNSET: case NGM_WLAN_NODES_GET: if (msg->header.arglen != sizeof(struct ng_wlan_config)) { error = EINVAL; break; } nodes = (struct ng_wlan_config *)msg->data; node1 = nodes->node1; node2 = nodes->node2; if (msg->header.cmd == NGM_WLAN_NODES_GET) { NG_MKRESPONSE(resp, msg, sizeof(*set_data), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } set_data = (struct ng_wlan_set_data*)resp->data; bzero(set_data, sizeof(*set_data)); /* make fake peer/node structures for lookup */ #ifdef FREEBSD411 h1.peer = &h2; h2.peer = &h1; h1.node = &n1; h2.node = &n2; n1.ID = node1; n2.ID = node2; #else h1.hk_peer = &h2; h2.hk_peer = &h1; h1.hk_node = &n1; h2.hk_node = &n2; n1.nd_ID = node1; n2.nd_ID = node2; #endif if (ng_wlan_lookup(node, &h1, &h2, &tag)) { set_data->node1 = node1; set_data->node2 = node2; WLAN_TAG_COPY(set_data, (&tag)); } /* if not found, node1/node2 will be zero */ break; } if (msg->header.cmd == NGM_WLAN_LINK_NODES) error = ng_wlan_link(node, node1, node2, NULL); else error = ng_wlan_unlink(node, node1, node2); break; case NGM_WLAN_NODES_SET: if (msg->header.arglen != sizeof(struct ng_wlan_set_data)) { error = EINVAL; break; } set_data = (struct ng_wlan_set_data *)msg->data; node1 = set_data->node1; node2 = set_data->node2; if (set_data->delay > NG_WLAN_MAX_DELAY || set_data->bandwidth > NG_WLAN_MAX_BW || set_data->per > NG_WLAN_MAX_PER || set_data->duplicate > NG_WLAN_MAX_DUP || set_data->jitter > NG_WLAN_MAX_JITTER || set_data->burst > NG_WLAN_MAX_BURST) { error = EINVAL; break; } error = ng_wlan_link(node, node1, node2, set_data); break; case NGM_WLAN_MER: if (msg->header.arglen != sizeof(struct ng_wlan_mer)) { error = EINVAL; break; } priv->mer = *((u_int16_t *)msg->data); priv->mburst = *((u_int16_t *)&msg->data[2]); break; case NGM_WLAN_MULTICAST_SET: case NGM_WLAN_MULTICAST_UNSET: case NGM_WLAN_MULTICAST_GET: #ifndef MULTICAST_LOOKUPS error = ENOTSUP; break; #else if (msg->header.arglen != sizeof(struct ng_wlan_multicast_set_data)) { error = EINVAL; break; } unlink = (msg->header.cmd == NGM_WLAN_MULTICAST_UNSET); mcsd = (struct ng_wlan_multicast_set_data *)msg->data; node1 = mcsd->node1; node2 = mcsd->node2; group = mcsd->group; src = mcsd->source; if (msg->header.cmd == NGM_WLAN_MULTICAST_GET) { NG_MKRESPONSE(resp, msg, sizeof(*mcsd), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } mcsd = (struct ng_wlan_multicast_set_data*) resp->data; bzero(mcsd, sizeof(*mcsd)); /* make fake peer/node structures for lookup */ #ifdef FREEBSD411 h1.peer = &h2; h2.peer = &h1; h1.node = &n1; h2.node = &n2; n1.ID = node1; n2.ID = node2; #else h1.hk_peer = &h2; h2.hk_peer = &h1; h1.hk_node = &n1; h2.hk_node = &n2; n1.nd_ID = node1; n2.nd_ID = node2; #endif if (ng_wlan_mcast_lookup(node, &h1, &h2, group, src)){ mcsd->node1 = node1; mcsd->node2 = node2; mcsd->group = group; } /* if not found, node1/node2 will be zero */ break; } error = ng_wlan_mcast_link(node, node1, node2, group, src, unlink); break; #endif /* MULTICAST_LOOKUPS */ default: error = EINVAL; break; } break; default: error = EINVAL; break; } #ifndef FREEBSD411 NG_RESPOND_MSG(error, node, item, resp); #endif NG_FREE_MSG(msg); #ifndef FREEBSD411 #ifdef WLAN_GIANT_LOCK mtx_unlock(&ng_wlan_giant); #else mtx_unlock(&priv->ng_wlan_tab_lock); #ifdef MULTICAST_LOOKUPS mtx_unlock(&priv->ng_wlan_mcast_tab_lock); #endif /* MULTICAST_LOOKUPS */ #endif #endif return(error); } #ifdef FREEBSD411 /* * Handle incoming data from connected netgraph hooks. * FreeBSD 4.11 version uses netgraph metadata. * Does not support ksocket backchannel, multicast lookups. */ static int ng_wlan_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) { const node_p node = NG_HOOK_NODE(hook); const priv_p priv = NG_NODE_PRIVATE(node); int error = 0; hook_p hook2; struct mbuf *m2; int nhooks; struct ng_wlan_tag *tag = NULL; /* Checking for NG_INVALID flag fixes race upon shutdown */ if ((NG_NODE_NOT_VALID(node)) || ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { NG_FREE_DATA(m, meta); return (0); } /* Meta information is not preserved by this node but replaced with * its own data. This sets meta = NULL */ NG_FREE_META(meta); /* Count number of linked nodes, not just number of hooks */ nhooks = 0; LIST_FOREACH(hook2, &node->hooks, hooks) { /* TODO: maintain a count of the number of linked nodes */ if (hook2 == hook) continue; if (!ng_wlan_lookup(node, hook, hook2, NULL)) continue; nhooks++; } if (nhooks==0) /* Nobody to receive the data */ goto rcvdata_free_item_error; LIST_FOREACH(hook2, &node->hooks, hooks) { if (hook2 == hook) continue; /* Allocate a meta+tag for sending with the data, which may or may not be used. If used, the ptr is set to NULL for the next loop iteration; unused (non-NULL ptr) will be freed after loop. */ if (!meta) { MALLOC(meta, meta_p, WLAN_META_SIZE, M_NETGRAPH, M_NOWAIT | M_ZERO); if (!meta) goto rcvdata_free_item_error_nobufs; meta->used_len = (u_short) WLAN_META_SIZE; meta->allocated_len = (u_short) WLAN_META_SIZE; meta->flags = 0; meta->priority = WLAN_META_PRIORITY; meta->discardability = -1; tag = (struct ng_wlan_tag*)meta->options; tag->meta_hdr.cookie = NGM_WLAN_COOKIE; tag->meta_hdr.type = NG_TAG_WLAN; tag->meta_hdr.len = sizeof(struct ng_wlan_tag); } WLAN_TAG_ZERO(tag); if ( !ng_wlan_lookup(node, hook, hook2, tag)) { /* determine if peers are connected, fill in tag data */ continue; } if ((m->m_flags & M_MCAST) && (priv->mer > 0) && tag) { tag->per = priv->mer; /* use configured mcast error */ tag->burst = priv->mburst; /* use conf mcast burst */ } if (--nhooks == 0) { /* nhooks is really number of links */ if (tag && TAG_HAS_DATA(tag)) { /* send metadata and set meta = NULL */ NG_SEND_DATA(error, hook2, m, meta); tag = NULL; /* tag used */ } else { /* Don't send any metadata */ NG_SEND_DATA_ONLY(error, hook2, m); } break; /* no need to loop and malloc */ } else { if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) goto rcvdata_free_item_error_nobufs; if (tag && TAG_HAS_DATA(tag)) { /* send metadata and set meta = NULL */ NG_SEND_DATA(error, hook2, m2, meta); tag = NULL; /* tag used */ } else { /* Don't send any metadata */ NG_SEND_DATA_ONLY(error, hook2, m2); if (error) /* XXX free mbuf? */ continue; /* don't give up */ } } /* end if nhooks==0 */ } /* end FOREACH hook */ if (meta) /* cleanup unused meta+tag */ NG_FREE_META(meta); goto rcvdata_out; rcvdata_free_item_error_nobufs: error = ENOBUFS; rcvdata_free_item_error: NG_FREE_DATA(m, meta); rcvdata_out: return (error); } #else /* FREEBSD411 */ /* * Handle incoming data from connected netgraph hooks. * FreeBSD 7.0 version uses mbuf tags; has additional features: * - ksocket backchannel for connecting two ng_wlans together * - multicast lookups for different forwarding behavior for multicast packets */ static int ng_wlan_rcvdata(hook_p hook, item_p item) { const node_p node = NG_HOOK_NODE(hook); int error = 0; hook_p hook2; struct mbuf *m2; int nhooks; struct ng_wlan_tag *tag = NULL; struct mbuf *m; const priv_p priv = NG_NODE_PRIVATE(node); ng_ID_t srcid; node_p peer; #ifdef MULTICAST_LOOKUPS u_int32_t group, src; struct ip *ip; struct ether_header *eh; #endif /* MULTICAST_LOOKUPS */ /* Checking for NG_INVALID flag fixes race upon shutdown */ if ((NG_NODE_NOT_VALID(node)) || ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { NG_FREE_ITEM(item); return (0); } #ifdef WLAN_GIANT_LOCK mtx_lock(&ng_wlan_giant); #else mtx_lock(&priv->ng_wlan_tab_lock); #endif m = NGI_M(item); /* 'item' still owns it... we are peeking */ #ifdef MULTICAST_LOOKUPS mtx_lock(&priv->ng_wlan_mcast_tab_lock); src = group = 0; if (priv->multicast_enabled && (m->m_flags & M_MCAST) && (m->m_flags & M_PKTHDR)) { /* disassociate mbuf from item (now we must free it) */ NGI_GET_M(item, m); /* Get group of packets sent to non-local multicast addresses */ if ((m->m_pkthdr.len >= IP_MCAST_MIN_LEN) && (m = m_pullup(m, IP_MCAST_MIN_LEN)) != NULL) { eh = mtod_off(m, 0, struct ether_header *); if (ETHER_IS_MULTICAST(eh->ether_dhost) && ntohs(eh->ether_type) == ETHERTYPE_IP) { ip = mtod_off(m, IP_MCAST_HDR_OFFSET, struct ip *); if ((ip->ip_v == IPVERSION) && IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && !(IN_LOCAL_GROUP(ntohl(ip->ip_dst.s_addr)))) { group = ntohl(ip->ip_dst.s_addr); src = NG_NODE_ID(NG_PEER_NODE(hook)); } } } else if (!m) { /* m_pullup failed, free item and leave */ error = EINVAL; goto rcvdata_free_item_error; } NGI_M(item) = m; /* give mbuf back to item */ } #endif /* MULTICAST_LOOKUPS */ /* Count number of linked nodes, not just number of hooks */ nhooks = 0; LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { /* TODO: maintain a count of the number of linked nodes */ if (hook2 == hook) continue; if (IS_PEER_KSOCKET(hook2)) { /* count all ksockets */ nhooks++; continue; } #ifdef MULTICAST_LOOKUPS /* count hook using multicast lookup if packet is multicast */ if ( group > 0 ) { if (!ng_wlan_mcast_lookup(node, hook, hook2, group, src) || !ng_wlan_lookup(node, hook, hook2, NULL)) continue; /* use normal unicast lookup */ } else #endif /* MULTICAST_LOOKUPS */ if (!ng_wlan_lookup(node, hook, hook2, NULL)) continue; nhooks++; } if (nhooks==0) /* Nobody to receive the data */ goto rcvdata_free_item_error; LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { if (hook2 == hook) continue; /* Allocate a tag for prepending to the mbuf, which may or may not be used. If used, the ptr is set to NULL for the next loop iteration; unused (non-NULL ptr) will be freed after loop. */ if (!tag) tag = (struct ng_wlan_tag *)m_tag_alloc(NGM_WLAN_COOKIE, NG_TAG_WLAN, TAGSIZE, M_NOWAIT | M_ZERO); if (!tag) goto rcvdata_free_item_error_nobufs; WLAN_TAG_ZERO(tag); /* check for ksocket backchannel to another ng_wlan */ srcid = 0; if (IS_PEER_KSOCKET(hook2)) { /* this hook is connected to a ksocket * set srcid for prepending the mbuf */ peer = NG_PEER_NODE(hook2); srcid = (NG_NODE_ID(peer) << 8) + NG_NODE_ID(NG_PEER_NODE(hook)); } else #ifdef MULTICAST_LOOKUPS if ( group > 0 ) { if (!ng_wlan_mcast_lookup(node, hook, hook2, group, src) || !ng_wlan_lookup(node, hook, hook2, tag)) continue; /* multicast lookup failed */ /* multicast lookup success - tag data filled in */ } else #endif /* MULTICAST_LOOKUPS */ if ( !ng_wlan_lookup(node, hook, hook2, tag)) { /* determine if peers are connected, fill in tag data */ continue; } if ((m->m_flags & M_MCAST) && (priv->mer > 0) && tag) { tag->per = priv->mer; /* use configured mcast error */ tag->burst = priv->mburst; /* use conf mcast burst */ } if (--nhooks == 0) { /* nhooks is really number of links */ if (srcid > 0) { /* add srcid for ksockets */ NGI_GET_M(item, m); M_PREPEND(m, sizeof(ng_ID_t), M_DONTWAIT); if (!m) goto rcvdata_free_item_error_nobufs; mtod(m, ng_ID_t*)[0] = htonl(srcid); NGI_M(item) = m; } else if (tag && TAG_HAS_DATA(tag)) { m_tag_prepend(m, &tag->tag); tag = NULL; /* tag used */ } NG_FWD_ITEM_HOOK(error, item, hook2); break; /* no need to loop and malloc */ } else { if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) goto rcvdata_free_item_error_nobufs; if (srcid > 0) { /* add srcid for ksockets */ M_PREPEND(m2, sizeof(ng_ID_t), M_DONTWAIT); if (!m2) goto rcvdata_free_item_error_nobufs; mtod(m2, ng_ID_t*)[0] = htonl(srcid); } else if (tag && TAG_HAS_DATA(tag)) { m_tag_prepend(m2, &tag->tag); tag = NULL; /* tag used */ } NG_SEND_DATA_ONLY(error, hook2, m2); if (error) /* XXX free mbuf? */ continue; /* don't give up */ } /* end if nhooks==0 */ } /* end FOREACH hook */ if (tag) /* cleanup unused tag */ m_tag_free(&tag->tag); /* assume item has been freed by fwd above (nhooks==0) */ goto rcvdata_out; rcvdata_free_item_error_nobufs: error = ENOBUFS; rcvdata_free_item_error: NG_FREE_ITEM(item); rcvdata_out: #ifdef WLAN_GIANT_LOCK mtx_unlock(&ng_wlan_giant); #else mtx_unlock(&priv->ng_wlan_tab_lock); #ifdef MULTICAST_LOOKUPS mtx_unlock(&priv->ng_wlan_mcast_tab_lock); #endif /* MULTICAST_LOOKUPS */ #endif return (error); } #endif /* FREEBSD411 */ #ifndef FREEBSD411 /* * Handle incoming data from hooks connected to kernel sockets */ static int ng_wlan_rcvdata_ks(hook_p hook, item_p item) { const node_p node = NG_HOOK_NODE(hook); const priv_p priv = NG_NODE_PRIVATE(node); int error = 0; hook_p hook2; struct mbuf *m, *m2; int nhooks; struct ng_wlan_tag *tag = NULL; ng_ID_t srcid; struct ng_hook hooklookup, hooklookup2; struct ng_node nodelookup; /* Checking for NG_INVALID flag fixes race upon shutdown */ if ((NG_NODE_NOT_VALID(node)) || ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { NG_FREE_ITEM(item); return (0); } #ifndef FREEBSD411 #ifdef WLAN_GIANT_LOCK mtx_lock(&ng_wlan_giant); #else mtx_lock(&priv->ng_wlan_tab_lock); #endif #endif /* this packet came from another system, so we read the * netgraph ID from the mbuf for use in lookups */ NGI_GET_M(item, m); if (m->m_pkthdr.len < sizeof(ng_ID_t)) { /* too short */ error = EINVAL; goto rcvdata_ks_free_item_error; } if (m->m_len < sizeof(ng_ID_t) && (m = m_pullup(m, sizeof(ng_ID_t))) == NULL) { goto rcvdata_ks_free_item_error_nobufs; } srcid = ntohl(*mtod(m, ng_ID_t*)); m_adj(m, sizeof(ng_ID_t)); NGI_M(item) = (m); /* build fake hooks/node for performing lookup */ hooklookup2.hk_node = &nodelookup; hooklookup.hk_peer = &hooklookup2; nodelookup.nd_ID = srcid; /* Count number of linked nodes, not just number of hooks */ nhooks = 0; LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { /* TODO: maintain a count of the number of linked nodes */ if (hook2 == hook) continue; /* ksockets not counted here -- they'll be skipped */ if (!ng_wlan_lookup(node, &hooklookup, hook2, NULL)) continue; nhooks++; } if (nhooks==0) /* Nobody to receive the data */ goto rcvdata_ks_free_item_error; LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { if (hook2 == hook) continue; /* Allocate a tag for prepending to the mbuf, which may or may not be used. If used, the ptr is set to NULL for the next loop iteration; unused (non-NULL ptr) will be freed after loop. */ if (!tag) tag = (struct ng_wlan_tag *)m_tag_alloc(NGM_WLAN_COOKIE, NG_TAG_WLAN, TAGSIZE, M_NOWAIT | M_ZERO); if (!tag) goto rcvdata_ks_free_item_error_nobufs; WLAN_TAG_ZERO(tag); /* don't send data to other ksockets */ if (IS_PEER_KSOCKET(hook2)) { continue; /* determine if peers are connected */ } else if ( !ng_wlan_lookup(node, &hooklookup, hook2, tag)) { continue; } if (--nhooks == 0) { /* nhooks is really number of links */ if (tag && TAG_HAS_DATA(tag)) { m_tag_prepend(m, &tag->tag); tag = NULL; /* tag used */ } NG_FWD_ITEM_HOOK(error, item, hook2); } else { if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) goto rcvdata_ks_free_item_error_nobufs; if (tag && TAG_HAS_DATA(tag)) { m_tag_prepend(m2, &tag->tag); tag = NULL; /* tag used */ } NG_SEND_DATA_ONLY(error, hook2, m2); if (error) /* XXX free mbuf? */ continue; /* don't give up */ } } if (tag) /* cleanup unused tag */ m_tag_free(&tag->tag); goto rcvdata_ks_out; rcvdata_ks_free_item_error_nobufs: error = ENOBUFS; rcvdata_ks_free_item_error: NG_FREE_ITEM(item); rcvdata_ks_out: #ifndef FREEBSD411 #ifdef WLAN_GIANT_LOCK mtx_unlock(&ng_wlan_giant); #else mtx_unlock(&priv->ng_wlan_tab_lock); #endif #endif return (error); } #endif /* !FREEBSD411 */ static int ng_wlan_disconnect(hook_p hook) { #ifdef FREEBSD411 const priv_p priv = hook->node->private; #else const priv_p priv = hook->hk_node->nd_private; #endif if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent) #ifdef FREEBSD411 ng_rmnode(NG_HOOK_NODE(hook)); #else ng_rmnode_self(NG_HOOK_NODE(hook)); #endif return (0); } static int ng_wlan_rmnode(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); int b, s; struct ng_wlan_hent *tmp; #ifdef MULTICAST_LOOKUPS struct ng_wlan_mcast_hent *mtmp; #endif /* MULTICAST_LOOKUPS */ s=splimp(); #ifdef FREEBSD411 node->flags |= NG_INVALID; ng_cutlinks(node); ng_unname(node); #else node->nd_flags |= NGF_INVALID; #endif NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); /* empty any link lists */ for (b = 0; b < MIN_BUCKETS; b++) { tmp = SLIST_FIRST(&priv->tab[b]); while (tmp) { SLIST_REMOVE_HEAD(&priv->tab[b], next); FREE(tmp, M_NETGRAPH_WLAN); tmp = SLIST_FIRST(&priv->tab[b]); } } FREE(priv->tab, M_NETGRAPH_WLAN); #ifndef FREEBSD411 mtx_destroy(&priv->ng_wlan_tab_lock); #endif priv->tab = NULL; #ifdef MULTICAST_LOOKUPS /* empty any multicast entry link lists */ for (b = 0; b < MIN_BUCKETS; b++) { mtmp = SLIST_FIRST(&priv->mcast_tab[b]); while (mtmp) { SLIST_REMOVE_HEAD(&priv->mcast_tab[b], next); FREE(mtmp, M_NETGRAPH_WLAN); mtmp = SLIST_FIRST(&priv->mcast_tab[b]); } } FREE(priv->mcast_tab, M_NETGRAPH_WLAN); mtx_destroy(&priv->ng_wlan_mcast_tab_lock); #endif /* MULTICAST_LOOKUPS */ FREE(priv, M_NETGRAPH_WLAN); splx(s); return 0; } /********************************************************************* * WLAN FUNCTIONS * **********************************************************************/ #define NODE_SORT(a, b, l, g) do { \ if (a > b) { \ g = a; \ l = b; \ } else { \ g = b; \ l = a; \ } \ } while (0); /* * Returns 1 if peers are linked, 0 if unlinked (default). */ static int ng_wlan_lookup(node_p node, hook_p hook1, hook_p hook2, struct ng_wlan_tag *tag) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_wlan_hent *hent; node_p node1, node2; ng_ID_t l_id, g_id; int bucket; if (!hook1 || !hook2) return 0; node1 = NG_PEER_NODE(hook1); node2 = NG_PEER_NODE(hook2); if (!node1 || !node2) return 0; NODE_SORT(NG_NODE_ID(node1), NG_NODE_ID(node2), l_id, g_id); bucket = HASH(l_id, g_id); /* mtx_lock(&priv->ng_wlan_tab_lock); */ SLIST_FOREACH(hent, &priv->tab[bucket], next) { if ((hent->l_id == l_id) && (hent->g_id == g_id)) { /* optionally fill in tag with link data*/ if (tag && hent->linked) { tag->delay = hent->delay; tag->bandwidth = hent->bandwidth; tag->per = hent->per; tag->duplicate = hent->duplicate; tag->jitter = hent->jitter; tag->burst = hent->burst; } /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return (hent->linked); /* linked or not linked flag */ } } /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return 0; /* not linked (not found) */ } #ifdef MULTICAST_LOOKUPS /* * Returns 1 if peers are linked for this multicast group, * 0 if unlinked (default). */ static int ng_wlan_mcast_lookup(node_p node, hook_p hook1, hook_p hook2, u_int32_t group, u_int32_t source) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_wlan_mcast_hent *hent; node_p node1, node2; ng_ID_t l_id, g_id; int bucket; if (!hook1 || !hook2) return 0; node1 = NG_PEER_NODE(hook1); node2 = NG_PEER_NODE(hook2); if (!node1 || !node2) return 0; NODE_SORT(NG_NODE_ID(node1), NG_NODE_ID(node2), l_id, g_id); bucket = MCAST_HASH(l_id, g_id, group); SLIST_FOREACH(hent, &priv->mcast_tab[bucket], next) { if ((hent->l_id == l_id) && (hent->g_id == g_id) && (hent->group == group) && (hent->source == source)) { return (hent->linked); } } return 0; /* not linked (not found) */ } /* * Link/unlink to peers for a given multicast group. */ static int ng_wlan_mcast_link(node_p node, ng_ID_t node1, ng_ID_t node2, u_int32_t group, u_int32_t source, int unlink) { const priv_p priv = NG_NODE_PRIVATE(node); ng_ID_t l_id, g_id; int bucket; struct ng_wlan_mcast_hent *hent; NODE_SORT(node1, node2, l_id, g_id); bucket = MCAST_HASH(l_id, g_id, group); priv->multicast_enabled = 1; /* turn on multicast lookups, this is never turned off */ /* Look for existing entry */ SLIST_FOREACH(hent, &priv->mcast_tab[bucket], next) { if ((hent->l_id == l_id) && (hent->g_id == g_id) && (hent->group == group) && (hent->source == source)) break; } /* Unlink called but no entry exists */ if (!hent && unlink) { return 0; } /* Allocate and initialize a new hash table entry */ if (!hent) { MALLOC( hent, struct ng_wlan_mcast_hent *, sizeof(*hent), M_NETGRAPH_WLAN, M_NOWAIT); if (hent == NULL) { return(ENOBUFS); } hent->l_id = l_id; hent->g_id = g_id; hent->group = group; hent->source = source; /* Add the new element to the hash bucket */ SLIST_INSERT_HEAD(&priv->mcast_tab[bucket], hent, next); } if (unlink) hent->linked = 0; else hent->linked = 1; return 0; } #endif /* MULTICAST_LOOKUPS */ /* * Link two peers together. * Once two peers have been linked together, the link can be flagged as * linked/unlinked in their hash table entry. Set link data if supplied. */ static int ng_wlan_link(node_p node, ng_ID_t node1, ng_ID_t node2, struct ng_wlan_set_data *data) { const priv_p priv = NG_NODE_PRIVATE(node); ng_ID_t l_id, g_id; int bucket; struct ng_wlan_hent *hent; NODE_SORT(node1, node2, l_id, g_id); bucket = HASH(l_id, g_id); /* mtx_lock(&priv->ng_wlan_tab_lock); */ /* Look for existing entry */ SLIST_FOREACH(hent, &priv->tab[bucket], next) { if ((hent->l_id == l_id) && (hent->g_id == g_id)) break; } /* Allocate and initialize a new hash table entry */ if (!hent) { MALLOC( hent, struct ng_wlan_hent *, sizeof(*hent), M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); if (hent == NULL) { /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return(ENOBUFS); } hent->l_id = l_id; hent->g_id = g_id; /* Add the new element to the hash bucket */ SLIST_INSERT_HEAD(&priv->tab[bucket], hent, next); } hent->linked = 1; if (data) { hent->delay = data->delay; hent->bandwidth = data->bandwidth; hent->per = data->per; hent->duplicate = data->duplicate; hent->jitter = data->jitter; hent->burst = data->burst; } else { WLAN_TAG_ZERO(hent); } /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return 0; } /* * Unlink two previously-linked peers. * because singly-linked list is not optimized for removals, we just * unset the "linked" flag. Link data is zeroed. */ static int ng_wlan_unlink(node_p node, ng_ID_t node1, ng_ID_t node2) { const priv_p priv = NG_NODE_PRIVATE(node); ng_ID_t l_id, g_id; int bucket; struct ng_wlan_hent *hent; NODE_SORT(node1, node2, l_id, g_id); bucket = HASH(l_id, g_id); /* Look for existing entry */ /* mtx_lock(&priv->ng_wlan_tab_lock); */ SLIST_FOREACH(hent, &priv->tab[bucket], next) { /* entry exists in hash table, unset linked flag */ if ((hent->l_id == l_id) && (hent->g_id == g_id)) { hent->linked = 0; WLAN_TAG_ZERO(hent); /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return(0); } } /* Entry does not exist in the hash table, do nothing. */ /* mtx_unlock(&priv->ng_wlan_tab_lock); */ return 0; } core-4.6/kernel/freebsd/ng_wlan/ng_wlan.h0000664000175000017500000000655111622252141015356 00000000000000/* * Copyright (c) 2006-2011 the Boeing Company * ng_wlan is based on ng_hub, which is: * Copyright (c) 2004 Ruslan Ermilov * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef _NETGRAPH_NG_WLAN_H_ #define _NETGRAPH_NG_WLAN_H_ /* Node type name and magic cookie. */ #define NG_WLAN_NODE_TYPE "wlan" #define NGM_WLAN_COOKIE 1146673193 /* Control message parse info */ struct ng_wlan_config { u_int32_t node1; u_int32_t node2; }; #define NG_WLAN_CONFIG_TYPE_INFO { \ { "node1", &ng_parse_uint32_type }, \ { "node2", &ng_parse_uint32_type }, \ { NULL } \ } struct ng_wlan_set_data { u_int32_t node1; u_int32_t node2; u_int64_t delay; /* keep these aligned with struct ng_wlan_tag */ u_int64_t bandwidth; u_int16_t per; u_int16_t duplicate; u_int32_t jitter; u_int16_t burst; }; #define NG_WLAN_SET_DATA_TYPE_INFO { \ { "node1", &ng_parse_uint32_type }, \ { "node2", &ng_parse_uint32_type }, \ { "delay", &ng_parse_uint64_type }, \ { "bandwidth", &ng_parse_uint64_type }, \ { "per", &ng_parse_uint16_type }, \ { "duplicate", &ng_parse_uint16_type }, \ { "jitter", &ng_parse_uint32_type }, \ { "burst", &ng_parse_uint16_type }, \ { NULL } \ } struct ng_wlan_mer { uint16_t mer; uint16_t mburst; }; #define NG_WLAN_MER_TYPE_INFO { \ { "mer", &ng_parse_uint16_type }, \ { "mburst", &ng_parse_uint16_type }, \ { NULL } \ } #ifdef MULTICAST_LOOKUPS struct ng_wlan_multicast_set_data { u_int32_t node1; u_int32_t node2; u_int32_t group; u_int32_t source; }; #define NG_WLAN_MULTICAST_SET_DATA_TYPE_INFO { \ { "node1", &ng_parse_uint32_type }, \ { "node2", &ng_parse_uint32_type }, \ { "group", &ng_parse_uint32_type }, \ { "source", &ng_parse_uint32_type }, \ { NULL } \ } #endif /* MULTICAST_LOOKUPS */ /* List of supported Netgraph control messages */ enum { NGM_WLAN_LINK_NODES = 1, NGM_WLAN_UNLINK_NODES, NGM_WLAN_NODES_SET, NGM_WLAN_NODES_UNSET, NGM_WLAN_NODES_GET, NGM_WLAN_MER, /* MULTICAST_ERR */ NGM_WLAN_MULTICAST_SET, /* MULTICAST_LOOKUPS */ NGM_WLAN_MULTICAST_UNSET, /* MULTICAST_LOOKUPS */ NGM_WLAN_MULTICAST_GET, /* MULTICAST_LOOKUPS */ }; #endif /* _NETGRAPH_NG_WLAN_H_ */ core-4.6/kernel/freebsd/ng_wlan/README0000664000175000017500000000507411622252141014437 00000000000000 ng_wlan FreeBSD kernel module (c) 2006-2011 the Boeing Company author: Jeff Ahrenholz The ng_wlan modules implements a netgraph node that models wireless LAN connectivity. ng_wlan extends the ng_hub node, only instead of sending packets to each connected peer, maintains a hash table of node connectivity, and sends packets between two nodes only when they are linked. By default all nodes are unlinked. Nodes can be linked and unlinked using "link" and "unlink" messages: ngctl msg e0_n2: link { node1=0x23 node2=0x0c } The node IDs of the two nodes are the parameters, as depicted above. Link effects between can also be specified for each node pair. If two nodes are linked and parameters are specified, an mbuf tag will be added to each data packet mbuf that specifies the effects. For FreeBSD 4.11, the metadata parameter is used instead of mbuf tags. Delay (microseconds), bandwidth (bits per second), PER (% packet errors), duplicates (%), jitter (microseconds), and burst (% burst errors) are supported. This tag is then removed by the ng_pipe node and the appropriate effects are applied. Link effects are specified with "set" and "unset" messages: ngctl msg e0_n2: set { node1=0x23 node2=0x0c delay=50000 bandwidth=54000000 per=0 duplicate=0 jitter=5000 burst=30 } ngctl msg e0_n2: unset { node1=0x23 node2=0x0c } Note that a special ng_pipe module is needed (the default one does not support the mbuf tags and some effects.) A separate error rate and burst rate affecting all multicast packets may be defined. Use the "mer" message: ngctl msg e0_n2: mer { mer=20 mburst=35 } The above example sets the multicast error rate to drop 20% of all multicast packets, with 35% burst errors. When MULTICAST_LOOKUPS is defined, a second lookup table is defined for each WLAN where multicast group, source, and node pair tuples can be linked or unlinked. This causes different forwarding behavior for multicast packets, where non-local groups are only forwarded if the node pair has been linked together for that group (and the normal node pair has been linked). Usage: ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0x0a000002 } ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0} ngctl msg e0_n2: mcastunset { node1=0x23 node2=0x0c group=0xEF020364 source=0 } Once the first mcastset/mcastunset message is received, that ng_wlan will drop all non-local multicast packets that do not have a matching source, group, node pair entry. The source address of zero matches any IP source. core-4.6/kernel/freebsd/vimage/0000775000175000017500000000000012220631372013456 500000000000000core-4.6/kernel/freebsd/vimage/vimage.c0000664000175000017500000002366211432516554015033 00000000000000/* * Copyright (c) 2002-2004 Marko Zec * Copyright (c) 2009 University of Zagreb * Copyright (c) 2009 FreeBSD Foundation * * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include typedef enum { VI_SWITCHTO, VI_CREATE, VI_MODIFY, VI_DESTROY, VI_IFMOVE, VI_GET } vi_cmd_t; typedef struct vimage_status { char name[MAXPATHLEN]; /* Must be first field for strcmp(). */ char path[MAXPATHLEN]; char hostname[MAXPATHLEN]; char domainname[MAXPATHLEN]; int jid; int parentjid; int vnet; int childcnt; int childmax; int cpuset; int rawsock; int socket_af; int mount; } vstat_t; #define VST_SIZE_STEP 1024 #define MAXPARAMS 32 static int getjail(vstat_t *, int, int); static char *invocname; static void usage(void) { fprintf(stderr, "usage: %s [-c | -m] vname [param=value ...]\n" " %s -d vname\n" " %s -l[rvj] [vname]\n" " %s -i vname ifname [newifname]\n" " %s vname [command ...]\n", invocname, invocname, invocname, invocname, invocname); exit(1); } int main(int argc, char **argv) { struct jailparam params[MAXPARAMS]; char ifname[IFNAMSIZ]; struct ifreq ifreq; vi_cmd_t newcmd, cmd; int recurse = 0; int verbose = 0; int jid, i, s, namelen; int vst_size, vst_last; vstat_t *vst; char *str; char ch; invocname = argv[0]; newcmd = cmd = VI_SWITCHTO; /* Default if no modifiers specified. */ while ((ch = getopt(argc, argv, "cdijlmrv")) != -1) { switch (ch) { case 'c': newcmd = VI_CREATE; break; case 'm': newcmd = VI_MODIFY; break; case 'd': newcmd = VI_DESTROY; break; case 'l': newcmd = VI_GET; break; case 'i': newcmd = VI_IFMOVE; break; case 'r': recurse = 1; break; case 'v': verbose++; break; case 'j': verbose = 2; break; default: usage(); } if (cmd == VI_SWITCHTO || cmd == newcmd) cmd = newcmd; else usage(); } argc -= optind; argv += optind; if ((cmd != VI_GET && (argc == 0 || recurse != 0 || verbose != 0)) || (cmd == VI_IFMOVE && (argc < 2 || argc > 3)) || (cmd == VI_MODIFY && argc < 2) || argc >= MAXPARAMS) usage(); switch (cmd) { case VI_GET: vst_last = 0; vst_size = VST_SIZE_STEP; if ((vst = malloc(vst_size * sizeof(*vst))) == NULL) break; if (argc == 1) namelen = strlen(argv[0]); else namelen = 0; jid = 0; while ((jid = getjail(&vst[vst_last], jid, verbose)) > 0) { /* Skip jails which do not own vnets. */ if (vst[vst_last].vnet != 1) continue; /* Skip non-matching vnames / hierarchies. */ if (namelen && ((strlen(vst[vst_last].name) < namelen || strncmp(vst[vst_last].name, argv[0], namelen) != 0) || (strlen(vst[vst_last].name) > namelen && vst[vst_last].name[namelen] != '.'))) continue; /* Skip any sub-trees if -r not requested. */ if (!recurse && (strlen(vst[vst_last].name) < namelen || strchr(&vst[vst_last].name[namelen], '.') != NULL)) continue; /* Grow vst table if necessary. */ if (++vst_last == vst_size) { vst_size += VST_SIZE_STEP; vst = realloc(vst, vst_size * sizeof(*vst)); if (vst == NULL) break; } } if (vst == NULL) break; /* Sort: the key is the 1st field in *vst, i.e. vimage name. */ qsort(vst, vst_last, sizeof(*vst), (void *) strcmp); for (i = 0; i < vst_last; i++) { if (!verbose) { printf("%s\n", vst[i].name); continue; } printf("%s:\n", vst[i].name); printf(" Path: %s\n", vst[i].path); printf(" Hostname: %s\n", vst[i].hostname); printf(" Domainname: %s\n", vst[i].domainname); printf(" Children: %d\n", vst[i].childcnt); if (verbose < 2) continue; printf(" Children limit: %d\n", vst[i].childmax); printf(" CPUsetID: %d\n", vst[i].cpuset); printf(" JID: %d\n", vst[i].jid); printf(" PJID: %d\n", vst[i].parentjid); printf(" Raw sockets allowed: %d\n", vst[i].rawsock); printf(" All AF allowed: %d\n", vst[i].socket_af); printf(" Mount allowed: %d\n", vst[i].mount); } free(vst); exit(0); case VI_IFMOVE: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) break; if ((jid = jail_getid(argv[0])) < 0) break; ifreq.ifr_jid = jid; strncpy(ifreq.ifr_name, argv[1], sizeof(ifreq.ifr_name)); if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0) break; close(s); if (argc == 3) snprintf(ifname, sizeof(ifname), "%s", argv[2]); else snprintf(ifname, sizeof(ifname), "eth0"); ifreq.ifr_data = ifname; /* Do we need to rename the ifnet? */ if (strcmp(ifreq.ifr_name, ifname) != 0) { /* Switch to the context of the target vimage. */ if (jail_attach(jid) < 0) break; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) break; for (namelen = 0; isalpha(ifname[namelen]); namelen++); i = 0; /* Search for a free ifunit in target vnet. Unsafe. */ while (ioctl(s, SIOCSIFNAME, (caddr_t)&ifreq) < 0) { snprintf(&ifname[namelen], sizeof(ifname) - namelen, "%d", i); /* Emergency brake. */ if (i++ == IF_MAXUNIT) break; } } if (i < IF_MAXUNIT) printf("%s@%s\n", ifname, argv[0]); else printf("%s@%s\n", ifreq.ifr_name, argv[0]); exit(0); case VI_CREATE: if (jail_setv(JAIL_CREATE, "name", argv[0], "vnet", NULL, "host", NULL, "persist", NULL, "allow.raw_sockets", "true", "allow.socket_af", "true", "allow.mount", "true", NULL) < 0) break; if (argc == 1) exit(0); /* Not done yet, proceed to apply non-default parameters. */ case VI_MODIFY: jailparam_init(¶ms[0], "name"); jailparam_import(¶ms[0], argv[0]); for (i = 1; i < argc; i++) { for (str = argv[i]; *str != '=' && *str != 0; str++) { /* Do nothing - search for '=' delimeter. */ } if (*str == 0) break; *str++ = 0; if (*str == 0) break; jailparam_init(¶ms[i], argv[i]); jailparam_import(¶ms[i], str); } if (i != argc) break; if (jailparam_set(params, i, JAIL_UPDATE) < 0) break; exit(0); case VI_DESTROY: if ((jid = jail_getid(argv[0])) < 0) break; if (jail_remove(jid) < 0) break; exit(0); case VI_SWITCHTO: if ((jid = jail_getid(argv[0])) < 0) break; if (jail_attach(jid) < 0) break; if (argc == 1) { printf("Switched to vimage %s\n", argv[0]); if ((str = getenv("SHELL")) == NULL) execlp("/bin/sh", invocname, NULL); else execlp(str, invocname, NULL); } else execvp(argv[1], &argv[1]); break; default: /* Should be unreachable. */ break; } if (jail_errmsg[0]) fprintf(stderr, "Error: %s\n", jail_errmsg); else perror("Error"); exit(1); } static int getjail(vstat_t *vs, int lastjid, int verbose) { struct jailparam params[32]; /* Must be > max(psize). */ int psize = 0; bzero(params, sizeof(params)); bzero(vs, sizeof(*vs)); jailparam_init(¶ms[psize], "lastjid"); jailparam_import_raw(¶ms[psize++], &lastjid, sizeof lastjid); jailparam_init(¶ms[psize], "vnet"); jailparam_import_raw(¶ms[psize++], &vs->vnet, sizeof(vs->vnet)); jailparam_init(¶ms[psize], "name"); jailparam_import_raw(¶ms[psize++], &vs->name, sizeof(vs->name)); if (verbose == 0) goto done; jailparam_init(¶ms[psize], "path"); jailparam_import_raw(¶ms[psize++], &vs->path, sizeof(vs->path)); jailparam_init(¶ms[psize], "host.hostname"); jailparam_import_raw(¶ms[psize++], &vs->hostname, sizeof(vs->hostname)); jailparam_init(¶ms[psize], "host.domainname"); jailparam_import_raw(¶ms[psize++], &vs->domainname, sizeof(vs->domainname)); jailparam_init(¶ms[psize], "children.cur"); jailparam_import_raw(¶ms[psize++], &vs->childcnt, sizeof(vs->childcnt)); if (verbose == 1) goto done; jailparam_init(¶ms[psize], "children.max"); jailparam_import_raw(¶ms[psize++], &vs->childmax, sizeof(vs->childmax)); jailparam_init(¶ms[psize], "cpuset.id"); jailparam_import_raw(¶ms[psize++], &vs->cpuset, sizeof(vs->cpuset)); jailparam_init(¶ms[psize], "parent"); jailparam_import_raw(¶ms[psize++], &vs->parentjid, sizeof(vs->parentjid)); jailparam_init(¶ms[psize], "allow.raw_sockets"); jailparam_import_raw(¶ms[psize++], &vs->rawsock, sizeof(vs->rawsock)); jailparam_init(¶ms[psize], "allow.socket_af"); jailparam_import_raw(¶ms[psize++], &vs->socket_af, sizeof(vs->socket_af)); jailparam_init(¶ms[psize], "allow.mount"); jailparam_import_raw(¶ms[psize++], &vs->mount, sizeof(vs->mount)); done: vs->jid = jailparam_get(params, psize, 0); jailparam_free(params, psize); return (vs->jid); } core-4.6/kernel/freebsd/vimage/vimage.80000664000175000017500000001274611432516554014761 00000000000000.\" Copyright (c) 2002, 2003 Marko Zec .\" Copyright (c) 2009 University of Zagreb .\" Copyright (c) 2009 FreeBSD Foundation .\" .\" 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. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd August 25, 2009 .Dt VIMAGE 8 .Os .Sh NAME .Nm vimage .Nd manage virtual network stacks .Sh SYNOPSIS .Nm .Op Fl c | m .Ar vname .Op Ar param=value ... .Nm .Fl d .Ar vname .Nm .Fl l .Op Fl rvj .Op Ar vname .Nm .Fl i .Ar vname ifname .Op Ar newifname .Nm .Ar vi_name .Op command ... .Sh DESCRIPTION The .Nm utility is an alternative user interface for controlling virtual network stacks in FreeBSD, aimed primarily at supporting legacy applications which are not yet converted to using .Xr jail 8 , .Xr jexec 8 , and .Xr jls 8 . . .Ss Overview A virtual image or vimage is a jail with its own independent network stack instance. Every process, socket and network interface present in the system is always attached to one, and only one, virtual network stack instance (vnet). During system bootup sequence a default vnet is created to which all the configured interfaces and user processes are initially attached. Assuming that enough system resources are are available, a user with sufficient privileges can create and manage a hierarchy of subordinated virtual images. The .Nm command allows for creation, deletion and monitoring of virtual images, as well as for execution of arbitrary processes in a targeted virtual image. .Ss Invocation If invoked with no modifiers, the .Nm command spawns a new interactive shell in virtual image .Ar vname . If optional additional arguments following .Ar vname are provided, the first of those will be executed in place of the interactive shell, and the rest of the arguments will be passed as arguments to the executed command. .Pp The following modifiers are available: .Bl -tag -width indent .It Fl c Create a new virtual image named .Ar vname . Additional arguments, if provided, may be used to specify operating parameters different from defaults, in format .Ar param=value . See .Xr jail 8 for an extensive list of available parameters. .It Fl m Modify the parameters of a virtual image named .Ar vname , using the same syntax as with the -c form of the command. .It Fl d Delete the virtual image .Ar vname . No processes and/or sockets should exist in the target virtual image in order for the delete request to succeed. Non-loopback interfaces residing in the target virtual image will be reassigned to the virtual image's parent. .It Fl l List the properties and statistics for virtual images one level below the current one in the hierarchy. If an optional argument .Ar vname is provided, only the information regarding the target virtual image .Ar vname is displayed. With the optional .Op Ar -r switch enabled the list will include all virtual images below the current level in the vimage hierarchy. Enabling the optional .Op Ar -v or .Op Ar -j switches results in a more detailed output. .It Fl i Move interface .Ar ifname to the target virtual image .Ar vname . Interfaces will be automatically renamed to .So ethXX .Sc , unless an optional argument specifying the desired interface name .Op Ar newifname is provided. .El .Sh EXAMPLES Create a new virtual image named .So v1 .Sc , which is allowed to create and manage an own subhierarchy of vimages: .Pp .Dl vimage -c v1 children.max=100 .Pp Execute the .So ifconfig .Sc command in the virtual image .So v1 .Sc : .Pp .Dl vimage v1 ifconfig .Pp Move the interface .So vlan0 .Sc to the virtual image .So v1 .Sc while renaming the interface as .So ve0 .Sc : .Pp .Dl vimage -i v1 vlan0 ve0 .Pp Show the status information for virtual image .So v1 .Sc : .Pp .Dl vimage -lv v1 .Sh DIAGNOSTICS The .Nm command exits 0 on success, and >0 if an error occurs. .Sh SEE ALSO .Xr jail 8 .Xr jexec 8 .Xr jls 8 .Sh HISTORY Network stack virtualization framework first appeared as a patchset against the FreeBSD 4.7 kernel in 2002, and was maintained outside of the main FreeBSD tree. As a result of a project sponsored by the FreeBSD Foundation and Stiching NLNet, integrated virtualized network stack first appeared in FreeBSD 8.0. .Sh BUGS Deletion of vimages / vnets is known to leak kernel memory and fail at stopping various timers, hence may lead to system crashes. .Sh AUTHOR .An "Marko Zec" Aq zec@fer.hr core-4.6/kernel/freebsd/vimage/Makefile0000664000175000017500000000023011432516554015041 00000000000000# $FreeBSD$ PROG= vimage LDADD= -ljail DPADD= ${LIBJAIL} WARNS?= 2 CFLAGS+= -I../../../sys MAN= vimage.8 BINDIR?= /usr/sbin .include core-4.6/kernel/freebsd/4.11-R-CORE.diff0000664000175000017500000062770612021411051014277 00000000000000diff -urN sys/i386/conf/CORE sys.CORE/i386/conf/CORE --- sys/i386/conf/CORE Wed Dec 31 16:00:00 1969 +++ sys.CORE/i386/conf/CORE Wed Jan 31 16:02:43 2007 @@ -0,0 +1,182 @@ +machine i386 +cpu I586_CPU +cpu I686_CPU +ident CORE +maxusers 0 + +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +options DDB + +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options IPSEC +options IPSEC_ESP +#options IPSEC_DEBUG +options FFS #Berkeley Fast Filesystem +options FFS_ROOT #FFS usable as root device [keep this!] +options SOFTUPDATES #Enable FFS soft updates support +options UFS_DIRHASH #Improve performance on big directories +options MFS #Memory Filesystem +options MD_ROOT #MD is a potential root device +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options CD9660_ROOT #CD-ROM usable as root, CD9660 required +options PROCFS #Process filesystem +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options UCONSOLE #Allow users to grab the console +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options P1003_1B #Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING +options ICMP_BANDLIM #Rate limit bad replies +options KBD_INSTALL_CDEV # install a CDEV entry in /dev + +device isa +device pci + +# Floppy drives +device fdc0 at isa? port IO_FD1 irq 6 drq 2 +device fd0 at fdc0 drive 0 + +# ATA and ATAPI devices +device ata0 at isa? port IO_WD1 irq 14 +device ata1 at isa? port IO_WD2 irq 15 +device ata +device atadisk # ATA disk drives +device atapicd # ATAPI CDROM drives +device atapifd # ATAPI floppy drives +device atapist # ATAPI tape drives +options ATA_STATIC_ID #Static device numbering + +# SCSI peripherals +device scbus # SCSI bus (required) +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) + +# atkbdc0 controls both the keyboard and the PS/2 mouse +device atkbdc0 at isa? port IO_KBD +device atkbd0 at atkbdc? irq 1 flags 0x1 +device psm0 at atkbdc? irq 12 + +device vga0 at isa? + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? flags 0x100 + +device agp # support several AGP chipsets + +# Floating point support - do not disable. +device npx0 at nexus? port IO_NPX irq 13 + +# Power management support (see LINT for more options) +#device apm0 at nexus? #flags 0x20 # Advanced Power Management + +# PCCARD (PCMCIA) support +device card +device pcic0 at isa? irq 0 port 0x3e0 iomem 0xd0000 +device pcic1 at isa? irq 0 port 0x3e2 iomem 0xd4000 disable + +# Serial (COM) ports +# jeffa: added debug flag +device sio0 at isa? port IO_COM1 flags 0x80 irq 4 +#device sio0 at isa? port IO_COM1 flags 0x10 irq 4 +device sio1 at isa? port IO_COM2 irq 3 + +# PCI Ethernet NICs. +device de # DEC/Intel DC21x4x (``Tulip'') +device em # Intel PRO/1000 adapter Gigabit Ethernet Card (``Wiseman'') +device txp # 3Com 3cR990 (``Typhoon'') +device vx # 3Com 3c590, 3c595 (``Vortex'') + +# PCI Ethernet NICs that use the common MII bus controller code. +# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! +device miibus # MII bus support +device dc # DEC/Intel 21143 and various workalikes +device fxp # Intel EtherExpress PRO/100B (82557, 82558) +device pcn # AMD Am79C97x PCI 10/100 NICs +device rl # RealTek 8129/8139 +device sf # Adaptec AIC-6915 (``Starfire'') +device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device ste # Sundance ST201 (D-Link DFE-550TX) +device tl # Texas Instruments ThunderLAN +device tx # SMC EtherPower II (83c170 ``EPIC'') +device vr # VIA Rhine, Rhine II +device wb # Winbond W89C840F +device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') +device bge # Broadcom BCM570x (``Tigon III'') + +# ISA Ethernet NICs. +# 'device ed' requires 'device miibus' +device ed0 at isa? disable port 0x280 irq 10 iomem 0xd8000 +device ex +device ep +device fe0 at isa? disable port 0x300 +# Xircom Ethernet +device xe + +# Wireless +#device awi +device wi +device an + +# The probe order of these is presently determined by i386/isa/isa_compat.c. +device ie0 at isa? disable port 0x300 irq 10 iomem 0xd0000 +#device le0 at isa? disable port 0x300 irq 5 iomem 0xd0000 +device lnc0 at isa? disable port 0x280 irq 10 drq 0 +device cs0 at isa? disable port 0x300 +device sn0 at isa? disable port 0x300 irq 10 + +# Pseudo devices - the number indicates how many units to allocate. +pseudo-device loop # Network loopback +pseudo-device ether # Ethernet support +pseudo-device tun # Packet tunnel. +pseudo-device pty # Pseudo-ttys (telnet etc) +pseudo-device md # Memory "disks" +pseudo-device gif +pseudo-device gre + +# The `bpf' pseudo-device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +pseudo-device bpf #Berkeley packet filter + +# USB support +device uhci # UHCI PCI->USB interface +device ohci # OHCI PCI->USB interface +device usb # USB Bus (required) +device ugen # Generic +device uhid # "Human Interface Devices" +device ukbd # Keyboard +device ulpt # Printer +device umass # Disks/Mass storage - Requires scbus and da +device ums # Mouse +# USB Ethernet, requires mii +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet +# USB com devices +device ucom +device uftdi + +# LIMUNES specific options +options ROOTDEVNAME=\"cd9660:acd0\" +options UNION # Is this really needed? +options EXT2FS # And this? +pseudo-device vn 15 # Vnode driver (turns a file into a device) + +options MROUTING # Multicast routing +options PIM # Protocol Independent Multicast +#options IPFIREWALL # firewall +#options IPFIREWALL_DEFAULT_TO_ACCEPT # allow everything by default +#options IPDIVERT # divert sockets + +options HZ=1000 +#options AUTO_EOI_1 +options CPU_ENABLE_SSE +options CPU_FASTER_5X86_FPU +makeoptions CONF_CFLAGS=-mpentiumpro diff -urN sys/kern/kern_vimage.c sys.CORE/kern/kern_vimage.c --- sys/kern/kern_vimage.c Wed Jan 31 15:57:04 2007 +++ sys.CORE/kern/kern_vimage.c Wed Jan 31 16:02:43 2007 @@ -52,9 +52,13 @@ #include #include #include +#include #include #include +#ifdef IPSEC +#include +#endif /* Arbitrary values */ #define TCP_SYNCACHE_HASHSIZE 512 @@ -107,6 +111,12 @@ { "mrt6stat", V_NET, v_mrt6stat, sizeof (x_vnet->mrt6stat) }, { "mf6ctable", V_NET, v_mf6ctable, sizeof (x_vnet->mf6ctable) }, { "mif6table", V_NET, v_mif6table, sizeof (x_vnet->mif6table) }, +#ifdef IPSEC + { "ipsecstat", V_NET, v_ipsecstat, sizeof (x_vnet->ipsecstat) }, +#ifdef INET6 + { "ipsec6stat", V_NET, v_ipsec6stat, sizeof (x_vnet->ipsec6stat) }, +#endif /* INET6 */ +#endif /* IPSEC */ { NULL, 0, 0 , 0 } }; @@ -742,7 +752,17 @@ } rtable_init((void **)vnet->rt_tables, vnet); +#ifdef IPSEC + if (vnet != vnet0) + key_init(vnet); +#endif vi_loopattach(vnet); + if (vnet != vnet0) + gif_init(vnet); + + /*Boeing IDC*/ + if (vnet != vnet0) + gre_init(vnet); if (IPFW_LOADED) ip_fw_init_ptr(vnet); @@ -796,6 +816,15 @@ free((caddr_t)vnet->ifnet_addrs, M_IFADDR); free((caddr_t)vnet->ifindex2ifnet, M_IFADDR); + + while (!LIST_EMPTY(&vnet->gif_softc_list)) + gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if); + rman_fini(vnet->gifunits); + + /*Boeing IDC*/ + while (!LIST_EMPTY(&vnet->gre_softc_list)) + gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if); + rman_fini(vnet->greunits); /* hopefully, we are finally clear to free the vnet container itself! */ LIST_REMOVE(vnet, vnet_le); diff -urN sys/net/if.c sys.CORE/net/if.c --- sys/net/if.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/if.c Wed Jan 31 16:19:58 2007 @@ -276,6 +276,11 @@ sdl->sdl_data[--namelen] = 0xff; TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); } +#ifdef MROUTING +#ifdef PIM + vnet->reg_vif_num = -1; /* XXX means VIFI_INVALID */ +#endif +#endif /* Announce the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); diff -urN sys/net/if_gif.c sys.CORE/net/if_gif.c --- sys/net/if_gif.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/if_gif.c Wed Jan 31 16:02:43 2007 @@ -90,7 +90,9 @@ #define GIF_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); +#ifdef MOVED_TO_VNET static struct rman gifunits[1]; +#endif /* MOVED_TO_VNET */ int gif_clone_create __P((struct if_clone *, int *, struct vnet *)); void gif_clone_destroy __P((struct ifnet *)); @@ -114,22 +116,26 @@ */ #define MAX_GIF_NEST 1 #endif +#ifdef MOVED_TO_VNET static int max_gif_nesting = MAX_GIF_NEST; -SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, - &max_gif_nesting, 0, "Max nested tunnels"); +#endif /* MOVED_TO_VNET */ +SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, + v_max_gif_nesting, 0, "Max nested tunnels"); /* * By default, we disallow creation of multiple tunnels between the same * pair of addresses. Some applications require this functionality so * we allow control over this check here. */ +#ifdef MOVED_TO_VNET #ifdef XBONEHACK static int parallel_tunnels = 1; #else static int parallel_tunnels = 0; #endif -SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, - ¶llel_tunnels, 0, "Allow parallel tunnels?"); +#endif /* MOVED_TO_VNET */ +SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, + v_parallel_tunnels, 0, "Allow parallel tunnels?"); int gif_clone_create(ifc, unit, vnet) @@ -140,17 +146,19 @@ struct resource *r; struct gif_softc *sc; + if (vnet == NULL) + panic("gif_clone_create: NULL vnet was passed."); if (*unit > GIF_MAXUNIT) return (ENXIO); if (*unit < 0) { - r = rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1, + r = rman_reserve_resource(vnet->gifunits, 0, GIF_MAXUNIT, 1, RF_ALLOCATED | RF_ACTIVE, NULL); if (r == NULL) return (ENOSPC); *unit = rman_get_start(r); } else { - r = rman_reserve_resource(gifunits, *unit, *unit, 1, + r = rman_reserve_resource(vnet->gifunits, *unit, *unit, 1, RF_ALLOCATED | RF_ACTIVE, NULL); if (r == NULL) return (EEXIST); @@ -202,6 +210,8 @@ struct gif_softc *sc = ifp->if_softc; struct vnet *vnet = ifp->if_vnet; + if (vnet == NULL) + panic("gif_clone_destroy: NULL vnet from ifp."); gif_delete_tunnel(&sc->gif_if); LIST_REMOVE(sc, gif_list); #ifdef INET6 @@ -226,31 +236,61 @@ free(sc, M_GIF); } +/* Initialize gif vars for a single vnet */ +int +gif_init(vnet) + struct vnet *vnet; +{ + int err=0; + + vnet->max_gif_nesting = MAX_GIF_NEST; + vnet->parallel_tunnels = 0; + vnet->gifunits->rm_type = RMAN_ARRAY; + vnet->gifunits->rm_descr = "configurable if_gif units"; + err = rman_init(vnet->gifunits); + if (err != 0) + return (err); + err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT); + if (err != 0) { + printf("%s: gifunits: rman_manage_region: Failed %d\n", + GIFNAME, err); + rman_fini(vnet->gifunits); + return (err); + } + LIST_INIT(&vnet->gif_softc_list); + + return 0; +} + static int gifmodevent(mod, type, data) module_t mod; int type; void *data; { - int err; + int err=0; struct vnet *vnet; switch (type) { case MOD_LOAD: - gifunits->rm_type = RMAN_ARRAY; - gifunits->rm_descr = "configurable if_gif units"; - err = rman_init(gifunits); + LIST_FOREACH(vnet, &vnet_head, vnet_le) + { + vnet->max_gif_nesting = MAX_GIF_NEST; + vnet->parallel_tunnels = 0; + vnet->gifunits->rm_type = RMAN_ARRAY; + vnet->gifunits->rm_descr = "configurable if_gif units"; + err = rman_init(vnet->gifunits); if (err != 0) return (err); - err = rman_manage_region(gifunits, 0, GIF_MAXUNIT); + err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT); if (err != 0) { printf("%s: gifunits: rman_manage_region: Failed %d\n", GIFNAME, err); - rman_fini(gifunits); + rman_fini(vnet->gifunits); return (err); } - LIST_FOREACH(vnet, &vnet_head, vnet_le) - LIST_INIT(&vnet->gif_softc_list); + LIST_INIT(&vnet->gif_softc_list); + } if_clone_attach(&gif_cloner); #ifdef INET6 @@ -261,11 +301,12 @@ case MOD_UNLOAD: if_clone_detach(&gif_cloner); - LIST_FOREACH(vnet, &vnet_head, vnet_le) + LIST_FOREACH(vnet, &vnet_head, vnet_le) { while (!LIST_EMPTY(&vnet->gif_softc_list)) gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if); + err = rman_fini(vnet->gifunits); + } - err = rman_fini(gifunits); if (err != 0) return (err); #ifdef INET6 @@ -295,6 +336,8 @@ struct ip ip; struct gif_softc *sc; + if (vnet == NULL) + panic("gif_encapcheck: NULL vnet was passed."); sc = (struct gif_softc *)arg; if (sc == NULL) return 0; @@ -358,6 +401,11 @@ struct gif_softc *sc = (struct gif_softc*)ifp; int error = 0; static int called = 0; /* XXX: MUTEX */ + struct vnet *vnet; + + vnet = ifp->if_vnet; + /*if (vnet == NULL) + panic("gif_output: cannot find vnet.");*/ /* * gif may cause infinite recursion calls when misconfigured. @@ -366,7 +414,7 @@ * mutual exclusion of the variable CALLED, especially if we * use kernel thread. */ - if (++called > max_gif_nesting) { + if (++called > vnet->max_gif_nesting) { log(LOG_NOTICE, "gif_output: recursively called too many times(%d)\n", called); @@ -441,13 +489,16 @@ int s, isr; struct p_ifqueue *p_ifq = NULL; struct ifqueue *ifq; - struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; + struct vnet *vnet; if (ifp == NULL) { /* just in case */ m_freem(m); return; } + vnet = ifp->if_vnet; + if (vnet == NULL) + panic("gif_input: NULL vnet was passed."); m->m_pkthdr.rcvif = ifp; @@ -779,6 +830,8 @@ int error = 0; struct vnet *vnet = sc->gif_vnet; + if (vnet == NULL) + panic("gif_set_tunnel: NULL vnet from sc->gif_vnet"); s = splnet(); LIST_FOREACH(sc2, &vnet->gif_softc_list, gif_list) { @@ -796,7 +849,7 @@ * Disallow parallel tunnels unless instructed * otherwise. */ - if (!parallel_tunnels && + if (!vnet->parallel_tunnels && bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { error = EADDRNOTAVAIL; diff -urN sys/net/if_gif.h sys.CORE/net/if_gif.h --- sys/net/if_gif.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/if_gif.h Wed Jan 31 16:02:43 2007 @@ -75,6 +75,7 @@ #define GIF_MTU_MAX (8192) /* Maximum MTU */ /* Prototypes */ +int gif_init(struct vnet *); void gifattach0 __P((struct gif_softc *)); void gif_input __P((struct mbuf *, int, struct ifnet *)); int gif_output __P((struct ifnet *, struct mbuf *, diff -urN sys/net/if_gre.c sys.CORE/net/if_gre.c --- sys/net/if_gre.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/if_gre.c Wed Jan 31 16:02:43 2007 @@ -97,10 +97,14 @@ #define GRE_MAXUNIT 0x7fff static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation"); +#ifdef MOVED_TO_VNET static struct rman greunits[1]; +#endif /* MOVED_TO_VNET */ -static int gre_clone_create(struct if_clone *, int *, struct vnet *); -static void gre_clone_destroy(struct ifnet *); +/*Boeing IDC static int gre_clone_create(struct if_clone *, int *, struct vnet *);*/ +/*Boeing IDC static void gre_clone_destroy(struct ifnet *);*/ +int gre_clone_create __P((struct if_clone *, int *, struct vnet *)); +void gre_clone_destroy __P((struct ifnet *)); static int gre_ioctl(struct ifnet *, u_long, caddr_t); static int gre_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *rt); @@ -144,9 +148,11 @@ */ #define MAX_GRE_NEST 1 #endif +#ifdef MOVED_TO_VNET static int max_gre_nesting = MAX_GRE_NEST; -SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW, - &max_gre_nesting, 0, "Max nested tunnels"); +#endif /* MOVED_TO_VNET */ +SYSCTL_V_INT(V_NET, _net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW, + v_max_gre_nesting, 0, "Max nested tunnels"); /* ARGSUSED */ static void @@ -167,17 +173,20 @@ struct resource *r; struct gre_softc *sc; + if (vnet == NULL) + panic("gre_clone_create: NULL vnet was passed."); + if (*unit > GRE_MAXUNIT) return (ENXIO); if (*unit < 0) { - r = rman_reserve_resource(greunits, 0, GRE_MAXUNIT, 1, + r = rman_reserve_resource(vnet->greunits, 0, GRE_MAXUNIT, 1, RF_ALLOCATED | RF_ACTIVE, NULL); if (r == NULL) return (ENOSPC); *unit = rman_get_start(r); } else { - r = rman_reserve_resource(greunits, *unit, *unit, 1, + r = rman_reserve_resource(vnet->greunits, *unit, *unit, 1, RF_ALLOCATED | RF_ACTIVE, NULL); if (r == NULL) return (EEXIST); @@ -211,12 +220,16 @@ return (0); } -static void +/*static*/ +void gre_clone_destroy(ifp) struct ifnet *ifp; { int err; struct gre_softc *sc = ifp->if_softc; + /*Boeing IDC copied from if_gif.c*/ + if (sc->g_vnet == NULL) + panic("gre_clone_destroy: NULL vnet from ifp."); #ifdef INET if (sc->encap != NULL) @@ -232,6 +245,37 @@ free(sc, M_GRE); } + +/*Boeing IDC*/ + +/* Initialize gif vars for a single vnet */ +int +gre_init(vnet) + struct vnet *vnet; +{ + int err=0; + + vnet->max_gre_nesting = MAX_GRE_NEST; + vnet->parallel_tunnels = 0; + vnet->greunits->rm_type = RMAN_ARRAY; + vnet->gifunits->rm_descr = "configurable if_gre units"; + err = rman_init(vnet->greunits); + if (err != 0) + return (err); + err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT); + if (err != 0) { + printf("%s: greunits: rman_manage_region: Failed %d\n", + GRENAME, err); + rman_fini(vnet->greunits); + return (err); + } + LIST_INIT(&vnet->gre_softc_list); + return 0; +} + + + + /* * The output routine. Takes a packet and encapsulates it in the protocol * given by sc->g_proto. See also RFC 1701 and RFC 2004 @@ -247,12 +291,14 @@ u_char osrc; u_short etype = 0; struct mobile_h mob_h; + struct vnet *vnet; + vnet = ifp->if_vnet; /* * gre may cause infinite recursion calls when misconfigured. * We'll prevent this by introducing upper limit. */ - if (++(sc->called) > max_gre_nesting) { + if (++(sc->called) > vnet->max_gre_nesting) { printf("%s: gre_output: recursively called too many " "times(%d)\n", if_name(&sc->sc_if), sc->called); m_freem(m); @@ -780,31 +826,33 @@ switch (type) { case MOD_LOAD: - greunits->rm_type = RMAN_ARRAY; - greunits->rm_descr = "configurable if_gre units"; - err = rman_init(greunits); + LIST_FOREACH(vnet, &vnet_head, vnet_le) + { + vnet->max_gre_nesting = MAX_GRE_NEST; + vnet->greunits->rm_type = RMAN_ARRAY; + vnet->greunits->rm_descr = "configurable if_gre units"; + err = rman_init(vnet->greunits); if (err != 0) return (err); - err = rman_manage_region(greunits, 0, GRE_MAXUNIT); + err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT); if (err != 0) { - printf("%s: greunits: rman_manage_region: Failed %d\n", - GRENAME, err); - rman_fini(greunits); - return (err); + printf("%s: greunits: rman_manage_region: Failed %d\n", + GRENAME, err); + rman_fini(vnet->greunits); + return (err); + } + greattach(vnet); } - - LIST_FOREACH(vnet, &vnet_head, vnet_le) - greattach(vnet); - break; case MOD_UNLOAD: if_clone_detach(&gre_cloner); - LIST_FOREACH(vnet, &vnet_head, vnet_le) + err = 0; + LIST_FOREACH(vnet, &vnet_head, vnet_le) { while (!LIST_EMPTY(&vnet->gre_softc_list)) gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if); - - err = rman_fini(greunits); + err += rman_fini(vnet->greunits); + } if (err != 0) return (err); diff -urN sys/net/if_gre.h sys.CORE/net/if_gre.h --- sys/net/if_gre.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/if_gre.h Wed Jan 31 16:02:43 2007 @@ -172,4 +172,7 @@ u_short gre_in_cksum(u_short *p, u_int len); #endif /* _KERNEL */ +/* Prototypes */ +int gre_init(struct vnet *); + #endif diff -urN sys/net/vnet.h sys.CORE/net/vnet.h --- sys/net/vnet.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/net/vnet.h Wed Jan 31 16:02:43 2007 @@ -83,6 +83,15 @@ #include #include +/* IPsec support */ +#include +#include +#include +#include +/* gif support */ +#include +#include + #ifdef _KERNEL int vi_if_move(struct vi_req *, struct ifnet *, struct vimage *); @@ -131,6 +140,7 @@ TAILQ_HEAD(dadq_head, dadq); +/**/ struct vnet { LIST_ENTRY(vnet) vnet_le; /* linked list of all vnets */ @@ -172,7 +182,8 @@ struct ifnet loif; /* from net/if_loop.c */ struct ifnet vipa; /* from net/if_loop.c */ - struct gre_softc_head gre_softc_list; + /*Boeing IDC struct gre_softc_head gre_softc_list;*/ + LIST_HEAD(, gre_softc) gre_softc_list; LIST_HEAD(, gif_softc) gif_softc_list; /* NETINET */ @@ -370,6 +381,8 @@ struct udpstat udpstat; /* from udp_usrreq.c */ struct icmpstat icmpstat; /* from ip_icmp.c */ struct igmpstat igmpstat; /* from igmp.c */ + struct pfkeystat pfkeystat; /* from keysock.c */ + struct _keystat { u_long getspi_count; } keystat; u_int rsvpdebug; /* from ip_mroute.c */ u_int mrtdebug; @@ -571,6 +584,67 @@ struct ip_fib_heap_entry ip_fib_heap[33]; int ip_fib_heap_index; + +/* gif tunneling interface stuff */ + /* + * from net/if_gif.c + */ + struct rman gifunits[1]; + int max_gif_nesting; + int parallel_tunnels; + /* + * from net/if_gre.c + */ + struct rman greunits[1]; + int max_gre_nesting; +/* IPsec stuff */ +/* Do not use #ifdef IPSEC here, or problems will occur! */ + /* + * from netkey/key.c + */ + u_int key_spi_trycnt; + u_int32_t key_spi_minval; + u_int32_t key_spi_maxval; + u_int32_t policy_id; + u_int key_int_random; /*interval to initialize randseed,1(m)*/ + u_int key_larval_lifetime; /* interval to expire acquiring, 30(s)*/ + int key_blockacq_count; /* counter for blocking SADB_ACQUIRE.*/ + int key_blockacq_lifetime; /* lifetime for blocking SADB_ACQUIRE.*/ + int key_preferred_oldsa; /* preferred old sa rather than new sa.*/ + u_int32_t acq_seq; + int key_tick_init_random; + LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ + LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ + LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; /* regd list*/ + LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ + LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ + struct key_cb key_cb; + + /* + * from netinet6/ipsec.c + */ + /* int ipsec_debug; stays in ipsec.c to avoid unnecessary passing + of vnet in simple functions that are printing */ + struct ipsecstat ipsecstat; + int ip4_ah_cleartos; + int ip4_ah_offsetmask; /* maybe IP_DF? */ + int ip4_ipsec_dfbit; /* DF bit on encap. 0: clear 1: set 2: copy */ + int ip4_esp_trans_deflev; + int ip4_esp_net_deflev; + int ip4_ah_trans_deflev; + int ip4_ah_net_deflev; + struct secpolicy ip4_def_policy; + int ip4_ipsec_ecn; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ + int ip4_esp_randpad; + struct ipsecstat ipsec6stat; + int ip6_esp_trans_deflev; + int ip6_esp_net_deflev; + int ip6_ah_trans_deflev; + int ip6_ah_net_deflev; + struct secpolicy ip6_def_policy; + int ip6_ipsec_ecn; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ + int ip6_esp_randpad; + }; /* @@ -827,7 +901,41 @@ #define v_rtq_reallyold6 offsetof(struct vnet, rtq_reallyold6) #define v_rtq_minreallyold6 offsetof(struct vnet, rtq_minreallyold6) #define v_rtq_toomany6 offsetof(struct vnet, rtq_toomany6) - +#define v_max_gif_nesting offsetof(struct vnet, max_gif_nesting) +#define v_parallel_tunnels offsetof(struct vnet, parallel_tunnels) +#define v_max_gre_nesting offsetof(struct vnet, max_gre_nesting) +#define v_key_debug_level offsetof(struct vnet, key_debug_level) +#define v_key_spi_trycnt offsetof(struct vnet, key_spi_trycnt) +#define v_key_spi_minval offsetof(struct vnet, key_spi_minval) +#define v_key_spi_maxval offsetof(struct vnet, key_spi_maxval) +#define v_policy_id offsetof(struct vnet, policy_id) +#define v_key_int_random offsetof(struct vnet, key_int_random) +#define v_key_larval_lifetime offsetof(struct vnet, key_larval_lifetime) +#define v_key_blockacq_count offsetof(struct vnet, key_blockacq_count) +#define v_key_blockacq_lifetime offsetof(struct vnet, key_blockacq_lifetime) +#define v_key_preferred_oldsa offsetof(struct vnet, key_preferred_oldsa) +#define v_acq_seq offsetof(struct vnet, acq_seq) +#define v_key_tick_init_random offsetof(struct vnet, key_tick_init_random) +#define v_key_cb offsetof(struct vnet, key_cb) +#define v_ipsecstat offsetof(struct vnet, ipsecstat) +#define v_ip4_ah_cleartos offsetof(struct vnet, ip4_ah_cleartos) +#define v_ip4_ah_offsetmask offsetof(struct vnet, ip4_ah_offsetmask) +#define v_ip4_ipsec_dfbit offsetof(struct vnet, ip4_ipsec_dfbit) +#define v_ip4_esp_trans_deflev offsetof(struct vnet, ip4_esp_trans_deflev) +#define v_ip4_esp_net_deflev offsetof(struct vnet, ip4_esp_net_deflev) +#define v_ip4_ah_trans_deflev offsetof(struct vnet, ip4_ah_trans_deflev) +#define v_ip4_ah_net_deflev offsetof(struct vnet, ip4_ah_net_deflev) +#define v_ip4_def_policy offsetof(struct vnet, ip4_def_policy) +#define v_ip4_ipsec_ecn offsetof(struct vnet, ip4_ipsec_ecn) +#define v_ip4_esp_randpad offsetof(struct vnet, ip4_esp_randpad) +#define v_ipsec6stat offsetof(struct vnet, ipsec6stat) +#define v_ip6_esp_trans_deflev offsetof(struct vnet, ip6_esp_trans_deflev) +#define v_ip6_esp_net_deflev offsetof(struct vnet, ip6_esp_net_deflev) +#define v_ip6_ah_trans_deflev offsetof(struct vnet, ip6_ah_trans_deflev) +#define v_ip6_ah_net_deflev offsetof(struct vnet, ip6_ah_net_deflev) +#define v_ip6_def_policy offsetof(struct vnet, ip6_def_policy) +#define v_ip6_ipsec_ecn offsetof(struct vnet, ip6_ipsec_ecn) +#define v_ip6_esp_randpad offsetof(struct vnet, ip6_esp_randpad) #endif _KERNEL diff -urN sys/netinet/ip_encap.c sys.CORE/netinet/ip_encap.c --- sys/netinet/ip_encap.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/ip_encap.c Wed Jan 31 16:02:43 2007 @@ -151,6 +151,7 @@ match = NULL; matchprio = 0; + for (ep = LIST_FIRST(&vnet->encaptab); ep; ep = LIST_NEXT(ep, chain)) { if (ep->af != AF_INET) continue; @@ -228,7 +229,7 @@ const struct ip6protosw *psw; struct encaptab *ep, *match; int prio, matchprio; - struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; + struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; ip6 = mtod(m, struct ip6_hdr *); @@ -378,7 +379,7 @@ encap_attach_func(af, proto, func, psw, arg, vnet) int af; int proto; - int (*func) __P((const struct mbuf *, int, int, void *)); + int (*func) __P((const struct mbuf *, int, int, void *, struct vnet *)); const struct protosw *psw; void *arg; struct vnet *vnet; @@ -450,6 +451,8 @@ u_int8_t *r; int matchlen; + char *inetadd; + if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) return 0; if (sp->sa_family != ep->af || dp->sa_family != ep->af) @@ -483,11 +486,24 @@ d.ss_len = dp->sa_len; d.ss_family = dp->sa_family; - if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && + if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) { return matchlen; - } else - return 0; + /*Boeing IDC MTUN IPv4 case*/ + } else if ((ep->src.ss_family == AF_INET) && + (IN_MULTICAST(ntohl(((struct sockaddr_in*)&ep->dst)->sin_addr.s_addr ))) && + (IN_MULTICAST(ntohl(((struct sockaddr_in*)sp)->sin_addr.s_addr ))) && + (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) { + return matchlen+1; + /*Boeing IDC MTUN IPv6 case*/ + } else if ((ep->src.ss_family == AF_INET6) && + (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)&ep->dst)->sin6_addr))) && + (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)sp)->sin6_addr))) && + (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) { + return matchlen+1; + } else { + return 0; + } } static void diff -urN sys/netinet/ip_encap.h sys.CORE/netinet/ip_encap.h --- sys/netinet/ip_encap.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/ip_encap.h Wed Jan 31 16:02:43 2007 @@ -57,7 +57,7 @@ const struct sockaddr *, const struct protosw *, void *, struct vnet *); const struct encaptab *encap_attach_func(int, int, - int (*)(const struct mbuf *, int, int, void *), + int (*)(const struct mbuf *, int, int, void *, struct vnet *), const struct protosw *, void *, struct vnet *); int encap_detach(const struct encaptab *, struct vnet *); void *encap_getarg(struct mbuf *); diff -urN sys/netinet/ip_icmp.c sys.CORE/netinet/ip_icmp.c --- sys/netinet/ip_icmp.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/ip_icmp.c Wed Jan 31 16:02:43 2007 @@ -600,7 +600,7 @@ (struct sockaddr *)&icmpgw, (struct rtentry **)0, vnet); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc, vnet); #ifdef IPSEC - key_sa_routechange((struct sockaddr *)&icmpsrc); + key_sa_routechange((struct sockaddr *)&icmpsrc, vnet); #endif break; diff -urN sys/netinet/ip_input.c sys.CORE/netinet/ip_input.c --- sys/netinet/ip_input.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/ip_input.c Wed Jan 31 16:02:43 2007 @@ -694,8 +694,8 @@ /* * Enforce inbound IPsec SPD. */ - if (ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; + if (ipsec4_in_reject(m, NULL, vnet)) { + vnet->ipsecstat.in_polvio++; goto bad; } #endif /* IPSEC */ @@ -903,8 +903,8 @@ * code - like udp/tcp/raw ip. */ if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; + ipsec4_in_reject(m, NULL, vnet)) { + vnet->ipsecstat.in_polvio++; goto bad; } #endif @@ -1970,7 +1970,7 @@ sp = ipsec4_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, IP_FORWARDING, - &ipsecerror); + &ipsecerror, vnet); if (sp == NULL) destifp = vnet->ipforward_rt.ro_rt->rt_ifp; @@ -1978,7 +1978,7 @@ /* count IPsec header size */ ipsechdr = ipsec4_hdrsiz(mcopy, IPSEC_DIR_OUTBOUND, - NULL); + NULL, vnet); /* * find the correct route for outer IPv4 @@ -2029,7 +2029,7 @@ /* count IPsec header size */ ipsechdr = ipsec4_hdrsiz(mcopy, IPSEC_DIR_OUTBOUND, - NULL); + NULL, vnet); /* * find the correct route for outer IPv4 diff -urN sys/netinet/ip_output.c sys.CORE/netinet/ip_output.c --- sys/netinet/ip_output.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/ip_output.c Wed Jan 31 16:02:43 2007 @@ -320,14 +320,22 @@ * See if the caller provided any multicast options */ if (imo != NULL) { - ip->ip_ttl = imo->imo_multicast_ttl; + /* Boeing IDC to handle divert re-injection + * If you don't want the TTL to be modified then + * set the multicast_ttl socket option to zero. + */ + if (imo->imo_multicast_ttl != 0){ + ip->ip_ttl = imo->imo_multicast_ttl; + } if (imo->imo_multicast_vif != -1) ip->ip_src.s_addr = ip_mcast_src ? ip_mcast_src(imo->imo_multicast_vif, vnet) : INADDR_ANY; - } else - ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; + } else { + ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; + } + /* * Confirm that the outgoing interface supports multicast. */ @@ -459,12 +467,12 @@ #ifdef IPSEC /* get SP for this packet */ if (so == NULL) - sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error); + sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error, vnet); else sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); if (sp == NULL) { - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; goto bad; } @@ -476,7 +484,7 @@ /* * This packet is just discarded. */ - ipsecstat.out_polvio++; + vnet->ipsecstat.out_polvio++; goto bad; case IPSEC_POLICY_BYPASS: diff -urN sys/netinet/raw_ip.c sys.CORE/netinet/raw_ip.c --- sys/netinet/raw_ip.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/raw_ip.c Wed Jan 31 16:02:43 2007 @@ -184,9 +184,9 @@ #ifdef IPSEC /* check AH/ESP integrity. */ - if (n && ipsec4_in_reject_so(n, last->inp_socket)) { + if (n && ipsec4_in_reject_so(n, last->inp_socket, vnet)) { m_freem(n); - ipsecstat.in_polvio++; + vnet->ipsecstat.in_polvio++; /* do not inject data to pcb */ } else #endif /*IPSEC*/ @@ -217,9 +217,9 @@ } #ifdef IPSEC /* check AH/ESP integrity. */ - if (last && ipsec4_in_reject_so(m, last->inp_socket)) { + if (last && ipsec4_in_reject_so(m, last->inp_socket, vnet)) { m_freem(m); - ipsecstat.in_polvio++; + vnet->ipsecstat.in_polvio++; vnet->ipstat.ips_delivered--; /* do not inject data to pcb */ } else diff -urN sys/netinet/tcp_input.c sys.CORE/netinet/tcp_input.c --- sys/netinet/tcp_input.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/tcp_input.c Wed Jan 31 16:02:43 2007 @@ -580,13 +580,15 @@ #ifdef IPSEC if (isipv6) { - if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) { - ipsec6stat.in_polvio++; +#ifdef INET6 + if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket, vnet)) { + vnet->ipsec6stat.in_polvio++; goto drop; } +#endif } else { - if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; + if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket, vnet)) { + vnet->ipsecstat.in_polvio++; goto drop; } } diff -urN sys/netinet/tcp_subr.c sys.CORE/netinet/tcp_subr.c --- sys/netinet/tcp_subr.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/tcp_subr.c Wed Jan 31 16:02:43 2007 @@ -1468,9 +1468,13 @@ struct ip6_hdr *ip6; #endif /* INET6 */ struct tcphdr *th; + struct vnet *vnet; if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL)) return 0; + vnet = tp->t_vnet; + if (vnet == NULL) + panic("ipsec_hdrsiz_tcp: NULL vnet was passed."); MGETHDR(m, M_DONTWAIT, MT_DATA); if (!m) return 0; @@ -1482,7 +1486,7 @@ m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); tcp_fillheaders(tp, ip6, th); - hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); + hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet); } else #endif /* INET6 */ { @@ -1490,7 +1494,7 @@ th = (struct tcphdr *)(ip + 1); m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr); tcp_fillheaders(tp, ip, th); - hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); + hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet); } m_free(m); diff -urN sys/netinet/udp_usrreq.c sys.CORE/netinet/udp_usrreq.c --- sys/netinet/udp_usrreq.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet/udp_usrreq.c Wed Jan 31 16:02:43 2007 @@ -325,8 +325,8 @@ #ifdef IPSEC /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) - ipsecstat.in_polvio++; + if (ipsec4_in_reject_so(m, last->inp_socket, vnet)) + vnet->ipsecstat.in_polvio++; /* do not inject data to pcb */ else #endif /*IPSEC*/ @@ -365,8 +365,8 @@ } #ifdef IPSEC /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) { - ipsecstat.in_polvio++; + if (ipsec4_in_reject_so(m, last->inp_socket, vnet)) { + vnet->ipsecstat.in_polvio++; goto bad; } #endif /*IPSEC*/ @@ -410,8 +410,8 @@ return; } #ifdef IPSEC - if (ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; + if (ipsec4_in_reject_so(m, inp->inp_socket, vnet)) { + vnet->ipsecstat.in_polvio++; goto bad; } #endif /*IPSEC*/ diff -urN sys/netinet6/ah.h sys.CORE/netinet6/ah.h --- sys/netinet6/ah.h Sat Apr 27 22:40:26 2002 +++ sys.CORE/netinet6/ah.h Wed Jan 31 16:02:43 2007 @@ -86,9 +86,9 @@ extern size_t ah_hdrsiz __P((struct ipsecrequest *)); extern void ah4_input __P((struct mbuf *, ...)); -extern int ah4_output __P((struct mbuf *, struct ipsecrequest *)); +extern int ah4_output __P((struct mbuf *, struct ipsecrequest *, struct vnet*)); extern int ah4_calccksum __P((struct mbuf *, caddr_t, size_t, - const struct ah_algorithm *, struct secasvar *)); + const struct ah_algorithm *, struct secasvar *, struct vnet *)); #endif /* _KERNEL */ #endif /* _NETINET6_AH_H_ */ diff -urN sys/netinet6/ah_core.c sys.CORE/netinet6/ah_core.c --- sys/netinet6/ah_core.c Sat Apr 27 22:40:26 2002 +++ sys.CORE/netinet6/ah_core.c Wed Jan 31 16:02:43 2007 @@ -52,6 +52,7 @@ #include #include +#include #include #include @@ -1181,12 +1182,13 @@ * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. */ int -ah4_calccksum(m, ahdat, len, algo, sav) +ah4_calccksum(m, ahdat, len, algo, sav, vnet) struct mbuf *m; caddr_t ahdat; size_t len; const struct ah_algorithm *algo; struct secasvar *sav; + struct vnet *vnet; { int off; int hdrtype; @@ -1200,6 +1202,9 @@ if ((m->m_flags & M_PKTHDR) == 0) return EINVAL; + if (vnet == NULL) + panic("ah4_calccksum: NULL vnet was passed."); + ahseen = 0; hdrtype = -1; /* dummy, it is called IPPROTO_IP */ @@ -1231,9 +1236,9 @@ #endif iphdr.ip_ttl = 0; iphdr.ip_sum = htons(0); - if (ip4_ah_cleartos) + if (vnet->ip4_ah_cleartos) iphdr.ip_tos = 0; - iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask); + iphdr.ip_off = htons(ntohs(iphdr.ip_off) & vnet->ip4_ah_offsetmask); (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip)); if (hlen != sizeof(struct ip)) { diff -urN sys/netinet6/ah_input.c sys.CORE/netinet6/ah_input.c --- sys/netinet6/ah_input.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ah_input.c Wed Jan 31 16:02:43 2007 @@ -87,6 +87,8 @@ #define KEYDEBUG(lev,arg) #endif +#include + #include #include @@ -120,19 +122,25 @@ int off, proto; va_list ap; size_t stripsiz = 0; + struct vnet *vnet; va_start(ap, m); off = va_arg(ap, int); proto = va_arg(ap, int); va_end(ap); + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ah4_input: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; + if (vnet == NULL) + panic("ah4_input: NULL vnet passed."); #ifndef PULLDOWN_TEST if (m->m_len < off + sizeof(struct newah)) { m = m_pullup(m, off + sizeof(struct newah)); if (!m) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" "dropping the packet for simplicity\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } } @@ -145,7 +153,7 @@ if (ah == NULL) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" "dropping the packet for simplicity\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } #endif @@ -161,11 +169,11 @@ if ((sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, - IPPROTO_AH, spi)) == 0) { + IPPROTO_AH, spi, vnet)) == 0) { ipseclog((LOG_WARNING, "IPv4 AH input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_nosa++; + vnet->ipsecstat.in_nosa++; goto fail; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, @@ -175,7 +183,7 @@ ipseclog((LOG_DEBUG, "IPv4 AH input: non-mature/dying SA found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; + vnet->ipsecstat.in_badspi++; goto fail; } @@ -184,7 +192,7 @@ ipseclog((LOG_DEBUG, "IPv4 AH input: " "unsupported authentication algorithm for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; + vnet->ipsecstat.in_badspi++; goto fail; } @@ -225,7 +233,7 @@ "(%lu, should be at least %lu): %s\n", (u_long)siz1, (u_long)siz, ipsec4_logpacketstr(ip, spi))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } if ((ah->ah_len << 2) - sizoff != siz1) { @@ -233,7 +241,7 @@ "(%d should be %lu): %s\n", (ah->ah_len << 2) - sizoff, (u_long)siz1, ipsec4_logpacketstr(ip, spi))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } @@ -242,7 +250,7 @@ m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1); if (!m) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } @@ -254,7 +262,7 @@ sizeof(struct ah) + sizoff + siz1); if (ah == NULL) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } #endif @@ -267,7 +275,7 @@ if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) ; /* okey */ else { - ipsecstat.in_ahreplay++; + vnet->ipsecstat.in_ahreplay++; ipseclog((LOG_WARNING, "replay packet in IPv4 AH input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); @@ -283,7 +291,7 @@ if (!cksum) { ipseclog((LOG_DEBUG, "IPv4 AH input: " "couldn't alloc temporary region for cksum\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } @@ -293,12 +301,12 @@ */ ip->ip_len = htons(ip->ip_len + hlen); ip->ip_off = htons(ip->ip_off); - if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { + if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav, vnet)) { free(cksum, M_TEMP); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } - ipsecstat.in_ahhist[sav->alg_auth]++; + vnet->ipsecstat.in_ahhist[sav->alg_auth]++; /* * flip them back. */ @@ -321,7 +329,7 @@ "checksum mismatch in IPv4 AH input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); free(cksum, M_TEMP); - ipsecstat.in_ahauthfail++; + vnet->ipsecstat.in_ahauthfail++; goto fail; } } @@ -374,12 +382,12 @@ ipseclog((LOG_DEBUG, "IPv4 AH input: authentication succeess\n")); #endif - ipsecstat.in_ahauthsucc++; + vnet->ipsecstat.in_ahauthsucc++; } else { ipseclog((LOG_WARNING, "authentication failed in IPv4 AH input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_ahauthfail++; + vnet->ipsecstat.in_ahauthfail++; goto fail; } @@ -388,7 +396,7 @@ */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { - ipsecstat.in_ahreplay++; + vnet->ipsecstat.in_ahreplay++; goto fail; } } @@ -416,19 +424,19 @@ if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (!m) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } } ip = mtod(m, struct ip *); /* ECN consideration. */ - ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); + ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos); if (!key_checktunnelsanity(sav, AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " "in IPv4 AH input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } @@ -459,13 +467,13 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; goto fail; } s = splimp(); if (IF_QFULL(&g_ipintrq)) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; splx(s); goto fail; } @@ -521,7 +529,7 @@ if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (m == NULL) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } } @@ -536,14 +544,14 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; goto fail; } if (nxt != IPPROTO_DONE) { if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; + ipsec4_in_reject(m, NULL, vnet)) { + vnet->ipsecstat.in_polvio++; goto fail; } (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); @@ -557,7 +565,7 @@ printf("DP ah4_input call free SA:%p\n", sav)); key_freesav(sav); } - ipsecstat.in_success++; + vnet->ipsecstat.in_success++; return; fail: @@ -591,7 +599,12 @@ u_int16_t nxt; int s; size_t stripsiz = 0; + struct vnet *vnet; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ah6_input: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; + if (vnet == NULL) #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE); ah = (struct ah *)(mtod(m, caddr_t) + off); @@ -599,7 +612,7 @@ IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah)); if (ah == NULL) { ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; return IPPROTO_DONE; } #endif @@ -612,17 +625,17 @@ if (ntohs(ip6->ip6_plen) == 0) { ipseclog((LOG_ERR, "IPv6 AH input: " "AH with IPv6 jumbogram is not supported.\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } if ((sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, - IPPROTO_AH, spi)) == 0) { + IPPROTO_AH, spi, vnet)) == 0) { ipseclog((LOG_WARNING, "IPv6 AH input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsec6stat.in_nosa++; + vnet->ipsec6stat.in_nosa++; goto fail; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, @@ -632,7 +645,7 @@ ipseclog((LOG_DEBUG, "IPv6 AH input: non-mature/dying SA found for spi %u; ", (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; + vnet->ipsec6stat.in_badspi++; goto fail; } @@ -641,7 +654,7 @@ ipseclog((LOG_DEBUG, "IPv6 AH input: " "unsupported authentication algorithm for spi %u\n", (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; + vnet->ipsec6stat.in_badspi++; goto fail; } @@ -665,7 +678,7 @@ "(%lu, should be at least %lu): %s\n", (u_long)siz1, (u_long)siz, ipsec6_logpacketstr(ip6, spi))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } if ((ah->ah_len << 2) - sizoff != siz1) { @@ -673,7 +686,7 @@ "(%d should be %lu): %s\n", (ah->ah_len << 2) - sizoff, (u_long)siz1, ipsec6_logpacketstr(ip6, spi))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } #ifndef PULLDOWN_TEST @@ -683,7 +696,7 @@ sizeof(struct ah) + sizoff + siz1); if (ah == NULL) { ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; m = NULL; goto fail; } @@ -697,7 +710,7 @@ if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) ; /* okey */ else { - ipsec6stat.in_ahreplay++; + vnet->ipsec6stat.in_ahreplay++; ipseclog((LOG_WARNING, "replay packet in IPv6 AH input: %s %s\n", ipsec6_logpacketstr(ip6, spi), @@ -714,16 +727,16 @@ if (!cksum) { ipseclog((LOG_DEBUG, "IPv6 AH input: " "couldn't alloc temporary region for cksum\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } if (ah6_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { free(cksum, M_TEMP); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } - ipsec6stat.in_ahhist[sav->alg_auth]++; + vnet->ipsec6stat.in_ahhist[sav->alg_auth]++; { caddr_t sumpos = NULL; @@ -741,7 +754,7 @@ "checksum mismatch in IPv6 AH input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); free(cksum, M_TEMP); - ipsec6stat.in_ahauthfail++; + vnet->ipsec6stat.in_ahauthfail++; goto fail; } } @@ -786,12 +799,12 @@ ipseclog((LOG_DEBUG, "IPv6 AH input: authentication succeess\n")); #endif - ipsec6stat.in_ahauthsucc++; + vnet->ipsec6stat.in_ahauthsucc++; } else { ipseclog((LOG_WARNING, "authentication failed in IPv6 AH input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_ahauthfail++; + vnet->ipsec6stat.in_ahauthfail++; goto fail; } @@ -800,7 +813,7 @@ */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { - ipsec6stat.in_ahreplay++; + vnet->ipsec6stat.in_ahreplay++; goto fail; } } @@ -832,20 +845,20 @@ */ m = m_pullup(m, sizeof(*ip6)); if (!m) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } } ip6 = mtod(m, struct ip6_hdr *); /* ECN consideration. */ - ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); + ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); if (!key_checktunnelsanity(sav, AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " "in IPv6 AH input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } @@ -861,17 +874,17 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; goto fail; } s = splimp(); - if (IF_QFULL(&ip6intrq)) { - ipsec6stat.in_inval++; + if (IF_QFULL(&g_ip6intrq)) { + vnet->ipsec6stat.in_inval++; splx(s); goto fail; } - IF_ENQUEUE(&ip6intrq, m); + IF_ENQUEUE(&g_ip6intrq, m); m = NULL; schednetisr(NETISR_IPV6); /* can be skipped but to make sure */ splx(s); @@ -934,7 +947,7 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; goto fail; } } @@ -947,7 +960,7 @@ printf("DP ah6_input call free SA:%p\n", sav)); key_freesav(sav); } - ipsec6stat.in_success++; + vnet->ipsec6stat.in_success++; return nxt; fail: @@ -972,6 +985,7 @@ struct secasvar *sav; struct ip6_hdr *ip6; struct mbuf *m; + struct vnet *vnet = NULL; struct ip6ctlparam *ip6cp = NULL; int off; struct sockaddr_in6 *sa6_src, *sa6_dst; @@ -986,11 +1000,15 @@ if (d != NULL) { ip6cp = (struct ip6ctlparam *)d; m = ip6cp->ip6c_m; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ah6_ctlinput: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; } else { m = NULL; ip6 = NULL; + off = 0; } if (ip6) { @@ -1025,7 +1043,7 @@ sav = key_allocsa(AF_INET6, (caddr_t)&sa6_src->sin6_addr, (caddr_t)&sa6_dst->sin6_addr, - IPPROTO_AH, ahp->ah_spi); + IPPROTO_AH, ahp->ah_spi, vnet); if (sav) { if (sav->state == SADB_SASTATE_MATURE || sav->state == SADB_SASTATE_DYING) @@ -1042,7 +1060,7 @@ * corresponding routing entry, or * - ignore the MTU change notification. */ - icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); + icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet); } /* we normally notify single pcb here */ diff -urN sys/netinet6/ah_output.c sys.CORE/netinet6/ah_output.c --- sys/netinet6/ah_output.c Mon May 5 23:46:58 2003 +++ sys.CORE/netinet6/ah_output.c Wed Jan 31 16:02:43 2007 @@ -75,6 +75,7 @@ #include #include +#include #ifdef INET static struct in_addr *ah4_finaldst __P((struct mbuf *)); @@ -142,9 +143,10 @@ * the function does not modify m. */ int -ah4_output(m, isr) +ah4_output(m, isr, vnet) struct mbuf *m; struct ipsecrequest *isr; + struct vnet *vnet; { struct secasvar *sav = isr->sav; const struct ah_algorithm *algo; @@ -159,6 +161,8 @@ struct in_addr *finaldst; int error; + if (vnet == NULL) + panic("ah4_output: NULL vnet was passed."); /* sanity checks */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { struct ip *ip; @@ -169,7 +173,7 @@ (u_int32_t)ntohl(ip->ip_src.s_addr), (u_int32_t)ntohl(ip->ip_dst.s_addr), (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); return EINVAL; } @@ -178,7 +182,7 @@ if (!algo) { ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: " "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); return EINVAL; } @@ -260,7 +264,7 @@ ipseclog((LOG_WARNING, "replay counter overflowed. %s\n", ipsec_logsastr(sav))); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); return EINVAL; } @@ -282,7 +286,7 @@ ip->ip_len = htons(ntohs(ip->ip_len) + ahlen); else { ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); return EMSGSIZE; } @@ -304,13 +308,13 @@ * calcurate the checksum, based on security association * and the algorithm specified. */ - error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); + error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav, vnet); if (error) { ipseclog((LOG_ERR, "error after ah4_calccksum, called from ah4_output")); m_freem(m); m = NULL; - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; return error; } @@ -318,8 +322,8 @@ ip = mtod(m, struct ip *); /* just to make sure */ ip->ip_dst.s_addr = dst.s_addr; } - ipsecstat.out_success++; - ipsecstat.out_ahhist[sav->alg_auth]++; + vnet->ipsecstat.out_success++; + vnet->ipsecstat.out_ahhist[sav->alg_auth]++; key_sa_recordxfer(sav, m); return 0; @@ -371,6 +375,11 @@ int error = 0; int ahlen; struct ip6_hdr *ip6; + struct vnet *vnet; + + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ah6_output: unable to find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; if (m->m_len < sizeof(struct ip6_hdr)) { ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n")); @@ -422,7 +431,7 @@ ipseclog((LOG_DEBUG, "ah6_output: internal error: " "sav->replay is null: SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; m_freem(m); return EINVAL; } @@ -431,7 +440,7 @@ if (!algo) { ipseclog((LOG_ERR, "ah6_output: unsupported algorithm: " "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; m_freem(m); return EINVAL; } @@ -467,7 +476,7 @@ ipseclog((LOG_WARNING, "replay counter overflowed. %s\n", ipsec_logsastr(sav))); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; m_freem(m); return EINVAL; } @@ -487,13 +496,13 @@ */ error = ah6_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); if (error) { - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; m_freem(m); } else { - ipsec6stat.out_success++; + vnet->ipsec6stat.out_success++; key_sa_recordxfer(sav, m); } - ipsec6stat.out_ahhist[sav->alg_auth]++; + vnet->ipsec6stat.out_ahhist[sav->alg_auth]++; return(error); } diff -urN sys/netinet6/esp.h sys.CORE/netinet6/esp.h --- sys/netinet6/esp.h Sat Apr 27 22:40:26 2002 +++ sys.CORE/netinet6/esp.h Wed Jan 31 16:02:43 2007 @@ -97,7 +97,8 @@ extern int esp_max_ivlen __P((void)); /* crypt routines */ -extern int esp4_output __P((struct mbuf *, struct ipsecrequest *)); +extern int esp4_output __P((struct mbuf *, struct ipsecrequest *, + struct vnet *vnet)); extern void esp4_input __P((struct mbuf *, ...)); extern size_t esp_hdrsiz __P((struct ipsecrequest *)); diff -urN sys/netinet6/esp6.h sys.CORE/netinet6/esp6.h --- sys/netinet6/esp6.h Tue Jul 3 04:01:49 2001 +++ sys.CORE/netinet6/esp6.h Wed Jan 31 16:02:43 2007 @@ -39,10 +39,10 @@ #ifdef _KERNEL extern int esp6_output __P((struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *)); + struct ipsecrequest *, struct vnet *)); extern int esp6_input __P((struct mbuf **, int *, int)); -extern void esp6_ctlinput __P((int, struct sockaddr *, void *)); +extern void esp6_ctlinput __P((int, struct sockaddr *, void *, struct vnet *)); #endif /*_KERNEL*/ #endif /*_NETINET6_ESP6_H_*/ diff -urN sys/netinet6/esp_input.c sys.CORE/netinet6/esp_input.c --- sys/netinet6/esp_input.c Fri Nov 28 06:52:52 2003 +++ sys.CORE/netinet6/esp_input.c Wed Jan 31 16:02:43 2007 @@ -89,6 +89,7 @@ #include #include +#include #define IPLEN_FLIPPED @@ -123,17 +124,21 @@ int s; va_list ap; int off, proto; + struct vnet *vnet; va_start(ap, m); off = va_arg(ap, int); proto = va_arg(ap, int); va_end(ap); + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("esp4_input: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; /* sanity check for alignment. */ if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem " "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -142,7 +147,7 @@ if (!m) { ipseclog((LOG_DEBUG, "IPv4 ESP input: can't pullup in esp4_input\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } } @@ -160,11 +165,11 @@ if ((sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, - IPPROTO_ESP, spi)) == 0) { + IPPROTO_ESP, spi, vnet)) == 0) { ipseclog((LOG_WARNING, "IPv4 ESP input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_nosa++; + vnet->ipsecstat.in_nosa++; goto bad; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, @@ -174,7 +179,7 @@ ipseclog((LOG_DEBUG, "IPv4 ESP input: non-mature/dying SA found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; + vnet->ipsecstat.in_badspi++; goto bad; } algo = esp_algorithm_lookup(sav->alg_enc); @@ -182,7 +187,7 @@ ipseclog((LOG_DEBUG, "IPv4 ESP input: " "unsupported encryption algorithm for spi %u\n", (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; + vnet->ipsecstat.in_badspi++; goto bad; } @@ -191,7 +196,7 @@ if (ivlen < 0) { ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -209,7 +214,7 @@ if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) ; /* okey */ else { - ipsecstat.in_espreplay++; + vnet->ipsecstat.in_espreplay++; ipseclog((LOG_WARNING, "replay packet in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); @@ -228,14 +233,14 @@ goto noreplaycheck; siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } if (AH_MAXSUMSIZE < siz) { ipseclog((LOG_DEBUG, "internal error: AH_MAXSUMSIZE must be larger than %lu\n", (u_long)siz)); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -244,14 +249,14 @@ if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_espauthfail++; + vnet->ipsecstat.in_espauthfail++; goto bad; } if (bcmp(sum0, sum, siz) != 0) { ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_espauthfail++; + vnet->ipsecstat.in_espauthfail++; goto bad; } @@ -264,7 +269,7 @@ ip->ip_len = htons(ntohs(ip->ip_len) - siz); #endif m->m_flags |= M_AUTHIPDGM; - ipsecstat.in_espauthsucc++; + vnet->ipsecstat.in_espauthsucc++; } /* @@ -272,7 +277,7 @@ */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { - ipsecstat.in_espreplay++; + vnet->ipsecstat.in_espreplay++; goto bad; } } @@ -294,7 +299,7 @@ if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { ipseclog((LOG_WARNING, "IPv4 ESP input: packet too short\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -303,7 +308,7 @@ if (!m) { ipseclog((LOG_DEBUG, "IPv4 ESP input: can't pullup in esp4_input\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } } @@ -312,7 +317,7 @@ * pre-compute and cache intermediate key */ if (esp_schedule(algo, sav) != 0) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -326,10 +331,10 @@ m = NULL; ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n", ipsec_logsastr(sav))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } - ipsecstat.in_esphist[sav->alg_enc]++; + vnet->ipsecstat.in_esphist[sav->alg_enc]++; m->m_flags |= M_DECRYPTED; @@ -346,7 +351,7 @@ ipseclog((LOG_WARNING, "bad pad length in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } @@ -375,36 +380,36 @@ if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (!m) { - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } } ip = mtod(m, struct ip *); /* ECN consideration. */ - ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); + ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos); if (!key_checktunnelsanity(sav, AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { ipseclog((LOG_ERR, "ipsec tunnel address mismatch " "in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto bad; } key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; goto bad; } s = splimp(); - if (IF_QFULL(&ipintrq)) { - ipsecstat.in_inval++; + if (IF_QFULL(&g_ipintrq)) { + vnet->ipsecstat.in_inval++; splx(s); goto bad; } - IF_ENQUEUE(&ipintrq, m); + IF_ENQUEUE(&g_ipintrq, m); m = NULL; schednetisr(NETISR_IP); /* can be skipped but to make sure */ splx(s); @@ -435,14 +440,14 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; goto bad; } if (nxt != IPPROTO_DONE) { if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; + ipsec4_in_reject(m, NULL, vnet)) { + vnet->ipsecstat.in_polvio++; goto bad; } (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); @@ -456,7 +461,7 @@ printf("DP esp4_input call free SA:%p\n", sav)); key_freesav(sav); } - ipsecstat.in_success++; + vnet->ipsecstat.in_success++; return; bad: @@ -478,6 +483,7 @@ int *offp, proto; { struct mbuf *m = *mp; + struct vnet *vnet; int off = *offp; struct ip6_hdr *ip6; struct esp *esp; @@ -491,11 +497,14 @@ size_t esplen; int s; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("esp6_input: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; /* sanity check for alignment. */ if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem " "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -505,7 +514,7 @@ #else IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN); if (esp == NULL) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; return IPPROTO_DONE; } #endif @@ -514,7 +523,7 @@ if (ntohs(ip6->ip6_plen) == 0) { ipseclog((LOG_ERR, "IPv6 ESP input: " "ESP with IPv6 jumbogram is not supported.\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -523,11 +532,11 @@ if ((sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, - IPPROTO_ESP, spi)) == 0) { + IPPROTO_ESP, spi, vnet)) == 0) { ipseclog((LOG_WARNING, "IPv6 ESP input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsec6stat.in_nosa++; + vnet->ipsec6stat.in_nosa++; goto bad; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, @@ -537,7 +546,7 @@ ipseclog((LOG_DEBUG, "IPv6 ESP input: non-mature/dying SA found for spi %u\n", (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; + vnet->ipsec6stat.in_badspi++; goto bad; } algo = esp_algorithm_lookup(sav->alg_enc); @@ -545,7 +554,7 @@ ipseclog((LOG_DEBUG, "IPv6 ESP input: " "unsupported encryption algorithm for spi %u\n", (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; + vnet->ipsec6stat.in_badspi++; goto bad; } @@ -554,7 +563,7 @@ if (ivlen < 0) { ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_badspi++; + vnet->ipsec6stat.in_badspi++; goto bad; } @@ -572,7 +581,7 @@ if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) ; /* okey */ else { - ipsec6stat.in_espreplay++; + vnet->ipsec6stat.in_espreplay++; ipseclog((LOG_WARNING, "replay packet in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); @@ -591,14 +600,14 @@ goto noreplaycheck; siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } if (AH_MAXSUMSIZE < siz) { ipseclog((LOG_DEBUG, "internal error: AH_MAXSUMSIZE must be larger than %lu\n", (u_long)siz)); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -607,14 +616,14 @@ if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_espauthfail++; + vnet->ipsec6stat.in_espauthfail++; goto bad; } if (bcmp(sum0, sum, siz) != 0) { ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_espauthfail++; + vnet->ipsec6stat.in_espauthfail++; goto bad; } @@ -624,7 +633,7 @@ ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz); m->m_flags |= M_AUTHIPDGM; - ipsec6stat.in_espauthsucc++; + vnet->ipsec6stat.in_espauthsucc++; } /* @@ -632,7 +641,7 @@ */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { - ipsec6stat.in_espreplay++; + vnet->ipsec6stat.in_espreplay++; goto bad; } } @@ -654,7 +663,7 @@ if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { ipseclog((LOG_WARNING, "IPv6 ESP input: packet too short\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -663,7 +672,7 @@ #else IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen); if (esp == NULL) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; m = NULL; goto bad; } @@ -674,7 +683,7 @@ * pre-compute and cache intermediate key */ if (esp_schedule(algo, sav) != 0) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -688,10 +697,10 @@ m = NULL; ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n", ipsec_logsastr(sav))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } - ipsec6stat.in_esphist[sav->alg_enc]++; + vnet->ipsec6stat.in_esphist[sav->alg_enc]++; m->m_flags |= M_DECRYPTED; @@ -708,7 +717,7 @@ ipseclog((LOG_WARNING, "bad pad length in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } @@ -740,37 +749,37 @@ #endif m = m_pullup(m, sizeof(*ip6)); if (!m) { - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } } ip6 = mtod(m, struct ip6_hdr *); /* ECN consideration. */ - ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); + ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); if (!key_checktunnelsanity(sav, AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { ipseclog((LOG_ERR, "ipsec tunnel address mismatch " "in IPv6 ESP input: %s %s\n", ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto bad; } key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; goto bad; } s = splimp(); - if (IF_QFULL(&ip6intrq)) { - ipsec6stat.in_inval++; + if (IF_QFULL(&g_ip6intrq)) { + vnet->ipsec6stat.in_inval++; splx(s); goto bad; } - IF_ENQUEUE(&ip6intrq, m); + IF_ENQUEUE(&g_ip6intrq, m); m = NULL; schednetisr(NETISR_IPV6); /* can be skipped but to make sure */ splx(s); @@ -864,7 +873,7 @@ key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; goto bad; } } @@ -877,7 +886,7 @@ printf("DP esp6_input call free SA:%p\n", sav)); key_freesav(sav); } - ipsec6stat.in_success++; + vnet->ipsec6stat.in_success++; return nxt; bad: @@ -892,10 +901,11 @@ } void -esp6_ctlinput(cmd, sa, d) +esp6_ctlinput(cmd, sa, d, vnet) int cmd; struct sockaddr *sa; void *d; + struct vnet *vnet; { const struct newesp *espp; struct newesp esp; @@ -906,6 +916,8 @@ int off; struct sockaddr_in6 *sa6_src, *sa6_dst; + if (vnet == NULL) + panic("esp6_ctlinput: NULL vnet was passed."); if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) return; @@ -921,6 +933,7 @@ } else { m = NULL; ip6 = NULL; + off = 0; } if (ip6) { @@ -939,7 +952,7 @@ */ bzero(&ip6cp1, sizeof(ip6cp1)); ip6cp1.ip6c_src = ip6cp->ip6c_src; - pfctlinput2(cmd, sa, (void *)&ip6cp1); + pfctlinput2(cmd, sa, (void *)&ip6cp1, vnet); /* * Then go to special cases that need ESP header information. @@ -973,7 +986,7 @@ sav = key_allocsa(AF_INET6, (caddr_t)&sa6_src->sin6_addr, (caddr_t)&sa6_dst->sin6_addr, - IPPROTO_ESP, espp->esp_spi); + IPPROTO_ESP, espp->esp_spi, vnet); if (sav) { if (sav->state == SADB_SASTATE_MATURE || sav->state == SADB_SASTATE_DYING) @@ -990,7 +1003,7 @@ * corresponding routing entry, or * - ignore the MTU change notification. */ - icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); + icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet); } } else { /* we normally notify any pcb here */ diff -urN sys/netinet6/esp_output.c sys.CORE/netinet6/esp_output.c --- sys/netinet6/esp_output.c Fri Nov 28 06:54:26 2003 +++ sys.CORE/netinet6/esp_output.c Wed Jan 31 16:02:43 2007 @@ -78,9 +78,10 @@ #include #include +#include static int esp_output __P((struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *, int)); + struct ipsecrequest *, int, struct vnet *)); /* * compute ESP header size. @@ -174,12 +175,13 @@ * <-----------------> espoff */ static int -esp_output(m, nexthdrp, md, isr, af) +esp_output(m, nexthdrp, md, isr, af, vnet) struct mbuf *m; u_char *nexthdrp; struct mbuf *md; struct ipsecrequest *isr; int af; + struct vnet *vnet; { struct mbuf *n; struct mbuf *mprev; @@ -197,17 +199,19 @@ int error = 0; struct ipsecstat *stat; + if (vnet == NULL) + panic("esp6_output: NULL vnet was passed."); switch (af) { #ifdef INET case AF_INET: afnumber = 4; - stat = &ipsecstat; + stat = &vnet->ipsecstat; break; #endif #ifdef INET6 case AF_INET6: afnumber = 6; - stat = &ipsec6stat; + stat = &vnet->ipsec6stat; break; #endif default: @@ -229,7 +233,7 @@ (u_int32_t)ntohl(ip->ip_src.s_addr), (u_int32_t)ntohl(ip->ip_dst.s_addr), (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; break; } #endif /* INET */ @@ -238,7 +242,7 @@ ipseclog((LOG_DEBUG, "esp6_output: internal error: " "sav->replay is null: SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; break; #endif /* INET6 */ default: @@ -368,7 +372,7 @@ else { ipseclog((LOG_ERR, "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); error = EMSGSIZE; goto fail; @@ -435,12 +439,12 @@ switch (af) { #ifdef INET case AF_INET: - randpadmax = ip4_esp_randpad; + randpadmax = vnet->ip4_esp_randpad; break; #endif #ifdef INET6 case AF_INET6: - randpadmax = ip6_esp_randpad; + randpadmax = vnet->ip6_esp_randpad; break; #endif default: @@ -539,7 +543,7 @@ else { ipseclog((LOG_ERR, "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); error = EMSGSIZE; goto fail; @@ -651,7 +655,7 @@ else { ipseclog((LOG_ERR, "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); error = EMSGSIZE; goto fail; @@ -686,9 +690,10 @@ #ifdef INET int -esp4_output(m, isr) +esp4_output(m, isr, vnet) struct mbuf *m; struct ipsecrequest *isr; + struct vnet *vnet; { struct ip *ip; if (m->m_len < sizeof(struct ip)) { @@ -698,23 +703,24 @@ } ip = mtod(m, struct ip *); /* XXX assumes that m->m_next points to payload */ - return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET); + return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET, vnet); } #endif /* INET */ #ifdef INET6 int -esp6_output(m, nexthdrp, md, isr) +esp6_output(m, nexthdrp, md, isr, vnet) struct mbuf *m; u_char *nexthdrp; struct mbuf *md; struct ipsecrequest *isr; + struct vnet *vnet; { if (m->m_len < sizeof(struct ip6_hdr)) { ipseclog((LOG_DEBUG, "esp6_output: first mbuf too short\n")); m_freem(m); return 0; } - return esp_output(m, nexthdrp, md, isr, AF_INET6); + return esp_output(m, nexthdrp, md, isr, AF_INET6, vnet); } #endif /* INET6 */ diff -urN sys/netinet6/icmp6.c sys.CORE/netinet6/icmp6.c --- sys/netinet6/icmp6.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/icmp6.c Wed Jan 31 16:02:43 2007 @@ -2416,7 +2416,7 @@ bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst, vnet); #ifdef IPSEC - key_sa_routechange((struct sockaddr *)&sdst); + key_sa_routechange((struct sockaddr *)&sdst, vnet); #endif } diff -urN sys/netinet6/in6_ifattach.c sys.CORE/netinet6/in6_ifattach.c --- sys/netinet6/in6_ifattach.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/in6_ifattach.c Wed Jan 31 16:02:43 2007 @@ -1032,6 +1032,8 @@ bzero(nullbuf, sizeof(nullbuf)); for (i = 1; i < vnet->if_index + 1; i++) { + if (vnet->nd_ifinfo == NULL) /* nd6 not initialized yet! */ + continue; ndi = &vnet->nd_ifinfo[i]; if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { /* diff -urN sys/netinet6/in6_proto.c sys.CORE/netinet6/in6_proto.c --- sys/netinet6/in6_proto.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/in6_proto.c Wed Jan 31 16:02:43 2007 @@ -209,7 +209,7 @@ #ifdef IPSEC { SOCK_RAW, &inet6domain, IPPROTO_AH, PR_ATOMIC|PR_ADDR, ah6_input, 0, 0, 0, - 0, + 0, 0, 0, 0, 0, 0, &nousrreqs, }, @@ -218,14 +218,14 @@ esp6_input, 0, esp6_ctlinput, 0, - 0, + 0, 0, 0, 0, 0, 0, &nousrreqs, }, #endif { SOCK_RAW, &inet6domain, IPPROTO_IPCOMP, PR_ATOMIC|PR_ADDR, ipcomp6_input, 0, 0, 0, - 0, + 0, 0, 0, 0, 0, 0, &nousrreqs, }, diff -urN sys/netinet6/ip6_forward.c sys.CORE/netinet6/ip6_forward.c --- sys/netinet6/ip6_forward.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ip6_forward.c Wed Jan 31 16:02:43 2007 @@ -122,9 +122,9 @@ * Don't increment ip6s_cantforward because this is the check * before forwarding packet actually. */ - if (ipsec6_in_reject(m, NULL)) { + if (ipsec6_in_reject(m, NULL, vnet)) { #if !defined(FAST_IPSEC) - ipsec6stat.in_polvio++; + vnet->ipsec6stat.in_polvio++; #endif m_freem(m); return; @@ -178,9 +178,9 @@ #ifdef IPSEC /* get a security policy for this packet */ sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING, - &error); + &error, vnet); if (sp == NULL) { - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; vnet->ip6stat.ip6s_cantforward++; if (mcopy) { #if 0 @@ -201,7 +201,7 @@ /* * This packet is just discarded. */ - ipsec6stat.out_polvio++; + vnet->ipsec6stat.out_polvio++; vnet->ip6stat.ip6s_cantforward++; key_freesp(sp); if (mcopy) { @@ -263,7 +263,7 @@ state.ro = NULL; /* update at ipsec6_output_tunnel() */ state.dst = NULL; /* update at ipsec6_output_tunnel() */ - error = ipsec6_output_tunnel(&state, sp, 0); + error = ipsec6_output_tunnel(&state, sp, 0, vnet); m = state.m; key_freesp(sp); @@ -401,10 +401,10 @@ * encapsulated packet as "rt->rt_ifp". */ sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, &ipsecerror); + IP_FORWARDING, &ipsecerror, vnet); if (sp) { ipsechdrsiz = ipsec6_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, NULL); + IPSEC_DIR_OUTBOUND, NULL, vnet); if (ipsechdrsiz < mtu) mtu -= ipsechdrsiz; } diff -urN sys/netinet6/ip6_input.c sys.CORE/netinet6/ip6_input.c --- sys/netinet6/ip6_input.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ip6_input.c Wed Jan 31 16:02:43 2007 @@ -928,8 +928,8 @@ * code - like udp/tcp/raw ip. */ if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec6_in_reject(m, NULL)) { - ipsec6stat.in_polvio++; + ipsec6_in_reject(m, NULL, vnet)) { + vnet->ipsec6stat.in_polvio++; goto bad; } #endif diff -urN sys/netinet6/ip6_output.c sys.CORE/netinet6/ip6_output.c --- sys/netinet6/ip6_output.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ip6_output.c Wed Jan 31 16:02:43 2007 @@ -193,6 +193,8 @@ ip6 = mtod(m, struct ip6_hdr *); #endif /* FAST_IPSEC */ + if (vnet == NULL) + panic("ip6_output: NULL vnet was passed."); #define MAKE_EXTHDR(hp, mp) \ do { \ if (hp) { \ @@ -221,12 +223,12 @@ #ifdef IPSEC /* get a security policy for this packet */ if (so == NULL) - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); + sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error, vnet); else sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); if (sp == NULL) { - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; goto freehdrs; } @@ -238,7 +240,7 @@ /* * This packet is just discarded. */ - ipsec6stat.out_polvio++; + vnet->ipsec6stat.out_polvio++; goto freehdrs; case IPSEC_POLICY_BYPASS: @@ -250,7 +252,7 @@ case IPSEC_POLICY_IPSEC: if (sp->req == NULL) { /* acquire a policy */ - error = key_spdacquire(sp); + error = key_spdacquire(sp, vnet); goto freehdrs; } needipsec = 1; @@ -436,7 +438,7 @@ bzero(&state, sizeof(state)); state.m = m; error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags, - &needipsectun); + &needipsectun, vnet); m = state.m; if (error) { /* mbuf is already reclaimed in ipsec6_output_trans. */ @@ -562,7 +564,7 @@ state.ro = (struct route *)ro; state.dst = (struct sockaddr *)dst; - error = ipsec6_output_tunnel(&state, sp, flags); + error = ipsec6_output_tunnel(&state, sp, flags, vnet); m = state.m; ro = (struct route_in6 *)state.ro; @@ -1337,6 +1339,8 @@ int alwaysfrag = 0; int error = 0; + if (vnet == NULL) + panic("ip6_getpmtu: NULL vnet was passed."); if (ro_pmtu != ro) { /* The first hop and the final destination may differ. */ struct sockaddr_in6 *sa6_dst = @@ -1416,6 +1420,8 @@ int optlen; struct proc *p; + if (vnet == NULL) + panic("ip6_ctloutput: NULL vnet from socket."); if (sopt) { level = sopt->sopt_level; op = sopt->sopt_dir; @@ -1853,6 +1859,8 @@ struct proc *p = sopt->sopt_p; int priv = 0; + if (vnet == NULL) + panic("ip6_pcbopts: NULL vnet from socket."); /* turn off any old options. */ if (opt) { #ifdef DIAGNOSTIC @@ -2042,6 +2050,8 @@ struct in6_multi_mship *imm; struct proc *p = curproc; /* XXX */ + if (vnet == NULL) + panic("ip6_setmoptions: NULL vnet passed."); if (im6o == NULL) { /* * No multicast option buffer attached to the pcb; @@ -2326,6 +2336,8 @@ *mp = m_get(M_WAIT, MT_HEADER); /* XXX */ + if (vnet == NULL) + panic("ip6_getmoptions: NULL vnet was passed."); switch (optname) { case IPV6_MULTICAST_IF: diff -urN sys/netinet6/ipcomp_input.c sys.CORE/netinet6/ipcomp_input.c --- sys/netinet6/ipcomp_input.c Sat Apr 27 22:40:27 2002 +++ sys.CORE/netinet6/ipcomp_input.c Wed Jan 31 16:02:43 2007 @@ -47,6 +47,7 @@ #include #include +/*#include */ #include #include #include @@ -79,6 +80,7 @@ #include #include +#include #define IPLEN_FLIPPED @@ -106,6 +108,7 @@ size_t newlen, olen; struct secasvar *sav = NULL; int off, proto; + struct vnet *vnet; va_list ap; va_start(ap, m); @@ -113,10 +116,14 @@ proto = va_arg(ap, int); va_end(ap); + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipcomp_input: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; + if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) { ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " "(packet too short)\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } @@ -125,7 +132,7 @@ m = NULL; /* already freed */ ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " "(pulldown failure)\n")); - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } ipcomp = mtod(md, struct ipcomp *); @@ -141,7 +148,7 @@ if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, - (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi)); + (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi), vnet); if (sav != NULL && (sav->state == SADB_SASTATE_MATURE || sav->state == SADB_SASTATE_DYING)) { @@ -153,7 +160,7 @@ if (!algo) { ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n", cpi)); - ipsecstat.in_nosa++; + vnet->ipsecstat.in_nosa++; goto fail; } @@ -173,13 +180,13 @@ error = (*algo->decompress)(m, m->m_next, &newlen); if (error != 0) { if (error == EINVAL) - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; else if (error == ENOBUFS) - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; m = NULL; goto fail; } - ipsecstat.in_comphist[cpi]++; + vnet->ipsecstat.in_comphist[cpi]++; /* * returning decompressed packet onto icmp is meaningless. @@ -204,7 +211,7 @@ len -= olen; if (len & ~0xffff) { /* packet too big after decompress */ - ipsecstat.in_inval++; + vnet->ipsecstat.in_inval++; goto fail; } #ifdef IPLEN_FLIPPED @@ -218,7 +225,7 @@ if (sav) { key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { - ipsecstat.in_nomem++; + vnet->ipsecstat.in_nomem++; goto fail; } key_freesav(sav); @@ -227,8 +234,8 @@ if (nxt != IPPROTO_DONE) { if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; + ipsec4_in_reject(m, NULL, vnet)) { + vnet->ipsecstat.in_polvio++; goto fail; } (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); @@ -236,7 +243,7 @@ m_freem(m); m = NULL; - ipsecstat.in_success++; + vnet->ipsecstat.in_success++; return; fail: @@ -265,16 +272,20 @@ size_t newlen; struct secasvar *sav = NULL; char *prvnxtp; + struct vnet *vnet = NULL; m = *mp; off = *offp; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipcomp6_input: unable to find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; md = m_pulldown(m, off, sizeof(*ipcomp), NULL); if (!m) { m = NULL; /* already freed */ ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed " "(pulldown failure)\n")); - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; goto fail; } ipcomp = mtod(md, struct ipcomp *); @@ -285,7 +296,8 @@ if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, - (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi)); + (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi), + vnet); if (sav != NULL && (sav->state == SADB_SASTATE_MATURE || sav->state == SADB_SASTATE_DYING)) { @@ -297,7 +309,7 @@ if (!algo) { ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; " "dropping the packet for simplicity\n", cpi)); - ipsec6stat.in_nosa++; + vnet->ipsec6stat.in_nosa++; goto fail; } @@ -311,13 +323,13 @@ error = (*algo->decompress)(m, md, &newlen); if (error != 0) { if (error == EINVAL) - ipsec6stat.in_inval++; + vnet->ipsec6stat.in_inval++; else if (error == ENOBUFS) - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; m = NULL; goto fail; } - ipsec6stat.in_comphist[cpi]++; + vnet->ipsec6stat.in_comphist[cpi]++; m->m_pkthdr.len = off + newlen; /* @@ -338,7 +350,7 @@ if (sav) { key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { - ipsec6stat.in_nomem++; + vnet->ipsec6stat.in_nomem++; goto fail; } key_freesav(sav); @@ -346,7 +358,7 @@ } *offp = off; *mp = m; - ipsec6stat.in_success++; + vnet->ipsec6stat.in_success++; return nxt; fail: diff -urN sys/netinet6/ipcomp_output.c sys.CORE/netinet6/ipcomp_output.c --- sys/netinet6/ipcomp_output.c Tue Apr 29 01:33:50 2003 +++ sys.CORE/netinet6/ipcomp_output.c Wed Jan 31 16:02:43 2007 @@ -80,6 +80,7 @@ #include #include +#include static int ipcomp_output __P((struct mbuf *, u_char *, struct mbuf *, struct ipsecrequest *, int)); @@ -123,18 +124,23 @@ int afnumber; int error = 0; struct ipsecstat *stat; + struct vnet *vnet; + + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipcomp_output: unable to get vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; switch (af) { #ifdef INET case AF_INET: afnumber = 4; - stat = &ipsecstat; + stat = &vnet->ipsecstat; break; #endif #ifdef INET6 case AF_INET6: afnumber = 6; - stat = &ipsec6stat; + stat = &vnet->ipsec6stat; break; #endif default: @@ -309,7 +315,7 @@ else { ipseclog((LOG_ERR, "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); error = EMSGSIZE; goto fail; @@ -353,9 +359,14 @@ struct ipsecrequest *isr; { struct ip *ip; + struct vnet *vnet; + + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipcomp4_output: unable to get vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; if (m->m_len < sizeof(struct ip)) { ipseclog((LOG_DEBUG, "ipcomp4_output: first mbuf too short\n")); - ipsecstat.out_inval++; + vnet->ipsecstat.out_inval++; m_freem(m); return 0; } @@ -373,9 +384,13 @@ struct mbuf *md; struct ipsecrequest *isr; { + struct vnet *vnet; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipcomp6_output: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; if (m->m_len < sizeof(struct ip6_hdr)) { ipseclog((LOG_DEBUG, "ipcomp6_output: first mbuf too short\n")); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; m_freem(m); return 0; } diff -urN sys/netinet6/ipsec.c sys.CORE/netinet6/ipsec.c --- sys/netinet6/ipsec.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ipsec.c Wed Jan 31 16:02:43 2007 @@ -112,6 +112,7 @@ int ipsec_debug = 0; #endif +#ifdef MOVED_TO_VNET struct ipsecstat ipsecstat; int ip4_ah_cleartos = 1; int ip4_ah_offsetmask = 0; /* maybe IP_DF? */ @@ -123,6 +124,7 @@ struct secpolicy ip4_def_policy; int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ int ip4_esp_randpad = -1; +#endif #ifdef SYSCTL_DECL SYSCTL_DECL(_net_inet_ipsec); @@ -132,32 +134,33 @@ #endif /* net.inet.ipsec */ -SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipsecstat, ipsecstat, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, - ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, - ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, - dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); +SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, IPSECCTL_STATS, + stats, CTLFLAG_RD, v_ipsecstat, ipsecstat, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY, + def_policy, CTLFLAG_RW, &((struct secpolicy*)v_ip4_def_policy)->policy, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, + esp_trans_deflev, CTLFLAG_RW, v_ip4_esp_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, + CTLFLAG_RW, v_ip4_esp_net_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, + CTLFLAG_RW, v_ip4_ah_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, + CTLFLAG_RW, v_ip4_ah_net_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS, + ah_cleartos, CTLFLAG_RW, v_ip4_ah_cleartos, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, + ah_offsetmask, CTLFLAG_RW, v_ip4_ah_offsetmask, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT, + dfbit, CTLFLAG_RW, v_ip4_ipsec_dfbit, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN, + ecn, CTLFLAG_RW, v_ip4_ipsec_ecn, 0, ""); SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD, + esp_randpad, CTLFLAG_RW, v_ip4_esp_randpad, 0, ""); #ifdef INET6 +#ifdef MOVED_TO_VNET struct ipsecstat ipsec6stat; int ip6_esp_trans_deflev = IPSEC_LEVEL_USE; int ip6_esp_net_deflev = IPSEC_LEVEL_USE; @@ -166,26 +169,27 @@ struct secpolicy ip6_def_policy; int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ int ip6_esp_randpad = -1; +#endif /* MOVED_TO_VNET */ /* net.inet6.ipsec6 */ -SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipsec6stat, ipsecstat, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip6_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); +SYSCTL_V_STRUCT(V_NET, _net_inet6_ipsec6, IPSECCTL_STATS, + stats, CTLFLAG_RD, v_ipsec6stat, ipsecstat, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY, + def_policy, CTLFLAG_RW, &((struct secpolicy *)v_ip6_def_policy)->policy, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, + esp_trans_deflev, CTLFLAG_RW, v_ip6_esp_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, + CTLFLAG_RW, v_ip6_esp_net_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, + ah_trans_deflev, CTLFLAG_RW, v_ip6_ah_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, + CTLFLAG_RW, v_ip6_ah_net_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN, + ecn, CTLFLAG_RW, v_ip6_ipsec_ecn, 0, ""); SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, + esp_randpad, CTLFLAG_RW, v_ip6_esp_randpad, 0, ""); #endif /* INET6 */ static int ipsec_setspidx_mbuf @@ -217,10 +221,10 @@ static struct mbuf *ipsec6_splithdr __P((struct mbuf *)); #endif #ifdef INET -static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *)); +static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *)); #endif #ifdef INET6 -static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *)); +static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *)); #endif /* @@ -245,11 +249,15 @@ struct inpcbpolicy *pcbsp = NULL; struct secpolicy *currsp = NULL; /* policy on socket */ struct secpolicy *kernsp = NULL; /* policy on kernel */ + struct vnet *vnet; /* sanity check */ if (m == NULL || so == NULL || error == NULL) panic("ipsec4_getpolicybysock: NULL pointer was passed."); - + vnet = so->so_vnet; + if (vnet == NULL) + panic("ipsec4_getpolicybysock: NULL vnet pointer."); + switch (so->so_proto->pr_domain->dom_family) { case AF_INET: /* set spidx in pcb */ @@ -306,7 +314,7 @@ case IPSEC_POLICY_ENTRUST: /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); + kernsp = key_allocsp(&currsp->spidx, dir, vnet); /* SP found */ if (kernsp != NULL) { @@ -318,16 +326,16 @@ } /* no SP found */ - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD - && ip4_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE)); + vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; } - ip4_def_policy.refcnt++; + vnet->ip4_def_policy.refcnt++; *error = 0; - return &ip4_def_policy; + return &vnet->ip4_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; @@ -345,7 +353,7 @@ /* when non-privilieged socket */ /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); + kernsp = key_allocsp(&currsp->spidx, dir, vnet); /* SP found */ if (kernsp != NULL) { @@ -366,16 +374,16 @@ return NULL; case IPSEC_POLICY_ENTRUST: - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD - && ip4_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE)); + vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; } - ip4_def_policy.refcnt++; + vnet->ip4_def_policy.refcnt++; *error = 0; - return &ip4_def_policy; + return &vnet->ip4_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; @@ -402,17 +410,20 @@ * others : error occured. */ struct secpolicy * -ipsec4_getpolicybyaddr(m, dir, flag, error) +ipsec4_getpolicybyaddr(m, dir, flag, error, vnet) struct mbuf *m; u_int dir; int flag; int *error; + struct vnet *vnet; { struct secpolicy *sp = NULL; /* sanity check */ if (m == NULL || error == NULL) panic("ipsec4_getpolicybyaddr: NULL pointer was passed."); + if (vnet == NULL) + panic("ipsec4_getpolicybyaddr: NULL vnet pointer was passed."); { struct secpolicyindex spidx; @@ -426,7 +437,7 @@ if (*error != 0) return NULL; - sp = key_allocsp(&spidx, dir); + sp = key_allocsp(&spidx, dir, vnet); } /* SP found */ @@ -439,16 +450,16 @@ } /* no SP found */ - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD - && ip4_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n", - ip4_def_policy.policy, + vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; } - ip4_def_policy.refcnt++; + vnet->ip4_def_policy.refcnt++; *error = 0; - return &ip4_def_policy; + return &vnet->ip4_def_policy; } #ifdef INET6 @@ -472,10 +483,15 @@ struct inpcbpolicy *pcbsp = NULL; struct secpolicy *currsp = NULL; /* policy on socket */ struct secpolicy *kernsp = NULL; /* policy on kernel */ + struct vnet *vnet; /* sanity check */ if (m == NULL || so == NULL || error == NULL) panic("ipsec6_getpolicybysock: NULL pointer was passed."); + vnet = so->so_vnet; + if (vnet == NULL) + panic("ipsec6_getpolicybysock: NULL vnet pointer was passed."); + #ifdef DIAGNOSTIC if (so->so_proto->pr_domain->dom_family != AF_INET6) @@ -516,7 +532,7 @@ case IPSEC_POLICY_ENTRUST: /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); + kernsp = key_allocsp(&currsp->spidx, dir, vnet); /* SP found */ if (kernsp != NULL) { @@ -528,16 +544,16 @@ } /* no SP found */ - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); + vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; } - ip6_def_policy.refcnt++; + vnet->ip6_def_policy.refcnt++; *error = 0; - return &ip6_def_policy; + return &vnet->ip6_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; @@ -555,7 +571,7 @@ /* when non-privilieged socket */ /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); + kernsp = key_allocsp(&currsp->spidx, dir, vnet); /* SP found */ if (kernsp != NULL) { @@ -576,16 +592,16 @@ return NULL; case IPSEC_POLICY_ENTRUST: - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); + vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; } - ip6_def_policy.refcnt++; + vnet->ip6_def_policy.refcnt++; *error = 0; - return &ip6_def_policy; + return &vnet->ip6_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; @@ -619,17 +635,20 @@ #endif struct secpolicy * -ipsec6_getpolicybyaddr(m, dir, flag, error) +ipsec6_getpolicybyaddr(m, dir, flag, error, vnet) struct mbuf *m; u_int dir; int flag; int *error; + struct vnet *vnet; { struct secpolicy *sp = NULL; /* sanity check */ if (m == NULL || error == NULL) panic("ipsec6_getpolicybyaddr: NULL pointer was passed."); + if (vnet == NULL) + panic("ipsec6_getpolicybyaddr: NULL vnet pointer was passed."); { struct secpolicyindex spidx; @@ -643,7 +662,7 @@ if (*error != 0) return NULL; - sp = key_allocsp(&spidx, dir); + sp = key_allocsp(&spidx, dir, vnet); } /* SP found */ @@ -656,15 +675,15 @@ } /* no SP found */ - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { + if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD + && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); + vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; } - ip6_def_policy.refcnt++; + vnet->ip6_def_policy.refcnt++; *error = 0; - return &ip6_def_policy; + return &vnet->ip6_def_policy; } #endif /* INET6 */ @@ -1505,8 +1524,9 @@ * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned. */ u_int -ipsec_get_reqlevel(isr) +ipsec_get_reqlevel(isr, vnet) struct ipsecrequest *isr; + struct vnet *vnet; { u_int level = 0; u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev; @@ -1514,6 +1534,8 @@ /* sanity check */ if (isr == NULL || isr->sp == NULL) panic("ipsec_get_reqlevel: NULL pointer is passed."); + if (vnet == NULL) + panic("ipsec_get_reqlevel: NULL vnet is passed."); if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family != ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family) panic("ipsec_get_reqlevel: family mismatched."); @@ -1534,18 +1556,18 @@ switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) { #ifdef INET case AF_INET: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev); + esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_trans_deflev); + esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_net_deflev); + ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_trans_deflev); + ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_net_deflev); break; #endif #ifdef INET6 case AF_INET6: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev); + esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_trans_deflev); + esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_net_deflev); + ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_trans_deflev); + ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_net_deflev); break; #endif /* INET6 */ default: @@ -1614,10 +1636,16 @@ struct ipsecrequest *isr; u_int level; int need_auth, need_conf, need_icv; + struct vnet *vnet; KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("ipsec_in_reject: using SP\n"); kdebug_secpolicy(sp)); + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipsec_in_reject(): unable to get vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; + if (vnet == NULL) + panic("ipsec_in_reject(): NULL vnet was passed."); /* check policy */ switch (sp->policy) { @@ -1644,7 +1672,7 @@ for (isr = sp->req; isr != NULL; isr = isr->next) { /* get current level */ - level = ipsec_get_reqlevel(isr); + level = ipsec_get_reqlevel(isr, vnet); switch (isr->saidx.proto) { case IPPROTO_ESP: @@ -1691,9 +1719,10 @@ * and {ah,esp}4_input for tunnel mode */ int -ipsec4_in_reject_so(m, so) +ipsec4_in_reject_so(m, so, vnet) struct mbuf *m; struct socket *so; + struct vnet *vnet; { struct secpolicy *sp = NULL; int error; @@ -1708,7 +1737,7 @@ * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. */ if (so == NULL) - sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); + sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet); else sp = ipsec4_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); @@ -1725,14 +1754,15 @@ } int -ipsec4_in_reject(m, inp) +ipsec4_in_reject(m, inp, vnet) struct mbuf *m; struct inpcb *inp; + struct vnet *vnet; { if (inp == NULL) - return ipsec4_in_reject_so(m, NULL); + return ipsec4_in_reject_so(m, NULL, vnet); if (inp->inp_socket) - return ipsec4_in_reject_so(m, inp->inp_socket); + return ipsec4_in_reject_so(m, inp->inp_socket, vnet); else panic("ipsec4_in_reject: invalid inpcb/socket"); } @@ -1744,9 +1774,10 @@ * and {ah,esp}6_input for tunnel mode */ int -ipsec6_in_reject_so(m, so) +ipsec6_in_reject_so(m, so, vnet) struct mbuf *m; struct socket *so; + struct vnet *vnet; { struct secpolicy *sp = NULL; int error; @@ -1761,7 +1792,7 @@ * ipsec6_getpolicybyaddr() with IP_FORWARDING flag. */ if (so == NULL) - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); + sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet); else sp = ipsec6_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); @@ -1777,14 +1808,15 @@ } int -ipsec6_in_reject(m, in6p) +ipsec6_in_reject(m, in6p, vnet) struct mbuf *m; struct in6pcb *in6p; + struct vnet *vnet; { if (in6p == NULL) - return ipsec6_in_reject_so(m, NULL); + return ipsec6_in_reject_so(m, NULL, vnet); if (in6p->in6p_socket) - return ipsec6_in_reject_so(m, in6p->in6p_socket); + return ipsec6_in_reject_so(m, in6p->in6p_socket, vnet); else panic("ipsec6_in_reject: invalid in6p/socket"); } @@ -1868,10 +1900,11 @@ /* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */ size_t -ipsec4_hdrsiz(m, dir, inp) +ipsec4_hdrsiz(m, dir, inp, vnet) struct mbuf *m; u_int dir; struct inpcb *inp; + struct vnet *vnet; { struct secpolicy *sp = NULL; int error; @@ -1888,7 +1921,7 @@ * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. */ if (inp == NULL) - sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error); + sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error,vnet); else sp = ipsec4_getpolicybysock(m, dir, inp->inp_socket, &error); @@ -1910,10 +1943,11 @@ * and maybe from ip6_forward.() */ size_t -ipsec6_hdrsiz(m, dir, in6p) +ipsec6_hdrsiz(m, dir, in6p, vnet) struct mbuf *m; u_int dir; struct in6pcb *in6p; + struct vnet *vnet; { struct secpolicy *sp = NULL; int error; @@ -1928,7 +1962,7 @@ /* get SP for this packet */ /* XXX Is it right to call with IP_FORWARDING. */ if (in6p == NULL) - sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error); + sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error, vnet); else sp = ipsec6_getpolicybysock(m, dir, in6p->in6p_socket, &error); @@ -1951,9 +1985,10 @@ * ip->ip_src must be fixed later on. */ static int -ipsec4_encapsulate(m, sav) +ipsec4_encapsulate(m, sav, vnet) struct mbuf *m; struct secasvar *sav; + struct vnet *vnet; { struct ip *oip; struct ip *ip; @@ -1967,6 +2002,8 @@ m_freem(m); return EINVAL; } + if (vnet == NULL) + panic("ipsec4_encapsulate(): vnet is NULL."); #if 0 /* XXX if the dst is myself, perform nothing. */ if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) { @@ -2030,7 +2067,7 @@ /* construct new IPv4 header. see RFC 2401 5.1.2.1 */ /* ECN consideration. */ - ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos); + ip_ecn_ingress(vnet->ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos); #ifdef _IP_VHL ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); #else @@ -2038,7 +2075,7 @@ #endif ip->ip_off &= htons(~IP_OFFMASK); ip->ip_off &= htons(~IP_MF); - switch (ip4_ipsec_dfbit) { + switch (vnet->ip4_ipsec_dfbit) { case 0: /* clear DF bit */ ip->ip_off &= htons(~IP_DF); break; @@ -2058,7 +2095,7 @@ #ifdef RANDOM_IP_ID ip->ip_id = ip_randomid(); #else - ip->ip_id = htons(ip_id++); + ip->ip_id = htons(vnet->ip_id++); #endif bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); @@ -2074,14 +2111,18 @@ #ifdef INET6 static int -ipsec6_encapsulate(m, sav) +ipsec6_encapsulate(m, sav, vnet) struct mbuf *m; struct secasvar *sav; + struct vnet *vnet; { struct ip6_hdr *oip6; struct ip6_hdr *ip6; size_t plen; + if (vnet == NULL) + panic("ipsec6_encapsulate(): vnet is NULL."); + /* can't tunnel between different AFs */ if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family @@ -2133,7 +2174,7 @@ /* construct new IPv6 header. see RFC 2401 5.1.2.2 */ /* ECN consideration. */ - ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); + ip6_ecn_ingress(vnet->ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) ip6->ip6_plen = htons(plen); else { @@ -2493,6 +2534,8 @@ panic("state->ro == NULL in ipsec4_output"); if (!state->dst) panic("state->dst == NULL in ipsec4_output"); + if (vnet == NULL) + panic("ipsec4_output: vnet is NULL."); KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("ipsec4_output: applyed SP\n"); @@ -2541,13 +2584,13 @@ * this packet because it is responsibility for * upper layer to retransmit the packet. */ - ipsecstat.out_nosa++; + vnet->ipsecstat.out_nosa++; goto bad; } /* validity check */ if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { + switch (ipsec_get_reqlevel(isr, vnet)) { case IPSEC_LEVEL_USE: continue; case IPSEC_LEVEL_REQUIRE: @@ -2565,7 +2608,7 @@ */ if (isr->sav->state != SADB_SASTATE_MATURE && isr->sav->state != SADB_SASTATE_DYING) { - ipsecstat.out_nosa++; + vnet->ipsecstat.out_nosa++; error = EINVAL; goto bad; } @@ -2596,7 +2639,7 @@ error = ENOMEM; goto bad; } - error = ipsec4_encapsulate(state->m, isr->sav); + error = ipsec4_encapsulate(state->m, isr->sav, vnet); splx(s); if (error) { state->m = NULL; @@ -2641,7 +2684,7 @@ switch (isr->saidx.proto) { case IPPROTO_ESP: #ifdef IPSEC_ESP - if ((error = esp4_output(state->m, isr)) != 0) { + if ((error = esp4_output(state->m, isr, vnet)) != 0) { state->m = NULL; goto bad; } @@ -2653,7 +2696,7 @@ goto bad; #endif case IPPROTO_AH: - if ((error = ah4_output(state->m, isr)) != 0) { + if ((error = ah4_output(state->m, isr, vnet)) != 0) { state->m = NULL; goto bad; } @@ -2695,13 +2738,14 @@ * IPsec output logic for IPv6, transport mode. */ int -ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun) +ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun, vnet) struct ipsec_output_state *state; u_char *nexthdrp; struct mbuf *mprev; struct secpolicy *sp; int flags; int *tun; + struct vnet *vnet; { struct ip6_hdr *ip6; struct ipsecrequest *isr = NULL; @@ -2722,6 +2766,8 @@ panic("sp == NULL in ipsec6_output_trans"); if (!tun) panic("tun == NULL in ipsec6_output_trans"); + if (!vnet) + panic("vnet == NULL in ipsec6_output_trans"); KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("ipsec6_output_trans: applyed SP\n"); @@ -2766,7 +2812,7 @@ } } - if (key_checkrequest(isr, &saidx) == ENOENT) { + if (key_checkrequest(isr, &saidx, vnet) == ENOENT) { /* * IPsec processing is required, but no SA found. * I assume that key_acquire() had been called @@ -2774,7 +2820,7 @@ * this packet because it is responsibility for * upper layer to retransmit the packet. */ - ipsec6stat.out_nosa++; + vnet->ipsec6stat.out_nosa++; error = ENOENT; /* @@ -2793,7 +2839,7 @@ /* validity check */ if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { + switch (ipsec_get_reqlevel(isr, vnet)) { case IPSEC_LEVEL_USE: continue; case IPSEC_LEVEL_REQUIRE: @@ -2808,7 +2854,7 @@ */ if (isr->sav->state != SADB_SASTATE_MATURE && isr->sav->state != SADB_SASTATE_DYING) { - ipsec6stat.out_nosa++; + vnet->ipsec6stat.out_nosa++; error = EINVAL; goto bad; } @@ -2816,7 +2862,7 @@ switch (isr->saidx.proto) { case IPPROTO_ESP: #ifdef IPSEC_ESP - error = esp6_output(state->m, nexthdrp, mprev->m_next, isr); + error = esp6_output(state->m, nexthdrp, mprev->m_next, isr, vnet); #else m_freem(state->m); error = EINVAL; @@ -2832,7 +2878,7 @@ ipseclog((LOG_ERR, "ipsec6_output_trans: " "unknown ipsec protocol %d\n", isr->saidx.proto)); m_freem(state->m); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; error = EINVAL; break; } @@ -2844,7 +2890,7 @@ if (plen > IPV6_MAXPACKET) { ipseclog((LOG_ERR, "ipsec6_output_trans: " "IPsec with IPv6 jumbogram is not supported\n")); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; error = EINVAL; /* XXX */ goto bad; } @@ -2868,10 +2914,11 @@ * IPsec output logic for IPv6, tunnel mode. */ int -ipsec6_output_tunnel(state, sp, flags) +ipsec6_output_tunnel(state, sp, flags, vnet) struct ipsec_output_state *state; struct secpolicy *sp; int flags; + struct vnet *vnet; { struct ip6_hdr *ip6; struct ipsecrequest *isr = NULL; @@ -2887,6 +2934,8 @@ panic("state->m == NULL in ipsec6_output_tunnel"); if (!sp) panic("sp == NULL in ipsec6_output_tunnel"); + if (!vnet) + panic("vnet == NULL in ipsec6_output_tunnel"); KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("ipsec6_output_tunnel: applyed SP\n"); @@ -2943,7 +2992,7 @@ } } - if (key_checkrequest(isr, &saidx) == ENOENT) { + if (key_checkrequest(isr, &saidx, vnet) == ENOENT) { /* * IPsec processing is required, but no SA found. * I assume that key_acquire() had been called @@ -2951,14 +3000,14 @@ * this packet because it is responsibility for * upper layer to retransmit the packet. */ - ipsec6stat.out_nosa++; + vnet->ipsec6stat.out_nosa++; error = ENOENT; goto bad; } /* validity check */ if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { + switch (ipsec_get_reqlevel(isr, vnet)) { case IPSEC_LEVEL_USE: continue; case IPSEC_LEVEL_REQUIRE: @@ -2973,7 +3022,7 @@ */ if (isr->sav->state != SADB_SASTATE_MATURE && isr->sav->state != SADB_SASTATE_DYING) { - ipsec6stat.out_nosa++; + vnet->ipsec6stat.out_nosa++; error = EINVAL; goto bad; } @@ -2994,7 +3043,7 @@ "family mismatched between inner and outer, spi=%u\n", (u_int32_t)ntohl(isr->sav->spi))); splx(s); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; error = EAFNOSUPPORT; goto bad; } @@ -3002,11 +3051,11 @@ state->m = ipsec6_splithdr(state->m); if (!state->m) { splx(s); - ipsec6stat.out_nomem++; + vnet->ipsec6stat.out_nomem++; error = ENOMEM; goto bad; } - error = ipsec6_encapsulate(state->m, isr->sav); + error = ipsec6_encapsulate(state->m, isr->sav, vnet); splx(s); if (error) { state->m = 0; @@ -3028,11 +3077,11 @@ dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); dst6->sin6_addr = ip6->ip6_dst; - rtalloc(state->ro); + rtalloc(state->ro, vnet); } if (state->ro->ro_rt == 0) { - ip6stat.ip6s_noroute++; - ipsec6stat.out_noroute++; + vnet->ip6stat.ip6s_noroute++; + vnet->ipsec6stat.out_noroute++; error = EHOSTUNREACH; goto bad; } @@ -3047,7 +3096,7 @@ state->m = ipsec6_splithdr(state->m); if (!state->m) { - ipsec6stat.out_nomem++; + vnet->ipsec6stat.out_nomem++; error = ENOMEM; goto bad; } @@ -3055,7 +3104,7 @@ switch (isr->saidx.proto) { case IPPROTO_ESP: #ifdef IPSEC_ESP - error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr); + error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr, vnet); #else m_freem(state->m); error = EINVAL; @@ -3071,7 +3120,7 @@ ipseclog((LOG_ERR, "ipsec6_output_tunnel: " "unknown ipsec protocol %d\n", isr->saidx.proto)); m_freem(state->m); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; error = EINVAL; break; } @@ -3083,7 +3132,7 @@ if (plen > IPV6_MAXPACKET) { ipseclog((LOG_ERR, "ipsec6_output_tunnel: " "IPsec with IPv6 jumbogram is not supported\n")); - ipsec6stat.out_inval++; + vnet->ipsec6stat.out_inval++; error = EINVAL; /* XXX */ goto bad; } @@ -3193,7 +3242,11 @@ int hlen; struct secpolicy *sp; struct ip *oip; + struct vnet *vnet; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipsec4_tunnel_validate: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; #ifdef DIAGNOSTIC if (m->m_len < sizeof(struct ip)) panic("too short mbuf on ipsec4_tunnel_validate"); @@ -3260,7 +3313,7 @@ */ sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, - (struct sockaddr *)&isrc, (struct sockaddr *)&idst); + (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet); if (!sp) return 0; key_freesp(sp); @@ -3282,7 +3335,12 @@ struct sockaddr_in6 osrc, odst, isrc, idst; struct secpolicy *sp; struct ip6_hdr *oip6; + struct vnet *vnet; + if (m == NULL || m->m_pkthdr.rcvif == NULL) + panic("ipsec6_tunnel_validate: cannot find vnet."); + vnet = m->m_pkthdr.rcvif->if_vnet; + #ifdef DIAGNOSTIC if (m->m_len < sizeof(struct ip6_hdr)) panic("too short mbuf on ipsec6_tunnel_validate"); @@ -3325,7 +3383,7 @@ */ sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, - (struct sockaddr *)&isrc, (struct sockaddr *)&idst); + (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet); /* * when there is no suitable inbound policy for the packet of the ipsec * tunnel mode, the kernel never decapsulate the tunneled packet diff -urN sys/netinet6/ipsec.h sys.CORE/netinet6/ipsec.h --- sys/netinet6/ipsec.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/ipsec.h Wed Jan 31 16:02:43 2007 @@ -285,6 +285,7 @@ extern int ipsec_debug; +#ifdef MOVED_TO_VNET extern struct ipsecstat ipsecstat; extern struct secpolicy ip4_def_policy; extern int ip4_esp_trans_deflev; @@ -296,34 +297,36 @@ extern int ip4_ipsec_dfbit; extern int ip4_ipsec_ecn; extern int ip4_esp_randpad; +#endif #define ipseclog(x) do { if (ipsec_debug) log x; } while (0) extern struct secpolicy *ipsec4_getpolicybysock __P((struct mbuf *, u_int, struct socket *, int *)); extern struct secpolicy *ipsec4_getpolicybyaddr - __P((struct mbuf *, u_int, int, int *)); + __P((struct mbuf *, u_int, int, int *, struct vnet *)); struct inpcb; extern int ipsec_init_policy __P((struct socket *so, struct inpcbpolicy **)); extern int ipsec_copy_policy __P((struct inpcbpolicy *, struct inpcbpolicy *)); -extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *)); +extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *, struct vnet *)); extern int ipsec4_set_policy __P((struct inpcb *inp, int optname, caddr_t request, size_t len, int priv)); extern int ipsec4_get_policy __P((struct inpcb *inpcb, caddr_t request, size_t len, struct mbuf **mp)); extern int ipsec4_delete_pcbpolicy __P((struct inpcb *)); -extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *)); -extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *)); +extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *)); +extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *)); struct secas; struct tcpcb; extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *)); extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *)); -extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *)); +extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *, + struct vnet *)); extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *)); struct ip; diff -urN sys/netinet6/ipsec6.h sys.CORE/netinet6/ipsec6.h --- sys/netinet6/ipsec6.h Tue Jul 3 04:01:54 2001 +++ sys.CORE/netinet6/ipsec6.h Wed Jan 31 16:02:43 2007 @@ -53,29 +53,29 @@ extern struct secpolicy *ipsec6_getpolicybysock __P((struct mbuf *, u_int, struct socket *, int *)); extern struct secpolicy *ipsec6_getpolicybyaddr - __P((struct mbuf *, u_int, int, int *)); + __P((struct mbuf *, u_int, int, int *, struct vnet *)); struct inpcb; -extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *)); +extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *)); extern int ipsec6_delete_pcbpolicy __P((struct inpcb *)); extern int ipsec6_set_policy __P((struct inpcb *inp, int optname, caddr_t request, size_t len, int priv)); extern int ipsec6_get_policy __P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp)); -extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *)); +extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *)); struct tcp6cb; -extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *)); +extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *, struct vnet *vnet)); struct ip6_hdr; extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t)); extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *, - struct mbuf *, struct secpolicy *, int, int *)); + struct mbuf *, struct secpolicy *, int, int *, struct vnet *)); extern int ipsec6_output_tunnel __P((struct ipsec_output_state *, - struct secpolicy *, int)); + struct secpolicy *, int, struct vnet *)); extern int ipsec6_tunnel_validate __P((struct mbuf *, int, u_int, struct secasvar *)); #endif /*_KERNEL*/ diff -urN sys/netinet6/raw_ip6.c sys.CORE/netinet6/raw_ip6.c --- sys/netinet6/raw_ip6.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/raw_ip6.c Wed Jan 31 16:02:43 2007 @@ -168,9 +168,9 @@ /* * Check AH/ESP integrity. */ - if (n && ipsec6_in_reject_so(n, last->inp_socket)) { + if (n && ipsec6_in_reject_so(n, last->inp_socket, vnet)) { m_freem(n); - ipsec6stat.in_polvio++; + vnet->ipsec6stat.in_polvio++; /* do not inject data into pcb */ } else #endif /*IPSEC*/ @@ -207,10 +207,10 @@ /* * Check AH/ESP integrity. */ - if (last && ipsec6_in_reject_so(m, last->inp_socket)) { + if (last && ipsec6_in_reject_so(m, last->inp_socket, vnet)) { m_freem(m); - ipsec6stat.in_polvio++; - ip6stat.ip6s_delivered--; + vnet->ipsec6stat.in_polvio++; + vnet->ip6stat.ip6s_delivered--; /* do not inject data into pcb */ } else #endif /*IPSEC*/ @@ -220,7 +220,7 @@ */ if (last && ipsec6_in_reject(m, last)) { m_freem(m); - ip6stat.ip6s_delivered--; + vnet->ip6stat.ip6s_delivered--; /* do not inject data into pcb */ } else #endif /*FAST_IPSEC*/ diff -urN sys/netinet6/udp6_usrreq.c sys.CORE/netinet6/udp6_usrreq.c --- sys/netinet6/udp6_usrreq.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netinet6/udp6_usrreq.c Wed Jan 31 16:02:43 2007 @@ -260,8 +260,8 @@ /* * Check AH/ESP integrity. */ - if (ipsec6_in_reject_so(m, last->inp_socket)) - ipsec6stat.in_polvio++; + if (ipsec6_in_reject_so(m, last->inp_socket, vnet)) + vnet->ipsec6stat.in_polvio++; /* do not inject data into pcb */ else #endif /* IPSEC */ @@ -327,8 +327,8 @@ /* * Check AH/ESP integrity. */ - if (ipsec6_in_reject_so(m, last->inp_socket)) { - ipsec6stat.in_polvio++; + if (ipsec6_in_reject_so(m, last->inp_socket, vnet)) { + vnet->ipsec6stat.in_polvio++; goto bad; } #endif /* IPSEC */ @@ -383,8 +383,8 @@ /* * Check AH/ESP integrity. */ - if (ipsec6_in_reject_so(m, in6p->in6p_socket)) { - ipsec6stat.in_polvio++; + if (ipsec6_in_reject_so(m, in6p->in6p_socket, vnet)) { + vnet->ipsec6stat.in_polvio++; goto bad; } #endif /* IPSEC */ diff -urN sys/netipsec/ipsec.c sys.CORE/netipsec/ipsec.c --- sys/netipsec/ipsec.c Mon Jun 30 18:38:13 2003 +++ sys.CORE/netipsec/ipsec.c Wed Jan 31 16:02:43 2007 @@ -53,6 +53,7 @@ #include #include +#include #include #include @@ -123,31 +124,31 @@ SYSCTL_DECL(_net_inet_ipsec); /* net.inet.ipsec */ -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV,esp_trans_deflev, CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS, ah_cleartos, CTLFLAG_RW, &ah_cleartos, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT, dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN, ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEBUG, debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD, esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); -SYSCTL_INT(_net_inet_ipsec, OID_AUTO, +SYSCTL_V_INT(V_NET, _net_inet_ipsec, OID_AUTO, crypto_support, CTLFLAG_RW, &crypto_support,0, ""); -SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO, +SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, OID_AUTO, ipsecstats, CTLFLAG_RD, &newipsecstat, newipsecstat, ""); #ifdef INET6 @@ -165,21 +166,21 @@ SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD, 0,0, compat_ipsecstats_sysctl, "S", ""); #endif /* COMPAT_KAME */ -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, + esp_trans_deflev, CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, + ah_trans_deflev, CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN, ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEBUG, debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, +SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); #endif /* INET6 */ diff -urN sys/netipsec/key.c sys.CORE/netipsec/key.c --- sys/netipsec/key.c Sat Feb 14 14:23:23 2004 +++ sys.CORE/netipsec/key.c Wed Jan 31 16:02:43 2007 @@ -54,6 +54,7 @@ #include #include +#include #include #include #include @@ -203,51 +204,51 @@ SYSCTL_DECL(_net_key); #endif -SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ &key_debug_level, 0, ""); /* max count of trial for the decision of spi value */ -SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ &key_spi_trycnt, 0, ""); /* minimum spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ &key_spi_minval, 0, ""); /* maximun spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ &key_spi_maxval, 0, ""); /* interval to initialize randseed */ -SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ &key_int_random, 0, ""); /* lifetime for larval SA */ -SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ &key_larval_lifetime, 0, ""); /* counter for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT,blockacq_count,CTLFLAG_RW, \ &key_blockacq_count, 0, ""); /* lifetime for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ &key_blockacq_lifetime, 0, ""); /* ESP auth */ -SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ &ipsec_esp_auth, 0, ""); /* minimum ESP key length */ -SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ &ipsec_esp_keymin, 0, ""); /* minimum AH key length */ -SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ &ipsec_ah_keymin, 0, ""); /* perfered old SA rather than new SA */ -SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA,prefered_oldsa, CTLFLAG_RW,\ &key_prefered_oldsa, 0, ""); #ifndef LIST_FOREACH @@ -349,12 +350,13 @@ int extlen[SADB_EXT_MAX + 1]; }; -static struct secasvar *key_allocsa_policy __P((const struct secasindex *)); +static struct secasvar *key_allocsa_policy __P((const struct secasindex *, + struct vnet *)); static void key_freesp_so __P((struct secpolicy **)); static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int)); static void key_delsp __P((struct secpolicy *)); -static struct secpolicy *key_getsp __P((struct secpolicyindex *)); -static struct secpolicy *key_getspbyid __P((u_int32_t)); +static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*)); +static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet *)); static u_int32_t key_newreqid __P((void)); static struct mbuf *key_gather_mbuf __P((struct mbuf *, const struct sadb_msghdr *, int, int, ...)); @@ -523,7 +525,7 @@ * others: found and return the pointer. */ struct secpolicy * -key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag) +key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag, struct vnet *vnet) { struct secpolicy *sp; int s; @@ -541,7 +543,7 @@ printf("*** objects\n"); kdebug_secpolicyindex(spidx)); - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("*** in SPD\n"); kdebug_secpolicyindex(&sp->spidx)); @@ -580,7 +582,7 @@ union sockaddr_union *dst, u_int8_t proto, u_int dir, - const char* where, int tag) + const char* where, int tag, struct vnet *vnet) { struct secpolicy *sp; int s; @@ -599,7 +601,7 @@ printf("spi %u proto %u dir %u\n", spi, proto, dir); kdebug_sockaddr(&dst->sa)); - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("*** in SPD\n"); kdebug_secpolicyindex(&sp->spidx)); @@ -642,7 +644,7 @@ const struct sockaddr *odst, const struct sockaddr *isrc, const struct sockaddr *idst, - const char* where, int tag) + const char* where, int tag, struct vnet *vnet) { struct secpolicy *sp; const int dir = IPSEC_DIR_INBOUND; @@ -661,7 +663,7 @@ } s = splnet(); /*called from softclock()*/ - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; @@ -817,7 +819,7 @@ struct secasvar *sav; u_int stateidx, state; - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) @@ -991,7 +993,7 @@ union sockaddr_union *dst, u_int proto, u_int32_t spi, - const char* where, int tag) + const char* where, int tag, struct vnet *vnet) { struct secashead *sah; struct secasvar *sav; @@ -1010,7 +1012,7 @@ * encrypted so we can't check internal IP header. */ s = splnet(); /*called from softclock()*/ - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { /* search valid state */ for (stateidx = 0; stateidx < _ARRAYLEN(saorder_state_valid); @@ -1213,13 +1215,13 @@ * others : found, pointer to a SP. */ static struct secpolicy * -key_getsp(struct secpolicyindex *spidx) +key_getsp(struct secpolicyindex *spidx, struct vnet *vnet) { struct secpolicy *sp; KASSERT(spidx != NULL, ("key_getsp: null spidx")); - LIST_FOREACH(sp, &sptree[spidx->dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (key_cmpspidx_exactly(spidx, &sp->spidx)) { @@ -1237,11 +1239,11 @@ * others : found, pointer to a SP. */ static struct secpolicy * -key_getspbyid(u_int32_t id) +key_getspbyid(u_int32_t id, struct vnet *vnet) { struct secpolicy *sp; - LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { + LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (sp->id == id) { @@ -1250,7 +1252,7 @@ } } - LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { + LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (sp->id == id) { @@ -7060,37 +7062,59 @@ } void -key_init() +key_init(vnet) + struct vnet *vnet; { int i; for (i = 0; i < IPSEC_DIR_MAX; i++) { - LIST_INIT(&sptree[i]); + LIST_INIT(&vnet->sptree[i]); } - LIST_INIT(&sahtree); + LIST_INIT(&vnet->sahtree); for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_INIT(®tree[i]); + LIST_INIT(&vnet->regtree[i]); } #ifndef IPSEC_NONBLOCK_ACQUIRE - LIST_INIT(&acqtree); + LIST_INIT(&vnet->acqtree); #endif - LIST_INIT(&spacqtree); + LIST_INIT(&vnet->spacqtree); /* system default */ - ip4_def_policy.policy = IPSEC_POLICY_NONE; - ip4_def_policy.refcnt++; /*never reclaim this*/ + vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip4_def_policy.refcnt++; /*never reclaim this*/ #ifndef IPSEC_DEBUG2 timeout((void *)key_timehandler, (void *)0, hz); #endif /*IPSEC_DEBUG2*/ /* initialize key statistics */ - keystat.getspi_count = 1; + vnet->keystat.getspi_count = 1; + + /* initialize vars in struct vnet */ + vnet->acq_seq = 0; + vnet->ip4_ah_offsetmask = 0; + vnet->ip4_ipsec_dfbit = 0; + vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ipsec_ecn = 0; + vnet->ip4_esp_randpad = -1; + vnet->crypto_support = 0; +#ifdef INET6 + vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ipsec_ecn = 0; + vnet->ip6_esp_randpad = -1; +#endif - printf("IPsec: Initialized Security Association Processing.\n"); + if (vnet == vnet0) + printf("IPsec: Initialized Security Association Processing.\n"); return; } diff -urN sys/netipsec/keysock.c sys.CORE/netipsec/keysock.c --- sys/netipsec/keysock.c Thu Jan 23 21:11:36 2003 +++ sys.CORE/netipsec/keysock.c Wed Jan 31 16:02:43 2007 @@ -592,10 +592,11 @@ }; static void -key_init0(void) +key_init0(vnet) + struct vnet *vnet; { - bzero((caddr_t)&key_cb, sizeof(key_cb)); - key_init(); + bzero((caddr_t)&vnet->key_cb, sizeof(key_cb)); + key_init(vnet); } struct domain keydomain = diff -urN sys/netkey/key.c sys.CORE/netkey/key.c --- sys/netkey/key.c Thu Jan 13 14:47:18 2005 +++ sys.CORE/netkey/key.c Wed Jan 31 16:02:43 2007 @@ -107,6 +107,8 @@ #include #include +#include +#include #ifndef satosin #define satosin(s) ((struct sockaddr_in *)s) @@ -126,6 +128,7 @@ */ u_int32_t key_debug_level = 0; +#ifdef MOVED_TO_VNET static u_int key_spi_trycnt = 1000; static u_int32_t key_spi_minval = 0x100; static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */ @@ -149,6 +152,7 @@ static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ struct key_cb key_cb; +#endif /* MOVED_TO_VNET */ /* search order for SAs */ static const u_int saorder_state_valid_prefer_old[] = { @@ -223,32 +227,32 @@ &key_debug_level, 0, ""); /* max count of trial for the decision of spi value */ -SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ - &key_spi_trycnt, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ + v_key_spi_trycnt, 0, ""); /* minimum spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ - &key_spi_minval, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ + v_key_spi_minval, 0, ""); /* maximun spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ - &key_spi_maxval, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ + v_key_spi_maxval, 0, ""); /* interval to initialize randseed */ -SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ - &key_int_random, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ + v_key_int_random, 0, ""); /* lifetime for larval SA */ -SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ - &key_larval_lifetime, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ + v_key_larval_lifetime, 0, ""); /* counter for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ - &key_blockacq_count, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ + v_key_blockacq_count, 0, ""); /* lifetime for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ - &key_blockacq_lifetime, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ + v_key_blockacq_lifetime, 0, ""); /* ESP auth */ SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ @@ -263,8 +267,8 @@ &ipsec_ah_keymin, 0, ""); /* perfered old SA rather than new SA */ -SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ - &key_preferred_oldsa, 0, ""); +SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ + v_key_preferred_oldsa, 0, ""); #ifndef LIST_FOREACH #define LIST_FOREACH(elm, head, field) \ @@ -352,9 +356,11 @@ } while (0) /* key statistics */ +#ifdef MOVED_TO_VNET struct _keystat { u_long getspi_count; /* the avarage of count to try to get new SPI */ } keystat; +#endif struct sadb_msghdr { struct sadb_msg *msg; @@ -363,18 +369,20 @@ int extlen[SADB_EXT_MAX + 1]; }; -static struct secasvar *key_allocsa_policy __P((struct secasindex *)); +static struct secasvar *key_allocsa_policy __P((struct secasindex *, + struct vnet *)); static void key_freesp_so __P((struct secpolicy **)); -static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int)); +static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int, + struct vnet *)); static void key_delsp __P((struct secpolicy *)); -static struct secpolicy *key_getsp __P((struct secpolicyindex *)); -static struct secpolicy *key_getspbyid __P((u_int32_t)); +static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*)); +static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet*)); static u_int32_t key_newreqid __P((void)); static struct mbuf *key_gather_mbuf __P((struct mbuf *, const struct sadb_msghdr *, int, int, ...)); static int key_spdadd __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); -static u_int32_t key_getnewspid __P((void)); +static u_int32_t key_getnewspid __P((struct vnet *)); static int key_spddelete __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); static int key_spddelete2 __P((struct socket *, struct mbuf *, @@ -388,14 +396,15 @@ static struct mbuf *key_setdumpsp __P((struct secpolicy *, u_int8_t, u_int32_t, u_int32_t)); static u_int key_getspreqmsglen __P((struct secpolicy *)); -static int key_spdexpire __P((struct secpolicy *)); -static struct secashead *key_newsah __P((struct secasindex *)); +static int key_spdexpire __P((struct secpolicy *, struct vnet *)); +static struct secashead *key_newsah __P((struct secasindex *, struct vnet *)); static void key_delsah __P((struct secashead *)); static struct secasvar *key_newsav __P((struct mbuf *, const struct sadb_msghdr *, struct secashead *, int *)); static void key_delsav __P((struct secasvar *)); -static struct secashead *key_getsah __P((struct secasindex *)); -static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t)); +static struct secashead *key_getsah __P((struct secasindex *, struct vnet *)); +static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t, + struct vnet *)); static struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t)); static int key_setsaval __P((struct secasvar *, struct mbuf *, const struct sadb_msghdr *)); @@ -416,7 +425,7 @@ u_int32_t)); static void *key_newbuf __P((const void *, u_int)); #ifdef INET6 -static int key_ismyaddr6 __P((struct sockaddr_in6 *)); +static int key_ismyaddr6 __P((struct sockaddr_in6 *, struct vnet *)); #endif /* flags for key_cmpsaidx() */ @@ -440,7 +449,8 @@ static int key_getspi __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); static u_int32_t key_do_getnewspi __P((struct sadb_spirange *, - struct secasindex *)); + struct secasindex *, + struct vnet *)); static int key_update __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); #ifdef IPSEC_DOSEQCHECK @@ -465,19 +475,20 @@ static struct mbuf *key_getcomb_ipcomp __P((void)); static struct mbuf *key_getprop __P((const struct secasindex *)); -static int key_acquire __P((struct secasindex *, struct secpolicy *)); +static int key_acquire __P((struct secasindex *, struct secpolicy *, + struct vnet *)); #ifndef IPSEC_NONBLOCK_ACQUIRE -static struct secacq *key_newacq __P((struct secasindex *)); -static struct secacq *key_getacq __P((struct secasindex *)); -static struct secacq *key_getacqbyseq __P((u_int32_t)); +static struct secacq *key_newacq __P((struct secasindex *, struct vnet *)); +static struct secacq *key_getacq __P((struct secasindex *, struct vnet *)); +static struct secacq *key_getacqbyseq __P((u_int32_t, struct vnet *)); #endif static struct secspacq *key_newspacq __P((struct secpolicyindex *)); -static struct secspacq *key_getspacq __P((struct secpolicyindex *)); +static struct secspacq *key_getspacq __P((struct secpolicyindex *, struct vnet *)); static int key_acquire2 __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); static int key_register __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); -static int key_expire __P((struct secasvar *)); +static int key_expire __P((struct secasvar *, struct vnet *vnet)); static int key_flush __P((struct socket *, struct mbuf *, const struct sadb_msghdr *)); static int key_dump __P((struct socket *, struct mbuf *, @@ -486,7 +497,7 @@ const struct sadb_msghdr *)); static int key_senderror __P((struct socket *, struct mbuf *, int)); static int key_validate_ext __P((const struct sadb_ext *, int)); -static int key_align __P((struct mbuf *, struct sadb_msghdr *)); +static int key_align __P((struct mbuf *, struct sadb_msghdr *, struct vnet *)); #if 0 static const char *key_getfqdn __P((void)); static const char *key_getuserfqdn __P((void)); @@ -502,9 +513,10 @@ * others: found and return the pointer. */ struct secpolicy * -key_allocsp(spidx, dir) +key_allocsp(spidx, dir, vnet) struct secpolicyindex *spidx; u_int dir; + struct vnet *vnet; { struct secpolicy *sp; struct timeval tv; @@ -513,6 +525,8 @@ /* sanity check */ if (spidx == NULL) panic("key_allocsp: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_allocsp: NULL vnet is passed.\n"); /* check direction */ switch (dir) { @@ -529,7 +543,7 @@ printf("*** objects\n"); kdebug_secpolicyindex(spidx)); - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { KEYDEBUG(KEYDEBUG_IPSEC_DATA, printf("*** in SPD\n"); kdebug_secpolicyindex(&sp->spidx)); @@ -564,8 +578,9 @@ * XXX slow */ struct secpolicy * -key_gettunnel(osrc, odst, isrc, idst) +key_gettunnel(osrc, odst, isrc, idst, vnet) struct sockaddr *osrc, *odst, *isrc, *idst; + struct vnet *vnet; { struct secpolicy *sp; const int dir = IPSEC_DIR_INBOUND; @@ -580,9 +595,11 @@ isrc->sa_family, idst->sa_family)); return NULL; } + if (vnet == NULL) + panic("key_gettunnel: NULL vnet is passed.\n"); s = splnet(); /*called from softclock()*/ - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; @@ -639,9 +656,10 @@ * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. */ int -key_checkrequest(isr, saidx) +key_checkrequest(isr, saidx, vnet) struct ipsecrequest *isr; struct secasindex *saidx; + struct vnet *vnet; { u_int level; int error; @@ -649,6 +667,8 @@ /* sanity check */ if (isr == NULL || saidx == NULL) panic("key_checkrequest: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_checkrequest: NULL vnet is passed.\n"); /* check mode */ switch (saidx->mode) { @@ -661,7 +681,7 @@ } /* get current level */ - level = ipsec_get_reqlevel(isr); + level = ipsec_get_reqlevel(isr, vnet); #if 0 /* @@ -704,14 +724,14 @@ * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. */ if (isr->sav == NULL) - isr->sav = key_allocsa_policy(saidx); + isr->sav = key_allocsa_policy(saidx, vnet); /* When there is SA. */ if (isr->sav != NULL) return 0; /* there is no SA */ - if ((error = key_acquire(saidx, isr->sp)) != 0) { + if ((error = key_acquire(saidx, isr->sp, vnet)) != 0) { /* XXX What should I do ? */ ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned " "from key_acquire.\n", error)); @@ -728,8 +748,9 @@ * others: found and return the pointer. */ static struct secasvar * -key_allocsa_policy(saidx) +key_allocsa_policy(saidx, vnet) struct secasindex *saidx; + struct vnet *vnet; { struct secashead *sah; struct secasvar *sav; @@ -737,7 +758,9 @@ const u_int *saorder_state_valid; int arraysize; - LIST_FOREACH(sah, &sahtree, chain) { + if (vnet == NULL) + panic("key_allocsa_policy: NULL vnet is passed.\n"); + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) @@ -752,7 +775,7 @@ * search a valid state list for outbound packet. * This search order is important. */ - if (key_preferred_oldsa) { + if (vnet->key_preferred_oldsa) { saorder_state_valid = saorder_state_valid_prefer_old; arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); } else { @@ -764,7 +787,7 @@ state = saorder_state_valid[stateidx]; - sav = key_do_allocsa_policy(sah, state); + sav = key_do_allocsa_policy(sah, state, vnet); if (sav != NULL) return sav; } @@ -780,12 +803,15 @@ * others : found, pointer to a SA. */ static struct secasvar * -key_do_allocsa_policy(sah, state) +key_do_allocsa_policy(sah, state, vnet) struct secashead *sah; u_int state; + struct vnet *vnet; { struct secasvar *sav, *nextsav, *candidate, *d; + if (vnet == NULL) + panic("key_do_allocsa_policy: NULL vnet is passed.\n"); /* initilize */ candidate = NULL; @@ -812,7 +838,7 @@ "lifetime_current is NULL.\n"); /* What the best method is to compare ? */ - if (key_preferred_oldsa) { + if (vnet->key_preferred_oldsa) { if (candidate->lft_c->sadb_lifetime_addtime > sav->lft_c->sadb_lifetime_addtime) { candidate = sav; @@ -883,7 +909,7 @@ PFKEY_UNIT64(result->m_pkthdr.len); if (key_sendup_mbuf(NULL, result, - KEY_SENDUP_REGISTERED)) + KEY_SENDUP_REGISTERED, vnet)) goto msgfail; msgfail: key_freesav(d); @@ -916,10 +942,11 @@ * keep source address in IPsec SA. We see a tricky situation here. */ struct secasvar * -key_allocsa(family, src, dst, proto, spi) +key_allocsa(family, src, dst, proto, spi, vnet) u_int family, proto; caddr_t src, dst; u_int32_t spi; + struct vnet *vnet; { struct secashead *sah; struct secasvar *sav; @@ -933,12 +960,14 @@ /* sanity check */ if (src == NULL || dst == NULL) panic("key_allocsa: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_allocsa: NULL vnet is passed.\n"); /* * when both systems employ similar strategy to use a SA. * the search order is important even in the inbound case. */ - if (key_preferred_oldsa) { + if (vnet->key_preferred_oldsa) { saorder_state_valid = saorder_state_valid_prefer_old; arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); } else { @@ -953,7 +982,7 @@ * encrypted so we can't check internal IP header. */ s = splnet(); /*called from softclock()*/ - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { /* * search a valid state list for inbound packet. * the search order is not important. @@ -1248,16 +1277,19 @@ * others : found, pointer to a SP. */ static struct secpolicy * -key_getsp(spidx) +key_getsp(spidx, vnet) struct secpolicyindex *spidx; + struct vnet *vnet; { struct secpolicy *sp; /* sanity check */ if (spidx == NULL) panic("key_getsp: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_getsp: NULL vnet is passed.\n"); - LIST_FOREACH(sp, &sptree[spidx->dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (key_cmpspidx_exactly(spidx, &sp->spidx)) { @@ -1275,12 +1307,15 @@ * others : found, pointer to a SP. */ static struct secpolicy * -key_getspbyid(id) +key_getspbyid(id, vnet) u_int32_t id; + struct vnet *vnet; { struct secpolicy *sp; - LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { + if (vnet == NULL) + panic("key_getspbyid: NULL vnet is passed.\n"); + LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (sp->id == id) { @@ -1289,7 +1324,7 @@ } } - LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { + LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) { if (sp->state == IPSEC_SPSTATE_DEAD) continue; if (sp->id == id) { @@ -1735,10 +1770,14 @@ struct secpolicy *newsp; struct timeval tv; int error; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spdadd: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spdadd: NULL vnet pointer.\n"); if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || @@ -1808,7 +1847,7 @@ * If the type is either SPDADD or SPDSETIDX AND a SP is found, * then error. */ - newsp = key_getsp(&spidx); + newsp = key_getsp(&spidx, vnet); if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { if (newsp) { newsp->state = IPSEC_SPSTATE_DEAD; @@ -1827,7 +1866,7 @@ return key_senderror(so, m, error); } - if ((newsp->id = key_getnewspid()) == 0) { + if ((newsp->id = key_getnewspid(vnet)) == 0) { keydb_delsecpolicy(newsp); return key_senderror(so, m, ENOBUFS); } @@ -1879,12 +1918,13 @@ newsp->refcnt = 1; /* do not reclaim until I say I do */ newsp->state = IPSEC_SPSTATE_ALIVE; - LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); + LIST_INSERT_TAIL(&vnet->sptree[newsp->spidx.dir], newsp, + secpolicy, chain); /* delete the entry in spacqtree */ if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { struct secspacq *spacq; - if ((spacq = key_getspacq(&spidx)) != NULL) { + if ((spacq = key_getspacq(&spidx, vnet)) != NULL) { /* reset counter in order to deletion by timehandler. */ microtime(&tv); spacq->created = tv.tv_sec; @@ -1934,7 +1974,7 @@ xpl->sadb_x_policy_id = newsp->id; m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -1945,17 +1985,22 @@ * others: success. */ static u_int32_t -key_getnewspid() +key_getnewspid(vnet) + struct vnet *vnet; { u_int32_t newid = 0; - int count = key_spi_trycnt; /* XXX */ + int count; struct secpolicy *sp; + if (vnet == NULL) + panic("key_getnewspid: NULL vnet was passed."); + count = vnet->key_spi_trycnt; /* XXX */ /* when requesting to allocate spi ranged */ while (count--) { - newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1)); + newid = (vnet->policy_id = (vnet->policy_id == ~0 ? + 1 : vnet->policy_id+1)); - if ((sp = key_getspbyid(newid)) == NULL) + if ((sp = key_getspbyid(newid, vnet)) == NULL) break; key_freesp(sp); @@ -1991,10 +2036,14 @@ struct sadb_x_policy *xpl0; struct secpolicyindex spidx; struct secpolicy *sp; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spddelete: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spddelete: NULL vnet pointer.\n"); if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || @@ -2034,7 +2083,7 @@ } /* Is there SP in SPD ? */ - if ((sp = key_getsp(&spidx)) == NULL) { + if ((sp = key_getsp(&spidx, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n")); return key_senderror(so, m, EINVAL); } @@ -2060,7 +2109,7 @@ newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -2084,10 +2133,14 @@ { u_int32_t id; struct secpolicy *sp; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spddelete2: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spddelete2: NULL vnet pointer.\n"); if (mhp->ext[SADB_X_EXT_POLICY] == NULL || mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { @@ -2099,7 +2152,7 @@ id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { + if ((sp = key_getspbyid(id, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id)); key_senderror(so, m, EINVAL); } @@ -2156,7 +2209,7 @@ newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -2181,10 +2234,14 @@ u_int32_t id; struct secpolicy *sp; struct mbuf *n; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spdget: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spdget: NULL vnet pointer.\n"); if (mhp->ext[SADB_X_EXT_POLICY] == NULL || mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { @@ -2195,7 +2252,7 @@ id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { + if ((sp = key_getspbyid(id, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id)); return key_senderror(so, m, ENOENT); } @@ -2203,7 +2260,7 @@ n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); if (n != NULL) { m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); } else return key_senderror(so, m, ENOBUFS); } @@ -2224,8 +2281,9 @@ * others: error number */ int -key_spdacquire(sp) +key_spdacquire(sp, vnet) struct secpolicy *sp; + struct vnet *vnet; { struct mbuf *result = NULL, *m; struct secspacq *newspacq; @@ -2238,10 +2296,12 @@ panic("key_spdacquire: called but there is request.\n"); if (sp->policy != IPSEC_POLICY_IPSEC) panic("key_spdacquire: policy mismathed. IPsec is expected.\n"); + if (vnet == NULL) + panic("key_spdacquire: NULL vnet is passed.\n"); /* get a entry to check whether sent message or not. */ - if ((newspacq = key_getspacq(&sp->spidx)) != NULL) { - if (key_blockacq_count < newspacq->count) { + if ((newspacq = key_getspacq(&sp->spidx, vnet)) != NULL) { + if (vnet->key_blockacq_count < newspacq->count) { /* reset counter and do send message. */ newspacq->count = 0; } else { @@ -2255,7 +2315,7 @@ return ENOBUFS; /* add to acqtree */ - LIST_INSERT_HEAD(&spacqtree, newspacq, chain); + LIST_INSERT_HEAD(&vnet->spacqtree, newspacq, chain); } /* create new sadb_msg to reply. */ @@ -2273,7 +2333,7 @@ mtod(result, struct sadb_msg *)->sadb_msg_len = PFKEY_UNIT64(result->m_pkthdr.len); - return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED, vnet); fail: if (result) @@ -2302,16 +2362,20 @@ struct sadb_msg *newmsg; struct secpolicy *sp; u_int dir; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spdflush: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spdflush: NULL vnet pointer.\n"); if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) return key_senderror(so, m, EINVAL); for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { sp->state = IPSEC_SPSTATE_DEAD; } } @@ -2329,7 +2393,7 @@ newmsg->sadb_msg_errno = 0; newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); } /* @@ -2353,15 +2417,19 @@ int cnt; u_int dir; struct mbuf *n; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_spddump: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_spddump: NULL vnet pointer.\n"); /* search SPD entry and get buffer size. */ cnt = 0; for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { cnt++; } } @@ -2370,13 +2438,13 @@ return key_senderror(so, m, ENOENT); for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { + LIST_FOREACH(sp, &vnet->sptree[dir], chain) { --cnt; n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, mhp->msg->sadb_msg_pid); if (n) - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); } } @@ -2481,8 +2549,9 @@ * others : error number */ static int -key_spdexpire(sp) +key_spdexpire(sp, vnet) struct secpolicy *sp; + struct vnet *vnet; { int s; struct mbuf *result = NULL, *m; @@ -2496,6 +2565,8 @@ /* sanity check */ if (sp == NULL) panic("key_spdexpire: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_spdexpire: NULL vnet is passed.\n"); /* set msg header */ m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); @@ -2580,7 +2651,7 @@ PFKEY_UNIT64(result->m_pkthdr.len); splx(s); - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); fail: if (result) @@ -2596,14 +2667,17 @@ * others : pointer to new SA head. */ static struct secashead * -key_newsah(saidx) +key_newsah(saidx, vnet) struct secasindex *saidx; + struct vnet *vnet; { struct secashead *newsah; /* sanity check */ if (saidx == NULL) panic("key_newsaidx: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_newsaidx: NULL vnet is passed.\n"); newsah = keydb_newsecashead(); if (newsah == NULL) @@ -2613,7 +2687,7 @@ /* add to saidxtree */ newsah->state = SADB_SASTATE_MATURE; - LIST_INSERT_HEAD(&sahtree, newsah, chain); + LIST_INSERT_HEAD(&vnet->sahtree, newsah, chain); return(newsah); } @@ -2846,12 +2920,15 @@ * others : found, pointer to a SA. */ static struct secashead * -key_getsah(saidx) +key_getsah(saidx, vnet) struct secasindex *saidx; + struct vnet *vnet; { struct secashead *sah; - LIST_FOREACH(sah, &sahtree, chain) { + if (vnet == NULL) + panic("key_getsah: NULL vnet was passed."); + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) @@ -2869,13 +2946,16 @@ * others : found, pointer to a SA. */ static struct secasvar * -key_checkspidup(saidx, spi) +key_checkspidup(saidx, spi, vnet) struct secasindex *saidx; u_int32_t spi; + struct vnet *vnet; { struct secashead *sah; struct secasvar *sav; + if (vnet == NULL) + panic("key_checkspidup: NULL vnet was passed."); /* check address family */ if (saidx->src.ss_family != saidx->dst.ss_family) { ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n")); @@ -2883,8 +2963,8 @@ } /* check all SAD */ - LIST_FOREACH(sah, &sahtree, chain) { - if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst)) + LIST_FOREACH(sah, &vnet->sahtree, chain) { + if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst, vnet)) continue; sav = key_getsavbyspi(sah, spi); if (sav != NULL) @@ -3794,8 +3874,9 @@ * 0: false */ int -key_ismyaddr(sa) +key_ismyaddr(sa, vnet) struct sockaddr *sa; + struct vnet *vnet; { #ifdef INET struct sockaddr_in *sin; @@ -3805,12 +3886,14 @@ /* sanity check */ if (sa == NULL) panic("key_ismyaddr: NULL pointer is passed.\n"); + if (vnet == NULL) + panic("key_ismyaddr: NULL vnet was passed."); switch (sa->sa_family) { #ifdef INET case AF_INET: sin = (struct sockaddr_in *)sa; - for (ia = in_ifaddrhead.tqh_first; ia; + for (ia = vnet->in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) { if (sin->sin_family == ia->ia_addr.sin_family && @@ -3824,7 +3907,7 @@ #endif #ifdef INET6 case AF_INET6: - return key_ismyaddr6((struct sockaddr_in6 *)sa); + return key_ismyaddr6((struct sockaddr_in6 *)sa, vnet); #endif } @@ -3841,13 +3924,16 @@ #include static int -key_ismyaddr6(sin6) +key_ismyaddr6(sin6, vnet) struct sockaddr_in6 *sin6; + struct vnet *vnet; { struct in6_ifaddr *ia; struct in6_multi *in6m; - for (ia = in6_ifaddr; ia; ia = ia->ia_next) { + if (vnet == NULL) + panic("key_ismyaddr6: NULL vnet was passed."); + for (ia = vnet->in6_ifaddr; ia; ia = ia->ia_next) { if (key_sockaddrcmp((struct sockaddr *)&sin6, (struct sockaddr *)&ia->ia_addr, 0) == 0) return 1; @@ -4178,17 +4264,22 @@ u_int dir; int s; struct timeval tv; + struct vnet *vnet; microtime(&tv); s = splnet(); /*called from softclock()*/ + /* This timer function is called once to step through every vnet. */ + LIST_FOREACH(vnet, &vnet_head, vnet_le) + { + /* SPD */ { struct secpolicy *sp, *nextsp; for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - for (sp = LIST_FIRST(&sptree[dir]); + for (sp = LIST_FIRST(&vnet->sptree[dir]); sp != NULL; sp = nextsp) { @@ -4208,7 +4299,7 @@ || (sp->validtime && tv.tv_sec - sp->lastused > sp->validtime)) { sp->state = IPSEC_SPSTATE_DEAD; - key_spdexpire(sp); + key_spdexpire(sp, vnet); continue; } } @@ -4220,7 +4311,7 @@ struct secashead *sah, *nextsah; struct secasvar *sav, *nextsav; - for (sah = LIST_FIRST(&sahtree); + for (sah = LIST_FIRST(&vnet->sahtree); sah != NULL; sah = nextsah) { @@ -4239,7 +4330,7 @@ nextsav = LIST_NEXT(sav, chain); - if (tv.tv_sec - sav->created > key_larval_lifetime) { + if (tv.tv_sec - sav->created > vnet->key_larval_lifetime) { key_freesav(sav); } } @@ -4284,7 +4375,7 @@ * message in the status of * DYING. Do remove below code. */ - key_expire(sav); + key_expire(sav, vnet); } } @@ -4303,7 +4394,7 @@ * message in the status of * DYING. Do remove below code. */ - key_expire(sav); + key_expire(sav, vnet); } } @@ -4387,13 +4478,13 @@ { struct secacq *acq, *nextacq; - for (acq = LIST_FIRST(&acqtree); + for (acq = LIST_FIRST(&vnet->acqtree); acq != NULL; acq = nextacq) { nextacq = LIST_NEXT(acq, chain); - if (tv.tv_sec - acq->created > key_blockacq_lifetime + if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime && __LIST_CHAINED(acq)) { LIST_REMOVE(acq, chain); KFREE(acq); @@ -4406,13 +4497,13 @@ { struct secspacq *acq, *nextacq; - for (acq = LIST_FIRST(&spacqtree); + for (acq = LIST_FIRST(&vnet->spacqtree); acq != NULL; acq = nextacq) { nextacq = LIST_NEXT(acq, chain); - if (tv.tv_sec - acq->created > key_blockacq_lifetime + if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime && __LIST_CHAINED(acq)) { LIST_REMOVE(acq, chain); KFREE(acq); @@ -4421,11 +4512,13 @@ } /* initialize random seed */ - if (key_tick_init_random++ > key_int_random) { - key_tick_init_random = 0; + if (vnet->key_tick_init_random++ > vnet->key_int_random) { + vnet->key_tick_init_random = 0; key_srandom(); } + /* end LIST_FOREACH(vnet, ...) */ + } #ifndef IPSEC_DEBUG2 /* do exchange to tick time !! */ (void)timeout((void *)key_timehandler, (void *)0, hz); @@ -4562,10 +4655,14 @@ u_int8_t mode; u_int32_t reqid; int error; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_getspi: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_getspi: cannot find vnet.\n"); if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { @@ -4633,14 +4730,14 @@ /* SPI allocation */ spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE], - &saidx); + &saidx, vnet); if (spi == 0) return key_senderror(so, m, EINVAL); /* get a SA index */ - if ((newsah = key_getsah(&saidx)) == NULL) { + if ((newsah = key_getsah(&saidx, vnet)) == NULL) { /* create a new SA index */ - if ((newsah = key_newsah(&saidx)) == NULL) { + if ((newsah = key_newsah(&saidx, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n")); return key_senderror(so, m, ENOBUFS); } @@ -4661,7 +4758,7 @@ /* delete the entry in acqtree */ if (mhp->msg->sadb_msg_seq != 0) { struct secacq *acq; - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { + if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) != NULL) { /* reset counter in order to deletion by timehandler. */ struct timeval tv; microtime(&tv); @@ -4722,7 +4819,7 @@ if (n->m_len < sizeof(struct sadb_msg)) { n = m_pullup(n, sizeof(struct sadb_msg)); if (n == NULL) - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); + return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet); } n->m_pkthdr.len = 0; @@ -4735,7 +4832,7 @@ newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); } } @@ -4747,21 +4844,26 @@ * others: success. */ static u_int32_t -key_do_getnewspi(spirange, saidx) +key_do_getnewspi(spirange, saidx, vnet) struct sadb_spirange *spirange; struct secasindex *saidx; + struct vnet *vnet; { u_int32_t newspi; u_int32_t min, max; - int count = key_spi_trycnt; + int count; + + if (vnet == NULL) + panic("key_do_getnewspi: NULL vnet was passed."); + count = vnet->key_spi_trycnt; /* set spi range to allocate */ if (spirange != NULL) { min = spirange->sadb_spirange_min; max = spirange->sadb_spirange_max; } else { - min = key_spi_minval; - max = key_spi_maxval; + min = vnet->key_spi_minval; + max = vnet->key_spi_maxval; } /* IPCOMP needs 2-byte SPI */ if (saidx->proto == IPPROTO_IPCOMP) { @@ -4776,7 +4878,7 @@ } if (min == max) { - if (key_checkspidup(saidx, min) != NULL) { + if (key_checkspidup(saidx, min, vnet) != NULL) { ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min)); return 0; } @@ -4794,7 +4896,7 @@ /* generate pseudo-random SPI value ranged. */ newspi = min + (key_random() % (max - min + 1)); - if (key_checkspidup(saidx, newspi) == NULL) + if (key_checkspidup(saidx, newspi, vnet) == NULL) break; } @@ -4805,8 +4907,8 @@ } /* statistics */ - keystat.getspi_count = - (keystat.getspi_count + key_spi_trycnt - count) / 2; + vnet->keystat.getspi_count = + (vnet->keystat.getspi_count + vnet->key_spi_trycnt - count)/2; return newspi; } @@ -4839,10 +4941,14 @@ u_int8_t mode; u_int32_t reqid; int error; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_update: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_update: cannot find vnet.\n"); /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -4887,7 +4993,7 @@ KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); /* get a SA header */ - if ((sah = key_getsah(&saidx)) == NULL) { + if ((sah = key_getsah(&saidx, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_update: no SA index found.\n")); return key_senderror(so, m, ENOENT); } @@ -4963,7 +5069,7 @@ } m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -5034,10 +5140,14 @@ u_int8_t mode; u_int32_t reqid; int error; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_add: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_add: NULL vnet pointer is passed.\n"); /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -5082,9 +5192,9 @@ KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); /* get a SA header */ - if ((newsah = key_getsah(&saidx)) == NULL) { + if ((newsah = key_getsah(&saidx, vnet)) == NULL) { /* create a new SA header */ - if ((newsah = key_newsah(&saidx)) == NULL) { + if ((newsah = key_newsah(&saidx, vnet)) == NULL) { ipseclog((LOG_DEBUG, "key_add: No more memory.\n")); return key_senderror(so, m, ENOBUFS); } @@ -5130,7 +5240,7 @@ } m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -5265,10 +5375,14 @@ struct secashead *sah; struct secasvar *sav = NULL; u_int16_t proto; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_delete: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_delete: NULL vnet pointer is passed.\n"); /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -5309,7 +5423,7 @@ KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) @@ -5349,7 +5463,7 @@ newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -5368,6 +5482,11 @@ struct secashead *sah; struct secasvar *sav, *nextsav; u_int stateidx, state; + struct vnet *vnet; + + if (so == NULL || so->so_vnet == NULL) + panic("key_delete_all: cannot find vnet.\n"); + vnet = so->so_vnet; src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); @@ -5375,7 +5494,7 @@ /* XXX boundary check against sa_len */ KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) @@ -5425,7 +5544,7 @@ newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); } } @@ -5453,10 +5572,14 @@ struct secashead *sah; struct secasvar *sav = NULL; u_int16_t proto; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_get: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_get: NULL vnet pointer is passed.\n"); /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -5485,7 +5608,7 @@ KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) @@ -5518,7 +5641,7 @@ return key_senderror(so, m, ENOBUFS); m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); } } @@ -5795,9 +5918,10 @@ * others: error number */ static int -key_acquire(saidx, sp) +key_acquire(saidx, sp, vnet) struct secasindex *saidx; struct secpolicy *sp; + struct vnet *vnet; { struct mbuf *result = NULL, *m; #ifndef IPSEC_NONBLOCK_ACQUIRE @@ -5812,6 +5936,8 @@ panic("key_acquire: NULL pointer is passed.\n"); if ((satype = key_proto2satype(saidx->proto)) == 0) panic("key_acquire: invalid proto is passed.\n"); + if (vnet == NULL) + panic("key_acquire: NULL vnet is passed.\n"); #ifndef IPSEC_NONBLOCK_ACQUIRE /* @@ -5821,8 +5947,8 @@ * managed with ACQUIRING list. */ /* get a entry to check whether sending message or not. */ - if ((newacq = key_getacq(saidx)) != NULL) { - if (key_blockacq_count < newacq->count) { + if ((newacq = key_getacq(saidx, vnet)) != NULL) { + if (vnet->key_blockacq_count < newacq->count) { /* reset counter and do send message. */ newacq->count = 0; } else { @@ -5832,11 +5958,11 @@ } } else { /* make new entry for blocking to send SADB_ACQUIRE. */ - if ((newacq = key_newacq(saidx)) == NULL) + if ((newacq = key_newacq(saidx, vnet)) == NULL) return ENOBUFS; /* add to acqtree */ - LIST_INSERT_HEAD(&acqtree, newacq, chain); + LIST_INSERT_HEAD(&vnet->acqtree, newacq, chain); } #endif @@ -5966,7 +6092,7 @@ mtod(result, struct sadb_msg *)->sadb_msg_len = PFKEY_UNIT64(result->m_pkthdr.len); - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); fail: if (result) @@ -5976,12 +6102,15 @@ #ifndef IPSEC_NONBLOCK_ACQUIRE static struct secacq * -key_newacq(saidx) +key_newacq(saidx, vnet) struct secasindex *saidx; + struct vnet *vnet; { struct secacq *newacq; struct timeval tv; + if (vnet == NULL) + panic("key_newacq: NULL vnet was passed."); /* get new entry */ KMALLOC(newacq, struct secacq *, sizeof(struct secacq)); if (newacq == NULL) { @@ -5992,7 +6121,7 @@ /* copy secindex */ bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); - newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq); + newacq->seq = (vnet->acq_seq == ~0 ? 1 : ++vnet->acq_seq); microtime(&tv); newacq->created = tv.tv_sec; newacq->count = 0; @@ -6001,12 +6130,15 @@ } static struct secacq * -key_getacq(saidx) +key_getacq(saidx, vnet) struct secasindex *saidx; + struct vnet *vnet; { struct secacq *acq; - LIST_FOREACH(acq, &acqtree, chain) { + if (vnet == NULL) + panic("key_getacq: NULL vnet was passed."); + LIST_FOREACH(acq, &vnet->acqtree, chain) { if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) return acq; } @@ -6015,12 +6147,15 @@ } static struct secacq * -key_getacqbyseq(seq) +key_getacqbyseq(seq, vnet) u_int32_t seq; + struct vnet *vnet; { struct secacq *acq; - LIST_FOREACH(acq, &acqtree, chain) { + if (vnet == NULL) + panic("key_getacqbyseq: NULL vnet was passed."); + LIST_FOREACH(acq, &vnet->acqtree, chain) { if (acq->seq == seq) return acq; } @@ -6054,12 +6189,15 @@ } static struct secspacq * -key_getspacq(spidx) +key_getspacq(spidx, vnet) struct secpolicyindex *spidx; + struct vnet *vnet; { struct secspacq *acq; - LIST_FOREACH(acq, &spacqtree, chain) { + if (vnet == NULL) + panic("key_getspacq: NULL vnet was passed."); + LIST_FOREACH(acq, &vnet->spacqtree, chain) { if (key_cmpspidx_exactly(spidx, &acq->spidx)) return acq; } @@ -6092,10 +6230,14 @@ struct secashead *sah; u_int16_t proto; int error; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_acquire2: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_acquire2: NULL vnet pointer is passed.\n"); /* * Error message from KMd. @@ -6115,7 +6257,7 @@ return 0; } - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { + if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) == NULL) { /* * the specified larval SA is already gone, or we got * a bogus sequence number. we can silently ignore it. @@ -6165,7 +6307,7 @@ KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); /* get a SA index */ - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID)) @@ -6176,14 +6318,14 @@ return key_senderror(so, m, EEXIST); } - error = key_acquire(&saidx, NULL); + error = key_acquire(&saidx, NULL, vnet); if (error != 0) { ipseclog((LOG_DEBUG, "key_acquire2: error %d returned " "from key_acquire.\n", mhp->msg->sadb_msg_errno)); return key_senderror(so, m, error); } - return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED, vnet); } /* @@ -6206,13 +6348,17 @@ const struct sadb_msghdr *mhp; { struct secreg *reg, *newreg = 0; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_register: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_register: NULL vnet is passed.\n"); /* check for invalid register message */ - if (mhp->msg->sadb_msg_satype >= sizeof(regtree)/sizeof(regtree[0])) + if (mhp->msg->sadb_msg_satype >= sizeof(vnet->regtree)/sizeof(vnet->regtree[0])) return key_senderror(so, m, EINVAL); /* When SATYPE_UNSPEC is specified, only return sabd_supported. */ @@ -6220,7 +6366,7 @@ goto setmsg; /* check whether existing or not */ - LIST_FOREACH(reg, ®tree[mhp->msg->sadb_msg_satype], chain) { + LIST_FOREACH(reg, &vnet->regtree[mhp->msg->sadb_msg_satype], chain) { if (reg->so == so) { ipseclog((LOG_DEBUG, "key_register: socket exists already.\n")); return key_senderror(so, m, EEXIST); @@ -6239,7 +6385,8 @@ ((struct keycb *)sotorawcb(so))->kp_registered++; /* add regnode to regtree. */ - LIST_INSERT_HEAD(®tree[mhp->msg->sadb_msg_satype], newreg, chain); + LIST_INSERT_HEAD(&vnet->regtree[mhp->msg->sadb_msg_satype], + newreg, chain); setmsg: { @@ -6355,7 +6502,7 @@ #endif m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED, vnet); } } @@ -6369,10 +6516,14 @@ { struct secreg *reg; int i; + struct vnet *vnet; /* sanity check */ if (so == NULL) panic("key_freereg: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_freereg: NULL vnet pointer is passed.\n"); /* * check whether existing or not. @@ -6380,7 +6531,7 @@ * one socket is registered to multiple type of SA. */ for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_FOREACH(reg, ®tree[i], chain) { + LIST_FOREACH(reg, &vnet->regtree[i], chain) { if (reg->so == so && __LIST_CHAINED(reg)) { LIST_REMOVE(reg, chain); @@ -6404,8 +6555,9 @@ * others : error number */ static int -key_expire(sav) +key_expire(sav, vnet) struct secasvar *sav; + struct vnet *vnet; { int s; int satype; @@ -6414,6 +6566,8 @@ int error = -1; struct sadb_lifetime *lt; + if (vnet == NULL) + panic("key_expire: NULL vnet was passed."); /* XXX: Why do we lock ? */ s = splnet(); /*called from softclock()*/ @@ -6513,7 +6667,7 @@ PFKEY_UNIT64(result->m_pkthdr.len); splx(s); - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); + return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); fail: if (result) @@ -6546,10 +6700,14 @@ u_int16_t proto; u_int8_t state; u_int stateidx; + struct vnet *vnet; /* sanity check */ if (so == NULL || mhp == NULL || mhp->msg == NULL) panic("key_flush: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_flush: NULL vnet pointer is passed.\n"); /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -6558,7 +6716,7 @@ } /* no SATYPE specified, i.e. flushing all SA. */ - for (sah = LIST_FIRST(&sahtree); + for (sah = LIST_FIRST(&vnet->sahtree); sah != NULL; sah = nextsah) { nextsah = LIST_NEXT(sah, chain); @@ -6599,7 +6757,7 @@ newmsg->sadb_msg_errno = 0; newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); } /* @@ -6629,10 +6787,12 @@ int cnt; struct sadb_msg *newmsg; struct mbuf *n; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_dump: NULL pointer is passed.\n"); + vnet = so->so_vnet; /* map satype to proto */ if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { @@ -6642,7 +6802,7 @@ /* count sav entries to be sent to the userland. */ cnt = 0; - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; @@ -6662,7 +6822,7 @@ /* send this to the userland, one at a time. */ newmsg = NULL; - LIST_FOREACH(sah, &sahtree, chain) { + LIST_FOREACH(sah, &vnet->sahtree, chain) { if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; @@ -6683,7 +6843,7 @@ if (!n) return key_senderror(so, m, ENOBUFS); - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); } } } @@ -6704,10 +6864,14 @@ const struct sadb_msghdr *mhp; { int olen; + struct vnet *vnet; /* sanity check */ if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) panic("key_promisc: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL); + panic("key_promisc: NULL vnet pointer is passed.\n"); olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); @@ -6736,14 +6900,14 @@ /* send the original message back to everyone */ mhp->msg->sadb_msg_errno = 0; - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); } else { /* send packet as is */ m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); /* TODO: if sadb_msg_seq is specified, send to specific pid */ - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); + return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); } } @@ -6790,6 +6954,7 @@ struct mbuf *m; struct socket *so; { + struct vnet *vnet; struct sadb_msg *msg; struct sadb_msghdr mh; u_int orglen; @@ -6799,6 +6964,9 @@ /* sanity check */ if (m == NULL || so == NULL) panic("key_parse: NULL pointer is passed.\n"); + vnet = so->so_vnet; + if (vnet == NULL) + panic("key_parse: NULL vnet is passed.\n"); #if 0 /*kdebug_sadb assumes msg in linear buffer*/ KEYDEBUG(KEYDEBUG_KEY_DUMP, @@ -6818,7 +6986,7 @@ if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len != m->m_pkthdr.len) { ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n")); - pfkeystat.out_invlen++; + vnet->pfkeystat.out_invlen++; error = EINVAL; goto senderror; } @@ -6827,7 +6995,7 @@ ipseclog((LOG_DEBUG, "key_parse: PF_KEY version %u is mismatched.\n", msg->sadb_msg_version)); - pfkeystat.out_invver++; + vnet->pfkeystat.out_invver++; error = EINVAL; goto senderror; } @@ -6835,7 +7003,7 @@ if (msg->sadb_msg_type > SADB_MAX) { ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", msg->sadb_msg_type)); - pfkeystat.out_invmsgtype++; + vnet->pfkeystat.out_invmsgtype++; error = EINVAL; goto senderror; } @@ -6868,7 +7036,7 @@ } /* align the mbuf chain so that extensions are in contiguous region. */ - error = key_align(m, &mh); + error = key_align(m, &mh, vnet); if (error) return error; @@ -6892,7 +7060,7 @@ case SADB_EXPIRE: ipseclog((LOG_DEBUG, "key_parse: must specify satype " "when msg type=%u.\n", msg->sadb_msg_type)); - pfkeystat.out_invsatype++; + vnet->pfkeystat.out_invsatype++; error = EINVAL; goto senderror; } @@ -6911,7 +7079,7 @@ case SADB_X_SPDDELETE2: ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n", msg->sadb_msg_type)); - pfkeystat.out_invsatype++; + vnet->pfkeystat.out_invsatype++; error = EINVAL; goto senderror; } @@ -6922,7 +7090,7 @@ case SADB_SATYPE_MIP: ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n", msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; + vnet->pfkeystat.out_invsatype++; error = EOPNOTSUPP; goto senderror; case 1: /* XXX: What does it do? */ @@ -6932,7 +7100,7 @@ default: ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; + vnet->pfkeystat.out_invsatype++; error = EINVAL; goto senderror; } @@ -6949,7 +7117,7 @@ /* check upper layer protocol */ if (src0->sadb_address_proto != dst0->sadb_address_proto) { ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -6958,7 +7126,7 @@ if (PFKEY_ADDR_SADDR(src0)->sa_family != PFKEY_ADDR_SADDR(dst0)->sa_family) { ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -6966,7 +7134,7 @@ PFKEY_ADDR_SADDR(dst0)->sa_len) { ipseclog((LOG_DEBUG, "key_parse: address struct size mismatched.\n")); - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -6975,7 +7143,7 @@ case AF_INET: if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in)) { - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -6983,7 +7151,7 @@ case AF_INET6: if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in6)) { - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -6991,7 +7159,7 @@ default: ipseclog((LOG_DEBUG, "key_parse: unsupported address family.\n")); - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EAFNOSUPPORT; goto senderror; } @@ -7013,7 +7181,7 @@ dst0->sadb_address_prefixlen > plen) { ipseclog((LOG_DEBUG, "key_parse: illegal prefixlen.\n")); - pfkeystat.out_invaddr++; + vnet->pfkeystat.out_invaddr++; error = EINVAL; goto senderror; } @@ -7026,7 +7194,7 @@ if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) || key_typesw[msg->sadb_msg_type] == NULL) { - pfkeystat.out_invmsgtype++; + vnet->pfkeystat.out_invmsgtype++; error = EINVAL; goto senderror; } @@ -7035,7 +7203,7 @@ senderror: msg->sadb_msg_errno = error; - return key_sendup_mbuf(so, m, target); + return key_sendup_mbuf(so, m, target, vnet); } static int @@ -7044,14 +7212,18 @@ struct mbuf *m; int code; { + struct vnet *vnet; struct sadb_msg *msg; + if (so == NULL || so->so_vnet == NULL) + panic("key_senderror: cannot find vnet"); + vnet = so->so_vnet; if (m->m_len < sizeof(struct sadb_msg)) panic("invalid mbuf passed to key_senderror"); msg = mtod(m, struct sadb_msg *); msg->sadb_msg_errno = code; - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); + return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet); } /* @@ -7060,9 +7232,10 @@ * XXX larger-than-MCLBYTES extension? */ static int -key_align(m, mhp) +key_align(m, mhp, vnet) struct mbuf *m; struct sadb_msghdr *mhp; + struct vnet *vnet; { struct mbuf *n; struct sadb_ext *ext; @@ -7075,6 +7248,8 @@ panic("key_align: NULL pointer is passed.\n"); if (m->m_len < sizeof(struct sadb_msg)) panic("invalid mbuf passed to key_align"); + if (vnet == NULL) + panic("key_align: NULL vnet is passed.\n"); /* initialize */ bzero(mhp, sizeof(*mhp)); @@ -7122,7 +7297,7 @@ "key_align: duplicate ext_type %u " "is passed.\n", ext->sadb_ext_type)); m_freem(m); - pfkeystat.out_dupext++; + vnet->pfkeystat.out_dupext++; return EINVAL; } break; @@ -7131,7 +7306,7 @@ "key_align: invalid ext_type %u is passed.\n", ext->sadb_ext_type)); m_freem(m); - pfkeystat.out_invexttype++; + vnet->pfkeystat.out_invexttype++; return EINVAL; } @@ -7139,7 +7314,7 @@ if (key_validate_ext(ext, extlen)) { m_freem(m); - pfkeystat.out_invlen++; + vnet->pfkeystat.out_invlen++; return EINVAL; } @@ -7157,7 +7332,7 @@ if (off != end) { m_freem(m); - pfkeystat.out_invlen++; + vnet->pfkeystat.out_invlen++; return EINVAL; } @@ -7224,49 +7399,97 @@ } void -key_init() +key_init(vnet) + struct vnet *vnet; { int i; - bzero((caddr_t)&key_cb, sizeof(key_cb)); + if (vnet == NULL) + panic("key_init: NULL vnet was passed."); + bzero((caddr_t)&vnet->key_cb, sizeof(vnet->key_cb)); for (i = 0; i < IPSEC_DIR_MAX; i++) { - LIST_INIT(&sptree[i]); + LIST_INIT(&vnet->sptree[i]); } - LIST_INIT(&sahtree); + LIST_INIT(&vnet->sahtree); for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_INIT(®tree[i]); + LIST_INIT(&vnet->regtree[i]); } #ifndef IPSEC_NONBLOCK_ACQUIRE - LIST_INIT(&acqtree); + LIST_INIT(&vnet->acqtree); #endif - LIST_INIT(&spacqtree); + LIST_INIT(&vnet->spacqtree); /* system default */ #ifdef INET - ip4_def_policy.policy = IPSEC_POLICY_NONE; - ip4_def_policy.refcnt++; /*never reclaim this*/ + vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip4_def_policy.refcnt++; /*never reclaim this*/ #endif #ifdef INET6 - ip6_def_policy.policy = IPSEC_POLICY_NONE; - ip6_def_policy.refcnt++; /*never reclaim this*/ + vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; + vnet->ip6_def_policy.refcnt++; /*never reclaim this*/ #endif -#ifndef IPSEC_DEBUG2 - timeout((void *)key_timehandler, (void *)0, hz); -#endif /*IPSEC_DEBUG2*/ - /* initialize key statistics */ - keystat.getspi_count = 1; + vnet->keystat.getspi_count = 1; - printf("IPsec: Initialized Security Association Processing.\n"); + /* initalize vnet variables (normally static) */ + /* from netkey/key.c */ + vnet->key_spi_trycnt = 1000; + vnet->key_spi_minval = 0x100; + vnet->key_spi_maxval = 0x0fffffff; /* XXX */ + vnet->policy_id = 0; + vnet->key_int_random = 60; /*interval to initialize randseed,1(m)*/ + vnet->key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ + vnet->key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ + vnet->key_blockacq_lifetime = 20;/* lifetime f/ blocking SADB_ACQUIRE.*/ + vnet->key_preferred_oldsa = 1; /* preferred old sa rather than new sa.*/ + vnet->acq_seq = 0; + vnet->key_tick_init_random = 0; + + /* from netinet6/ipsec.c */ + vnet->ip4_ah_cleartos = 1; + vnet->ip4_ah_offsetmask = 0; /* maybe IP_DF? */ + vnet->ip4_ipsec_dfbit = 0;/* DF bit on encap. 0: clear 1: set 2: copy */ + vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE; + vnet->ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ + vnet->ip4_esp_randpad = -1; +#ifdef INET6 + /* what about ipsec6stat? */ + vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE; + vnet->ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ + vnet->ip6_esp_randpad = -1; +#endif + +/* net.inet6.ipsec6 */ + +#ifndef IPSEC_DEBUG2 + if (vnet == vnet0) /* one timehandler iterates for all vnets */ + timeout((void *)key_timehandler, (void *)0, hz); +#endif /*IPSEC_DEBUG2*/ + + if (vnet == vnet0) + printf("IPsec: Initialized Security Association Processing.\n"); return; } +void +key_destroy(vnet) +struct vnet *vnet; +{ + /* XXX do nothing */ +} + /* * XXX: maybe This function is called after INBOUND IPsec processing. * @@ -7406,13 +7629,16 @@ /* dumb version */ void -key_sa_routechange(dst) +key_sa_routechange(dst, vnet) struct sockaddr *dst; + struct vnet *vnet; { struct secashead *sah; struct route *ro; - LIST_FOREACH(sah, &sahtree, chain) { + if (vnet == NULL) + panic("key_sa_routechange: NULL vnet was passed."); + LIST_FOREACH(sah, &vnet->sahtree, chain) { ro = &sah->sa_route; if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { diff -urN sys/netkey/key.h sys.CORE/netkey/key.h --- sys/netkey/key.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/netkey/key.h Wed Jan 31 16:02:43 2007 @@ -35,7 +35,7 @@ #ifdef _KERNEL -extern struct key_cb key_cb; +/*extern struct key_cb key_cb;*/ struct secpolicy; struct secpolicyindex; @@ -46,14 +46,15 @@ struct sadb_msg; struct sadb_x_policy; -extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int)); +extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int, + struct vnet*)); extern struct secpolicy *key_gettunnel __P((struct sockaddr *, - struct sockaddr *, struct sockaddr *, struct sockaddr *)); + struct sockaddr *, struct sockaddr *, struct sockaddr *, struct vnet*)); extern int key_checkrequest __P((struct ipsecrequest *isr, struct secasindex *, struct vnet *)); extern struct secasvar *key_allocsa __P((u_int, caddr_t, caddr_t, - u_int, u_int32_t)); + u_int, u_int32_t, struct vnet *)); extern void key_freesp __P((struct secpolicy *)); extern void key_freeso __P((struct socket *)); extern void key_freesav __P((struct secasvar *)); @@ -68,11 +69,12 @@ extern void key_randomfill __P((void *, size_t)); extern void key_freereg __P((struct socket *)); extern int key_parse __P((struct mbuf *, struct socket *)); -extern void key_init __P((void)); +extern void key_init __P((struct vnet *)); +extern void key_destroy __P((struct vnet *)); extern int key_checktunnelsanity __P((struct secasvar *, u_int, caddr_t, caddr_t)); extern void key_sa_recordxfer __P((struct secasvar *, struct mbuf *)); -extern void key_sa_routechange __P((struct sockaddr *)); +extern void key_sa_routechange __P((struct sockaddr *, struct vnet *)); extern void key_sa_stir_iv __P((struct secasvar *)); #ifdef MALLOC_DECLARE diff -urN sys/netkey/keysock.c sys.CORE/netkey/keysock.c --- sys/netkey/keysock.c Wed Jan 31 15:57:05 2007 +++ sys.CORE/netkey/keysock.c Wed Jan 31 16:02:43 2007 @@ -65,9 +65,7 @@ struct sockaddr key_dst = { 2, PF_KEY, }; struct sockaddr key_src = { 2, PF_KEY, }; -static int key_sendup0 __P((struct rawcb *, struct mbuf *, int)); - -struct pfkeystat pfkeystat; +static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, struct vnet*)); /* * key_output() @@ -86,27 +84,31 @@ int s; struct socket *so; va_list ap; + struct vnet *vnet; va_start(ap, m); so = va_arg(ap, struct socket *); + vnet = va_arg(ap, struct vnet *); va_end(ap); if (m == 0) panic("key_output: NULL pointer was passed.\n"); + if (vnet == NULL) + panic("key_output: NULL vnet was passed.\n"); - pfkeystat.out_total++; - pfkeystat.out_bytes += m->m_pkthdr.len; + vnet->pfkeystat.out_total++; + vnet->pfkeystat.out_bytes += m->m_pkthdr.len; len = m->m_pkthdr.len; if (len < sizeof(struct sadb_msg)) { - pfkeystat.out_tooshort++; + vnet->pfkeystat.out_tooshort++; error = EINVAL; goto end; } if (m->m_len < sizeof(struct sadb_msg)) { if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { - pfkeystat.out_nomem++; + vnet->pfkeystat.out_nomem++; error = ENOBUFS; goto end; } @@ -118,9 +120,9 @@ KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); msg = mtod(m, struct sadb_msg *); - pfkeystat.out_msgtype[msg->sadb_msg_type]++; + vnet->pfkeystat.out_msgtype[msg->sadb_msg_type]++; if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { - pfkeystat.out_invlen++; + vnet->pfkeystat.out_invlen++; error = EINVAL; goto end; } @@ -140,13 +142,17 @@ * send message to the socket. */ static int -key_sendup0(rp, m, promisc) +key_sendup0(rp, m, promisc, vnet) struct rawcb *rp; struct mbuf *m; int promisc; + struct vnet *vnet; { int error; + if (vnet == NULL) + panic("key_sendup0: NULL vnet was passed.\n"); + if (promisc) { struct sadb_msg *pmsg; @@ -154,7 +160,7 @@ if (m && m->m_len < sizeof(struct sadb_msg)) m = m_pullup(m, sizeof(struct sadb_msg)); if (!m) { - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; m_freem(m); return ENOBUFS; } @@ -167,12 +173,12 @@ pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); /* pid and seq? */ - pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; + vnet->pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; } if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, m, NULL)) { - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; m_freem(m); error = ENOBUFS; } else @@ -196,6 +202,8 @@ /* sanity check */ if (so == 0 || msg == 0) panic("key_sendup: NULL pointer was passed.\n"); + if (vnet == NULL) + panic("key_sendup: NULL vnet was passed.\n"); KEYDEBUG(KEYDEBUG_KEY_DUMP, printf("key_sendup: \n"); @@ -205,9 +213,9 @@ * we increment statistics here, just in case we have ENOBUFS * in this function. */ - pfkeystat.in_total++; - pfkeystat.in_bytes += len; - pfkeystat.in_msgtype[msg->sadb_msg_type]++; + vnet->pfkeystat.in_total++; + vnet->pfkeystat.in_bytes += len; + vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++; /* * Get mbuf chain whenever possible (not clusters), @@ -229,7 +237,7 @@ n->m_len = MLEN; } if (!n) { - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; return ENOBUFS; } if (tlen >= MCLBYTES) { /*XXX better threshold? */ @@ -237,7 +245,7 @@ if ((n->m_flags & M_EXT) == 0) { m_free(n); m_freem(m); - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; return ENOBUFS; } n->m_len = MCLBYTES; @@ -260,9 +268,9 @@ m_copyback(m, 0, len, (caddr_t)msg); /* avoid duplicated statistics */ - pfkeystat.in_total--; - pfkeystat.in_bytes -= len; - pfkeystat.in_msgtype[msg->sadb_msg_type]--; + vnet->pfkeystat.in_total--; + vnet->pfkeystat.in_bytes -= len; + vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]--; return key_sendup_mbuf(so, m, target, vnet); } @@ -285,14 +293,16 @@ panic("key_sendup_mbuf: NULL pointer was passed.\n"); if (so == NULL && target == KEY_SENDUP_ONE) panic("key_sendup_mbuf: NULL pointer was passed.\n"); + if (vnet == NULL) + panic("key_sendup_mbuf: NULL vnet pointer was passed.\n"); - pfkeystat.in_total++; - pfkeystat.in_bytes += m->m_pkthdr.len; + vnet->pfkeystat.in_total++; + vnet->pfkeystat.in_bytes += m->m_pkthdr.len; if (m->m_len < sizeof(struct sadb_msg)) { #if 1 m = m_pullup(m, sizeof(struct sadb_msg)); if (m == NULL) { - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; return ENOBUFS; } #else @@ -302,7 +312,7 @@ if (m->m_len >= sizeof(struct sadb_msg)) { struct sadb_msg *msg; msg = mtod(m, struct sadb_msg *); - pfkeystat.in_msgtype[msg->sadb_msg_type]++; + vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++; } LIST_FOREACH(rp, &vnet->rawcb_list, list) @@ -323,7 +333,7 @@ */ if (((struct keycb *)rp)->kp_promisc) { if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { - (void)key_sendup0(rp, n, 1); + (void)key_sendup0(rp, n, 1, vnet); n = NULL; } } @@ -347,18 +357,18 @@ sendup++; break; } - pfkeystat.in_msgtarget[target]++; + vnet->pfkeystat.in_msgtarget[target]++; if (!sendup) continue; if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { m_freem(m); - pfkeystat.in_nomem++; + vnet->pfkeystat.in_nomem++; return ENOBUFS; } - if ((error = key_sendup0(rp, n, 0)) != 0) { + if ((error = key_sendup0(rp, n, 0, vnet)) != 0) { m_freem(m); return error; } @@ -367,7 +377,7 @@ } if (so) { - error = key_sendup0(sotorawcb(so), m, 0); + error = key_sendup0(sotorawcb(so), m, 0, vnet); m = NULL; } else { error = 0; @@ -397,9 +407,12 @@ static int key_attach(struct socket *so, int proto, struct proc *p) { + struct vnet *vnet = so->so_vnet; struct keycb *kp; int s, error; + if (vnet == NULL) + panic("key_attach: NULL vnet was passed.\n"); if (sotorawcb(so) != 0) return EISCONN; /* XXX panic? */ kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */ @@ -428,8 +441,8 @@ kp->kp_promisc = kp->kp_registered = 0; if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count++; - key_cb.any_count++; + vnet->key_cb.key_count++; + vnet->key_cb.any_count++; kp->kp_raw.rcb_laddr = &key_src; kp->kp_raw.rcb_faddr = &key_dst; soisconnected(so); @@ -474,15 +487,18 @@ static int key_detach(struct socket *so) { + struct vnet *vnet = so->so_vnet; struct keycb *kp = (struct keycb *)sotorawcb(so); int s, error; + if (vnet == NULL) + panic("key_detach: NULL vnet from sock."); s = splnet(); if (kp != 0) { if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count--; - key_cb.any_count--; + vnet->key_cb.key_count--; + vnet->key_cb.any_count--; key_freereg(so); } @@ -585,13 +601,13 @@ { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, 0, key_output, raw_ctlinput, 0, 0, - raw_init, 0, 0, 0, + raw_init, raw_destroy, 0, 0, 0, &key_usrreqs } }; struct domain keydomain = - { PF_KEY, "key", key_init, 0, 0, + { PF_KEY, "key", key_init, key_destroy, 0, 0, keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] }; DOMAIN_SET(key); diff -urN sys/netkey/keysock.h sys.CORE/netkey/keysock.h --- sys/netkey/keysock.h Wed Jan 31 15:57:05 2007 +++ sys.CORE/netkey/keysock.h Wed Jan 31 16:02:43 2007 @@ -69,8 +69,6 @@ int kp_registered; /* registered socket */ }; -extern struct pfkeystat pfkeystat; - extern int key_output __P((struct mbuf *, ...)); extern int key_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *)); core-4.6/kernel/freebsd/freebsd7-config-COREDEBUG0000664000175000017500000000057312021411051016304 00000000000000# # VIMAGE - sample kernel configuration file with a virtualized network stack # configure. # # $FreeBSD$ # include GENERIC ident COREDEBUG device crypto options IPSEC options VIMAGE options DDB options GDB options KDB options KDB_TRACE # # Some kernel subsystems and functions don't yet compile with VIMAGE. Remove # from the configuration for now. # nooptions SCTP core-4.6/kernel/freebsd/freebsd7-config-CORE0000664000175000017500000000062312021411051015531 00000000000000# # VIMAGE - sample kernel configuration file with a virtualized network stack # configure. # # $FreeBSD$ # include GENERIC ident CORE options IPSEC device crypto options VIMAGE options IPFIREWALL options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default # # Some kernel subsystems and functions don't yet compile with VIMAGE. Remove # from the configuration for now. # nooptions SCTP core-4.6/kernel/freebsd/README.txt0000664000175000017500000000235412021411051013615 00000000000000CORE kernel patches For information on the kernel modules ng_pipe and ng_wlan, see the README files in their respective directories. You should run the make && make install from the module directories for CORE to work properly. FreeBSD 8.x requires the small patches to allow per-node directories. The FreeBSD 7.x version of CORE does not require the patch included here. Instead you should download the latest vimage_7 kernel from: http://imunes.net/virtnet/ The FreeBSD 4.11 version of CORE requires the included patch to work. See the CORE manual for patching details. ng_pipe module you should install with FreeBSD 4.11 or 7.x ng_wlan module you should install with FreeBSD 4.11 or 7.x 4.11-R-CORE.diff patch you should use with FreeBSD 4.11 freebsd7-config-CORE config that you may use with vimage_7 kernels freebsd7-config-COREDEBUG debugging config for use with vimage_7 kernels vimage_7-CORE.diff patch to add multicast routing to vimage_7_20081015 imunes-8.0-RELEASE.diff per-node directories, persistent hub/switch, and traffic snopping for wireshark for FreeBSD 8.0 symlinks-8.1-RELEASE.diff per-node directories for FreeBSD 8.1 core-4.6/kernel/core-kernel-3.5/0000775000175000017500000000000012220631372013305 500000000000000core-4.6/kernel/core-kernel-3.5/patches/0000775000175000017500000000000012220631372014734 500000000000000core-4.6/kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch0000664000175000017500000002270412077611200021311 00000000000000From 5af499895ded68e1d42510df30be2004b4b778bf Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Thu, 26 Jul 2012 23:57:06 -0700 Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per netns. This allows subsystems to create per-netns entries. Signed-off-by: Tom Goff --- include/linux/netfilter.h | 5 ----- include/net/net_namespace.h | 3 +++ net/netfilter/core.c | 35 +++++++++++++++++++++++------- net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++---- net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++---- net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++----------- net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------ 7 files changed, 148 insertions(+), 48 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index ff9c84c..e28a566 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -350,11 +350,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #endif } -#ifdef CONFIG_PROC_FS -#include -extern struct proc_dir_entry *proc_net_netfilter; -#endif - #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 1b9c99a..449fc8e 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -86,6 +86,9 @@ struct net { struct netns_dccp dccp; #endif #ifdef CONFIG_NETFILTER +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_net_netfilter; +#endif struct netns_xt xt; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index e19f365..c7c9f39 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -266,25 +266,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) EXPORT_SYMBOL(nf_conntrack_destroy); #endif /* CONFIG_NF_CONNTRACK */ +static int __net_init netfilter_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", + net->proc_net); + if (!net->proc_net_netfilter) { + pr_err("%s: cannot create netfilter proc entry\n", __func__); + return -ENOMEM; + } +#endif + + return 0; +} + +static void __net_exit netfilter_net_exit(struct net *net) +{ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; -EXPORT_SYMBOL(proc_net_netfilter); + proc_net_remove(net, "netfilter"); #endif +} + +static struct pernet_operations netfilter_net_ops = { + .init = netfilter_net_init, + .exit = netfilter_net_exit, +}; void __init netfilter_init(void) { int i, h; + + if (register_pernet_subsys(&netfilter_net_ops)) + panic("%s: failed to register per netns operations", __func__); + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } -#ifdef CONFIG_PROC_FS - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); - if (!proc_net_netfilter) - panic("cannot create netfilter proc entry"); -#endif - if (netfilter_queue_init() < 0) panic("cannot initialize nf_queue"); if (netfilter_log_init() < 0) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 703fb26..4507932 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void) } #endif /* CONFIG_SYSCTL */ -int __init netfilter_log_init(void) +static int __net_init netfilter_log_net_init(struct net *net) { - int i, r; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + net->proc_net_netfilter, &nflog_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit netfilter_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_log", net->proc_net_netfilter); #endif +} + +static struct pernet_operations netfilter_log_net_ops = { + .init = netfilter_log_net_init, + .exit = netfilter_log_net_exit, +}; + +int __init netfilter_log_init(void) +{ + int i, r; + + r = register_pernet_subsys(&netfilter_log_net_ops); + if (r) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return r; + } /* Errors will trigger panic, unroll on error is unnecessary. */ r = netfilter_log_sysctl_init(); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ce60cf0..288c6f5 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -407,14 +407,37 @@ static const struct file_operations nfqueue_file_ops = { }; #endif /* PROC_FS */ - -int __init netfilter_queue_init(void) +static int __net_init netfilter_queue_net_init(struct net *net) { #ifdef CONFIG_PROC_FS if (!proc_create("nf_queue", S_IRUGO, - proc_net_netfilter, &nfqueue_file_ops)) - return -1; + net->proc_net_netfilter, &nfqueue_file_ops)) + return -ENOMEM; #endif + return 0; } +static void __net_exit netfilter_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations netfilter_queue_net_ops = { + .init = netfilter_queue_net_init, + .exit = netfilter_queue_net_exit, +}; + +int __init netfilter_queue_init(void) +{ + int err; + + err = register_pernet_subsys(&netfilter_queue_net_ops); + if (err) + pr_err("%s: cannot initialize per netns operations\n", + __func__); + + return err; +} diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index bbc1d91..e5c1731 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -966,9 +966,39 @@ static const struct file_operations nful_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_log_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_log", 0440, + net->proc_net_netfilter, &nful_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_log_net_ops = { + .init = nfnetlink_log_net_init, + .exit = nfnetlink_log_net_exit, +}; + static int __init nfnetlink_log_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_log_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -991,17 +1021,8 @@ static int __init nfnetlink_log_init(void) goto cleanup_subsys; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) - goto cleanup_logger; -#endif return status; -#ifdef CONFIG_PROC_FS -cleanup_logger: - nf_log_unregister(&nfulnl_logger); -#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: @@ -1012,9 +1033,6 @@ cleanup_netlink_notifier: static void __exit nfnetlink_log_fini(void) { nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 4162437..add33dc 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -982,9 +982,39 @@ static const struct file_operations nfqnl_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_queue_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_queue", 0440, + net->proc_net_netfilter, &nfqnl_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_queue_net_ops = { + .init = nfnetlink_queue_net_init, + .exit = nfnetlink_queue_net_exit, +}; + static int __init nfnetlink_queue_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_queue_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -996,19 +1026,9 @@ static int __init nfnetlink_queue_init(void) goto cleanup_netlink_notifier; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) - goto cleanup_subsys; -#endif - register_netdevice_notifier(&nfqnl_dev_notifier); return status; -#ifdef CONFIG_PROC_FS -cleanup_subsys: - nfnetlink_subsys_unregister(&nfqnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; @@ -1018,9 +1038,6 @@ static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handlers(&nfqh); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- 1.7.10.4 core-4.6/kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch0000664000175000017500000003466412077611200021322 00000000000000From 1ede1963c84e15359d4b5bf7fb01587d90bcf1d4 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Thu, 26 Jul 2012 23:58:38 -0700 Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. Make nfnetlink_queue network namespace aware including a per-netns /proc/net/netfilter/nfnetlink_queue file. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 6 ++ include/net/netfilter/nf_queue.h | 3 +- include/net/netns/nfqnl.h | 14 ++++ net/netfilter/nf_queue.c | 12 +++- net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++------------------- 5 files changed, 101 insertions(+), 70 deletions(-) create mode 100644 include/net/netns/nfqnl.h diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 449fc8e..c4229f1 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -21,6 +21,9 @@ #include #endif #include +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) +#include +#endif struct proc_dir_entry; struct net_device; @@ -95,6 +98,9 @@ struct net { #endif struct sock *nfnl; struct sock *nfnl_stash; +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) + struct netns_nfqnl nfqnl; +#endif #endif #ifdef CONFIG_WEXT_CORE struct sk_buff_head wext_nlevents; diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 252fd10..3e5bde8 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -19,7 +19,8 @@ struct nf_queue_entry { /* Packet queuing */ struct nf_queue_handler { - int (*outfn)(struct nf_queue_entry *entry, + int (*outfn)(struct net *net, + struct nf_queue_entry *entry, unsigned int queuenum); char *name; }; diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h new file mode 100644 index 0000000..0fe7fbe --- /dev/null +++ b/include/net/netns/nfqnl.h @@ -0,0 +1,14 @@ +#ifndef __NETNS_NFQNL_H +#define __NETNS_NFQNL_H + +#include +#include + +#define NFQNL_INSTANCE_BUCKETS 16 + +struct netns_nfqnl { + spinlock_t instances_lock; + struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; +}; + +#endif /* __NETNS_NFQNL_H */ diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 288c6f5..3cb8733 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, #endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; + struct net *net; + + if (indev) + net = dev_net(indev); + else if (skb->sk) + net = sock_net(skb->sk); + else if (outdev) + net = dev_net(outdev); + else + return status; /* QUEUE == DROP if no one is waiting, to be safe. */ rcu_read_lock(); @@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, #endif skb_dst_force(skb); afinfo->saveroute(skb, entry); - status = qh->outfn(entry, queuenum); + status = qh->outfn(net, entry, queuenum); rcu_read_unlock(); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index add33dc..43c50bb 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -64,24 +64,19 @@ struct nfqnl_instance { typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -static DEFINE_SPINLOCK(instances_lock); - -#define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; - static inline u_int8_t instance_hashfn(u_int16_t queue_num) { - return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; + return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct net *net, u_int16_t queue_num) { struct hlist_head *head; struct hlist_node *pos; struct nfqnl_instance *inst; - head = &instance_table[instance_hashfn(queue_num)]; + head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int pid) +instance_create(struct net *net, u_int16_t queue_num, int pid) { struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&net->nfqnl.instances_lock); + if (instance_lookup(net, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return ERR_PTR(err); } @@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct net *net, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + spin_lock(&net->nfqnl.instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); } static inline void @@ -400,7 +395,8 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { struct sk_buff *nskb; struct nfqnl_instance *queue; @@ -408,7 +404,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) __be32 *packet_id_ptr; /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(net, queuenum); if (!queue) { err = -ESRCH; goto err_out; @@ -440,7 +436,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) *packet_id_ptr = htonl(entry->id); /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -549,16 +545,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; rcu_read_lock(); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &net->nfqnl.instance_table[i]; hlist_for_each_entry_rcu(inst, tmp, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -575,12 +571,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -598,19 +591,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, int i; /* destroy all instances for this pid */ - spin_lock(&instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + spin_lock(&n->net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &n->net->nfqnl.instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((n->net == &init_net) && - (n->pid == inst->peer_pid)) + if (n->pid == inst->peer_pid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&n->net->nfqnl.instances_lock); } return NOTIFY_DONE; } @@ -630,11 +623,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { [NFQA_MARK] = { .type = NLA_U32 }, }; -static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) +static struct nfqnl_instance *verdict_instance_lookup(struct net *net, + u16 queue_num, int nlpid) { struct nfqnl_instance *queue; - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) return ERR_PTR(-ENODEV); @@ -678,7 +672,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, LIST_HEAD(batch_list); u16 queue_num = ntohs(nfmsg->res_id); - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); + queue = verdict_instance_lookup(sock_net(ctnl), queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -723,11 +718,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; unsigned int verdict; struct nf_queue_entry *entry; + struct net *net = sock_net(ctnl); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); + queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -782,6 +778,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); if (nfqa[NFQA_CFG_CMD]) { cmd = nla_data(nfqa[NFQA_CFG_CMD]); @@ -798,7 +795,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto err_out_unlock; @@ -811,7 +808,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).pid); + queue = instance_create(net, queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -822,7 +820,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(net, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -886,65 +884,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct net *net, struct iter_state *st) { - struct iter_state *st = seq->private; - if (!st) return NULL; - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { + if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) + return net->nfqnl.instance_table[st->bucket].first; } return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct net *net, struct iter_state *st, + struct hlist_node *h) { - struct iter_state *st = seq->private; - h = h->next; while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) + if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + h = net->nfqnl.instance_table[st->bucket].first; } return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct net *net, struct iter_state *st, + loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(net, st); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(net, st, head))) pos--; return pos ? NULL : head; } static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) { - spin_lock(&instances_lock); - return get_idx(seq, *pos); + struct net *net = seq_file_net(seq); + spin_lock(&net->nfqnl.instances_lock); + return get_idx(net, seq->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s, v); + return get_next(seq_file_net(s), s->private, v); } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) { - spin_unlock(&instances_lock); + struct net *net = seq_file_net(s); + spin_unlock(&net->nfqnl.instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -968,8 +965,8 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nfqnl_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nfqnl_file_ops = { @@ -977,13 +974,19 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ static int __net_init nfnetlink_queue_net_init(struct net *net) { + int i; + + spin_lock_init(&net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); + #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_queue", 0440, net->proc_net_netfilter, &nfqnl_file_ops)) @@ -1007,7 +1010,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { static int __init nfnetlink_queue_init(void) { - int i, status; + int status; status = register_pernet_subsys(&nfnetlink_queue_net_ops); if (status) { @@ -1016,9 +1019,6 @@ static int __init nfnetlink_queue_init(void) return status; } - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); - netlink_register_notifier(&nfqnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfqnl_subsys); if (status < 0) { -- 1.7.10.4 core-4.6/kernel/core-kernel-3.5/patches/00-ifindex.patch0000664000175000017500000000336412077611200017544 00000000000000From e98f08306dd0dc854d93339730a8603638173e23 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Fri, 27 Jul 2012 00:02:50 -0700 Subject: [PATCH] Make network device ifindex sequential per network namespace. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 2 ++ net/core/dev.c | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index ac9195e..1b9c99a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -62,6 +62,8 @@ struct net { struct sock *rtnl; /* rtnetlink socket */ struct sock *genl_sock; + int ifindex; + struct list_head dev_base_head; struct hlist_head *dev_name_head; struct hlist_head *dev_index_head; diff --git a/net/core/dev.c b/net/core/dev.c index 3ad746b..7bec156 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5168,12 +5168,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) */ static int dev_new_index(struct net *net) { - static int ifindex; for (;;) { - if (++ifindex <= 0) - ifindex = 1; - if (!__dev_get_by_index(net, ifindex)) - return ifindex; + if (++net->ifindex <= 0) + net->ifindex = 1; + if (!__dev_get_by_index(net, net->ifindex)) + return net->ifindex; } } @@ -6182,8 +6181,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Actually switch the network namespace */ dev_net_set(dev, net); - /* If there is an ifindex conflict assign a new one */ - if (__dev_get_by_index(net, dev->ifindex)) { + /* Assign a new ifindex */ + { int iflink = (dev->iflink == dev->ifindex); dev->ifindex = dev_new_index(net); if (iflink) -- 1.7.10.4 core-4.6/kernel/core-kernel-3.5/Makefile0000664000175000017500000000363012077611200014665 00000000000000VERSION := $(shell dpkg -l linux-source 2> /dev/null | \ awk '/^i/ {print gensub("([0-9]+[.][0-9]+[.][0-9]+)[.0-9]*", "\\1", "1", $$3)}') TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 SUBVERSION := -core REVISION := 1.0 PATCHDIR := patches PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) CONFIG := config.core DEPDEBS := linux-source kernel-package po-debconf gettext CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \ awk '/^CPU\(s\)/ {print $$2}') ifeq ($(strip $(CONCURRENCY_LEVEL)),) CONCURRENCY_LEVEL := 1 endif MAINTAINER ?= $(shell id -nu) EMAIL ?= $(MAINTAINER)@$(shell hostname -f) MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ --append-to-version $(SUBVERSION) --revision $(REVISION) .PHONY: build build: debcheck defaultconfig patch export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && \ if [ -f ../$(CONFIG) ]; then \ cat ../$(CONFIG) >> .config; \ fi && \ fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch .PHONY: debcheck debcheck: for d in $(DEPDEBS); do \ if ! dpkg-query -s $$d > /dev/null 2>&1; then \ echo ERROR: build dependency not installed: $$d >&2; \ exit 1; \ fi; \ done .PHONY: defaultconfig defaultconfig: linux-source-$(VERSION) export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure .PHONY: patch patch: linux-source-$(VERSION) patch-stamp patch-stamp: $(PATCHES) for p in $^; do \ if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ echo ERROR: applying patch failed: $$p >&2; \ exit 1; \ fi; \ done touch patch-stamp .PHONY: source source: linux-source-$(VERSION) linux-source-$(VERSION): $(TARBALL) tar -xjf $^ .PHONY: clean clean: rm -rf linux-source-$(VERSION) patch-stamp core-4.6/kernel/core-kernel-3.5/config.core0000664000175000017500000000003112077611200015334 00000000000000CONFIG_XFRM_STATISTICS=y core-4.6/kernel/core-kernel-2.6.38/0000775000175000017500000000000012220631372013536 500000000000000core-4.6/kernel/core-kernel-2.6.38/patches/0000775000175000017500000000000012220631372015165 500000000000000core-4.6/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch0000664000175000017500000013541511574504065022247 00000000000000netfilter: make nfnetlink network namespace aware Move static variables to structures allocated per netns and accessed with generic net pointers. Make nfnetlink subsystem registration per netns. Make proc filesystem entries per netns. --- include/linux/netfilter.h | 2 +- include/linux/netfilter/nfnetlink.h | 10 +- include/net/netfilter/nf_queue.h | 3 +- net/ipv4/netfilter/ip_queue.c | 6 +- net/ipv6/netfilter/ip6_queue.c | 6 +- net/netfilter/core.c | 55 +++++++-- net/netfilter/nf_conntrack_netlink.c | 55 ++++++--- net/netfilter/nf_log.c | 34 ++++-- net/netfilter/nf_queue.c | 47 ++++++- net/netfilter/nfnetlink.c | 89 ++++++++++---- net/netfilter/nfnetlink_log.c | 218 ++++++++++++++++++++++------------ net/netfilter/nfnetlink_queue.c | 191 ++++++++++++++++++++---------- net/netfilter/xt_osf.c | 42 +++++-- 13 files changed, 537 insertions(+), 221 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 1893837..f52e719 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -329,7 +329,7 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #ifdef CONFIG_PROC_FS #include -extern struct proc_dir_entry *proc_net_netfilter; +extern struct proc_dir_entry *proc_net_netfilter(struct net *net); #endif #else /* !CONFIG_NETFILTER */ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 361d6b5..8acaa17 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -70,8 +70,10 @@ struct nfnetlink_subsystem { const struct nfnl_callback *cb; /* callback for individual types */ }; -extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); -extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); +extern int nfnetlink_subsys_register(struct net *net, + const struct nfnetlink_subsystem *n); +extern int nfnetlink_subsys_unregister(struct net *net, + const struct nfnetlink_subsystem *n); extern int nfnetlink_has_listeners(struct net *net, unsigned int group); extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, @@ -79,8 +81,8 @@ extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigne extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); -extern void nfnl_lock(void); -extern void nfnl_unlock(void); +extern void nfnl_lock(struct net *net); +extern void nfnl_unlock(struct net *net); #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 252fd10..3e5bde8 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -19,7 +19,8 @@ struct nf_queue_entry { /* Packet queuing */ struct nf_queue_handler { - int (*outfn)(struct nf_queue_entry *entry, + int (*outfn)(struct net *net, + struct nf_queue_entry *entry, unsigned int queuenum); char *name; }; diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d2c1311..bccef48 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -223,7 +223,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -237,6 +238,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 413ab07..b227789 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -223,7 +223,8 @@ nlmsg_failure: } static int -ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; @@ -237,6 +238,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) spin_lock_bh(&queue_lock); + if (!net_eq(net, &init_net)) + goto err_out_free_nskb; + if (!peer_pid) goto err_out_free_nskb; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 4aa614b..157785f 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "nf_internals.h" @@ -249,24 +250,62 @@ EXPORT_SYMBOL(nf_conntrack_destroy); #endif /* CONFIG_NF_CONNTRACK */ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; +static int netfilter_net_id __read_mostly; +struct netns_netfilter { + struct proc_dir_entry *proc_net_netfilter; +}; + +struct proc_dir_entry *proc_net_netfilter(struct net *net) +{ + struct netns_netfilter *net_netfilter; + + net_netfilter = net_generic(net, netfilter_net_id); + return net_netfilter->proc_net_netfilter; +} EXPORT_SYMBOL(proc_net_netfilter); -#endif + +static int __net_init netfilter_net_init(struct net *net) +{ + struct netns_netfilter *net_netfilter = + net_generic(net, netfilter_net_id); + + net_netfilter->proc_net_netfilter = + proc_net_mkdir(net, "netfilter", net->proc_net); + if (!net_netfilter->proc_net_netfilter) { + pr_err("cannot create netfilter proc entry\n"); + return -ENOMEM; + } + + return 0; +} + +static void __net_exit netfilter_net_exit(struct net *net) +{ + proc_net_remove(net, "netfilter"); +} + +static struct pernet_operations netfilter_net_ops = { + .init = netfilter_net_init, + .exit = netfilter_net_exit, + .id = &netfilter_net_id, + .size = sizeof(struct netns_netfilter), +}; +#endif /* CONFIG_PROC_FS */ void __init netfilter_init(void) { int i, h; + +#ifdef CONFIG_PROC_FS + if (register_pernet_subsys(&netfilter_net_ops)) + panic("netfilter_init: cannot initialize per netns operations"); +#endif + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } -#ifdef CONFIG_PROC_FS - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); - if (!proc_net_netfilter) - panic("cannot create netfilter proc entry"); -#endif - if (netfilter_queue_init() < 0) panic("cannot initialize nf_queue"); if (netfilter_log_init() < 0) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index eead9db..6c22c74 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -984,20 +984,21 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, const struct nlattr *attr) { typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup; + struct net *net = nf_ct_net(ct); parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook); if (!parse_nat_setup) { #ifdef CONFIG_MODULES rcu_read_unlock(); spin_unlock_bh(&nf_conntrack_lock); - nfnl_unlock(); + nfnl_unlock(net); if (request_module("nf-nat-ipv4") < 0) { - nfnl_lock(); + nfnl_lock(net); spin_lock_bh(&nf_conntrack_lock); rcu_read_lock(); return -EOPNOTSUPP; } - nfnl_lock(); + nfnl_lock(net); spin_lock_bh(&nf_conntrack_lock); rcu_read_lock(); if (nfnetlink_parse_nat_setup_hook) @@ -2114,28 +2115,59 @@ MODULE_ALIAS("ip_conntrack_netlink"); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); -static int __init ctnetlink_init(void) +static int __net_init ctnetlink_net_init(struct net *net) { int ret; pr_info("ctnetlink v%s: registering with nfnetlink.\n", version); - ret = nfnetlink_subsys_register(&ctnl_subsys); + ret = nfnetlink_subsys_register(net, &ctnl_subsys); if (ret < 0) { pr_err("ctnetlink_init: cannot register with nfnetlink.\n"); goto err_out; } - ret = nfnetlink_subsys_register(&ctnl_exp_subsys); + ret = nfnetlink_subsys_register(net, &ctnl_exp_subsys); if (ret < 0) { pr_err("ctnetlink_init: cannot register exp with nfnetlink.\n"); goto err_unreg_subsys; } + return 0; + +err_unreg_subsys: + nfnetlink_subsys_unregister(net, &ctnl_subsys); +err_out: + return ret; +} + +static void __net_exit ctnetlink_net_exit(struct net *net) +{ + pr_info("ctnetlink: unregistering from nfnetlink.\n"); + + nfnetlink_subsys_unregister(net, &ctnl_exp_subsys); + nfnetlink_subsys_unregister(net, &ctnl_subsys); +} + +static struct pernet_operations ctnetlink_net_ops = { + .init = ctnetlink_net_init, + .exit = ctnetlink_net_exit, +}; + +static int __init ctnetlink_init(void) +{ + int ret; + + ret = register_pernet_subsys(&ctnetlink_net_ops); + if (ret) { + pr_err("ctnetlink_init: cannot initialize ctnetlink.\n"); + goto err_out; + } + #ifdef CONFIG_NF_CONNTRACK_EVENTS ret = nf_conntrack_register_notifier(&ctnl_notifier); if (ret < 0) { pr_err("ctnetlink_init: cannot register notifier.\n"); - goto err_unreg_exp_subsys; + goto err_out; } ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); @@ -2150,27 +2182,20 @@ static int __init ctnetlink_init(void) #ifdef CONFIG_NF_CONNTRACK_EVENTS err_unreg_notifier: nf_conntrack_unregister_notifier(&ctnl_notifier); -err_unreg_exp_subsys: - nfnetlink_subsys_unregister(&ctnl_exp_subsys); #endif -err_unreg_subsys: - nfnetlink_subsys_unregister(&ctnl_subsys); err_out: return ret; } static void __exit ctnetlink_exit(void) { - pr_info("ctnetlink: unregistering from nfnetlink.\n"); - nf_ct_remove_userspace_expectations(); #ifdef CONFIG_NF_CONNTRACK_EVENTS nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); nf_conntrack_unregister_notifier(&ctnl_notifier); #endif - nfnetlink_subsys_unregister(&ctnl_exp_subsys); - nfnetlink_subsys_unregister(&ctnl_subsys); + unregister_pernet_subsys(&ctnetlink_net_ops); } module_init(ctnetlink_init); diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 9181699..6c193b1 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -209,7 +209,24 @@ static const struct file_operations nflog_file_ops = { .release = seq_release, }; +static int __net_init netfilter_log_net_init(struct net *net) +{ + if (!proc_create("nf_log", S_IRUGO, + proc_net_netfilter(net), &nflog_file_ops)) + return -ENOMEM; + + return 0; +} +static void __net_exit netfilter_log_net_exit(struct net *net) +{ + remove_proc_entry("nf_log", proc_net_netfilter(net)); +} + +static struct pernet_operations netfilter_log_net_ops = { + .init = netfilter_log_net_init, + .exit = netfilter_log_net_exit, +}; #endif /* PROC_FS */ #ifdef CONFIG_SYSCTL @@ -288,26 +305,27 @@ static __init int netfilter_log_sysctl_init(void) return 0; } -#else -static __init int netfilter_log_sysctl_init(void) -{ - return 0; -} #endif /* CONFIG_SYSCTL */ int __init netfilter_log_init(void) { int i, r; + #ifdef CONFIG_PROC_FS - if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + r = register_pernet_subsys(&netfilter_log_net_ops); + if (r) { + pr_err("netfilter_log_init: " + "cannot initialize per netns operations\n"); + return r; + } #endif +#ifdef CONFIG_SYSCTL /* Errors will trigger panic, unroll on error is unnecessary. */ r = netfilter_log_sysctl_init(); if (r < 0) return r; +#endif for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) INIT_LIST_HEAD(&(nf_loggers_l[i])); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 74aebed..c9fc05f 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -123,6 +123,7 @@ static int __nf_queue(struct sk_buff *skb, #endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; + struct net *net = NULL; /* QUEUE == DROP if noone is waiting, to be safe. */ rcu_read_lock(); @@ -156,6 +157,17 @@ static int __nf_queue(struct sk_buff *skb, return 0; } + if (indev) + net = dev_net(indev); + else if (outdev) + net = dev_net(outdev); + else if (skb->sk) + net = sock_net(skb->sk); + else { + pr_warn("%s: no net for skb: %p\n", __func__, skb); + goto err_unlock; + } + /* Bump dev refs so they don't vanish while packet is out */ if (indev) dev_hold(indev); @@ -173,7 +185,7 @@ static int __nf_queue(struct sk_buff *skb, #endif skb_dst_force(skb); afinfo->saveroute(skb, entry); - status = qh->outfn(entry, queuenum); + status = qh->outfn(net, entry, queuenum); rcu_read_unlock(); @@ -344,16 +356,37 @@ static const struct file_operations nfqueue_file_ops = { .llseek = seq_lseek, .release = seq_release, }; -#endif /* PROC_FS */ - -int __init netfilter_queue_init(void) +static int __net_init netfilter_queue_net_init(struct net *net) { -#ifdef CONFIG_PROC_FS if (!proc_create("nf_queue", S_IRUGO, - proc_net_netfilter, &nfqueue_file_ops)) + proc_net_netfilter(net), &nfqueue_file_ops)) return -1; -#endif + return 0; } +static void __net_exit netfilter_queue_net_exit(struct net *net) +{ + remove_proc_entry("nf_queue", proc_net_netfilter(net)); +} + +static struct pernet_operations netfilter_queue_net_ops = { + .init = netfilter_queue_net_init, + .exit = netfilter_queue_net_exit, +}; +#endif /* PROC_FS */ + +int __init netfilter_queue_init(void) +{ + int err = 0; + +#ifdef CONFIG_PROC_FS + err = register_pernet_subsys(&netfilter_queue_net_ops); + if (err) + pr_err("netfilter_queue_init: " + "cannot initialize per netns operations\n"); +#endif + + return err; +} diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index b4a4532..235da38 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,55 +37,79 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); +static int nfnl_net_id __read_mostly; +struct netns_nfnl { + const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; + struct mutex nfnl_mutex; +}; + static char __initdata nfversion[] = "0.30"; -static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; -static DEFINE_MUTEX(nfnl_mutex); +static void __nfnl_lock(struct netns_nfnl *net_nfnl) +{ + mutex_lock(&net_nfnl->nfnl_mutex); +} -void nfnl_lock(void) +void nfnl_lock(struct net *net) { - mutex_lock(&nfnl_mutex); + struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); + + __nfnl_lock(net_nfnl); } EXPORT_SYMBOL_GPL(nfnl_lock); -void nfnl_unlock(void) +static void __nfnl_unlock(struct netns_nfnl *net_nfnl) +{ + mutex_unlock(&net_nfnl->nfnl_mutex); +} + +void nfnl_unlock(struct net *net) { - mutex_unlock(&nfnl_mutex); + struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); + + __nfnl_unlock(net_nfnl); } EXPORT_SYMBOL_GPL(nfnl_unlock); -int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) +int nfnetlink_subsys_register(struct net *net, + const struct nfnetlink_subsystem *n) { - nfnl_lock(); - if (subsys_table[n->subsys_id]) { - nfnl_unlock(); + struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); + + __nfnl_lock(net_nfnl); + if (net_nfnl->subsys_table[n->subsys_id]) { + __nfnl_unlock(net_nfnl); return -EBUSY; } - subsys_table[n->subsys_id] = n; - nfnl_unlock(); + net_nfnl->subsys_table[n->subsys_id] = n; + __nfnl_unlock(net_nfnl); return 0; } EXPORT_SYMBOL_GPL(nfnetlink_subsys_register); -int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) +int nfnetlink_subsys_unregister(struct net *net, + const struct nfnetlink_subsystem *n) { - nfnl_lock(); - subsys_table[n->subsys_id] = NULL; - nfnl_unlock(); + struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); + + __nfnl_lock(net_nfnl); + net_nfnl->subsys_table[n->subsys_id] = NULL; + __nfnl_unlock(net_nfnl); return 0; } EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); -static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type) +static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(struct netns_nfnl *net_nfnl, + u_int16_t type) { u_int8_t subsys_id = NFNL_SUBSYS_ID(type); if (subsys_id >= NFNL_SUBSYS_COUNT) return NULL; - return subsys_table[subsys_id]; + return net_nfnl->subsys_table[subsys_id]; } static inline const struct nfnl_callback * @@ -129,6 +155,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) const struct nfnl_callback *nc; const struct nfnetlink_subsystem *ss; int type, err; + struct netns_nfnl *net_nfnl; if (security_netlink_recv(skb, CAP_NET_ADMIN)) return -EPERM; @@ -137,15 +164,17 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) return 0; + net_nfnl = net_generic(net, nfnl_net_id); + type = nlh->nlmsg_type; replay: - ss = nfnetlink_get_subsys(type); + ss = nfnetlink_get_subsys(net_nfnl, type); if (!ss) { #ifdef CONFIG_MODULES - nfnl_unlock(); + nfnl_unlock(net); request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); - nfnl_lock(); - ss = nfnetlink_get_subsys(type); + nfnl_lock(net); + ss = nfnetlink_get_subsys(net_nfnl, type); if (!ss) #endif return -EINVAL; @@ -176,14 +205,18 @@ replay: static void nfnetlink_rcv(struct sk_buff *skb) { - nfnl_lock(); + struct net *net = sock_net(skb->sk); + + nfnl_lock(net); netlink_rcv_skb(skb, &nfnetlink_rcv_msg); - nfnl_unlock(); + nfnl_unlock(net); } static int __net_init nfnetlink_net_init(struct net *net) { struct sock *nfnl; + int i; + struct netns_nfnl *net_nfnl; nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX, nfnetlink_rcv, NULL, THIS_MODULE); @@ -191,6 +224,12 @@ static int __net_init nfnetlink_net_init(struct net *net) return -ENOMEM; net->nfnl_stash = nfnl; rcu_assign_pointer(net->nfnl, nfnl); + + net_nfnl = net_generic(net, nfnl_net_id); + for (i = 0; i < NFNL_SUBSYS_COUNT; i++) + net_nfnl->subsys_table[i] = NULL; + mutex_init(&net_nfnl->nfnl_mutex); + return 0; } @@ -208,6 +247,8 @@ static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list) static struct pernet_operations nfnetlink_net_ops = { .init = nfnetlink_net_init, .exit_batch = nfnetlink_net_exit_batch, + .id = &nfnl_net_id, + .size = sizeof(struct netns_nfnl), }; static int __init nfnetlink_init(void) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 6a1572b..44508bb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include @@ -67,14 +69,17 @@ struct nfulnl_instance { u_int16_t flags; u_int8_t copy_mode; struct rcu_head rcu; -}; -static DEFINE_SPINLOCK(instances_lock); -static atomic_t global_seq; + struct net *net; +}; #define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS]; -static unsigned int hash_init; +static int nfulnl_net_id __read_mostly; +struct netns_nfulnl { + spinlock_t instances_lock; + atomic_t global_seq; + struct hlist_head instance_table[INSTANCE_BUCKETS]; +}; static inline u_int8_t instance_hashfn(u_int16_t group_num) { @@ -82,13 +87,13 @@ static inline u_int8_t instance_hashfn(u_int16_t group_num) } static struct nfulnl_instance * -__instance_lookup(u_int16_t group_num) +__instance_lookup(struct netns_nfulnl *net_nfulnl, u_int16_t group_num) { struct hlist_head *head; struct hlist_node *pos; struct nfulnl_instance *inst; - head = &instance_table[instance_hashfn(group_num)]; + head = &net_nfulnl->instance_table[instance_hashfn(group_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->group_num == group_num) return inst; @@ -103,12 +108,12 @@ instance_get(struct nfulnl_instance *inst) } static struct nfulnl_instance * -instance_lookup_get(u_int16_t group_num) +instance_lookup_get(struct netns_nfulnl *net_nfulnl, u_int16_t group_num) { struct nfulnl_instance *inst; rcu_read_lock_bh(); - inst = __instance_lookup(group_num); + inst = __instance_lookup(net_nfulnl, group_num); if (inst && !atomic_inc_not_zero(&inst->use)) inst = NULL; rcu_read_unlock_bh(); @@ -118,7 +123,10 @@ instance_lookup_get(u_int16_t group_num) static void nfulnl_instance_free_rcu(struct rcu_head *head) { - kfree(container_of(head, struct nfulnl_instance, rcu)); + struct nfulnl_instance *inst = + container_of(head, struct nfulnl_instance, rcu); + put_net(inst->net); + kfree(inst); module_put(THIS_MODULE); } @@ -132,13 +140,14 @@ instance_put(struct nfulnl_instance *inst) static void nfulnl_timer(unsigned long data); static struct nfulnl_instance * -instance_create(u_int16_t group_num, int pid) +instance_create(struct net *net, struct netns_nfulnl *net_nfulnl, + u_int16_t group_num, int pid) { struct nfulnl_instance *inst; int err; - spin_lock_bh(&instances_lock); - if (__instance_lookup(group_num)) { + spin_lock_bh(&net_nfulnl->instances_lock); + if (__instance_lookup(net_nfulnl, group_num)) { err = -EEXIST; goto out_unlock; } @@ -171,15 +180,17 @@ instance_create(u_int16_t group_num, int pid) inst->copy_mode = NFULNL_COPY_PACKET; inst->copy_range = NFULNL_COPY_RANGE_MAX; + inst->net = get_net(net); + hlist_add_head_rcu(&inst->hlist, - &instance_table[instance_hashfn(group_num)]); + &net_nfulnl->instance_table[instance_hashfn(group_num)]); - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&net_nfulnl->instances_lock); return inst; out_unlock: - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&net_nfulnl->instances_lock); return ERR_PTR(err); } @@ -208,11 +219,11 @@ __instance_destroy(struct nfulnl_instance *inst) } static inline void -instance_destroy(struct nfulnl_instance *inst) +instance_destroy(struct netns_nfulnl *net_nfulnl, struct nfulnl_instance *inst) { - spin_lock_bh(&instances_lock); + spin_lock_bh(&net_nfulnl->instances_lock); __instance_destroy(inst); - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&net_nfulnl->instances_lock); } static int @@ -334,7 +345,7 @@ __nfulnl_send(struct nfulnl_instance *inst) NLMSG_DONE, sizeof(struct nfgenmsg)); - status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_pid, + status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_pid, MSG_DONTWAIT); inst->qlen = 0; @@ -369,7 +380,8 @@ nfulnl_timer(unsigned long data) /* This is an inline function, we don't really care about a long * list of arguments */ static inline int -__build_packet_message(struct nfulnl_instance *inst, +__build_packet_message(struct netns_nfulnl *net_nfulnl, + struct nfulnl_instance *inst, const struct sk_buff *skb, unsigned int data_len, u_int8_t pf, @@ -507,7 +519,7 @@ __build_packet_message(struct nfulnl_instance *inst, /* global sequence number */ if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL, - htonl(atomic_inc_return(&global_seq))); + htonl(atomic_inc_return(&net_nfulnl->global_seq))); if (data_len) { struct nlattr *nla; @@ -563,13 +575,16 @@ nfulnl_log_packet(u_int8_t pf, const struct nf_loginfo *li; unsigned int qthreshold; unsigned int plen; + struct netns_nfulnl *net_nfulnl; + + net_nfulnl = net_generic(dev_net(in), nfulnl_net_id); if (li_user && li_user->type == NF_LOG_TYPE_ULOG) li = li_user; else li = &default_loginfo; - inst = instance_lookup_get(li->u.ulog.group); + inst = instance_lookup_get(net_nfulnl, li->u.ulog.group); if (!inst) return; @@ -651,7 +666,7 @@ nfulnl_log_packet(u_int8_t pf, inst->qlen++; - __build_packet_message(inst, skb, data_len, pf, + __build_packet_message(net_nfulnl, inst, skb, data_len, pf, hooknum, in, out, li, prefix, plen); if (inst->qlen >= qthreshold) @@ -680,24 +695,26 @@ nfulnl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; + struct netns_nfulnl *net_nfulnl; + net_nfulnl = net_generic(n->net, nfulnl_net_id); if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { int i; /* destroy all instances for this pid */ - spin_lock_bh(&instances_lock); + spin_lock_bh(&net_nfulnl->instances_lock); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfulnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &net_nfulnl->instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((net_eq(n->net, &init_net)) && - (n->pid == inst->peer_pid)) + if (n->pid == inst->peer_pid) __instance_destroy(inst); } } - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&net_nfulnl->instances_lock); } return NOTIFY_DONE; } @@ -739,6 +756,10 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfulnl_instance *inst; struct nfulnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); + struct netns_nfulnl *net_nfulnl; + + net_nfulnl = net_generic(net, nfulnl_net_id); if (nfula[NFULA_CFG_CMD]) { u_int8_t pf = nfmsg->nfgen_family; @@ -754,7 +775,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } } - inst = instance_lookup_get(group_num); + inst = instance_lookup_get(net_nfulnl, group_num); if (inst && inst->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto out_put; @@ -768,7 +789,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto out_put; } - inst = instance_create(group_num, + inst = instance_create(net, net_nfulnl, group_num, NETLINK_CB(skb).pid); if (IS_ERR(inst)) { ret = PTR_ERR(inst); @@ -781,7 +802,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto out; } - instance_destroy(inst); + instance_destroy(net_nfulnl, inst); goto out_put; default: ret = -ENOTSUPP; @@ -867,37 +888,45 @@ struct iter_state { unsigned int bucket; }; -static struct hlist_node *get_first(struct iter_state *st) +static struct hlist_node *get_first(struct seq_file *seq) { + struct iter_state *st = seq->private; + struct netns_nfulnl *net_nfulnl; + if (!st) return NULL; + net_nfulnl = net_generic(seq_file_net(seq), nfulnl_net_id); for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return rcu_dereference_bh(instance_table[st->bucket].first); + if (!hlist_empty(&net_nfulnl->instance_table[st->bucket])) + return rcu_dereference_bh(net_nfulnl->instance_table[st->bucket].first); } return NULL; } -static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) +static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) { + struct iter_state *st = seq->private; + struct netns_nfulnl *net_nfulnl; + + net_nfulnl = net_generic(seq_file_net(seq), nfulnl_net_id); h = rcu_dereference_bh(h->next); while (!h) { if (++st->bucket >= INSTANCE_BUCKETS) return NULL; - h = rcu_dereference_bh(instance_table[st->bucket].first); + h = rcu_dereference_bh(net_nfulnl->instance_table[st->bucket].first); } return h; } -static struct hlist_node *get_idx(struct iter_state *st, loff_t pos) +static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) { struct hlist_node *head; - head = get_first(st); + head = get_first(seq); if (head) - while (pos && (head = get_next(st, head))) + while (pos && (head = get_next(seq, head))) pos--; return pos ? NULL : head; } @@ -906,13 +935,13 @@ static void *seq_start(struct seq_file *seq, loff_t *pos) __acquires(rcu_bh) { rcu_read_lock_bh(); - return get_idx(seq->private, *pos); + return get_idx(seq, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s->private, v); + return get_next(s, v); } static void seq_stop(struct seq_file *s, void *v) @@ -941,8 +970,8 @@ static const struct seq_operations nful_seq_ops = { static int nful_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nful_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nful_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nful_file_ops = { @@ -950,62 +979,103 @@ static const struct file_operations nful_file_ops = { .open = nful_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ -static int __init nfnetlink_log_init(void) +static int __net_init nfnetlink_log_net_init(struct net *net) { - int i, status = -ENOMEM; + int err, i; + struct netns_nfulnl *net_nfulnl = net_generic(net, nfulnl_net_id); + spin_lock_init(&net_nfulnl->instances_lock); + atomic_set(&net_nfulnl->global_seq, 0); for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); + INIT_HLIST_HEAD(&net_nfulnl->instance_table[i]); - /* it's not really all that important to have a random value, so - * we can do this from the init function, even if there hasn't - * been that much entropy yet */ - get_random_bytes(&hash_init, sizeof(hash_init)); +#ifdef CONFIG_PROC_FS + if (proc_net_fops_create(net, "nfnetlink_log", 0440, + &nful_file_ops)) + return -ENOMEM; +#endif - netlink_register_notifier(&nfulnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfulnl_subsys); - if (status < 0) { + err = nfnetlink_subsys_register(net, &nfulnl_subsys); + if (err < 0) { printk(KERN_ERR "log: failed to create netlink socket\n"); - goto cleanup_netlink_notifier; + goto cleanup_proc; } - status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); - if (status < 0) { - printk(KERN_ERR "log: failed to register logger\n"); - goto cleanup_subsys; - } + return 0; +cleanup_proc: #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) - goto cleanup_logger; + proc_net_remove(net, "nfnetlink_log"); #endif - return status; + return err; +} + +static void __net_exit nfnetlink_log_net_exit(struct net *net) +{ + int i; + struct netns_nfulnl *net_nfulnl; + nfnetlink_subsys_unregister(net, &nfulnl_subsys); #ifdef CONFIG_PROC_FS -cleanup_logger: - nf_log_unregister(&nfulnl_logger); + proc_net_remove(net, "nfnetlink_log"); #endif -cleanup_subsys: - nfnetlink_subsys_unregister(&nfulnl_subsys); + + net_nfulnl = net_generic(net, nfulnl_net_id); + spin_lock_bh(&net_nfulnl->instances_lock); + for (i = 0; i < INSTANCE_BUCKETS; i++) { + struct hlist_node *tmp, *t2; + struct nfulnl_instance *inst; + struct hlist_head *head = &net_nfulnl->instance_table[i]; + + hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) + __instance_destroy(inst); + } + spin_unlock_bh(&net_nfulnl->instances_lock); +} + +static struct pernet_operations nfnetlink_log_net_ops = { + .init = nfnetlink_log_net_init, + .exit = nfnetlink_log_net_exit, + .id = &nfulnl_net_id, + .size = sizeof(struct netns_nfulnl), +}; + +static int __init nfnetlink_log_init(void) +{ + int err; + + err = register_pernet_subsys(&nfnetlink_log_net_ops); + if (err) { + pr_err("nfnetlink_log_init: " + "cannot initialize per netns operations\n"); + return err; + } + + netlink_register_notifier(&nfulnl_rtnl_notifier); + + err = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); + if (err < 0) { + pr_err("log: failed to register logger\n"); + goto cleanup_netlink_notifier; + } + + return err; + cleanup_netlink_notifier: netlink_unregister_notifier(&nfulnl_rtnl_notifier); - return status; + return err; } static void __exit nfnetlink_log_fini(void) { nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif - nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); + unregister_pernet_subsys(&nfnetlink_log_net_ops); } MODULE_DESCRIPTION("netfilter userspace logging"); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 68e67d1..3fa78a7 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include @@ -62,12 +64,14 @@ struct nfqnl_instance { struct list_head queue_list; /* packets in queue */ }; -typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - -static DEFINE_SPINLOCK(instances_lock); - #define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; +static int nfqnl_net_id __read_mostly; +struct netns_nfqnl { + spinlock_t instances_lock; + struct hlist_head instance_table[INSTANCE_BUCKETS]; +}; + +typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); static inline u_int8_t instance_hashfn(u_int16_t queue_num) { @@ -75,13 +79,14 @@ static inline u_int8_t instance_hashfn(u_int16_t queue_num) } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct net *net, u_int16_t queue_num) { struct hlist_head *head; struct hlist_node *pos; struct nfqnl_instance *inst; + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - head = &instance_table[instance_hashfn(queue_num)]; + head = &net_nfqnl->instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -90,14 +95,15 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int pid) +instance_create(struct net *net, u_int16_t queue_num, int pid) { + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&net_nfqnl->instances_lock); + if (instance_lookup(net, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -122,16 +128,16 @@ instance_create(u_int16_t queue_num, int pid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &net_nfqnl->instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&net_nfqnl->instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&net_nfqnl->instances_lock); return ERR_PTR(err); } @@ -157,11 +163,13 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct net *net, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); + + spin_lock(&net_nfqnl->instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&net_nfqnl->instances_lock); } static inline void @@ -383,14 +391,15 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { struct sk_buff *nskb; struct nfqnl_instance *queue; int err; /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(net, queuenum); if (!queue) goto err_out; @@ -416,7 +425,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) } /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -525,16 +534,17 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); rcu_read_lock(); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct hlist_node *tmp; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &net_nfqnl->instance_table[i]; hlist_for_each_entry_rcu(inst, tmp, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -551,12 +561,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -569,24 +576,25 @@ nfqnl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; + struct netns_nfqnl *net_nfqnl = net_generic(n->net, nfqnl_net_id); if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { int i; /* destroy all instances for this pid */ - spin_lock(&instances_lock); + spin_lock(&net_nfqnl->instances_lock); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &net_nfqnl->instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((n->net == &init_net) && - (n->pid == inst->peer_pid)) + if (n->pid == inst->peer_pid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&net_nfqnl->instances_lock); } return NOTIFY_DONE; } @@ -614,9 +622,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, unsigned int verdict; struct nf_queue_entry *entry; int err; + struct net *net = sock_net(ctnl); rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) { err = -ENODEV; goto err_out_unlock; @@ -692,6 +701,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); if (nfqa[NFQA_CFG_CMD]) { cmd = nla_data(nfqa[NFQA_CFG_CMD]); @@ -708,7 +718,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto err_out_unlock; @@ -721,7 +731,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).pid); + queue = instance_create(net, queue_num, + NETLINK_CB(skb).pid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -732,7 +743,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(net, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -799,13 +810,15 @@ struct iter_state { static struct hlist_node *get_first(struct seq_file *seq) { struct iter_state *st = seq->private; + struct net *net = seq_file_net(seq); + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); if (!st) return NULL; for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + if (!hlist_empty(&net_nfqnl->instance_table[st->bucket])) + return net_nfqnl->instance_table[st->bucket].first; } return NULL; } @@ -813,13 +826,15 @@ static struct hlist_node *get_first(struct seq_file *seq) static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) { struct iter_state *st = seq->private; + struct net *net = seq_file_net(seq); + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); h = h->next; while (!h) { if (++st->bucket >= INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + h = net_nfqnl->instance_table[st->bucket].first; } return h; } @@ -836,9 +851,11 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) } static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) { - spin_lock(&instances_lock); + struct netns_nfqnl *net_nfqnl = + net_generic(seq_file_net(seq), nfqnl_net_id); + + spin_lock(&net_nfqnl->instances_lock); return get_idx(seq, *pos); } @@ -849,9 +866,11 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) { - spin_unlock(&instances_lock); + struct netns_nfqnl *net_nfqnl = + net_generic(seq_file_net(s), nfqnl_net_id); + + spin_unlock(&net_nfqnl->instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -875,8 +894,8 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nfqnl_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nfqnl_file_ops = { @@ -884,54 +903,96 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ -static int __init nfnetlink_queue_init(void) +static int __net_init nfnetlink_queue_net_init(struct net *net) { - int i, status = -ENOMEM; + int err, i; + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); + spin_lock_init(&net_nfqnl->instances_lock); for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); + INIT_HLIST_HEAD(&net_nfqnl->instance_table[i]); - netlink_register_notifier(&nfqnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfqnl_subsys); - if (status < 0) { +#ifdef CONFIG_PROC_FS + if (proc_net_fops_create(net, "nfnetlink_queue", 0440, + &nfqnl_file_ops) == NULL) + return -ENOMEM; +#endif + + err = nfnetlink_subsys_register(net, &nfqnl_subsys); + if (err < 0) { printk(KERN_ERR "nf_queue: failed to create netlink socket\n"); - goto cleanup_netlink_notifier; + goto cleanup_proc; } + return 0; + +cleanup_proc: #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) - goto cleanup_subsys; + proc_net_remove(net, "nfnetlink_queue"); #endif + return err; +} - register_netdevice_notifier(&nfqnl_dev_notifier); - return status; +static void __net_exit nfnetlink_queue_net_exit(struct net *net) +{ + int i; + struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); + nfnetlink_subsys_unregister(net, &nfqnl_subsys); #ifdef CONFIG_PROC_FS -cleanup_subsys: - nfnetlink_subsys_unregister(&nfqnl_subsys); + proc_net_remove(net, "nfnetlink_queue"); #endif -cleanup_netlink_notifier: - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - return status; + + spin_lock(&net_nfqnl->instances_lock); + for (i = 0; i < INSTANCE_BUCKETS; i++) { + struct hlist_node *tmp, *t2; + struct nfqnl_instance *inst; + struct hlist_head *head = &net_nfqnl->instance_table[i]; + + hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) + __instance_destroy(inst); + } + spin_unlock(&net_nfqnl->instances_lock); +} + +static struct pernet_operations nfnetlink_queue_net_ops = { + .init = nfnetlink_queue_net_init, + .exit = nfnetlink_queue_net_exit, + .id = &nfqnl_net_id, + .size = sizeof(struct netns_nfqnl), +}; + +static int __init nfnetlink_queue_init(void) +{ + int err; + + err = register_pernet_subsys(&nfnetlink_queue_net_ops); + if (err) { + pr_err("nfnetlink_queue_init: " + "cannot initialize per netns operations\n"); + return err; + } + + netlink_register_notifier(&nfqnl_rtnl_notifier); + register_netdevice_notifier(&nfqnl_dev_notifier); + + return err; } static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handlers(&nfqh); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif - nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); rcu_barrier(); /* Wait for completion of call_rcu()'s */ + + unregister_pernet_subsys(&nfnetlink_queue_net_ops); } MODULE_DESCRIPTION("netfilter packet queue handler"); diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 4327e10..62fdeb1 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -359,6 +360,27 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) return fmatch == FMATCH_OK; } +static int __net_init xt_osf_net_init(struct net *net) +{ + int err; + + err = nfnetlink_subsys_register(net, &xt_osf_nfnetlink); + if (err < 0) + pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err); + + return err; +} + +static void __net_exit xt_osf_net_exit(struct net *net) +{ + nfnetlink_subsys_unregister(net, &xt_osf_nfnetlink); +} + +static struct pernet_operations xt_osf_net_ops = { + .init = xt_osf_net_init, + .exit = xt_osf_net_exit, +}; + static struct xt_match xt_osf_match = { .name = "osf", .revision = 0, @@ -374,29 +396,26 @@ static struct xt_match xt_osf_match = { static int __init xt_osf_init(void) { - int err = -EINVAL; + int err; int i; for (i=0; iifindex <= 0) + net->ifindex = 1; + if (!__dev_get_by_index(net, net->ifindex)) + return net->ifindex; } } @@ -5918,8 +5917,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Actually switch the network namespace */ dev_net_set(dev, net); - /* If there is an ifindex conflict assign a new one */ - if (__dev_get_by_index(net, dev->ifindex)) { + /* Assign a new ifindex */ + { int iflink = (dev->iflink == dev->ifindex); dev->ifindex = dev_new_index(net); if (iflink) core-4.6/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.flow-cache.patch0000664000175000017500000000152411574504065022260 00000000000000Only use the flow cache for the initial network namespace. The flow cache is not per netns and its entries do not include what namespace they are valid for. This causes problems when transformed traffic is sent between namespaces. --- net/core/flow.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/net/core/flow.c b/net/core/flow.c index 127c8a7..890510f 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -24,6 +24,7 @@ #include #include #include +#include struct flow_cache_entry { union { @@ -227,6 +228,9 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, if (!fcp->hash_table) goto nocache; + if (!net_eq(net, &init_net)) + goto nocache; + if (fcp->hash_rnd_recalc) flow_new_hash_rnd(fc, fcp); core-4.6/kernel/core-kernel-2.6.38/Makefile0000664000175000017500000000313411574504065015130 00000000000000VERSION := 2.6.38 TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 SUBVERSION := -core REVISION := 1.0 PATCHDIR := patches PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) CONFIG := config.core DEPDEBS := linux-source kernel-package po-debconf gettext CONCURRENCY_LEVEL := 2 MAINTAINER ?= Tom Goff EMAIL ?= thomas.goff@boeing.com MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ --append-to-version $(SUBVERSION) --revision $(REVISION) .PHONY: build build: debcheck defaultconfig patch export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && \ if [ -f ../$(CONFIG) ]; then \ cat ../$(CONFIG) >> .config; \ fi && \ fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch .PHONY: debcheck debcheck: for d in $(DEPDEBS); do \ if ! dpkg-query -s $$d > /dev/null 2>&1; then \ echo ERROR: build dependency not installed: $$d >&2; \ exit 1; \ fi; \ done .PHONY: defaultconfig defaultconfig: linux-source-$(VERSION) export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure .PHONY: patch patch: linux-source-$(VERSION) patch-stamp patch-stamp: $(PATCHES) for p in $^; do \ if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ echo ERROR: applying patch failed: $$p >&2; \ exit 1; \ fi; \ done touch patch-stamp linux-source-$(VERSION): $(TARBALL) tar -xjf $^ .PHONY: clean clean: rm -rf linux-source-$(VERSION) patch-stamp core-4.6/kernel/core-kernel-2.6.38/config.core0000664000175000017500000000003111574504065015600 00000000000000CONFIG_XFRM_STATISTICS=y core-4.6/kernel/core-kernel-2.6.38/README.txt0000664000175000017500000000077112021412002015143 00000000000000Author: Tom Goff The Makefile is basically a wrapper around the make-kpkg command that simplifies building kernel packages. Running make will do some basic dependency checks then build architecture appropriate kernel packages that include changes from the patches directory. The nfnetlink patch is what virtualizes the netfilter queue mechanism; the flow-cache patch allows using IPsec between network namespaces; the ifindex patch virtualizes network interface index numbers. core-4.6/kernel/core-kernel-3.8/0000775000175000017500000000000012220631372013310 500000000000000core-4.6/kernel/core-kernel-3.8/patches/0000775000175000017500000000000012220631372014737 500000000000000core-4.6/kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch0000664000175000017500000002052712153242402021314 00000000000000From 433bc9e01b6a50db276c0b0d9dcd8bfcc2bc42f8 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Mon, 3 Jun 2013 18:30:31 -0700 Subject: [PATCH 2/3] netfilter: Make the /proc/net/netfilter directory per netns. This allows subsystems to create per-netns entries. Signed-off-by: Tom Goff --- include/linux/netfilter.h | 5 ---- include/net/net_namespace.h | 3 +++ net/netfilter/core.c | 35 ++++++++++++++++++++------- net/netfilter/nf_log.c | 33 ++++++++++++++++++++++---- net/netfilter/nfnetlink_log.c | 46 ++++++++++++++++++++++++------------ net/netfilter/nfnetlink_queue_core.c | 45 ++++++++++++++++++++++++----------- 6 files changed, 121 insertions(+), 46 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index ee14284..0060fde 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -289,11 +289,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #endif } -#ifdef CONFIG_PROC_FS -#include -extern struct proc_dir_entry *proc_net_netfilter; -#endif - #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index de644bc..96b2242 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -94,6 +94,9 @@ struct net { struct netns_dccp dccp; #endif #ifdef CONFIG_NETFILTER +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_net_netfilter; +#endif struct netns_xt xt; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a9c488b..00e356d 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -276,25 +276,44 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); EXPORT_SYMBOL(nf_nat_decode_session_hook); #endif +static int __net_init netfilter_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", + net->proc_net); + if (!net->proc_net_netfilter) { + pr_err("%s: cannot create netfilter proc entry\n", __func__); + return -ENOMEM; + } +#endif + + return 0; +} + +static void __net_exit netfilter_net_exit(struct net *net) +{ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; -EXPORT_SYMBOL(proc_net_netfilter); + proc_net_remove(net, "netfilter"); #endif +} + +static struct pernet_operations netfilter_net_ops = { + .init = netfilter_net_init, + .exit = netfilter_net_exit, +}; void __init netfilter_init(void) { int i, h; + + if (register_pernet_subsys(&netfilter_net_ops)) + panic("%s: failed to register per netns operations", __func__); + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } -#ifdef CONFIG_PROC_FS - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); - if (!proc_net_netfilter) - panic("cannot create netfilter proc entry"); -#endif - if (netfilter_log_init() < 0) panic("cannot initialize nf_log"); } diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 9e31269..5f33072 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void) } #endif /* CONFIG_SYSCTL */ -int __init netfilter_log_init(void) +static int __net_init netfilter_log_net_init(struct net *net) { - int i, r; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + net->proc_net_netfilter, &nflog_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit netfilter_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_log", net->proc_net_netfilter); #endif +} + +static struct pernet_operations netfilter_log_net_ops = { + .init = netfilter_log_net_init, + .exit = netfilter_log_net_exit, +}; + +int __init netfilter_log_init(void) +{ + int i, r; + + r = register_pernet_subsys(&netfilter_log_net_ops); + if (r) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return r; + } /* Errors will trigger panic, unroll on error is unnecessary. */ r = netfilter_log_sysctl_init(); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 92fd8ec..9571c43 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -986,9 +986,39 @@ static const struct file_operations nful_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_log_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_log", 0440, + net->proc_net_netfilter, &nful_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_log_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_log_net_ops = { + .init = nfnetlink_log_net_init, + .exit = nfnetlink_log_net_exit, +}; + static int __init nfnetlink_log_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_log_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -1011,19 +1041,8 @@ static int __init nfnetlink_log_init(void) goto cleanup_subsys; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) { - status = -ENOMEM; - goto cleanup_logger; - } -#endif return status; -#ifdef CONFIG_PROC_FS -cleanup_logger: - nf_log_unregister(&nfulnl_logger); -#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: @@ -1034,9 +1053,6 @@ cleanup_netlink_notifier: static void __exit nfnetlink_log_fini(void) { nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); } diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 3158d87..8f2d9bb 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -1048,9 +1048,39 @@ static const struct file_operations nfqnl_file_ops = { #endif /* PROC_FS */ +static int __net_init nfnetlink_queue_net_init(struct net *net) +{ +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_queue", 0440, + net->proc_net_netfilter, &nfqnl_file_ops)) + return -ENOMEM; +#endif + + return 0; +} + +static void __net_exit nfnetlink_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); +#endif +} + +static struct pernet_operations nfnetlink_queue_net_ops = { + .init = nfnetlink_queue_net_init, + .exit = nfnetlink_queue_net_exit, +}; + static int __init nfnetlink_queue_init(void) { - int i, status = -ENOMEM; + int i, status; + + status = register_pernet_subsys(&nfnetlink_queue_net_ops); + if (status) { + pr_err("%s: failed to register per netns operations\n", + __func__); + return status; + } for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -1062,20 +1092,10 @@ static int __init nfnetlink_queue_init(void) goto cleanup_netlink_notifier; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) - goto cleanup_subsys; -#endif - register_netdevice_notifier(&nfqnl_dev_notifier); nf_register_queue_handler(&nfqh); return status; -#ifdef CONFIG_PROC_FS -cleanup_subsys: - nfnetlink_subsys_unregister(&nfqnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; @@ -1085,9 +1105,6 @@ static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handler(); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- 1.8.1.2 core-4.6/kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch0000664000175000017500000003405512153242402021316 00000000000000From 3d1c0bfef9d6ca43050e7a9077b46e0139ee1e1f Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Mon, 3 Jun 2013 18:31:29 -0700 Subject: [PATCH 3/3] netfilter: nfnetlink_queue: Add netns support. Make nfnetlink_queue network namespace aware including a per-netns /proc/net/netfilter/nfnetlink_queue file. Signed-off-by: Tom Goff --- include/net/net_namespace.h | 6 ++ include/net/netfilter/nf_queue.h | 3 +- net/netfilter/nf_queue.c | 12 ++- net/netfilter/nfnetlink_queue_core.c | 137 ++++++++++++++++++----------------- 4 files changed, 88 insertions(+), 70 deletions(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 96b2242..1af155b 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -22,6 +22,9 @@ #include #endif #include +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) +#include +#endif struct user_namespace; struct proc_dir_entry; @@ -106,6 +109,9 @@ struct net { #endif struct sock *nfnl; struct sock *nfnl_stash; +#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) + struct netns_nfqnl nfqnl; +#endif #endif #ifdef CONFIG_WEXT_CORE struct sk_buff_head wext_nlevents; diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index fb1c0be..484453d 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -19,7 +19,8 @@ struct nf_queue_entry { /* Packet queuing */ struct nf_queue_handler { - int (*outfn)(struct nf_queue_entry *entry, + int (*outfn)(struct net *net, + struct nf_queue_entry *entry, unsigned int queuenum); }; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d812c12..0d69be9 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -81,6 +81,16 @@ static int __nf_queue(struct sk_buff *skb, #endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; + struct net *net; + + if (indev) + net = dev_net(indev); + else if (skb->sk) + net = sock_net(skb->sk); + else if (outdev) + net = dev_net(outdev); + else + return status; /* QUEUE == DROP if no one is waiting, to be safe. */ rcu_read_lock(); @@ -133,7 +143,7 @@ static int __nf_queue(struct sk_buff *skb, #endif skb_dst_force(skb); afinfo->saveroute(skb, entry); - status = qh->outfn(entry, queuenum); + status = qh->outfn(net, entry, queuenum); rcu_read_unlock(); diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 8f2d9bb..1e0a830 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -66,24 +66,19 @@ struct nfqnl_instance { typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -static DEFINE_SPINLOCK(instances_lock); - -#define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; - static inline u_int8_t instance_hashfn(u_int16_t queue_num) { - return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; + return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct net *net, u_int16_t queue_num) { struct hlist_head *head; struct hlist_node *pos; struct nfqnl_instance *inst; - head = &instance_table[instance_hashfn(queue_num)]; + head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, pos, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -92,14 +87,14 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int portid) +instance_create(struct net *net, u_int16_t queue_num, int portid) { struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&net->nfqnl.instances_lock); + if (instance_lookup(net, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -124,16 +119,16 @@ instance_create(u_int16_t queue_num, int portid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); return ERR_PTR(err); } @@ -159,11 +154,11 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct net *net, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + spin_lock(&net->nfqnl.instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&net->nfqnl.instances_lock); } static inline void @@ -417,7 +412,8 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) +nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, + unsigned int queuenum) { struct sk_buff *nskb; struct nfqnl_instance *queue; @@ -426,7 +422,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) int failopen = 0; /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(net, queuenum); if (!queue) { err = -ESRCH; goto err_out; @@ -463,7 +459,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) *packet_id_ptr = htonl(entry->id); /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_portid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -576,16 +572,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; rcu_read_lock(); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &net->nfqnl.instance_table[i]; hlist_for_each_entry_rcu(inst, tmp, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -602,12 +598,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -625,19 +618,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, int i; /* destroy all instances for this portid */ - spin_lock(&instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { + spin_lock(&n->net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { struct hlist_node *tmp, *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = + &n->net->nfqnl.instance_table[i]; hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { - if ((n->net == &init_net) && - (n->portid == inst->peer_portid)) + if (n->portid == inst->peer_portid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&n->net->nfqnl.instances_lock); } return NOTIFY_DONE; } @@ -658,11 +651,13 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { [NFQA_MARK] = { .type = NLA_U32 }, }; -static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlportid) +static struct nfqnl_instance *verdict_instance_lookup(struct net *net, + u16 queue_num, + int nlportid) { struct nfqnl_instance *queue; - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) return ERR_PTR(-ENODEV); @@ -706,7 +701,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, LIST_HEAD(batch_list); u16 queue_num = ntohs(nfmsg->res_id); - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); + queue = verdict_instance_lookup(sock_net(ctnl), queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -751,13 +747,14 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; unsigned int verdict; struct nf_queue_entry *entry; + struct net *net = sock_net(ctnl); enum ip_conntrack_info uninitialized_var(ctinfo); struct nf_conn *ct = NULL; - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (!queue) - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); + queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -822,6 +819,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; int ret = 0; + struct net *net = sock_net(ctnl); if (nfqa[NFQA_CFG_CMD]) { cmd = nla_data(nfqa[NFQA_CFG_CMD]); @@ -834,7 +832,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(net, queue_num); if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { ret = -EPERM; goto err_out_unlock; @@ -847,7 +845,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).portid); + queue = instance_create(net, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -858,7 +857,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(net, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -952,65 +951,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct net *net, struct iter_state *st) { - struct iter_state *st = seq->private; - if (!st) return NULL; - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { + if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) + return net->nfqnl.instance_table[st->bucket].first; } return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct net *net, struct iter_state *st, + struct hlist_node *h) { - struct iter_state *st = seq->private; - h = h->next; while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) + if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + h = net->nfqnl.instance_table[st->bucket].first; } return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct net *net, struct iter_state *st, + loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(net, st); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(net, st, head))) pos--; return pos ? NULL : head; } static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) { - spin_lock(&instances_lock); - return get_idx(seq, *pos); + struct net *net = seq_file_net(seq); + spin_lock(&net->nfqnl.instances_lock); + return get_idx(net, seq->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s, v); + return get_next(seq_file_net(s), s->private, v); } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) { - spin_unlock(&instances_lock); + struct net *net = seq_file_net(s); + spin_unlock(&net->nfqnl.instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -1034,8 +1032,8 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nfqnl_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nfqnl_file_ops = { @@ -1043,13 +1041,19 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ static int __net_init nfnetlink_queue_net_init(struct net *net) { + int i; + + spin_lock_init(&net->nfqnl.instances_lock); + for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); + #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_queue", 0440, net->proc_net_netfilter, &nfqnl_file_ops)) @@ -1073,7 +1077,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { static int __init nfnetlink_queue_init(void) { - int i, status; + int status; status = register_pernet_subsys(&nfnetlink_queue_net_ops); if (status) { @@ -1082,9 +1086,6 @@ static int __init nfnetlink_queue_init(void) return status; } - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); - netlink_register_notifier(&nfqnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfqnl_subsys); if (status < 0) { -- 1.8.1.2 core-4.6/kernel/core-kernel-3.8/patches/00-ifindex.patch0000664000175000017500000000161012153242402017536 00000000000000From 1d992600b0f1962d0478df2083b76b1ceba50517 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Mon, 3 Jun 2013 18:29:42 -0700 Subject: [PATCH 1/3] Make network device ifindex sequential per network namespace. Signed-off-by: Tom Goff --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index d592214..4b8da6e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6455,8 +6455,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Actually switch the network namespace */ dev_net_set(dev, net); - /* If there is an ifindex conflict assign a new one */ - if (__dev_get_by_index(net, dev->ifindex)) { + /* Assign a new ifindex */ + { int iflink = (dev->iflink == dev->ifindex); dev->ifindex = dev_new_index(net); if (iflink) -- 1.8.1.2 core-4.6/kernel/core-kernel-3.8/Makefile0000664000175000017500000000363012153242402014667 00000000000000VERSION := $(shell dpkg -l linux-source 2> /dev/null | \ awk '/^i/ {print gensub("([0-9]+[.][0-9]+[.][0-9]+)[.0-9]*", "\\1", "1", $$3)}') TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 SUBVERSION := -core REVISION := 1.0 PATCHDIR := patches PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) CONFIG := config.core DEPDEBS := linux-source kernel-package po-debconf gettext CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \ awk '/^CPU\(s\)/ {print $$2}') ifeq ($(strip $(CONCURRENCY_LEVEL)),) CONCURRENCY_LEVEL := 1 endif MAINTAINER ?= $(shell id -nu) EMAIL ?= $(MAINTAINER)@$(shell hostname -f) MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ --append-to-version $(SUBVERSION) --revision $(REVISION) .PHONY: build build: debcheck defaultconfig patch export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && \ if [ -f ../$(CONFIG) ]; then \ cat ../$(CONFIG) >> .config; \ fi && \ fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch .PHONY: debcheck debcheck: for d in $(DEPDEBS); do \ if ! dpkg-query -s $$d > /dev/null 2>&1; then \ echo ERROR: build dependency not installed: $$d >&2; \ exit 1; \ fi; \ done .PHONY: defaultconfig defaultconfig: linux-source-$(VERSION) export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure .PHONY: patch patch: linux-source-$(VERSION) patch-stamp patch-stamp: $(PATCHES) for p in $^; do \ if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ echo ERROR: applying patch failed: $$p >&2; \ exit 1; \ fi; \ done touch patch-stamp .PHONY: source source: linux-source-$(VERSION) linux-source-$(VERSION): $(TARBALL) tar -xjf $^ .PHONY: clean clean: rm -rf linux-source-$(VERSION) patch-stamp core-4.6/kernel/core-kernel-3.8/config.core0000664000175000017500000000003112153242402015336 00000000000000CONFIG_XFRM_STATISTICS=y core-4.6/doc/0000775000175000017500000000000012220631512010055 500000000000000core-4.6/doc/machine.rst0000664000175000017500000000564312205477411012154 00000000000000.. This file is part of the CORE Manual (c)2012-2013 the Boeing Company .. _Machine_Types: ************* Machine Types ************* .. index:: machine types Different node types can be configured in CORE, and each node type has a *machine type* that indicates how the node will be represented at run time. Different machine types allow for different virtualization options. .. _netns: netns ===== .. index:: netns machine type The *netns* machine type is the default. This is for nodes that will be backed by Linux network namespaces. See :ref:`Linux` for a brief explanation of netns. This default machine type is very lightweight, providing a minimum amount of virtualization in order to emulate a network. Another reason this is designated as the default machine type is because this virtualization technology typically requires no changes to the kernel; it is available out-of-the-box from the latest mainstream Linux distributions. .. index:: physical machine type .. index:: emulation testbed machines .. index:: real node .. index:: physical node .. _physical: physical ======== The *physical* machine type is used for nodes that represent a real Linux-based machine that will participate in the emulated network scenario. This is typically used, for example, to incorporate racks of server machines from an emulation testbed. A physical node is one that is running the CORE daemon (:file:`core-daemon`), but will not be further partitioned into virtual machines. Services that are run on the physical node do not run in an isolated or virtualized environment, but directly on the operating system. Physical nodes must be assigned to servers, the same way nodes are assigned to emulation servers with :ref:`Distributed_Emulation`. The list of available physical nodes currently shares the same dialog box and list as the emulation servers, accessed using the *Emulation Servers...* entry from the *Session* menu. .. index:: GRE tunnels with physical nodes Support for physical nodes is under development and may be improved in future releases. Currently, when any node is linked to a physical node, a dashed line is drawn to indicate network tunneling. A GRE tunneling interface will be created on the physical node and used to tunnel traffic to and from the emulated world. Double-clicking on a physical node during runtime opens a terminal with an SSH shell to that node. Users should configure public-key SSH login as done with emulation servers. .. _xen: xen === .. index:: xen machine type The *xen* machine type is an experimental new type in CORE for managing Xen domUs from within CORE. After further development, it may be documented here. Current limitations include only supporting ISO-based filesystems, and lack of integration with node services, EMANE, and possibly other features of CORE. There is a :file:`README-Xen` file available in the CORE source that contains further instructions for setting up Xen-based nodes. core-4.6/doc/conf.py0000664000175000017500000001773312220631433011311 00000000000000# -*- coding: utf-8 -*- # # CORE documentation build configuration file, created by # sphinx-quickstart on Wed Jun 13 10:44:22 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'CORE' copyright = u'2012, core-dev' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '4.6' # The full version, including alpha/beta/rc tags. release = '4.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'COREdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'CORE.tex', u'CORE Documentation', u'core-dev', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'core', u'CORE Documentation', [u'core-dev'], 1) ] # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. epub_title = u'CORE' epub_author = u'core-dev' epub_publisher = u'core-dev' epub_copyright = u'2012, core-dev' # The language of the text. It defaults to the language option # or en if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. #epub_exclude_files = [] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True core-4.6/doc/emane.rst0000664000175000017500000003132212210125600011610 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. _EMANE: ***** EMANE ***** .. index:: EMANE This chapter describes running CORE with the EMANE emulator. .. _What_is_EMANE?: What is EMANE? ============== .. index:: EMANE; introduction to The Extendable Mobile Ad-hoc Network Emulator (EMANE) allows heterogeneous network emulation using a pluggable MAC and PHY layer architecture. The EMANE framework provides an implementation architecture for modeling different radio interface types in the form of *Network Emulation Modules* (NEMs) and incorporating these modules into a real-time emulation running in a distributed environment. EMANE is developed by U.S. Naval Research Labs (NRL) Code 5522 and Adjacent Link LLC, who maintain these websites: * ``_ * ``_ * ``_ (former EMANE project home) Instead of building Linux Ethernet bridging networks with CORE, higher-fidelity wireless networks can be emulated using EMANE bound to virtual devices. CORE emulates layers 3 and above (network, session, application) with its virtual network stacks and process space for protocols and applications, while EMANE emulates layers 1 and 2 (physical and data link) using its pluggable PHY and MAC models. The interface between CORE and EMANE is a TAP device. CORE builds the virtual node using Linux network namespaces, and installs the TAP device into the namespace. EMANE binds a userspace socket to the device, on the host before it is pushed into the namespace, for sending and receiving data. The *Virtual Transport* is the EMANE component responsible for connecting with the TAP device. EMANE models are configured through CORE's WLAN configuration dialog. A corresponding EmaneModel Python class is sub-classed for each supported EMANE model, to provide configuration items and their mapping to XML files. This way new models can be easily supported. When CORE starts the emulation, it generates the appropriate XML files that specify the EMANE NEM configuration, and launches the EMANE daemons. Some EMANE models support location information to determine when packets should be dropped. EMANE has an event system where location events are broadcast to all NEMs. CORE can generate these location events when nodes are moved on the canvas. The canvas size and scale dialog has controls for mapping the X,Y coordinate system to a latitude, longitude geographic system that EMANE uses. When specified in the :file:`core.conf` configuration file, CORE can also subscribe to EMANE location events and move the nodes on the canvas as they are moved in the EMANE emulation. This would occur when an Emulation Script Generator, for example, is running a mobility script. .. index:: EMANE; Configuration .. index:: EMANE; Installation .. _EMANE_Configuration: EMANE Configuration =================== CORE and EMANE currently work together only on the Linux network namespaces platform. The normal CORE installation instructions should be followed from :ref:`Installation`. The CORE configuration file :file:`/etc/core/core.conf` has options specific to EMANE. Namely, the `emane_models` line contains a comma-separated list of EMANE models that will be available. Each model has a corresponding Python file containing the *EmaneModel* subclass. A portion of the default :file:`core.conf` file is shown below: :: # EMANE configuration emane_platform_port = 8101 emane_transform_port = 8201 emane_event_monitor = False emane_models = RfPipe, Ieee80211abg EMANE can be installed from deb or RPM packages or from source. See the `EMANE website `_ for full details. Here are quick instructions for installing all EMANE packages: :: # install dependencies sudo apt-get install libssl-dev libxml-lixbml-perl libxml-simple-perl # download and install EMANE 0.8.1 export URL=http://labs.cengen.com/emane/download/deb/ubuntu-12_04 wget $URL/0.8.1/amd64/emane-bundle-0.8.1.amd64.tgz mkdir emane-0.8.1 cd emane-0.8.1 tar xzf ../emane-bundle-0.8.1.amd64.tgz sudo dpkg -i *.deb If you have an EMANE event generator (e.g. mobility or pathloss scripts) and want to have CORE subscribe to EMANE location events, set the following line in the :file:`/etc/core/core.conf` configuration file: :: emane_event_monitor = True Do not set the above option to True if you want to manually drag nodes around on the canvas to update their location in EMANE. Another common issue is if installing EMANE from source, the default configure prefix will place the DTD files in :file:`/usr/local/share/emane/dtd` while CORE expects them in :file:`/usr/share/emane/dtd`. A symbolic link will fix this: :: sudo ln -s /usr/local/share/emane /usr/share/emane .. _Single_PC_with_EMANE: Single PC with EMANE ==================== This section describes running CORE and EMANE on a single machine. This is the default mode of operation when building an EMANE network with CORE. The OTA manager interface is off and the virtual nodes use the loopback device for communicating with one another. This prevents your emulation session from sending data on your local network and interfering with other EMANE users. EMANE is configured through a WLAN node, because it is all about emulating wireless radio networks. Once a node is linked to a WLAN cloud configured with an EMANE model, the radio interface on that node may also be configured separately (apart from the cloud.) Double-click on a WLAN node to invoke the WLAN configuration dialog. Click the *EMANE* tab; when EMANE has been properly installed, EMANE wireless modules should be listed in the *EMANE Models* list. (You may need to restart the CORE daemon if it was running prior to installing the EMANE Python bindings.) Click on a model name to enable it. When an EMANE model is selected in the *EMANE Models* list, clicking on the *model options* button causes the GUI to query the CORE daemon for configuration items. Each model will have different parameters, refer to the EMANE documentation for an explanation of each item. The defaults values are presented in the dialog. Clicking *Apply* and *Apply* again will store the EMANE model selections. The *EMANE options* button allows specifying some global parameters for EMANE, some of which are necessary for distributed operation, see :ref:`Distributed_EMANE`. .. index:: RF-PIPE model .. index:: 802.11 model .. index:: ieee80211abg model .. index:: geographic location .. index:: Universal PHY The RF-PIPE and IEEE 802.11abg models use a Universal PHY that supports geographic location information for determining pathloss between nodes. A default latitude and longitude location is provided by CORE and this location-based pathloss is enabled by default; this is the *pathloss mode* setting for the Universal PHY. Moving a node on the canvas while the emulation is running generates location events for EMANE. To view or change the geographic location or scale of the canvas use the *Canvas Size and Scale* dialog available from the *Canvas* menu. .. index:: UTM zones .. index:: UTM projection Note that conversion between geographic and Cartesian coordinate systems is done using UTM (Universal Transverse Mercator) projection, where different zones of 6 degree longitude bands are defined. The location events generated by CORE may become inaccurate near the zone boundaries for very large scenarios that span multiple UTM zones. It is recommended that EMANE location scripts be used to achieve geo-location accuracy in this situation. Clicking the green *Start* button launches the emulation and causes TAP devices to be created in the virtual nodes that are linked to the EMANE WLAN. These devices appear with interface names such as eth0, eth1, etc. The EMANE daemons should now be running on the host: :: > ps -aef | grep emane root 10472 1 1 12:57 ? 00:00:00 emane --logl 0 platform.xml root 10526 1 1 12:57 ? 00:00:00 emanetransportd --logl 0 tr The above example shows the *emane* and *emanetransportd* daemons started by CORE. To view the configuration generated by CORE, look in the :file:`/tmp/pycore.nnnnn/` session directory for a :file:`platform.xml` file and other XML files. One easy way to view this information is by double-clicking one of the virtual nodes, and typing *cd ..* in the shell to go up to the session directory. When EMANE is used to network together CORE nodes, no Ethernet bridging device is used. The Virtual Transport creates a TAP device that is installed into the network namespace container, so no corresponding device is visible on the host. .. index:: Distributed_EMANE .. _Distributed_EMANE: Distributed EMANE ================= Running CORE and EMANE distributed among two or more emulation servers is similar to running on a single machine. There are a few key configuration items that need to be set in order to be successful, and those are outlined here. Because EMANE uses a multicast channel to disseminate data to all NEMs, it is a good idea to maintain separate networks for data and control. The control network may be a shared laboratory network, for example, but you do not want multicast traffic on the data network to interfere with other EMANE users. The examples described here will use *eth0* as a control interface and *eth1* as a data interface, although using separate interfaces is not strictly required. Note that these interface names refer to interfaces present on the host machine, not virtual interfaces within a node. Each machine that will act as an emulation server needs to have CORE and EMANE installed. Refer to the :ref:`Distributed_Emulation` section for configuring CORE. The IP addresses of the available servers are configured from the CORE emulation servers dialog box (choose *Session* then *Emulation servers...*) described in :ref:`Distributed_Emulation`. This list of servers is stored in a :file:`~/.core/servers.conf` file. The dialog shows available servers, some or all of which may be assigned to nodes on the canvas. Nodes need to be assigned to emulation servers as described in :ref:`Distributed_Emulation`. Select several nodes, right-click them, and choose *Assign to* and the name of the desired server. When a node is not assigned to any emulation server, it will be emulated locally. The local machine that the GUI connects with is considered the "master" machine, which in turn connects to the other emulation server "slaves". Public key SSH should be configured from the master to the slaves as mentioned in the :ref:`Distributed_Emulation` section. The EMANE models can be configured as described in :ref:`Single_PC_with_EMANE`. Under the *EMANE* tab of the EMANE WLAN, click on the *EMANE options* button. This brings up the emane configuration dialog. The *enable OTA Manager channel* should be set to *on*. The *OTA Manager device* and *Event Service device* should be set to something other than the loopback *lo* device. For example, if eth0 is your control device and eth1 is for data, set the OTA Manager device to eth1 and the Event Service device to eth0. Click *Apply* to save these settings. .. HINT:: Here is a quick checklist for distributed emulation with EMANE. 1. Follow the steps outlined for normal CORE :ref:`Distributed_Emulation`. 2. Under the *EMANE* tab of the EMANE WLAN, click on *EMANE options*. 3. Turn on the *OTA Manager channel* and set the *OTA Manager device*. Also set the *Event Service device*. 4. Select groups of nodes, right-click them, and assign them to servers using the *Assign to* menu. 5. Synchronize your machine's clocks prior to starting the emulation, using ``ntp`` or ``ptp``. Some EMANE models are sensitive to timing. 6. Press the *Start* button to launch the distributed emulation. Now when the Start button is used to instantiate the emulation, the local CORE Python daemon will connect to other emulation servers that have been assigned to nodes. Each server will have its own session directory where the :file:`platform.xml` file and other EMANE XML files are generated. The NEM IDs are automatically coordinated across servers so there is no overlap. Each server also gets its own Platform ID. Instead of using the loopback device for disseminating multicast EMANE events, an Ethernet device is used as specified in the *configure emane* dialog. EMANE's Event Service can be run with mobility or pathloss scripts as described in :ref:`Single_PC_with_EMANE`. If CORE is not subscribed to location events, it will generate them as nodes are moved on the canvas. Double-clicking on a node during runtime will cause the GUI to attempt to SSH to the emulation server for that node and run an interactive shell. The public key SSH configuration should be tested with all emulation servers prior to starting the emulation. core-4.6/doc/constants.txt0000664000175000017500000000166612204512703012565 00000000000000.. |UBUNTUVERSION| replace:: 12.04, 12.10, or 13.04 .. |FEDORAVERSION| replace:: 17, 18, or 19 .. |CENTOSVERSION| replace:: 6.x .. |BSDVERSION| replace:: 9.0 .. |CORERPM| replace:: 1.fc19.x86_64.rpm .. |CORERPM2| replace:: 1.fc19.noarch.rpm .. |COREDEB| replace:: 0ubuntu1_precise_amd64.deb .. |COREDEB2| replace:: 0ubuntu1_precise_all.deb .. |QVER| replace:: quagga-0.99.21mr2.2 .. |QVERDEB| replace:: quagga-mr_0.99.21mr2.2_amd64.deb .. |QVERRPM| replace:: quagga-0.99.21mr2.2-1.fc16.x86_64.rpm .. |APTDEPS| replace:: bash bridge-utils ebtables iproute libev-dev python .. |APTDEPS2| replace:: tcl8.5 tk8.5 libtk-img .. |APTDEPS3| replace:: autoconf automake gcc libev-dev make python-dev libreadline-dev pkg-config imagemagick help2man .. |YUMDEPS| replace:: bash bridge-utils ebtables iproute libev python .. |YUMDEPS2| replace:: tcl tk tkimg .. |YUMDEPS3| replace:: autoconf automake make libev-devel python-devel ImageMagick help2man core-4.6/doc/_static/0000775000175000017500000000000012220631372011507 500000000000000core-4.6/doc/scripting.rst0000664000175000017500000001176012205477411012547 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. _Python_Scripting: **************** Python Scripting **************** .. index:: Python scripting CORE can be used via the :ref:`GUI ` or Python scripting. Writing your own Python scripts offers a rich programming environment with complete control over all aspects of the emulation. This chapter provides a brief introduction to scripting. Most of the documentation is available from sample scripts, or online via interactive Python. .. index:: sample Python scripts The best starting point is the sample scripts that are included with CORE. If you have a CORE source tree, the example script files can be found under :file:`core/daemon/examples/netns/`. When CORE is installed from packages, the example script files will be in :file:`/usr/share/core/examples/netns/` (or the :file:`/usr/local/...` prefix when installed from source.) For the most part, the example scripts are self-documenting; see the comments contained within the Python code. The scripts should be run with root privileges because they create new network namespaces. In general, a CORE Python script does not connect to the CORE daemon, :file:`core-daemon`; in fact, :file:`core-daemon` is just another Python script that uses the CORE Python modules and exchanges messages with the GUI. To connect the GUI to your scripts, see the included sample scripts that allow for GUI connections. Here are the basic elements of a CORE Python script: :: #!/usr/bin/python from core import pycore session = pycore.Session(persistent=True) node1 = session.addobj(cls=pycore.nodes.CoreNode, name="n1") node2 = session.addobj(cls=pycore.nodes.CoreNode, name="n2") hub1 = session.addobj(cls=pycore.nodes.HubNode, name="hub1") node1.newnetif(hub1, ["10.0.0.1/24"]) node2.newnetif(hub1, ["10.0.0.2/24"]) node1.icmd(["ping", "-c", "5", "10.0.0.2"]) session.shutdown() The above script creates a CORE session having two nodes connected with a hub. The first node pings the second node with 5 ping packets; the result is displayed on screen. A good way to learn about the CORE Python modules is via interactive Python. Scripts can be run using *python -i*. Cut and paste the simple script above and you will have two nodes connected by a hub, with one node running a test ping to the other. The CORE Python modules are documented with comments in the code. From an interactive Python shell, you can retrieve online help about the various classes and methods; for example *help(pycore.nodes.CoreNode)* or *help(pycore.Session)*. An interactive development environment (IDE) is available for browsing the CORE source, the `Eric Python IDE `_. CORE has a project file that can be opened by Eric, in the source under :file:`core/daemon/CORE.e4p`. This IDE has a class browser for viewing a tree of classes and methods. It features syntax highlighting, auto-completion, indenting, and more. One feature that is helpful with learning the CORE Python modules is the ability to generate class diagrams; right-click on a class, choose *Diagrams*, and *Class Diagram*. .. index:: daemon versus script .. index:: script versus daemon .. index:: script with GUI support .. index:: connecting GUI to script .. NOTE:: The CORE daemon :file:`core-daemon` manages a list of sessions and allows the GUI to connect and control sessions. Your Python script uses the same CORE modules but runs independently of the daemon. The daemon does not need to be running for your script to work. The session created by a Python script may be viewed in the GUI if certain steps are followed. The GUI has a :ref:`File_Menu`, *Execute Python script...* option for running a script and automatically connecting to it. Once connected, normal GUI interaction is possible, such as moving and double-clicking nodes, activating Widgets, etc. The script should have a line such as the following for running it from the GUI. :: if __name__ == "__main__" or __name__ == "__builtin__": main() Also, the script should add its session to the session list after creating it. A global ``server`` variable is exposed to the script pointing to the ``CoreServer`` object in the :file:`core-daemon`. :: def add_to_server(session): ''' Add this session to the server's list if this script is executed from the core-daemon server. ''' global server try: server.addsession(session) return True except NameError: return False :: session = pycore.Session(persistent=True) add_to_server(session) Finally, nodes and networks need to have their coordinates set to something, otherwise they will be grouped at the coordinates ``<0, 0>``. First sketching the topology in the GUI and then using the *Export Python script* option may help here. :: switch.setposition(x=80,y=50) A fully-worked example script that you can launch from the GUI is available in the file :file:`switch.py` in the examples directory. core-4.6/doc/_templates/0000775000175000017500000000000012220631372012216 500000000000000core-4.6/doc/credits.rst0000664000175000017500000000221011772356751012203 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. _Acknowledgements: *************** Acknowledgments *************** The CORE project was derived from the open source IMUNES project from the University of Zagreb in 2004. In 2006, changes for CORE were released back to that project, some items of which were adopted. Marko Zec is the primary developer from the University of Zagreb responsible for the IMUNES (GUI) and VirtNet (kernel) projects. Ana Kukec and Miljenko Mikuc are known contributors. Jeff Ahrenholz has been the primary Boeing developer of CORE, and has written this manual. Tom Goff designed the Python framework and has made significant contributions. Claudiu Danilov , Gary Pei , Phil Spagnolo, and Ian Chakeres have contributed code to CORE. Dan Mackley helped develop the CORE API, originally to interface with a simulator. Jae Kim and Tom Henderson have supervised the project and provided direction. core-4.6/doc/install.rst0000664000175000017500000006111112206710505012201 00000000000000.. This file is part of the CORE Manual (c)2012-2013 the Boeing Company .. include:: constants.txt .. _Installation: ************ Installation ************ This chapter describes how to set up a CORE machine. Note that the easiest way to install CORE is using a binary package on Ubuntu or Fedora (deb or rpm) using the distribution's package manager to automatically install dependencies, see :ref:`Installing_from_Packages`. Ubuntu and Fedora Linux are the recommended distributions for running CORE. Ubuntu |UBUNTUVERSION| and Fedora |FEDORAVERSION| ship with kernels with support for namespaces built-in. They support the latest hardware. However, these distributions are not strictly required. CORE will likely work on other flavors of Linux, see :ref:`Installing_from_Source`. The primary dependencies are Tcl/Tk (8.5 or newer) for the GUI, and Python 2.6 or 2.7 for the CORE daemon. .. index:: install locations .. index:: paths .. index:: install paths CORE files are installed to the following directories. When installing from source, the :file:`/usr/local` prefix is used in place of :file:`/usr` by default. ============================================= ================================= Install Path Description ============================================= ================================= :file:`/usr/bin/core-gui` GUI startup command :file:`/usr/sbin/core-daemon` Daemon startup command :file:`/usr/sbin/` Misc. helper commands/scripts :file:`/usr/lib/core` GUI files :file:`/usr/lib/python2.7/dist-packages/core` Python modules for daemon/scripts :file:`/etc/core/` Daemon configuration files :file:`~/.core/` User-specific GUI preferences and scenario files :file:`/usr/share/core/` Example scripts and scenarios :file:`/usr/share/man/man1/` Command man pages :file:`/etc/init.d/core-daemon` System startup script for daemon ============================================= ================================= Under Fedora, :file:`/site-packages/` is used instead of :file:`/dist-packages/` for the Python modules, and :file:`/etc/systemd/system/core-daemon.service` instead of :file:`/etc/init.d/core-daemon` for the system startup script. .. _Prerequisites: Prerequisites ============= .. index:: Prerequisites The Linux or FreeBSD operating system is required. The GUI uses the Tcl/Tk scripting toolkit, and the CORE daemon require Python. Details of the individual software packages required can be found in the installation steps. .. _Required_Hardware: Required Hardware ----------------- .. index:: Hardware requirements .. index:: System requirements Any computer capable of running Linux or FreeBSD should be able to run CORE. Since the physical machine will be hosting numerous virtual machines, as a general rule you should select a machine having as much RAM and CPU resources as possible. A *general recommendation* would be: * 2.0GHz or better x86 processor, the more processor cores the better * 2 GB or more of RAM * about 3 MB of free disk space (plus more for dependency packages such as Tcl/Tk) * X11 for the GUI, or remote X11 over SSH The computer can be a laptop, desktop, or rack-mount server. A keyboard, mouse, and monitor are not required if a network connection is available for remotely accessing the machine. A 3D accelerated graphics card is not required. .. _Required_Software: Required Software ----------------- CORE requires the Linux or FreeBSD operating systems because it uses virtualization provided by the kernel. It does not run on the Windows or Mac OS X operating systems (unless it is running within a virtual machine guest.) There are two different virtualization technologies that CORE can currently use: Linux network namespaces and FreeBSD jails, see :ref:`How_Does_it_Work?` for virtualization details. **Linux network namespaces is the recommended platform.** Development is focused here and it supports the latest features. It is the easiest to install because there is no need to patch, install, and run a special Linux kernel. FreeBSD |BSDVERSION|-RELEASE may offer the best scalability. If your applications run under FreeBSD and you are comfortable with that platform, this may be a good choice. Device and application support by BSD may not be as extensive as Linux. The CORE GUI requires the X.Org X Window system (X11), or can run over a remote X11 session. For specific Tcl/Tk, Python, and other libraries required to run CORE, refer to the :ref:`Installation` section. .. NOTE:: CORE :ref:`Services` determine what runs on each node. You may require other software packages depending on the services you wish to use. For example, the `HTTP` service will require the `apache2` package. .. _Installing_from_Packages: Installing from Packages ======================== .. index:: installer .. index:: binary packages The easiest way to install CORE is using the pre-built packages. The package managers on Ubuntu or Fedora will automatically install dependencies for you. You can obtain the CORE packages from the `CORE downloads `_ page. .. _Installing_from_Packages_on_Ubuntu: Installing from Packages on Ubuntu ---------------------------------- First install the Ubuntu |UBUNTUVERSION| operating system. .. NOTE:: Linux package managers (e.g. `software-center`, `yum`) will take care of installing the dependencies for you when you use the CORE packages. You do not need to manually use these installation lines. You do need to select which Quagga package to use. * **Optional:** install the prerequisite packages (otherwise skip this step and have the package manager install them for you.) .. parsed-literal:: # make sure the system is up to date; you can also use synaptic or # update-manager instead of apt-get update/dist-upgrade sudo apt-get update sudo apt-get dist-upgrade sudo apt-get install |APTDEPS| |APTDEPS2| * Install Quagga for routing. If you plan on working with wireless networks, we recommend installing `OSPF MDR `__ (replace `amd64` below with `i386` if needed to match your architecture): .. parsed-literal:: export URL=http://downloads.pf.itd.nrl.navy.mil/ospf-manet wget $URL/|QVER|/|QVERDEB| sudo dpkg -i |QVERDEB| or, for the regular Ubuntu version of Quagga: :: sudo apt-get install quagga * Install the CORE deb packages for Ubuntu, using a GUI that automatically resolves dependencies (note that the absolute path to the deb file must be used with ``software-center``): .. parsed-literal:: software-center /home/user/Downloads/core-daemon\_\ |version|-|COREDEB| software-center /home/user/Downloads/core-gui\_\ |version|-|COREDEB2| or install from command-line: .. parsed-literal:: sudo dpkg -i core-daemon\_\ |version|-|COREDEB| sudo dpkg -i core-gui\_\ |version|-|COREDEB2| * Start the CORE daemon as root. :: sudo /etc/init.d/core-daemon start * Run the CORE GUI as a normal user: :: core-gui After running the ``core-gui`` command, a GUI should appear with a canvas for drawing topologies. Messages will print out on the console about connecting to the CORE daemon. .. _Installing_from_Packages_on_Fedora: Installing from Packages on Fedora/CentOS ----------------------------------------- The commands shown here should be run as root. First Install the Fedora |FEDORAVERSION| or CentOS |CENTOSVERSION| operating system. The `x86_64` architecture is shown in the examples below, replace with `i686` is using a 32-bit architecture. Also, `fc15` is shown below for Fedora 15 packages, replace with the appropriate Fedora release number. * **CentOS only:** in order to install the `libev` prerequisite package, you first need to install the `EPEL `_ repo (Extra Packages for Enterprise Linux): :: wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm yum localinstall epel-release-6-8.noarch.rpm * **Optional:** install the prerequisite packages (otherwise skip this step and have the package manager install them for you.) .. parsed-literal:: # make sure the system is up to date; you can also use the # update applet instead of yum update yum update yum install |YUMDEPS| |YUMDEPS2| * **Optional (Fedora 17+):** Fedora 17 and newer have an additional prerequisite providing the required netem kernel modules (otherwise skip this step and have the package manager install it for you.) :: yum install kernel-modules-extra * Install Quagga for routing. If you plan on working with wireless networks, we recommend installing `OSPF MDR `_: .. parsed-literal:: export URL=http://downloads.pf.itd.nrl.navy.mil/ospf-manet wget $URL/|QVER|/|QVERRPM| yum localinstall |QVERRPM| or, for the regular Fedora version of Quagga: :: yum install quagga * Install the CORE RPM packages for Fedora and automatically resolve dependencies: .. parsed-literal:: yum localinstall core-daemon-|version|-|CORERPM| --nogpgcheck yum localinstall core-gui-|version|-|CORERPM2| --nogpgcheck or install from the command-line: .. parsed-literal:: rpm -ivh core-daemon-|version|-|CORERPM| rpm -ivh core-gui-|version|-|CORERPM2| * Turn off SELINUX by setting ``SELINUX=disabled`` in the :file:`/etc/sysconfig/selinux` file, and adding ``selinux=0`` to the kernel line in your :file:`/etc/grub.conf` file; on Fedora 15 and newer, disable sandboxd using ``chkconfig sandbox off``; you need to reboot in order for this change to take effect * Turn off firewalls with ``systemctl disable firewalld``, ``systemctl disable iptables.service``, ``systemctl disable ip6tables.service`` (``chkconfig iptables off``, ``chkconfig ip6tables off``) or configure them with permissive rules for CORE virtual networks; you need to reboot after making this change, or flush the firewall using ``iptables -F``, ``ip6tables -F``. * Start the CORE daemon as root. Fedora uses the ``systemd`` start-up daemon instead of traditional init scripts. CentOS uses the init script. :: # for Fedora using systemd: systemctl daemon-reload systemctl start core-daemon.service # or for CentOS: /etc/init.d/core-daemon start * Run the CORE GUI as a normal user: :: core-gui After running the ``core-gui`` command, a GUI should appear with a canvas for drawing topologies. Messages will print out on the console about connecting to the CORE daemon. .. _Installing_from_Source: Installing from Source ====================== This option is listed here for developers and advanced users who are comfortable patching and building source code. Please consider using the binary packages instead for a simplified install experience. .. _Installing_from_Source_on_Ubuntu: Installing from Source on Ubuntu -------------------------------- To build CORE from source on Ubuntu, first install these development packages. These packages are not required for normal binary package installs. .. parsed-literal:: sudo apt-get install |APTDEPS| \\ |APTDEPS2| \\ |APTDEPS3| You can obtain the CORE source from the `CORE source `_ page. Choose either a stable release version or the development snapshot available in the `nightly_snapshots` directory. The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up builds on multi-core systems. .. parsed-literal:: tar xzf core-|version|.tar.gz cd core-|version| ./bootstrap.sh ./configure make -j8 sudo make install The CORE Manual documentation is built separately from the :file:`doc/` sub-directory in the source. It requires Sphinx: .. parsed-literal:: sudo apt-get install python-sphinx cd core-|version|/doc make html make latexpdf .. _Installing_from_Source_on_Fedora: Installing from Source on Fedora -------------------------------- To build CORE from source on Fedora, install these development packages. These packages are not required for normal binary package installs. .. parsed-literal:: yum install |YUMDEPS| \\ |YUMDEPS2| \\ |YUMDEPS3| .. NOTE:: For a minimal X11 installation, also try these packages:: yum install xauth xterm urw-fonts You can obtain the CORE source from the `CORE source `_ page. Choose either a stable release version or the development snapshot available in the :file:`nightly_snapshots` directory. The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up builds on multi-core systems. Notice the ``configure`` flag to tell the build system that a systemd service file should be installed under Fedora. .. parsed-literal:: tar xzf core-|version|.tar.gz cd core-|version| ./bootstrap.sh ./configure --with-startup=systemd make -j8 sudo make install Note that the Linux RPM and Debian packages do not use the ``/usr/local`` prefix, and files are instead installed to ``/usr/sbin``, and ``/usr/lib``. This difference is a result of aligning with the directory structure of Linux packaging systems and FreeBSD ports packaging. Another note is that the Python distutils in Fedora Linux will install the CORE Python modules to :file:`/usr/lib/python2.7/site-packages/core`, instead of using the :file:`dist-packages` directory. The CORE Manual documentation is built separately from the :file:`doc/` sub-directory in the source. It requires Sphinx: .. parsed-literal:: sudo yum install python-sphinx cd core-|version|/doc make html make latexpdf .. _Installing_from_Source_on_CentOS: Installing from Source on CentOS/EL6 ------------------------------------ To build CORE from source on CentOS/EL6, first install the `EPEL `_ repo (Extra Packages for Enterprise Linux) in order to provide the `libev` package. :: wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm yum localinstall epel-release-6-8.noarch.rpm Now use the same instructions shown in :ref:`Installing_from_Source_on_Fedora`. CentOS/EL6 does not use the systemd service file, so the `configure` option `--with-startup=systemd` should be omitted: :: ./configure .. _Installing_from_Source_on_SUSE: Installing from Source on SUSE ------------------------------ To build CORE from source on SUSE or OpenSUSE, use the similar instructions shown in :ref:`Installing_from_Source_on_Fedora`, except that the following `configure` option should be used: :: ./configure --with-startup=suse This causes a separate init script to be installed that is tailored towards SUSE systems. The `zypper` command is used instead of `yum`. For OpenSUSE/Xen based installations, refer to the `README-Xen` file included in the CORE source. .. _Installing_from_Source_on_FreeBSD: Installing from Source on FreeBSD --------------------------------- .. index:: kernel patch **Rebuilding the FreeBSD Kernel** The FreeBSD kernel requires a small patch to allow per-node directories in the filesystem. Also, the `VIMAGE` build option needs to be turned on to enable jail-based network stack virtualization. The source code for the FreeBSD kernel is located in :file:`/usr/src/sys`. Instructions below will use the :file:`/usr/src/sys/amd64` architecture directory, but the directory :file:`/usr/src/sys/i386` should be substituted if you are using a 32-bit architecture. The kernel patch is available from the CORE source tarball under core-|version|/kernel/symlinks-8.1-RELEASE.diff. This patch applies to the FreeBSD 8.x or 9.x kernels. .. parsed-literal:: cd /usr/src/sys # first you can check if the patch applies cleanly using the '-C' option patch -p1 -C < ~/core-|version|/kernel/symlinks-8.1-RELEASE.diff # without '-C' applies the patch patch -p1 < ~/core-|version|/kernel/symlinks-8.1-RELEASE.diff A kernel configuration file named :file:`CORE` can be found within the source tarball: core-|version|/kernel/freebsd8-config-CORE. The config is valid for FreeBSD 8.x or 9.x kernels. The contents of this configuration file are shown below; you can edit it to suit your needs. :: # this is the FreeBSD 9.x kernel configuration file for CORE include GENERIC ident CORE options VIMAGE nooptions SCTP options IPSEC device crypto options IPFIREWALL options IPFIREWALL_DEFAULT_TO_ACCEPT The kernel configuration file can be linked or copied to the kernel source directory. Use it to configure and build the kernel: .. parsed-literal:: cd /usr/src/sys/amd64/conf cp ~/core-|version|/kernel/freebsd8-config-CORE CORE config CORE cd ../compile/CORE make cleandepend && make depend make -j8 && make install Change the number 8 above to match the number of CPU cores you have times two. Note that the ``make install`` step will move your existing kernel to ``/boot/kernel.old`` and removes that directory if it already exists. Reboot to enable this new patched kernel. **Building CORE from Source on FreeBSD** Here are the prerequisite packages from the FreeBSD ports system: :: pkg_add -r tk85 pkg_add -r libimg pkg_add -r bash pkg_add -r libev pkg_add -r sudo pkg_add -r python pkg_add -r autotools pkg_add -r gmake Note that if you are installing to a bare FreeBSD system and want to SSH with X11 forwarding to that system, these packages will help: :: pkg_add -r xauth pkg_add -r xorg-fonts The ``sudo`` package needs to be configured so a normal user can run the CORE GUI using the command ``core-gui`` (opening a shell window on a node uses a command such as ``sudo vimage n1``.) On FreeBSD, the CORE source is built using autotools and gmake: .. parsed-literal:: tar xzf core-|version|.tar.gz cd core-|version| ./bootstrap.sh ./configure gmake -j8 sudo gmake install Build and install the ``vimage`` utility for controlling virtual images. The source can be obtained from `FreeBSD SVN `_, or it is included with the CORE source for convenience: .. parsed-literal:: cd core-|version|/kernel/vimage make make install .. index:: FreeBSD; kernel modules .. index:: kernel modules .. index:: ng_wlan and ng_pipe On FreeBSD you should also install the CORE kernel modules for wireless emulation. Perform this step after you have recompiled and installed FreeBSD kernel. .. parsed-literal:: cd core-|version|/kernel/ng_pipe make sudo make install cd ../ng_wlan make sudo make install The :file:`ng_wlan` kernel module allows for the creation of WLAN nodes. This is a modified :file:`ng_hub` Netgraph module. Instead of packets being copied to every connected node, the WLAN maintains a hash table of connected node pairs. Furthermore, link parameters can be specified for node pairs, in addition to the on/off connectivity. The parameters are tagged to each packet and sent to the connected :file:`ng_pipe` module. The :file:`ng_pipe` has been modified to read any tagged parameters and apply them instead of its default link effects. The :file:`ng_wlan` also supports linking together multiple WLANs across different machines using the :file:`ng_ksocket` Netgraph node, for distributed emulation. The Quagga routing suite is recommended for routing, :ref:`Quagga_Routing_Software` for installation. .. _Quagga_Routing_Software: Quagga Routing Software ======================= .. index:: Quagga Virtual networks generally require some form of routing in order to work (e.g. to automatically populate routing tables for routing packets from one subnet to another.) CORE builds OSPF routing protocol configurations by default when the blue router node type is used. The OSPF protocol is available from the `Quagga open source routing suite `_. Other routing protocols are available using different node services, :ref:`Default_Services_and_Node_Types`. Quagga is not specified as a dependency for the CORE packages because there are two different Quagga packages that you may use: * `Quagga `_ - the standard version of Quagga, suitable for static wired networks, and usually available via your distribution's package manager. .. index:: OSPFv3 MANET .. index:: OSPFv3 MDR .. index:: MANET Designated Routers (MDR) * `OSPF MANET Designated Routers `_ (MDR) - the Quagga routing suite with a modified version of OSPFv3, optimized for use with mobile wireless networks. The *mdr* node type (and the MDR service) requires this variant of Quagga. If you plan on working with wireless networks, we recommend installing OSPF MDR; otherwise install the standard version of Quagga using your package manager or from source. .. _Installing_Quagga_from_Packages: Installing Quagga from Packages ------------------------------- To install the standard version of Quagga from packages, use your package manager (Linux) or the ports system (FreeBSD). Ubuntu users: :: sudo apt-get install quagga Fedora users: :: yum install quagga FreeBSD users: :: pkg_add -r quagga To install the Quagga variant having OSPFv3 MDR, first download the appropriate package, and install using the package manager. Ubuntu users: .. parsed-literal:: export URL=http://downloads.pf.itd.nrl.navy.mil/ospf-manet wget $URL/|QVER|/|QVERDEB| sudo dpkg -i |QVERDEB| Replace `amd64` with `i686` if using a 32-bit architecture. Fedora users: .. parsed-literal:: export URL=http://downloads.pf.itd.nrl.navy.mil/ospf-manet wget $URL/|QVER|/|QVERRPM| yum localinstall |QVERRPM| Replace `x86_64` with `i686` if using a 32-bit architecture. .. _Compiling_Quagga_for_CORE: Compiling Quagga for CORE ------------------------- To compile Quagga to work with CORE on Linux: .. parsed-literal:: tar xzf |QVER|.tar.gz cd |QVER| ./configure --enable-user=root --enable-group=root --with-cflags=-ggdb \\ --sysconfdir=/usr/local/etc/quagga --enable-vtysh \\ --localstatedir=/var/run/quagga make sudo make install Note that the configuration directory :file:`/usr/local/etc/quagga` shown for Quagga above could be :file:`/etc/quagga`, if you create a symbolic link from :file:`/etc/quagga/Quagga.conf -> /usr/local/etc/quagga/Quagga.conf` on the host. The :file:`quaggaboot.sh` script in a Linux network namespace will try and do this for you if needed. If you try to run quagga after installing from source and get an error such as: .. parsed-literal:: error while loading shared libraries libzebra.so.0 this is usually a sign that you have to run `sudo ldconfig` to refresh the cache file. To compile Quagga to work with CORE on FreeBSD: .. parsed-literal:: tar xzf |QVER|.tar.gz cd |QVER| ./configure --enable-user=root --enable-group=wheel \\ --sysconfdir=/usr/local/etc/quagga --enable-vtysh \\ --localstatedir=/var/run/quagga gmake gmake install On FreeBSD |BSDVERSION| you can use ``make`` or ``gmake``. You probably want to compile Quagga from the ports system in :file:`/usr/ports/net/quagga`. VCORE ===== .. index:: virtual machines .. index:: VirtualBox .. index:: VMware CORE is capable of running inside of a virtual machine, using software such as VirtualBox, VMware Server or QEMU. However, CORE itself is performing machine virtualization in order to realize multiple emulated nodes, and running CORE virtually adds additional contention for the physical resources. **For performance reasons, this is not recommended.** Timing inside of a VM often has problems. If you do run CORE from within a VM, it is recommended that you view the GUI with remote X11 over SSH, so the virtual machine does not need to emulate the video card with the X11 application. .. index:: VCORE A CORE virtual machine is provided for download, named VCORE. This is the perhaps the easiest way to get CORE up and running as the machine is already set up for you. This may be adequate for initially evaluating the tool but keep in mind the performance limitations of running within VirtualBox or VMware. To install the virtual machine, you first need to obtain VirtualBox from http://www.virtualbox.org, or VMware Server or Player from http://www.vmware.com (this commercial software is distributed for free.) Once virtualization software has been installed, you can import the virtual machine appliance using the ``vbox`` file for VirtualBox or the ``vmx`` file for VMware. See the documentation that comes with VCORE for login information. core-4.6/doc/performance.rst0000664000175000017500000000527612124660203013044 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. _Performance: .. include:: constants.txt *********** Performance *********** .. index:: performance .. index:: number of nodes The top question about the performance of CORE is often *how many nodes can it handle?* The answer depends on several factors: * Hardware - the number and speed of processors in the computer, the available processor cache, RAM memory, and front-side bus speed may greatly affect overall performance. * Operating system version - Linux or FreeBSD, and the specific kernel versions used will affect overall performance. * Active processes - all nodes share the same CPU resources, so if one or more nodes is performing a CPU-intensive task, overall performance will suffer. * Network traffic - the more packets that are sent around the virtual network increases the amount of CPU usage. * GUI usage - widgets that run periodically, mobility scenarios, and other GUI interactions generally consume CPU cycles that may be needed for emulation. On a typical single-CPU Xeon 3.0GHz server machine with 2GB RAM running FreeBSD |BSDVERSION|, we have found it reasonable to run 30-75 nodes running OSPFv2 and OSPFv3 routing. On this hardware CORE can instantiate 100 or more nodes, but at that point it becomes critical as to what each of the nodes is doing. .. index:: network performance Because this software is primarily a network emulator, the more appropriate question is *how much network traffic can it handle?* On the same 3.0GHz server described above, running FreeBSD 4.11, about 300,000 packets-per-second can be pushed through the system. The number of hops and the size of the packets is less important. The limiting factor is the number of times that the operating system needs to handle a packet. The 300,000 pps figure represents the number of times the system as a whole needed to deal with a packet. As more network hops are added, this increases the number of context switches and decreases the throughput seen on the full length of the network path. .. NOTE:: The right question to be asking is *"how much traffic?"*, not *"how many nodes?"*. For a more detailed study of performance in CORE, refer to the following publications: * J\. Ahrenholz, T. Goff, and B. Adamson, Integration of the CORE and EMANE Network Emulators, Proceedings of the IEEE Military Communications Conference 2011, November 2011. * Ahrenholz, J., Comparison of CORE Network Emulation Platforms, Proceedings of the IEEE Military Communications Conference 2010, pp. 864-869, November 2010. * J\. Ahrenholz, C. Danilov, T. Henderson, and J.H. Kim, CORE: A real-time network emulator, Proceedings of IEEE MILCOM Conference, 2008. core-4.6/doc/Makefile.am0000664000175000017500000001232112021436556012042 00000000000000# CORE # (c)2009-2012 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # Builds html and pdf documentation using Sphinx. # SUBDIRS = man figures # extra cruft to remove DISTCLEANFILES = Makefile.in stamp-vti rst_files = conf.py constants.txt credits.rst devguide.rst emane.rst \ index.rst install.rst intro.rst machine.rst ns3.rst \ performance.rst scripting.rst usage.rst EXTRA_DIST = $(rst_files) _build _static _templates # clean up dirs included by EXTRA_DIST dist-hook: rm -rf $(distdir)/_build/.svn $(distdir)/_static/.svn \ $(distdir)/_templates/.svn ###### below this line was generated using sphinx-quickstart ###### # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CORE.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CORE.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/CORE" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CORE" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." core-4.6/doc/conf.py.in0000664000175000017500000001776112122624673011730 00000000000000# -*- coding: utf-8 -*- # # CORE documentation build configuration file, created by # sphinx-quickstart on Wed Jun 13 10:44:22 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'CORE' copyright = u'2012, core-dev' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '@CORE_VERSION@' # The full version, including alpha/beta/rc tags. release = '@CORE_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'COREdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'CORE.tex', u'CORE Documentation', u'core-dev', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'core', u'CORE Documentation', [u'core-dev'], 1) ] # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. epub_title = u'CORE' epub_author = u'core-dev' epub_publisher = u'core-dev' epub_copyright = u'2012, core-dev' # The language of the text. It defaults to the language option # or en if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. #epub_exclude_files = [] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True core-4.6/doc/ns3.rst0000664000175000017500000002460112205477411011246 00000000000000.. This file is part of the CORE Manual (c)2012-2013 the Boeing Company .. _ns-3: **** ns-3 **** .. index:: ns-3 This chapter describes running CORE with the `ns-3 network simulator `_. .. _What_is_ns-3?: What is ns-3? ============= .. index:: ns-3 Introduction ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. [#f1]_ By default, ns-3 simulates entire networks, from applications down to channels, and it does so in simulated time, instead of real (wall-clock) time. CORE can run in conjunction with ns-3 to simulate some types of networks. CORE network namespace virtual nodes can have virtual TAP interfaces installed using the simulator for communication. The simulator needs to run at wall clock time with the real-time scheduler. In this type of configuration, the CORE namespaces are used to provide packets to the ns-3 devices and channels. This allows, for example, wireless models developed for ns-3 to be used in an emulation context. Users simulate networks with ns-3 by writing C++ programs or Python scripts that import the ns-3 library. Simulation models are objects instantiated in these scripts. Combining the CORE Python modules with ns-3 Python bindings allow a script to easily set up and manage an emulation + simulation environment. .. rubric:: Footnotes .. [#f1] http://www.nsnam.org .. _ns-3_Scripting: ns-3 Scripting ============== .. index:: ns-3 scripting Currently, ns-3 is supported by writing :ref:`Python scripts `, but not through drag-and-drop actions within the GUI. If you have a copy of the CORE source, look under :file:`core/daemon/ns3/examples/` for example scripts; a CORE installation package puts these under :file:`/usr/share/core/examples/corens3`. To run these scripts, install CORE so the CORE Python libraries are accessible, and download and build ns-3. This has been tested using ns-3 releases starting with 3.11 (and through 3.16 as of this writing). The first step is to open an ns-3 waf shell. `waf `_ is the build system for ns-3. Opening a waf shell as root will merely set some environment variables useful for finding python modules and ns-3 executables. The following environment variables are extended or set by issuing `waf shell`: :: PATH PYTHONPATH LD_LIBRARY_PATH NS3_MODULE_PATH NS3_EXECUTABLE_PATH Open a waf shell as root, so that network namespaces may be instantiated by the script with root permissions. For an example, run the :file:`ns3wifi.py` program, which simply instantiates 10 nodes (by default) and places them on an ns-3 WiFi channel. That is, the script will instantiate 10 namespace nodes, and create a special tap device that sends packets between the namespace node and a special ns-3 simulation node, where the tap device is bridged to an ns-3 WiFi network device, and attached to an ns-3 WiFi channel. :: > cd ns-allinone-3.16/ns-3.16 > sudo ./waf shell # # use '/usr/local' below if installed from source # cd /usr/share/core/examples/corens3/ # python -i ns3wifi.py running ns-3 simulation for 600 seconds >>> print session >>> The interactive Python shell allows some interaction with the Python objects for the emulation. In another terminal, nodes can be accessed using *vcmd*: :: vcmd -c /tmp/pycore.10781/n1 -- bash root@n1:/tmp/pycore.10781/n1.conf# root@n1:/tmp/pycore.10781/n1.conf# ping 10.0.0.3 PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data. 64 bytes from 10.0.0.3: icmp_req=1 ttl=64 time=7.99 ms 64 bytes from 10.0.0.3: icmp_req=2 ttl=64 time=3.73 ms 64 bytes from 10.0.0.3: icmp_req=3 ttl=64 time=3.60 ms ^C --- 10.0.0.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 3.603/5.111/7.993/2.038 ms root@n1:/tmp/pycore.10781/n1.conf# The ping packets shown above are traversing an ns-3 ad-hoc Wifi simulated network. To clean up the session, use the Session.shutdown() method from the Python terminal. :: >>> print session >>> >>> session.shutdown() >>> A CORE/ns-3 Python script will instantiate an Ns3Session, which is a CORE Session having CoreNs3Nodes, an ns-3 MobilityHelper, and a fixed duration. The CoreNs3Node inherits from both the CoreNode and the ns-3 Node classes -- it is a network namespace having an associated simulator object. The CORE TunTap interface is used, represented by a ns-3 TapBridge in `CONFIGURE_LOCAL` mode, where ns-3 creates and configures the tap device. An event is scheduled to install the taps at time 0. .. NOTE:: The GUI can be used to run the :file:`ns3wifi.py` and :file:`ns3wifirandomwalk.py` scripts directly. First, ``core-daemon`` must be stopped and run within the waf root shell. Then the GUI may be run as a normal user, and the *Execute Python Script...* option may be used from the *File* menu. Dragging nodes around in the :file:`ns3wifi.py` example will cause their ns-3 positions to be updated. Users may find the files :file:`ns3wimax.py` and :file:`ns3lte.py` in that example directory; those files were similarly configured, but the underlying ns-3 support is not present as of ns-3.16, so they will not work. Specifically, the ns-3 has to be extended to support bridging the Tap device to an LTE and a WiMax device. .. _ns-3_Integration_details: Integration details =================== .. index:: ns-3 integration details The previous example :file:`ns3wifi.py` used Python API from the special Python objects *Ns3Session* and *Ns3WifiNet*. The example program does not import anything directly from the ns-3 python modules; rather, only the above two objects are used, and the API available to configure the underlying ns-3 objects is constrained. For example, *Ns3WifiNet* instantiates a constant-rate 802.11a-based ad hoc network, using a lot of ns-3 defaults. However, programs may be written with a blend of ns-3 API and CORE Python API calls. This section examines some of the fundamental objects in the CORE ns-3 support. Source code can be found in :file:`daemon/ns3/corens3/obj.py` and example code in :file:`daemon/ns3/corens3/examples/`. Ns3Session ---------- The *Ns3Session* class is a CORE Session that starts an ns-3 simulation thread. ns-3 actually runs as a separate process on the same host as the CORE daemon, and the control of starting and stopping this process is performed by the *Ns3Session* class. Example: :: session = Ns3Session(persistent=True, duration=opt.duration) Note the use of the duration attribute to control how long the ns-3 simulation should run. By default, the duration is 600 seconds. Typically, the session keeps track of the ns-3 nodes (holding a node container for references to the nodes). This is accomplished via the `addnode()` method, e.g.: :: for i in xrange(1, opt.numnodes + 1): node = session.addnode(name = "n%d" % i) `addnode()` creates instances of a *CoreNs3Node*, which we'll cover next. CoreNs3Node ----------- A *CoreNs3Node* is both a CoreNode and an ns-3 node: :: class CoreNs3Node(CoreNode, ns.network.Node): ''' The CoreNs3Node is both a CoreNode backed by a network namespace and an ns-3 Node simulator object. When linked to simulated networks, the TunTap device will be used. CoreNs3Net ----------- A *CoreNs3Net* derives from *PyCoreNet*. This network exists entirely in simulation, using the TunTap device to interact between the emulated and the simulated realm. *Ns3WifiNet* is a specialization of this. As an example, this type of code would be typically used to add a WiFi network to a session: :: wifi = session.addobj(cls=Ns3WifiNet, name="wlan1", rate="OfdmRate12Mbps") wifi.setposition(30, 30, 0) The above two lines will create a wlan1 object and set its initial canvas position. Later in the code, the newnetif method of the CoreNs3Node can be used to add interfaces on particular nodes to this network; e.g.: :: for i in xrange(1, opt.numnodes + 1): node = session.addnode(name = "n%d" % i) node.newnetif(wifi, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) .. _ns-3_Mobility: Mobility ======== .. index:: ns-3 mobility Mobility in ns-3 is handled by an object (a MobilityModel) aggregated to an ns-3 node. The MobilityModel is able to report the position of the object in the ns-3 space. This is a slightly different model from, for instance, EMANE, where location is associated with an interface, and the CORE GUI, where mobility is configured by right-clicking on a WiFi cloud. The CORE GUI supports the ability to render the underlying ns-3 mobility model, if one is configured, on the CORE canvas. For example, the example program :file:`ns3wifirandomwalk.py` uses five nodes (by default) in a random walk mobility model. This can be executed by starting the core daemon from an ns-3 waf shell: :: # sudo bash # cd /path/to/ns-3 # ./waf shell # core-daemon and in a separate window, starting the CORE GUI (not from a waf shell) and selecting the *Execute Python script...* option from the File menu, selecting the :file:`ns3wifirandomwalk.py` script. The program invokes ns-3 mobility through the following statement: :: session.setuprandomwalkmobility(bounds=(1000.0, 750.0, 0)) This can be replaced by a different mode of mobility, in which nodes are placed according to a constant mobility model, and a special API call to the CoreNs3Net object is made to use the CORE canvas positions. :: - session.setuprandomwalkmobility(bounds=(1000.0, 750.0, 0)) + session.setupconstantmobility() + wifi.usecorepositions() In this mode, the user dragging around the nodes on the canvas will cause CORE to update the position of the underlying ns-3 nodes. .. _ns-3_Under_Development: Under Development ================= .. index:: limitations with ns-3 Support for ns-3 is fairly new and still under active development. Improved support may be found in the development snapshots available on the web. The following limitations will be addressed in future releases: * GUI configuration and control - currently ns-3 networks can only be instantiated from a Python script or from the GUI hooks facility. * Model support - currently the WiFi model is supported. The WiMAX and 3GPP LTE models have been experimented with, but are not currently working with the TapBridge device. core-4.6/doc/figures/0000775000175000017500000000000012220631512011521 500000000000000core-4.6/doc/figures/core-workflow.jpg0000664000175000017500000005137311772163355014774 00000000000000JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222x" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( (9>Xi-ZkE$Y>U,rçjzDe55ߘmYFv F0O@q"7Ěw6I JXo$F),D7*Of7n紸]ͼ7܆y$|H#sr7EeZC,[@b+qfk^oh3t% Bw A$ϱ7/Yڛ8~١>JʳK>+:O^^Ιd>ufª pst~/|ig&hΠ,)V|'-9ႺhٖWW6izm Ӭq0"0U:/Cu5F./ZiIp9⮓{AR &n%G|V)!F];?)ӯ<t-lfݞ;dq nęE#oVR$:n0<+}ł$ћ]њ+ܤ\[WpX:;Ceku=+x& D׾xH &<=K9u8$G˴lW93A]BETͳfr>T|3<uO Yɦƺn=n#:Z @5ߌ};Q&{SvUi# _Ixd554%/3;Z%'%zcfQmgP;Dr }Yb 3a0m3oڤ0 8XvkiLF! m;82趉[B;4ꥊI8Su2k5/x-muycHV`qh;#[^K=kjr,n # 2.=>iO9hEPKF$+<83ԤX"!.5LrDKFW)tx$c_ mB{{m53x$Pll/ˌW5<~Ԟh!:%m8ݘ ùr:PLJg7ΰG"WRHv@?&x~jwrZ!#YvIǹ :Qr:EqZSVz,iOim4r3۴λbH:WYp-U/M!PN`l@tQEQE[3_+Zͦ)HA!X$뎶7֓4au6&)">d8<&ZH\\HdLVS<tjwzS:Sjoc5hC6RsQ0< OigQ}=ٌK<1_^&Nn48$rU3#  2z1wm+[z捧jZX.9\g g'=x@|Sjp7"Sn/ƿfw:}~6q|v1nwYH2;(W*O=ǃnuoh ;oc7ncDIh{k{+ r#c9P[ct<ѭtn풘̒+Fi9c ^^}M D9dGhP^۰ڻ$r WK.\ݮKYmiYebN:f𮬚ܺ&ݍS[#dkDu/ )982ЙDKeisQ (pe.R85akXC}e0eFG>mš]|lxf`/*p $kT'mY$EPEPEPE} 闒YJ8rRr2?gxV^mn4SP|":ϖA`z6xCXƿ)]bx^[}K|FT.'i_oKv+ڇtڇugO ͣ|_UxWm⨰[?##?##?xWm¿3hEmCB?R??mCB?R? fѿ>/*M<+C6TX9[?##?##?xWm¿3hEmCB?R?yOӭ^>/MTE/?QK[-sL;!7v'O\%`=Z(Yl4qZՇ羝d"@G V5H꞉%{ÿcN9Y-G GG-G G]-X\5 jk jkKEs5H5H륢9ڇtڇuEmCB?R??mCB?R?hrW:|#kxiD\ ?K5aVZw u6O8?-JNYwux# J9.ڇtڇuNs-G GG-G G]-X9k?##?##,5 jk jkKEs5H5H륢9ڇu^>Z|_mo7>_]mp?k?GEzQH>(i>#+/}:fEށםp: jk=J9Ɲr9[PЏ_.[PЏ_.Z(k?##?##,5 jk jkKEs5H5H륢9ڇtڇuE>3u^G|骈8%9 ~5u??k?G^HQE ( (2G[֤ KT Zf$UԱy s\-G GM'ψIc@ܽ %5 jk jkKE'mCB?R??mCB?R?hs_ƿ)]ƿ)]tQ`9[PЏ_.[PЏ_.Z(s-G GG-G G]-X9N5\CXa骾dQr&dE{I@}Fc̍$!GEIpZ)V.|^e{gidٛ~qg?j(^\y U 2 製m'«h./#oRo2@:jK5aV!QE ( (_>O?ɺX n#X8 oQ Wid{H7pOuX~4Y|,! =+fɻ(QEQEQETsO<1)y$($w+^>HBI(sY6]Fd 7'@Zi&}⻸K5$ŋEf %Xp:EwV6fmagkkC n'j(FO'TcIfm|WIfm|U=Š‹6UH, 1w;'qUώ4ŖX$`?1v#8ppOc&mF:Aj('s]q's]4e-Š( (((($Y>:jK5aV!WhW ;Iz}y%{ÿA-Ɗ(3 ( ( ( ( 0,0,V*MO0?|@wk?|@wi)nQE1Q@Q@Q@Q@?%׫W`Yz&i (PQEWOωN~.9ܮXyJ_KKC*|ry'dwQEQQEQEQEQEW$&y4hWͥ y(B e$;N2x赝ZBѮ[ok@-2@,N*2[^]ojr8;S` 2=JeAQHK4ooK4oo`xv_.8&aO>O | XK2!}P~aQ 4H F0cue9@<0蚑Z[o^}$ lT&r ohKp#2ycr;[aڈ4`%D$ˇ'AݞZMY{V")Pp=+] ǧ)#bJsq ]G7eNA:/++I,fϘ!ϖw?Pqt*R pY6v<{j_ !#FBNF=Io t!g%K/OQ@Xs,Xg`d$) 3WMXVVUI_OkQ^C*N `r[ ?%׫W`Yz&i DNk4O+? lv4QEQQT.u+f`%[yfLpA9.chUKy +m݂}:P|"*1 2dS -JVf-QU%2sJqQGdhV iW)xG'56OE`\&A$um.8Iuo, w<Ȯ pr*jG*9( má#?yx{S}rNtnhTDx"UNQ;bwl͎ǥ>cOfmma6 $9Ywm'# ku;]j<^ 9*.8P;(Q@?sYDj=, idu$|XF2Tkի<ߏdtK=gޙDylag*)R22P`jKb]5Mqܮp JxK$E4rJ'i9p})i֋4jVVƊStPOyS09|au (NЪKsdN1=};]SkIl̑Kop6獻x HW.1, \G B&"Fb nTя! %쮮h*wT@OkB-2m͗!ʨ W8^Fo^䰆2,!IP}~nZFÏ*ms4dt?L4o5EZ"|;,K$OMԪO7lFLu}9FX-DW;` *>#5-1ck5`RLCJ0 !2qXor@SJ·HjkfI}.Lnn@5^?2dQCy( rNwrۺ8ɯs ;{Ikwu5@`YzyO%]{XDžZ,%+цAr$b4Q^a^p'5|-*?ٺ~vw16 *%{ÿA-Ɗ*)wI>ۻ'FeK SkQ+[rᱏ0эS6R٥EI@˻%v#Ө.e!ҜXH!PcUE 9T7&7 K|._cw9 ~Q ]3<׷B$1`ۆS rLgȭ4ѭ㲵.iI$y5ޓ߽oYͰa2Q/ga% , ޘ휏Su[Yu).C. sf,8e PlƟ".7A1]ezIn?mX¦q)*p;rqڮ3!YogtVxP9sx玵Öi:Hńby\?%q\?%5W/{XDžZ,%+цAr$b/wl{|`ԡ^p'5^p'5FRƹ՝ܫ8 p`m֣K\,n*ƌcv̿.ryHg_4=$brGq9]NPךc:[5[) 2:`ilIbHYsptpwݚR%QI;`bmu;He7(jD@.Bpg-Mmw =^]Fa2΍lwQBxxVS~4 .T8%Ir9$O1.o%6l#=Fz bjX͡Z>^#,3ڲ߮oݴWR4Fd;T r8N8`o_zP{ ern0r銫u为L$ /#$qsvzaimn9Hm% v+n1sL[LWZ;0&?_%~\!H:6;儖E+%R?#aqB{`u>_=Wuq#bd v(ʩ Zp?k?G^^SIfl?|uԙ6 (n4Us*F=FA$`'nQFW4<[Xii;QA,p987O xmؗ?%܀x. ֗śeݧxۻ'̞??{k̤(uv(͍oَ*泠K\4^$XVU2ps׷`C9Y/а6ClƪA\&s88oLo/2">]rAs]zںKDX9`&ty}q@rImљ<.=uX>jFslLD+7_bOyt7A:,ۄDF 34(li5K!&.]͑ЩjzHnv>p=:V5ZZ˩IpvF;1d)7SPMn+yX|{Ҁ%5kr@]đ'dm皊}̄"𯃮.7$ӭwW,q&Bn`Hێ⵾0,Z4 ^Ueȱl72/qy[,r? ƚE%ZdQnz'sI;(+vq IRKY:oageUMHW< og>mes0ô&*q9;|cw$WB,ߛ8ЇCQ&&{۷{Ux+±Xe"m$=ɠz~50H5uP1 8Z_bMDIO$dޕtm/uVFZ0#!K =yixvE_bM2I` cph Z*/bf>|*'R$jz`Yw`Y[? ¾ܒjNztq\=ę #n;<]ּbo'd_oH YH+*MO Fo^4-y-" sԟ0@A;DNkkqڌV4$\ʹrXƖa%KYR73yNF[/Κz}k;K b[1r96tM܍ϐ>PvsjСa$- q'Fq``rb&O#p,{S mCm3:%㕓Ifl?|uԙ6<vV_-5K@ZZgT3b8@Rfx^Xw̠mrk0HH |7n?;2Eo"f߀@`pA4?7XO}qx^/Z5Ls6^f\a0cX&<5k3e,P H|,Q q fe$ʇ$ n@dzhfgF[ɼו10`6i©Rx>\IZ4tƲG,r2+x.3wސjZ֡i$Y1Nd劳0z7s?oHh'u<{K^=-嵇03#4`U/sʨ$[Nu D !ۼ'RމkyZ[ efS* GNkZ)+MYOxHdkmyq;d^c}5.ll$5gM2'I$i\;wI gNXv#Aeom!AIԹER,(K4ooK4ooQE (=((+??D5w_JG?CD-?k?GG? !h$Y>:Aj('s]q's]4e-Š( (((($Y>:jK5aV!WhW ;Iz}y%{ÿA-Ƴ5>]F(H%Y ̣?+\x'|I[0tC[#<wz Cn_68K=d\fbn9Uȼ#zsK 'w#b̠iH8n\WdYc;x3XW'm-&K{dFIY7`4x 6|k4R71._dc+֬OS,]F <hշt͞M^к߻a5u9ĩl$UiBb4EqrpF S9S'`xU$>,K] QpG 9zZkAA俗Hp;=GՈ|EO1\3<@ˀ @'ScQVI3Q|r98Y͕$,s2Τ;$46hN˷NPI8@V;H|Q%&𽟞ho'#bo(u*8`2sz}p? t/6Χ Ρ! D @r~P=IVAEP0(~,ѿ,ѿ'QE(((+??D5wbxߎ22s*Â@@,==h*TE5{x>1P@jYTi;-c֥i qi:ʝ 5^q'|TYچu--W"Օ@( 墒L(ghW ;Iv5hW ;Iv4є (((((gի~0,Z4^a^p'5'sI;(((((+$Y>:+$Y>:=Z(5J+?$F>J*EP (7Y̗Ҥ׵Y!)ofIl 6* KxPdž|)u=m6ʤ"cdQ oR<9x[K]7E9}KcԳ1%AORj=M/L @~Ӊr H<`qk?IKz40%u(I-pWL\qjx!(T)$r(eu#x 1Jr ⹂9%Ueu# 8 .~>ýiĶ,C) ddgMsGԾ?="ɾ7$,W̤ǀŒozzpʝ[ 4J[\t?Yy:Η-c7qdӮ*Th仰w{YވlBӀzEEQ@a^p'5^p'5FR(b ( ( ( (8K5aV)$Y>:jLy%{ÿקטhW ;I$h0((((g븮gj( J9ƸJ9ƚ2ESQEQEQEQE`YzyO%׫Rf+ʼx]'&imp(+P.RqK;Ol'mF- yA P$2:dбɡQL((((CVa[HP @ʛB :Gkˠ Ly.P^<o3<\$v-KU?9dkkQ;qmIH!$r1# 5괙VER((( +!nw &y! &0[/N,}?4hsim/ ̂$=_ԾIgxg]J[8%E4cqa;$9 2%(:N {^wnl8k# (յ7BkVKu+cq;Tuf8$LpzKh[hj]),X d w@_Ծ$yx:gQB\xH! gi/FO> i~4#kw@-_%W S|quPEPEPhW ;Iv5j5_'<:ğTaf ;(?w!Ŷu4W-/ *A|wE/(PT\\h[_KU_P⨸r3oA|wE/(PT )BΦAQ/ *#:+RG ;(?.Ifl?|uZTfϳo$K rP;ת.*^a^p'5皧zoO'΃1'UE:\ ;(??ASh[_KU_P⨸r3oA|wE/(PT )BΦAQ/ *#:+RG ;(?.k$Y>:/ * |[SiO>mdؑ.0aʸ=@EƢU)y%{ÿc\֩^x'SIF~foQ )Br[gSEr_PREΦAQ/ *#:+RG ;(?.h[_KU_P⨸r3oA|wE/(PT )B?k?G^^U|-nMj<9bD*z"yU|M[G;XSJ50XQ #A $S]ub&jI ̷ GERxOS-{_S&IuW%k _Wu\\hK;(r/_Wug|Z;ζ俳-{_Qk ‹+:+~w_Qϥ\ #KΥD>#pdmW[GNd~]jY.)B:,WR=lGE{6\n͋R@8*C̲T ݻ\).Z>|TٝԌɉȷuAdug`~("ՍΫ.;:y^u $j[(2Z ^O Ll_P{cTqc4~4N)w)"U'CUK4$^bڋ\9:?5v4ℓ]d!R^02;$MŮfc;~+{r)gW,x8K_{'/ecʊdʤrd1`#}Gy]H hgٰ% !F%哌=7&" 7%dU6Xz*N:l2&!W kPA'S.&S[:m'|?TqE uPd!zz^;ceGXDZTa@sTTl90[(OQ;giN{LԡQf׀Trk=vyjR;c6#ԇeߩN+vz pq1 )]1M默 wӳ>6O6({`H-D|8-Le{Qecep))#|T?1 -ʞBO!P?! Tltj1(NZ4N٨)sB!jN0&M`@Br3 3b%SJ=T9( Ex>FiJL# qc6R&Svɰ,]ݝ?@]x aPp\yv# B(D_R EJ#+Àw( nOC!Hz_c1Y`Ql[TT re![/n< ƃ~L ,CDAq4)|jPf6 #( A2߬OI<2)V׶O' #5 Qn9'UQB:ϟP[e2lTu)v`1Z|R1έ:*T :D ͧ{!*)/=6\Ywz9WXoyy ق(pاߍRKj ;;Wb6軈jiKY%KurGg"X?1rqx9 Y(͸E!Һ5ZD@D:3,"FI!mM0x$E+)8`V;.Z,gPɊ$͕m`4\!^e_7,8d&/w716H\iW(ăIڹiǸT8Ba@u:s:U-L+C3*ޛN("eQ)"L:u߲<.('(~)ĨQ+}72f163s7 }|VO( 'hcsN.aa%yI>bw>TޠinG09nj^c+ 3k٤ӱsMքxX^[WLSKC ٽ %P n')cu>ٽm) 0vqL/2 峦Rx1{nuEOk]X_.uSRW{&d<=Ui/ucPzyl4/ 묈/;t!Q*,$ʒDU{rf|KEw>Zuh4=UނHF5R˄LoN?uR3x'fS e[\:cM7Xڬei]PK-l#su{+-Z) Z={kjӷx{/]7HUԎDQn:q8QT)ƔxAO36g$g9uw8 mEμ~_T]o|zW5Dcore-4.6/doc/figures/core-architecture.dia0000664000175000017500000000344512124636166015553 00000000000000\mo6_!,R%5MXZlg[^<}o);-Kq,jP@X>ݑ'yt޾Kb< tQ:п]}xufYxU6M;P]䩎DL=U?!H ^e b1H1 ⩯"~iKP22!ST"tLp~|0w0-i47JT8SNSi)s Nu['!o`"߇2}9Lblڨ)鈤aыݑzJИ˦ T"" | ڰi30ٲlm;ֺG1IG:F;|Jr5ٹ;lo㩏c^y<]$0ϲy]zxXR0Pa@5z!P<; G~ѯܹ Ǵo{jʞdQ ?><bd,K\m3n)x8\8,|9.%8 [5NHfM2}d|ژ~ )`5 akw<Bֽ|W헯O_?(< ` EnHR/\}Ik՗}qj!&Io ĽQgsV_`CٯΎИRԽԩʗp. ќ^9mG%Wt*:P!뭢S_j:&ʿL(+IKzТK*?P|%2 ELrH/&@4M ߋL_B}9tbcore-4.6/doc/figures/core-architecture.jpg0000664000175000017500000011272012124636166015573 00000000000000JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222 p" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? ?ɩ?S'57]rǰ{I8T /MM ?ɩ裖=O§Ojo.T /MMgE}3? St§Ojo.:(`q@_? SuG,{sO]@_Ί9c=g*&O]vtQ'?S'57G*&볢Xi> ?ɩ?S'57]rǰ{I8T /MM ?ɩ裖=OMk"k4Vk?nQIppOClCj%2A+$ A_Ht/x҉+KcܓL wf%ܱ[ZFIs3$kI'_o ?ɩ?S'57]rǰ{I8T /MM ?ɩ裖=O§Ojo.T /MMgE}3? St§Ojo.:(`q@_? SuG,{sO]>?M BH}g8vQ'W|'֎k>"i}#)` QA'Jk+暳NNQMQRXQEQEQEQEQEQEQEQEQEQEQE_ G=vu|'go\~y>6QE2B((((((((((CIW/$:DnV|?J?_S>GDgEWQQ@Q@Q@W\ۏiebyP=ǣRnÌy=!to'M/ 9O>EMKpX*t3CWLKeыq\Mw;J+u ᫋). &o2x䍋9ﷃ۶*{d((L &=Ԓ&w ((((((((((((Lm:>3?z? <ڟ (!EPEPEPkqac$gk3ݟ±/|+]MZbKM4lJL]n[kzE֙v 2#¹koe.t[ŀd(^ ޵N{##*^9~aw0];{#OVna3c^@=̚ΙhLyszl$(Ec$I9SvJ)Zivq{/H[bG$So_]k@'"'|[m{iHb vfhV3N^~p*JCC%0ʖ90G!ӸQ{ ŤlUY״{k[n$wC s:b>'h +aipHe)+M*i1OEOܮDGV~i"D336܁PIڙji5Ϳɉ8{ygĶ7<< m|.~\Q78ܧ;sqmLb;heIh2Rgy>n5_iڱRo&,8,Cg?Es|Oe }$3IBzǢ9 NMp:έxRX5+-A:=PϠ5rYh5}O: .o 0ƲDCle]r1G0r3D57WFVSGWU^"XZI^UC:Ik-ZQӊwڨ!E#V8.`) NE.a7J+޷xemev"v58;ʌNOξ}Jivoi; ``zRIk/J*pAkl!xV-CSLm W\:cZK_ MŵQd*T\n*WES */$:DzCIXua^g Jg蔯L3%3JVqOTQEupQE|@W 7f?Ƒc?|񷝽\Qt+,l(\HmnU_kǟͷ;^WKuJ$'MKolpVS L63Vݮ須"YJ ꧨj\:]?,V9.4{ch>5;S 1`uz"xz8ڭF>ʒ\}۞3]aƱ]SGXfmȀX>q9Clu[ɣ֖r1Wا's~{8[ݔa#o8aIs/Óykl-:&,d\BcV-tN|B݌ ilsv6Y!Yaӭ3.v$ztbcBnˤ[A{ k.`n$P(@t dtűHm`Tb(# aܜ G(?7>wٶog{g>/yg ýP6B@LҺmJhL,јU(Xa#VbY!(f+"]N>rOh> Cz  :Ʌ! WCZ-{Tt+d?X +pF9z쿳,?m~/qfдہqwX8$:rFh8BSZ7J6§ҿo^eycoN3n K7vuXIӀpsƲ9ớ ZTK%h ]= Ad9:QgpV:((/x N+kɯx N+kAETQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@5Imsg\g&zG]uGSaX^*5-6 T5wX쇔$ܥ[SzwK:4)7pS>k ;RkJy!"KWByWEECRh|;}hcji+=m RIѴ˛}cZԯo'U) @OĒEgkx 8ɥѾ-/VFϰG:y[3 3񍾇9Z(]U_k?hxcn99ڳ'he,3$m'y,~YA*2NNF ,NqUt%>T5gP\61ֽY39KK`"9c%H(Vto[KxZ(ldGf|Ā t4Rfei:7]s7BvmE\g'?w9e6_Inm#@c:RHv=zWSE; g-ujz鼚eEmDHCcܞs8zsw*G mNG9fJޢ96QE1Q%$B(U_Ht/x҉+7S+!Lq|?J?73j( /'宙Gmcho.1c( zWI\CMi$-SN ĕ_?AOai:# f82j]Gq췷7Eg9hssMKZuo/佷3+ 1mc*]EY2M$ ApqJUsEZ8&剥Ug(MA'3eMIkm+s:[lw# UmnkfDjgVN]=~Ѭ[pF=x4/`5^I_48pppqԺLt}W9 `c$e`;X]?<+ V4 ",daJ$vfߦ>E[x{ƞ2fYPzsE(ŝV7N.HM[5{C=]^‹)3!$RAr:f|?#^Rn`aӏcZb]3l;7vd؜R3ڶ}R0ЍJ(r#w ޺K$fFW( $hR<Fеข9#3+n!9Mu9tm{`I-Rg;԰=7q+wsuq?b!cW8BLes)*t .byTK;FXgKKMۏ˥rl;]*By{>&5V\||sޖבi#13xr7AuPO̱5#ME9+j]j^148n|=5v, 89ZlSj/$H 㸝܀U{88M%~y>](k-N7xTt`;7)^=+S]1ޟ?di/?ER7k-QE9+k+3QEEPEPEPEPEPEPEPEPEPEPEP|'go?hwbwZ!m;񌞝k(j|l(dQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q%$B(U_Ht/x҉+7S+!Lqcw;M'W~vg=Ee?QEuhTr;DoQFG#>%QEQEQEQEQEQEQEQE—p&BF8 du%PEP1%{_q^^M%{_q^\>&w ((((((((((((+V Zm̥bD\.$/9$|VhSkb%N2whoCsz>Vh%ܟaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬Gp#Χj#X'* #>g ñ#?'?[ {x [Ov}ͻNJ3A$/c}7U5OYo_Yv}>rYrǫK{}JoƨfG}! K丸`Ž0Ż0)[ }3N˵!7'ZEKm\bGX.K [me V09qZR(8l~#xnCDZz[ǒH 䜒Csz*:0}&?'?[n޽fphۘ],x^A"Hb ]StZ[[{AopI1@$Fa2x&>VIaY?TU{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬GpMNoG!9ݽz{IwaOoD+v}׬Gp?<}jw"w C;0vDQF@$f(+h((((((((((((((((((((((()+ /J޾((( fsy'kk3'j(%'o+P:~NJ }2PLqp>BÜm^'l,<$jnhY0rZAyx#~ѐFgDu"c7.sH ڪJܵi+O7O2F$jPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^zǚ=h$q}d1]YWI W w7sPޫ1]##<7ZxNYK$3s!$YM[ms(ڦF.<$a8#'99-#W4MSOL-MOV  7=pl4:v}jMq qΙǚ2]Osmg.c#mw=}*w>5m< e=儂S} h69 @ 3ÚV2K U5+n\n]w6w1r 8v$$2v H u8 Z^+G"Lu2:N hpI-(uor<'4 `CỄ5)w:@ @*]홺6Pn9`bP>9 HKm<%e?ss+`َ$lfb{U?ŧxKPˁ]'8\--NT}]\q`:IcUm {YxD: ̢0rNpF3@mZhz灧ڕu'+,CHyARNqֽE|'(70F??v&4}N--PҲ?xĚܐR(h 0I,xQw%ÍV(,_\&?&5x<:~"iz>e5踎$ ]®D`䏿w,߈gR!K[-N+#αUTA<.]xĚܐ`XؒE `X6W:tM4KK*_ЭTܸbIUS8>x\ځsoss~F[ROǵiRxNbQvM겦pwR _Myn5'-Qy x3()+ /J޾((f~-m"i_諒bp$ZKx|?o%t $XE+t)m_QW*6W,HРWu_[Svj㴈!|99w'x@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?SW[?8_ۏ}@Q@Q@* "|PҼb]0+摙o-8`bzVcvfml$NI'I'$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (5o$qPD.3#></J޾<]j5^W%H|U͆~bAr:z |Mx]r x畒-#e܊pIvy`(_m+Z_ e '*J^ <8'!HgLx䍊0 Aƚϊg3λ-?3txc='o-,a,Tmrw$i -Ϙ9a V|5dG0ػr"P;vAPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE|S}'HݴjQY\, Dז1 V9qOO[o LjX·6|cNtV&[5z][m[YۦȢN?$y$y5r2g &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg?|m WlD:j70%>Pz^a?u.$$dֽ9s[4cWh;<]׾ ~VOۭ%-f+s 6Q{q[S+qs4v O"v1D+MAc&(a?Loҏ~ ӿ=\#3a]Wy9s=#:ZZ-wvoPT*z8 "+'}m*?%|MjP"7xPH 2H$e>VQEQEQEaźGRNc3$2c$PHȮdjZS@JЭxPg#;XDrgcW?1D+Mw4Rbg &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg &?^h[5G;vpAc&L~ 1]sg)M RM Z&d`-#d`IҹkKn6A[ʲ8{0A$Do̺h'KnцbI%@IINW; (((((((((= ^^{+%Oc+#(((((((((((GuD;GuD#6 (((~ $ $` (((((((((((_Ht/x҉+# ?JS=(4 ( ( ( ( ( ( ( ( [wq/U1_!i=;(0 ((jȑZ#- FjKWNձiTC18ؿliw}j;wOƟd~^f߳`ݳsǷJvjqN/MRLPQ1!ִ!S[u:$ZkaS<#O;f88[ٽ;q` BuE) !C28xɧ\:]VWZSY]Rr t[赮+Cw7?mқfdھNoLw±xOWMIkhd<ˉv9bqMliھi!5 SJ?<9wb?!fȒOe犱K%(M4-mKT>]0Qa{{GK Zy.dl“Ru켿,˶i@-  jm5-Orp6LI)v;Nҍ"^ %U'eܓ 9  COP}gN[)j\ m4gٿ6sz {Ho^6g)mPA?2i6n8:zW4Oxr;H]j*-UaEǮΗYެgmY6}h1hޚ+M`$F=kG~C[v`M2g q6; ,Jyǡ ǫQXKhSOwbrI1&)(#ji + 2n&DpIe:\<7v-sHe~R22Jjx^Oݡh]4t8kP];ܟz=S,j9yK*ctsH՞DuK+׏ﭵHW봜RE-E|K2u557~o;wm+uFMiؿcůؼifݝۿ, ysʗD" z^k6aOrd\ ,Kͼrj#.i2F{93[uy.ΠŬXek]|^psXv=H ;;mmBB⥼ҴBll-nmWhUcF+玒mQUm$g#kcvn;oOlng+ut<1,l10ԐM(ҴN,-ERBQSl1튰b0WiB8LcҸAZUX Fg0leA9)Ht8]aU%f`~GҝY]].vO,-%n[$lh5OXKu"yHWZv+.D2,1EPNŚpfLrd%hsӾ)jiQD*RFobl纇TU=3Ś.~llD~hH$gzr*/jWz?5F_&MpA 1髦4i>!_+^zS-4=#OhJhC6cp\3u+>.tD{ RWcׅ&0YJ v)PԵyQW>sr1GqOEsX>f(C=@q*4/[/>\l럯:mtft{me[I}F:g3m s3JJT`n=N=VF ;xN*Io rI'&Ou r7 gV;cAp0=_hgE$q$%= SӴm/HW]3MY\[@>@Ie Ym!c$)}-rsϿfZXPŴ, qӭ?H.Kq43E,/ = WPppy( M8a$$qơU ;S]/JYO(ʬIG"E v9=.wЛ:eбW 8aX(y=oNjڵ`%Ϸt(H <]D7)gj1ÝסS Y?wm jVUkvS, HmbOzdsvW֗ۯmcI&c s=j,.\o|WAC}y_uY9᱑gz.A{XIj,b=C@oX~G%5y?򮪊W OkZgt wE"qj!e{>P5\Mf`KΌ SQj).x lnMͶf109`cQxAw"ZI#վQrH<G8#=Z>#*.n/kd#@MvuR]2}NQv ? |n2p9q 袊B8O^wq/'ZJ^wq/'ZJ;C`* ( (]r[)j:m$k>>MX0( #GB?JکizMla$)f,dJx'EuE#KB^p{Rw?cƟ +{~0i> ֻjBXE;-)!mq'yN}B@SRm4][#W- OA3Rַ{if)G9Fg<C]V<|J׸l<+?Vf6ڕ٦dbї ~ou.WDAݎI A~yxU^^W=v8?$  Y_ !пJ$3(@((((((((/n}xzMEԭD|""w ='Iۀ 5Q@KDVg-ᕸxuGgdNs:t.$;$a(f$)//3goEqнrR_?^ۏ9G {3R_?^ۏ9G)//=\G)//vQ#vQ K ;q(fvW K ;q(%r;z+%’yBN9ٝ’yBN?I|<{'n?ފ?I|<{'n?нr@goEqнrR_?^ۏ9G {3R_?^ۏ9G)//=\G)//vQ̡aEߊzv,a.QdT1FsU VoO6zevvZZǝ$ OV*iYX(c ?sjU|*/+Ȓ@cwsoWNH$麿ǿM]xN̄f5 W<dߌ[RԚK9LFrJ8$cb*C2;k;tIG$O$NIJҬt=.L-MD2I$I$䚹@_jx'Ǻφuu)u=.XPp'nPޏPk:95{/m['dɝ7)ꭂpg\)//qw;z+%’yBN\goEqнrR_?^ۏ9G {3R_?^ۏ9G)//=\G)//| &rBtvN ֎@g^S߅|]sJ]z¯c a:R_?^ۏ9G {3R_?^ۏ9G)//=_4>>2x_@Ӵ'L' m,Xe@^ K ;q(fvW K ;q(%r;z+%’yBN9ٝ’yBN?I|<{'n?ފ?I|<{'n?нr@f|cc1&9._ɱn8T ddu$^GlCy#'\3ޏ|:o 揢A3+9%r*Q(PQEQEQEQEQEQEQEQEQEQ^ykJkm? Xķ6p81KT+TaxW!iKV+axW!ho&\.zemD+4oC.!+axW!ho&\]CWoC MG,s(3o&\r&YviQ^g MG,/6?MLr&X^6m9e=;Ey,/6?MmD+4r˰{Hw=2?X^6m?axW!h`zemD+4oC.!+axW!iQլj $v>vu})rshzGtԴ[ ޠVC+T8 pAEjR(*z]Ƨmgn(d4jjzvvY_I8I _8jZ=t5d퓇̃+ 6L427}3zt۝OzVcvfml$NI'I'$? xcKA[3r{ؠ(((((P̞L⚺֛pMc-e\d6z.fc4+4Op-L,?{J}6 F{ku&I#YWEbh*|Aumyl$0՞x{-gKԤx5+;AX'W*=\YZ[kE=n,͐v2SEKk^UgdOZR0`qRr쌦%wwGn;sn [O{hXFfRI&;MJϱivhĞL ǡmCqۢXU_@asicʤkæԶ}NO3ݜn31ַ.K"Q`yA|{Vww+X Waj. VaFY[Z̰D}HNh]/VEic.mf%$`6H, *=".tigKڊW*Px#847IVdAy,t;L 4>?<+rZ((((<\\Ioݙ$Q1]['ow2~|Fp5CIzsTCh!($ qUE81RQEAQEQEQEQEQEQEW?'%Uj+*E5y$P** IaY?TUQE?8_ۏ}_?SW[QEQEQEQEQEQEQEQEQEQEQEQEQEQEWB?%++!LqQ>mQEyEPEPX^+.t6l\%vvT0Fcڡ+vO)ze=Hf_ΓqvV#t]%C,-NsoMrj?]^%Pt㒼UFöKqJAj:lPB#I$Y$K[_}lsymu:/#g}=zUM>-TֵM>_El,)V;$݆v;XM͢OE|anΑUA\nzc4_藷l$dr6 ~D#yknD̑I=]H ,jcլtr0?)1r#RScK. J%*<7\g u|Hž#22~WUMAESQEQE_^?Wד_^?W5O?(5 ( ( ( ( ( ( w$Ŀ M]s;y_]覠?jEE^^?8' qҷ+p +z ( ( ( ( ( ( ( ( ( ( ( ( ( ( OWr--3pGB!n.:PGtȵ(},d}  fvwDtW-Al<}&71\̱K ) F{/ ZGWUicj?1iG%HwATV/%H?/ ZGQtUm+"̻]FGr>/ ZGQ b?6?*fʨU 31e-'K{0~`SW#?f_  ŤlUA"vB ss?/ݣ__++_~ϧOhЯ0>?/ݣ__++_~ϧOhЯ0>?/ݣ__++_~ϧOhY[SDoT]Z$${'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧE 4?C'T]GWWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEQ\WWڿ?N/??ӧEW?'%Uj?EB¾tȿvY7 !~k'.&bI\52;?O5 `f6zc{n>ؑ"8#+3^/??ӧEQ\WWڿ?N/??ӧE|n?V|NQ_/9ϻ];׷k}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEk}?~tW?/??ӧEbQn5ho4ZɧlI<@k}e2w(b((((((((((((((((((((((((-Ʃp!nAf%zzz_yZčrtVmnmR+y,QSO5mc6᫽2E̫HR@XsruQEQEQEQEQEQEQEIu w$Ŀ M@8aNc _[xoPVW hmELb;,`|ziEQEQEQEQEQEQEQEIu w$Ŀ M@8@'xóI=6$Zh|&28$ ?|Es<K Z;E1?zz(tIk= I]?P.nD{f@6H~:n4Er[bei.c!>OgQ^+ _ɩ?Ux+57G!ه+Ux+57G*&;0>Ex*&U]\f__3ڨU]@_?{Ua {xyt˔8Գ;xy*&U]\f__2$P** _U^ /MMԑ:Ҭ3k:ٚ2q.:f{5V Ai~-}OQ<.V?0*될@ ~.NKӮ>OgQ^+ _ɩ?Ux+57G!ه+Ux+57G*&;0>Ex*&U]\f__3ڨU]@_?{U@_W St}r}~g|jWW StªWjo.CTWªWjo.U^ /MMva}=_U^ /MM _ɩ>>OgQ^3í*?Zo]Iql'>,9<~`Atzn})ׅGdmK sh((((((((((((+>'nQ}L if_$rzm%xL^^cJW?#R~u]3Z((((((((((((V1j| 5RE2>ٮJO]i?>5د/ՅQYQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@swWq'+o⣧ et=r(T((((((((((((/GDzuy_)^J ^֢+<(((;m`y&cI*$)2Aw{ǟ!ʣ5˭j4:UI)g;j/(^1_Ywz~/Crisbu]u,x 9*煿`_D ^{EQYQ@Q@Q@ox'߿HʸJO]i=Y1XQEQETMsnIl.KEQԁԁϽK\O$&dP=̖ rvF7!,@9#U;;Gl-1B@bWSmjnmx(w8ܪz:p*o5O}0G'8 ӎ&ź kjNa8I<Q\$>* xNvj2ۢ)ubszչ5^iZ$v( \x7*(R;rICI5K[-5 5 xm絿ˈLu'aޱeņ]CTAuF…z-uKۋ--)is*.y&L 4XPwO18.\iڦu3}tDB~lkf%S"J.f'&>k^]o.m$NH#VՂ( ((W?)^ +'}?Vk?> (2 ( uW>s!&v$,W'=騪wEFN.|'Z'-io&\n#q$·u&}OWL/=Y 䁜~Ucm%ԧӒ\${Oʭ8iױ}j:Ƒ-stXG,y0 6{so^[xMsPA2 X @HnB@$⻪l,JC4Foj;&yRa"%l-׊C>#uy7v1F;)|OViDi0G2[B}TsW}S9+ ? mcf)Ryqǥ7Pyss jjVqHd+ⴟVs4jUv'$8*|-=턺θ `[,Y +#=+%Jקlk_Z6vWB+.7nQN~Q>-BTO"ɳeb\ԺV}o~ѷf/Urss:CM)>f͹2zn^i<֞_QYQ@ox'߿HʸJO]i=Y1XQEW#-ε&T6vY6c@XpXrAfe˧F+ q%FRϐH ~5-;k~I ֛v-V D}7qyj".q\[{Թ.vr^˦9%(Í[վ6梖(P(O#9#r.hW:e֭~(ddk+}s+irgY>+^jmui0:=O/!A1,[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[tW7NoG!:ݽV>[b77\\Av18+JP/쵋^}Uբ39!8tHr;2eQtZooBi 2E+QPKvxBNwdHrNIxirna']Z:j+_?'_[nޱ^T:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:J+_?'_[nޏUT:JxOG!:ݽt~=xW  F Fs﹛z'HaB4core-4.6/doc/figures/Makefile.am0000664000175000017500000000273412022167657013521 00000000000000# CORE # (c)2009-2012 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # # define new file extensions for handling figures and html SUFFIXES = .jpg .gif GIFTOJPG = convert -background white -flatten # dia figures can be manually converted to jpg # On Ubuntu 11.10, this is failing for some reason. DIATOJPG = dia -t jpg -e # these are file extension handlers for automatically converting between image # file types; the .jpg files are built from .gif files from the GUI # file extension handler to convert .gif to .jpg %.jpg: %.gif $(GIFTOJPG) $(top_srcdir)/gui/icons/tiny/$< $@ # file extension handler so we can list .gif as dependency for .gif.jpg %.gif: @echo "Using GUI file $(top_srcdir)/gui/icons/tiny/$@" # list of base names for figures figures = core-architecture core-workflow # list of figures + dia suffix figures_dia = $(figures:%=%.dia) # list of figure + jpg suffix figures_jpg = $(figures:%=%.jpg) # icons from the GUI source icons = select start router host pc mdr router_green \ lanswitch hub wlan \ link rj45 tunnel marker oval rectangle text \ stop observe plot twonode run document-properties # list of icons + .gif.jpg suffix icons_jpg = $(icons:%=%.jpg) BUILT_SOURCES = $(figures_dia) $(figures_jpg) $(icons_jpg) clean-local: rm -f $(icons_jpg) EXTRA_DIST = $(figures_dia) $(figures_jpg) # extra cruft to remove DISTCLEANFILES = Makefile.in $(icons_jpg) core-4.6/doc/figures/Makefile.in0000664000175000017500000002706212220631420013513 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@ # CORE # (c)2009-2012 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # 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 = : subdir = doc/figures DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac 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 = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ ARCH = @ARCH@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COREDPY_VERSION = @COREDPY_VERSION@ CORE_CONF_DIR = @CORE_CONF_DIR@ CORE_DATA_DIR = @CORE_DATA_DIR@ CORE_GUI_CONF_DIR = @CORE_GUI_CONF_DIR@ CORE_LIB_DIR = @CORE_LIB_DIR@ CORE_STATE_DIR = @CORE_STATE_DIR@ CORE_VERSION = @CORE_VERSION@ CORE_VERSION_DATE = @CORE_VERSION_DATE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ HELP2MAN = @HELP2MAN@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIB_DIR = @LIB_DIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SBINDIR = @SBINDIR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ brctl_path = @brctl_path@ build_alias = @build_alias@ builddir = @builddir@ convert = @convert@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ ebtables_path = @ebtables_path@ enable_daemon = @enable_daemon@ enable_gui = @enable_gui@ exec_prefix = @exec_prefix@ gmake = @gmake@ help2man = @help2man@ host_alias = @host_alias@ htmldir = @htmldir@ ifconfig_path = @ifconfig_path@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ip_path = @ip_path@ libdir = @libdir@ libev_CFLAGS = @libev_CFLAGS@ libev_LIBS = @libev_LIBS@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mount_path = @mount_path@ ngctl_path = @ngctl_path@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ sysctl_path = @sysctl_path@ target_alias = @target_alias@ tc_path = @tc_path@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ umount_path = @umount_path@ vimage_path = @vimage_path@ with_startup = @with_startup@ # define new file extensions for handling figures and html SUFFIXES = .jpg .gif GIFTOJPG = convert -background white -flatten # dia figures can be manually converted to jpg # On Ubuntu 11.10, this is failing for some reason. DIATOJPG = dia -t jpg -e # list of base names for figures figures = core-architecture core-workflow # list of figures + dia suffix figures_dia = $(figures:%=%.dia) # list of figure + jpg suffix figures_jpg = $(figures:%=%.jpg) # icons from the GUI source icons = select start router host pc mdr router_green \ lanswitch hub wlan \ link rj45 tunnel marker oval rectangle text \ stop observe plot twonode run document-properties # list of icons + .gif.jpg suffix icons_jpg = $(icons:%=%.jpg) BUILT_SOURCES = $(figures_dia) $(figures_jpg) $(icons_jpg) EXTRA_DIST = $(figures_dia) $(figures_jpg) # extra cruft to remove DISTCLEANFILES = Makefile.in $(icons_jpg) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .jpg .gif $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --foreign doc/figures/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/figures/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): tags: TAGS TAGS: ctags: CTAGS CTAGS: 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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic 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-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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-local \ distclean distclean-generic 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am # these are file extension handlers for automatically converting between image # file types; the .jpg files are built from .gif files from the GUI # file extension handler to convert .gif to .jpg %.jpg: %.gif $(GIFTOJPG) $(top_srcdir)/gui/icons/tiny/$< $@ # file extension handler so we can list .gif as dependency for .gif.jpg %.gif: @echo "Using GUI file $(top_srcdir)/gui/icons/tiny/$@" clean-local: rm -f $(icons_jpg) # 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: core-4.6/doc/man/0000775000175000017500000000000012220631512010630 500000000000000core-4.6/doc/man/vnoded.10000664000175000017500000000223412205716053012121 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH VNODED "1" "August 2013" "CORE" "User Commands" .SH NAME vnoded \- network namespace daemon used by CORE to create a lightweight container .SH SYNOPSIS .B vnoded [\fI-h|-V\fR] [\fI-v\fR] [\fI-n\fR] [\fI-C \fR] [\fI-l \fR] [\fI-p \fR] \fI-c \fR .SH DESCRIPTION Linux namespace container server daemon runs as PID 1 in the container. Normally this process is launched automatically by the CORE daemon. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-V\fR, \fB\-\-version\fR show version number and exit .TP \fB\-v\fR enable verbose logging .TP \fB\-n\fR do not create and run daemon within a new network namespace (for debug) .TP \fB\-C\fR change to the specified directory .TP \fB\-l\fR log output to the specified file .TP \fB\-p\fR write process id to the specified file .TP \fB\-c\fR establish the specified for receiving control commands .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), .BR vcmd(1), .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/coresendmsg.10000664000175000017500000000450412205716053013155 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH CORESENDMSG "1" "August 2013" "CORE" "User Commands" .SH NAME coresendmsg \- send a CORE API message to the core-daemon daemon .SH SYNOPSIS .B coresendmsg [\fI-h|-H\fR] [\fIoptions\fR] [\fImessage-type\fR] [\fIflags=flags\fR] [\fImessage-TLVs\fR] .SH DESCRIPTION .SS "Supported message types:" .IP ['node', 'link', 'exec', 'reg', 'conf', 'file', 'iface', 'event', 'sess', 'excp'] .SS "Supported message flags (flags=f1,f2,...):" .IP ['add', 'del', 'cri', 'loc', 'str', 'txt', 'tty'] .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-H\fR show example usage help message and exit .TP \fB\-p\fR PORT, \fB\-\-port\fR=\fIPORT\fR TCP port to connect to, default: 4038 .TP \fB\-a\fR ADDRESS, \fB\-\-address\fR=\fIADDRESS\fR Address to connect to, default: localhost .TP \fB\-s\fR SESSION, \fB\-\-session\fR=\fISESSION\fR Session to join, default: None .TP \fB\-l\fR, \fB\-\-listen\fR Listen for a response message and print it. .TP \fB\-t\fR, \fB\-\-list\-tlvs\fR List TLVs for the specified message type. .TP \fB\-T\fR, \fB\-\-tcp\fR Use TCP instead of UDP and connect to a session, default: False .PP Usage: coresendmsg [\-h|\-H] [options] [message\-type] [flags=flags] [message\-TLVs] .SS "Supported message types:" .IP ['node', 'link', 'exec', 'reg', 'conf', 'file', 'iface', 'event', 'sess', 'excp'] .SS "Supported message flags (flags=f1,f2,...):" .IP ['add', 'del', 'cri', 'loc', 'str', 'txt', 'tty'] .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-H\fR show example usage help message and exit .TP \fB\-p\fR PORT, \fB\-\-port\fR=\fIPORT\fR TCP port to connect to, default: 4038 .TP \fB\-a\fR ADDRESS, \fB\-\-address\fR=\fIADDRESS\fR Address to connect to, default: localhost .TP \fB\-s\fR SESSION, \fB\-\-session\fR=\fISESSION\fR Session to join, default: None .TP \fB\-l\fR, \fB\-\-listen\fR Listen for a response message and print it. .TP \fB\-t\fR, \fB\-\-list\-tlvs\fR List TLVs for the specified message type. .TP \fB\-T\fR, \fB\-\-tcp\fR Use TCP instead of UDP and connect to a session, default: False .SH "EXAMPLES" .TP A list of examples is available using the following command: coresendmsg \-H .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/netns.10000664000175000017500000000131212205716053011765 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH NETNS "1" "August 2013" "CORE" "User Commands" .SH NAME netns \- run commands within a network namespace .SH SYNOPSIS .B netns [\fI-h|-V\fR] [\fI-w\fR] \fI-- command \fR[\fIargs\fR...] .SH DESCRIPTION Run the specified command in a new network namespace. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-V\fR, \fB\-\-version\fR show version number and exit .TP \fB\-w\fR wait for command to complete (useful for interactive commands) .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), .BR unshare(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/core-daemon.10000664000175000017500000000264112205716053013035 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH CORE "1" "August 2013" "CORE" "User Commands" .SH NAME core-daemon \- CORE daemon manages emulation sessions started from GUI or scripts .SH SYNOPSIS .B core-daemon [\fI-h\fR] [\fIoptions\fR] [\fIargs\fR] .SH DESCRIPTION CORE daemon instantiates Linux network namespace nodes. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-f\fR CONFIGFILE, \fB\-\-configfile\fR=\fICONFIGFILE\fR read config from specified file; default = /etc/core/core.conf .TP \fB\-d\fR, \fB\-\-daemonize\fR run in background as daemon; default=False .TP \fB\-e\fR EXECFILE, \fB\-\-execute\fR=\fIEXECFILE\fR execute a Python/XML\-based session .TP \fB\-l\fR LOGFILE, \fB\-\-logfile\fR=\fILOGFILE\fR log output to specified file; default = /var/log/core-daemon.log .TP \fB\-p\fR PORT, \fB\-\-port\fR=\fIPORT\fR port number to listen on; default = 4038 .TP \fB\-i\fR PIDFILE, \fB\-\-pidfile\fR=\fIPIDFILE\fR filename to write pid to; default = /var/run/core-daemon.pid .TP \fB\-t\fR NUMTHREADS, \fB\-\-numthreads\fR=\fINUMTHREADS\fR number of server threads; default = 1 .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose logging; default = False .TP \fB\-g\fR, \fB\-\-debug\fR enable debug logging; default = False .SH "SEE ALSO" .BR core-gui(1), .BR coresendmsg(1), .BR netns(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/vcmd.10000664000175000017500000000200212205716053011564 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH VCMD "1" "August 2013" "CORE" "User Commands" .SH NAME vcmd \- run a command in a network namespace created by vnoded .SH SYNOPSIS .B vcmd [\fI-h|-V\fR] [\fI-v\fR] [\fI-q|-i|-I\fR] \fI-c -- command args\fR... .SH DESCRIPTION Run the specified command in the Linux namespace container specified by the control , with the specified arguments. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-V\fR, \fB\-\-version\fR show version number and exit .TP \fB\-v\fR enable verbose logging .TP \fB\-q\fR run the command quietly, without local input or output .TP \fB\-i\fR run the command interactively (use PTY) .TP \fB\-I\fR run the command non\-interactively (without PTY) .TP \fB\-c\fR control channel name (e.g. '/tmp/pycore.45647/n3') .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), .BR netns(1), .BR vnoded(1), .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/core-xen-cleanup.10000664000175000017500000000132112205716053014003 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH CORE-XEN-CLEANUP "1" "August 2013" "CORE" "User Commands" .SH NAME core-xen-cleanup \- clean-up script for CORE Xen domUs .SH DESCRIPTION usage: core\-xen\-cleanup [\-d] .IP Clean up all CORE Xen domUs, bridges, interfaces, and session directories. Options: .TP \fB\-h\fR show this help message and exit .TP \fB\-d\fR also kill the Python daemon .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), .BR core-cleanup(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Warning! This script will remove logical volumes that match the name "/dev/vg*/c*-n*-" on all volume groups. Use with care. Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/core-gui.10000664000175000017500000000170512205716053012356 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH CORE "1" "August 2013" "CORE" "User Commands" .SH NAME core-gui \- Common Open Research Emulator (CORE) graphical user interface .SH SYNOPSIS .B core-gui [\fI-h|-v\fR] [\fI-b|-c \fR] [\fI-s\fR] [\fI\fR] .SH DESCRIPTION Launches the CORE Tcl/Tk X11 GUI or starts an imn\-based emulation. .TP \-(\fB\-h\fR)elp show help message and exit .TP \-(\fB\-v\fR)ersion show version number and exit .TP \-(\fB\-b\fR)atch batch mode (no X11 GUI) .TP \-(\fB\-c\fR)losebatch stop and clean up a batch mode session .TP \-(\fB\-s\fR)tart start in execute mode, not edit mode .TP (optional) load the specified imn scenario file .PP With no parameters, starts the GUI in edit mode with a blank canvas. .SH "SEE ALSO" .BR core-daemon(1), .BR coresendmsg(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/Makefile.am0000775000175000017500000000265412205716053012625 00000000000000# CORE # (c)2012-2013 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # Makefile for building man pages. # if WANT_GUI GUI_MANS = core-gui.1 endif if WANT_DAEMON DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 coresendmsg.1 \ core-cleanup.1 core-xen-cleanup.1 endif man_MANS = $(GUI_MANS) $(DAEMON_MANS) .PHONY: generate-mans generate-mans: $(HELP2MAN) --source CORE 'sh $(top_srcdir)/gui/core-gui' -o core-gui.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vnoded -o vnoded.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vcmd -o vcmd.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/netns -o netns.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-xen-cleanup -o core-xen-cleanup.1.new .PHONY: diff diff: for m in ${man_MANS}; do \ colordiff -u $$m $$m.new | less -R; \ done; DISTCLEANFILES = Makefile.in EXTRA_DIST = $(man_MANS) core-4.6/doc/man/core-cleanup.10000664000175000017500000000120212205716053013211 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. .TH CORE-CLEANUP "1" "August 2013" "CORE" "User Commands" .SH NAME core-cleanup \- clean-up script for CORE .SH DESCRIPTION usage: core\-cleanup [\-d [\-l]] .IP Clean up all CORE namespaces processes, bridges, interfaces, and session directories. Options: .TP \fB\-h\fR show this help message and exit .TP \fB\-d\fR also kill the Python daemon .TP \fB\-l\fR remove the core-daemon.log file .SH "SEE ALSO" .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), .BR core-xen-cleanup(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS Report bugs to .BI core-dev@pf.itd.nrl.navy.mil. core-4.6/doc/man/Makefile.in0000664000175000017500000003557712220631420012634 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@ # CORE # (c)2012-2013 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # Makefile for building man pages. # 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 = : subdir = doc/man DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac 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 = SOURCES = DIST_SOURCES = 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__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" NROFF = nroff MANS = $(man_MANS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ ARCH = @ARCH@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COREDPY_VERSION = @COREDPY_VERSION@ CORE_CONF_DIR = @CORE_CONF_DIR@ CORE_DATA_DIR = @CORE_DATA_DIR@ CORE_GUI_CONF_DIR = @CORE_GUI_CONF_DIR@ CORE_LIB_DIR = @CORE_LIB_DIR@ CORE_STATE_DIR = @CORE_STATE_DIR@ CORE_VERSION = @CORE_VERSION@ CORE_VERSION_DATE = @CORE_VERSION_DATE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ HELP2MAN = @HELP2MAN@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIB_DIR = @LIB_DIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SBINDIR = @SBINDIR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ brctl_path = @brctl_path@ build_alias = @build_alias@ builddir = @builddir@ convert = @convert@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ ebtables_path = @ebtables_path@ enable_daemon = @enable_daemon@ enable_gui = @enable_gui@ exec_prefix = @exec_prefix@ gmake = @gmake@ help2man = @help2man@ host_alias = @host_alias@ htmldir = @htmldir@ ifconfig_path = @ifconfig_path@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ip_path = @ip_path@ libdir = @libdir@ libev_CFLAGS = @libev_CFLAGS@ libev_LIBS = @libev_LIBS@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mount_path = @mount_path@ ngctl_path = @ngctl_path@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ sysctl_path = @sysctl_path@ target_alias = @target_alias@ tc_path = @tc_path@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ umount_path = @umount_path@ vimage_path = @vimage_path@ with_startup = @with_startup@ @WANT_GUI_TRUE@GUI_MANS = core-gui.1 @WANT_DAEMON_TRUE@DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 coresendmsg.1 \ @WANT_DAEMON_TRUE@ core-cleanup.1 core-xen-cleanup.1 man_MANS = $(GUI_MANS) $(DAEMON_MANS) DISTCLEANFILES = Makefile.in EXTRA_DIST = $(man_MANS) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --foreign doc/man/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/man/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-man1: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" @list=''; test -n "$(man1dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 $(MANS) installdirs: for dir in "$(DESTDIR)$(man1dir)"; 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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 mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic 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-man1 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am uninstall-man uninstall-man1 .PHONY: generate-mans generate-mans: $(HELP2MAN) --source CORE 'sh $(top_srcdir)/gui/core-gui' -o core-gui.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vnoded -o vnoded.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vcmd -o vcmd.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/netns -o netns.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-xen-cleanup -o core-xen-cleanup.1.new .PHONY: diff diff: for m in ${man_MANS}; do \ colordiff -u $$m $$m.new | less -R; \ done; # 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: core-4.6/doc/devguide.rst0000664000175000017500000002612112205477411012336 00000000000000.. This file is part of the CORE Manual (c)2012-2013 the Boeing Company .. _Developer's_Guide: ***************** Developer's Guide ***************** This section contains advanced usage information, intended for developers and others who are comfortable with the command line. .. _Coding_Standard: Coding Standard =============== The coding standard and style guide for the CORE project are maintained online. Please refer to the `coding standard `_ posted on the CORE Wiki. .. _Source_Code_Guide: Source Code Guide ================= The CORE source consists of several different programming languages for historical reasons. Current development focuses on the Python modules and daemon. Here is a brief description of the source directories. These are being actively developed as of CORE |version|: * *gui* - Tcl/Tk GUI. This uses Tcl/Tk because of its roots with the IMUNES project. * *daemon* - Python modules are found in the :file:`daemon/core` directory, the daemon under :file:`daemon/sbin/core-daemon`, and Python extension modules for Linux Network Namespace support are in :file:`daemon/src`. * *doc* - Documentation for the manual lives here in reStructuredText format. * *packaging* - Control files and script for building CORE packages are here. These directories are not so actively developed: * *kernel* - patches and modules mostly related to FreeBSD. .. _The_CORE_API: The CORE API ============ .. index:: CORE; API .. index:: API .. index:: remote API The CORE API is used between different components of CORE for communication. The GUI communicates with the CORE daemon using the API. One emulation server communicates with another using the API. The API also allows other systems to interact with the CORE emulation. The API allows another system to add, remove, or modify nodes and links, and enables executing commands on the emulated systems. On FreeBSD, the API is used for enhancing the wireless LAN calculations. Wireless link parameters are updated on-the-fly based on node positions. CORE listens on a local TCP port for API messages. The other system could be software running locally or another machine accessible across the network. The CORE API is currently specified in a separate document, available from the CORE website. .. _Linux_network_namespace_Commands: Linux network namespace Commands ================================ .. index:: lxctools Linux network namespace containers are often managed using the *Linux Container Tools* or *lxc-tools* package. The lxc-tools website is available here ``_ for more information. CORE does not use these management utilities, but includes its own set of tools for instantiating and configuring network namespace containers. This section describes these tools. .. index:: vnoded The *vnoded* daemon is the program used to create a new namespace, and listen on a control channel for commands that may instantiate other processes. This daemon runs as PID 1 in the container. It is launched automatically by the CORE daemon. The control channel is a UNIX domain socket usually named :file:`/tmp/pycore.23098/n3`, for node 3 running on CORE session 23098, for example. Root privileges are required for creating a new namespace. .. index:: vcmd The *vcmd* program is used to connect to the *vnoded* daemon in a Linux network namespace, for running commands in the namespace. The CORE daemon uses the same channel for setting up a node and running processes within it. This program has two required arguments, the control channel name, and the command line to be run within the namespace. This command does not need to run with root privileges. When you double-click on a node in a running emulation, CORE will open a shell window for that node using a command such as: :: gnome-terminal -e vcmd -c /tmp/pycore.50160/n1 -- bash Similarly, the IPv4 routes Observer Widget will run a command to display the routing table using a command such as: :: vcmd -c /tmp/pycore.50160/n1 -- /sbin/ip -4 ro .. index:: core-cleanup A script named *core-cleanup* is provided to clean up any running CORE emulations. It will attempt to kill any remaining vnoded processes, kill any EMANE processes, remove the :file:`/tmp/pycore.*` session directories, and remove any bridges or *ebtables* rules. With a *-d* option, it will also kill any running CORE daemon. .. index:: netns The *netns* command is not used by CORE directly. This utility can be used to run a command in a new network namespace for testing purposes. It does not open a control channel for receiving further commands. Here are some other Linux commands that are useful for managing the Linux network namespace emulation. :: # view the Linux bridging setup brctl show # view the netem rules used for applying link effects tc qdisc show # view the rules that make the wireless LAN work ebtables -L Below is a transcript of creating two emulated nodes and connecting them together with a wired link: .. index:: create nodes from command-line .. index:: command-line :: # create node 1 namespace container vnoded -c /tmp/n1.ctl -l /tmp/n1.log -p /tmp/n1.pid # create a virtual Ethernet (veth) pair, installing one end into node 1 ip link add name n1.0.1 type veth peer name n1.0 ip link set n1.0 netns `cat /tmp/n1.pid` vcmd -c /tmp/n1.ctl -- ip link set n1.0 name eth0 vcmd -c /tmp/n1.ctl -- ifconfig eth0 10.0.0.1/24 # create node 2 namespace container vnoded -c /tmp/n2.ctl -l /tmp/n2.log -p /tmp/n2.pid # create a virtual Ethernet (veth) pair, installing one end into node 2 ip link add name n2.0.1 type veth peer name n2.0 ip link set n2.0 netns `cat /tmp/n2.pid` vcmd -c /tmp/n2.ctl -- ip link set n2.0 name eth0 vcmd -c /tmp/n2.ctl -- ifconfig eth0 10.0.0.2/24 # bridge together nodes 1 and 2 using the other end of each veth pair brctl addbr b.1.1 brctl setfd b.1.1 0 brctl addif b.1.1 n1.0.1 brctl addif b.1.1 n2.0.1 ip link set n1.0.1 up ip link set n2.0.1 up ip link set b.1.1 up # display connectivity and ping from node 1 to node 2 brctl show vcmd -c /tmp/n1.ctl -- ping 10.0.0.2 The above example script can be found as :file:`twonodes.sh` in the :file:`examples/netns` directory. Use *core-cleanup* to clean up after the script. .. _FreeBSD_Commands: FreeBSD Commands ================ .. index:: vimage .. index:: ngctl .. index:: Netgraph .. _FreeBSD_Kernel_Commands: FreeBSD Kernel Commands ----------------------- The FreeBSD kernel emulation controlled by CORE is realized through several userspace commands. The CORE GUI itself could be thought of as a glorified script that dispatches these commands to build and manage the kernel emulation. * **vimage** - the vimage command, short for "virtual image", is used to create lightweight virtual machines and execute commands within the virtual image context. On a FreeBSD CORE machine, see the *vimage(8)* man page for complete details. The vimage command comes from the VirtNet project which virtualizes the FreeBSD network stack. * **ngctl** - the ngctl command, short for "netgraph control", creates Netgraph nodes and hooks, connects them together, and allows for various interactions with the Netgraph nodes. See the *ngctl(8)* man page for complete details. The ngctl command is built-in to FreeBSD because the Netgraph system is part of the kernel. Both commands must be run as root. Some example usage of the *vimage* command follows below. :: vimage # displays the current virtual image vimage -l # lists running virtual images vimage e0_n0 ps aux # list the processes running on node 0 for i in 1 2 3 4 5 do # execute a command on all nodes vimage e0_n$i sysctl -w net.inet.ip.redirect=0 done The *ngctl* command is more complex, due to the variety of Netgraph nodes available and each of their options. :: ngctl l # list active Netgraph nodes ngctl show e0_n8: # display node hook information ngctl msg e0_n0-n1: getstats # get pkt count statistics from a pipe node ngctl shutdown \\[0x0da3\\]: # shut down unnamed node using hex node ID There are many other combinations of commands not shown here. See the online manual (man) pages for complete details. Below is a transcript of creating two emulated nodes, `router0` and `router1`, and connecting them together with a link: .. index:: create nodes from command-line .. index:: command-line :: # create node 0 vimage -c e0_n0 vimage e0_n0 hostname router0 ngctl mkpeer eiface ether ether vimage -i e0_n0 ngeth0 eth0 vimage e0_n0 ifconfig eth0 link 40:00:aa:aa:00:00 vimage e0_n0 ifconfig lo0 inet localhost vimage e0_n0 sysctl net.inet.ip.forwarding=1 vimage e0_n0 sysctl net.inet6.ip6.forwarding=1 vimage e0_n0 ifconfig eth0 mtu 1500 # create node 1 vimage -c e0_n1 vimage e0_n1 hostname router1 ngctl mkpeer eiface ether ether vimage -i e0_n1 ngeth1 eth0 vimage e0_n1 ifconfig eth0 link 40:00:aa:aa:0:1 vimage e0_n1 ifconfig lo0 inet localhost vimage e0_n1 sysctl net.inet.ip.forwarding=1 vimage e0_n1 sysctl net.inet6.ip6.forwarding=1 vimage e0_n1 ifconfig eth0 mtu 1500 # create a link between n0 and n1 ngctl mkpeer eth0@e0_n0: pipe ether upper ngctl name eth0@e0_n0:ether e0_n0-n1 ngctl connect e0_n0-n1: eth0@e0_n1: lower ether ngctl msg e0_n0-n1: setcfg \\ {{ bandwidth=100000000 delay=0 upstream={ BER=0 dupl icate=0 } downstream={ BER=0 duplicate=0 } }} ngctl msg e0_n0-n1: setcfg {{ downstream={ fifo=1 } }} ngctl msg e0_n0-n1: setcfg {{ downstream={ droptail=1 } }} ngctl msg e0_n0-n1: setcfg {{ downstream={ queuelen=50 } }} ngctl msg e0_n0-n1: setcfg {{ upstream={ fifo=1 } }} ngctl msg e0_n0-n1: setcfg {{ upstream={ droptail=1 } }} ngctl msg e0_n0-n1: setcfg {{ upstream={ queuelen=50 } }} Other FreeBSD commands that may be of interest: .. index:: FreeBSD commands * **kldstat**, **kldload**, **kldunload** - list, load, and unload FreeBSD kernel modules * **sysctl** - display and modify various pieces of kernel state * **pkg_info**, **pkg_add**, **pkg_delete** - list, add, or remove FreeBSD software packages. * **vtysh** - start a Quagga CLI for router configuration Netgraph Nodes -------------- .. index:: Netgraph .. index:: Netgraph nodes Each Netgraph node implements a protocol or processes data in some well-defined manner (see the `netgraph(4)` man page). The netgraph source code is located in `/usr/src/sys/netgraph`. There you might discover additional nodes that implement some desired functionality, that have not yet been included in CORE. Using certain kernel commands, you can likely include these types of nodes into your CORE emulation. The following Netgraph nodes are used by CORE: * **ng_bridge** - switch node performs Ethernet bridging * **ng_cisco** - Cisco HDLC serial links * **ng_eiface** - virtual Ethernet interface that is assigned to each virtual machine * **ng_ether** - physical Ethernet devices, used by the RJ45 tool * **ng_hub** - hub node * **ng_pipe** - used for wired Ethernet links, imposes packet delay, bandwidth restrictions, and other link characteristics * **ng_socket** - socket used by *ngctl* utility * **ng_wlan** - wireless LAN node core-4.6/doc/usage.rst0000664000175000017500000020562612210125600011641 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. _Using_the_CORE_GUI: ****************** Using the CORE GUI ****************** .. index:: workflow .. index:: how to use CORE CORE can be used via the GUI or :ref:`Python_Scripting`. A typical emulation workflow is outlined in :ref:`emulation-workflow`. Often the GUI is used to draw nodes and network devices on the canvas. A Python script could also be written, that imports the CORE Python module, to configure and instantiate nodes and networks. This chapter primarily covers usage of the CORE GUI. .. _emulation-workflow: .. figure:: figures/core-workflow.* :alt: Emulation Workflow :align: center Emulation Workflow CORE can be customized to perform any action at each phase depicted in :ref:`emulation-workflow`. See the *Hooks...* entry on the :ref:`Session_Menu` for details about when these session states are reached. .. _Modes_of_Operation: Modes of Operation ================== .. index:: Execute mode .. index:: Edit mode The CORE GUI has two primary modes of operation, **Edit** and **Execute** modes. Running the GUI, by typing ``core-gui`` with no options, starts in Edit mode. Nodes are drawn on a blank canvas using the toolbar on the left and configured from right-click menus or by double-clicking them. The GUI does not need to be run as root. Once editing is complete, pressing the green `Start` button (or choosing `Execute` from the `Session` menu) instantiates the topology within the FreeBSD kernel and enters Execute mode. In execute mode, the user can interact with the running emulated machines by double-clicking or right-clicking on them. The editing toolbar disappears and is replaced by an execute toolbar, which provides tools while running the emulation. Pressing the red `Stop` button (or choosing `Terminate` from the `Session` menu) will destroy the running emulation and return CORE to Edit mode. CORE can be started directly in Execute mode by specifying ``--start`` and a topology file on the command line: :: core-gui --start ~/.core/configs/myfile.imn Once the emulation is running, the GUI can be closed, and a prompt will appear asking if the emulation should be terminated. The emulation may be left running and the GUI can reconnect to an existing session at a later time. .. index:: Batch mode .. index:: batch There is also a **Batch** mode where CORE runs without the GUI and will instantiate a topology from a given file. This is similar to the ``--start`` option, except that the GUI is not used: :: core-gui --batch ~/.core/configs/myfile.imn A session running in batch mode can be accessed using the ``vcmd`` command (or ``vimage`` on FreeBSD), or the GUI can connect to the session. .. index:: closebatch The session number is printed in the terminal when batch mode is started. This session number can later be used to stop the batch mode session: :: core-gui --closebatch 12345 .. NOTE:: If you like to use batch mode, consider writing a CORE :ref:`Python script ` directly. This enables access to the full power of the Python API. The :ref:`File_Menu` has a basic `Export Python Script` option for getting started with a GUI-designed topology. There is also an `Execute Python script` option for later connecting the GUI to such scripts. .. index:: root privileges The GUI can be run as a normal user on Linux. For FreeBSD, the GUI should be run as root in order to start an emulation. .. _Toolbar: Toolbar ======= The toolbar is a row of buttons that runs vertically along the left side of the CORE GUI window. The toolbar changes depending on the mode of operation. .. _Editing_Toolbar: Editing Toolbar --------------- When CORE is in Edit mode (the default), the vertical Editing Toolbar exists on the left side of the CORE window. Below are brief descriptions for each toolbar item, starting from the top. Most of the tools are grouped into related sub-menus, which appear when you click on their group icon. .. |select| image:: figures/select.* .. |start| image:: figures/start.* .. |link| image:: figures/link.* .. |router| image:: figures/router.* .. |host| image:: figures/host.* .. |pc| image:: figures/pc.* .. |mdr| image:: figures/mdr.* .. |router_green| image:: figures/router_green.* .. |document_properties| image:: figures/document-properties.* .. |hub| image:: figures/hub.* .. |lanswitch| image:: figures/lanswitch.* .. |wlan| image:: figures/wlan.* .. |rj45| image:: figures/rj45.* .. |tunnel| image:: figures/tunnel.* .. |marker| image:: figures/marker.* .. |oval| image:: figures/oval.* .. |rectangle| image:: figures/rectangle.* .. |text| image:: figures/text.* .. index:: Selection Tool * |select| *Selection Tool* - default tool for selecting, moving, configuring nodes .. index:: Start button * |start| *Start button* - starts Execute mode, instantiates the emulation .. index:: Link Tool * |link| *Link* - the Link Tool allows network links to be drawn between two nodes by clicking and dragging the mouse .. index:: network-layer virtual nodes .. index:: Router Tool .. index:: Host Tool .. index:: PC Tool .. index:: MDR Tool .. index:: PRouter Tool .. index:: Edit Node Types * |router| *Network-layer virtual nodes* * |router| *Router* - runs Quagga OSPFv2 and OSPFv3 routing to forward packets * |host| *Host* - emulated server machine having a default route, runs SSH server * |pc| *PC* - basic emulated machine having a default route, runs no processes by default * |mdr| *MDR* - runs Quagga OSPFv3 MDR routing for MANET-optimized routing * |router_green| *PRouter* - physical router represents a real testbed machine, :ref:`physical`. * |document_properties| *Edit* - edit node types button invokes the CORE Node Types dialog. New types of nodes may be created having different icons and names. The default services that are started with each node type can be changed here. .. index:: link-layer virtual nodes .. index:: Hub Tool .. index:: Switch Tool .. index:: Wireless Tool .. index:: RJ45 Tool .. index:: Tunnel Tool .. index:: GRE tunnels * |hub| *Link-layer nodes* * |hub| *Hub* - the Ethernet hub forwards incoming packets to every connected node * |lanswitch| *Switch* - the Ethernet switch intelligently forwards incoming packets to attached hosts using an Ethernet address hash table * |wlan| *Wireless LAN* - when routers are connected to this WLAN node, they join a wireless network and an antenna is drawn instead of a connecting line; the WLAN node typically controls connectivity between attached wireless nodes based on the distance between them * |rj45| *RJ45* - with the RJ45 Physical Interface Tool, emulated nodes can be linked to real physical interfaces on the Linux or FreeBSD machine; using this tool, real networks and devices can be physically connected to the live-running emulation (:ref:`RJ45_Tool`) * |tunnel| *Tunnel* - the Tunnel Tool allows connecting together more than one CORE emulation using GRE tunnels (:ref:`Tunnel_Tool`) .. index:: annotation tools .. index:: Marker Tool .. index:: background annotations .. index:: Oval Tool .. index:: Oval Tool .. index:: Rectangle Tool .. index:: Text Tool * *Annotation Tools* * |marker| *Marker* - for drawing marks on the canvas * |oval| *Oval* - for drawing circles on the canvas that appear in the background * |rectangle| *Rectangle* - for drawing rectangles on the canvas that appear in the background * |text| *Text* - for placing text captions on the canvas .. _Execution_Toolbar: Execution Toolbar ----------------- When the Start button is pressed, CORE switches to Execute mode, and the Edit toolbar on the left of the CORE window is replaced with the Execution toolbar. Below are the items on this toolbar, starting from the top. .. |stop| image:: figures/stop.* .. |observe| image:: figures/observe.* .. |plot| image:: figures/plot.* .. |twonode| image:: figures/twonode.* .. |run| image:: figures/run.* .. index:: Selection Tool * |select| *Selection Tool* - in Execute mode, the Selection Tool can be used for moving nodes around the canvas, and double-clicking on a node will open a shell window for that node; right-clicking on a node invokes a pop-up menu of run-time options for that node .. index:: Stop button * |stop| *Stop button* - stops Execute mode, terminates the emulation, returns CORE to edit mode. * |observe| *Observer Widgets Tool* - clicking on this magnifying glass icon invokes a menu for easily selecting an Observer Widget. The icon has a darker gray background when an Observer Widget is active, during which time moving the mouse over a node will pop up an information display for that node (:ref:`Observer_Widgets`). .. index:: Throughput tool * |plot| *Plot Tool* - with this tool enabled, clicking on any link will activate the Throughput Widget and draw a small, scrolling throughput plot on the canvas. The plot shows the real-time kbps traffic for that link. The plots may be dragged around the canvas; right-click on a plot to remove it. .. index:: Marker Tool * |marker| *Marker* - for drawing freehand lines on the canvas, useful during demonstrations; markings are not saved .. index:: Two-node Tool .. index:: traceroute .. index:: ping .. index:: route .. index:: network path .. index:: path * |twonode| *Two-node Tool* - click to choose a starting and ending node, and run a one-time *traceroute* between those nodes or a continuous *ping -R* between nodes. The output is displayed in real time in a results box, while the IP addresses are parsed and the complete network path is highlighted on the CORE display. .. index:: Run Tool .. index:: run command * |run| *Run Tool* - this tool allows easily running a command on all or a subset of all nodes. A list box allows selecting any of the nodes. A text entry box allows entering any command. The command should return immediately, otherwise the display will block awaiting response. The *ping* command, for example, with no parameters, is not a good idea. The result of each command is displayed in a results box. The first occurrence of the special text "NODE" will be replaced with the node name. The command will not be attempted to run on nodes that are not routers, PCs, or hosts, even if they are selected. .. _Menubar: Menubar ======= .. index:: menubar .. index:: menus .. index:: menu The menubar runs along the top of the CORE GUI window and provides access to a variety of features. Some of the menus are detachable, such as the *Widgets* menu, by clicking the dashed line at the top. .. _File_Menu: File Menu --------- .. index:: file menu .. index:: detachable menus The File menu contains options for manipulating the :file:`.imn` :ref:`Configuration_Files`. Generally, these menu items should not be used in Execute mode (:ref:`Modes_of_Operation`.) .. index:: New * *New* - this starts a new file with an empty canvas. .. index:: Open * *Open* - invokes the File Open dialog box for selecting a new :file:`.imn` topology file to open. You can change the default path used for this dialog in the :ref:`Preferences` Dialog. .. index:: Save * *Save* - saves the current topology. If you have not yet specified a file name, the Save As dialog box is invoked. .. index:: Save As XML * *Save As XML* - invokes the Save As dialog box for selecting a new :file:`.xml` scenario file for saving the current configuration. This format includes a Network Plan, Motion Plan, Services Plan, and more within a `Scenario` XML tag, described in :ref:`Configuration_Files`. .. index:: Save As imn * *Save As imn* - invokes the Save As dialog box for selecting a new :file:`.imn` topology file for saving the current configuration. Files are saved in the *IMUNES network configuration* file format described in :ref:`Configuration_Files`. .. index:: Export Python script * *Export Python script* - prints Python snippets to the console, for inclusion in a CORE Python script. .. index:: Execute Python script * *Execute Python script* - invokes a File Open dialog fox for selecting a Python script to run and automatically connect to. The script must create a new CORE Session and add this session to the daemon's list of sessions in order for this to work; see :ref:`Python_Scripting`. .. index:: Open current file in editor * *Open current file in editor* - this opens the current topology file in the ``vim`` text editor. First you need to save the file. Once the file has been edited with a text editor, you will need to reload the file to see your changes. The text editor can be changed from the :ref:`Preferences` Dialog. .. index:: Print .. index:: printing * *Print* - this uses the Tcl/Tk postscript command to print the current canvas to a printer. A dialog is invoked where you can specify a printing command, the default being ``lpr``. The postscript output is piped to the print command. .. index:: Save screenshot * *Save screenshot* - saves the current canvas as a postscript graphic file. .. index:: Recently used files * Recently used files - above the Quit menu command is a list of recently use files, if any have been opened. You can clear this list in the :ref:`Preferences` dialog box. You can specify the number of files to keep in this list from the :ref:`Preferences` dialog. Click on one of the file names listed to open that configuration file. .. index:: Quit * *Quit* - the Quit command should be used to exit the CORE GUI. CORE may prompt for termination if you are currently in Execute mode. Preferences and the recently-used files list are saved. .. _Edit_Menu: Edit Menu --------- .. index:: undo * *Undo* - attempts to undo the last edit in edit mode. .. index:: redo * *Redo* - attempts to redo an edit that has been undone. .. index:: cut .. index:: copy .. index:: paste * *Cut*, *Copy*, *Paste* - used to cut, copy, and paste a selection. When nodes are pasted, their node numbers are automatically incremented, and existing links are preserved with new IP addresses assigned. Services and their customizations are copied to the new node, but care should be taken as node IP addresses have changed with possibly old addresses remaining in any custom service configurations. Annotations may also be copied and pasted. .. index:: select all * *Select All* - selects all items on the canvas. Selected items can be moved as a group. .. index:: select adjacent * *Select Adjacent* - select all nodes that are linked to the already selected node(s). For wireless nodes this simply selects the WLAN node(s) that the wireless node belongs to. You can use this by clicking on a node and pressing CTRL+N to select the adjacent nodes. .. index:: find * *Find...* - invokes the *Find* dialog box. The Find dialog can be used to search for nodes by name or number. Results are listed in a table that includes the node or link location and details such as IP addresses or link parameters. Clicking on a result will focus the canvas on that node or link, switching canvases if necessary. .. index:: clear marker .. index:: marker, erasing * *Clear marker* - clears any annotations drawn with the marker tool. Also clears any markings used to indicate a node's status. * *Preferences...* - invokes the :ref:`Preferences` dialog box. .. _Canvas_Menu: Canvas Menu ----------- .. index:: canvas The canvas menu provides commands for adding, removing, changing, and switching to different editing canvases, :ref:`Multiple_Canvases`. .. index:: canvas, new * *New* - creates a new empty canvas at the right of all existing canvases. .. index:: manage canvases * *Manage...* - invokes the *Manage Canvases* dialog box, where canvases may be renamed and reordered, and you can easily switch to one of the canvases by selecting it. .. index:: canvas, deleting * *Delete* - deletes the current canvas and all items that it contains. .. index:: canvas, resizing .. index:: resizing canvas .. index:: canvas size and scale .. index:: coordinate systems .. index:: latitude and longitude * *Size/scale...* - invokes a Canvas Size and Scale dialog that allows configuring the canvas size, scale, and geographic reference point. The size controls allow changing the width and height of the current canvas, in pixels or meters. The scale allows specifying how many meters are equivalent to 100 pixels. The reference point controls specify the latitude, longitude, and altitude reference point used to convert between geographic and Cartesian coordinate systems. By clicking the *Save as default* option, all new canvases will be created with these properties. The default canvas size can also be changed in the :ref:`Preferences` dialog box. * *Wallpaper...* - used for setting the canvas background image, :ref:`Customizing_your_Topology's_Look`. .. index:: canvas, switching * *Previous*, *Next*, *First*, *Last* - used for switching the active canvas to the first, last, or adjacent canvas. .. _View_Menu: View Menu --------- .. index:: view menu The View menu features items for controlling what is displayed on the drawing canvas. .. index:: show menu .. index:: hide items .. index:: show items .. index:: decluttering the display * *Show* - opens a submenu of items that can be displayed or hidden, such as interface names, addresses, and labels. Use these options to help declutter the display. These options are generally saved in the topology files, so scenarios have a more consistent look when copied from one computer to another. .. index:: show hidden nodes .. index:: hide nodes * *Show hidden nodes* - reveal nodes that have been hidden. Nodes are hidden by selecting one or more nodes, right-clicking one and choosing *hide*. .. index:: locked view * *Locked* - toggles locked view; when the view is locked, nodes cannot be moved around on the canvas with the mouse. This could be useful when sharing the topology with someone and you do not expect them to change things. .. index:: 3D GUI .. index:: SDT3D * *3D GUI...* - launches a 3D GUI by running the command defined under :ref:`Preferences`, *3D GUI command*. This is typically a script that runs the SDT3D display. SDT is the Scripted Display Tool from NRL that is based on NASA's Java-based WorldWind virtual globe software. .. index:: zoom in * *Zoom In* - magnifies the display. You can also zoom in by clicking *zoom 100%* label in the status bar, or by pressing the **+** (plus) key. * *Zoom Out* - reduces the size of the display. You can also zoom out by right-clicking *zoom 100%* label in the status bar or by pressing the **-** (minus) key. .. _Tools_Menu: Tools Menu ---------- .. index:: tools menu The tools menu lists different utility functions. .. index:: autorearrange all .. index:: autorearrange mode * *Autorearrange all* - automatically arranges all nodes on the canvas. Nodes having a greater number of links are moved to the center. This mode can continue to run while placing nodes. To turn off this autorearrange mode, click on a blank area of the canvas with the select tool, or choose this menu option again. .. index:: autorearrange selected * *Autorearrange selected* - automatically arranges the selected nodes on the canvas. .. index:: align to grid * *Align to grid* - moves nodes into a grid formation, starting with the smallest-numbered node in the upper-left corner of the canvas, arranging nodes in vertical columns. .. index:: Traffic Flows .. index:: traffic * *Traffic...* - invokes the CORE Traffic Flows dialog box, which allows configuring, starting, and stopping MGEN traffic flows for the emulation. .. index:: IP Addresses dialog * *IP addresses...* - invokes the IP Addresses dialog box for configuring which IPv4/IPv6 prefixes are used when automatically addressing new interfaces. .. index:: MAC Addresses dialog * *MAC addresses...* - invokes the MAC Addresses dialog box for configuring the starting number used as the lowest byte when generating each interface MAC address. This value should be changed when tunneling between CORE emulations to prevent MAC address conflicts. .. index:: hosts file .. index:: Build hosts File dialog * *Build hosts file...* - invokes the Build hosts File dialog box for generating :file:`/etc/hosts` file entries based on IP addresses used in the emulation. .. index:: renumber nodes * *Renumber nodes...* - invokes the Renumber Nodes dialog box, which allows swapping one node number with another in a few clicks. .. index:: ns2imunes converter .. index:: topology partitioning * *Experimental...* - menu of experimental options, such as a tool to convert ns-2 scripts to IMUNES imn topologies, supporting only basic ns-2 functionality, and a tool for automatically dividing up a topology into partitions. .. index:: topology generator .. index:: topogen .. index:: random .. index:: grid topology .. index:: connected grid topology .. index:: chain .. index:: star .. index:: cycle .. index:: wheel .. index:: cube .. index:: clique .. index:: bipartite * *Topology generator* - opens a submenu of topologies to generate. You can first select the type of node that the topology should consist of, or routers will be chosen by default. Nodes may be randomly placed, aligned in grids, or various other topology patterns. * *Random* - nodes are randomly placed about the canvas, but are not linked together. This can be used in conjunction with a WLAN node (:ref:`Editing_Toolbar`) to quickly create a wireless network. * *Grid* - nodes are placed in horizontal rows starting in the upper-left corner, evenly spaced to the right; nodes are not linked to each other. * *Connected Grid* - nodes are placed in an N x M (width and height) rectangular grid, and each node is linked to the node above, below, left and right of itself. * *Chain* - nodes are linked together one after the other in a chain. * *Star* - one node is placed in the center with N nodes surrounding it in a circular pattern, with each node linked to the center node * *Cycle* - nodes are arranged in a circular pattern with every node connected to its neighbor to form a closed circular path. * *Wheel* - the wheel pattern links nodes in a combination of both Star and Cycle patterns. * *Cube* - generate a cube graph of nodes * *Clique* - creates a clique graph of nodes, where every node is connected to every other node * *Bipartite* - creates a bipartite graph of nodes, having two disjoint sets of vertices. * *Debugger...* - opens the CORE Debugger window for executing arbitrary Tcl/Tk commands. .. _Widgets_Menu: Widgets Menu ------------ .. index:: widget .. index:: widgets *Widgets* are GUI elements that allow interaction with a running emulation. Widgets typically automate the running of commands on emulated nodes to report status information of some type and display this on screen. .. _Periodic_Widgets: Periodic Widgets ^^^^^^^^^^^^^^^^ These Widgets are those available from the main *Widgets* menu. More than one of these Widgets may be run concurrently. An event loop fires once every second that the emulation is running. If one of these Widgets is enabled, its periodic routine will be invoked at this time. Each Widget may have a configuration dialog box which is also accessible from the *Widgets* menu. Here are some standard widgets: .. index:: Adjacency Widget .. index:: router adjacency .. index:: OSPF neighbors * *Adjacency* - displays router adjacency states for Quagga's OSPFv2 and OSPFv3 routing protocols. A line is drawn from each router halfway to the router ID of an adjacent router. The color of the line is based on the OSPF adjacency state such as Two-way or Full. To learn about the different colors, see the *Configure Adjacency...* menu item. The :file:`vtysh` command is used to dump OSPF neighbor information. Only half of the line is drawn because each router may be in a different adjacency state with respect to the other. .. index:: Throughput Widget .. index:: throughput * *Throughput* - displays the kilobits-per-second throughput above each link, using statistics gathered from the ng_pipe Netgraph node that implements each link. If the throughput exceeds a certain threshold, the link will become highlighted. For wireless nodes which broadcast data to all nodes in range, the throughput rate is displayed next to the node and the node will become circled if the threshold is exceeded. *Note: under FreeBSD, the Throughput Widget will display "0.0 kbps" on all links that have no configured link effects, because of the way link statistics are counted; to fix this, add a small delay or a bandwidth limit to each link.* .. _Observer_Widgets: Observer Widgets ^^^^^^^^^^^^^^^^ These Widgets are available from the *Observer Widgets* submenu of the *Widgets* menu, and from the Widgets Tool on the toolbar (:ref:`Execution_Toolbar`). Only one Observer Widget may be used at a time. Mouse over a node while the session is running to pop up an informational display about that node. Available Observer Widgets include IPv4 and IPv6 routing tables, socket information, list of running processes, and OSPFv2/v3 neighbor information. .. index:: editing Observer Widgets Observer Widgets may be edited by the user and rearranged. Choosing *Edit...* from the Observer Widget menu will invoke the Observer Widgets dialog. A list of Observer Widgets is displayed along with up and down arrows for rearranging the list. Controls are available for renaming each widget, for changing the command that is run during mouse over, and for adding and deleting items from the list. Note that specified commands should return immediately to avoid delays in the GUI display. Changes are saved to a :file:`widgets.conf` file in the CORE configuration directory. .. _Session_Menu: Session Menu --------------- The Session Menu has entries for starting, stopping, and managing sessions, in addition to global options such as node types, comments, hooks, servers, and options. .. index:: start .. index:: stop * *Start* or *Stop* - this starts or stops the emulation, performing the same function as the green Start or red Stop button. .. index:: Change sessions .. index:: CORE Sessions Dialog * *Change sessions...* - invokes the CORE Sessions dialog box containing a list of active CORE sessions in the daemon. Basic session information such as name, node count, start time, and a thumbnail are displayed. This dialog allows connecting to different sessions, shutting them down, or starting a new session. .. index:: Edit Node Types * *Node types...* - invokes the CORE Node Types dialog, performing the same function as the Edit button on the Network-Layer Nodes toolbar. .. index:: comments .. index:: CORE Session Comments window * *Comments...* - invokes the CORE Session Comments window where optional text comments may be specified. These comments are saved at the top of the configuration file, and can be useful for describing the topology or how to use the network. .. index:: script .. index:: hooks .. index:: hook scripts .. index:: CORE Session Hooks window .. index:: session state .. index:: states .. index:: hook states * *Hooks...* - invokes the CORE Session Hooks window where scripts may be configured for a particular session state. The top of the window has a list of configured hooks, and buttons on the bottom left allow adding, editing, and removing hook scripts. The new or edit button will open a hook script editing window. A hook script is a shell script invoked on the host (not within a virtual node). The script is started at the session state specified in the drop down: * *definition* - used by the GUI to tell the backend to clear any state. * *configuration* - when the user presses the *Start* button, node, link, and other configuration data is sent to the backend. This state is also reached when the user customizes a service. * *instantiation* - after configuration data has been sent, just before the nodes are created. * *runtime* - all nodes and networks have been built and are running. (This is the same state at which the previously-named *global experiment script* was run.) * *datacollect* - the user has pressed the *Stop* button, but before services have been stopped and nodes have been shut down. This is a good time to collect log files and other data from the nodes. * *shutdown* - all nodes and networks have been shut down and destroyed. * *Reset node positions* - if you have moved nodes around using the mouse or by using a mobility module, choosing this item will reset all nodes to their original position on the canvas. The node locations are remembered when you first press the Start button. * *Emulation servers...* - invokes the CORE emulation servers dialog for configuring :ref:`Distributed_Emulation`. * *Change Sessions...* - invokes the Sessions dialog for switching between different running sessions. This dialog is presented during startup when one or more sessions are already running. * *Options...* - presents per-session options, such as the IPv4 prefix to be used, if any, for a control network (see :ref:`Communicating_with_the_Host_Machine`); the ability to preserve the session directory; and an on/off switch for SDT3D support. .. _Help_Menu: Help Menu --------- * *Online manual (www)*, *CORE website (www)*, *Mailing list (www)* - these options attempt to open a web browser with the link to the specified web resource. * *About* - invokes the About dialog box for viewing version information .. _Connecting_with_Physical_Networks: Connecting with Physical Networks ================================= CORE's emulated networks run in real time, so they can be connected to live physical networks. The RJ45 tool and the Tunnel tool help with connecting to the real world. These tools are available from the *Link-layer nodes* menu. When connecting two or more CORE emulations together, MAC address collisions should be avoided. CORE automatically assigns MAC addresses to interfaces when the emulation is started, starting with ``00:00:00:aa:00:00`` and incrementing the bottom byte. The starting byte should be changed on the second CORE machine using the *MAC addresses...* option from the *Tools* menu. .. _RJ45_Tool: RJ45 Tool --------- .. index:: RJ45 Tool The RJ45 node in CORE represents a physical interface on the real CORE machine. Any real-world network device can be connected to the interface and communicate with the CORE nodes in real time. The main drawback is that one physical interface is required for each connection. When the physical interface is assigned to CORE, it may not be used for anything else. Another consideration is that the computer or network that you are connecting to must be co-located with the CORE machine. To place an RJ45 connection, click on the *Link-layer nodes* toolbar and select the *RJ45 Tool* from the submenu. Click on the canvas near the node you want to connect to. This could be a router, hub, switch, or WLAN, for example. Now click on the *Link Tool* and draw a link between the RJ45 and the other node. The RJ45 node will display "UNASSIGNED". Double-click the RJ45 node to assign a physical interface. A list of available interfaces will be shown, and one may be selected by double-clicking its name in the list, or an interface name may be entered into the text box. .. NOTE:: When you press the Start button to instantiate your topology, the interface assigned to the RJ45 will be connected to the CORE topology. The interface can no longer be used by the system. For example, if there was an IP address assigned to the physical interface before execution, the address will be removed and control given over to CORE. No IP address is needed; the interface is put into promiscuous mode so it will receive all packets and send them into the emulated world. .. index:: VLAN .. index:: VLANning .. index:: VLAN devices Multiple RJ45 nodes can be used within CORE and assigned to the same physical interface if 802.1x VLANs are used. This allows for more RJ45 nodes than physical ports are available, but the (e.g. switching) hardware connected to the physical port must support the VLAN tagging, and the available bandwidth will be shared. You need to create separate VLAN virtual devices on the Linux or FreeBSD host, and then assign these devices to RJ45 nodes inside of CORE. The VLANning is actually performed outside of CORE, so when the CORE emulated node receives a packet, the VLAN tag will already be removed. Here are example commands for creating VLAN devices under Linux: :: ip link add link eth0 name eth0.1 type vlan id 1 ip link add link eth0 name eth0.2 type vlan id 2 ip link add link eth0 name eth0.3 type vlan id 3 .. _Tunnel_Tool: Tunnel Tool ----------- .. index:: Tunnel Tool .. index:: GRE tunnels The tunnel tool builds GRE tunnels between CORE emulations or other hosts. Tunneling can be helpful when the number of physical interfaces is limited or when the peer is located on a different network. Also a physical interface does not need to be dedicated to CORE as with the RJ45 tool. The peer GRE tunnel endpoint may be another CORE machine or a (Linux, FreeBSD, etc.) host that supports GRE tunneling. When placing a Tunnel node, initially the node will display "UNASSIGNED". This text should be replaced with the IP address of the tunnel peer. This is the IP address of the other CORE machine or physical machine, not an IP address of another virtual node. .. NOTE:: Be aware of possible MTU issues with GRE devices. The *gretap* device has an interface MTU of 1,458 bytes; when joined to a Linux bridge, the bridge's MTU becomes 1,458 bytes. The Linux bridge will not perform fragmentation for large packets if other bridge ports have a higher MTU such as 1,500 bytes. The GRE key is used to identify flows with GRE tunneling. This allows multiple GRE tunnels to exist between that same pair of tunnel peers. A unique number should be used when multiple tunnels are used with the same peer. When configuring the peer side of the tunnel, ensure that the matching keys are used. .. index:: gretap .. index:: ip link command Here are example commands for building the other end of a tunnel on a Linux machine. In this example, a router in CORE has the virtual address ``10.0.0.1/24`` and the CORE host machine has the (real) address ``198.51.100.34/24``. The Linux box that will connect with the CORE machine is reachable over the (real) network at ``198.51.100.76/24``. The emulated router is linked with the Tunnel Node. In the Tunnel Node configuration dialog, the address ``198.51.100.76`` is entered, with the key set to ``1``. The gretap interface on the Linux box will be assigned an address from the subnet of the virtual router node, ``10.0.0.2/24``. :: # these commands are run on the tunnel peer sudo ip link add gt0 type gretap remote 198.51.100.34 local 198.51.100.76 key 1 sudo ip addr add 10.0.0.2/24 dev gt0 sudo ip link set dev gt0 up Now the virtual router should be able to ping the Linux machine: :: # from the CORE router node ping 10.0.0.2 And the Linux machine should be able to ping inside the CORE emulation: :: # from the tunnel peer ping 10.0.0.1 To debug this configuration, ``tcpdump`` can be run on the gretap devices, or on the physical interfaces on the CORE or Linux machines. Make sure that a firewall is not blocking the GRE traffic. .. _Communicating_with_the_Host_Machine: Communicating with the Host Machine ----------------------------------- Control Network ^^^^^^^^^^^^^^^ .. index:: controlnet .. index:: control network .. index:: X11 applications .. index:: node access to the host .. index:: host access to a node The host machine that runs the CORE GUI and/or daemon is not necessarily accessible from a node. Running an X11 application on a node, for example, requires some channel of communication for the application to connect with the X server for graphical display. There are several different ways to connect from the node to the host and vice versa. Under the :ref:`Session_Menu`, the *Options...* dialog has an option to set a *control network prefix*. This can be set to a network prefix such as ``172.16.0.0/24``. A bridge will be created on the host machine having the last address in the prefix range (e.g. ``172.16.0.254``), and each node will have an extra ``ctrl0`` control interface configured with an address corresponding to its node number (e.g. ``172.16.0.3`` for ``n3``.) A default value for the control network may also be specified by setting the ``controlnet`` line in the :file:`/etc/core/core.conf` configuration file which new sessions will use by default. For multiple sessions at once, the session option should be used instead of the :file:`core.conf` default. .. NOTE:: If you have a large scenario with more than 253 nodes, use a control network prefix that allows more than the suggested ``/24``, such as ``/23`` or greater. .. index:: X11 forwarding .. index:: SSH X11 forwarding To run an X11 application on the node, the ``SSH`` service can be enabled on the node, and SSH with X11 forwarding can be used from the host to the node: :: # SSH from host to node n5 to run an X11 app ssh -X 172.16.0.5 xclock Note that the :file:`coresendmsg` utility can be used for a node to send messages to the CORE daemon running on the host (if the ``listenaddr = 0.0.0.0`` is set in the :file:`/etc/core/core.conf` file) to interact with the running emulation. For example, a node may move itself or other nodes, or change its icon based on some node state. Control Networks with Distributed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: distributed control network .. index:: control network distributed When a control network is defined for a distributed session, a control network bridge will be created on each of the slave servers, with GRE tunnels back to the master server's bridge. The slave control bridges are not assigned an address. From the host, any of the nodes (local or remote) can be accessed, just like the single server case. In some situations, remote emulated nodes need to communicate with the host on which they are running and not the master server. Multiple control network prefixes can be specified in the session option, separated by spaces. In this case, control network addresses are allocated from the first prefix on the master server. The remaining network prefixes are used for subsequent servers sorted by alphabetic host name. For example, if the control network option is set to "``172.16.1.0/24 172.16.2.0/24 192.168.0.0/16``" and the servers *core1*, *core2*, and *server1* are involved, the control network bridges will be assigned as follows: *core1* = ``172.16.1.254`` (assuming it is the master server), *core2* = ``172.16.2.254``, and *server1* = ``192.168.255.254``. Tunnels back to the master server will still be built, but it is up to the user to add appropriate routes if networking between control network prefixes is desired. The control network script may help with this. Control Network Script ^^^^^^^^^^^^^^^^^^^^^^ .. index:: control network scripts .. index:: controlnet_updown_script A control network script may be specified using the ``controlnet_updown_script`` option in the :file:`/etc/core/core.conf` file. This script will be run after the bridge has been built (and address assigned) with the first argument the name of the bridge, and the second argument the keyword "``startup``". The script will again be invoked prior to bridge removal with the second argument being the keyword "``shutdown``". Other Methods ^^^^^^^^^^^^^ .. index:: dummy interface .. index:: dummy0 There are still other ways to connect a host with a node. The :ref:`RJ45_Tool` can be used in conjunction with a dummy interface to access a node: :: sudo modprobe dummy numdummies=1 A ``dummy0`` interface should appear on the host. Use the RJ45 tool assigned to ``dummy0``, and link this to a node in your scenario. After starting the session, configure an address on the host. :: sudo brctl show # determine bridge name from the above command # assign an IP address on the same network as the linked node sudo ifconfig b.48304.34658 10.0.1.2/24 In the example shown above, the host will have the address ``10.0.1.2`` and the node linked to the RJ45 may have the address ``10.0.1.1``. .. _Building_Sample_Networks: Building Sample Networks ======================== .. _Wired_Networks: Wired Networks -------------- .. index:: links .. index:: wired links .. index:: Ethernet Wired networks are created using the *Link Tool* to draw a link between two nodes. This automatically draws a red line representing an Ethernet link and creates new interfaces on network-layer nodes. .. index:: link configuration Double-click on the link to invoke the *link configuration* dialog box. Here you can change the Bandwidth, Delay, Loss, and Duplicate rate parameters for that link. You can also modify the color and width of the link, affecting its display. .. index:: hub .. index:: switch .. index:: lanswitch Link-layer nodes are provided for modeling wired networks. These do not create a separate network stack when instantiated, but are implemented using bridging (Linux) or Netgraph nodes (FreeBSD). These are the hub, switch, and wireless LAN nodes. The hub copies each packet from the incoming link to every connected link, while the switch behaves more like an Ethernet switch and keeps track of the Ethernet address of the connected peer, forwarding unicast traffic only to the appropriate ports. The wireless LAN (WLAN) is covered in the next section. .. _Wireless_Networks: Wireless Networks ----------------- .. index:: WLAN .. index:: wireless .. index:: wireless LAN The wireless LAN node allows you to build wireless networks where moving nodes around affects the connectivity between them. The wireless LAN, or WLAN, node appears as a small cloud. The WLAN offers several levels of wireless emulation fidelity, depending on your modeling needs. The WLAN tool can be extended with plug-ins for different levels of wireless fidelity. The basic on/off range is the default setting available on all platforms. Other plug-ins offer higher fidelity at the expense of greater complexity and CPU usage. The availability of certain plug-ins varies depending on platform. See the table below for a brief overview of wireless model types. ============= ===================== ======== ================================================================== Model Type Supported Platform(s) Fidelity Description ============= ===================== ======== ================================================================== Basic on/off Linux, FreeBSD Low Linux Ethernet bridging with ebtables (Linux) or ng_wlan (FreeBSD) EMANE Plug-in Linux High TAP device connected to EMANE emulator with pluggable MAC and PHY radio types ============= ===================== ======== ================================================================== To quickly build a wireless network, you can first place several router nodes onto the canvas. If you have the :ref:`Quagga MDR software ` installed, it is recommended that you use the *mdr* node type for reduced routing overhead. Next choose the *wireless LAN* from the *Link-layer nodes* submenu. First set the desired WLAN parameters by double-clicking the cloud icon. Then you can link all of the routers by right-clicking on the WLAN and choosing *Link to all routers*. Linking a router to the WLAN causes a small antenna to appear, but no red link line is drawn. Routers can have multiple wireless links and both wireless and wired links (however, you will need to manually configure route redistribution.) The mdr node type will generate a routing configuration that enables OSPFv3 with MANET extensions. This is a Boeing-developed extension to Quagga's OSPFv3 that reduces flooding overhead and optimizes the flooding procedure for mobile ad-hoc (MANET) networks. .. index:: basic on/off range The default configuration of the WLAN is set to use the basic range model, using the *Basic* tab in the WLAN configuration dialog. Having this model selected causes :file:`core-daemon` to calculate the distance between nodes based on screen pixels. A numeric range in screen pixels is set for the wireless network using the *Range* slider. When two wireless nodes are within range of each other, a green line is drawn between them and they are linked. Two wireless nodes that are farther than the range pixels apart are not linked. During Execute mode, users may move wireless nodes around by clicking and dragging them, and wireless links will be dynamically made or broken. .. index:: EMANE tab The *EMANE* tab lists available EMANE models to use for wireless networking. See the :ref:`EMANE` chapter for details on using EMANE. On FreeBSD, the WLAN node is realized using the *ng_wlan* Netgraph node. .. _Mobility_Scripting: Mobility Scripting ------------------ .. index:: scripting .. index:: script .. index:: mobility script .. index:: mobility scripting CORE has a few ways to script mobility. * ns-2 script - the script specifies either absolute positions or waypoints with a velocity. Locations are given with Cartesian coordinates. * CORE API - an external entity can move nodes by sending CORE API Node messages with updated X,Y coordinates; the :file:`coresendmsg` utility allows a shell script to generate these messages. * EMANE events - see :ref:`EMANE` for details on using EMANE scripts to move nodes around. Location information is typically given as latitude, longitude, and altitude. For the first method, you can create a mobility script using a text editor, or using a tool such as `BonnMotion `_, and associate the script with one of the wireless using the WLAN configuration dialog box. Click the *ns-2 mobility script...* button, and set the *mobility script file* field in the resulting *ns2script* configuration dialog. Here is an example for creating a BonnMotion script for 10 nodes: :: bm -f sample RandomWaypoint -n 10 -d 60 -x 1000 -y 750 bm NSFile -f sample # use the resulting 'sample.ns_movements' file in CORE When the Execute mode is started and one of the WLAN nodes has a mobility script, a mobility script window will appear. This window contains controls for starting, stopping, and resetting the running time for the mobility script. The *loop* checkbox causes the script to play continuously. The *resolution* text box contains the number of milliseconds between each timer event; lower values cause the mobility to appear smoother but consumes greater CPU time. The format of an ns-2 mobility script looks like: :: # nodes: 3, max time: 35.000000, max x: 600.00, max y: 600.00 $node_(2) set X_ 144.0 $node_(2) set Y_ 240.0 $node_(2) set Z_ 0.00 $ns_ at 1.00 "$node_(2) setdest 130.0 280.0 15.0" The first three lines set an initial position for node 2. The last line in the above example causes node 2 to move towards the destination `(130, 280)` at speed `15`. All units are screen coordinates, with speed in units per second. The total script time is learned after all nodes have reached their waypoints. Initially, the time slider in the mobility script dialog will not be accurate. Examples mobility scripts (and their associated topology files) can be found in the :file:`configs/` directory (see :ref:`Configuration_Files`). .. _Multiple_Canvases: Multiple Canvases ----------------- .. index:: canvas CORE supports multiple canvases for organizing emulated nodes. Nodes running on different canvases may be linked together. To create a new canvas, choose *New* from the *Canvas* menu. A new canvas tab appears in the bottom left corner. Clicking on a canvas tab switches to that canvas. Double-click on one of the tabs to invoke the *Manage Canvases* dialog box. Here, canvases may be renamed and reordered, and you can easily switch to one of the canvases by selecting it. Each canvas maintains its own set of nodes and annotations. To link between canvases, select a node and right-click on it, choose *Create link to*, choose the target canvas from the list, and from that submenu the desired node. A pseudo-link will be drawn, representing the link between the two nodes on different canvases. Double-clicking on the label at the end of the arrow will jump to the canvas that it links. .. _Distributed_Emulation: Distributed Emulation --------------------- .. index:: distributed emulation .. index:: headless mode .. index:: server .. index:: emulation server A large emulation scenario can be deployed on multiple emulation servers and controlled by a single GUI. The GUI, representing the entire topology, can be run on one of the emulation servers or on a separate machine. Emulations can be distributed on Linux, while tunneling support has not been added yet for FreeBSD. Each machine that will act as an emulation server needs to have CORE installed. It is not important to have the GUI component but the CORE Python daemon :file:`core-daemon` needs to be installed. Set the ``listenaddr`` line in the :file:`/etc/core/core.conf` configuration file so that the CORE Python daemon will respond to commands from other servers: :: ### core-daemon configuration options ### [core-daemon] pidfile = /var/run/core-daemon.pid logfile = /var/log/core-daemon.log listenaddr = 0.0.0.0 The ``listenaddr`` should be set to the address of the interface that should receive CORE API control commands from the other servers; setting ``listenaddr = 0.0.0.0`` causes the Python daemon to listen on all interfaces. CORE uses TCP port 4038 by default to communicate from the controlling machine (with GUI) to the emulation servers. Make sure that firewall rules are configured as necessary to allow this traffic. In order to easily open shells on the emulation servers, the servers should be running an SSH server, and public key login should be enabled. This is accomplished by generating an SSH key for your user if you do not already have one (use ``ssh-keygen -t rsa``), and then copying your public key to the authorized_keys file on the server (for example, ``ssh-copy-id user@server`` or ``scp ~/.ssh/id_rsa.pub server:.ssh/authorized_keys``.) When double-clicking on a node during runtime, instead of opening a local shell, the GUI will attempt to SSH to the emulation server to run an interactive shell. The user name used for these remote shells is the same user that is running the CORE GUI. .. HINT:: Here is a quick distributed emulation checklist. 1. Install the CORE daemon on all servers. 2. Configure public-key SSH access to all servers (if you want to use double-click shells or Widgets.) 3. Set ``listenaddr=0.0.0.0`` in all of the server's core.conf files, then start (or restart) the daemon. 4. Select nodes, right-click them, and choose *Assign to* to assign the servers (add servers through *Session*, *Emulation Servers...*) 5. Press the *Start* button to launch the distributed emulation. Servers are configured by choosing *Emulation servers...* from the *Session* menu. Servers parameters are configured in the list below and stored in a *servers.conf* file for use in different scenarios. The IP address and port of the server must be specified. The name of each server will be saved in the topology file as each node's location. The user needs to assign nodes to emulation servers in the scenario. Making no assignment means the node will be emulated locally, on the same machine that the GUI is running. In the configuration window of every node, a drop-down box located between the *Node name* and the *Image* button will select the name of the emulation server. By default, this menu shows *(none)*, indicating that the node will be emulated locally. When entering Execute mode, the CORE GUI will deploy the node on its assigned emulation server. Another way to assign emulation servers is to select one or more nodes using the select tool (shift-click to select multiple), and right-click one of the nodes and choose *Assign to...*. The *CORE emulation servers* dialog box may also be used to assign nodes to servers. The assigned server name appears in parenthesis next to the node name. To assign all nodes to one of the servers, click on the server name and then the *all nodes* button. Servers that have assigned nodes are shown in blue in the server list. Another option is to first select a subset of nodes, then open the *CORE emulation servers* box and use the *selected nodes* button. The emulation server machines should be reachable on the specified port and via SSH. SSH is used when double-clicking a node to open a shell, the GUI will open an SSH prompt to that node's emulation server. Public-key authentication should be configured so that SSH passwords are not needed. If there is a link between two nodes residing on different servers, the GUI will draw the link with a dashed line, and automatically create necessary tunnels between the nodes when executed. Care should be taken to arrange the topology such that the number of tunnels is minimized. The tunnels carry data between servers to connect nodes as specified in the topology. These tunnels are created using GRE tunneling, similar to the :ref:`Tunnel_Tool`. .. index:: distributed wireless Wireless nodes, i.e. those connected to a WLAN node, can be assigned to different emulation servers and participate in the same wireless network only if an EMANE model is used for the WLAN. See :ref:`Distributed_EMANE` for more details. The basic range model does not work across multiple servers due to the Linux bridging and ebtables rules that are used. .. NOTE:: The basic range wireless model does not support distributed emulation, but EMANE does. .. index:: node services .. index:: services .. _Services: Services ======== CORE uses the concept of services to specify what processes or scripts run on a node when it is started. Layer-3 nodes such as routers and PCs are defined by the services that they run. The :ref:`Quagga_Routing_Software`, for example, transforms a node into a router. Services may be customized for each node, or new custom services can be created. New node types can be created each having a different name, icon, and set of default services. Each service defines the per-node directories, configuration files, startup index, starting commands, validation commands, shutdown commands, and meta-data associated with a node. .. NOTE:: Network namespace nodes do not undergo the normal Linux boot process using the ``init``, ``upstart``, or ``systemd`` frameworks. These lightweight nodes use configured CORE *services*. .. _Default_Services_and_Node_Types: Default Services and Node Types ------------------------------- Here are the default node types and their services: .. index:: Xen .. index:: physical nodes * *router* - zebra, OSFPv2, OSPFv3, vtysh, and IPForward services for IGP link-state routing. * *host* - DefaultRoute and SSH services, representing an SSH server having a default route when connected directly to a router. * *PC* - DefaultRoute service for having a default route when connected directly to a router. * *mdr* - zebra, OSPFv3MDR, vtysh, and IPForward services for wireless-optimized MANET Designated Router routing. * *prouter* - a physical router, having the same default services as the *router* node type; for incorporating Linux testbed machines into an emulation, the :ref:`Machine_Types` is set to :ref:`physical`. * *xen* - a Xen-based router, having the same default services as the *router* node type; for incorporating Xen domUs into an emulation, the :ref:`Machine_Types` is set to :ref:`xen`, and different *profiles* are available. Configuration files can be automatically generated by each service. For example, CORE automatically generates routing protocol configuration for the router nodes in order to simplify the creation of virtual networks. To change the services associated with a node, double-click on the node to invoke its configuration dialog and click on the *Services...* button, or right-click a node a choose *Services...* from the menu. Services are enabled or disabled by clicking on their names. The button next to each service name allows you to customize all aspects of this service for this node. For example, special route redistribution commands could be inserted in to the Quagga routing configuration associated with the zebra service. .. index:: default services To change the default services associated with a node type, use the Node Types dialog available from the *Edit* button at the end of the Layer-3 nodes toolbar, or choose *Node types...* from the *Session* menu. Note that any new services selected are not applied to existing nodes if the nodes have been customized. .. index:: nodes.conf The node types are saved in a :file:`~/.core/nodes.conf` file, not with the `.imn` file. Keep this in mind when changing the default services for existing node types; it may be better to simply create a new node type. It is recommended that you do not change the default built-in node types. The :file:`nodes.conf` file can be copied between CORE machines to save your custom types. .. _Customizing_a_Service: Customizing a Service --------------------- .. index:: customizing services .. index:: service customization dialog A service can be fully customized for a particular node. From the node's configuration dialog, click on the button next to the service name to invoke the service customization dialog for that service. The dialog has three tabs for configuring the different aspects of the service: files, directories, and startup/shutdown. .. NOTE:: A **yellow** customize icon next to a service indicates that service requires customization (e.g. the *Firewall* service). A **green** customize icon indicates that a custom configuration exists. Click the *Defaults* button when customizing a service to remove any customizations. .. index:: files tab The Files tab is used to display or edit the configuration files or scripts that are used for this service. Files can be selected from a drop-down list, and their contents are displayed in a text entry below. The file contents are generated by the CORE daemon based on the network topology that exists at the time the customization dialog is invoked. .. index:: directories tab .. index:: per-node directories The Directories tab shows the per-node directories for this service. For the default types, CORE nodes share the same filesystem tree, except for these per-node directories that are defined by the services. For example, the `/var/run/quagga` directory needs to be unique for each node running the Zebra service, because Quagga running on each node needs to write separate PID files to that directory. .. NOTE:: The :file:`/var/log` and :file:`/var/run` directories are mounted uniquely per-node by default. Per-node mount targets can be found in :file:`/tmp/pycore.nnnnn/nN.conf/` (where *nnnnn* is the session number and *N* is the node number.) .. index:: startup/shutdown tab .. index:: startup index .. index:: startup commands .. index:: shutdown commands The Startup/shutdown tab lists commands that are used to start and stop this service. The startup index allows configuring when this service starts relative to the other services enabled for this node; a service with a lower startup index value is started before those with higher values. Because shell scripts generated by the Files tab will not have execute permissions set, the startup commands should include the shell name, with something like "`sh script.sh`". Shutdown commands optionally terminate the process(es) associated with this service. Generally they send a kill signal to the running process using the *kill* or *killall* commands. If the service does not terminate the running processes using a shutdown command, the processes will be killed when the *vnoded* daemon is terminated (with *kill -9*) and the namespace destroyed. It is a good practice to specify shutdown commands, which will allow for proper process termination, and for run-time control of stopping and restarting services. .. index:: validate commands Validate commands are executed following the startup commands. A validate command can execute a process or script that should return zero if the service has started successfully, and have a non-zero return value for services that have had a problem starting. For example, the *pidof* command will check if a process is running and return zero when found. When a validate command produces a non-zero return value, an exception is generated, which will cause an error to be displayed in the :ref:`Check_Emulation_Light`. .. tip:: To start, stop, and restart services during run-time, right-click a node and use the *Services...* menu. .. _Creating_new_Services: Creating new Services --------------------- .. index:: creating services Services can save time required to configure nodes, especially if a number of nodes require similar configuration procedures. New services can be introduced to automate tasks. .. index:: UserDefined service The easiest way to capture the configuration of a new process into a service is by using the **UserDefined** service. This is a blank service where any aspect may be customized. The UserDefined service is convenient for testing ideas for a service before adding a new service type. To introduce new service types, a :file:`myservices/` directory exists in the user's CORE configuration directory, at :file:`~/.core/myservices/`. A detailed :file:`README.txt` file exists in that directory to outline the steps necessary for adding a new service. First, you need to create a small Python file that defines the service; then the `custom_services_dir` entry must be set in the :file:`/etc/core/core.conf` configuration file. A sample is provided in the :file:`myservices/` directory. If you have created a new service type that may be useful to others, please consider contributing it to the CORE project. .. _Check_Emulation_Light: Check Emulation Light ===================== .. index:: check emulation light .. index:: CEL The Check Emulation Light, or CEL, is located in the bottom right-hand corner of the status bar in the CORE GUI. This is a yellow icon that indicates one or more problems with the running emulation. Clicking on the CEL will invoke the CEL dialog. .. index:: exceptions The Check Emulation Light dialog contains a list of exceptions received from the CORE daemon. An exception has a time, severity level, optional node number, and source. When the CEL is blinking, this indicates one or more fatal exceptions. An exception with a fatal severity level indicates that one or more of the basic pieces of emulation could not be created, such as failure to create a bridge or namespace, or the failure to launch EMANE processes for an EMANE-based network. Clicking on an exception displays details for that exception. If a node number is specified, that node is highlighted on the canvas when the exception is selected. The exception source is a text string to help trace where the exception occurred; "service:UserDefined" for example, would appear for a failed validation command with the UserDefined service. Buttons are available at the bottom of the dialog for clearing the exception list and for viewing the CORE daemon and node log files. .. _Configuration_Files: Configuration Files =================== .. index:: configuration file .. index:: imn file Configurations are saved to :file:`xml` or :file:`.imn` topology files using the *File* menu. You can easily edit these files with a text editor. Any time you edit the topology file, you will need to stop the emulation if it were running and reload the file. The :file:`.xml` file schema is `specified by NRL `_. Planning documents are specified in NRL's Network Modeling Framework (NMF). Here the individual planning documents are several tags encased in one `` tag: * `` - describes nodes, hosts, interfaces, and the networks to which they belong. * `` - describes position and motion patterns for nodes in an emulation. * `` - describes services (protocols, applications) and traffic flows that are associated with certain nodes. * `` - meta-data that is not part of the NRL XML schema but used only by CORE. For example, GUI options, canvas and annotation info, etc. are contained here. .. index:: indentation The :file:`.imn` file format comes from :ref:`IMUNES `, and is basically Tcl lists of nodes, links, etc. Tabs and spacing in the topology files are important. The file starts by listing every node, then links, annotations, canvases, and options. Each entity has a block contained in braces. The first block is indented by four spaces. Within the `network-config` block (and any *custom-*-config* block), the indentation is one tab character. .. tip:: There are several topology examples included with CORE in the :file:`configs/` directory. This directory can be found in :file:`~/.core/configs`, or installed to the filesystem under :file:`/usr[/local]/share/examples/configs`. .. tip:: When using the :file:`.imn` file format, file paths for things like custom icons may contain the special variables `$CORE_DATA_DIR` or `$CONFDIR` which will be substituted with :file:`/usr/share/core` or :file:`~/.core/configs`. .. tip:: Feel free to edit the files directly using your favorite text editor. .. _Customizing_your_Topology's_Look: Customizing your Topology's Look ================================ .. index:: annotation tools .. index:: captions .. index:: text tool .. index:: ovals .. index:: rectangles Several annotation tools are provided for changing the way your topology is presented. Captions may be added with the Text tool. Ovals and rectangles may be drawn in the background, helpful for visually grouping nodes together. .. index:: marker tool During live demonstrations the marker tool may be helpful for drawing temporary annotations on the canvas that may be quickly erased. A size and color palette appears at the bottom of the toolbar when the marker tool is selected. Markings are only temporary and are not saved in the topology file. .. index:: images .. index:: icons .. index:: custom icons The basic node icons can be replaced with a custom image of your choice. Icons appear best when they use the GIF or PNG format with a transparent background. To change a node's icon, double-click the node to invoke its configuration dialog and click on the button to the right of the node name that shows the node's current icon. .. index:: wallpaper .. index:: canvas wallpaper A background image for the canvas may be set using the *Wallpaper...* option from the *Canvas* menu. The image may be centered, tiled, or scaled to fit the canvas size. An existing terrain, map, or network diagram could be used as a background, for example, with CORE nodes drawn on top. .. _Preferences: Preferences =========== .. index:: preferences .. index:: Preferences Dialog The *Preferences* Dialog can be accessed from the :ref:`Edit_Menu`. There are numerous defaults that can be set with this dialog, which are stored in the :file:`~/.core/prefs.conf` preferences file. core-4.6/doc/_build/0000775000175000017500000000000012220631372011317 500000000000000core-4.6/doc/index.rst0000664000175000017500000000056212130605674011653 00000000000000.. This file is part of the CORE Manual (c)2012 the Boeing Company .. only:: html or latex CORE Manual =========== .. toctree:: :maxdepth: 2 :numbered: intro install usage scripting machine emane ns3 performance devguide credits Indices and tables ================== .. only:: html * :ref:`genindex` * :ref:`search` core-4.6/doc/Makefile.in0000664000175000017500000005444612220631420012055 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@ # CORE # (c)2009-2012 the Boeing Company. # See the LICENSE file included in this distribution. # # author: Jeff Ahrenholz # # Builds html and pdf documentation using Sphinx. # 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 = : subdir = doc DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/conf.py.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = conf.py CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ ARCH = @ARCH@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COREDPY_VERSION = @COREDPY_VERSION@ CORE_CONF_DIR = @CORE_CONF_DIR@ CORE_DATA_DIR = @CORE_DATA_DIR@ CORE_GUI_CONF_DIR = @CORE_GUI_CONF_DIR@ CORE_LIB_DIR = @CORE_LIB_DIR@ CORE_STATE_DIR = @CORE_STATE_DIR@ CORE_VERSION = @CORE_VERSION@ CORE_VERSION_DATE = @CORE_VERSION_DATE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ HELP2MAN = @HELP2MAN@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIB_DIR = @LIB_DIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SBINDIR = @SBINDIR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ brctl_path = @brctl_path@ build_alias = @build_alias@ builddir = @builddir@ convert = @convert@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ ebtables_path = @ebtables_path@ enable_daemon = @enable_daemon@ enable_gui = @enable_gui@ exec_prefix = @exec_prefix@ gmake = @gmake@ help2man = @help2man@ host_alias = @host_alias@ htmldir = @htmldir@ ifconfig_path = @ifconfig_path@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ip_path = @ip_path@ libdir = @libdir@ libev_CFLAGS = @libev_CFLAGS@ libev_LIBS = @libev_LIBS@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mount_path = @mount_path@ ngctl_path = @ngctl_path@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ sysctl_path = @sysctl_path@ target_alias = @target_alias@ tc_path = @tc_path@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ umount_path = @umount_path@ vimage_path = @vimage_path@ with_startup = @with_startup@ SUBDIRS = man figures # extra cruft to remove DISTCLEANFILES = Makefile.in stamp-vti rst_files = conf.py constants.txt credits.rst devguide.rst emane.rst \ index.rst install.rst intro.rst machine.rst ns3.rst \ performance.rst scripting.rst usage.rst EXTRA_DIST = $(rst_files) _build _static _templates ###### below this line was generated using sphinx-quickstart ###### # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --foreign doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/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): conf.py: $(top_builddir)/config.status $(srcdir)/conf.py.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done 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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ 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: ctags-recursive $(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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic ctags \ ctags-recursive dist-hook distclean distclean-generic \ 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am # clean up dirs included by EXTRA_DIST dist-hook: rm -rf $(distdir)/_build/.svn $(distdir)/_static/.svn \ $(distdir)/_templates/.svn .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CORE.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CORE.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/CORE" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CORE" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." # 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: core-4.6/doc/intro.rst0000664000175000017500000002525112206666102011676 00000000000000.. This file is part of the CORE Manual (c)2012-2013 the Boeing Company .. _Introduction: ************ Introduction ************ The Common Open Research Emulator (CORE) is a tool for building virtual networks. As an emulator, CORE builds a representation of a real computer network that runs in real time, as opposed to simulation, where abstract models are used. The live-running emulation can be connected to physical networks and routers. It provides an environment for running real applications and protocols, taking advantage of virtualization provided by the Linux or FreeBSD operating systems. Some of its key features are: .. index:: single: key features * efficient and scalable * runs applications and protocols without modification * easy-to-use GUI * highly customizable CORE is typically used for network and protocol research, demonstrations, application and platform testing, evaluating networking scenarios, security studies, and increasing the size of physical test networks. .. index:: single: CORE; components of single: CORE; API single: API single: CORE; GUI .. _Architecture: Architecture ============ The main components of CORE are shown in :ref:`core-architecture`. A *CORE daemon* (backend) manages emulation sessions. It builds emulated networks using kernel virtualization for virtual nodes and some form of bridging and packet manipulation for virtual networks. The nodes and networks come together via interfaces installed on nodes. The daemon is controlled via the graphical user interface, the *CORE GUI* (frontend). The daemon uses Python modules that can be imported directly by Python scripts. The GUI and the daemon communicate using a custom, asynchronous, sockets-based API, known as the *CORE API*. The dashed line in the figure notionally depicts the user-space and kernel-space separation. The components the user interacts with are colored blue: GUI, scripts, or command-line tools. The system is modular to allow mixing different components. The virtual networks component, for example, can be realized with other network simulators and emulators, such as ns-3 and EMANE. Different types of kernel virtualization are supported. Another example is how a session can be designed and started using the GUI, and continue to run in "headless" operation with the GUI closed. The CORE API is sockets based, to allow the possibility of running different components on different physical machines. .. _core-architecture: .. figure:: figures/core-architecture.* :alt: CORE architecture diagram :align: center CORE Architecture The CORE GUI is a Tcl/Tk program; it is started using the command ``core-gui``. The CORE daemon, named ``core-daemon``, is usually started via the init script (``/etc/init.d/core-daemon`` or ``core-daemon.service``, depending on platform.) The CORE daemon manages sessions of virtual nodes and networks, of which other scripts and utilities may be used for further control. .. _How_Does_It_Work?: How Does it Work? ================= A CORE node is a lightweight virtual machine. The CORE framework runs on Linux and FreeBSD systems. The primary platform used for development is Linux. .. index:: single: Linux; virtualization single: Linux; containers single: LXC single: network namespaces * :ref:`Linux` CORE uses Linux network namespace virtualization to build virtual nodes, and ties them together with virtual networks using Linux Ethernet bridging. * :ref:`FreeBSD` CORE uses jails with a network stack virtualization kernel option to build virtual nodes, and ties them together with virtual networks using BSD's Netgraph system. .. _Linux: Linux ----- Linux network namespaces (also known as netns, LXC, or `Linux containers `_) is the primary virtualization technique used by CORE. LXC has been part of the mainline Linux kernel since 2.6.24. Recent Linux distributions such as Fedora and Ubuntu have namespaces-enabled kernels out of the box, so the kernel does not need to be patched or recompiled. A namespace is created using the ``clone()`` system call. Similar to the BSD jails, each namespace has its own process environment and private network stack. Network namespaces share the same filesystem in CORE. .. index:: single: Linux; bridging single: Linux; networking single: ebtables CORE combines these namespaces with Linux Ethernet bridging to form networks. Link characteristics are applied using Linux Netem queuing disciplines. Ebtables is Ethernet frame filtering on Linux bridges. Wireless networks are emulated by controlling which interfaces can send and receive with ebtables rules. .. _FreeBSD: FreeBSD ------- .. index:: single: FreeBSD; Network stack virtualization single: FreeBSD; jails single: FreeBSD; vimages FreeBSD jails provide an isolated process space, a virtual environment for running programs. Starting with FreeBSD 8.0, a new `vimage` kernel option extends BSD jails so that each jail can have its own virtual network stack -- its own networking variables such as addresses, interfaces, routes, counters, protocol state, socket information, etc. The existing networking algorithms and code paths are intact but operate on this virtualized state. Each jail plus network stack forms a lightweight virtual machine. These are named jails or *virtual images* (or *vimages*) and are created using a the ``jail`` or ``vimage`` command. Unlike traditional virtual machines, vimages do not feature entire operating systems running on emulated hardware. All of the vimages will share the same processor, memory, clock, and other system resources. Because the actual hardware is not emulated and network packets can be passed by reference through the in-kernel Netgraph system, vimages are quite lightweight and a single system can accommodate numerous instances. Virtual network stacks in FreeBSD were historically available as a patch to the FreeBSD 4.11 and 7.0 kernels, and the VirtNet project [#f1]_ [#f2]_ added this functionality to the mainline 8.0-RELEASE and newer kernels. .. index:: single: FreeBSD; Netgraph The FreeBSD Operating System kernel features a graph-based networking subsystem named Netgraph. The netgraph(4) manual page quoted below best defines this system: The netgraph system provides a uniform and modular system for the implementation of kernel objects which perform various networking functions. The objects, known as nodes, can be arranged into arbitrarily complicated graphs. Nodes have hooks which are used to connect two nodes together, forming the edges in the graph. Nodes communicate along the edges to process data, implement protocols, etc. The aim of netgraph is to supplement rather than replace the existing kernel networking infrastructure. .. index:: single: IMUNES single: VirtNet single: prior work .. rubric:: Footnotes .. [#f1] http://www.nlnet.nl/project/virtnet/ .. [#f2] http://www.imunes.net/virtnet/ .. _Prior_Work: Prior Work ========== The Tcl/Tk CORE GUI was originally derived from the open source `IMUNES `_ project from the University of Zagreb as a custom project within Boeing Research and Technology's Network Technology research group in 2004. Since then they have developed the CORE framework to use not only FreeBSD but Linux virtualization, have developed a Python framework, and made numerous user- and kernel-space developments, such as support for wireless networks, IPsec, the ability to distribute emulations, simulation integration, and more. The IMUNES project also consists of userspace and kernel components. Originally, one had to download and apply a patch for the FreeBSD 4.11 kernel, but the more recent `VirtNet `_ effort has brought network stack virtualization to the more modern FreeBSD 8.x kernel. .. _Open_Source_Project_and_Resources: Open Source Project and Resources ================================= .. index:: single: open source project single: license single: website single: supplemental website single: contributing CORE has been released by Boeing to the open source community under the BSD license. If you find CORE useful for your work, please contribute back to the project. Contributions can be as simple as reporting a bug, dropping a line of encouragement or technical suggestions to the mailing lists, or can also include submitting patches or maintaining aspects of the tool. For details on contributing to CORE, please visit the `wiki `_. Besides this manual, there are other additional resources available online: * `CORE website `_ - main project page containing demos, downloads, and mailing list information. * `CORE supplemental website `_ - supplemental Google Code page with a quickstart guide, wiki, bug tracker, and screenshots. .. index:: single: wiki single: CORE; wiki The `CORE wiki `_ is a good place to check for the latest documentation and tips. Goals ----- These are the Goals of the CORE project; they are similar to what we consider to be the :ref:`key features `. #. Ease of use - In a few clicks the user should have a running network. #. Efficiency and scalability - A node is more lightweight than a full virtual machine. Tens of nodes should be possible on a standard laptop computer. #. Real software - Run real implementation code, protocols, networking stacks. #. Networking - CORE is focused on emulating networks and offers various ways to connect the running emulation with real or simulated networks. #. Hackable - The source code is available and easy to understand and modify. Non-Goals --------- This is a list of Non-Goals, specific things that people may be interested in but are not areas that we will pursue. #. Reinventing the wheel - Where possible, CORE reuses existing open source components such as virtualization, Netgraph, netem, bridging, Quagga, etc. #. 1,000,000 nodes - While the goal of CORE is to provide efficient, scalable network emulation, there is no set goal of N number of nodes. There are realistic limits on what a machine can handle as its resources are divided amongst virtual nodes. We will continue to make things more efficient and let the user determine the right number of nodes based on available hardware and the activities each node is performing. #. Solves every problem - CORE is about emulating networking layers 3-7 using virtual network stacks in the Linux or FreeBSD operating systems. #. Hardware-specific - CORE itself is not an instantiation of hardware, a testbed, or a specific laboratory setup; it should run on commodity laptop and desktop PCs, in addition to high-end server hardware. core-4.6/scripts/0000775000175000017500000000000012220631511010776 500000000000000core-4.6/scripts/core-daemon-init.d-SUSE0000775000175000017500000002362512206710505015012 00000000000000#!/bin/sh # # Template SUSE system startup script for example service/daemon core # Copyright (C) 1995--2005 Kurt Garloff, SUSE / Novell Inc. # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser 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. # # /etc/init.d/FOO # and its symbolic link # /(usr/)sbin/rcFOO # # Template system startup script for some example service/daemon FOO # # LSB compatible service control script; see http://www.linuxbase.org/spec/ # # Note: This template uses functions rc_XXX defined in /etc/rc.status on # UnitedLinux/SUSE/Novell based Linux distributions. If you want to base your # script on this template and ensure that it works on non UL based LSB # compliant Linux distributions, you either have to provide the rc.status # functions from UL or change the script to work without them. # See skeleton.compat for a template that works with other distros as well. # ### BEGIN INIT INFO # Provides: core-daemon # Required-Start: $network $remote_fs xend # Required-Stop: $network $remote_fs xend # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: core-daemon # Description: Start core-daemon # continued on second line by '#' # should contain enough info for the runlevel editor # to give admin some idea what this service does and # what it's needed for ... # (The Short-Description should already be a good hint.) ### END INIT INFO # # Any extensions to the keywords given above should be preceeded by # X-VendorTag- (X-UnitedLinux- X-SuSE- for us) according to LSB. # # Notes on Required-Start/Should-Start: # * There are two different issues that are solved by Required-Start # and Should-Start # (a) Hard dependencies: This is used by the runlevel editor to determine # which services absolutely need to be started to make the start of # this service make sense. Example: nfsserver should have # Required-Start: $portmap # Also, required services are started before the dependent ones. # The runlevel editor will warn about such missing hard dependencies # and suggest enabling. During system startup, you may expect an error, # if the dependency is not fulfilled. # (b) Specifying the init script ordering, not real (hard) dependencies. # This is needed by insserv to determine which service should be # started first (and at a later stage what services can be started # in parallel). The tag Should-Start: is used for this. # It tells, that if a service is available, it should be started # before. If not, never mind. # * When specifying hard dependencies or ordering requirements, you can # use names of services (contents of their Provides: section) # or pseudo names starting with a $. The following ones are available # according to LSB (1.1): # $local_fs all local file systems are mounted # (most services should need this!) # $remote_fs all remote file systems are mounted # (note that /usr may be remote, so # many services should Require this!) # $syslog system logging facility up # $network low level networking (eth card, ...) # $named hostname resolution available # $netdaemons all network daemons are running # The $netdaemons pseudo service has been removed in LSB 1.2. # For now, we still offer it for backward compatibility. # These are new (LSB 1.2): # $time the system time has been set correctly # $portmap SunRPC portmapping service available # UnitedLinux extensions: # $ALL indicates that a script should be inserted # at the end # * The services specified in the stop tags # (Required-Stop/Should-Stop) # specify which services need to be still running when this service # is shut down. Often the entries there are just copies or a subset # from the respective start tag. # * Should-Start/Stop are now part of LSB as of 2.0, # formerly SUSE/Unitedlinux used X-UnitedLinux-Should-Start/-Stop. # insserv does support both variants. # * X-UnitedLinux-Default-Enabled: yes/no is used at installation time # (%fillup_and_insserv macro in %post of many RPMs) to specify whether # a startup script should default to be enabled after installation. # It's not used by insserv. # # Note on runlevels: # 0 - halt/poweroff 6 - reboot # 1 - single user 2 - multiuser without network exported # 3 - multiuser w/ network (text mode) 5 - multiuser w/ network and X11 (xdm) # # Note on script names: # http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/scrptnames.html # A registry has been set up to manage the init script namespace. # http://www.lanana.org/ # Please use the names already registered or register one or use a # vendor prefix. # Check for missing binaries (stale symlinks should not happen) # Note: Special treatment of stop for LSB conformance CORE_BIN=/usr/local/sbin/core-daemon test -x $CORE_BIN || { echo "$CORE_BIN not installed"; if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; } # Check for existence of needed config file and read it CORE_CONFIG=/etc/core test -r $CORE_CONFIG || { echo "$CORE_CONFIG not existing"; if [ "$1" = "stop" ]; then exit 0; else exit 6; fi; } # Source LSB init functions # providing start_daemon, killproc, pidofproc, # log_success_msg, log_failure_msg and log_warning_msg. # This is currently not used by UnitedLinux based distributions and # not needed for init scripts for UnitedLinux only. If it is used, # the functions from rc.status should not be sourced or used. #. /lib/lsb/init-functions # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v be verbose in local rc status and clear it afterwards # rc_status -v -r ditto and clear both the local and overall rc status # rc_status -s display "skipped" and exit with status 3 # rc_status -u display "unused" and exit with status 3 # rc_failed set local and overall rc status to failed # rc_failed set local and overall rc status to # rc_reset clear both the local and overall rc status # rc_exit exit appropriate to overall rc status # rc_active checks whether a service is activated by symlinks . /etc/rc.status # Reset status of this service rc_reset # Return values acc. to LSB for all commands but status: # 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - user had insufficient privileges # 5 - program is not installed # 6 - program is not configured # 7 - program is not running # 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) # # Note that starting an already running service, stopping # or restarting a not-running service as well as the restart # with force-reload (in case signaling is not supported) are # considered a success. case "$1" in start) echo -n "Starting CORE " ## Start daemon with startproc(8). If this fails ## the return value is set appropriately by startproc. /sbin/startproc $CORE_BIN -d # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down CORE " ## Stop daemon with killproc(8) and if this fails ## killproc sets the return value according to LSB. if [ -r /var/run/core-daemon.pid ] ; then /bin/kill -TERM `cat /var/run/core-daemon.pid` /bin/rm -f /var/run/core-daemon.pid fi # Remember status and be verbose rc_status -v ;; try-restart|condrestart) ## Do a restart only if the service was active before. ## Note: try-restart is now part of LSB (as of 1.9). ## RH has a similar command named condrestart. if test "$1" = "condrestart"; then echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}" fi $0 status if test $? = 0; then $0 restart else rc_reset # Not running is not a failure. fi # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; force-reload) ## Signal the daemon to reload its config. Most daemons ## do this on signal 1 (SIGHUP). ## If it does not support it, restart the service if it ## is running. echo -n "Reload service CORE " $0 try-restart rc_status ;; reload) ## Like force-reload, but if daemon does not support ## signaling, do nothing (!) ## It does not support reload: rc_failed 3 rc_status -v ;; status) echo -n "Checking for service CORE " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Return value is slightly different for the status command: # 0 - service up and running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running (unused) # 4 - service status unknown :-( # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) # NOTE: checkproc returns LSB compliant status values. /sbin/checkproc -p /var/run/core-daemon.pid python # NOTE: rc_status knows that we called this init script with # "status" option and adapts its messages accordingly. rc_status -v ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}" exit 1 ;; esac rc_exit core-4.6/scripts/perf/0000775000175000017500000000000012220631511011732 500000000000000core-4.6/scripts/perf/timesyncstart.sh0000664000175000017500000000105011713023241015114 00000000000000#!/bin/sh # (c)2010-2012 the Boeing Company # author: Yueli Yang # # start time sync with ntpd if it is installed but not started # # Usage: sudo timesyncstart.sh [debug] dbg=$1 if [ "$dbg" = "debug" ]; then date +%y%h%d-%T-%N fi if [ -e /usr/sbin/ntpd ]; then /etc/init.d/ntp status if [ $? = 3 ]; then /etc/init.d/ntp start if [ "$dbg" = "debug" ]; then echo "start ntpd process" ntptime ntpq -c peers fi fi fi if [ "$dbg" = "debug" ]; then date +%y%h%d-%T-%N fi core-4.6/scripts/perf/perflogserver.py0000775000175000017500000005365511713021177015141 00000000000000#!/usr/bin/env python # # (c)2011-2012 the Boeing Company # # perfmon.py - CORE server and node performace metrics logger and alarmer # server metrics: loadave1, 5, 15, mem, used cpu% of total, cpu1, cpu2, ..., cpun # node metrics: throughput, mem, cpu total, usr, sys, wait # import os, sys, time, re, optparse, signal, commands, pdb def readfile(fname): lines=[] try: f = open(fname, "r") except: if options.timestamp == True: print str(time.time()), print "ERROR: failed to open file %s\n" % fname else : lines = f.readlines() f.close() return lines def numcpus(): lines = readfile("/proc/stat") n = 0 for l in lines[1:]: if l[:3] != "cpu": break n += 1 return n def handler(signum, frame): print "stop timestamp:", str(time.time()) + ", cyclecount=", cyclecount, ", caught signal", signum sys.exit(0) class ServerMetrics(object): def __init__(self): self.smetrics = { "serverloadavg1" : 0.0, "serverloadavg5" : 0.0, "serverloadavg15" : 0.0, "serverusedmemory" : 0.0, "serverusedcputime" : 0.0, "processorusedcputime" : [] } # set values from val = (nump, ldavg1, ldavg5, adavg15, mem, cpu, p1cpu, p2cpu...) def setvalues(self, val): self.smetrics["serverloadavg1"] = val[0] self.smetrics["serverloadavg5"] = val[1] self.smetrics["serverloadavg15"] = val[2] self.smetrics["serverusedmemory"] = val[4] self.smetrics["serverusedcputime"] = val[5] #print self.smetrics.keys(), self.smetrics.values() pcpu = [] for ind in range(5,len(val)): pcpu.append(val[ind]) # print "[" + ",".join(map(lambda(x):str(round(x, 2)), pcpu)) +"]" self.smetrics["processorusedcputime"] = pcpu #print self.smetrics.keys(), self.smetrics.values() def setvalue(self, key, val): self.smetrics[key] = val def getvalue(self, key): return self.smetrics[key] def getkeys(self): return self.smetrics.keys() def tocsv(self): rv = "Server" for k in self.smetrics: # print k, self.smetrics[k] if isinstance(self.smetrics[k], float): rv += ", %.2f" % self.smetrics[k] else: if isinstance(self.smetrics[k], list): rv += ", [" + \ ", ".join(map(lambda(x):str(round(x, 2)), self.smetrics[k])) \ + "]" else: rv += ", " + str(self.smetrics[k]) return rv def readserverthresholds(filename): if filename is None: return lines = readfile(filename) for l in lines: mval = l.strip().split('=') #print "read line %s" % mval if len(mval) > 1 : thekey = mval[0].strip() theval = mval[1].strip() if thekey in serverthresholds.getkeys(): serverthresholds.setvalue(thekey, float(theval)) # print thekey," = %.2f" % float(theval) def checkserverthreshold(metricval): # print out an alarm if a ServerMetrics value crosses threshold for key in serverthresholds.getkeys(): # print "checking threshold of key = ", key if key == "processorusedcputime": pcpus = metricval.getvalue(key) # print key, pcpus, serverthresholds[key] for ind in range(0, len(pcpus)): # print ind, pcpus[ind] if pcpus[ind] > serverthresholds.getvalue(key): alarm = ["server", os.uname()[1], str(ind) + key, "%.2f" % pcpus[ind], ">", serverthresholds.getvalue(key)] if options.timestamp: print str(time.time()) + ",", print ", ".join(map(lambda(x):str(x), alarm)) else: if metricval.getvalue(key) > serverthresholds.getvalue(key): alarm = ["server", os.uname()[1], key, "%.2f" % metricval.getvalue(key), ">", serverthresholds.getvalue(key)] if options.timestamp: print str(time.time()) + ",", print ", ".join(map(lambda(x):str(x), alarm)) def collectservercputimes(): # return cpu times in ticks of this server total and each processor 3*(1+#cpu) columns # (user+nice, sys, idle) from each /proc/stat cpu lines assume columns are: # cpu# user nice sys idle iowait irq softirq steal guest (man 5 proc) rval = {} lines = readfile("/proc/stat") for i in range(ncpus + 1): items = lines[i].split() (user, nice, sys, idle) = map(lambda(x): int(x), items[1:5]) rval[i] = [user+nice, sys, idle] return rval def csvservercputimes(cputimes): # return a csv string of this server total and each processor's cpu times # (usr, sys, idle) in ticks rval = '' for i in range(len(cputimes)): rval += ', '.join(map(lambda(x):str(x), cputimes[i])) return rval def calcservercputimes(cputimea, cputimeb): # return cpu used/total % of this server total and each processor (1+#cpu columns) p = {} for n in range(ncpus + 1): # print cputimeb[n] p[n] = [] for i in range(len(cputimea[n])): p[n].append(cputimeb[n][i] - cputimea[n][i]) # print p[n] total = sum(p[n]) # cpu times total delta # print total if total == 0: p[n] = 0.0 else: p[n] = 100 - ((100.0 * p[n][-1]) / total) return p def collectservermems(): # return memory (total, free) in KB from proc/meminfo lines = readfile("/proc/meminfo") mem = map(lambda(x):x.split(), lines[0:2]) return map(lambda(x):int(x), zip(*mem)[1]) def csvservermems(mems): # return a csv string of this server memory (total, free) return ", ".join(map(lambda x: str(x), mems)) def calcserverusedmem(mems): # return int(100*(MemTotal-MemFree)/MemTotal) from /proc/meminfo return 100 * (mems[0] - mems[1]) / mems[0] def collectservermetrics(cputimes, mems, thresholdcheck): # return ServerMetrics object with a dictionary of # loadavg1,loadavg5,loadavg15, usedmem%, usedcpu% for total, cpu1, cpu2, ... metricval = [] ldavgs=os.getloadavg() for v in ldavgs: metricval.append(v) metricval.append(calcserverusedmem(mems)) for i in range(ncpus + 1): metricval.append(cputimes[i]) # print cputimes[i] srvmetrics = ServerMetrics() srvmetrics.setvalues(metricval) # print srvmetrics.tocsv() if thresholdcheck: checkserverthreshold(srvmetrics) return srvmetrics def csvservermetrics(srvmetrics): # return a csv string of ServerMetrics.tocsv() # loadavg1,loadavg5,loadavg15, usedmem%, usedcpu% for total, cpu1, cpu2, ... rv = "" if options.timestamp: rv = str(time.time()) + ", " rv += srvmetrics.tocsv() return rv def csvserverbaseline(): # return a csv string of raw server metrics data: memfree, memtotal, cpuused, cpusystem, cpuidle return "memory (total, free) = " + csvservermems(collectservermems()) + "\ncputime (used, sys, idl) = " + csvservercputimes(collectservercputimes()) class NodeMetrics(object): def __init__(self): self.nmetrics = {"nodethroughput" : 0.0, "nodeusedmemory" : 0.0, "nodetotalcpu" : 0.0, "nodeusercpu" : 0.0, "nodesystemcpu" : 0.0, "nodewaitcpu" : 0.0} # set values from val = (throughput, mem, tcpu, ucpu, scpu, wcpu): def setvalues(self, val): self.nmetrics["nodethroughput"] = val[0] self.nmetrics["nodeusedmemory"] = val[1] self.nmetrics["nodetotalcpu"] = val[2] self.nmetrics["nodeusercpu"] = val[3] self.nmetrics["nodesystemcpu"] = val[4] self.nmetrics["nodewaitcpu"] = val[5] def setvalue(self, key, val): self.nmetrics[key] = val def getvalue(self, key): return self.nmetrics[key] def getkeys(self): return self.nmetrics.keys() def tocsv(self): return ", ".join(map(lambda(x):str(x), self.nmetrics.values())) class LogSession(object): def __init__(self): self.nodethresholds = NodeMetrics() # set node threshold default values: # nodethroughput=20.0, nodeusedmemory=15.0, nodetotalcpu=90.0, # nodeusercpu=30.0, nodewaitcpu=50.0, nodesystemcpu=20.0} self.nodethresholds.setvalues([20.0, 15.0, 90.0, 30.0, 50.0, 20.0]) if options.configfile is not None: self.readnodethresholds(options.configfile) self.pids = {} self.nodemetricsA = {} self.nodemetricsB = {} self.nodemetricsC = {} def getpids(self): # return dict of all CORE session pids in a dict using node name as the keys # parent pid (vnoded) is the first value self.pids = {} nodes = commands.getstatusoutput("ls /tmp/pycore.%s/*pid" % options.session) if nodes[0] != 0: # if options.timestamp == True: # print str(time.time()), # print "CORE session %s has not created nodes" % options.session return nodes = nodes[1].split('\n') for nod in nodes: nodename = nod.split('/')[-1].strip(".pid") self.pids[nodename] = commands.getoutput("cat %s" % nod) # do not expect failure of this command procs = commands.getoutput('ps -eo ppid,pid,comm').split('\n') # build self.pids dict with key=nodename and val="ppid,pid,cmd" for nname in self.pids: # print nname, self.pids[nname] if self.pids[nname] == "": if options.timestamp == True: print str(time.time()), print "ERROR: null vnoded pid of node: %s" % nname else: childprocs = [] ppid = self.pids[nname] for proc in procs: val=proc.split() if ppid == val[1]: childprocs.append([val[1], val[2]] ) if ppid == val[0]: childprocs.append([val[1], val[2]]) self.pids[nname] = childprocs # print nname, self.pids[nname] return self.pids def printsesspids(self): if self.pids == {}: return {} for pp in self.pids: if self.pids[pp] != []: for ap in range(len(self.pids[pp]) - 1): print ", " + self.pids[pp][ap][0], # ap pid print ", " + self.pids[pp][ap][1], # ap cmd procmetrics = map(lambda(x):str(x),self.pids[pp][ap][-1]) print ", " + ", ".join(procmetrics), nodemetrics = map(lambda(x):str(x), self.pids[pp][-1]) print ", " + ", ".join(nodemetrics) def getprocessmetrics(self, pid): # return [cpu#, vsize(kb), ttime, utime, stime, wtime] # from a /proc/pid/stat (a single line file) assume columns are: # pid(0) comm(1) state ppid pgrp sess tty_nr tpgid flags # minflt cmiflt majflt cmajflt # utime(12) stime cutime cstime # priority nice num_threads itrealvalue starttime vsize(22) rss rsslim # startcode endcode startstack kstkesp signal blocked sigignore sigcatch # wchan nswap cnswap exit_signal processor(38) rt_priority # policy ioblock guest_time cguest_time (man 5 proc) #rval = ProcessMetrics() #rval.__init__() rval = {} lines = readfile("/proc/" + pid + "/stat") if lines == []: return rval items = lines[0].split() (utime, stime, cutime, cstime) = map(lambda(x):int(x), items[13:17]) # print ">???", utime, stime, cutime, cstime rval = (items[38], # last run processor int(items[22])/1000, # process virtual mem in kb utime + stime + cutime + cstime,# totoal time utime, # user time stime, # system time cutime + cstime) # wait time # print "pid --- processmetrics", rval return rval def getnodethroughput(self, pid): # return node throughput of total receive and transmit packets in kb lines = readfile("/proc/" + pid + "/net/dev") if lines == []: return -0.00 ifs = map(lambda(x): x.split(), lines[2:]) ifm = zip(*ifs) rv = sum(map(lambda(x):int(x), ifm[1])) # received bytes tr = sum(map(lambda(x):int(x), ifm[9])) # transmited bytes #print 'node thruput :', rv, tr, (rv + tr)/1000 return (rv + tr)/1000 def getnodemetrics(self, mindex): # return NodeMetrics with indexed by nodename, values are rows of # [ [ppid, vnoded, [cpu#, vmem(kb), ttime, utime, stime, wtime]], # [cpid, cmd, [cpu#, vmem(kb), ttime, utime, stime, wtime]], ... , # [thrput, vmem(kb), ttime, utime, stime, wtime]] if mindex == 'a': metricref = self.nodemetricsA else: metricref = self.nodemetricsB self.getpids() # print " inside getnodemetrics()", self.pids if self.pids == {}: return {} for nod in self.pids: nmetric = NodeMetrics() nmetric.__init__() nodeapps = {} for ap in range(len(self.pids[nod])): # get each process metrics procm = self.getprocessmetrics(self.pids[nod][ap][0]) if procm == []: if options.timestamp == True: print str(time.time()), print "WARNING: transient process", self.pids[nod][ap][1], \ "/", self.pids[nod][ap][0], "on node %s" % nod else: nodeapps[ap] = procm self.pids[nod][ap].append(nodeapps[ap]) processm = zip(*nodeapps.values()) # get overall node metrics # print processm if len(processm) > 0: # if nod == 'n6': # print nod, self.getnodethroughput(self.pids[nod][0][0]) nmetric.setvalues(( self.getnodethroughput(self.pids[nod][0][0]), sum(map(lambda(x):int(x), processm[1])), # vsize(kb) sum(map(lambda(x):int(x), processm[2])), # ttime sum(map(lambda(x):int(x), processm[3])), # utime sum(map(lambda(x):int(x), processm[4])), # stime sum(map(lambda(x):int(x), processm[5])))) # wtime metricref[nod] = nmetric # print nod, self.pids[nod][0][0], metricref[nod].tocsv() return metricref def setnodemetricsC(self, key, val): self.nodemetricsC[key] = val def printnodemetrics(self, mindex): if mindex == 'c': mm = self.nodemetricsC else: if mindex == 'a': mm = self.nodemetricsA else: mm = self.nodemetricsB for k in self.nodemetricsC: if options.timestamp: print str(time.time()) + ",", print k, ",", mm[k].tocsv() def readnodethresholds(self, filename): if filename is None: return lines = readfile(filename) for l in lines: mval = l.strip().split('=') # print "read line %s" % mval if len(mval) > 1 : thekey = mval[0].strip() theval = mval[1].strip() if thekey in self.nodethresholds.getkeys(): self.nodethresholds.setvalue(thekey, float(theval)) #print thekey," = %.2f" % float(theval) def checknodethresholds(self, nname): # print "check node thresholds", nname calcm = self.nodemetricsC[nname] for keyname in self.nodethresholds.getkeys(): # print "HIII", keyname, calcm.getvalue(keyname), self.nodethresholds.getvalue(keyname) if float(calcm.getvalue(keyname)) > float(self.nodethresholds.getvalue(keyname)): # print calculatednodem.getvalue(m) alarm = ["node", nname + "/" + self.pids[nname][0][0], keyname,\ calcm.getvalue(keyname), ">", self.nodethresholds.getvalue(keyname)] if options.timestamp: print str(time.time()) + ",", print ", ".join(map(lambda(x):str(x), alarm)) def calcnodemetrics(self, cputimea, cputimeb, mems): # return a dict of nodemetrics indexed by node name # nodemetrics[nodename][-1] = node/host% p = [] for i in range(len(cputimeb[0])): p.append(cputimeb[0][i] - cputimea[0][i]) hostusedcpu = p[0] + p[1] hostusedmem = mems[0] - mems[1] if hostusedcpu == 0: print "WARNING: host used cpu = 0, ", p[0], p[1] hostusedcpu = 1 if hostusedmem == 0: print "WARNING: host used mem = 0, ", mems[0], mems[1] hostusedmem = 1 nodesa = self.nodemetricsA nodesb = self.nodemetricsB for nod in nodesb: calcm = self.nodemetricsC calcm = NodeMetrics() calcm.__init__() if (nod in nodesa): try: if (nodesb[nod] == []) | (nodesa[nod] == []) | \ ( False == isinstance(nodesb[nod], NodeMetrics)) | \ ( False == isinstance(nodesa[nod], NodeMetrics)): if options.timestamp == True: print str(time.time()), print "Warning: nodes %s is not fully instanciated" % nod else: # calc throughput kbps #print "node b : ", nodesb[nod].tocsv() #print "node a : ", nodesa[nod].tocsv() #if nod == 'n6': #print nodesb[nod].getvalue("nodethroughput"), nodesa[nod].getvalue("nodethroughput") calcm.setvalue("nodethroughput", "%.2f" % (8 * (nodesb[nod].getvalue("nodethroughput") \ - nodesa[nod].getvalue("nodethroughput")) / options.interval)) # calc mem node used / host used calcm.setvalue("nodeusedmemory", "%.2f" % (100.0 * (nodesb[nod].getvalue("nodeusedmemory") / hostusedmem))) # calc total cpu time node / host calcm.setvalue("nodetotalcpu", "%.2f" % (100.0 * (nodesb[nod].getvalue("nodetotalcpu")\ - nodesa[nod].getvalue("nodetotalcpu")) /hostusedcpu)) # calc user cpu time node / host calcm.setvalue("nodeusercpu", "%.2f" % (100.0 * (nodesb[nod].getvalue("nodeusercpu")\ - nodesa[nod].getvalue("nodeusercpu")) /hostusedcpu)) # calc system cpu time node / host calcm.setvalue("nodesystemcpu", "%.2f" % (100.0 * (nodesb[nod].getvalue("nodesystemcpu")\ - nodesa[nod].getvalue("nodesystemcpu")) /hostusedcpu)) # calc waitcpu time node / host calcm.setvalue("nodewaitcpu", "%.2f" % (100.0 * (nodesb[nod].getvalue("nodewaitcpu")\ - nodesa[nod].getvalue("nodewaitcpu")) /hostusedcpu)) #print nod, calcm.tocsv() #print '==========================' logsession.nodemetricsC[nod] = calcm # logsession.printnodemetrics('c') if options.alarm is not None: logsession.checknodethresholds(nod) except IndexError: pass else: print "Warning: transient node %s " % nod return nodesb def main(): usagestr = "%prog [-h] [options] [args]\n\nLog server and optional CORE session metrics to stdout." parser = optparse.OptionParser(usage = usagestr) parser.set_defaults(interval=2, timestamp=False, configfile = "/etc/core/perflogserver.conf",\ alarm = True, session = None) parser.add_option("-i", "--interval", dest = "interval", type = int, help = "seconds to wait between samples; default=%s" % parser.defaults["interval"]) parser.add_option("-t", "--timestamp", action = "store_true", dest = "timestamp", help = "include timestamp on each line") parser.add_option("-c", "--configfile", dest = "configfile", type = "string", help = "read threshold values from the specified file;\ default=%s" % parser.defaults["configfile"]) parser.add_option("-a", "--alarm", action = "store_true", dest = "alarm", help = "generate alarms based threshold check on each cycle") parser.add_option("-s", "--session", dest = "session", type = int, help = "CORE session id; default=%s" % parser.defaults["session"]) global options global ncpus global serverthresholds global logsession global cyclecount (options, args) = parser.parse_args() # print options signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGTERM, handler) ncpus = numcpus() # server threshold dictionary - a ServerMetrics instant with default values serverthresholds = ServerMetrics() # set to server threshold default values: serverloadavg1=3.5, # serverloadavg5=3.5, serverloadavg15=3.5, serverusedmemory=80.0, # serverusedcputime=80.0, processorusedcputime=90.0 serverthresholds.setvalues([3.5, 3.5, 3.5, 80.0, 80.0, 90.0]) if options.alarm is True: # read server threshold values from configuration file readserverthresholds(options.configfile) if options.session is not None: logsession = LogSession() # print logsession # mark host log baseline print "server: ", ", ".join(map(lambda(x):str(x), os.uname())), ",", ncpus, "CPU cores" print "start timestamp:", time.time(), ", baseline data: " print csvserverbaseline() print "server metrics: ", ", ".join(map(lambda(x):str(x), serverthresholds.getkeys())) if options.session is not None: print "node metrics: nodename, ", ", ".join(map(lambda(x):str(x), logsession.nodethresholds.getkeys())) cyclecount = 0 while True: cputimea = collectservercputimes() if options.session is not None: nodesa = logsession.getnodemetrics('a') # print "nodes a:", nodesa time.sleep(options.interval) cputimeb = collectservercputimes() mems = collectservermems() calccputime = calcservercputimes(cputimea, cputimeb) m = csvservermetrics(collectservermetrics(calccputime, mems, options.alarm)) print m if options.session is not None: nodesb = logsession.getnodemetrics('b') # print "nodes b:", nodesb if nodesb != {}: logsession.calcnodemetrics(cputimea, cputimeb, mems) logsession.printnodemetrics('c') sys.stdout.flush() cyclecount = cyclecount + 1 if __name__ == "__main__": main() core-4.6/scripts/perf/perflogstart.sh0000664000175000017500000000056511713023241014731 00000000000000#!/bin/sh # (c)2010-2012 the Boeing Company # author: Yueli Yang # # start core performance logging and collect output to file # /tmp/pycore.nnnn/perf.log HOOKS_DIR=`dirname $0` sid=` pwd | awk -F / {'print $3'} | awk -F . {'print $2'} ` python $HOOKS_DIR/perflogserver.py -t -a -c /etc/core/perflogserver.conf -s $sid > perf$sid.log & core-4.6/scripts/perf/configuration_hook.sh0000664000175000017500000000033111654123375016110 00000000000000#!/bin/sh # experiment hook script; write commands here to execute on the host at the # specified state sh /usr/local/share/core/examples/hooks/timesyncstop.sh sh /usr/local/share/core/examples/hooks/perflogstart.sh core-4.6/scripts/perf/perflogstop.sh0000664000175000017500000000051311713023241014552 00000000000000#!/bin/sh # (c)2010-2012 the Boeing Company # author: Yueli Yang # # terminate core perfromance logging process perfproc=` ps aux | grep perflogserver | grep python | awk {'print $2'} ` if [ ! $perfproc = "" ]; then echo "terminating core performance log process $perfproc" kill -9 $perfproc fi core-4.6/scripts/perf/datacollect_hook.sh0000664000175000017500000000042711654361672015532 00000000000000#!/bin/sh # experiment hook script; write commands here to execute on the host at the # specified state sh /usr/local/share/core/examples/hooks/perflogstop.sh sh /usr/local/share/core/examples/hooks/sessiondatacollect.sh sh /usr/local/share/core/examples/hooks/timesyncstart.sh core-4.6/scripts/perf/timesyncstop.sh0000664000175000017500000000272611713023241014757 00000000000000#!/bin/sh # (c)2010-2012 the Boeing Company # author: Yueli Yang # # Stop timesync service. If it was not yet in sync with any ntp server, # adjust its time to the first ntp server in # configured in /etc/ntp.conf # # Usage: sudo sh timesyncstop.sh [deubg] dbg=$1 if [ "$dbg" = "debug" ]; then date +%y%h%d-%T-%N fi svs="" if [ -e /usr/sbin/ntpd ]; then # command "sudo /usr/sbin/ntpd -q -g" will start the ntp service and # keep it on until it performs a good synchronization, then it leaves. # It is not quick enough for our need here /etc/init.d/ntp status if [ $? = 0 ]; then svs=`ntpq -c peers | awk {'print $1'} | grep ^*` if [ "$dbg" = "debug" ]; then ntpq -c peers echo "get time servers for later need: $svs" ntptime echo "terminate ntpd process" fi /etc/init.d/ntp stop fi # if there are time servers configured in file /etc/ntp.conf, # adjust time to the first server if [ "$svs" = "" ]; then svs=`grep ^server /etc/ntp.conf | awk {'print $2'} ` if [ "$dbg" = "debug" ]; then echo "$svs" fi for sv in "$svs"; do ntpdate $sv # may use "sntp -s $sv" or "rdate" if ntpdate is deprecated break done else if [ "$dbg" = "debug" ]; then echo No time adjustment because time sync was stable with $svs fi fi fi if [ "$dbg" = "debug" ]; then date +%y%h%d-%T-%N fi core-4.6/scripts/perf/sessiondatacollect.sh0000664000175000017500000000312211713023241016070 00000000000000#!/bin/sh # (c)2010-2012 the Boeing Company # author: Yueli Yang # # Create a tar ball of the CORE session's runtime folder /tmp/pycore.nnnn # Collection such runtime tar balls from all distributed servers to folder # /tmp/--