Makefile
Makefile.in
-/include/xtables.h
+/include/xtables-version.h
/include/iptables/internal.h
/aclocal.m4
if ENABLE_LIBIPQ
SUBDIRS += libipq
endif
-if HAVE_LIBNFNETLINK
SUBDIRS += utils
-endif
# Depends on libxtables:
SUBDIRS += extensions
# Depends on extensions/libext.a:
tar -C /tmp -cjf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/;
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
+install-data-hook:
+ @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || :
+ @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || :
+
config.status: extensions/GNUmakefile.in \
- include/xtables.h.in include/iptables/internal.h.in
+ include/xtables-version.h.in include/iptables/internal.h.in
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# -*- Makefile -*-
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
host_triplet = @host@
@ENABLE_DEVEL_TRUE@am__append_1 = include
@ENABLE_LIBIPQ_TRUE@am__append_2 = libipq
-@HAVE_LIBNFNETLINK_TRUE@am__append_3 = utils
subdir = .
DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/configure \
$(top_srcdir)/extensions/GNUmakefile.in \
$(top_srcdir)/include/iptables/internal.h.in COPYING INSTALL \
- build-aux/compile build-aux/config.guess build-aux/config.sub \
- build-aux/depcomp build-aux/install-sh build-aux/ltmain.sh \
- build-aux/missing
+ build-aux/ar-lib build-aux/compile build-aux/config.guess \
+ build-aux/config.sub build-aux/depcomp build-aux/install-sh \
+ build-aux/ltmain.sh build-aux/missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
AUTOMAKE_OPTIONS = foreign subdir-objects
# Depends on libxtables:
# Depends on extensions/libext.a:
-SUBDIRS = libiptc libxtables $(am__append_1) $(am__append_2) \
- $(am__append_3) extensions iptables
+SUBDIRS = libiptc libxtables $(am__append_1) $(am__append_2) utils \
+ extensions iptables
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
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 \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
*.zip*) \
unzip $(distdir).zip ;;\
esac
- chmod -R a-w $(distdir); chmod a+w $(distdir)
+ chmod -R a-w $(distdir); chmod u+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
info-am:
install-data-am:
-
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
install-dvi: install-dvi-recursive
install-dvi-am:
uninstall-am:
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
- ctags-recursive install-am install-strip tags-recursive
+ ctags-recursive install-am install-data-am install-strip \
+ tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am am--refresh check check-am clean clean-generic \
dist-zip distcheck distclean distclean-generic distclean-hdr \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck 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 mostlyclean-libtool pdf pdf-am \
- ps ps-am tags tags-recursive uninstall uninstall-am
+ install install-am install-data install-data-am \
+ install-data-hook 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 \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
.PHONY: tarball
tar -C /tmp -cjf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/;
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
+install-data-hook:
+ @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || :
+ @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || :
+
config.status: extensions/GNUmakefile.in \
- include/xtables.h.in include/iptables/internal.h.in
+ include/xtables-version.h.in include/iptables/internal.h.in
# 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.
-# generated automatically by aclocal 1.11.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
[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], [],
+m4_if([$1], [1.11.6], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# 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
+[AM_AUTOMAKE_VERSION([1.11.6])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+# Copyright (C) 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_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed. If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+ [am_cv_ar_interface=ar
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+ [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+ ])
+ ])
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ m4_default([$1],
+ [AC_MSG_ERROR([could not determine $AR interface])])
+ ;;
+esac
+AC_SUBST([AR])dnl
+])
+
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
--- /dev/null
+#! /bin/sh
+# Wrapper for Microsoft lib.exe
+
+me=ar-lib
+scriptversion=2012-03-01.08; # UTC
+
+# Copyright (C) 2010, 2012 Free Software Foundation, Inc.
+# Written by Peter Rosin <peda@lysator.liu.se>.
+#
+# 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, 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, see <http://www.gnu.org/licenses/>.
+
+# 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.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+
+# func_error message
+func_error ()
+{
+ echo "$me: $1" 1>&2
+ exit 1
+}
+
+file_conv=
+
+# func_file_conv build_file
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv in
+ mingw)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_at_file at_file operation archive
+# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
+# for each of them.
+# When interpreting the content of the @FILE, do NOT use func_file_conv,
+# since the user would need to supply preconverted file names to
+# binutils ar, at least for MinGW.
+func_at_file ()
+{
+ operation=$2
+ archive=$3
+ at_file_contents=`cat "$1"`
+ eval set x "$at_file_contents"
+ shift
+
+ for member
+ do
+ $AR -NOLOGO $operation:"$member" "$archive" || exit $?
+ done
+}
+
+case $1 in
+ '')
+ func_error "no command. Try '$0 --help' for more information."
+ ;;
+ -h | --h*)
+ cat <<EOF
+Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
+
+Members may be specified in a file named with @FILE.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "$me, version $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test $# -lt 3; then
+ func_error "you must specify a program, an action and an archive"
+fi
+
+AR=$1
+shift
+while :
+do
+ if test $# -lt 2; then
+ func_error "you must specify a program, an action and an archive"
+ fi
+ case $1 in
+ -lib | -LIB \
+ | -ltcg | -LTCG \
+ | -machine* | -MACHINE* \
+ | -subsystem* | -SUBSYSTEM* \
+ | -verbose | -VERBOSE \
+ | -wx* | -WX* )
+ AR="$AR $1"
+ shift
+ ;;
+ *)
+ action=$1
+ shift
+ break
+ ;;
+ esac
+done
+orig_archive=$1
+shift
+func_file_conv "$orig_archive"
+archive=$file
+
+# strip leading dash in $action
+action=${action#-}
+
+delete=
+extract=
+list=
+quick=
+replace=
+index=
+create=
+
+while test -n "$action"
+do
+ case $action in
+ d*) delete=yes ;;
+ x*) extract=yes ;;
+ t*) list=yes ;;
+ q*) quick=yes ;;
+ r*) replace=yes ;;
+ s*) index=yes ;;
+ S*) ;; # the index is always updated implicitly
+ c*) create=yes ;;
+ u*) ;; # TODO: don't ignore the update modifier
+ v*) ;; # TODO: don't ignore the verbose modifier
+ *)
+ func_error "unknown action specified"
+ ;;
+ esac
+ action=${action#?}
+done
+
+case $delete$extract$list$quick$replace,$index in
+ yes,* | ,yes)
+ ;;
+ yesyes*)
+ func_error "more than one action specified"
+ ;;
+ *)
+ func_error "no action specified"
+ ;;
+esac
+
+if test -n "$delete"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -REMOVE "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+
+elif test -n "$extract"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ if test $# -gt 0; then
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -EXTRACT "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+ else
+ $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
+ do
+ $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
+ done
+ fi
+
+elif test -n "$quick$replace"; then
+ if test ! -f "$orig_archive"; then
+ if test -z "$create"; then
+ echo "$me: creating $orig_archive"
+ fi
+ orig_archive=
+ else
+ orig_archive=$archive
+ fi
+
+ for member
+ do
+ case $1 in
+ @*)
+ func_file_conv "${1#@}"
+ set x "$@" "@$file"
+ ;;
+ *)
+ func_file_conv "$1"
+ set x "$@" "$file"
+ ;;
+ esac
+ shift
+ shift
+ done
+
+ if test -n "$orig_archive"; then
+ $AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
+ else
+ $AR -NOLOGO -OUT:"$archive" "$@" || exit $?
+ fi
+
+elif test -n "$list"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ $AR -NOLOGO -LIST "$archive" || exit $?
+fi
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
-scriptversion=2012-01-04.17; # UTC
+scriptversion=2012-03-05.13; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
# Software Foundation, Inc.
esac
}
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
;;
esac
;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
-l*)
- lib=${1#-l}
- found=no
- save_IFS=$IFS
- IFS=';'
- for dir in $lib_path $LIB
- do
- IFS=$save_IFS
- if $shared && test -f "$dir/$lib.dll.lib"; then
- found=yes
- set x "$@" "$dir/$lib.dll.lib"
- break
- fi
- if test -f "$dir/$lib.lib"; then
- found=yes
- set x "$@" "$dir/$lib.lib"
- break
- fi
- done
- IFS=$save_IFS
-
- test "$found" != yes && set x "$@" "$lib.lib"
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
shift
;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
-L*)
- func_file_conv "${1#-L}"
- if test -z "$lib_path"; then
- lib_path=$file
- else
- lib_path="$lib_path;$file"
- fi
- linker_opts="$linker_opts -LIBPATH:$file"
+ func_cl_dashL "${1#-L}"
;;
-static)
shared=false
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2012-02-10'
+timestamp='2012-04-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
c4x-* | tic4x-*)
os=-coff
;;
+ hexagon-*)
+ os=-elf
+ ;;
tic54x-*)
os=-coff
;;
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
-scriptversion=2011-12-04.11; # UTC
+scriptversion=2012-03-27.16; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
# 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
case $1 in
'')
- echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
Environment variables:
depmode Dependency tracking mode.
- source Source file read by `PROGRAMS ARGS'.
- object Object file output by `PROGRAMS ARGS'.
+ source Source file read by 'PROGRAMS ARGS'.
+ object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
;;
esac
+# A tabulation character.
+tab=' '
+# A newline character.
+nl='
+'
+
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
depmode=msvc7
fi
+if test "$depmode" = xlc; then
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
+ gccflag=-qmakedep=gcc,-MF
+ depmode=gcc
+fi
+
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
- tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'. On the theory
+ tr ' ' "$nl" < "$tmpdepfile" |
+## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
- # the IRIX cc adds comments like `#:fec' to the end of the
+ # the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
- tr ' ' '
-' < "$tmpdepfile" \
+ tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
- tr '
-' ' ' >> "$depfile"
+ tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
- tr ' ' '
-' < "$tmpdepfile" \
+ tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
rm -f "$tmpdepfile"
;;
+xlc)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
- # current directory. Also, the AIX compiler puts `$object:' at the
+ # current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
- # Each line is of the form `foo.o: dependent.h'.
+ # Each line is of the form 'foo.o: dependent.h'.
# Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
+ # '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
;;
icc)
- # Intel's C compiler understands `-MD -MF file'. However on
- # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
+ # However on
+ # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
- # which is wrong. We want:
+ # which is wrong. We want
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
- # and will wrap long lines using \ :
+ # and will wrap long lines using '\':
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
-
+ # tcc 0.9.26 (FIXME still under development at the moment of writing)
+ # will emit a similar output, but also prepend the continuation lines
+ # with horizontal tabulation characters.
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
exit $stat
fi
rm -f "$depfile"
- # Each line is of the form `foo.o: dependent.h',
- # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Each line is of the form 'foo.o: dependent.h',
+ # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
# Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
- # Some versions of the HPUX 10.20 sed can't process this invocation
- # correctly. Breaking it into two sed invocations is a workaround.
- sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
- sed -e 's/$/ :/' >> "$depfile"
+ # '$object: dependent.h' and one to simply 'dependent.h:'.
+ sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
+ < "$tmpdepfile" > "$depfile"
+ sed '
+ s/[ '"$tab"'][ '"$tab"']*/ /g
+ s/^ *//
+ s/ *\\*$//
+ s/^[^:]*: *//
+ /^$/d
+ /:$/d
+ s/$/ :/
+ ' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
- # Add `dependent.h:' lines.
+ # Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
- # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
- # dependencies in `foo.d' instead, so we check for that too.
+ # dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
-s/\(.*\)/ \1 \\/p
+s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
- s/.*/ /
+ s/.*/'"$tab"'/
G
p
}' >> "$depfile"
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
done
test -z "$dashmflag" && dashmflag=-M
- # Require at least two characters before searching for `:'
+ # Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
- # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
- sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
- tr ' ' '
-' < "$tmpdepfile" | \
+ tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
- sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
+ sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
- sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
- echo " " >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+ echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.2
# automake: $automake_version
# autoconf: $autoconf_version
#
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1"
+VERSION="2.4.2 Debian-2.4.2-1.2"
TIMESTAMP=""
package_revision=1.3337
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for iptables 1.4.14.
+# Generated by GNU Autoconf 2.69 for iptables 1.4.19.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Identity of this package.
PACKAGE_NAME='iptables'
PACKAGE_TARNAME='iptables'
-PACKAGE_VERSION='1.4.14'
-PACKAGE_STRING='iptables 1.4.14'
+PACKAGE_VERSION='1.4.19.1'
+PACKAGE_STRING='iptables 1.4.19.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
PKG_CONFIG_LIBDIR
PKG_CONFIG_PATH
PKG_CONFIG
+ENABLE_BPFC_FALSE
+ENABLE_BPFC_TRUE
ENABLE_LIBIPQ_FALSE
ENABLE_LIBIPQ_TRUE
ENABLE_DEVEL_FALSE
DSYMUTIL
MANIFEST_TOOL
RANLIB
-ac_ct_AR
-AR
DLLTOOL
OBJDUMP
LN_S
build_cpu
build
LIBTOOL
+ac_ct_AR
+AR
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
enable_largefile
enable_devel
enable_libipq
+enable_bpf_compiler
with_pkgconfigdir
'
ac_precious_vars='build_alias
# 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 iptables 1.4.14 to adapt to many kinds of systems.
+\`configure' configures iptables 1.4.19.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of iptables 1.4.14:";;
+ short | recursive ) echo "Configuration of iptables 1.4.19.1:";;
esac
cat <<\_ACEOF
--disable-largefile Do not build largefile support
--enable-devel Install Xtables development headers
--enable-libipq Build and install libipq
+ --enable-bpf-compiler Build bpf compiler
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-iptables configure 1.4.14
+iptables configure 1.4.19.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by iptables $as_me 1.4.14, which was
+It was created by iptables $as_me 1.4.19.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# See libtool.info "Libtool's versioning system"
-libxtables_vcurrent=7
+libxtables_vcurrent=10
libxtables_vage=0
ac_aux_dir=
# Define the identity of the package.
PACKAGE='iptables'
- VERSION='1.4.14'
+ VERSION='1.4.19.1'
cat >>confdefs.h <<_ACEOF
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar lib "link -lib"
+ 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_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$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
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar lib "link -lib"
+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_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$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_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ 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
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+$as_echo_n "checking the archiver ($AR) interface... " >&6; }
+if ${am_cv_ar_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_ar_interface=ar
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+$as_echo "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+ ;;
+esac
+
case `pwd` in
*\ * | *\ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
fi
;;
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
-
if test -n "$ac_tool_prefix"; then
for ac_prog in ar
do
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
;;
ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
lt_prog_compiler_static='-non_shared'
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
# old Intel for x86_64 which still supported -KPIC.
ecc*)
esac
;;
-gnu*)
- version_type=linux # correct to gnu/linux during the next big refactor
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
enableval=$enable_libipq;
fi
+# Check whether --enable-bpf-compiler was given.
+if test "${enable_bpf_compiler+set}" = set; then :
+ enableval=$enable_bpf_compiler; enable_bpfc="yes"
+fi
+
# Check whether --with-pkgconfigdir was given.
if test "${with_pkgconfigdir+set}" = set; then :
ENABLE_LIBIPQ_FALSE=
fi
+ if test "$enable_bpfc" = "yes"; then
+ ENABLE_BPFC_TRUE=
+ ENABLE_BPFC_FALSE='#'
+else
+ ENABLE_BPFC_TRUE='#'
+ ENABLE_BPFC_FALSE=
+fi
+
libxtables_vmajor=$(($libxtables_vcurrent - $libxtables_vage));
-ac_config_files="$ac_config_files Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc libipq/Makefile libipq/libipq.pc libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile include/xtables.h include/iptables/internal.h"
+ac_config_files="$ac_config_files Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc libipq/Makefile libipq/libipq.pc libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile include/xtables-version.h include/iptables/internal.h"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
as_fn_error $? "conditional \"ENABLE_LIBIPQ\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${ENABLE_BPFC_TRUE}" && test -z "${ENABLE_BPFC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_BPFC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${HAVE_LIBNFNETLINK_TRUE}" && test -z "${HAVE_LIBNFNETLINK_FALSE}"; then
as_fn_error $? "conditional \"HAVE_LIBNFNETLINK\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by iptables $as_me 1.4.14, which was
+This file was extended by iptables $as_me 1.4.19.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-iptables config.status 1.4.14
+iptables config.status 1.4.19.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
"libiptc/libip6tc.pc") CONFIG_FILES="$CONFIG_FILES libiptc/libip6tc.pc" ;;
"libxtables/Makefile") CONFIG_FILES="$CONFIG_FILES libxtables/Makefile" ;;
"utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;;
- "include/xtables.h") CONFIG_FILES="$CONFIG_FILES include/xtables.h" ;;
+ "include/xtables-version.h") CONFIG_FILES="$CONFIG_FILES include/xtables-version.h" ;;
"include/iptables/internal.h") CONFIG_FILES="$CONFIG_FILES include/iptables/internal.h" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
-AC_INIT([iptables], [1.4.14])
+AC_INIT([iptables], [1.4.19.1])
# See libtool.info "Libtool's versioning system"
-libxtables_vcurrent=7
+libxtables_vcurrent=10
libxtables_vage=0
AC_CONFIG_AUX_DIR([build-aux])
AC_PROG_CC
AM_PROG_CC_C_O
AC_DISABLE_STATIC
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AM_PROG_LIBTOOL
AC_ARG_WITH([kernel],
[enable_devel="$enableval"], [enable_devel="yes"])
AC_ARG_ENABLE([libipq],
AS_HELP_STRING([--enable-libipq], [Build and install libipq]))
+AC_ARG_ENABLE([bpf-compiler],
+ AS_HELP_STRING([--enable-bpf-compiler], [Build bpf compiler]),
+ [enable_bpfc="yes"])
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
AM_CONDITIONAL([ENABLE_LARGEFILE], [test "$enable_largefile" = "yes"])
AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"])
AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"])
+AM_CONDITIONAL([ENABLE_BPFC], [test "$enable_bpfc" = "yes"])
PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
[nfnetlink=1], [nfnetlink=0])
libiptc/Makefile libiptc/libiptc.pc
libiptc/libip4tc.pc libiptc/libip6tc.pc
libxtables/Makefile utils/Makefile
- include/xtables.h include/iptables/internal.h])
+ include/xtables-version.h include/iptables/internal.h])
AC_OUTPUT
--- /dev/null
+# example connlabel.conf mapping file.
+# used by the "connlabel" match to translate names to their bit-value.
+0 eth0-in
+1 eth0-out
+2 ppp-in
+3 ppp-out
+4 bulk-traffic
+5 interactive
/GNUmakefile
/initext.c
/initext?.c
-/matches?.man
-/targets?.man
+/matches.man
+/targets.man
# Wildcard module list
#
pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
+pfx_symlinks := NOTRACK state
@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod})
pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
-pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
+pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks})
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
#
# Building blocks
#
-targets := libext.a libext4.a libext6.a \
- matches4.man matches6.man \
- targets4.man targets6.man
+targets := libext.a libext4.a libext6.a matches.man targets.man
targets_install :=
@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
clean:
- rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext.c initext4.c initext6.c;
+ rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c;
+ rm -f .*.d .*.dd;
distclean: clean
- rm -f .*.d .*.dd;
init%.o: init%.c
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
lib%.oo: ${srcdir}/lib%.c
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
+libxt_NOTRACK.so: libxt_CT.so
+ ln -fs $< $@
+libxt_state.so: libxt_conntrack.so
+ ln -fs $< $@
+
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
xt_RATEEST_LIBADD = -lm
xt_statistic_LIBADD = -lm
-
#
# Static bits
#
${AM_VERBOSE_GEN} \
for ext in $(sort ${1}); do \
f="${srcdir}/libxt_$$ext.man"; \
- cf="${srcdir}/libxt_$$ext.c"; \
- if [ -f "$$f" ] && grep -Eq "$(3)|NFPROTO_UNSPEC" "$$cf"; then \
+ if [ -f "$$f" ]; then \
echo -e "\t+ $$f" >&2; \
echo ".SS $$ext"; \
cat "$$f" || exit $$?; \
- continue; \
fi; \
- f="${srcdir}/lib$(2)t_$$ext.man"; \
+ f="${srcdir}/libip6t_$$ext.man"; \
if [ -f "$$f" ]; then \
echo -e "\t+ $$f" >&2; \
- echo ".SS $$ext"; \
+ echo ".SS $$ext (IPv6-specific)"; \
+ cat "$$f" || exit $$?; \
+ fi; \
+ f="${srcdir}/libipt_$$ext.man"; \
+ if [ -f "$$f" ]; then \
+ echo -e "\t+ $$f" >&2; \
+ echo ".SS $$ext (IPv4-specific)"; \
cat "$$f" || exit $$?; \
- continue; \
fi; \
done >$@;
-matches4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
-
-matches6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
-
-targets4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
+matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
-targets6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
+targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
--- /dev/null
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_DEST = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ O_X_TO_DEST,
+ F_TO_DEST = 1 << O_TO_DEST,
+ F_RANDOM = 1 << O_RANDOM,
+ F_X_TO_DEST = 1 << O_X_TO_DEST,
+};
+
+static void DNAT_help(void)
+{
+ printf(
+"DNAT target options:\n"
+" --to-destination [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+" Address to map destination to.\n"
+"[--random] [--persistent]\n");
+}
+
+static const struct xt_option_entry DNAT_opts[] = {
+ {.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_MULTI},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Ranges expected in network order. */
+static void
+parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
+{
+ char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ const struct in6_addr *ip;
+
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
+
+ start = strchr(arg, '[');
+ if (start == NULL) {
+ start = arg;
+ /* Lets assume one colon is port information. Otherwise its an IPv6 address */
+ colon = strchr(arg, ':');
+ if (colon && strchr(colon+1, ':'))
+ colon = NULL;
+ }
+ else {
+ start++;
+ end = strchr(start, ']');
+ if (end == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid address format");
+
+ *end = '\0';
+ colon = strchr(end + 1, ':');
+ }
+
+ if (colon) {
+ int port;
+
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ port = atoi(colon+1);
+ if (port <= 0 || port > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", colon+1);
+
+ error = strchr(colon+1, ':');
+ if (error)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid port:port syntax - use dash\n");
+
+ dash = strchr(colon, '-');
+ if (!dash) {
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ } else {
+ int maxport;
+
+ maxport = atoi(dash + 1);
+ if (maxport <= 0 || maxport > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", dash+1);
+ if (maxport < port)
+ /* People are stupid. */
+ xtables_error(PARAMETER_PROBLEM,
+ "Port range `%s' funky\n", colon+1);
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ }
+ /* Starts with colon or [] colon? No IP info...*/
+ if (colon == arg || colon == arg+2) {
+ free(arg);
+ return;
+ }
+ *colon = '\0';
+ }
+
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ dash = strchr(start, '-');
+ if (colon && dash && dash > colon)
+ dash = NULL;
+
+ if (dash)
+ *dash = '\0';
+
+ ip = xtables_numeric_to_ip6addr(start);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ start);
+ range->min_addr.in6 = *ip;
+ if (dash) {
+ ip = xtables_numeric_to_ip6addr(dash + 1);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ dash+1);
+ range->max_addr.in6 = *ip;
+ } else
+ range->max_addr = range->min_addr;
+
+ free(arg);
+ return;
+}
+
+static void DNAT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_DEST:
+ if (cb->xflags & F_X_TO_DEST) {
+ if (!kernel_version)
+ get_kernel_version();
+ if (kernel_version > LINUX_VERSION(2, 6, 10))
+ xtables_error(PARAMETER_PROBLEM,
+ "DNAT: Multiple --to-destination not supported");
+ }
+ parse_to(cb->arg, portok, range);
+ break;
+ case O_PERSISTENT:
+ range->flags |= NF_NAT_RANGE_PERSISTENT;
+ break;
+ }
+}
+
+static void DNAT_fcheck(struct xt_fcheck_call *cb)
+{
+ static const unsigned int f = F_TO_DEST | F_RANDOM;
+ struct nf_nat_range *mr = cb->data;
+
+ if ((cb->xflags & f) == f)
+ mr->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+}
+
+static void print_range(const struct nf_nat_range *range)
+{
+ if (range->flags & NF_NAT_RANGE_MAP_IPS) {
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("[");
+ printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
+ if (memcmp(&range->min_addr, &range->max_addr,
+ sizeof(range->min_addr)))
+ printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("]");
+ }
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(":");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ }
+}
+
+static void DNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" to:");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" persistent");
+}
+
+static void DNAT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" --to-destination ");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" --persistent");
+}
+
+static struct xtables_target snat_tg_reg = {
+ .name = "DNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = DNAT_help,
+ .x6_parse = DNAT_parse,
+ .x6_fcheck = DNAT_fcheck,
+ .print = DNAT_print,
+ .save = DNAT_save,
+ .x6_options = DNAT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snat_tg_reg);
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+
+enum {
+ O_SRC_PFX = 1 << 0,
+ O_DST_PFX = 1 << 1,
+};
+
+static const struct xt_option_entry DNPT_options[] = {
+ { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { }
+};
+
+static void DNPT_help(void)
+{
+ printf("DNPT target options:"
+ "\n"
+ " --src-pfx prefix/length\n"
+ " --dst-pfx prefix/length\n"
+ "\n");
+}
+
+static void DNPT_parse(struct xt_option_call *cb)
+{
+ struct ip6t_npt_tginfo *npt = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_PFX:
+ npt->src_pfx = cb->val.haddr;
+ npt->src_pfx_len = cb->val.hlen;
+ break;
+ case O_DST_PFX:
+ npt->dst_pfx = cb->val.haddr;
+ npt->dst_pfx_len = cb->val.hlen;
+ break;
+ }
+}
+
+static void DNPT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct ip6t_npt_tginfo *npt = (const void *)target->data;
+
+ printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ npt->src_pfx_len);
+ printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ npt->dst_pfx_len);
+}
+
+static void DNPT_save(const void *ip, const struct xt_entry_target *target)
+{
+ static const struct in6_addr zero_addr;
+ const struct ip6t_npt_tginfo *info = (const void *)target->data;
+
+ if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
+ info->src_pfx_len != 0)
+ printf("--src-pfx %s/%u ",
+ xtables_ip6addr_to_numeric(&info->src_pfx.in6),
+ info->src_pfx_len);
+ if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
+ info->dst_pfx_len != 0)
+ printf("--dst-pfx %s/%u ",
+ xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
+ info->dst_pfx_len);
+}
+
+static struct xtables_target snpt_tg_reg = {
+ .name = "DNPT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
+ .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
+ .help = DNPT_help,
+ .x6_parse = DNPT_parse,
+ .print = DNPT_print,
+ .save = DNPT_save,
+ .x6_options = DNPT_options,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snpt_tg_reg);
+}
--- /dev/null
+Provides stateless destination IPv6-to-IPv6 Network Prefix Translation (as
+described by RFC 6296).
+.PP
+You have to use this target in the
+.B mangle
+table, not in the
+.B nat
+table. It takes the following options:
+.TP
+\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
+Set source prefix that you want to translate and length
+.TP
+\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
+Set destination prefix that you want to use in the translation and length
+.PP
+You have to use the SNPT target to undo the translation. Example:
+.IP
+ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
+\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
+.IP
+ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
+\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
+.PP
+You may need to enable IPv6 neighbor proxy:
+.IP
+sysctl -w net.ipv6.conf.all.proxy_ndp=1
+.PP
+You also have to use the
+.B NOTRACK
+target to disable connection tracking for translated flows.
then DROP (or REJECT).
.TP
\fB\-\-log\-level\fP \fIlevel\fP
-Level of logging (numeric or see \fIsyslog.conf\fP(5)).
+Level of logging, which can be (system-specific) numeric or a mnemonic.
+Possible values are (in decreasing order of priority): \fBemerg\fP,
+\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP
+or \fBdebug\fP.
.TP
\fB\-\-log\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 29 letters long,
--- /dev/null
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+};
+
+static void MASQUERADE_help(void)
+{
+ printf(
+"MASQUERADE target options:\n"
+" --to-ports <port>[-<port>]\n"
+" Port (range) to map to.\n"
+" --random\n"
+" Randomize source port.\n");
+}
+
+static const struct xt_option_entry MASQUERADE_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Parses ports */
+static void
+parse_ports(const char *arg, struct nf_nat_range *r)
+{
+ char *end;
+ unsigned int port, maxport;
+
+ r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
+
+ switch (*end) {
+ case '\0':
+ r->min_proto.tcp.port
+ = r->max_proto.tcp.port
+ = htons(port);
+ return;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
+ break;
+
+ if (maxport < port)
+ break;
+
+ r->min_proto.tcp.port = htons(port);
+ r->max_proto.tcp.port = htons(maxport);
+ return;
+ default:
+ break;
+ }
+ xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
+}
+
+static void MASQUERADE_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *r = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+ parse_ports(cb->arg, r);
+ break;
+ case O_RANDOM:
+ r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ }
+}
+
+static void
+MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" masq ports: ");
+ printf("%hu", ntohs(r->min_proto.tcp.port));
+ if (r->max_proto.tcp.port != r->min_proto.tcp.port)
+ printf("-%hu", ntohs(r->max_proto.tcp.port));
+ }
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+}
+
+static void
+MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port));
+ if (r->max_proto.tcp.port != r->min_proto.tcp.port)
+ printf("-%hu", ntohs(r->max_proto.tcp.port));
+ }
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+}
+
+static struct xtables_target masquerade_tg_reg = {
+ .name = "MASQUERADE",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = MASQUERADE_help,
+ .x6_parse = MASQUERADE_parse,
+ .print = MASQUERADE_print,
+ .save = MASQUERADE_save,
+ .x6_options = MASQUERADE_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&masquerade_tg_reg);
+}
--- /dev/null
+This target is only valid in the
+.B nat
+table, in the
+.B POSTROUTING
+chain. It should only be used with dynamically assigned IPv6 (dialup)
+connections: if you have a static IP address, you should use the SNAT
+target. Masquerading is equivalent to specifying a mapping to the IP
+address of the interface the packet is going out, but also has the
+effect that connections are
+.I forgotten
+when the interface goes down. This is the correct behavior when the
+next dialup is unlikely to have the same interface address (and hence
+any established connections are lost anyway).
+.TP
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
+This specifies a range of source ports to use, overriding the default
+.B SNAT
+source port-selection heuristics (see above). This is only valid
+if the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+Randomize source port mapping
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized.
+.RS
+.PP
--- /dev/null
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <libiptc/libip6tc.h>
+#include <linux/netfilter/nf_nat.h>
+
+#define MODULENAME "NETMAP"
+
+enum {
+ O_TO = 0,
+};
+
+static const struct xt_option_entry NETMAP_opts[] = {
+ {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND},
+ XTOPT_TABLEEND,
+};
+
+static void NETMAP_help(void)
+{
+ printf(MODULENAME" target options:\n"
+ " --%s address[/mask]\n"
+ " Network address to map to.\n\n",
+ NETMAP_opts[0].name);
+}
+
+static void NETMAP_parse(struct xt_option_call *cb)
+{
+ struct nf_nat_range *range = cb->data;
+ unsigned int i;
+
+ xtables_option_parse(cb);
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ for (i = 0; i < 4; i++) {
+ range->min_addr.ip6[i] = cb->val.haddr.ip6[i] &
+ cb->val.hmask.ip6[i];
+ range->max_addr.ip6[i] = range->min_addr.ip6[i] |
+ ~cb->val.hmask.ip6[i];
+ }
+}
+
+static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+ struct in6_addr a;
+ unsigned int i;
+ int bits;
+
+ a = r->min_addr.in6;
+ printf("%s", xtables_ip6addr_to_numeric(&a));
+ for (i = 0; i < 4; i++)
+ a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]);
+ bits = xtables_ip6mask_to_cidr(&a);
+ if (bits < 0)
+ printf("/%s", xtables_ip6addr_to_numeric(&a));
+ else
+ printf("/%d", bits);
+}
+
+static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
+{
+ printf(" --%s ", NETMAP_opts[0].name);
+ NETMAP_print(ip, target, 0);
+}
+
+static struct xtables_target netmap_tg_reg = {
+ .name = MODULENAME,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = NETMAP_help,
+ .x6_parse = NETMAP_parse,
+ .print = NETMAP_print,
+ .save = NETMAP_save,
+ .x6_options = NETMAP_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&netmap_tg_reg);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+ F_TO_PORTS = 1 << O_TO_PORTS,
+ F_RANDOM = 1 << O_RANDOM,
+};
+
+static void REDIRECT_help(void)
+{
+ printf(
+"REDIRECT target options:\n"
+" --to-ports <port>[-<port>]\n"
+" Port (range) to map to.\n"
+" [--random]\n");
+}
+
+static const struct xt_option_entry REDIRECT_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Parses ports */
+static void
+parse_ports(const char *arg, struct nf_nat_range *range)
+{
+ char *end = "";
+ unsigned int port, maxport;
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
+
+ switch (*end) {
+ case '\0':
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ return;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ break;
+
+ if (maxport < port)
+ break;
+
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ return;
+ default:
+ break;
+ }
+ xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
+}
+
+static void REDIRECT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = (void *)(*cb->target)->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP
+ || entry->ipv6.proto == IPPROTO_UDP
+ || entry->ipv6.proto == IPPROTO_SCTP
+ || entry->ipv6.proto == IPPROTO_DCCP
+ || entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+ parse_ports(cb->arg, range);
+ if (cb->xflags & F_RANDOM)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ case O_RANDOM:
+ if (cb->xflags & F_TO_PORTS)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ }
+}
+
+static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" redir ports ");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ }
+}
+
+static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" --to-ports ");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ }
+}
+
+static struct xtables_target redirect_tg_reg = {
+ .name = "REDIRECT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = REDIRECT_help,
+ .x6_parse = REDIRECT_parse,
+ .print = REDIRECT_print,
+ .save = REDIRECT_save,
+ .x6_options = REDIRECT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&redirect_tg_reg);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_SRC = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ O_X_TO_SRC,
+ F_TO_SRC = 1 << O_TO_SRC,
+ F_RANDOM = 1 << O_RANDOM,
+ F_X_TO_SRC = 1 << O_X_TO_SRC,
+};
+
+static void SNAT_help(void)
+{
+ printf(
+"SNAT target options:\n"
+" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+" Address to map source to.\n"
+"[--random] [--persistent]\n");
+}
+
+static const struct xt_option_entry SNAT_opts[] = {
+ {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_MULTI},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Ranges expected in network order. */
+static void
+parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
+{
+ char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ const struct in6_addr *ip;
+
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
+
+ start = strchr(arg, '[');
+ if (start == NULL) {
+ start = arg;
+ /* Lets assume one colon is port information. Otherwise its an IPv6 address */
+ colon = strchr(arg, ':');
+ if (colon && strchr(colon+1, ':'))
+ colon = NULL;
+ }
+ else {
+ start++;
+ end = strchr(start, ']');
+ if (end == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid address format");
+
+ *end = '\0';
+ colon = strchr(end + 1, ':');
+ }
+
+ if (colon) {
+ int port;
+
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ port = atoi(colon+1);
+ if (port <= 0 || port > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", colon+1);
+
+ error = strchr(colon+1, ':');
+ if (error)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid port:port syntax - use dash\n");
+
+ dash = strchr(colon, '-');
+ if (!dash) {
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ } else {
+ int maxport;
+
+ maxport = atoi(dash + 1);
+ if (maxport <= 0 || maxport > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", dash+1);
+ if (maxport < port)
+ /* People are stupid. */
+ xtables_error(PARAMETER_PROBLEM,
+ "Port range `%s' funky\n", colon+1);
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ }
+ /* Starts with colon or [] colon? No IP info...*/
+ if (colon == arg || colon == arg+2) {
+ free(arg);
+ return;
+ }
+ *colon = '\0';
+ }
+
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ dash = strchr(start, '-');
+ if (colon && dash && dash > colon)
+ dash = NULL;
+
+ if (dash)
+ *dash = '\0';
+
+ ip = xtables_numeric_to_ip6addr(start);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ start);
+ range->min_addr.in6 = *ip;
+ if (dash) {
+ ip = xtables_numeric_to_ip6addr(dash + 1);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ dash+1);
+ range->max_addr.in6 = *ip;
+ } else
+ range->max_addr = range->min_addr;
+
+ free(arg);
+ return;
+}
+
+static void SNAT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_SRC:
+ if (cb->xflags & F_X_TO_SRC) {
+ if (!kernel_version)
+ get_kernel_version();
+ if (kernel_version > LINUX_VERSION(2, 6, 10))
+ xtables_error(PARAMETER_PROBLEM,
+ "SNAT: Multiple --to-source not supported");
+ }
+ parse_to(cb->arg, portok, range);
+ break;
+ case O_PERSISTENT:
+ range->flags |= NF_NAT_RANGE_PERSISTENT;
+ break;
+ }
+}
+
+static void SNAT_fcheck(struct xt_fcheck_call *cb)
+{
+ static const unsigned int f = F_TO_SRC | F_RANDOM;
+ struct nf_nat_range *range = cb->data;
+
+ if ((cb->xflags & f) == f)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+}
+
+static void print_range(const struct nf_nat_range *range)
+{
+ if (range->flags & NF_NAT_RANGE_MAP_IPS) {
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("[");
+ printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
+ if (memcmp(&range->min_addr, &range->max_addr,
+ sizeof(range->min_addr)))
+ printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("]");
+ }
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(":");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ }
+}
+
+static void SNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" to:");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" persistent");
+}
+
+static void SNAT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" --to-source ");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" --persistent");
+}
+
+static struct xtables_target snat_tg_reg = {
+ .name = "SNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = SNAT_help,
+ .x6_parse = SNAT_parse,
+ .x6_fcheck = SNAT_fcheck,
+ .print = SNAT_print,
+ .save = SNAT_save,
+ .x6_options = SNAT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snat_tg_reg);
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+
+enum {
+ O_SRC_PFX = 1 << 0,
+ O_DST_PFX = 1 << 1,
+};
+
+static const struct xt_option_entry SNPT_options[] = {
+ { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { }
+};
+
+static void SNPT_help(void)
+{
+ printf("SNPT target options:"
+ "\n"
+ " --src-pfx prefix/length\n"
+ " --dst-pfx prefix/length\n"
+ "\n");
+}
+
+static void SNPT_parse(struct xt_option_call *cb)
+{
+ struct ip6t_npt_tginfo *npt = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_PFX:
+ npt->src_pfx = cb->val.haddr;
+ npt->src_pfx_len = cb->val.hlen;
+ break;
+ case O_DST_PFX:
+ npt->dst_pfx = cb->val.haddr;
+ npt->dst_pfx_len = cb->val.hlen;
+ break;
+ }
+}
+
+static void SNPT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct ip6t_npt_tginfo *npt = (const void *)target->data;
+
+ printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ npt->src_pfx_len);
+ printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ npt->dst_pfx_len);
+}
+
+static void SNPT_save(const void *ip, const struct xt_entry_target *target)
+{
+ static const struct in6_addr zero_addr;
+ const struct ip6t_npt_tginfo *info = (const void *)target->data;
+
+ if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
+ info->src_pfx_len != 0)
+ printf("--src-pfx %s/%u ",
+ xtables_ip6addr_to_numeric(&info->src_pfx.in6),
+ info->src_pfx_len);
+ if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
+ info->dst_pfx_len != 0)
+ printf("--dst-pfx %s/%u ",
+ xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
+ info->dst_pfx_len);
+}
+
+static struct xtables_target snpt_tg_reg = {
+ .name = "SNPT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
+ .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
+ .help = SNPT_help,
+ .x6_parse = SNPT_parse,
+ .print = SNPT_print,
+ .save = SNPT_save,
+ .x6_options = SNPT_options,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snpt_tg_reg);
+}
--- /dev/null
+Provides stateless source IPv6-to-IPv6 Network Prefix Translation (as described
+by RFC 6296).
+.PP
+You have to use this target in the
+.B mangle
+table, not in the
+.B nat
+table. It takes the following options:
+.TP
+\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
+Set source prefix that you want to translate and length
+.TP
+\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
+Set destination prefix that you want to use in the translation and length
+.PP
+You have to use the DNPT target to undo the translation. Example:
+.IP
+ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
+\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
+.IP
+ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
+\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
+.PP
+You may need to enable IPv6 neighbor proxy:
+.IP
+sysctl -w net.ipv6.conf.all.proxy_ndp=1
+.PP
+You also have to use the
+.B NOTRACK
+target to disable connection tracking for translated flows.
};
#undef s
+static void frag_init(struct xt_entry_match *m)
+{
+ struct ip6t_frag *fraginfo = (void *)m->data;
+
+ fraginfo->ids[1] = ~0U;
+}
+
static void frag_parse(struct xt_option_call *cb)
{
struct ip6t_frag *fraginfo = cb->data;
.size = XT_ALIGN(sizeof(struct ip6t_frag)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
.help = frag_help,
+ .init = frag_init,
.print = frag_print,
.save = frag_save,
.x6_parse = frag_parse,
#include <iptables.h> /* get_kernel_version */
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_DEST = 0,
struct ipt_natinfo
{
struct xt_entry_target t;
- struct nf_nat_multi_range mr;
+ struct nf_nat_ipv4_multi_range_compat mr;
};
static void DNAT_help(void)
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
{
unsigned int size;
static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
- struct nf_nat_range range;
+ struct nf_nat_ipv4_range range;
char *arg, *colon, *dash, *error;
const struct in_addr *ip;
xtables_error(PARAMETER_PROBLEM,
"Need TCP, UDP, SCTP or DCCP with port specification");
- range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
*colon = '\0';
}
- range.flags |= IP_NAT_RANGE_MAP_IPS;
+ range.flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (colon && dash && dash > colon)
dash = NULL;
cb->xflags |= F_X_TO_DEST;
break;
case O_PERSISTENT:
- info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
+ info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
break;
}
}
static void DNAT_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_DEST | F_RANDOM;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if ((cb->xflags & f) == f)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
-static void print_range(const struct nf_nat_range *r)
+static void print_range(const struct nf_nat_ipv4_range *r)
{
- if (r->flags & IP_NAT_RANGE_MAP_IPS) {
+ if (r->flags & NF_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(":");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf(" to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
}
for (i = 0; i < info->mr.rangesize; i++) {
printf(" --to-destination ");
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
}
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = DNAT_help,
.x6_parse = DNAT_parse,
.x6_fcheck = DNAT_fcheck,
then DROP (or REJECT).
.TP
\fB\-\-log\-level\fP \fIlevel\fP
-Level of logging (numeric or see \fIsyslog.conf\fP(5)).
+Level of logging, which can be (system-specific) numeric or a mnemonic.
+Possible values are (in decreasing order of priority): \fBemerg\fP,
+\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP
+or \fBdebug\fP.
.TP
\fB\-\-log\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 29 letters long,
#include <xtables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_PORTS = 0,
static void MASQUERADE_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
/* Parses ports */
static void
-parse_ports(const char *arg, struct nf_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
{
char *end;
unsigned int port, maxport;
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
{
const struct ipt_entry *entry = cb->xt_entry;
int portok;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
parse_ports(cb->arg, mr);
break;
case O_RANDOM:
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
}
}
MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" masq ports: ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
}
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
}
static void
MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" --to-ports %hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
}
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
}
.name = "MASQUERADE",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = MASQUERADE_help,
.init = MASQUERADE_init,
.x6_parse = MASQUERADE_parse,
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
#define MODULENAME "NETMAP"
static void NETMAP_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
static void NETMAP_parse(struct xt_option_call *cb)
{
- struct nf_nat_multi_range *mr = cb->data;
- struct nf_nat_range *range = &mr->range[0];
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
+ struct nf_nat_ipv4_range *range = &mr->range[0];
xtables_option_parse(cb);
- range->flags |= IP_NAT_RANGE_MAP_IPS;
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
range->max_ip = range->min_ip | ~cb->val.hmask.ip;
}
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
struct in_addr a;
int bits;
.name = MODULENAME,
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = NETMAP_help,
.init = NETMAP_init,
.x6_parse = NETMAP_parse,
#include <xtables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_PORTS = 0,
static void REDIRECT_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
/* Parses ports */
static void
-parse_ports(const char *arg, struct nf_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
{
char *end = "";
unsigned int port, maxport;
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
(port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
static void REDIRECT_parse(struct xt_option_call *cb)
{
const struct ipt_entry *entry = cb->xt_entry;
- struct nf_nat_multi_range *mr = (void *)(*cb->target)->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (void *)(*cb->target)->data;
int portok;
if (entry->ip.proto == IPPROTO_TCP
"Need TCP, UDP, SCTP or DCCP with port specification");
parse_ports(cb->arg, mr);
if (cb->xflags & F_RANDOM)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
case O_RANDOM:
if (cb->xflags & F_TO_PORTS)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
}
}
static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" redir ports ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
- if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
}
}
static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" --to-ports ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
- if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
}
}
.name = "REDIRECT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = REDIRECT_help,
.init = REDIRECT_init,
.x6_parse = REDIRECT_parse,
#include <string.h>
#include <stdlib.h>
#include <xtables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter_ipv4/ipt_SAME.h>
enum {
};
/* Parses range of IPs */
-static void parse_to(const char *orig_arg, struct nf_nat_range *range)
+static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range)
{
char *dash, *arg;
const struct in_addr *ip;
arg = strdup(orig_arg);
if (arg == NULL)
xtables_error(RESOURCE_PROBLEM, "strdup");
- range->flags |= IP_NAT_RANGE_MAP_IPS;
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (dash)
static void SAME_parse(struct xt_option_call *cb)
{
struct ipt_same_info *mr = cb->data;
+ unsigned int count;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_NODST:
mr->info |= IPT_SAME_NODST;
break;
+ case O_RANDOM:
+ for (count=0; count < mr->rangesize; count++)
+ mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
}
}
if ((cb->xflags & f) == f)
for (count = 0; count < mr->rangesize; ++count)
- mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
static void SAME_print(const void *ip, const struct xt_entry_target *target,
printf(" same:");
for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_range *r = &mr->range[count];
+ const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
int random_selection = 0;
for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_range *r = &mr->range[count];
+ const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
#include <iptables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_SRC = 0,
struct ipt_natinfo
{
struct xt_entry_target t;
- struct nf_nat_multi_range mr;
+ struct nf_nat_ipv4_multi_range_compat mr;
};
static void SNAT_help(void)
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
{
unsigned int size;
static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
- struct nf_nat_range range;
+ struct nf_nat_ipv4_range range;
char *arg, *colon, *dash, *error;
const struct in_addr *ip;
xtables_error(PARAMETER_PROBLEM,
"Need TCP, UDP, SCTP or DCCP with port specification");
- range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
*colon = '\0';
}
- range.flags |= IP_NAT_RANGE_MAP_IPS;
+ range.flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (colon && dash && dash > colon)
dash = NULL;
cb->xflags |= F_X_TO_SRC;
break;
case O_PERSISTENT:
- info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
+ info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
break;
}
}
static void SNAT_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_SRC | F_RANDOM;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if ((cb->xflags & f) == f)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
-static void print_range(const struct nf_nat_range *r)
+static void print_range(const struct nf_nat_ipv4_range *r)
{
- if (r->flags & IP_NAT_RANGE_MAP_IPS) {
+ if (r->flags & NF_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(":");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf(" to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
}
for (i = 0; i < info->mr.rangesize; i++) {
printf(" --to-source ");
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
}
.name = "SNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = SNAT_help,
.x6_parse = SNAT_parse,
.x6_fcheck = SNAT_fcheck,
.B nat
table, in the
.B POSTROUTING
-chain. It specifies that the source address of the packet should be
+and
+.B INPUT
+chains, and user-defined chains which are only called from those
+chains. It specifies that the source address of the packet should be
modified (and all future packets in this connection will also be
mangled), and rules should cease being examined. It takes one type
of option:
Gives a client the same source-/destination-address for each connection.
This supersedes the SAME target. Support for persistent mappings is available
from 2.6.29-rc2.
+.PP
+Kernels prior to 2.6.36-rc1 don't have the ability to
+.B SNAT
+in the
+.B INPUT
+chain.
printf(" --zone %u", info->zone);
}
+static void notrack_ct0_tg_init(struct xt_entry_target *target)
+{
+ struct xt_ct_target_info *info = (void *)target->data;
+
+ info->flags = XT_CT_NOTRACK;
+}
+
+static void notrack_ct1_tg_init(struct xt_entry_target *target)
+{
+ struct xt_ct_target_info_v1 *info = (void *)target->data;
+
+ info->flags = XT_CT_NOTRACK;
+}
+
static struct xtables_target ct_target_reg[] = {
{
.family = NFPROTO_UNSPEC,
.x6_parse = ct_parse_v1,
.x6_options = ct_opts_v1,
},
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "NOTRACK",
+ .real_name = "CT",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
+ .userspacesize = offsetof(struct xt_ct_target_info, ct),
+ .init = notrack_ct0_tg_init,
+ },
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "NOTRACK",
+ .real_name = "CT",
+ .revision = 1,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
+ .userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
+ .init = notrack_ct1_tg_init,
+ },
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "NOTRACK",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ },
};
void _init(void)
--- /dev/null
+/*
+ * (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
+ * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Description: shared library add-on to iptables to add HMARK target support
+ *
+ * Initial development by Hans Schillstrom. Pablo's improvements to this piece
+ * of software has been sponsored by Sophos Astaro <http://www.sophos.com>.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xtables.h"
+#include <linux/netfilter/xt_HMARK.h>
+
+static void HMARK_help(void)
+{
+ printf(
+"HMARK target options, i.e. modify hash calculation by:\n"
+" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n"
+" --hmark-mod value nfmark modulus value\n"
+" --hmark-offset value Last action add value to nfmark\n\n"
+" --hmark-rnd Random see for hashing\n"
+" Alternatively, fine tuning of what will be included in hash calculation\n"
+" --hmark-src-prefix length Source address mask CIDR prefix\n"
+" --hmark-dst-prefix length Dest address mask CIDR prefix\n"
+" --hmark-sport-mask value Mask src port with value\n"
+" --hmark-dport-mask value Mask dst port with value\n"
+" --hmark-spi-mask value For esp and ah AND spi with value\n"
+" --hmark-sport value OR src port with value\n"
+" --hmark-dport value OR dst port with value\n"
+" --hmark-spi value For esp and ah OR spi with value\n"
+" --hmark-proto-mask value Mask Protocol with value\n");
+}
+
+#define hi struct xt_hmark_info
+
+enum {
+ O_HMARK_SADDR_MASK,
+ O_HMARK_DADDR_MASK,
+ O_HMARK_SPI,
+ O_HMARK_SPI_MASK,
+ O_HMARK_SPORT,
+ O_HMARK_DPORT,
+ O_HMARK_SPORT_MASK,
+ O_HMARK_DPORT_MASK,
+ O_HMARK_PROTO_MASK,
+ O_HMARK_RND,
+ O_HMARK_MODULUS,
+ O_HMARK_OFFSET,
+ O_HMARK_CT,
+ O_HMARK_TYPE,
+};
+
+#define HMARK_OPT_PKT_MASK \
+ ((1 << O_HMARK_SADDR_MASK) | \
+ (1 << O_HMARK_DADDR_MASK) | \
+ (1 << O_HMARK_SPI_MASK) | \
+ (1 << O_HMARK_SPORT_MASK) | \
+ (1 << O_HMARK_DPORT_MASK) | \
+ (1 << O_HMARK_PROTO_MASK) | \
+ (1 << O_HMARK_SPI_MASK) | \
+ (1 << O_HMARK_SPORT) | \
+ (1 << O_HMARK_DPORT) | \
+ (1 << O_HMARK_SPI))
+
+static const struct xt_option_entry HMARK_opts[] = {
+ { .name = "hmark-tuple",
+ .type = XTTYPE_STRING,
+ .id = O_HMARK_TYPE,
+ },
+ { .name = "hmark-src-prefix",
+ .type = XTTYPE_PLENMASK,
+ .id = O_HMARK_SADDR_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask)
+ },
+ { .name = "hmark-dst-prefix",
+ .type = XTTYPE_PLENMASK,
+ .id = O_HMARK_DADDR_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask)
+ },
+ { .name = "hmark-sport-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_SPORT_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
+ },
+ { .name = "hmark-dport-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_DPORT_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
+ },
+ { .name = "hmark-spi-mask",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_SPI_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
+ },
+ { .name = "hmark-sport",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_SPORT,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
+ },
+ { .name = "hmark-dport",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_DPORT,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
+ },
+ { .name = "hmark-spi",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_SPI,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
+ },
+ { .name = "hmark-proto-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_PROTO_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask)
+ },
+ { .name = "hmark-rnd",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_RND,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
+ },
+ { .name = "hmark-mod",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_MODULUS,
+ .min = 1,
+ .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus)
+ },
+ { .name = "hmark-offset",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_OFFSET,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset)
+ },
+ XTOPT_TABLEEND,
+};
+
+static int
+hmark_parse(const char *type, size_t len, struct xt_hmark_info *info,
+ unsigned int *xflags)
+{
+ if (strncasecmp(type, "ct", len) == 0) {
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ *xflags |= (1 << O_HMARK_CT);
+ } else if (strncasecmp(type, "src", len) == 0) {
+ memset(&info->src_mask, 0xff, sizeof(info->src_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
+ *xflags |= (1 << O_HMARK_SADDR_MASK);
+ } else if (strncasecmp(type, "dst", len) == 0) {
+ memset(&info->dst_mask, 0xff, sizeof(info->dst_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
+ *xflags |= (1 << O_HMARK_DADDR_MASK);
+ } else if (strncasecmp(type, "sport", len) == 0) {
+ memset(&info->port_mask.p16.src, 0xff,
+ sizeof(info->port_mask.p16.src));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
+ *xflags |= (1 << O_HMARK_SPORT_MASK);
+ } else if (strncasecmp(type, "dport", len) == 0) {
+ memset(&info->port_mask.p16.dst, 0xff,
+ sizeof(info->port_mask.p16.dst));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
+ *xflags |= (1 << O_HMARK_DPORT_MASK);
+ } else if (strncasecmp(type, "proto", len) == 0) {
+ memset(&info->proto_mask, 0xff, sizeof(info->proto_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
+ *xflags |= (1 << O_HMARK_PROTO_MASK);
+ } else if (strncasecmp(type, "spi", len) == 0) {
+ memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
+ *xflags |= (1 << O_HMARK_SPI_MASK);
+ } else
+ return 0;
+
+ return 1;
+}
+
+static void
+hmark_parse_type(struct xt_option_call *cb)
+{
+ const char *arg = cb->arg;
+ struct xt_hmark_info *info = cb->data;
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg ||
+ !hmark_parse(arg, comma-arg, info, &cb->xflags))
+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
+ arg = comma+1;
+ }
+ if (!*arg)
+ xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires "
+ "a list of types with no "
+ "spaces, e.g. "
+ "src,dst,sport,dport,proto");
+ if (strlen(arg) == 0 ||
+ !hmark_parse(arg, strlen(arg), info, &cb->xflags))
+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
+}
+
+static void HMARK_parse(struct xt_option_call *cb, int plen)
+{
+ struct xt_hmark_info *info = cb->data;
+
+ xtables_option_parse(cb);
+
+ switch (cb->entry->id) {
+ case O_HMARK_TYPE:
+ hmark_parse_type(cb);
+ break;
+ case O_HMARK_SADDR_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
+ break;
+ case O_HMARK_DADDR_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
+ break;
+ case O_HMARK_SPI:
+ info->port_set.v32 = htonl(cb->val.u32);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI);
+ break;
+ case O_HMARK_SPORT:
+ info->port_set.p16.src = htons(cb->val.u16);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
+ break;
+ case O_HMARK_DPORT:
+ info->port_set.p16.dst = htons(cb->val.u16);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
+ break;
+ case O_HMARK_SPORT_MASK:
+ info->port_mask.p16.src = htons(cb->val.u16);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
+ break;
+ case O_HMARK_DPORT_MASK:
+ info->port_mask.p16.dst = htons(cb->val.u16);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
+ break;
+ case O_HMARK_SPI_MASK:
+ info->port_mask.v32 = htonl(cb->val.u32);
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
+ break;
+ case O_HMARK_PROTO_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
+ break;
+ case O_HMARK_RND:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
+ break;
+ case O_HMARK_MODULUS:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
+ break;
+ case O_HMARK_OFFSET:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
+ break;
+ case O_HMARK_CT:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ break;
+ }
+ cb->xflags |= (1 << cb->entry->id);
+}
+
+static void HMARK_ip4_parse(struct xt_option_call *cb)
+{
+ HMARK_parse(cb, 32);
+}
+static void HMARK_ip6_parse(struct xt_option_call *cb)
+{
+ HMARK_parse(cb, 128);
+}
+
+static void HMARK_check(struct xt_fcheck_call *cb)
+{
+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
+ if (!(cb->xflags & (1 << O_HMARK_RND)))
+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
+ if (cb->xflags & (1 << O_HMARK_SPI_MASK) &&
+ (cb->xflags & ((1 << O_HMARK_SPORT_MASK) |
+ (1 << O_HMARK_DPORT_MASK))))
+ xtables_error(PARAMETER_PROBLEM, "you cannot use "
+ "--hmark-spi-mask and --hmark-?port-mask,"
+ "at the same time");
+ if (!((cb->xflags & HMARK_OPT_PKT_MASK) ||
+ cb->xflags & (1 << O_HMARK_CT)))
+ xtables_error(PARAMETER_PROBLEM, "you have to specify "
+ "--hmark-tuple at least");
+}
+
+static void HMARK_print(const struct xt_hmark_info *info)
+{
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
+ printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
+ printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
+ printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
+ printf("sport 0x%x ", htons(info->port_set.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
+ printf("dport 0x%x ", htons(info->port_set.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
+ printf("spi 0x%x ", htonl(info->port_set.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
+ printf("proto-mask 0x%x ", info->proto_mask);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
+ printf("rnd 0x%x ", info->hashrnd);
+}
+
+static void HMARK_ip6_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+
+ printf(" HMARK ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf("mod %u ", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf("+ 0x%x ", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf("ct, ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
+ printf("src-prefix %s ",
+ xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
+ printf("dst-prefix %s ",
+ xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1);
+ HMARK_print(info);
+}
+static void HMARK_ip4_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+
+ printf(" HMARK ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf("mod %u ", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf("+ 0x%x ", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf("ct, ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
+ printf("src-prefix %u ",
+ xtables_ipmask_to_cidr(&info->src_mask.in));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
+ printf("dst-prefix %u ",
+ xtables_ipmask_to_cidr(&info->dst_mask.in));
+ HMARK_print(info);
+}
+
+static void HMARK_save(const struct xt_hmark_info *info)
+{
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
+ printf(" --hmark-sport-mask 0x%04x",
+ htons(info->port_mask.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
+ printf(" --hmark-dport-mask 0x%04x",
+ htons(info->port_mask.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
+ printf(" --hmark-spi-mask 0x%08x",
+ htonl(info->port_mask.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
+ printf(" --hmark-sport 0x%04x",
+ htons(info->port_set.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
+ printf(" --hmark-dport 0x%04x",
+ htons(info->port_set.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
+ printf(" --hmark-spi 0x%08x", htonl(info->port_set.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
+ printf(" --hmark-proto-mask 0x%02x", info->proto_mask);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
+ printf(" --hmark-rnd 0x%08x", info->hashrnd);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf(" --hmark-mod %u", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf(" --hmark-offset %u", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf(" --hmark-tuple ct");
+}
+
+static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+ int ret;
+
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
+ ret = xtables_ip6mask_to_cidr(&info->src_mask.in6);
+ printf(" --hmark-src-prefix %d", ret);
+ }
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
+ ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6);
+ printf(" --hmark-dst-prefix %d", ret);
+ }
+ HMARK_save(info);
+}
+
+static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+ int ret;
+
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
+ ret = xtables_ipmask_to_cidr(&info->src_mask.in);
+ printf(" --hmark-src-prefix %d", ret);
+ }
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
+ ret = xtables_ipmask_to_cidr(&info->dst_mask.in);
+ printf(" --hmark-dst-prefix %d", ret);
+ }
+ HMARK_save(info);
+}
+
+static struct xtables_target mark_tg_reg[] = {
+ {
+ .family = NFPROTO_IPV4,
+ .name = "HMARK",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .help = HMARK_help,
+ .print = HMARK_ip4_print,
+ .save = HMARK_ip4_save,
+ .x6_parse = HMARK_ip4_parse,
+ .x6_fcheck = HMARK_check,
+ .x6_options = HMARK_opts,
+ },
+ {
+ .family = NFPROTO_IPV6,
+ .name = "HMARK",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .help = HMARK_help,
+ .print = HMARK_ip6_print,
+ .save = HMARK_ip6_save,
+ .x6_parse = HMARK_ip6_parse,
+ .x6_fcheck = HMARK_check,
+ .x6_options = HMARK_opts,
+ },
+};
+
+void _init(void)
+{
+ xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
+}
--- /dev/null
+Like MARK, i.e. set the fwmark, but the mark is calculated from hashing
+packet selector at choice. You have also to specify the mark range and,
+optionally, the offset to start from. ICMP error messages are inspected
+and used to calculate the hashing.
+.PP
+Existing options are:
+.TP
+\fB\-\-hmark\-tuple\fP tuple\fI\fP
+Possible tuple members are:
+.B src
+meaning source address (IPv4, IPv6 address),
+.B dst
+meaning destination address (IPv4, IPv6 address),
+.B sport
+meaning source port (TCP, UDP, UDPlite, SCTP, DCCP),
+.B dport
+meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP),
+.B spi
+meaning Security Parameter Index (AH, ESP), and
+.B ct
+meaning the usage of the conntrack tuple instead of the packet selectors.
+.TP
+\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP
+Modulus for hash calculation (to limit the range of possible marks)
+.TP
+\fB\-\-hmark\-offset\fP \fIvalue\fP
+Offset to start marks from.
+.TP
+For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom
+prefixes and masks:
+.TP
+\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP
+The source address mask in CIDR notation.
+.TP
+\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP
+The destination address mask in CIDR notation.
+.TP
+\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP
+A 16 bit source port mask in hexadecimal.
+.TP
+\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP
+A 16 bit destination port mask in hexadecimal.
+.TP
+\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
+A 32 bit field with spi mask.
+.TP
+\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
+An 8 bit field with layer 4 protocol number.
+.TP
+\fB\-\-hmark\-rnd\fP \fIvalue\fP
+A 32 bit random custom value to feed hash calculation.
+.PP
+\fIExamples:\fP
+.PP
+iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW
+ \-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000
+\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe
+.PP
+iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark\-offset 10000
+\-\-hmark-tuple src,dst,proto \-\-hmark-mod 10 \-\-hmark\-rnd 0xdeafbeef
static void LED_parse(struct xt_option_call *cb)
{
struct xt_led_info *led = cb->data;
+ unsigned int delay;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_LED_DELAY:
if (strncasecmp(cb->arg, "inf", 3) == 0)
led->delay = -1;
- else
- led->delay = strtoul(cb->arg, NULL, 0);
+ else if (!xtables_strtoui(cb->arg, NULL, &delay, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Delay value must be within range 0..%u",
+ UINT32_MAX);
break;
case O_LED_ALWAYS_BLINK:
led->always_blink = 1;
.TP
\fB\-\-queue\-bypass\fP
By default, if no userspace program is listening on an NFQUEUE, then all packets that are to be queued
-are dropped. When this option is used, the NFQUEUE rule is silently bypassed instead. The packet
-will move on to the next rule.
+are dropped. When this option is used, the NFQUEUE rule behaves like ACCEPT instead, and the packet
+will move on to the next table.
+++ /dev/null
-/* Shared library add-on to iptables to add NOTRACK target support. */
-#include <xtables.h>
-
-static struct xtables_target notrack_target = {
- .family = NFPROTO_UNSPEC,
- .name = "NOTRACK",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(0),
- .userspacesize = XT_ALIGN(0),
-};
-
-void _init(void)
-{
- xtables_register_target(¬rack_target);
-}
This target disables connection tracking for all packets matching that rule.
-.PP
-It can only be used in the
-.B raw
-table.
+It is obsoleted by \-j CT \-\-notrack. Like CT, NOTRACK can only be used in
+the \fBraw\fP table.
-This modules adds and/or deletes entries from IP sets which can be defined
+This module adds and/or deletes entries from IP sets which can be defined
by ipset(8).
.TP
\fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
-add the address(es)/port(s) of the packet to the sets
+add the address(es)/port(s) of the packet to the set
.TP
\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
-delete the address(es)/port(s) of the packet from the sets
+delete the address(es)/port(s) of the packet from the set
.IP
-where flags are
+where \fIflag\fP(s) are
.BR "src"
and/or
.BR "dst"
specifications and there can be no more than six of them.
.TP
\fB\-\-timeout\fP \fIvalue\fP
-when adding entry, the timeout value to use instead of the default
+when adding an entry, the timeout value to use instead of the default
one from the set definition
.TP
\fB\-\-exist\fP
-when adding entry if it already exists, reset the timeout value
+when adding an entry if it already exists, reset the timeout value
to the specified one or to the default from the set definition
.PP
Use of -j SET requires that ipset kernel support is provided, which, for
" [!] --src-type type[,...] Match source address type\n"
" [!] --dst-type type[,...] Match destination address type\n"
" --limit-iface-in Match only on the packet's incoming device\n"
-" --limit-iface-out Match only on the packet's incoming device\n"
+" --limit-iface-out Match only on the packet's outgoing device\n"
"\n"
"Valid types: \n");
addrtype_help_types();
--- /dev/null
+/*
+ * Xtables BPF extension
+ *
+ * Written by Willem de Bruijn (willemb@google.com)
+ * Copyright Google, Inc. 2013
+ * Licensed under the GNU General Public License version 2 (GPLv2)
+*/
+
+#include <linux/netfilter/xt_bpf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <xtables.h>
+
+#define BCODE_FILE_MAX_LEN_B 1024
+
+enum {
+ O_BCODE_STDIN = 0,
+};
+
+static void bpf_help(void)
+{
+ printf(
+"bpf match options:\n"
+"--bytecode <program> : a bpf program as generated by\n"
+" `nfbpf_compiler RAW <filter>`\n");
+}
+
+static const struct xt_option_entry bpf_opts[] = {
+ {.name = "bytecode", .id = O_BCODE_STDIN, .type = XTTYPE_STRING},
+ XTOPT_TABLEEND,
+};
+
+static void bpf_parse_string(struct xt_option_call *cb, const char *bpf_program,
+ const char separator)
+{
+ struct xt_bpf_info *bi = (void *) cb->data;
+ const char *token;
+ char sp;
+ int i;
+
+ /* parse head: length. */
+ if (sscanf(bpf_program, "%hu%c", &bi->bpf_program_num_elem, &sp) != 2 ||
+ sp != separator)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: error parsing program length");
+ if (!bi->bpf_program_num_elem)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: illegal zero length program");
+ if (bi->bpf_program_num_elem > XT_BPF_MAX_NUM_INSTR)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: number of instructions exceeds maximum");
+
+ /* parse instructions. */
+ i = 0;
+ token = bpf_program;
+ while ((token = strchr(token, separator)) && (++token)[0]) {
+ if (i >= bi->bpf_program_num_elem)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: real program length exceeds"
+ " the encoded length parameter");
+ if (sscanf(token, "%hu %hhu %hhu %u,",
+ &bi->bpf_program[i].code,
+ &bi->bpf_program[i].jt,
+ &bi->bpf_program[i].jf,
+ &bi->bpf_program[i].k) != 4)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: error at instr %d", i);
+ i++;
+ }
+
+ if (i != bi->bpf_program_num_elem)
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: parsed program length is less than the"
+ " encoded length parameter");
+}
+
+static void bpf_parse(struct xt_option_call *cb)
+{
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_BCODE_STDIN:
+ bpf_parse_string(cb, cb->arg, ',');
+ break;
+ default:
+ xtables_error(PARAMETER_PROBLEM, "bpf: unknown option");
+ }
+}
+
+static void bpf_print_code(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_bpf_info *info = (void *) match->data;
+ int i;
+
+ for (i = 0; i < info->bpf_program_num_elem-1; i++)
+ printf("%hu %hhu %hhu %u,", info->bpf_program[i].code,
+ info->bpf_program[i].jt,
+ info->bpf_program[i].jf,
+ info->bpf_program[i].k);
+
+ printf("%hu %hhu %hhu %u", info->bpf_program[i].code,
+ info->bpf_program[i].jt,
+ info->bpf_program[i].jf,
+ info->bpf_program[i].k);
+}
+
+static void bpf_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_bpf_info *info = (void *) match->data;
+
+ printf(" --bytecode \"%hu,", info->bpf_program_num_elem);
+ bpf_print_code(ip, match);
+ printf("\"");
+}
+
+static void bpf_fcheck(struct xt_fcheck_call *cb)
+{
+ if (!(cb->xflags & (1 << O_BCODE_STDIN)))
+ xtables_error(PARAMETER_PROBLEM,
+ "bpf: missing --bytecode parameter");
+}
+
+static void bpf_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ printf("match bpf ");
+ return bpf_print_code(ip, match);
+}
+
+static struct xtables_match bpf_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "bpf",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_bpf_info)),
+ .userspacesize = XT_ALIGN(offsetof(struct xt_bpf_info, filter)),
+ .help = bpf_help,
+ .print = bpf_print,
+ .save = bpf_save,
+ .x6_parse = bpf_parse,
+ .x6_fcheck = bpf_fcheck,
+ .x6_options = bpf_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&bpf_match);
+}
--- /dev/null
+Match using Linux Socket Filter. Expects a BPF program in decimal format. This
+is the format generated by the \fBnfbpf_compile\fP utility.
+.TP
+\fB\-\-bytecode\fP \fIcode\fP
+Pass the BPF byte code format (described in the example below).
+.PP
+The code format is similar to the output of the tcpdump -ddd command: one line
+that stores the number of instructions, followed by one line for each
+instruction. Instruction lines follow the pattern 'u16 u8 u8 u32' in decimal
+notation. Fields encode the operation, jump offset if true, jump offset if
+false and generic multiuse field 'K'. Comments are not supported.
+.PP
+For example, to read only packets matching 'ip proto 6', insert the following,
+without the comments or trailing whitespace:
+.IP
+4 # number of instructions
+.br
+48 0 0 9 # load byte ip->proto
+.br
+21 0 1 6 # jump equal IPPROTO_TCP
+.br
+6 0 0 1 # return pass (non-zero)
+.br
+6 0 0 0 # return fail (zero)
+.PP
+You can pass this filter to the bpf match with the following command:
+.IP
+iptables \-A OUTPUT \-m bpf \-\-bytecode '4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0' \-j ACCEPT
+.PP
+Or instead, you can invoke the nfbpf_compile utility.
+.IP
+iptables \-A OUTPUT \-m bpf \-\-bytecode "`nfbpf_compile RAW 'ip proto 6'`" \-j ACCEPT
+.PP
+You may want to learn more about BPF from FreeBSD's bpf(4) manpage.
--- /dev/null
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_connlabel.h>
+
+enum {
+ O_LABEL = 0,
+ O_SET = 1,
+};
+
+#define CONNLABEL_CFG "/etc/xtables/connlabel.conf"
+
+static void connlabel_mt_help(void)
+{
+ puts(
+"connlabel match options:\n"
+"[!] --label name Match if label has been set on connection\n"
+" --set Set label on connection");
+}
+
+static const struct xt_option_entry connlabel_mt_opts[] = {
+ {.name = "label", .id = O_LABEL, .type = XTTYPE_STRING,
+ .min = 1, .flags = XTOPT_MAND|XTOPT_INVERT},
+ {.name = "set", .id = O_SET, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+static int
+xtables_parse_connlabel_numerical(const char *s, char **end)
+{
+ uintmax_t value;
+
+ if (!xtables_strtoul(s, end, &value, 0, XT_CONNLABEL_MAXBIT))
+ return -1;
+ return value;
+}
+
+static bool is_space_posix(int c)
+{
+ return c == ' ' || c == '\f' || c == '\r' || c == '\t' || c == '\v';
+}
+
+static char * trim_label(char *label)
+{
+ char *end;
+
+ while (is_space_posix(*label))
+ label++;
+ end = strchr(label, '\n');
+ if (end)
+ *end = 0;
+ else
+ end = strchr(label, '\0');
+ end--;
+
+ while (is_space_posix(*end) && end > label) {
+ *end = 0;
+ end--;
+ }
+
+ return *label ? label : NULL;
+}
+
+static void
+xtables_get_connlabel(uint16_t bit, char *buf, size_t len)
+{
+ FILE *fp = fopen(CONNLABEL_CFG, "r");
+ char label[1024];
+ char *end;
+
+ if (!fp)
+ goto error;
+
+ while (fgets(label, sizeof(label), fp)) {
+ int tmp;
+
+ if (label[0] == '#')
+ continue;
+ tmp = xtables_parse_connlabel_numerical(label, &end);
+ if (tmp < 0 || tmp < (int) bit)
+ continue;
+ if (tmp > (int) bit)
+ break;
+
+ end = trim_label(end);
+ if (!end)
+ continue;
+ snprintf(buf, len, "%s", end);
+ fclose(fp);
+ return;
+ }
+ fclose(fp);
+ error:
+ snprintf(buf, len, "%u", (unsigned int) bit);
+}
+
+
+static uint16_t xtables_parse_connlabel(const char *s)
+{
+ FILE *fp = fopen(CONNLABEL_CFG, "r");
+ char label[1024];
+ char *end;
+ int bit;
+
+ if (!fp)
+ xtables_error(PARAMETER_PROBLEM, "label '%s': could not open '%s': %s",
+ s, CONNLABEL_CFG, strerror(errno));
+
+ while (fgets(label, sizeof(label), fp)) {
+ if (label[0] == '#' || !strstr(label, s))
+ continue;
+ bit = xtables_parse_connlabel_numerical(label, &end);
+ if (bit < 0)
+ continue;
+
+ end = trim_label(end);
+ if (!end)
+ continue;
+ if (strcmp(end, s) == 0) {
+ fclose(fp);
+ return bit;
+ }
+ }
+ fclose(fp);
+ xtables_error(PARAMETER_PROBLEM, "label '%s' not found in config file %s",
+ s, CONNLABEL_CFG);
+}
+
+static void connlabel_mt_parse(struct xt_option_call *cb)
+{
+ struct xt_connlabel_mtinfo *info = cb->data;
+ int tmp;
+
+ xtables_option_parse(cb);
+
+ switch (cb->entry->id) {
+ case O_LABEL:
+ tmp = xtables_parse_connlabel_numerical(cb->arg, NULL);
+ info->bit = tmp < 0 ? xtables_parse_connlabel(cb->arg) : tmp;
+
+ if (cb->invert)
+ info->options |= XT_CONNLABEL_OP_INVERT;
+ break;
+ case O_SET:
+ info->options |= XT_CONNLABEL_OP_SET;
+ break;
+ }
+
+}
+
+static void
+connlabel_mt_print_op(const struct xt_connlabel_mtinfo *info, const char *prefix)
+{
+ if (info->options & XT_CONNLABEL_OP_SET)
+ printf(" %sset", prefix);
+}
+
+static void
+connlabel_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connlabel_mtinfo *info = (const void *)match->data;
+ char buf[1024];
+
+ printf(" connlabel");
+ if (info->options & XT_CONNLABEL_OP_INVERT)
+ printf(" !");
+ if (numeric) {
+ printf(" %u", info->bit);
+ } else {
+ xtables_get_connlabel(info->bit, buf, sizeof(buf));
+ printf(" '%s'", buf);
+ }
+ connlabel_mt_print_op(info, "");
+}
+
+static void
+connlabel_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connlabel_mtinfo *info = (const void *)match->data;
+ char buf[1024];
+
+ if (info->options & XT_CONNLABEL_OP_INVERT)
+ printf(" !");
+
+ xtables_get_connlabel(info->bit, buf, sizeof(buf));
+ printf(" --label \"%s\"", buf);
+
+ connlabel_mt_print_op(info, "--");
+}
+
+static struct xtables_match connlabel_mt_reg = {
+ .family = NFPROTO_UNSPEC,
+ .name = "connlabel",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connlabel_mtinfo)),
+ .userspacesize = offsetof(struct xt_connlabel_mtinfo, bit),
+ .help = connlabel_mt_help,
+ .print = connlabel_mt_print,
+ .save = connlabel_mt_save,
+ .x6_parse = connlabel_mt_parse,
+ .x6_options = connlabel_mt_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&connlabel_mt_reg);
+}
--- /dev/null
+Module matches or adds connlabels to a connection.
+connlabels are similar to connmarks, except labels are bit-based; i.e.
+all labels may be attached to a flow at the same time.
+Up to 128 unique labels are currently supported.
+.TP
+[\fB!\fP] \fB\-\-label\fP \fBname\fP
+matches if label \fBname\fP has been set on a connection.
+Instead of a name (which will be translated to a number, see EXAMPLE below),
+a number may be used instead. Using a number always overrides connlabel.conf.
+.TP
+\fB\-\-set\fP
+if the label has not been set on the connection, set it.
+Note that setting a label can fail. This is because the kernel allocates the
+conntrack label storage area when the connection is created, and it only
+reserves the amount of memory required by the ruleset that exists at
+the time the connection is created.
+In this case, the match will fail (or succeed, in case \fB\-\-label\fP
+option was negated).
+.PP
+Label translation is done via the \fB/etc/xtables/connlabel.conf\fP configuration file.
+.PP
+Example:
+.IP
+.nf
+0 eth0-in
+1 eth0-out
+2 ppp-in
+3 ppp-out
+4 bulk-traffic
+5 interactive
+.fi
+.PP
#include <string.h>
#include <xtables.h>
#include <linux/netfilter/xt_conntrack.h>
+#include <linux/netfilter/xt_state.h>
#include <linux/netfilter/nf_conntrack_common.h>
+#ifndef XT_STATE_UNTRACKED
+#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
+#endif
struct ip_conntrack_old_tuple {
struct {
if (info->match_flags & XT_CONNTRACK_STATE) {
if (info->invert_flags & XT_CONNTRACK_STATE)
printf(" !");
- printf(" %sctstate", prefix);
+ printf(" %s%s", prefix,
+ info->match_flags & XT_CONNTRACK_STATE_ALIAS
+ ? "state" : "ctstate");
print_state(info->state_mask);
}
}
}
+static const char *
+conntrack_print_name_alias(const struct xt_entry_match *match)
+{
+ struct xt_conntrack_mtinfo1 *info = (void *)match->data;
+
+ return info->match_flags & XT_CONNTRACK_STATE_ALIAS
+ ? "state" : "conntrack";
+}
+
static void conntrack_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
conntrack_dump(&up, "--", NFPROTO_IPV6, true, false);
}
+static void
+state_help(void)
+{
+ printf(
+"state match options:\n"
+" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
+" State(s) to match\n");
+}
+
+static const struct xt_option_entry state_opts[] = {
+ {.name = "state", .id = O_CTSTATE, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_INVERT},
+ XTOPT_TABLEEND,
+};
+
+static unsigned int
+state_parse_state(const char *state, size_t len)
+{
+ if (strncasecmp(state, "INVALID", len) == 0)
+ return XT_CONNTRACK_STATE_INVALID;
+ else if (strncasecmp(state, "NEW", len) == 0)
+ return XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+ else if (strncasecmp(state, "ESTABLISHED", len) == 0)
+ return XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+ else if (strncasecmp(state, "RELATED", len) == 0)
+ return XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+ else if (strncasecmp(state, "UNTRACKED", len) == 0)
+ return XT_CONNTRACK_STATE_UNTRACKED;
+ return 0;
+}
+
+static unsigned int
+state_parse_states(const char *arg)
+{
+ const char *comma;
+ unsigned int mask = 0, flag;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg)
+ goto badstate;
+ flag = state_parse_state(arg, comma-arg);
+ if (flag == 0)
+ goto badstate;
+ mask |= flag;
+ arg = comma+1;
+ }
+ if (!*arg)
+ xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
+ "states with no spaces, e.g. "
+ "ESTABLISHED,RELATED");
+ if (strlen(arg) == 0)
+ goto badstate;
+ flag = state_parse_state(arg, strlen(arg));
+ if (flag == 0)
+ goto badstate;
+ mask |= flag;
+ return mask;
+ badstate:
+ xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
+}
+
+static void state_parse(struct xt_option_call *cb)
+{
+ struct xt_state_info *sinfo = cb->data;
+
+ xtables_option_parse(cb);
+ sinfo->statemask = state_parse_states(cb->arg);
+ if (cb->invert)
+ sinfo->statemask = ~sinfo->statemask;
+}
+
+static void state_ct1_parse(struct xt_option_call *cb)
+{
+ struct xt_conntrack_mtinfo1 *sinfo = cb->data;
+
+ xtables_option_parse(cb);
+ sinfo->match_flags = XT_CONNTRACK_STATE | XT_CONNTRACK_STATE_ALIAS;
+ sinfo->state_mask = state_parse_states(cb->arg);
+ if (cb->invert)
+ sinfo->invert_flags |= XT_CONNTRACK_STATE;
+}
+
+static void state_ct23_parse(struct xt_option_call *cb)
+{
+ struct xt_conntrack_mtinfo3 *sinfo = cb->data;
+
+ xtables_option_parse(cb);
+ sinfo->match_flags = XT_CONNTRACK_STATE | XT_CONNTRACK_STATE_ALIAS;
+ sinfo->state_mask = state_parse_states(cb->arg);
+ if (cb->invert)
+ sinfo->invert_flags |= XT_CONNTRACK_STATE;
+}
+
+static void state_print_state(unsigned int statemask)
+{
+ const char *sep = "";
+
+ if (statemask & XT_CONNTRACK_STATE_INVALID) {
+ printf("%sINVALID", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
+ printf("%sNEW", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
+ printf("%sRELATED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
+ printf("%sESTABLISHED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
+ printf("%sUNTRACKED", sep);
+ sep = ",";
+ }
+}
+
+static void
+state_print(const void *ip,
+ const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_state_info *sinfo = (const void *)match->data;
+
+ printf(" state ");
+ state_print_state(sinfo->statemask);
+}
+
+static void state_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_state_info *sinfo = (const void *)match->data;
+
+ printf(" --state ");
+ state_print_state(sinfo->statemask);
+}
+
static struct xtables_match conntrack_mt_reg[] = {
{
.version = XTABLES_VERSION,
.x6_fcheck = conntrack_mt_check,
.print = conntrack_print,
.save = conntrack_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack_mt_opts_v0,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack1_mt4_print,
.save = conntrack1_mt4_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack2_mt_opts,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack1_mt6_print,
.save = conntrack1_mt6_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack2_mt_opts,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack2_mt_print,
.save = conntrack2_mt_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack2_mt_opts,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack2_mt6_print,
.save = conntrack2_mt6_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack2_mt_opts,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack3_mt_print,
.save = conntrack3_mt_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack3_mt_opts,
},
{
.x6_fcheck = conntrack_mt_check,
.print = conntrack3_mt6_print,
.save = conntrack3_mt6_save,
+ .alias = conntrack_print_name_alias,
.x6_options = conntrack3_mt_opts,
},
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "state",
+ .real_name = "conntrack",
+ .revision = 1,
+ .ext_flags = XTABLES_EXT_ALIAS,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .help = state_help,
+ .x6_parse = state_ct1_parse,
+ .x6_options = state_opts,
+ },
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "state",
+ .real_name = "conntrack",
+ .revision = 2,
+ .ext_flags = XTABLES_EXT_ALIAS,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .help = state_help,
+ .x6_parse = state_ct23_parse,
+ .x6_options = state_opts,
+ },
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "state",
+ .real_name = "conntrack",
+ .revision = 3,
+ .ext_flags = XTABLES_EXT_ALIAS,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
+ .help = state_help,
+ .x6_parse = state_ct23_parse,
+ .x6_options = state_opts,
+ },
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "state",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_state_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
+ .help = state_help,
+ .print = state_print,
+ .save = state_save,
+ .x6_parse = state_parse,
+ .x6_options = state_opts,
+ },
};
void _init(void)
States for \fB\-\-ctstate\fP:
.TP
\fBINVALID\fP
-meaning that the packet is associated with no known connection
+The packet is associated with no known connection.
.TP
\fBNEW\fP
-meaning that the packet has started a new connection, or otherwise associated
-with a connection which has not seen packets in both directions, and
+The packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions.
.TP
\fBESTABLISHED\fP
-meaning that the packet is associated with a connection which has seen packets
-in both directions,
+The packet is associated with a connection which has seen packets
+in both directions.
.TP
\fBRELATED\fP
-meaning that the packet is starting a new connection, but is associated with an
+The packet is starting a new connection, but is associated with an
existing connection, such as an FTP data transfer, or an ICMP error.
.TP
\fBUNTRACKED\fP
-meaning that the packet is not tracked at all, which happens if you use
-the NOTRACK target in raw table.
+The packet is not tracked at all, which happens if you explicitly untrack it
+by using \-j CT \-\-notrack in the raw table.
.TP
\fBSNAT\fP
A virtual state, matching if the original source address differs from the reply
None of the below.
.TP
\fBEXPECTED\fP
-This is an expected connection (i.e. a conntrack helper set it up)
+This is an expected connection (i.e. a conntrack helper set it up).
.TP
\fBSEEN_REPLY\fP
Conntrack has seen packets in both directions.
fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
}
+static void devgroup_parse_groupspec(const char *arg, unsigned int *group,
+ unsigned int *mask)
+{
+ char *end;
+ bool ok;
+
+ ok = xtables_strtoui(arg, &end, group, 0, UINT32_MAX);
+ if (ok && (*end == '/' || *end == '\0')) {
+ if (*end == '/')
+ ok = xtables_strtoui(end + 1, NULL, mask,
+ 0, UINT32_MAX);
+ else
+ *mask = ~0U;
+ if (!ok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad group value \"%s\"", arg);
+ } else {
+ *group = xtables_lmap_name2id(devgroups, arg);
+ if (*group == -1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Device group \"%s\" not found", arg);
+ *mask = ~0U;
+ }
+}
+
static void devgroup_parse(struct xt_option_call *cb)
{
struct xt_devgroup_info *info = cb->data;
- unsigned int id;
- char *end;
+ unsigned int id, mask;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_SRC_GROUP:
- info->src_group = strtoul(cb->arg, &end, 0);
- if (end != cb->arg && (*end == '/' || *end == '\0')) {
- if (*end == '/')
- info->src_mask = strtoul(end+1, &end, 0);
- else
- info->src_mask = 0xffffffff;
- if (*end != '\0' || end == cb->arg)
- xtables_error(PARAMETER_PROBLEM,
- "Bad src-group value `%s'",
- cb->arg);
- } else {
- id = xtables_lmap_name2id(devgroups, cb->arg);
- if (id == -1)
- xtables_error(PARAMETER_PROBLEM,
- "Device group `%s' not found",
- cb->arg);
- info->src_group = id;
- info->src_mask = 0xffffffff;
- }
+ devgroup_parse_groupspec(cb->arg, &id, &mask);
+ info->src_group = id;
+ info->src_mask = mask;
info->flags |= XT_DEVGROUP_MATCH_SRC;
if (cb->invert)
info->flags |= XT_DEVGROUP_INVERT_SRC;
break;
case O_DST_GROUP:
- info->dst_group = strtoul(cb->arg, &end, 0);
- if (end != cb->arg && (*end == '/' || *end == '\0')) {
- if (*end == '/')
- info->dst_mask = strtoul(end+1, &end, 0);
- else
- info->dst_mask = 0xffffffff;
- if (*end != '\0' || end == cb->arg)
- xtables_error(PARAMETER_PROBLEM,
- "Bad dst-group value `%s'",
- cb->arg);
- } else {
- id = xtables_lmap_name2id(devgroups, cb->arg);
- if (id == -1)
- xtables_error(PARAMETER_PROBLEM,
- "Device group `%s' not found",
- cb->arg);
- info->dst_group = id;
- info->dst_mask = 0xffffffff;
- }
+ devgroup_parse_groupspec(cb->arg, &id, &mask);
+ info->dst_group = id;
+ info->dst_mask = mask;
info->flags |= XT_DEVGROUP_MATCH_DST;
if (cb->invert)
info->flags |= XT_DEVGROUP_INVERT_DST;
--- /dev/null
+Match device group of a packets incoming/outgoing interface.
+.TP
+[\fB!\fP] \fB\-\-src\-group\fP \fIname\fP
+Match device group of incoming device
+.TP
+[\fB!\fP] \fB\-\-dst\-group\fP \fIname\fP
+Match device group of outgoing device
*
* Error corections by nmalykh@bilim.com (22.01.2005)
*/
+#define _BSD_SOURCE 1
+#define _ISOC99_SOURCE 1
+#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <linux/netfilter/xt_hashlimit.h>
#define XT_HASHLIMIT_BURST 5
+#define XT_HASHLIMIT_BURST_MAX 10000
+
+#define XT_HASHLIMIT_BYTE_EXPIRE 15
+#define XT_HASHLIMIT_BYTE_EXPIRE_BURST 60
/* miliseconds */
#define XT_HASHLIMIT_GCINTERVAL 1000
O_HTABLE_MAX,
O_HTABLE_GCINT,
O_HTABLE_EXPIRE,
+ F_BURST = 1 << O_BURST,
F_UPTO = 1 << O_UPTO,
F_ABOVE = 1 << O_ABOVE,
F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE,
{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING},
{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
- .min = 1, .max = 10000, .flags = XTOPT_PUT,
+ .min = 1, .max = XT_HASHLIMIT_BURST_MAX, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.burst)},
{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
- {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
- .min = 1, .max = 10000, .flags = XTOPT_PUT,
- XTOPT_POINTER(s, cfg.burst)},
+ {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.size)},
};
#undef s
+static uint32_t cost_to_bytes(uint32_t cost)
+{
+ uint32_t r;
+
+ r = cost ? UINT32_MAX / cost : UINT32_MAX;
+ r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
+ return r;
+}
+
+static uint64_t bytes_to_cost(uint32_t bytes)
+{
+ uint32_t r = bytes >> XT_HASHLIMIT_BYTE_SHIFT;
+ return UINT32_MAX / (r+1);
+}
+
+static uint32_t get_factor(int chr)
+{
+ switch (chr) {
+ case 'm': return 1024 * 1024;
+ case 'k': return 1024;
+ }
+ return 1;
+}
+
+static void burst_error(void)
+{
+ xtables_error(PARAMETER_PROBLEM, "bad value for option "
+ "\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX);
+}
+
+static uint32_t parse_burst(const char *burst, struct xt_hashlimit_mtinfo1 *info)
+{
+ uintmax_t v;
+ char *end;
+
+ if (!xtables_strtoul(burst, &end, &v, 1, UINT32_MAX) ||
+ (*end == 0 && v > XT_HASHLIMIT_BURST_MAX))
+ burst_error();
+
+ v *= get_factor(*end);
+ if (v > UINT32_MAX)
+ xtables_error(PARAMETER_PROBLEM, "bad value for option "
+ "\"--hashlimit-burst\", value \"%s\" too large "
+ "(max %umb).", burst, UINT32_MAX/1024/1024);
+ return v;
+}
+
+static bool parse_bytes(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud)
+{
+ unsigned int factor = 1;
+ uint64_t tmp;
+ int r;
+ const char *mode = strstr(rate, "b/s");
+ if (!mode || mode == rate)
+ return false;
+
+ mode--;
+ r = atoi(rate);
+ if (r == 0)
+ return false;
+
+ factor = get_factor(*mode);
+ tmp = (uint64_t) r * factor;
+ if (tmp > UINT32_MAX)
+ xtables_error(PARAMETER_PROBLEM,
+ "Rate value too large \"%llu\" (max %u)\n",
+ (unsigned long long)tmp, UINT32_MAX);
+
+ *val = bytes_to_cost(tmp);
+ if (*val == 0)
+ xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", rate);
+
+ ud->mult = XT_HASHLIMIT_BYTE_EXPIRE;
+ return true;
+}
+
static
int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud)
{
if (!r)
return 0;
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / ud->mult > XT_HASHLIMIT_SCALE)
- xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
-
*val = XT_HASHLIMIT_SCALE * ud->mult / r;
+ if (*val == 0)
+ /*
+ * The rate maps to infinity. (1/day is the minimum they can
+ * specify, so we are ok at that end).
+ */
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
return 1;
}
xtables_option_parse(cb);
switch (cb->entry->id) {
+ case O_BURST:
+ info->cfg.burst = parse_burst(cb->arg, info);
+ break;
case O_UPTO:
if (cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
- if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
+ if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata))
+ info->cfg.mode |= XT_HASHLIMIT_BYTES;
+ else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-upto", cb->arg);
break;
case O_ABOVE:
if (!cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
- if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
+ if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata))
+ info->cfg.mode |= XT_HASHLIMIT_BYTES;
+ else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-above", cb->arg);
break;
"You have to specify --hashlimit");
if (!(cb->xflags & F_HTABLE_EXPIRE))
info->cfg.expire = udata->mult * 1000; /* from s to msec */
+
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
+ uint32_t burst = 0;
+ if (cb->xflags & F_BURST) {
+ if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
+ xtables_error(PARAMETER_PROBLEM,
+ "burst cannot be smaller than %ub", cost_to_bytes(info->cfg.avg));
+
+ burst = info->cfg.burst;
+ burst /= cost_to_bytes(info->cfg.avg);
+ if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
+ burst++;
+ if (!(cb->xflags & F_HTABLE_EXPIRE))
+ info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
+ }
+ info->cfg.burst = burst;
+ } else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX)
+ burst_error();
}
static const struct rates
{
unsigned int i;
+ if (period == 0) {
+ printf(" %f", INFINITY);
+ return 0;
+ }
+
for (i = 1; i < ARRAY_SIZE(rates); ++i)
if (period > rates[i].mult
|| rates[i].mult/period < rates[i].mult%period)
return rates[i-1].mult / XT_HASHLIMIT_SCALE * 1000;
}
+static const struct {
+ const char *name;
+ uint32_t thresh;
+} units[] = {
+ { "m", 1024 * 1024 },
+ { "k", 1024 },
+ { "", 1 },
+};
+
+static uint32_t print_bytes(uint32_t avg, uint32_t burst, const char *prefix)
+{
+ unsigned int i;
+ unsigned long long r;
+
+ r = cost_to_bytes(avg);
+
+ for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
+ if (r >= units[i].thresh &&
+ bytes_to_cost(r & ~(units[i].thresh - 1)) == avg)
+ break;
+ printf(" %llu%sb/s", r/units[i].thresh, units[i].name);
+
+ if (burst == 0)
+ return XT_HASHLIMIT_BYTE_EXPIRE * 1000;
+
+ r *= burst;
+ printf(" %s", prefix);
+ for (i = 0; i < ARRAY_SIZE(units) -1; ++i)
+ if (r >= units[i].thresh)
+ break;
+
+ printf("burst %llu%sb", r / units[i].thresh, units[i].name);
+ return XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
+}
+
static void print_mode(unsigned int mode, char separator)
{
bool prevmode = false;
fputs(" limit: above", stdout);
else
fputs(" limit: up to", stdout);
- quantum = print_rate(info->cfg.avg);
- printf(" burst %u", info->cfg.burst);
+
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
+ quantum = print_bytes(info->cfg.avg, info->cfg.burst, "");
+ } else {
+ quantum = print_rate(info->cfg.avg);
+ printf(" burst %u", info->cfg.burst);
+ }
if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
fputs(" mode", stdout);
fputs(" --hashlimit-mode", stdout);
print_mode(r->cfg.mode, ',');
-
+
printf(" --hashlimit-name %s", r->name);
if (r->cfg.size)
fputs(" --hashlimit-above", stdout);
else
fputs(" --hashlimit-upto", stdout);
- quantum = print_rate(info->cfg.avg);
- printf(" --hashlimit-burst %u", info->cfg.burst);
+
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
+ quantum = print_bytes(info->cfg.avg, info->cfg.burst, "--hashlimit-");
+ } else {
+ quantum = print_rate(info->cfg.avg);
+ printf(" --hashlimit-burst %u", info->cfg.burst);
+ }
if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
\fBlimit\fP match) for a group of connections using a \fBsingle\fP iptables
rule. Grouping can be done per-hostgroup (source and/or destination address)
and/or per-port. It gives you the ability to express "\fIN\fP packets per time
-quantum per group" (see below for some examples).
+quantum per group" or "\fIN\fP bytes per seconds" (see below for some examples).
.PP
A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
\fB\-\-hashlimit\-name\fP are required.
.TP
\fB\-\-hashlimit\-upto\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
-Match if the rate is below or equal to \fIamount\fP/quantum. It is specified as
-a number, with an optional time quantum suffix; the default is 3/hour.
+Match if the rate is below or equal to \fIamount\fP/quantum. It is specified either as
+a number, with an optional time quantum suffix (the default is 3/hour), or as
+\fIamount\fPb/second (number of bytes per second).
.TP
\fB\-\-hashlimit\-above\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
Match if the rate is above \fIamount\fP/quantum.
\fB\-\-hashlimit\-burst\fP \fIamount\fP
Maximum initial number of packets to match: this number gets recharged by one
every time the limit specified above is not reached, up to this number; the
-default is 5.
+default is 5. When byte-based rate matching is requested, this option specifies
+the amount of bytes that can exceed the given rate. This option should be used
+with caution -- if the entry expires, the burst value is reset too.
.TP
\fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP...
A comma-separated list of objects to take into consideration. If no
"10000 packets per minute for every /28 subnet (groups of 8 addresses)
in 10.0.0.0/8" =>
\-s 10.0.0.8 \-\-hashlimit\-mask 28 \-\-hashlimit\-upto 10000/min
+.TP
+matching bytes per second
+"flows exceeding 512kbyte/s" =>
+\-\-hashlimit-mode srcip,dstip,srcport,dstport \-\-hashlimit\-above 512kb/s
+.TP
+matching bytes per second
+"hosts that exceed 512kbyte/s, but permit up to 1Megabytes without matching"
+\-\-hashlimit-mode dstip \-\-hashlimit\-above 512kb/s \-\-hashlimit-burst 1mb
* Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
* Hervé Eychenne <rv@wallfire.org>
*/
+#define _BSD_SOURCE 1
+#define _ISOC99_SOURCE 1
+#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
if (!r)
return 0;
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / mult > XT_LIMIT_SCALE)
- xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
-
*val = XT_LIMIT_SCALE * mult / r;
+ if (*val == 0)
+ /*
+ * The rate maps to infinity. (1/day is the minimum they can
+ * specify, so we are ok at that end).
+ */
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
return 1;
}
{
unsigned int i;
+ if (period == 0) {
+ printf(" %f", INFINITY);
+ return;
+ }
+
for (i = 1; i < ARRAY_SIZE(rates); ++i)
if (period > rates[i].mult
|| rates[i].mult/period < rates[i].mult%period)
This module matches a set of source or destination ports. Up to 15
ports can be specified. A port range (port:port) counts as two
-ports. It can only be used in conjunction with
-\fB\-p tcp\fP
-or
-\fB\-p udp\fP.
+ports. It can only be used in conjunction with one of the
+following protocols:
+\fBtcp\fP, \fBudp\fP, \fBudplite\fP, \fBdccp\fP and \fBsctp\fP.
.TP
[\fB!\fP] \fB\-\-source\-ports\fP,\fB\-\-sports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
Match if the source port is one of the given ports. The flag
{
const struct xt_osf_info *info = (const struct xt_osf_info*) match->data;
- printf(" --genre %s%s", (info->flags & XT_OSF_INVERT) ? "! ": "", info->genre);
+ if (info->flags & XT_OSF_INVERT)
+ printf(" !");
+
+ printf(" --genre %s", info->genre);
+ if (info->flags & XT_OSF_TTL)
+ printf(" --ttl %u", info->ttl);
+ if (info->flags & XT_OSF_LOG)
+ printf(" --log %u", info->loglevel);
}
static struct xtables_match osf_match = {
O_NAME,
O_RSOURCE,
O_RDEST,
+ O_MASK,
F_SET = 1 << O_SET,
F_RCHECK = 1 << O_RCHECK,
F_UPDATE = 1 << O_UPDATE,
};
#define s struct xt_recent_mtinfo
-static const struct xt_option_entry recent_opts[] = {
+static const struct xt_option_entry recent_opts_v0[] = {
{.name = "set", .id = O_SET, .type = XTTYPE_NONE,
.excl = F_ANY_OP, .flags = XTOPT_INVERT},
{.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
};
#undef s
+#define s struct xt_recent_mtinfo_v1
+static const struct xt_option_entry recent_opts_v1[] = {
+ {.name = "set", .id = O_SET, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
+ .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+ {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)},
+ {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
+ {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
+ .excl = F_SET | F_REMOVE},
+ {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
+ {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
+ {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
+ {.name = "mask", .id = O_MASK, .type = XTTYPE_HOST,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)},
+ XTOPT_TABLEEND,
+};
+#undef s
+
static void recent_help(void)
{
printf(
" --name name Name of the recent list to be used. DEFAULT used if none given.\n"
" --rsource Match/Save the source address of each packet in the recent list table (default).\n"
" --rdest Match/Save the destination address of each packet in the recent list table.\n"
+" --mask netmask Netmask that will be applied to this recent list.\n"
"xt_recent by: Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n");
}
-static void recent_init(struct xt_entry_match *match)
+enum {
+ XT_RECENT_REV_0 = 0,
+ XT_RECENT_REV_1,
+};
+
+static void recent_init(struct xt_entry_match *match, unsigned int rev)
{
- struct xt_recent_mtinfo *info = (void *)(match)->data;
+ struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)match->data;
+ struct xt_recent_mtinfo_v1 *info_v1 =
+ (struct xt_recent_mtinfo_v1 *)match->data;
strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
/* even though XT_RECENT_NAME_LEN is currently defined as 200,
* better be safe, than sorry */
info->name[XT_RECENT_NAME_LEN-1] = '\0';
info->side = XT_RECENT_SOURCE;
+ if (rev == XT_RECENT_REV_1)
+ memset(&info_v1->mask, 0xFF, sizeof(info_v1->mask));
}
static void recent_parse(struct xt_option_call *cb)
static void recent_check(struct xt_fcheck_call *cb)
{
- struct xt_recent_mtinfo *info = cb->data;
-
if (!(cb->xflags & F_ANY_OP))
xtables_error(PARAMETER_PROBLEM,
"recent: you must specify one of `--set', `--rcheck' "
}
static void recent_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
+ unsigned int family)
{
- const struct xt_recent_mtinfo *info = (const void *)match->data;
+ const struct xt_recent_mtinfo_v1 *info = (const void *)match->data;
if (info->invert)
printf(" !");
printf(" side: source");
if (info->side == XT_RECENT_DEST)
printf(" side: dest");
+
+ switch(family) {
+ case NFPROTO_IPV4:
+ printf(" mask: %s",
+ xtables_ipaddr_to_numeric(&info->mask.in));
+ break;
+ case NFPROTO_IPV6:
+ printf(" mask: %s",
+ xtables_ip6addr_to_numeric(&info->mask.in6));
+ break;
+ }
}
-static void recent_save(const void *ip, const struct xt_entry_match *match)
+static void recent_save(const void *ip, const struct xt_entry_match *match,
+ unsigned int family)
{
- const struct xt_recent_mtinfo *info = (const void *)match->data;
+ const struct xt_recent_mtinfo_v1 *info = (const void *)match->data;
if (info->invert)
printf(" !");
if (info->check_set & XT_RECENT_TTL)
printf(" --rttl");
if(info->name) printf(" --name %s",info->name);
+
+ switch(family) {
+ case NFPROTO_IPV4:
+ printf(" --mask %s",
+ xtables_ipaddr_to_numeric(&info->mask.in));
+ break;
+ case NFPROTO_IPV6:
+ printf(" --mask %s",
+ xtables_ip6addr_to_numeric(&info->mask.in6));
+ break;
+ }
+
if (info->side == XT_RECENT_SOURCE)
printf(" --rsource");
if (info->side == XT_RECENT_DEST)
printf(" --rdest");
}
-static struct xtables_match recent_mt_reg = {
- .name = "recent",
- .version = XTABLES_VERSION,
- .family = NFPROTO_UNSPEC,
- .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
- .help = recent_help,
- .init = recent_init,
- .x6_parse = recent_parse,
- .x6_fcheck = recent_check,
- .print = recent_print,
- .save = recent_save,
- .x6_options = recent_opts,
+static void recent_init_v0(struct xt_entry_match *match)
+{
+ recent_init(match, XT_RECENT_REV_0);
+}
+
+static void recent_init_v1(struct xt_entry_match *match)
+{
+ recent_init(match, XT_RECENT_REV_1);
+}
+
+static void recent_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ recent_save(ip, match, NFPROTO_UNSPEC);
+}
+
+static void recent_save_v4(const void *ip, const struct xt_entry_match *match)
+{
+ recent_save(ip, match, NFPROTO_IPV4);
+}
+
+static void recent_save_v6(const void *ip, const struct xt_entry_match *match)
+{
+ recent_save(ip, match, NFPROTO_IPV6);
+}
+
+static void recent_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ recent_print(ip, match, NFPROTO_UNSPEC);
+}
+
+static void recent_print_v4(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ recent_print(ip, match, NFPROTO_IPV4);
+}
+
+static void recent_print_v6(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ recent_print(ip, match, NFPROTO_IPV6);
+}
+
+static struct xtables_match recent_mt_reg[] = {
+ {
+ .name = "recent",
+ .version = XTABLES_VERSION,
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
+ .help = recent_help,
+ .init = recent_init_v0,
+ .x6_parse = recent_parse,
+ .x6_fcheck = recent_check,
+ .print = recent_print_v0,
+ .save = recent_save_v0,
+ .x6_options = recent_opts_v0,
+ },
+ {
+ .name = "recent",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
+ .help = recent_help,
+ .init = recent_init_v1,
+ .x6_parse = recent_parse,
+ .x6_fcheck = recent_check,
+ .print = recent_print_v4,
+ .save = recent_save_v4,
+ .x6_options = recent_opts_v1,
+ },
+ {
+ .name = "recent",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
+ .help = recent_help,
+ .init = recent_init_v1,
+ .x6_parse = recent_parse,
+ .x6_fcheck = recent_check,
+ .print = recent_print_v6,
+ .save = recent_save_v6,
+ .x6_options = recent_opts_v1,
+ },
};
void _init(void)
{
- xtables_register_match(&recent_mt_reg);
+ xtables_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
}
\fB\-\-rdest\fP
Match/save the destination address of each packet in the recent list table.
.TP
+\fB\-\-mask\fP \fInetmask\fP
+Netmask that will be applied to this recent list.
+.TP
[\fB!\fP] \fB\-\-rcheck\fP
Check if the source address of the packet is currently in the list.
.TP
\fB\-\-accept\-local\fP
This will permit packets arriving from the network with a source address that is also
assigned to the local machine.
+.TP
\fB\-\-invert\fP
This will invert the sense of the match. Instead of matching packets that passed the
reverse path filter test, match those that have failed it.
print_match("--match-set", &info->match_set);
}
+/* Revision 2 */
+static void
+set_help_v2(void)
+{
+ printf("set match options:\n"
+ " [!] --match-set name flags [--return-nomatch]\n"
+ " 'name' is the set name from to match,\n"
+ " 'flags' are the comma separated list of\n"
+ " 'src' and 'dst' specifications.\n");
+}
+
+static const struct option set_opts_v2[] = {
+ {.name = "match-set", .has_arg = true, .val = '1'},
+ {.name = "set", .has_arg = true, .val = '2'},
+ {.name = "return-nomatch", .has_arg = false, .val = '3'},
+ XT_GETOPT_TABLEEND,
+};
+
+static int
+set_parse_v2(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_set_info_match_v1 *myinfo =
+ (struct xt_set_info_match_v1 *) (*match)->data;
+ struct xt_set_info *info = &myinfo->match_set;
+
+ switch (c) {
+ case '3':
+ info->flags |= IPSET_RETURN_NOMATCH;
+ break;
+ case '2':
+ fprintf(stderr,
+ "--set option deprecated, please use --match-set\n");
+ case '1': /* --match-set <set> <flag>[,<flag> */
+ if (info->dim)
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set can be specified only once");
+ if (invert)
+ info->flags |= IPSET_INV_MATCH;
+
+ if (!argv[optind]
+ || argv[optind][0] == '-'
+ || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set requires two args.");
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, info);
+ parse_dirs(argv[optind], info);
+ DEBUGP("parse: set index %u\n", info->index);
+ optind++;
+
+ *flags = 1;
+ break;
+ }
+
+ return 1;
+}
+
+/* Prints out the matchinfo. */
+static void
+set_print_v2(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_set_info_match_v1 *info = (const void *)match->data;
+
+ print_match("match-set", &info->match_set);
+ if (info->match_set.flags & IPSET_RETURN_NOMATCH)
+ printf(" return-nomatch");
+}
+
+static void
+set_save_v2(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_set_info_match_v1 *info = (const void *)match->data;
+
+ print_match("--match-set", &info->match_set);
+ if (info->match_set.flags & IPSET_RETURN_NOMATCH)
+ printf(" --return-nomatch");
+}
+
static struct xtables_match set_mt_reg[] = {
{
.name = "set",
.save = set_save_v1,
.extra_opts = set_opts_v0,
},
+ {
+ .name = "set",
+ .revision = 2,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+ .help = set_help_v2,
+ .parse = set_parse_v2,
+ .final_check = set_check_v0,
+ .print = set_print_v2,
+ .save = set_save_v2,
+ .extra_opts = set_opts_v2,
+ },
};
void _init(void)
the set type of the specified set is single dimension (for example ipmap),
then the command will match packets for which the source address can be
found in the specified set.
+.TP
+\fB\-\-return\-\-nomatch\fP
+If the \fB\-\-return\-\-nomatch\fP option is specified and the set type
+supports the \fBnomatch\fP flag, then the matching is reversed: a match
+with an element flagged with \fBnomatch\fP returns \fBtrue\fP, while a
+match with a plain element returns \fBfalse\fP.
.PP
The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does
not clash with an option of other extensions.
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <xtables.h>
-#include <linux/netfilter/nf_conntrack_common.h>
-#include <linux/netfilter/xt_state.h>
-
-#ifndef XT_STATE_UNTRACKED
-#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
-#endif
-
-enum {
- O_STATE = 0,
-};
-
-static void
-state_help(void)
-{
- printf(
-"state match options:\n"
-" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
-" State(s) to match\n");
-}
-
-static const struct xt_option_entry state_opts[] = {
- {.name = "state", .id = O_STATE, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND | XTOPT_INVERT},
- XTOPT_TABLEEND,
-};
-
-static int
-state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
-{
- if (strncasecmp(state, "INVALID", len) == 0)
- sinfo->statemask |= XT_STATE_INVALID;
- else if (strncasecmp(state, "NEW", len) == 0)
- sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
- else if (strncasecmp(state, "ESTABLISHED", len) == 0)
- sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
- else if (strncasecmp(state, "RELATED", len) == 0)
- sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
- else if (strncasecmp(state, "UNTRACKED", len) == 0)
- sinfo->statemask |= XT_STATE_UNTRACKED;
- else
- return 0;
- return 1;
-}
-
-static void
-state_parse_states(const char *arg, struct xt_state_info *sinfo)
-{
- const char *comma;
-
- while ((comma = strchr(arg, ',')) != NULL) {
- if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
- xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
- arg = comma+1;
- }
- if (!*arg)
- xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
- "states with no spaces, e.g. "
- "ESTABLISHED,RELATED");
- if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
- xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
-}
-
-static void state_parse(struct xt_option_call *cb)
-{
- struct xt_state_info *sinfo = cb->data;
-
- xtables_option_parse(cb);
- state_parse_states(cb->arg, sinfo);
- if (cb->invert)
- sinfo->statemask = ~sinfo->statemask;
-}
-
-static void state_print_state(unsigned int statemask)
-{
- const char *sep = "";
-
- if (statemask & XT_STATE_INVALID) {
- printf("%sINVALID", sep);
- sep = ",";
- }
- if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
- printf("%sNEW", sep);
- sep = ",";
- }
- if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
- printf("%sRELATED", sep);
- sep = ",";
- }
- if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
- printf("%sESTABLISHED", sep);
- sep = ",";
- }
- if (statemask & XT_STATE_UNTRACKED) {
- printf("%sUNTRACKED", sep);
- sep = ",";
- }
-}
-
-static void
-state_print(const void *ip,
- const struct xt_entry_match *match,
- int numeric)
-{
- const struct xt_state_info *sinfo = (const void *)match->data;
-
- printf(" state ");
- state_print_state(sinfo->statemask);
-}
-
-static void state_save(const void *ip, const struct xt_entry_match *match)
-{
- const struct xt_state_info *sinfo = (const void *)match->data;
-
- printf(" --state ");
- state_print_state(sinfo->statemask);
-}
-
-static struct xtables_match state_match = {
- .family = NFPROTO_UNSPEC,
- .name = "state",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_state_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
- .help = state_help,
- .print = state_print,
- .save = state_save,
- .x6_parse = state_parse,
- .x6_options = state_opts,
-};
-
-void _init(void)
-{
- xtables_register_match(&state_match);
-}
-This module, when combined with connection tracking, allows access to
-the connection tracking state for this packet.
+The "state" extension is a subset of the "conntrack" module.
+"state" allows access to the connection tracking state for this packet.
.TP
[\fB!\fP] \fB\-\-state\fP \fIstate\fP
-Where state is a comma separated list of the connection states to
-match. Possible states are
-.B INVALID
-meaning that the packet could not be identified for some reason which
-includes running out of memory and ICMP errors which don't correspond to any
-known connection,
-.B ESTABLISHED
-meaning that the packet is associated with a connection which has seen
-packets in both directions,
-.B NEW
-meaning that the packet has started a new connection, or otherwise
-associated with a connection which has not seen packets in both
-directions, and
-.B RELATED
-meaning that the packet is starting a new connection, but is
-associated with an existing connection, such as an FTP data transfer,
-or an ICMP error.
-.B UNTRACKED
-meaning that the packet is not tracked at all, which happens if you use
-the NOTRACK target in raw table.
+Where state is a comma separated list of the connection states to match. Only a
+subset of the states unterstood by "conntrack" are recognized: \fBINVALID\fP,
+\fBESTABLISHED\fP, \fBNEW\fP, \fBRELATED\fP or \fBUNTRACKED\fP. For their
+description, see the "conntrack" heading in this manpage.
(info->flags & XT_STATISTIC_INVERT) ? " !" : "",
prefix,
info->u.nth.every + 1);
- if (info->u.nth.packet)
+ if (info->u.nth.packet || *prefix)
printf(" %spacket %u", prefix, info->u.nth.packet);
break;
}
print_flags(uint8_t mask, uint8_t cmp, int invert, int numeric)
{
if (mask || invert) {
- printf("flags:%s", invert ? "!" : "");
+ printf(" flags:%s", invert ? "!" : "");
if (numeric)
- printf(" 0x%02X/0x%02X", mask, cmp);
+ printf("0x%02X/0x%02X", mask, cmp);
else {
- printf(" ");
print_tcpf(mask);
printf("/");
print_tcpf(cmp);
O_DATE_STOP,
O_TIME_START,
O_TIME_STOP,
+ O_TIME_CONTIGUOUS,
O_MONTHDAYS,
O_WEEKDAYS,
O_LOCAL_TZ,
F_LOCAL_TZ = 1 << O_LOCAL_TZ,
F_UTC = 1 << O_UTC,
F_KERNEL_TZ = 1 << O_KERNEL_TZ,
+ F_TIME_CONTIGUOUS = 1 << O_TIME_CONTIGUOUS,
};
static const char *const week_days[] = {
{.name = "datestop", .id = O_DATE_STOP, .type = XTTYPE_STRING},
{.name = "timestart", .id = O_TIME_START, .type = XTTYPE_STRING},
{.name = "timestop", .id = O_TIME_STOP, .type = XTTYPE_STRING},
+ {.name = "contiguous", .id = O_TIME_CONTIGUOUS, .type = XTTYPE_NONE},
{.name = "weekdays", .id = O_WEEKDAYS, .type = XTTYPE_STRING,
.flags = XTOPT_INVERT},
{.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING,
case O_TIME_STOP:
info->daytime_stop = time_parse_minutes(cb->arg);
break;
+ case O_TIME_CONTIGUOUS:
+ info->flags |= XT_TIME_CONTIGUOUS;
+ break;
case O_LOCAL_TZ:
fprintf(stderr, "WARNING: --localtz is being replaced by "
"--kerneltz, since \"local\" is ambiguous. Note the "
}
if (!(info->flags & XT_TIME_LOCAL_TZ))
printf(" UTC");
+ if (info->flags & XT_TIME_CONTIGUOUS)
+ printf(" contiguous");
}
static void time_save(const void *ip, const struct xt_entry_match *match)
time_print_date(info->date_stop, "--datestop");
if (info->flags & XT_TIME_LOCAL_TZ)
printf(" --kerneltz");
+ if (info->flags & XT_TIME_CONTIGUOUS)
+ printf(" --contiguous");
+}
+
+static void time_check(struct xt_fcheck_call *cb)
+{
+ const struct xt_time_info *info = (const void *) cb->data;
+ if ((cb->xflags & F_TIME_CONTIGUOUS) &&
+ info->daytime_start < info->daytime_stop)
+ xtables_error(PARAMETER_PROBLEM,
+ "time: --contiguous only makes sense when stoptime is smaller than starttime");
}
static struct xtables_match time_match = {
.print = time_print,
.save = time_save,
.x6_parse = time_parse,
+ .x6_fcheck = time_check,
.x6_options = time_opts,
};
to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP,
\fBTu\fP, etc.).
.TP
+\fB\-\-contiguous\fP
+When \fB\-\-timestop\fP is smaller than \fB\-\-timestart\fP value, match
+this as a single time period instead distinct intervals. See EXAMPLES.
+.TP
\fB\-\-kerneltz\fP
Use the kernel timezone instead of UTC to determine whether a packet meets the
time regulations.
(Note that this exploits a certain mathematical property. It is not possible to
say "fourth Thursday OR fourth Friday" in one rule. It is possible with
multiple rules, though.)
+.PP
+Matching across days might not do what is expected. For instance,
+.IP
+\-m time \-\-weekdays Mo \-\-timestart 23:00 \-\-timestop 01:00
+Will match Monday, for one hour from midnight to 1 a.m., and then
+again for another hour from 23:00 onwards. If this is unwanted, e.g. if you
+would like 'match for two hours from Montay 23:00 onwards' you need to also specify
+the \-\-contiguous option in the example above.
/* string_to_number() is not quite what we need here ... */
static uint32_t parse_number(const char **s, int pos)
{
- uint32_t number;
+ unsigned int number;
char *end;
- errno = 0;
- number = strtoul(*s, &end, 0);
- if (end == *s)
+ if (!xtables_strtoui(*s, &end, &number, 0, UINT32_MAX) ||
+ end == *s)
xtables_error(PARAMETER_PROBLEM,
- "u32: at char %d: expected number", pos);
- if (errno != 0)
- xtables_error(PARAMETER_PROBLEM,
- "u32: at char %d: error reading number", pos);
+ "u32: at char %d: not a number or out of range", pos);
*s = end;
return number;
}
# -*- Makefile -*-
include_HEADERS =
-nobase_include_HEADERS = xtables.h
+nobase_include_HEADERS = xtables.h xtables-version.h
if ENABLE_LIBIPQ
include_HEADERS += libipq/libipq.h
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# -*- Makefile -*-
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
subdir = include
DIST_COMMON = $(am__include_HEADERS_DIST) $(nobase_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
- $(srcdir)/xtables.h.in
+ $(srcdir)/xtables-version.h.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = xtables.h
+CONFIG_CLEAN_FILES = xtables-version.h
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
am__include_HEADERS_DIST = libipq/libipq.h
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
top_srcdir = @top_srcdir@
xtlibdir = @xtlibdir@
include_HEADERS = $(am__append_1)
-nobase_include_HEADERS = xtables.h libiptc/ipt_kernel_headers.h \
- libiptc/libiptc.h libiptc/libip6tc.h libiptc/libxtc.h \
- libiptc/xtcshared.h
+nobase_include_HEADERS = xtables.h xtables-version.h \
+ libiptc/ipt_kernel_headers.h libiptc/libiptc.h \
+ libiptc/libip6tc.h libiptc/libxtc.h libiptc/xtcshared.h
all: all-am
.SUFFIXES:
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
-xtables.h: $(top_builddir)/config.status $(srcdir)/xtables.h.in
+xtables-version.h: $(top_builddir)/config.status $(srcdir)/xtables-version.h.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
mostlyclean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
- test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
install-nobase_includeHEADERS: $(nobase_include_HEADERS)
@$(NORMAL_INSTALL)
- test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
$(am__nobase_list) | while read dir files; do \
xfiles=; for file in $$files; do \
if test -f "$$file"; then xfiles="$$xfiles $$file"; \
else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
test -z "$$xfiles" || { \
test "x$$dir" = x. || { \
- echo "$(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \
echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \
$(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \
/* Translates errno numbers into more human-readable form than strerror. */
const char *ip6tc_strerror(int err);
-/* Return prefix length, or -1 if not contiguous */
-int ipv6_prefix_length(const struct in6_addr *a);
-
extern void dump_entries6(struct xtc_handle *const);
extern const struct xtc_ops ip6tc_ops;
* If changed, new revision of iptables match/target is required.
*/
IPSET_DIM_MAX = 6,
+ IPSET_BIT_RETURN_NOMATCH = 7,
};
/* Option flags for kernel operations */
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
+ IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
};
IP_CT_DIR_MAX
};
+/* The protocol-specific manipulable parts of the tuple: always in
+ * network order
+ */
+union nf_conntrack_man_proto {
+ /* Add other protocols here. */
+ __be16 all;
+
+ struct {
+ __be16 port;
+ } tcp;
+ struct {
+ __be16 port;
+ } udp;
+ struct {
+ __be16 id;
+ } icmp;
+ struct {
+ __be16 port;
+ } dccp;
+ struct {
+ __be16 port;
+ } sctp;
+ struct {
+ __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
+ } gre;
+};
+
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
--- /dev/null
+#ifndef _NETFILTER_NF_NAT_H
+#define _NETFILTER_NF_NAT_H
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+#define NF_NAT_RANGE_MAP_IPS 1
+#define NF_NAT_RANGE_PROTO_SPECIFIED 2
+#define NF_NAT_RANGE_PROTO_RANDOM 4
+#define NF_NAT_RANGE_PERSISTENT 8
+
+struct nf_nat_ipv4_range {
+ unsigned int flags;
+ __be32 min_ip;
+ __be32 max_ip;
+ union nf_conntrack_man_proto min;
+ union nf_conntrack_man_proto max;
+};
+
+struct nf_nat_ipv4_multi_range_compat {
+ unsigned int rangesize;
+ struct nf_nat_ipv4_range range[1];
+};
+
+struct nf_nat_range {
+ unsigned int flags;
+ union nf_inet_addr min_addr;
+ union nf_inet_addr max_addr;
+ union nf_conntrack_man_proto min_proto;
+ union nf_conntrack_man_proto max_proto;
+};
+
+#endif /* _NETFILTER_NF_NAT_H */
--- /dev/null
+#ifndef XT_HMARK_H_
+#define XT_HMARK_H_
+
+#include <linux/types.h>
+
+enum {
+ XT_HMARK_SADDR_MASK,
+ XT_HMARK_DADDR_MASK,
+ XT_HMARK_SPI,
+ XT_HMARK_SPI_MASK,
+ XT_HMARK_SPORT,
+ XT_HMARK_DPORT,
+ XT_HMARK_SPORT_MASK,
+ XT_HMARK_DPORT_MASK,
+ XT_HMARK_PROTO_MASK,
+ XT_HMARK_RND,
+ XT_HMARK_MODULUS,
+ XT_HMARK_OFFSET,
+ XT_HMARK_CT,
+ XT_HMARK_METHOD_L3,
+ XT_HMARK_METHOD_L3_4,
+};
+#define XT_HMARK_FLAG(flag) (1 << flag)
+
+union hmark_ports {
+ struct {
+ __u16 src;
+ __u16 dst;
+ } p16;
+ struct {
+ __be16 src;
+ __be16 dst;
+ } b16;
+ __u32 v32;
+ __be32 b32;
+};
+
+struct xt_hmark_info {
+ union nf_inet_addr src_mask;
+ union nf_inet_addr dst_mask;
+ union hmark_ports port_mask;
+ union hmark_ports port_set;
+ __u32 flags;
+ __u16 proto_mask;
+ __u32 hashrnd;
+ __u32 hmodulus;
+ __u32 hoffset; /* Mark offset to start from */
+};
+
+#endif /* XT_HMARK_H_ */
--- /dev/null
+#ifndef _XT_BPF_H
+#define _XT_BPF_H
+
+#include <linux/filter.h>
+#include <linux/types.h>
+
+#define XT_BPF_MAX_NUM_INSTR 64
+
+struct xt_bpf_info {
+ __u16 bpf_program_num_elem;
+ struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR];
+
+ /* only used in the kernel */
+ struct sk_filter *filter __attribute__((aligned(8)));
+};
+
+#endif /*_XT_BPF_H */
--- /dev/null
+#include <linux/types.h>
+
+#define XT_CONNLABEL_MAXBIT 127
+enum xt_connlabel_mtopts {
+ XT_CONNLABEL_OP_INVERT = 1 << 0,
+ XT_CONNLABEL_OP_SET = 1 << 1,
+};
+
+struct xt_connlabel_mtinfo {
+ __u16 bit;
+ __u16 options;
+};
XT_CONNTRACK_REPLSRC_PORT = 1 << 10,
XT_CONNTRACK_REPLDST_PORT = 1 << 11,
XT_CONNTRACK_DIRECTION = 1 << 12,
+ XT_CONNTRACK_STATE_ALIAS = 1 << 13,
};
struct xt_conntrack_mtinfo1 {
/* timings are in milliseconds. */
#define XT_HASHLIMIT_SCALE 10000
/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
- seconds, or one every 59 hours. */
+ seconds, or one packet every 59 hours. */
+
+/* packet length accounting is done in 16-byte steps */
+#define XT_HASHLIMIT_BYTE_SHIFT 4
/* details of this structure hidden by the implementation */
struct xt_hashlimit_htable;
XT_HASHLIMIT_HASH_SIP = 1 << 2,
XT_HASHLIMIT_HASH_SPT = 1 << 3,
XT_HASHLIMIT_INVERT = 1 << 4,
+ XT_HASHLIMIT_BYTES = 1 << 5,
};
struct hashlimit_cfg {
__u8 side;
};
+struct xt_recent_mtinfo_v1 {
+ __u32 seconds;
+ __u32 hit_count;
+ __u8 check_set;
+ __u8 invert;
+ char name[XT_RECENT_NAME_LEN];
+ __u8 side;
+ union nf_inet_addr mask;
+};
+
#endif /* _LINUX_NETFILTER_XT_RECENT_H */
enum {
/* Match against local time (instead of UTC) */
XT_TIME_LOCAL_TZ = 1 << 0,
+ XT_TIME_CONTIGUOUS = 1 << 1,
/* Shortcuts */
XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE,
--- /dev/null
+/*
+ * This is a module which is used for queueing IPv4 packets and
+ * communicating with userspace via netlink.
+ *
+ * (C) 2000 James Morris, this code is GPL.
+ */
+#ifndef _IP_QUEUE_H
+#define _IP_QUEUE_H
+
+#ifdef __KERNEL__
+#ifdef DEBUG_IPQ
+#define QDEBUG(x...) printk(KERN_DEBUG ## x)
+#else
+#define QDEBUG(x...)
+#endif /* DEBUG_IPQ */
+#else
+#include <net/if.h>
+#endif /* ! __KERNEL__ */
+
+/* Messages sent from kernel */
+typedef struct ipq_packet_msg {
+ unsigned long packet_id; /* ID of queued packet */
+ unsigned long mark; /* Netfilter mark value */
+ long timestamp_sec; /* Packet arrival time (seconds) */
+ long timestamp_usec; /* Packet arrvial time (+useconds) */
+ unsigned int hook; /* Netfilter hook we rode in on */
+ char indev_name[IFNAMSIZ]; /* Name of incoming interface */
+ char outdev_name[IFNAMSIZ]; /* Name of outgoing interface */
+ __be16 hw_protocol; /* Hardware protocol (network order) */
+ unsigned short hw_type; /* Hardware type */
+ unsigned char hw_addrlen; /* Hardware address length */
+ unsigned char hw_addr[8]; /* Hardware address */
+ size_t data_len; /* Length of packet data */
+ unsigned char payload[0]; /* Optional packet data */
+} ipq_packet_msg_t;
+
+/* Messages sent from userspace */
+typedef struct ipq_mode_msg {
+ unsigned char value; /* Requested mode */
+ size_t range; /* Optional range of packet requested */
+} ipq_mode_msg_t;
+
+typedef struct ipq_verdict_msg {
+ unsigned int value; /* Verdict to hand to netfilter */
+ unsigned long id; /* Packet ID for this verdict */
+ size_t data_len; /* Length of replacement data */
+ unsigned char payload[0]; /* Optional replacement packet */
+} ipq_verdict_msg_t;
+
+typedef struct ipq_peer_msg {
+ union {
+ ipq_verdict_msg_t verdict;
+ ipq_mode_msg_t mode;
+ } msg;
+} ipq_peer_msg_t;
+
+/* Packet delivery modes */
+enum {
+ IPQ_COPY_NONE, /* Initial mode, packets are dropped */
+ IPQ_COPY_META, /* Copy metadata */
+ IPQ_COPY_PACKET /* Copy metadata + packet (range) */
+};
+#define IPQ_COPY_MAX IPQ_COPY_PACKET
+
+/* Types of messages */
+#define IPQM_BASE 0x10 /* standard netlink messages below this */
+#define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */
+#define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */
+#define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */
+#define IPQM_MAX (IPQM_BASE + 4)
+
+#endif /*_IP_QUEUE_H*/
__u32 *iparray;
/* hangs off end. */
- struct nf_nat_range range[IPT_SAME_MAX_RANGE];
+ struct nf_nat_ipv4_range range[IPT_SAME_MAX_RANGE];
};
#endif /*_IPT_SAME_H*/
--- /dev/null
+#ifndef __NETFILTER_IP6T_NPT
+#define __NETFILTER_IP6T_NPT
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+struct ip6t_npt_tginfo {
+ union nf_inet_addr src_pfx;
+ union nf_inet_addr dst_pfx;
+ __u8 src_pfx_len;
+ __u8 dst_pfx_len;
+ /* Used internally by the kernel */
+ __sum16 adjustment;
+};
+
+#endif /* __NETFILTER_IP6T_NPT */
+++ /dev/null
-/* This file was manually copied from the Linux kernel source
- * and manually stripped from __KERNEL__ sections and unused functions.
- */
-
-/*
- * Definitions and Declarations for tuple.
- *
- * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
- * - generalize L3 protocol dependent part.
- *
- * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
- */
-
-#ifndef _NF_CONNTRACK_TUPLE_H
-#define _NF_CONNTRACK_TUPLE_H
-
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/nf_conntrack_tuple_common.h>
-
-/* A `tuple' is a structure containing the information to uniquely
- identify a connection. ie. if two packets have the same tuple, they
- are in the same connection; if not, they are not.
-
- We divide the structure along "manipulatable" and
- "non-manipulatable" lines, for the benefit of the NAT code.
-*/
-
-#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
-
-/* The protocol-specific manipulable parts of the tuple: always in
- network order! */
-union nf_conntrack_man_proto
-{
- /* Add other protocols here. */
- __be16 all;
-
- struct {
- __be16 port;
- } tcp;
- struct {
- __be16 port;
- } udp;
- struct {
- __be16 id;
- } icmp;
- struct {
- __be16 port;
- } dccp;
- struct {
- __be16 port;
- } sctp;
- struct {
- __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
- } gre;
-};
-
-/* The manipulable part of the tuple. */
-struct nf_conntrack_man
-{
- union nf_inet_addr u3;
- union nf_conntrack_man_proto u;
- /* Layer 3 protocol */
- u_int16_t l3num;
-};
-
-/* This contains the information to distinguish a connection. */
-struct nf_conntrack_tuple
-{
- struct nf_conntrack_man src;
-
- /* These are the parts of the tuple which are fixed. */
- struct {
- union nf_inet_addr u3;
- union {
- /* Add other protocols here. */
- __be16 all;
-
- struct {
- __be16 port;
- } tcp;
- struct {
- __be16 port;
- } udp;
- struct {
- u_int8_t type, code;
- } icmp;
- struct {
- __be16 port;
- } dccp;
- struct {
- __be16 port;
- } sctp;
- struct {
- __be16 key;
- } gre;
- } u;
-
- /* The protocol. */
- u_int8_t protonum;
-
- /* The direction (for tuplehash) */
- u_int8_t dir;
- } dst;
-};
-
-struct nf_conntrack_tuple_mask
-{
- struct {
- union nf_inet_addr u3;
- union nf_conntrack_man_proto u;
- } src;
-};
-
-#endif /* _NF_CONNTRACK_TUPLE_H */
+++ /dev/null
-#ifndef _NF_NAT_H
-#define _NF_NAT_H
-#include <linux/netfilter_ipv4.h>
-#include <net/netfilter/nf_conntrack_tuple.h>
-
-#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
-
-enum nf_nat_manip_type
-{
- IP_NAT_MANIP_SRC,
- IP_NAT_MANIP_DST
-};
-
-/* SRC manip occurs POST_ROUTING or LOCAL_IN */
-#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
- (hooknum) != NF_INET_LOCAL_IN)
-
-#define IP_NAT_RANGE_MAP_IPS 1
-#define IP_NAT_RANGE_PROTO_SPECIFIED 2
-#define IP_NAT_RANGE_PROTO_RANDOM 4
-#define IP_NAT_RANGE_PERSISTENT 8
-
-/* NAT sequence number modifications */
-struct nf_nat_seq {
- /* position of the last TCP sequence number modification (if any) */
- u_int32_t correction_pos;
-
- /* sequence number offset before and after last modification */
- int16_t offset_before, offset_after;
-};
-
-/* Single range specification. */
-struct nf_nat_range
-{
- /* Set to OR of flags above. */
- unsigned int flags;
-
- /* Inclusive: network order. */
- __be32 min_ip, max_ip;
-
- /* Inclusive: network order */
- union nf_conntrack_man_proto min, max;
-};
-
-/* For backwards compat: don't use in modern code. */
-struct nf_nat_multi_range_compat
-{
- unsigned int rangesize; /* Must be 1. */
-
- /* hangs off end. */
- struct nf_nat_range range[1];
-};
-
-#define nf_nat_multi_range nf_nat_multi_range_compat
-#endif
--- /dev/null
+#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@"
+#define XTABLES_VERSION_CODE @libxtables_vmajor@
#define IPPROTO_UDPLITE 136
#endif
-#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@"
-#define XTABLES_VERSION_CODE @libxtables_vmajor@
+#include <xtables-version.h>
struct in_addr;
struct xtables_lmap *next;
};
+enum xtables_ext_flags {
+ XTABLES_EXT_ALIAS = 1 << 0,
+};
+
/* Include file for additions: new matches and targets. */
struct xtables_match
{
struct xtables_match *next;
const char *name;
+ const char *real_name;
/* Revision of match (0 by default). */
u_int8_t revision;
+ /* Extension flags */
+ u_int8_t ext_flags;
+
u_int16_t family;
/* Size of match data. */
/* ip is struct ipt_ip * for example */
void (*save)(const void *ip, const struct xt_entry_match *match);
+ /* Print match name or alias */
+ const char *(*alias)(const struct xt_entry_match *match);
+
/* Pointer to list of extra command-line options */
const struct option *extra_opts;
const char *name;
+ /* Real target behind this, if any. */
+ const char *real_name;
+
/* Revision of target (0 by default). */
u_int8_t revision;
+ /* Extension flags */
+ u_int8_t ext_flags;
+
u_int16_t family;
void (*save)(const void *ip,
const struct xt_entry_target *target);
+ /* Print target name or alias */
+ const char *(*alias)(const struct xt_entry_target *target);
+
/* Pointer to list of extra command-line options */
const struct option *extra_opts;
extern struct xtables_target *xtables_find_target(const char *name,
enum xtables_tryload);
+extern void xtables_rule_matches_free(struct xtables_rule_match **matches);
+
/* Your shared library should call one of these. */
extern void xtables_register_match(struct xtables_match *me);
extern void xtables_register_matches(struct xtables_match *, unsigned int);
extern const char *xtables_ipmask_to_numeric(const struct in_addr *);
extern struct in_addr *xtables_numeric_to_ipaddr(const char *);
extern struct in_addr *xtables_numeric_to_ipmask(const char *);
+extern int xtables_ipmask_to_cidr(const struct in_addr *);
extern void xtables_ipparse_any(const char *, struct in_addr **,
struct in_addr *, unsigned int *);
extern void xtables_ipparse_multiple(const char *, struct in_addr **,
extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *);
extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *);
extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *);
+extern int xtables_ip6mask_to_cidr(const struct in6_addr *);
extern void xtables_ip6parse_any(const char *, struct in6_addr **,
struct in6_addr *, unsigned int *);
extern void xtables_ip6parse_multiple(const char *, struct in6_addr **,
*/
extern void xtables_save_string(const char *value);
+#define FMT_NUMERIC 0x0001
+#define FMT_NOCOUNTS 0x0002
+#define FMT_KILOMEGAGIGA 0x0004
+#define FMT_OPTIONS 0x0008
+#define FMT_NOTABLE 0x0010
+#define FMT_NOTARGET 0x0020
+#define FMT_VIA 0x0040
+#define FMT_NONEWLINE 0x0080
+#define FMT_LINENUMBERS 0x0100
+
+#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
+ | FMT_NUMERIC | FMT_NOTABLE)
+#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
+
+extern void xtables_print_num(uint64_t number, unsigned int format);
+
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
# ifdef _INIT
# undef _init
/ip6tables-static
/iptables
/iptables.8
+/iptables-extensions.8
/iptables-save
/iptables-restore
/iptables-static
sbin_PROGRAMS = xtables-multi
man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \
iptables-xml.1 ip6tables.8 ip6tables-restore.8 \
- ip6tables-save.8
+ ip6tables-save.8 iptables-extensions.8
CLEANFILES = iptables.8 ip6tables.8
vx_bin_links = iptables-xml
v6_sbin_links = ip6tables ip6tables-restore ip6tables-save
endif
-iptables.8: ${srcdir}/iptables.8.in ../extensions/matches4.man ../extensions/targets4.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches4.man' -e '/@TARGET@/ r ../extensions/targets4.man' $< >$@;
+iptables.8: ${srcdir}/iptables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
-ip6tables.8: ${srcdir}/ip6tables.8.in ../extensions/matches6.man ../extensions/targets6.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches6.man' -e '/@TARGET@/ r ../extensions/targets6.man' $< >$@;
+ip6tables.8: ${srcdir}/ip6tables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
+
+iptables-extensions.8: ${srcdir}/iptables-extensions.8.in ../extensions/matches.man ../extensions/targets.man
+ ${AM_VERBOSE_GEN} sed -e \
+ 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' \
+ -e '/@MATCH@/ r ../extensions/matches.man' \
+ -e '/@TARGET@/ r ../extensions/targets.man' $< >$@;
pkgconfig_DATA = xtables.pc
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
$(LDFLAGS) -o $@
SOURCES = $(xtables_multi_SOURCES)
DIST_SOURCES = $(am__xtables_multi_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
$(am__append_7) ../libxtables/libxtables.la -lm
man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \
iptables-xml.1 ip6tables.8 ip6tables-restore.8 \
- ip6tables-save.8
+ ip6tables-save.8 iptables-extensions.8
CLEANFILES = iptables.8 ip6tables.8
vx_bin_links = iptables-xml
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
-rm -rf .libs _libs
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'; \
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
install-man8: $(man_MANS)
@$(NORMAL_INSTALL)
- test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list=''; test -n "$(man8dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
- test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
uninstall-man8 uninstall-pkgconfigDATA uninstall-sbinPROGRAMS
-iptables.8: ${srcdir}/iptables.8.in ../extensions/matches4.man ../extensions/targets4.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches4.man' -e '/@TARGET@/ r ../extensions/targets4.man' $< >$@;
+iptables.8: ${srcdir}/iptables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
+
+ip6tables.8: ${srcdir}/ip6tables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
-ip6tables.8: ${srcdir}/ip6tables.8.in ../extensions/matches6.man ../extensions/targets6.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches6.man' -e '/@TARGET@/ r ../extensions/targets6.man' $< >$@;
+iptables-extensions.8: ${srcdir}/iptables-extensions.8.in ../extensions/matches.man ../extensions/targets.man
+ ${AM_VERBOSE_GEN} sed -e \
+ 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' \
+ -e '/@MATCH@/ r ../extensions/matches.man' \
+ -e '/@TARGET@/ r ../extensions/targets.man' $< >$@;
# Using if..fi avoids an ugly "error (ignored)" message :)
install-exec-hook:
.SH NAME
ip6tables-restore \(em Restore IPv6 Tables
.SH SYNOPSIS
-\fBip6tables\-restore\fP [\fB\-c\fP] [\fB\-n\fP]
+\fBip6tables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
+[\fB\-T\fP \fIname\fP]
.SH DESCRIPTION
.PP
.B ip6tables-restore
\fB\-c\fR, \fB\-\-counters\fR
restore the values of all packet and byte counters
.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print a short option summary.
+.TP
\fB\-n\fR, \fB\-\-noflush\fR
-don't flush the previous contents of the table. If not specified,
+don't flush the previous contents of the table. If not specified,
+\fBip6tables-restore\fP flushes (deletes) all previous contents of the
+respective table.
+.TP
+\fB\-t\fP, \fB\-\-test\fP
+Only parse and construct the ruleset, but do not commit it.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Print additional debug info during ruleset processing.
+.TP
+\fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP
+Specify the path to the modprobe program. By default, ip6tables-restore will
+inspect /proc/sys/kernel/modprobe to determine the executable's path.
.TP
\fB\-T\fP, \fB\-\-table\fP \fIname\fP
Restore only the named table even if the input stream contains other ones.
free(newargv[i]);
}
+static void add_param_to_argv(char *parsestart)
+{
+ int quote_open = 0, escaped = 0, param_len = 0;
+ char param_buffer[1024], *curchar;
+
+ /* After fighting with strtok enough, here's now
+ * a 'real' parser. According to Rusty I'm now no
+ * longer a real hacker, but I can live with that */
+
+ for (curchar = parsestart; *curchar; curchar++) {
+ if (quote_open) {
+ if (escaped) {
+ param_buffer[param_len++] = *curchar;
+ escaped = 0;
+ continue;
+ } else if (*curchar == '\\') {
+ escaped = 1;
+ continue;
+ } else if (*curchar == '"') {
+ quote_open = 0;
+ *curchar = ' ';
+ } else {
+ param_buffer[param_len++] = *curchar;
+ continue;
+ }
+ } else {
+ if (*curchar == '"') {
+ quote_open = 1;
+ continue;
+ }
+ }
+
+ if (*curchar == ' '
+ || *curchar == '\t'
+ || * curchar == '\n') {
+ if (!param_len) {
+ /* two spaces? */
+ continue;
+ }
+
+ param_buffer[param_len] = '\0';
+
+ /* check if table name specified */
+ if (!strncmp(param_buffer, "-t", 2)
+ || !strncmp(param_buffer, "--table", 8)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "The -t option (seen in line %u) cannot be "
+ "used in ip6tables-restore.\n", line);
+ exit(1);
+ }
+
+ add_argv(param_buffer);
+ param_len = 0;
+ } else {
+ /* regular character, copy to buffer */
+ param_buffer[param_len++] = *curchar;
+
+ if (param_len >= sizeof(param_buffer))
+ xtables_error(PARAMETER_PROBLEM,
+ "Parameter too long!");
+ }
+ }
+}
+
int ip6tables_restore_main(int argc, char *argv[])
{
struct xtc_handle *handle = NULL;
char *bcnt = NULL;
char *parsestart;
- /* the parser */
- char *curchar;
- int quote_open, escaped;
- size_t param_len;
-
/* reset the newargv */
newargc = 0;
add_argv((char *) bcnt);
}
- /* After fighting with strtok enough, here's now
- * a 'real' parser. According to Rusty I'm now no
- * longer a real hacker, but I can live with that */
-
- quote_open = 0;
- escaped = 0;
- param_len = 0;
-
- for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
- if (quote_open) {
- if (escaped) {
- param_buffer[param_len++] = *curchar;
- escaped = 0;
- continue;
- } else if (*curchar == '\\') {
- escaped = 1;
- continue;
- } else if (*curchar == '"') {
- quote_open = 0;
- *curchar = ' ';
- } else {
- param_buffer[param_len++] = *curchar;
- continue;
- }
- } else {
- if (*curchar == '"') {
- quote_open = 1;
- continue;
- }
- }
-
- if (*curchar == ' '
- || *curchar == '\t'
- || * curchar == '\n') {
- if (!param_len) {
- /* two spaces? */
- continue;
- }
-
- param_buffer[param_len] = '\0';
-
- /* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
- xtables_error(PARAMETER_PROBLEM,
- "Line %u seems to have a "
- "-t table option.\n", line);
- exit(1);
- }
-
- add_argv(param_buffer);
- param_len = 0;
- } else {
- /* regular character, copy to buffer */
- param_buffer[param_len++] = *curchar;
-
- if (param_len >= sizeof(param_buffer))
- xtables_error(PARAMETER_PROBLEM,
- "Parameter too long!");
- }
- }
+ add_param_to_argv(parsestart);
DEBUGP("calling do_command6(%u, argv, &%s, handle):\n",
newargc, curtable);
is matched, the target specified by the chain policy determines the
fate of the packet.
.SH TABLES
-There are currently three independent tables (which tables are present
+There are currently five independent tables (which tables are present
at any time depends on the kernel configuration options and which
modules are present).
.TP
\fBFORWARD\fP (for packets being routed through the box), and
\fBOUTPUT\fP (for locally-generated packets).
.TP
+\fBnat\fP:
+This table is consulted when a packet that creates a new
+connection is encountered. It consists of three built-ins: \fBPREROUTING\fP
+(for altering packets as soon as they come in), \fBOUTPUT\fP
+(for altering locally-generated packets before routing), and \fBPOSTROUTING\fP
+(for altering packets as they are about to go out). Available since kernel 3.7.
+.TP
\fBmangle\fP:
This table is used for specialized packet alteration. Until kernel
2.4.17 it had two built-in chains: \fBPREROUTING\fP
The following parameters make up a rule specification (as used in the
add, delete, insert, replace and append commands).
.TP
+\fB\-4\fP, \fB\-\-ipv4\fP
+If a rule using the \fB\-4\fP option is inserted with (and only with)
+ip6tables-restore, it will be silently ignored. Any other uses will throw an
+error. This option allows to put both IPv4 and IPv6 rules in a single rule file
+for use with both iptables-restore and ip6tables-restore.
+.TP
+\fB\-6\fP, \fB\-\-ipv6\fP
+This option has no effect in ip6tables and ip6tables-restore.
+.TP
[\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP
The protocol of the rule or of the packet to check.
The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP,
(source) flag for a detailed description of the syntax. The flag
\fB\-\-dst\fP is an alias for this option.
.TP
+\fB\-m\fP, \fB\-\-match\fP \fImatch\fP
+Specifies a match to use, that is, an extension module that tests for a
+specific property. The set of matches make up the condition under which a
+target is invoked. Matches are evaluated first to last as specified on the
+command line and work in short-circuit fashion, i.e. if one extension yields
+false, evaluation will stop.
+.TP
\fB\-j\fP, \fB\-\-jump\fP \fItarget\fP
This specifies the target of the rule; i.e., what to do if the packet
matches it. The target can be a user-defined chain (other than the
to load any necessary modules (targets, match extensions, etc).
.SH MATCH EXTENSIONS
.PP
-ip6tables can use extended packet matching modules
-with the \fB\-m\fP or \fB\-\-match\fP
-options, followed by the matching module name; after these, various
-extra command line options become available, depending on the specific
-module. You can specify multiple extended match modules in one line,
-and you can use the \fB\-h\fP or \fB\-\-help\fP
-options after the module has been specified to receive help specific
-to that module.
-.PP
-If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
-unknown option is encountered, ip6tables will try load a match module of the
-same name as the protocol, to try making the option available.
-.\" @MATCH@
-.SH TARGET EXTENSIONS
-ip6tables can use extended target modules: the following are included
-in the standard distribution.
-.\" @TARGET@
+iptables can use extended packet matching and target modules.
+A list of these is available in the \fBiptables\-extensions\fP(8) manpage.
.SH DIAGNOSTICS
Various error messages are printed to standard error. The exit code
is 0 for correct functioning. Errors which appear to be caused by
\fBip6tables\-save\fP(8),
\fBip6tables\-restore\fP(8),
\fBiptables\fP(8),
+\fBiptables\-apply\fP(8),
+\fBiptables\-extensions\fP(8),
\fBiptables\-save\fP(8),
\fBiptables\-restore\fP(8),
\fBlibipq\fP(3).
#define FALSE 0
#endif
-#define FMT_NUMERIC 0x0001
-#define FMT_NOCOUNTS 0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS 0x0008
-#define FMT_NOTABLE 0x0010
-#define FMT_NOTARGET 0x0020
-#define FMT_VIA 0x0040
-#define FMT_NONEWLINE 0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
- | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_CHECK 0x4000U
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
- 'Z', 'N', 'X', 'P', 'E', 'S', 'C' };
+ 'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
#define NUMBER_OF_OPT ARRAY_SIZE(optflags)
static const char optflags[]
"Options:\n"
" --ipv4 -4 Error (line is ignored by ip6tables-restore)\n"
" --ipv6 -6 Nothing (line is ignored by iptables-restore)\n"
-"[!] --proto -p proto protocol: by number or name, eg. `tcp'\n"
+"[!] --protocol -p proto protocol: by number or name, eg. `tcp'\n"
"[!] --source -s address[/mask][,...]\n"
" source specification\n"
"[!] --destination -d address[/mask][,...]\n"
}
}
-static void
-print_num(uint64_t number, unsigned int format)
-{
- if (format & FMT_KILOMEGAGIGA) {
- if (number > 99999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
- }
- else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
- }
- else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
- } else
- printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
- } else
- printf(FMT("%5llu ","%llu "), (unsigned long long)number);
- } else
- printf(FMT("%8llu ","%llu "), (unsigned long long)number);
-}
-
static void
print_header(unsigned int format, const char *chain, struct xtc_handle *handle)
printf(" (policy %s", pol);
if (!(format & FMT_NOCOUNTS)) {
fputc(' ', stdout);
- print_num(counters.pcnt, (format|FMT_NOTABLE));
+ xtables_print_num(counters.pcnt, (format|FMT_NOTABLE));
fputs("packets, ", stdout);
- print_num(counters.bcnt, (format|FMT_NOTABLE));
+ xtables_print_num(counters.bcnt, (format|FMT_NOTABLE));
fputs("bytes", stdout);
}
printf(")\n");
printf(FMT("%-4u ", "%u "), num);
if (!(format & FMT_NOCOUNTS)) {
- print_num(fw->counters.pcnt, format);
- print_num(fw->counters.bcnt, format);
+ xtables_print_num(fw->counters.pcnt, format);
+ xtables_print_num(fw->counters.bcnt, format);
}
if (!(format & FMT_NOTARGET))
xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL);
if (match) {
- printf(" -m %s", e->u.user.name);
+ printf(" -m %s",
+ match->alias ? match->alias(e) : e->u.user.name);
/* some matches don't provide a save function */
if (match->save)
const struct in6_addr *mask, int invert)
{
char buf[51];
- int l = ipv6_prefix_length(mask);
+ int l = xtables_ip6mask_to_cidr(mask);
if (l == 0 && !invert)
return;
if (counters < 0)
printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
- /* Print target name */
+ /* Print target name and targinfo part */
target_name = ip6tc_get_target(e, h);
- if (target_name && (*target_name != '\0'))
-#ifdef IP6T_F_GOTO
- printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name);
-#else
- printf(" -j %s", target_name);
-#endif
-
- /* Print targinfo part */
t = ip6t_get_target((struct ip6t_entry *)e);
if (t->u.user.name[0]) {
struct xtables_target *target =
exit(1);
}
+ printf(" -j %s", target->alias ? target->alias(t) : target_name);
if (target->save)
target->save(&e->ipv6, t);
else {
exit(1);
}
}
- }
+ } else if (target_name && (*target_name != '\0'))
+#ifdef IP6T_F_GOTO
+ printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name);
+#else
+ printf(" -j %s", target_name);
+#endif
+
printf("\n");
}
return e;
}
-static void clear_rule_matches(struct xtables_rule_match **matches)
-{
- struct xtables_rule_match *matchp, *tmp;
-
- for (matchp = *matches; matchp;) {
- tmp = matchp->next;
- if (matchp->match->m) {
- free(matchp->match->m);
- matchp->match->m = NULL;
- }
- if (matchp->match == matchp->match->next) {
- free(matchp->match);
- matchp->match = NULL;
- }
- free(matchp);
- matchp = tmp;
- }
-
- *matches = NULL;
-}
-
static void command_jump(struct iptables_command_state *cs)
{
size_t size;
cs->target->t = xtables_calloc(1, size);
cs->target->t->u.target_size = size;
- strcpy(cs->target->t->u.user.name, cs->jumpto);
+ if (cs->target->real_name == NULL) {
+ strcpy(cs->target->t->u.user.name, cs->jumpto);
+ } else {
+ strcpy(cs->target->t->u.user.name, cs->target->real_name);
+ if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
+ fprintf(stderr, "Notice: The %s target is converted into %s target "
+ "in rule listing and saving.\n",
+ cs->jumpto, cs->target->real_name);
+ }
cs->target->t->u.user.revision = cs->target->revision;
+
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts,
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
m->m = xtables_calloc(1, size);
m->m->u.match_size = size;
- strcpy(m->m->u.user.name, m->name);
+ if (m->real_name == NULL) {
+ strcpy(m->m->u.user.name, m->name);
+ } else {
+ strcpy(m->m->u.user.name, m->real_name);
+ if (!(m->ext_flags & XTABLES_EXT_ALIAS))
+ fprintf(stderr, "Notice: The %s match is converted into %s match "
+ "in rule listing and saving.\n", m->name, m->real_name);
+ }
m->m->u.user.revision = m->revision;
+
xs_init_match(m);
if (m == m->next)
return;
if (verbose > 1)
dump_entries6(*handle);
- clear_rule_matches(&cs.matches);
+ xtables_rule_matches_free(&cs.matches);
if (e != NULL) {
free(e);
case, the script rolls back to the previous ruleset after the timeout
expired. The timeout can be set with \fB\-t\fP.
.PP
-When called as ip6tables\-apply, the script will use
+When called as \fBip6tables\-apply\fP, the script will use
ip6tables\-save/\-restore instead.
.SH OPTIONS
.TP
--- /dev/null
+.TH iptables-extensions 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@"
+.SH NAME
+iptables-extensions \(em list of extensions in the standard iptables distribution
+.SH SYNOPSIS
+\fBip6tables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]]
+[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...]
+.PP
+\fBiptables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]]
+[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...]
+.SH MATCH EXTENSIONS
+iptables can use extended packet matching modules
+with the \fB\-m\fP or \fB\-\-match\fP
+options, followed by the matching module name; after these, various
+extra command line options become available, depending on the specific
+module. You can specify multiple extended match modules in one line,
+and you can use the \fB\-h\fP or \fB\-\-help\fP
+options after the module has been specified to receive help specific
+to that module. The extended match modules are evaluated in the order
+they are specified in the rule.
+.PP
+If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
+unknown option is encountered, iptables will try load a match module of the
+same name as the protocol, to try making the option available.
+.\" @MATCH@
+.SH TARGET EXTENSIONS
+iptables can use extended target modules: the following are included
+in the standard distribution.
+.\" @TARGET@
.SH NAME
iptables-restore \(em Restore IP Tables
.SH SYNOPSIS
-\fBiptables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] [\fB\-T\fP \fIname\fP]
+\fBiptables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
+[\fB\-T\fP \fIname\fP]
.SH DESCRIPTION
.PP
.B iptables-restore
\fB\-c\fR, \fB\-\-counters\fR
restore the values of all packet and byte counters
.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print a short option summary.
+.TP
\fB\-n\fR, \fB\-\-noflush\fR
don't flush the previous contents of the table. If not specified,
.B iptables-restore
-flushes (deletes) all previous contents of the respective IP Table.
+flushes (deletes) all previous contents of the respective table.
+.TP
+\fB\-t\fP, \fB\-\-test\fP
+Only parse and construct the ruleset, but do not commit it.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Print additional debug info during ruleset processing.
+.TP
+\fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP
+Specify the path to the modprobe program. By default, iptables-restore will
+inspect /proc/sys/kernel/modprobe to determine the executable's path.
.TP
\fB\-T\fP, \fB\-\-table\fP \fIname\fP
Restore only the named table even if the input stream contains other ones.
free(newargv[i]);
}
+static void add_param_to_argv(char *parsestart)
+{
+ int quote_open = 0, escaped = 0, param_len = 0;
+ char param_buffer[1024], *curchar;
+
+ /* After fighting with strtok enough, here's now
+ * a 'real' parser. According to Rusty I'm now no
+ * longer a real hacker, but I can live with that */
+
+ for (curchar = parsestart; *curchar; curchar++) {
+ if (quote_open) {
+ if (escaped) {
+ param_buffer[param_len++] = *curchar;
+ escaped = 0;
+ continue;
+ } else if (*curchar == '\\') {
+ escaped = 1;
+ continue;
+ } else if (*curchar == '"') {
+ quote_open = 0;
+ *curchar = ' ';
+ } else {
+ param_buffer[param_len++] = *curchar;
+ continue;
+ }
+ } else {
+ if (*curchar == '"') {
+ quote_open = 1;
+ continue;
+ }
+ }
+
+ if (*curchar == ' '
+ || *curchar == '\t'
+ || * curchar == '\n') {
+ if (!param_len) {
+ /* two spaces? */
+ continue;
+ }
+
+ param_buffer[param_len] = '\0';
+
+ /* check if table name specified */
+ if (!strncmp(param_buffer, "-t", 2)
+ || !strncmp(param_buffer, "--table", 8)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "The -t option (seen in line %u) cannot be "
+ "used in iptables-restore.\n", line);
+ exit(1);
+ }
+
+ add_argv(param_buffer);
+ param_len = 0;
+ } else {
+ /* regular character, copy to buffer */
+ param_buffer[param_len++] = *curchar;
+
+ if (param_len >= sizeof(param_buffer))
+ xtables_error(PARAMETER_PROBLEM,
+ "Parameter too long!");
+ }
+ }
+}
+
int
iptables_restore_main(int argc, char *argv[])
{
char *bcnt = NULL;
char *parsestart;
- /* the parser */
- char *curchar;
- int quote_open, escaped;
- size_t param_len;
-
/* reset the newargv */
newargc = 0;
add_argv((char *) bcnt);
}
- /* After fighting with strtok enough, here's now
- * a 'real' parser. According to Rusty I'm now no
- * longer a real hacker, but I can live with that */
-
- quote_open = 0;
- escaped = 0;
- param_len = 0;
-
- for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
- if (quote_open) {
- if (escaped) {
- param_buffer[param_len++] = *curchar;
- escaped = 0;
- continue;
- } else if (*curchar == '\\') {
- escaped = 1;
- continue;
- } else if (*curchar == '"') {
- quote_open = 0;
- *curchar = ' ';
- } else {
- param_buffer[param_len++] = *curchar;
- continue;
- }
- } else {
- if (*curchar == '"') {
- quote_open = 1;
- continue;
- }
- }
-
- if (*curchar == ' '
- || *curchar == '\t'
- || * curchar == '\n') {
- if (!param_len) {
- /* two spaces? */
- continue;
- }
-
- param_buffer[param_len] = '\0';
-
- /* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
- xtables_error(PARAMETER_PROBLEM,
- "Line %u seems to have a "
- "-t table option.\n", line);
- exit(1);
- }
-
- add_argv(param_buffer);
- param_len = 0;
- } else {
- /* regular character, copy to buffer */
- param_buffer[param_len++] = *curchar;
-
- if (param_len >= sizeof(param_buffer))
- xtables_error(PARAMETER_PROBLEM,
- "Parameter too long!");
- }
- }
+ add_param_to_argv(parsestart);
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
newargc, curtable);
is matched, the target specified by the chain policy determines the
fate of the packet.
.SH TABLES
-There are currently three independent tables (which tables are present
+There are currently five independent tables (which tables are present
at any time depends on the kernel configuration options and which
modules are present).
.TP
The following parameters make up a rule specification (as used in the
add, delete, insert, replace and append commands).
.TP
+\fB\-4\fP, \fB\-\-ipv4\fP
+This option has no effect in iptables and iptables-restore.
+.TP
+\fB\-6\fP, \fB\-\-ipv6\fP
+If a rule using the \fB\-6\fP option is inserted with (and only with)
+iptables-restore, it will be silently ignored. Any other uses will throw an
+error. This option allows to put both IPv4 and IPv6 rules in a single rule file
+for use with both iptables-restore and ip6tables-restore.
+.TP
[\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP
The protocol of the rule or of the packet to check.
The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP,
(source) flag for a detailed description of the syntax. The flag
\fB\-\-dst\fP is an alias for this option.
.TP
+\fB\-m\fP, \fB\-\-match\fP \fImatch\fP
+Specifies a match to use, that is, an extension module that tests for a
+specific property. The set of matches make up the condition under which a
+target is invoked. Matches are evaluated first to last as specified on the
+command line and work in short-circuit fashion, i.e. if one extension yields
+false, evaluation will stop.
+.TP
\fB\-j\fP, \fB\-\-jump\fP \fItarget\fP
This specifies the target of the rule; i.e., what to do if the packet
matches it. The target can be a user-defined chain (other than the
\fB\-\-modprobe=\fP\fIcommand\fP
When adding or inserting rules into a chain, use \fIcommand\fP
to load any necessary modules (targets, match extensions, etc).
-.SH MATCH EXTENSIONS
-.PP
-iptables can use extended packet matching modules
-with the \fB\-m\fP or \fB\-\-match\fP
-options, followed by the matching module name; after these, various
-extra command line options become available, depending on the specific
-module. You can specify multiple extended match modules in one line,
-and you can use the \fB\-h\fP or \fB\-\-help\fP
-options after the module has been specified to receive help specific
-to that module.
+.SH MATCH AND TARGET EXTENSIONS
.PP
-If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
-unknown option is encountered, iptables will try load a match module of the
-same name as the protocol, to try making the option available.
-.\" @MATCH@
-.SH TARGET EXTENSIONS
-iptables can use extended target modules: the following are included
-in the standard distribution.
-.\" @TARGET@
+iptables can use extended packet matching and target modules.
+A list of these is available in the \fBiptables\-extensions\fP(8) manpage.
.SH DIAGNOSTICS
Various error messages are printed to standard error. The exit code
is 0 for correct functioning. Errors which appear to be caused by
.fi
There are several other changes in iptables.
.SH SEE ALSO
+\fBiptables\-apply\fP(8),
\fBiptables\-save\fP(8),
\fBiptables\-restore\fP(8),
+\fBiptables\-extensions\fP(8),
\fBip6tables\fP(8),
\fBip6tables\-save\fP(8),
\fBip6tables\-restore\fP(8),
#define FALSE 0
#endif
-#define FMT_NUMERIC 0x0001
-#define FMT_NOCOUNTS 0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS 0x0008
-#define FMT_NOTABLE 0x0010
-#define FMT_NOTARGET 0x0020
-#define FMT_VIA 0x0040
-#define FMT_NONEWLINE 0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
- | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_CHECK 0x4000U
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
- 'Z', 'N', 'X', 'P', 'E', 'S', 'C' };
+ 'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
#define OPT_FRAGMENT 0x00800U
#define NUMBER_OF_OPT ARRAY_SIZE(optflags)
#define prog_name iptables_globals.program_name
#define prog_vers iptables_globals.program_version
-/* Primitive headers... */
-/* defined in netinet/in.h */
-#if 0
-#ifndef IPPROTO_ESP
-#define IPPROTO_ESP 50
-#endif
-#ifndef IPPROTO_AH
-#define IPPROTO_AH 51
-#endif
-#endif
-
-enum {
- IPT_DOTTED_ADDR = 0,
- IPT_DOTTED_MASK
-};
-
static void __attribute__((noreturn))
exit_tryhelp(int status)
{
"Options:\n"
" --ipv4 -4 Nothing (line is ignored by ip6tables-restore)\n"
" --ipv6 -6 Error (line is ignored by iptables-restore)\n"
-"[!] --proto -p proto protocol: by number or name, eg. `tcp'\n"
+"[!] --protocol -p proto protocol: by number or name, eg. `tcp'\n"
"[!] --source -s address[/mask][...]\n"
" source specification\n"
"[!] --destination -d address[/mask][...]\n"
}
static void
-print_num(uint64_t number, unsigned int format)
-{
- if (format & FMT_KILOMEGAGIGA) {
- if (number > 99999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- if (number > 9999) {
- number = (number + 500) / 1000;
- printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
- }
- else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
- }
- else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
- } else
- printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
- } else
- printf(FMT("%5llu ","%llu "), (unsigned long long)number);
- } else
- printf(FMT("%8llu ","%llu "), (unsigned long long)number);
-}
-
-
-static void
print_header(unsigned int format, const char *chain, struct xtc_handle *handle)
{
struct xt_counters counters;
printf(" (policy %s", pol);
if (!(format & FMT_NOCOUNTS)) {
fputc(' ', stdout);
- print_num(counters.pcnt, (format|FMT_NOTABLE));
+ xtables_print_num(counters.pcnt, (format|FMT_NOTABLE));
fputs("packets, ", stdout);
- print_num(counters.bcnt, (format|FMT_NOTABLE));
+ xtables_print_num(counters.bcnt, (format|FMT_NOTABLE));
fputs("bytes", stdout);
}
printf(")\n");
printf(FMT("%-4u ", "%u "), num);
if (!(format & FMT_NOCOUNTS)) {
- print_num(fw->counters.pcnt, format);
- print_num(fw->counters.bcnt, format);
+ xtables_print_num(fw->counters.pcnt, format);
+ xtables_print_num(fw->counters.bcnt, format);
}
if (!(format & FMT_NOTARGET))
xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL);
if (match) {
- printf(" -m %s", e->u.user.name);
+ printf(" -m %s",
+ match->alias ? match->alias(e) : e->u.user.name);
/* some matches don't provide a save function */
if (match->save)
if (counters < 0)
printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
- /* Print target name */
+ /* Print target name and targinfo part */
target_name = iptc_get_target(e, h);
- if (target_name && (*target_name != '\0'))
-#ifdef IPT_F_GOTO
- printf(" -%c %s", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name);
-#else
- printf(" -j %s", target_name);
-#endif
-
- /* Print targinfo part */
t = ipt_get_target((struct ipt_entry *)e);
if (t->u.user.name[0]) {
const struct xtables_target *target =
exit(1);
}
+ printf(" -j %s", target->alias ? target->alias(t) : target_name);
if (target->save)
target->save(&e->ip, t);
else {
exit(1);
}
}
- }
+ } else if (target_name && (*target_name != '\0'))
+#ifdef IPT_F_GOTO
+ printf(" -%c %s", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name);
+#else
+ printf(" -j %s", target_name);
+#endif
+
printf("\n");
}
return e;
}
-static void clear_rule_matches(struct xtables_rule_match **matches)
-{
- struct xtables_rule_match *matchp, *tmp;
-
- for (matchp = *matches; matchp;) {
- tmp = matchp->next;
- if (matchp->match->m) {
- free(matchp->match->m);
- matchp->match->m = NULL;
- }
- if (matchp->match == matchp->match->next) {
- free(matchp->match);
- matchp->match = NULL;
- }
- free(matchp);
- matchp = tmp;
- }
-
- *matches = NULL;
-}
-
static void command_jump(struct iptables_command_state *cs)
{
size_t size;
cs->target->t = xtables_calloc(1, size);
cs->target->t->u.target_size = size;
- strcpy(cs->target->t->u.user.name, cs->jumpto);
+ if (cs->target->real_name == NULL) {
+ strcpy(cs->target->t->u.user.name, cs->jumpto);
+ } else {
+ /* Alias support for userspace side */
+ strcpy(cs->target->t->u.user.name, cs->target->real_name);
+ if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
+ fprintf(stderr, "Notice: The %s target is converted into %s target "
+ "in rule listing and saving.\n",
+ cs->jumpto, cs->target->real_name);
+ }
cs->target->t->u.user.revision = cs->target->revision;
+
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
m->m = xtables_calloc(1, size);
m->m->u.match_size = size;
- strcpy(m->m->u.user.name, m->name);
+ if (m->real_name == NULL) {
+ strcpy(m->m->u.user.name, m->name);
+ } else {
+ strcpy(m->m->u.user.name, m->real_name);
+ if (!(m->ext_flags & XTABLES_EXT_ALIAS))
+ fprintf(stderr, "Notice: the %s match is converted into %s match "
+ "in rule listing and saving.\n", m->name, m->real_name);
+ }
m->m->u.user.revision = m->revision;
+
xs_init_match(m);
if (m == m->next)
return;
if (verbose > 1)
dump_entries(*handle);
- clear_rule_matches(&cs.matches);
+ xtables_rule_matches_free(&cs.matches);
if (e != NULL) {
free(e);
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
$(LDFLAGS) -o $@
SOURCES = $(libipq_la_SOURCES)
DIST_SOURCES = $(libipq_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
man3dir = $(mandir)/man3
NROFF = nroff
MANS = $(man_MANS)
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
-rm -rf .libs _libs
install-man3: $(man_MANS)
@$(NORMAL_INSTALL)
- test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
- @list=''; test -n "$(man3dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.3[a-z]*$$/p'; \
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man3dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.3[a-z]*$$/p'; \
+ fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir)
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
- test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
$(libiptc_la_SOURCES)
DIST_SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES) \
$(libiptc_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
DATA = $(pkgconfig_DATA)
ETAGS = etags
CTAGS = ctags
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
-rm -rf .libs _libs
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
- test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
#define BIT6(a, l) \
((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
-int
+static int
ipv6_prefix_length(const struct in6_addr *a)
{
int l, i;
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# -*- Makefile -*-
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
$(LDFLAGS) -o $@
SOURCES = $(libxtables_la_SOURCES)
DIST_SOURCES = $(libxtables_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
xtables_pending_matches = me;
}
+/**
+ * Compare two actions for their preference
+ * @a: one action
+ * @b: another
+ *
+ * Like strcmp, returns a negative number if @a is less preferred than @b,
+ * positive number if @a is more preferred than @b, or zero if equally
+ * preferred.
+ */
+static int
+xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam,
+ bool b_alias, unsigned int b_rev, unsigned int b_fam)
+{
+ /*
+ * Alias ranks higher than no alias.
+ * (We want the new action to be used whenever possible.)
+ */
+ if (!a_alias && b_alias)
+ return -1;
+ if (a_alias && !b_alias)
+ return 1;
+
+ /* Higher revision ranks higher. */
+ if (a_rev < b_rev)
+ return -1;
+ if (a_rev > b_rev)
+ return 1;
+
+ /* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */
+ if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC)
+ return -1;
+ if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC)
+ return 1;
+
+ /* Must be the same thing. */
+ return 0;
+}
+
+static int xtables_match_prefer(const struct xtables_match *a,
+ const struct xtables_match *b)
+{
+ return xtables_mt_prefer(a->real_name != NULL,
+ a->revision, a->family,
+ b->real_name != NULL,
+ b->revision, b->family);
+}
+
+static int xtables_target_prefer(const struct xtables_target *a,
+ const struct xtables_target *b)
+{
+ /*
+ * Note that if x->real_name==NULL, it will be set to x->name in
+ * xtables_register_*; the direct pointer comparison here is therefore
+ * legitimate to detect an alias.
+ */
+ return xtables_mt_prefer(a->real_name != NULL,
+ a->revision, a->family,
+ b->real_name != NULL,
+ b->revision, b->family);
+}
+
static void xtables_fully_register_pending_match(struct xtables_match *me)
{
struct xtables_match **i, *old;
+ const char *rn;
+ int compare;
old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
if (old) {
- if (old->revision == me->revision &&
- old->family == me->family) {
+ compare = xtables_match_prefer(old, me);
+ if (compare == 0) {
fprintf(stderr,
"%s: match `%s' already registered.\n",
xt_params->program_name, me->name);
}
/* Now we have two (or more) options, check compatibility. */
- if (compatible_match_revision(old->name, old->revision)
- && old->revision > me->revision)
+ rn = (old->real_name != NULL) ? old->real_name : old->name;
+ if (compare > 0 &&
+ compatible_match_revision(rn, old->revision))
return;
/* See if new match can be used. */
- if (!compatible_match_revision(me->name, me->revision))
- return;
-
- /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
- if (old->revision == me->revision && me->family == AF_UNSPEC)
+ rn = (me->real_name != NULL) ? me->real_name : me->name;
+ if (!compatible_match_revision(rn, me->revision))
return;
/* Delete old one. */
static void xtables_fully_register_pending_target(struct xtables_target *me)
{
struct xtables_target *old;
+ const char *rn;
+ int compare;
old = xtables_find_target(me->name, XTF_DURING_LOAD);
if (old) {
struct xtables_target **i;
- if (old->revision == me->revision &&
- old->family == me->family) {
+ compare = xtables_target_prefer(old, me);
+ if (compare == 0) {
fprintf(stderr,
"%s: target `%s' already registered.\n",
xt_params->program_name, me->name);
}
/* Now we have two (or more) options, check compatibility. */
- if (compatible_target_revision(old->name, old->revision)
- && old->revision > me->revision)
+ rn = (old->real_name != NULL) ? old->real_name : old->name;
+ if (compare > 0 &&
+ compatible_target_revision(rn, old->revision))
return;
/* See if new target can be used. */
- if (!compatible_target_revision(me->name, me->revision))
- return;
-
- /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
- if (old->revision == me->revision && me->family == AF_UNSPEC)
+ rn = (me->real_name != NULL) ? me->real_name : me->name;
+ if (!compatible_target_revision(rn, me->revision))
return;
/* Delete old one. */
} while (n > 0);
}
+/* receives a list of xtables_rule_match, release them */
+void xtables_rule_matches_free(struct xtables_rule_match **matches)
+{
+ struct xtables_rule_match *matchp, *tmp;
+
+ for (matchp = *matches; matchp;) {
+ tmp = matchp->next;
+ if (matchp->match->m) {
+ free(matchp->match->m);
+ matchp->match->m = NULL;
+ }
+ if (matchp->match == matchp->match->next) {
+ free(matchp->match);
+ matchp->match = NULL;
+ }
+ free(matchp);
+ matchp = tmp;
+ }
+
+ *matches = NULL;
+}
+
/**
* xtables_param_act - act on condition
* @status: a constant from enum xtables_exittype
return xtables_ipaddr_to_numeric(addr);
}
-const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
+int xtables_ipmask_to_cidr(const struct in_addr *mask)
{
- static char buf[20];
uint32_t maskaddr, bits;
int i;
maskaddr = ntohl(mask->s_addr);
-
+ /* shortcut for /32 networks */
if (maskaddr == 0xFFFFFFFFL)
- /* we don't want to see "/32" */
- return "";
+ return 32;
i = 32;
bits = 0xFFFFFFFEL;
while (--i >= 0 && maskaddr != bits)
bits <<= 1;
if (i >= 0)
- sprintf(buf, "/%d", i);
- else
+ return i;
+
+ /* this mask cannot be converted to CIDR notation */
+ return -1;
+}
+
+const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
+{
+ static char buf[20];
+ uint32_t cidr;
+
+ cidr = xtables_ipmask_to_cidr(mask);
+ if (cidr < 0) {
/* mask was not a decent combination of 1's and 0's */
sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
+ return buf;
+ } else if (cidr == 32) {
+ /* we don't want to see "/32" */
+ return "";
+ }
+ sprintf(buf, "/%d", cidr);
return buf;
}
return xtables_ip6addr_to_numeric(addr);
}
-static int ip6addr_prefix_length(const struct in6_addr *k)
+int xtables_ip6mask_to_cidr(const struct in6_addr *k)
{
unsigned int bits = 0;
uint32_t a, b, c, d;
const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
{
static char buf[50+2];
- int l = ip6addr_prefix_length(addrp);
+ int l = xtables_ip6mask_to_cidr(addrp);
if (l == -1) {
strcpy(buf, "/");
return -1;
}
+void xtables_print_num(uint64_t number, unsigned int format)
+{
+ if (!(format & FMT_KILOMEGAGIGA)) {
+ printf(FMT("%8llu ","%llu "), (unsigned long long)number);
+ return;
+ }
+ if (number <= 99999) {
+ printf(FMT("%5llu ","%llu "), (unsigned long long)number);
+ return;
+ }
+ number = (number + 500) / 1000;
+ if (number <= 9999) {
+ printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
+ return;
+ }
+ number = (number + 500) / 1000;
+ if (number <= 9999) {
+ printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
+ return;
+ }
+ number = (number + 500) / 1000;
+ if (number <= 9999) {
+ printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
+ return;
+ }
+ number = (number + 500) / 1000;
+ printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
+}
+
int kernel_version;
void get_kernel_version(void)
free(lo_arg);
}
+static int xtopt_parse_mask(struct xt_option_call *cb)
+{
+ struct addrinfo hints = {.ai_family = afinfo->family,
+ .ai_flags = AI_NUMERICHOST };
+ struct addrinfo *res;
+ int ret;
+
+ ret = getaddrinfo(cb->arg, NULL, &hints, &res);
+ if (ret < 0)
+ return 0;
+
+ memcpy(&cb->val.hmask, xtables_sa_host(res->ai_addr, res->ai_family),
+ xtables_sa_hostlen(res->ai_family));
+
+ switch(afinfo->family) {
+ case AF_INET:
+ cb->val.hlen = xtables_ipmask_to_cidr(&cb->val.hmask.in);
+ break;
+ case AF_INET6:
+ cb->val.hlen = xtables_ip6mask_to_cidr(&cb->val.hmask.in6);
+ break;
+ }
+
+ freeaddrinfo(res);
+ return 1;
+}
+
/**
* Parse an integer and ensure it is within the address family's prefix length
* limits. The result is stored in @cb->val.hlen.
unsigned int prefix_len = 128; /* happiness is a warm gcc */
cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
- if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen))
+ if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) {
+ /* Is this mask expressed in full format? e.g. 255.255.255.0 */
+ if (xtopt_parse_mask(cb))
+ return;
+
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: bad value for option \"--%s\", "
- "or out of range (%u-%u).\n",
+ "neither a valid network mask "
+ "nor valid CIDR (%u-%u).\n",
cb->ext_name, entry->name, 0, cb->val.hlen);
-
+ }
cb->val.hlen = prefix_len;
}
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
;;
ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
esac
;;
-gnu*)
- version_type=linux # correct to gnu/linux during the next big refactor
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
fi
;;
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
;;
esac
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# KAI C++ Compiler
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
# old Intel for x86_64 which still supported -KPIC.
ecc*)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
- gnu*)
- ;;
-
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(inherit_rpath, $1)=yes
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
-A matches -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 1 --hashlimit-name mini2
-A matches -m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 1 --hashlimit-name mini3
-A matches -m hashlimit --hashlimit-upto 1/day --hashlimit-burst 1 --hashlimit-name mini4
+-A matches -m hashlimit --hashlimit-upto 4kb/s --hashlimit-burst 400kb --hashlimit-name mini5
+-A matches -m hashlimit --hashlimit-upto 10mb/s --hashlimit-name mini6
+-A matches -m hashlimit --hashlimit-upto 123456b/s --hashlimit-burst 1mb --hashlimit-name mini7
-A matches
-A matches -m hbh ! --hbh-len 5
-A matches
/nfnl_osf
+/nfbpf_compile
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \
-I${top_srcdir}/include ${libnfnetlink_CFLAGS}
-sbin_PROGRAMS = nfnl_osf
-pkgdata_DATA = pf.os
+sbin_PROGRAMS =
+pkgdata_DATA =
-nfnl_osf_LDADD = -lnfnetlink
+if HAVE_LIBNFNETLINK
+sbin_PROGRAMS += nfnl_osf
+pkgdata_DATA += pf.os
+
+nfnl_osf_LDADD = ${libnfnetlink_LIBS}
+endif
+
+if ENABLE_BPFC
+sbin_PROGRAMS += nfbpf_compile
+nfbpf_compile_LDADD = -lpcap
+endif
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-sbin_PROGRAMS = nfnl_osf$(EXEEXT)
+sbin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
+@HAVE_LIBNFNETLINK_TRUE@am__append_1 = nfnl_osf
+@HAVE_LIBNFNETLINK_TRUE@am__append_2 = pf.os
+@ENABLE_BPFC_TRUE@am__append_3 = nfbpf_compile
subdir = utils
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+@HAVE_LIBNFNETLINK_TRUE@am__EXEEXT_1 = nfnl_osf$(EXEEXT)
+@ENABLE_BPFC_TRUE@am__EXEEXT_2 = nfbpf_compile$(EXEEXT)
am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkgdatadir)"
PROGRAMS = $(sbin_PROGRAMS)
+nfbpf_compile_SOURCES = nfbpf_compile.c
+nfbpf_compile_OBJECTS = nfbpf_compile.$(OBJEXT)
+nfbpf_compile_DEPENDENCIES =
nfnl_osf_SOURCES = nfnl_osf.c
nfnl_osf_OBJECTS = nfnl_osf.$(OBJEXT)
-nfnl_osf_DEPENDENCIES =
+am__DEPENDENCIES_1 =
+@HAVE_LIBNFNETLINK_TRUE@nfnl_osf_DEPENDENCIES = $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = nfnl_osf.c
-DIST_SOURCES = nfnl_osf.c
+SOURCES = nfbpf_compile.c nfnl_osf.c
+DIST_SOURCES = nfbpf_compile.c nfnl_osf.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \
-I${top_srcdir}/include ${libnfnetlink_CFLAGS}
-pkgdata_DATA = pf.os
-nfnl_osf_LDADD = -lnfnetlink
+pkgdata_DATA = $(am__append_2)
+@HAVE_LIBNFNETLINK_TRUE@nfnl_osf_LDADD = ${libnfnetlink_LIBS}
+@ENABLE_BPFC_TRUE@nfbpf_compile_LDADD = -lpcap
all: all-am
.SUFFIXES:
$(am__aclocal_m4_deps):
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+nfbpf_compile$(EXEEXT): $(nfbpf_compile_OBJECTS) $(nfbpf_compile_DEPENDENCIES) $(EXTRA_nfbpf_compile_DEPENDENCIES)
+ @rm -f nfbpf_compile$(EXEEXT)
+ $(LINK) $(nfbpf_compile_OBJECTS) $(nfbpf_compile_LDADD) $(LIBS)
nfnl_osf$(EXEEXT): $(nfnl_osf_OBJECTS) $(nfnl_osf_DEPENDENCIES) $(EXTRA_nfnl_osf_DEPENDENCIES)
@rm -f nfnl_osf$(EXEEXT)
$(LINK) $(nfnl_osf_OBJECTS) $(nfnl_osf_LDADD) $(LIBS)
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfbpf_compile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfnl_osf.Po@am__quote@
.c.o:
-rm -rf .libs _libs
install-pkgdataDATA: $(pkgdata_DATA)
@$(NORMAL_INSTALL)
- test -z "$(pkgdatadir)" || $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)"
@list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
--- /dev/null
+/*
+ * BPF program compilation tool
+ *
+ * Generates decimal output, similar to `tcpdump -ddd ...`.
+ * Unlike tcpdump, will generate for any given link layer type.
+ *
+ * Written by Willem de Bruijn (willemb@google.com)
+ * Copyright Google, Inc. 2013
+ * Licensed under the GNU General Public License version 2 (GPLv2)
+*/
+
+#include <pcap.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ struct bpf_program program;
+ struct bpf_insn *ins;
+ int i, dlt = DLT_RAW;
+
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "Usage: %s [link] '<program>'\n\n"
+ " link is a pcap linklayer type:\n"
+ " one of EN10MB, RAW, SLIP, ...\n\n"
+ "Examples: %s RAW 'tcp and greater 100'\n"
+ " %s EN10MB 'ip proto 47'\n'",
+ argv[0], argv[0], argv[0]);
+ return 1;
+ }
+
+ if (argc == 3) {
+ dlt = pcap_datalink_name_to_val(argv[1]);
+ if (dlt == -1) {
+ fprintf(stderr, "Unknown datalinktype: %s\n", argv[1]);
+ return 1;
+ }
+ }
+
+ if (pcap_compile_nopcap(65535, dlt, &program, argv[argc - 1], 1,
+ PCAP_NETMASK_UNKNOWN)) {
+ fprintf(stderr, "Compilation error\n");
+ return 1;
+ }
+
+ printf("%d,", program.bf_len);
+ ins = program.bf_insns;
+ for (i = 0; i < program.bf_len-1; ++ins, ++i)
+ printf("%u %u %u %u,", ins->code, ins->jt, ins->jf, ins->k);
+
+ printf("%u %u %u %u\n", ins->code, ins->jt, ins->jf, ins->k);
+
+ pcap_freecode(&program);
+ return 0;
+}
+