From d7d418b995a098cce6e50bb1613550ab0c4b8451 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 16 Aug 2013 07:27:01 -0400 Subject: [PATCH] Imported Upstream version 1.4.19.1 --- .gitignore | 2 +- Makefile.am | 8 +- Makefile.in | 77 ++-- aclocal.m4 | 67 ++- build-aux/ar-lib | 270 +++++++++++++ build-aux/compile | 91 +++-- build-aux/config.sub | 11 +- build-aux/depcomp | 124 +++--- build-aux/ltmain.sh | 4 +- configure | 246 +++++++++-- configure.ac | 11 +- etc/xtables/connlabel.conf | 8 + extensions/.gitignore | 4 +- extensions/GNUmakefile.in | 46 +-- extensions/libip6t_DNAT.c | 252 ++++++++++++ extensions/libip6t_DNPT.c | 90 +++++ extensions/libip6t_DNPT.man | 30 ++ extensions/libip6t_LOG.man | 5 +- extensions/libip6t_MASQUERADE.c | 150 +++++++ extensions/libip6t_MASQUERADE.man | 30 ++ extensions/libip6t_NETMAP.c | 93 +++++ extensions/libip6t_REDIRECT.c | 151 +++++++ extensions/libip6t_SNAT.c | 252 ++++++++++++ extensions/libip6t_SNPT.c | 90 +++++ extensions/libip6t_SNPT.man | 30 ++ extensions/libip6t_frag.c | 8 + extensions/libipt_DNAT.c | 36 +- extensions/libipt_LOG.man | 5 +- extensions/libipt_MASQUERADE.c | 32 +- extensions/libipt_NETMAP.c | 18 +- extensions/libipt_REDIRECT.c | 34 +- extensions/libipt_SAME.c | 21 +- extensions/libipt_SNAT.c | 36 +- extensions/libipt_SNAT.man | 11 +- extensions/libxt_CT.c | 40 ++ extensions/libxt_HMARK.c | 450 +++++++++++++++++++++ extensions/libxt_HMARK.man | 60 +++ extensions/libxt_LED.c | 7 +- extensions/libxt_NFQUEUE.man | 4 +- extensions/libxt_NOTRACK.c | 15 - extensions/libxt_NOTRACK.man | 6 +- extensions/libxt_SET.man | 12 +- extensions/libxt_addrtype.c | 2 +- extensions/libxt_bpf.c | 152 +++++++ extensions/libxt_bpf.man | 34 ++ extensions/libxt_connlabel.c | 210 ++++++++++ extensions/libxt_connlabel.man | 32 ++ extensions/libxt_conntrack.c | 214 +++++++++- extensions/libxt_conntrack.man | 18 +- extensions/libxt_devgroup.c | 72 ++-- extensions/libxt_devgroup.man | 7 + extensions/libxt_hashlimit.c | 190 ++++++++- extensions/libxt_hashlimit.man | 19 +- extensions/libxt_limit.c | 19 +- extensions/libxt_multiport.man | 7 +- extensions/libxt_osf.c | 9 +- extensions/libxt_recent.c | 181 +++++++-- extensions/libxt_recent.man | 3 + extensions/libxt_rpfilter.man | 1 + extensions/libxt_set.c | 98 +++++ extensions/libxt_set.man | 6 + extensions/libxt_state.c | 137 ------- extensions/libxt_state.man | 28 +- extensions/libxt_statistic.c | 2 +- extensions/libxt_tcp.c | 5 +- extensions/libxt_time.c | 20 + extensions/libxt_time.man | 12 + extensions/libxt_u32.c | 12 +- include/Makefile.am | 2 +- include/Makefile.in | 48 ++- include/libiptc/libip6tc.h | 3 - include/linux/netfilter/ipset/ip_set.h | 2 + .../linux/netfilter/nf_conntrack_tuple_common.h | 27 ++ include/linux/netfilter/nf_nat.h | 33 ++ include/linux/netfilter/xt_HMARK.h | 50 +++ include/linux/netfilter/xt_bpf.h | 17 + include/linux/netfilter/xt_connlabel.h | 12 + include/linux/netfilter/xt_conntrack.h | 1 + include/linux/netfilter/xt_hashlimit.h | 6 +- include/linux/netfilter/xt_recent.h | 10 + include/linux/netfilter/xt_time.h | 1 + include/linux/netfilter_ipv4/ip_queue.h | 72 ++++ include/linux/netfilter_ipv4/ipt_SAME.h | 2 +- include/linux/netfilter_ipv6/ip6t_NPT.h | 16 + include/net/netfilter/nf_conntrack_tuple.h | 114 ------ include/net/netfilter/nf_nat.h | 55 --- include/xtables-version.h.in | 2 + include/{xtables.h.in => xtables.h} | 43 +- iptables/.gitignore | 1 + iptables/Makefile.am | 16 +- iptables/Makefile.in | 84 +++- iptables/ip6tables-restore.8 | 20 +- iptables/ip6tables-restore.c | 133 +++--- iptables/ip6tables.8.in | 46 ++- iptables/ip6tables.c | 120 ++---- iptables/iptables-apply.8 | 2 +- iptables/iptables-extensions.8.in | 28 ++ iptables/iptables-restore.8 | 18 +- iptables/iptables-restore.c | 133 +++--- iptables/iptables.8.in | 41 +- iptables/iptables.c | 136 ++----- libipq/Makefile.in | 49 ++- libiptc/Makefile.in | 32 +- libiptc/libip6tc.c | 2 +- libxtables/Makefile.in | 27 +- libxtables/xtables.c | 181 +++++++-- libxtables/xtoptions.c | 38 +- m4/libtool.m4 | 40 +- tests/options-most.rules | 3 + utils/.gitignore | 1 + utils/Makefile.am | 16 +- utils/Makefile.in | 60 ++- utils/nfbpf_compile.c | 55 +++ 113 files changed, 5002 insertions(+), 1223 deletions(-) create mode 100755 build-aux/ar-lib create mode 100644 etc/xtables/connlabel.conf create mode 100644 extensions/libip6t_DNAT.c create mode 100644 extensions/libip6t_DNPT.c create mode 100644 extensions/libip6t_DNPT.man create mode 100644 extensions/libip6t_MASQUERADE.c create mode 100644 extensions/libip6t_MASQUERADE.man create mode 100644 extensions/libip6t_NETMAP.c create mode 100644 extensions/libip6t_REDIRECT.c create mode 100644 extensions/libip6t_SNAT.c create mode 100644 extensions/libip6t_SNPT.c create mode 100644 extensions/libip6t_SNPT.man create mode 100644 extensions/libxt_HMARK.c create mode 100644 extensions/libxt_HMARK.man delete mode 100644 extensions/libxt_NOTRACK.c create mode 100644 extensions/libxt_bpf.c create mode 100644 extensions/libxt_bpf.man create mode 100644 extensions/libxt_connlabel.c create mode 100644 extensions/libxt_connlabel.man create mode 100644 extensions/libxt_devgroup.man delete mode 100644 extensions/libxt_state.c create mode 100644 include/linux/netfilter/nf_nat.h create mode 100644 include/linux/netfilter/xt_HMARK.h create mode 100644 include/linux/netfilter/xt_bpf.h create mode 100644 include/linux/netfilter/xt_connlabel.h create mode 100644 include/linux/netfilter_ipv4/ip_queue.h create mode 100644 include/linux/netfilter_ipv6/ip6t_NPT.h delete mode 100644 include/net/netfilter/nf_conntrack_tuple.h delete mode 100644 include/net/netfilter/nf_nat.h create mode 100644 include/xtables-version.h.in rename include/{xtables.h.in => xtables.h} (92%) create mode 100644 iptables/iptables-extensions.8.in create mode 100644 utils/nfbpf_compile.c diff --git a/.gitignore b/.gitignore index b7c3dfb..fa86c48 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ Makefile Makefile.in -/include/xtables.h +/include/xtables-version.h /include/iptables/internal.h /aclocal.m4 diff --git a/Makefile.am b/Makefile.am index 4eb63eb..cd008a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,9 +10,7 @@ endif if ENABLE_LIBIPQ SUBDIRS += libipq endif -if HAVE_LIBNFNETLINK SUBDIRS += utils -endif # Depends on libxtables: SUBDIRS += extensions # Depends on extensions/libext.a: @@ -26,5 +24,9 @@ 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 diff --git a/Makefile.in b/Makefile.in index 43f338a..1f5b0d6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -17,6 +17,23 @@ # -*- 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@ @@ -36,16 +53,15 @@ build_triplet = @build@ 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 \ @@ -69,6 +85,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ 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=) \ @@ -254,8 +275,8 @@ ACLOCAL_AMFLAGS = -I m4 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 @@ -492,13 +513,10 @@ distdir: $(DISTFILES) 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; \ @@ -584,7 +602,7 @@ distcheck: dist *.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) @@ -706,7 +724,8 @@ info: info-recursive info-am: install-data-am: - + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-recursive install-dvi-am: @@ -754,7 +773,8 @@ ps-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 \ @@ -763,14 +783,15 @@ uninstall-am: 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 @@ -781,8 +802,12 @@ 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. diff --git a/aclocal.m4 b/aclocal.m4 index 282ff63..dbde882 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# 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, @@ -198,7 +198,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.3], [], +m4_if([$1], [1.11.6], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -214,11 +214,72 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.3])dnl +[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. diff --git a/build-aux/ar-lib b/build-aux/ar-lib new file mode 100755 index 0000000..0f62c6f --- /dev/null +++ b/build-aux/ar-lib @@ -0,0 +1,270 @@ +#! /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 . +# +# 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 . + +# 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 or send patches to +# . + + +# 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 <&2 + echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) @@ -40,8 +40,8 @@ as side-effects. 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. @@ -57,6 +57,12 @@ EOF ;; 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 @@ -102,6 +108,12 @@ if test "$depmode" = msvc7msys; then 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 @@ -156,15 +168,14 @@ gcc) ## 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. @@ -203,18 +214,15 @@ sgi) # 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 @@ -226,10 +234,17 @@ sgi) 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|/[^/]*$|/|'` @@ -259,12 +274,11 @@ aix) 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 @@ -275,23 +289,26 @@ aix) ;; 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 : @@ -300,15 +317,21 @@ icc) 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" ;; @@ -344,7 +367,7 @@ hp2) 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/ \\*$// @@ -359,9 +382,9 @@ hp2) 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= @@ -407,8 +430,7 @@ tru64) 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 @@ -443,11 +465,11 @@ msvc7) 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" @@ -478,7 +500,7 @@ dashmstdout) shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -498,15 +520,14 @@ dashmstdout) 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" @@ -562,8 +583,7 @@ makedepend) # 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" @@ -583,7 +603,7 @@ cpp) shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -652,8 +672,8 @@ msvisualcpp) 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" ;; diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh index c7d06c3..499e473 100644 --- a/build-aux/ltmain.sh +++ b/build-aux/ltmain.sh @@ -70,7 +70,7 @@ # 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 # @@ -80,7 +80,7 @@ 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 diff --git a/configure b/configure index dd37099..6562649 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /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. @@ -587,8 +587,8 @@ MAKEFLAGS= # 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='' @@ -651,6 +651,8 @@ libnfnetlink_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG +ENABLE_BPFC_FALSE +ENABLE_BPFC_TRUE ENABLE_LIBIPQ_FALSE ENABLE_LIBIPQ_TRUE ENABLE_DEVEL_FALSE @@ -675,8 +677,6 @@ NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB -ac_ct_AR -AR DLLTOOL OBJDUMP LN_S @@ -697,6 +697,8 @@ build_vendor build_cpu build LIBTOOL +ac_ct_AR +AR am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE @@ -795,6 +797,7 @@ enable_ipv6 enable_largefile enable_devel enable_libipq +enable_bpf_compiler with_pkgconfigdir ' ac_precious_vars='build_alias @@ -1351,7 +1354,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures 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]... @@ -1421,7 +1424,7 @@ fi 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 @@ -1441,6 +1444,7 @@ Optional Features: --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] @@ -1545,7 +1549,7 @@ fi 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. @@ -2093,7 +2097,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by 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 $@ @@ -2443,7 +2447,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=7 +libxtables_vcurrent=10 libxtables_vage=0 ac_aux_dir= @@ -2916,7 +2920,7 @@ fi # Define the identity of the package. PACKAGE='iptables' - VERSION='1.4.14' + VERSION='1.4.19.1' cat >>confdefs.h <<_ACEOF @@ -4093,6 +4097,167 @@ fi + +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 @@ -4978,7 +5143,8 @@ else ;; *) 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 @@ -5379,10 +5545,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -5421,7 +5583,7 @@ irix5* | irix6* | nonstopux*) ;; # 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 ;; @@ -5683,7 +5845,6 @@ test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - if test -n "$ac_tool_prefix"; then for ac_prog in ar do @@ -6519,7 +6680,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) 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" @@ -8318,7 +8486,7 @@ lt_prog_compiler_static= 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*) @@ -10488,17 +10656,6 @@ freebsd* | dragonfly*) 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 @@ -10615,7 +10772,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # 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 @@ -11722,6 +11879,11 @@ if test "${enable_libipq+set}" = set; then : 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 : @@ -11906,6 +12068,14 @@ else ENABLE_LIBIPQ_FALSE= fi + if test "$enable_bpfc" = "yes"; then + ENABLE_BPFC_TRUE= + ENABLE_BPFC_FALSE='#' +else + ENABLE_BPFC_TRUE='#' + ENABLE_BPFC_FALSE= +fi + @@ -12135,7 +12305,7 @@ pkgdatadir='${datadir}/xtables'; 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 @@ -12290,6 +12460,10 @@ if test -z "${ENABLE_LIBIPQ_TRUE}" && test -z "${ENABLE_LIBIPQ_FALSE}"; then 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 @@ -12691,7 +12865,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # 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 @@ -12757,7 +12931,7 @@ _ACEOF 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\\" @@ -13179,7 +13353,7 @@ do "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;; diff --git a/configure.ac b/configure.ac index 2909a98..d165d52 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ -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]) @@ -13,6 +13,7 @@ AM_INIT_AUTOMAKE([-Wall]) 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], @@ -49,6 +50,9 @@ AC_ARG_ENABLE([devel], [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']) @@ -87,6 +91,7 @@ AM_CONDITIONAL([ENABLE_IPV6], [test "$enable_ipv6" = "yes"]) 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]) @@ -126,5 +131,5 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile 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 diff --git a/etc/xtables/connlabel.conf b/etc/xtables/connlabel.conf new file mode 100644 index 0000000..9167029 --- /dev/null +++ b/etc/xtables/connlabel.conf @@ -0,0 +1,8 @@ +# 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 diff --git a/extensions/.gitignore b/extensions/.gitignore index 2e74faf..b1260f0 100644 --- a/extensions/.gitignore +++ b/extensions/.gitignore @@ -5,5 +5,5 @@ /GNUmakefile /initext.c /initext?.c -/matches?.man -/targets?.man +/matches.man +/targets.man diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 218dc3a..1ae7f74 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,6 +39,7 @@ endif # 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}) @@ -47,7 +48,7 @@ pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_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}) @@ -55,9 +56,7 @@ 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} @@ -76,10 +75,10 @@ install: ${targets_install} 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 $<; @@ -96,11 +95,15 @@ lib%.so: lib%.oo 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 # @@ -196,30 +199,27 @@ man_run = \ ${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})) diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c new file mode 100644 index 0000000..eaa6bf1 --- /dev/null +++ b/extensions/libip6t_DNAT.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +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 [[-]][: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); +} diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c new file mode 100644 index 0000000..703adf6 --- /dev/null +++ b/extensions/libip6t_DNPT.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +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); +} diff --git a/extensions/libip6t_DNPT.man b/extensions/libip6t_DNPT.man new file mode 100644 index 0000000..61beeee --- /dev/null +++ b/extensions/libip6t_DNPT.man @@ -0,0 +1,30 @@ +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. diff --git a/extensions/libip6t_LOG.man b/extensions/libip6t_LOG.man index b7803fe..0a48640 100644 --- a/extensions/libip6t_LOG.man +++ b/extensions/libip6t_LOG.man @@ -11,7 +11,10 @@ separate rules with the same matching criteria, first using target LOG 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, diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c new file mode 100644 index 0000000..eb9213e --- /dev/null +++ b/extensions/libip6t_MASQUERADE.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_PORTS = 0, + O_RANDOM, +}; + +static void MASQUERADE_help(void) +{ + printf( +"MASQUERADE target options:\n" +" --to-ports [-]\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); +} diff --git a/extensions/libip6t_MASQUERADE.man b/extensions/libip6t_MASQUERADE.man new file mode 100644 index 0000000..c63d826 --- /dev/null +++ b/extensions/libip6t_MASQUERADE.man @@ -0,0 +1,30 @@ +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 diff --git a/extensions/libip6t_NETMAP.c b/extensions/libip6t_NETMAP.c new file mode 100644 index 0000000..a4df70e --- /dev/null +++ b/extensions/libip6t_NETMAP.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/extensions/libip6t_REDIRECT.c b/extensions/libip6t_REDIRECT.c new file mode 100644 index 0000000..1724aa6 --- /dev/null +++ b/extensions/libip6t_REDIRECT.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +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 [-]\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); +} diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c new file mode 100644 index 0000000..7382ad0 --- /dev/null +++ b/extensions/libip6t_SNAT.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +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 [[-]][: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); +} diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c new file mode 100644 index 0000000..7ed80b2 --- /dev/null +++ b/extensions/libip6t_SNPT.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +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); +} diff --git a/extensions/libip6t_SNPT.man b/extensions/libip6t_SNPT.man new file mode 100644 index 0000000..78d644a --- /dev/null +++ b/extensions/libip6t_SNPT.man @@ -0,0 +1,30 @@ +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. diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c index d8bcaee..023df62 100644 --- a/extensions/libip6t_frag.c +++ b/extensions/libip6t_frag.c @@ -41,6 +41,13 @@ static const struct xt_option_entry frag_opts[] = { }; #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; @@ -173,6 +180,7 @@ static struct xtables_match frag_mt6_reg = { .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, diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c index 466c9de..ff18799 100644 --- a/extensions/libipt_DNAT.c +++ b/extensions/libipt_DNAT.c @@ -6,7 +6,7 @@ #include /* get_kernel_version */ #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_DEST = 0, @@ -23,7 +23,7 @@ enum { 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) @@ -44,7 +44,7 @@ static const struct xt_option_entry DNAT_opts[] = { }; 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; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) 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; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) 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) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *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; @@ -177,7 +177,7 @@ static void DNAT_parse(struct xt_option_call *cb) 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; } } @@ -185,15 +185,15 @@ static void DNAT_parse(struct xt_option_call *cb) 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; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) 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) @@ -220,9 +220,9 @@ static void DNAT_print(const void *ip, const struct xt_entry_target *target, 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"); } } @@ -235,9 +235,9 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target) 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"); } } @@ -246,8 +246,8 @@ static struct xtables_target dnat_tg_reg = { .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, diff --git a/extensions/libipt_LOG.man b/extensions/libipt_LOG.man index 47c35e0..f2574f8 100644 --- a/extensions/libipt_LOG.man +++ b/extensions/libipt_LOG.man @@ -11,7 +11,10 @@ separate rules with the same matching criteria, first using target LOG 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, diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c index 7ba42df..ea07445 100644 --- a/extensions/libipt_MASQUERADE.c +++ b/extensions/libipt_MASQUERADE.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -31,7 +31,7 @@ static const struct xt_option_entry MASQUERADE_opts[] = { 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; @@ -39,12 +39,12 @@ static void MASQUERADE_init(struct xt_entry_target *t) /* 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); @@ -75,7 +75,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) { 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 @@ -95,7 +95,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) 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; } } @@ -104,33 +104,33 @@ static void 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"); } @@ -138,8 +138,8 @@ static struct xtables_target masquerade_tg_reg = { .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, diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c index 5c4471a..dee7b01 100644 --- a/extensions/libipt_NETMAP.c +++ b/extensions/libipt_NETMAP.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define MODULENAME "NETMAP" @@ -45,7 +45,7 @@ netmask2bits(uint32_t netmask) 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; @@ -53,11 +53,11 @@ static void NETMAP_init(struct xt_entry_target *t) 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; } @@ -65,8 +65,8 @@ static void NETMAP_parse(struct xt_option_call *cb) 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; @@ -90,8 +90,8 @@ static struct xtables_target netmap_tg_reg = { .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, diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c index e67360a..610a949 100644 --- a/extensions/libipt_REDIRECT.c +++ b/extensions/libipt_REDIRECT.c @@ -4,7 +4,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -30,7 +30,7 @@ static const struct xt_option_entry REDIRECT_opts[] = { 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; @@ -38,12 +38,12 @@ static void REDIRECT_init(struct xt_entry_target *t) /* 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) @@ -75,7 +75,7 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr) 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 @@ -95,11 +95,11 @@ static void REDIRECT_parse(struct xt_option_call *cb) "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; } } @@ -107,30 +107,30 @@ static void REDIRECT_parse(struct xt_option_call *cb) 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"); } } @@ -139,8 +139,8 @@ static struct xtables_target redirect_tg_reg = { .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, diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c index e603ef6..5d5bf63 100644 --- a/extensions/libipt_SAME.c +++ b/extensions/libipt_SAME.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include enum { @@ -37,7 +37,7 @@ static const struct xt_option_entry SAME_opts[] = { }; /* 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; @@ -45,7 +45,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) 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) @@ -74,6 +74,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) 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) { @@ -89,6 +90,10 @@ static void SAME_parse(struct xt_option_call *cb) 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; } } @@ -100,7 +105,7 @@ static void SAME_fcheck(struct xt_fcheck_call *cb) 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, @@ -113,7 +118,7 @@ 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; @@ -123,7 +128,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target, 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; } @@ -141,7 +146,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) 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; @@ -150,7 +155,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) 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; } diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index c8cb26d..1a24f3d 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_SRC = 0, @@ -23,7 +23,7 @@ enum { 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) @@ -44,7 +44,7 @@ static const struct xt_option_entry SNAT_opts[] = { }; 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; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) 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; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) 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) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *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; @@ -177,7 +177,7 @@ static void SNAT_parse(struct xt_option_call *cb) 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; } } @@ -185,15 +185,15 @@ static void SNAT_parse(struct xt_option_call *cb) 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; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) 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) @@ -220,9 +220,9 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, 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"); } } @@ -235,9 +235,9 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) 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"); } } @@ -246,8 +246,8 @@ static struct xtables_target snat_tg_reg = { .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, diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man index 626b592..093b09c 100644 --- a/extensions/libipt_SNAT.man +++ b/extensions/libipt_SNAT.man @@ -2,7 +2,10 @@ This target is only valid in the .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: @@ -35,3 +38,9 @@ is used then port mapping will be randomized (kernel >= 2.6.21). 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. diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 27a20e2..a576a95 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -248,6 +248,20 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target) 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, @@ -274,6 +288,32 @@ static struct xtables_target ct_target_reg[] = { .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) diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c new file mode 100644 index 0000000..94aebe9 --- /dev/null +++ b/extensions/libxt_HMARK.c @@ -0,0 +1,450 @@ +/* + * (C) 2012 by Hans Schillstrom + * (C) 2012 by Pablo Neira Ayuso + * + * 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 . + */ + +#include +#include +#include + +#include "xtables.h" +#include + +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)); +} diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man new file mode 100644 index 0000000..e7b5426 --- /dev/null +++ b/extensions/libxt_HMARK.man @@ -0,0 +1,60 @@ +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 diff --git a/extensions/libxt_LED.c b/extensions/libxt_LED.c index 9d68fa2..e6cf849 100644 --- a/extensions/libxt_LED.c +++ b/extensions/libxt_LED.c @@ -49,6 +49,7 @@ static void LED_help(void) 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) { @@ -59,8 +60,10 @@ static void LED_parse(struct xt_option_call *cb) 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; diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man index 910e386..f11e0c8 100644 --- a/extensions/libxt_NFQUEUE.man +++ b/extensions/libxt_NFQUEUE.man @@ -21,5 +21,5 @@ Packets belonging to the same connection are put into the same nfqueue. .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. diff --git a/extensions/libxt_NOTRACK.c b/extensions/libxt_NOTRACK.c deleted file mode 100644 index ca58700..0000000 --- a/extensions/libxt_NOTRACK.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Shared library add-on to iptables to add NOTRACK target support. */ -#include - -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); -} diff --git a/extensions/libxt_NOTRACK.man b/extensions/libxt_NOTRACK.man index c2cdf5a..633b965 100644 --- a/extensions/libxt_NOTRACK.man +++ b/extensions/libxt_NOTRACK.man @@ -1,5 +1,3 @@ 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. diff --git a/extensions/libxt_SET.man b/extensions/libxt_SET.man index 63eb383..c35ba93 100644 --- a/extensions/libxt_SET.man +++ b/extensions/libxt_SET.man @@ -1,24 +1,24 @@ -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 diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c index 59072b3..e8a8545 100644 --- a/extensions/libxt_addrtype.c +++ b/extensions/libxt_addrtype.c @@ -60,7 +60,7 @@ static void addrtype_help_v1(void) " [!] --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(); diff --git a/extensions/libxt_bpf.c b/extensions/libxt_bpf.c new file mode 100644 index 0000000..dca97d7 --- /dev/null +++ b/extensions/libxt_bpf.c @@ -0,0 +1,152 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BCODE_FILE_MAX_LEN_B 1024 + +enum { + O_BCODE_STDIN = 0, +}; + +static void bpf_help(void) +{ + printf( +"bpf match options:\n" +"--bytecode : a bpf program as generated by\n" +" `nfbpf_compiler RAW `\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); +} diff --git a/extensions/libxt_bpf.man b/extensions/libxt_bpf.man new file mode 100644 index 0000000..5b1d042 --- /dev/null +++ b/extensions/libxt_bpf.man @@ -0,0 +1,34 @@ +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. diff --git a/extensions/libxt_connlabel.c b/extensions/libxt_connlabel.c new file mode 100644 index 0000000..ae52901 --- /dev/null +++ b/extensions/libxt_connlabel.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/extensions/libxt_connlabel.man b/extensions/libxt_connlabel.man new file mode 100644 index 0000000..9fd2043 --- /dev/null +++ b/extensions/libxt_connlabel.man @@ -0,0 +1,32 @@ +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 diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index fff69f8..9f7b5db 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -13,7 +13,11 @@ #include #include #include +#include #include +#ifndef XT_STATE_UNTRACKED +#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) +#endif struct ip_conntrack_old_tuple { struct { @@ -797,7 +801,9 @@ conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix, 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); } @@ -898,6 +904,15 @@ conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix, } } +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) { @@ -1003,6 +1018,144 @@ conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match) 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, @@ -1016,6 +1169,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack_print, .save = conntrack_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack_mt_opts_v0, }, { @@ -1030,6 +1184,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt4_print, .save = conntrack1_mt4_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1044,6 +1199,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt6_print, .save = conntrack1_mt6_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1058,6 +1214,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt_print, .save = conntrack2_mt_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1072,6 +1229,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt6_print, .save = conntrack2_mt6_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1086,6 +1244,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt_print, .save = conntrack3_mt_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack3_mt_opts, }, { @@ -1100,8 +1259,61 @@ static struct xtables_match conntrack_mt_reg[] = { .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) diff --git a/extensions/libxt_conntrack.man b/extensions/libxt_conntrack.man index c397f74..15fd1dd 100644 --- a/extensions/libxt_conntrack.man +++ b/extensions/libxt_conntrack.man @@ -42,23 +42,23 @@ specified at all, matches packets in both directions. 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 @@ -74,7 +74,7 @@ Statuses for \fB\-\-ctstatus\fP: 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. diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c index 4487c83..4a69c82 100644 --- a/extensions/libxt_devgroup.c +++ b/extensions/libxt_devgroup.c @@ -42,58 +42,50 @@ static void devgroup_init(struct xt_entry_match *match) 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; diff --git a/extensions/libxt_devgroup.man b/extensions/libxt_devgroup.man new file mode 100644 index 0000000..4a66c9f --- /dev/null +++ b/extensions/libxt_devgroup.man @@ -0,0 +1,7 @@ +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 diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index da34cb2..c5b8d77 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -10,6 +10,9 @@ * * Error corections by nmalykh@bilim.com (22.01.2005) */ +#define _BSD_SOURCE 1 +#define _ISOC99_SOURCE 1 +#include #include #include #include @@ -20,6 +23,10 @@ #include #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 @@ -59,6 +66,7 @@ enum { 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, @@ -90,7 +98,7 @@ static const struct xt_option_entry hashlimit_opts[] = { {.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, @@ -122,9 +130,7 @@ static const struct xt_option_entry hashlimit_mt_opts[] = { .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)}, @@ -144,6 +150,82 @@ static const struct xt_option_entry hashlimit_mt_opts[] = { }; #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) { @@ -171,12 +253,13 @@ 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; } @@ -265,17 +348,24 @@ static void hashlimit_mt_parse(struct xt_option_call *cb) 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; @@ -315,6 +405,24 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb) "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 @@ -330,6 +438,11 @@ static uint32_t print_rate(uint32_t period) { 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) @@ -340,6 +453,41 @@ static uint32_t print_rate(uint32_t 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; @@ -398,8 +546,13 @@ hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) 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); @@ -449,7 +602,7 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match) fputs(" --hashlimit-mode", stdout); print_mode(r->cfg.mode, ','); - + printf(" --hashlimit-name %s", r->name); if (r->cfg.size) @@ -471,8 +624,13 @@ hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) 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)) { diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man index f90577e..17cb2b0 100644 --- a/extensions/libxt_hashlimit.man +++ b/extensions/libxt_hashlimit.man @@ -2,14 +2,15 @@ \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. @@ -17,7 +18,9 @@ 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 @@ -63,3 +66,11 @@ matching on subnet "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 diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c index b15b02f..f75ef2f 100644 --- a/extensions/libxt_limit.c +++ b/extensions/libxt_limit.c @@ -3,6 +3,9 @@ * Jérôme de Vivie * Hervé Eychenne */ +#define _BSD_SOURCE 1 +#define _ISOC99_SOURCE 1 +#include #include #include #include @@ -64,12 +67,13 @@ int parse_rate(const char *rate, uint32_t *val) 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; } @@ -118,6 +122,11 @@ static void print_rate(uint32_t period) { 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) diff --git a/extensions/libxt_multiport.man b/extensions/libxt_multiport.man index caf5c56..7eb083e 100644 --- a/extensions/libxt_multiport.man +++ b/extensions/libxt_multiport.man @@ -1,9 +1,8 @@ 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 diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c index 88274a0..52dba47 100644 --- a/extensions/libxt_osf.c +++ b/extensions/libxt_osf.c @@ -92,7 +92,14 @@ static void osf_save(const void *ip, const struct xt_entry_match *match) { 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 = { diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index c7dce4e..f4ebe6a 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -16,6 +16,7 @@ enum { O_NAME, O_RSOURCE, O_RDEST, + O_MASK, F_SET = 1 << O_SET, F_RCHECK = 1 << O_RCHECK, F_UPDATE = 1 << O_UPDATE, @@ -25,7 +26,7 @@ enum { }; #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, @@ -50,6 +51,32 @@ static const struct xt_option_entry recent_opts[] = { }; #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( @@ -74,18 +101,28 @@ static void recent_help(void) " --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 . 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) @@ -131,8 +168,6 @@ 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' " @@ -140,9 +175,9 @@ static void recent_check(struct xt_fcheck_call *cb) } 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(" !"); @@ -167,11 +202,23 @@ static void recent_print(const void *ip, const struct xt_entry_match *match, 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(" !"); @@ -191,28 +238,116 @@ static void recent_save(const void *ip, const struct xt_entry_match *match) 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)); } diff --git a/extensions/libxt_recent.man b/extensions/libxt_recent.man index 8043df4..d9bd5d2 100644 --- a/extensions/libxt_recent.man +++ b/extensions/libxt_recent.man @@ -24,6 +24,9 @@ is the default. \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 diff --git a/extensions/libxt_rpfilter.man b/extensions/libxt_rpfilter.man index aeb4a9d..f7f56d2 100644 --- a/extensions/libxt_rpfilter.man +++ b/extensions/libxt_rpfilter.man @@ -17,6 +17,7 @@ Also use the packets' nfmark value when performing the reverse path route lookup \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. diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index 77e3f07..e011156 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -205,6 +205,90 @@ set_save_v1(const void *ip, const struct xt_entry_match *match) 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 [, */ + 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", @@ -234,6 +318,20 @@ static struct xtables_match set_mt_reg[] = { .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) diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man index 1ad9085..ac60f14 100644 --- a/extensions/libxt_set.man +++ b/extensions/libxt_set.man @@ -14,6 +14,12 @@ address and destination port pair can be found in the specified set. If 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. diff --git a/extensions/libxt_state.c b/extensions/libxt_state.c deleted file mode 100644 index eff444c..0000000 --- a/extensions/libxt_state.c +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include -#include -#include -#include - -#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); -} diff --git a/extensions/libxt_state.man b/extensions/libxt_state.man index 37d095b..ec096ca 100644 --- a/extensions/libxt_state.man +++ b/extensions/libxt_state.man @@ -1,24 +1,8 @@ -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. diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c index 12a83dd..c23805f 100644 --- a/extensions/libxt_statistic.c +++ b/extensions/libxt_statistic.c @@ -107,7 +107,7 @@ static void print_match(const struct xt_statistic_info *info, char *prefix) (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; } diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c index e849fa2..bbdec45 100644 --- a/extensions/libxt_tcp.c +++ b/extensions/libxt_tcp.c @@ -278,11 +278,10 @@ static void 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); diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c index 44c05b8..9c5bda8 100644 --- a/extensions/libxt_time.c +++ b/extensions/libxt_time.c @@ -22,6 +22,7 @@ enum { O_DATE_STOP, O_TIME_START, O_TIME_STOP, + O_TIME_CONTIGUOUS, O_MONTHDAYS, O_WEEKDAYS, O_LOCAL_TZ, @@ -30,6 +31,7 @@ enum { 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[] = { @@ -41,6 +43,7 @@ static const struct xt_option_entry time_opts[] = { {.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, @@ -273,6 +276,9 @@ static void time_parse(struct xt_option_call *cb) 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 " @@ -403,6 +409,8 @@ static void time_print(const void *ip, const struct xt_entry_match *match, } 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) @@ -429,6 +437,17 @@ 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 = { @@ -442,6 +461,7 @@ static struct xtables_match time_match = { .print = time_print, .save = time_save, .x6_parse = time_parse, + .x6_fcheck = time_check, .x6_options = time_opts, }; diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man index 1d677b9..4c0cae0 100644 --- a/extensions/libxt_time.man +++ b/extensions/libxt_time.man @@ -30,6 +30,10 @@ Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP, 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. @@ -84,3 +88,11 @@ The fourth Friday in the month: (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. diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c index 6d024fb..2a7f5d8 100644 --- a/extensions/libxt_u32.c +++ b/extensions/libxt_u32.c @@ -88,17 +88,13 @@ static void u32_dump(const struct xt_u32 *data) /* 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; } diff --git a/include/Makefile.am b/include/Makefile.am index 6f7da59..e695120 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- include_HEADERS = -nobase_include_HEADERS = xtables.h +nobase_include_HEADERS = xtables.h xtables-version.h if ENABLE_LIBIPQ include_HEADERS += libipq/libipq.h diff --git a/include/Makefile.in b/include/Makefile.in index a90850c..5f39d74 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -18,6 +18,23 @@ # -*- 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@ @@ -39,7 +56,7 @@ host_triplet = @host@ 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 \ @@ -49,10 +66,15 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(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 \ @@ -219,9 +241,9 @@ top_builddir = @top_builddir@ 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: @@ -255,7 +277,7 @@ $(top_srcdir)/configure: $(am__configure_deps) $(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: @@ -265,8 +287,11 @@ clean-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"; \ @@ -283,15 +308,18 @@ uninstall-includeHEADERS: 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 $$?; }; \ diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index c656bc4..9aed80a 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -154,9 +154,6 @@ int ip6tc_get_raw_socket(void); /* 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; diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 79cb077..fff191d 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -186,6 +186,7 @@ enum ip_set_dim { * If changed, new revision of iptables match/target is required. */ IPSET_DIM_MAX = 6, + IPSET_BIT_RETURN_NOMATCH = 7, }; /* Option flags for kernel operations */ @@ -194,6 +195,7 @@ enum ip_set_kopt { 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), }; diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h index 2ea22b0..2f6bbc5 100644 --- a/include/linux/netfilter/nf_conntrack_tuple_common.h +++ b/include/linux/netfilter/nf_conntrack_tuple_common.h @@ -7,6 +7,33 @@ enum ip_conntrack_dir { 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 */ diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h new file mode 100644 index 0000000..bf0cc37 --- /dev/null +++ b/include/linux/netfilter/nf_nat.h @@ -0,0 +1,33 @@ +#ifndef _NETFILTER_NF_NAT_H +#define _NETFILTER_NF_NAT_H + +#include +#include + +#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 */ diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h new file mode 100644 index 0000000..826fc58 --- /dev/null +++ b/include/linux/netfilter/xt_HMARK.h @@ -0,0 +1,50 @@ +#ifndef XT_HMARK_H_ +#define XT_HMARK_H_ + +#include + +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_ */ diff --git a/include/linux/netfilter/xt_bpf.h b/include/linux/netfilter/xt_bpf.h new file mode 100644 index 0000000..5dda450 --- /dev/null +++ b/include/linux/netfilter/xt_bpf.h @@ -0,0 +1,17 @@ +#ifndef _XT_BPF_H +#define _XT_BPF_H + +#include +#include + +#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 */ diff --git a/include/linux/netfilter/xt_connlabel.h b/include/linux/netfilter/xt_connlabel.h new file mode 100644 index 0000000..c4bc9ee --- /dev/null +++ b/include/linux/netfilter/xt_connlabel.h @@ -0,0 +1,12 @@ +#include + +#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; +}; diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 74b904d..e971501 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -30,6 +30,7 @@ enum { 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 { diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index b1925b5..141efbd 100644 --- a/include/linux/netfilter/xt_hashlimit.h +++ b/include/linux/netfilter/xt_hashlimit.h @@ -6,7 +6,10 @@ /* 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; @@ -17,6 +20,7 @@ enum { 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 { diff --git a/include/linux/netfilter/xt_recent.h b/include/linux/netfilter/xt_recent.h index 83318e0..6ef36c1 100644 --- a/include/linux/netfilter/xt_recent.h +++ b/include/linux/netfilter/xt_recent.h @@ -32,4 +32,14 @@ struct xt_recent_mtinfo { __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 */ diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h index 7c37fac..a21d5bf 100644 --- a/include/linux/netfilter/xt_time.h +++ b/include/linux/netfilter/xt_time.h @@ -16,6 +16,7 @@ struct xt_time_info { 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, diff --git a/include/linux/netfilter_ipv4/ip_queue.h b/include/linux/netfilter_ipv4/ip_queue.h new file mode 100644 index 0000000..a03507f --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_queue.h @@ -0,0 +1,72 @@ +/* + * 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 +#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*/ diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h index 5bca782..a855167 100644 --- a/include/linux/netfilter_ipv4/ipt_SAME.h +++ b/include/linux/netfilter_ipv4/ipt_SAME.h @@ -14,7 +14,7 @@ struct ipt_same_info { __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*/ diff --git a/include/linux/netfilter_ipv6/ip6t_NPT.h b/include/linux/netfilter_ipv6/ip6t_NPT.h new file mode 100644 index 0000000..f763355 --- /dev/null +++ b/include/linux/netfilter_ipv6/ip6t_NPT.h @@ -0,0 +1,16 @@ +#ifndef __NETFILTER_IP6T_NPT +#define __NETFILTER_IP6T_NPT + +#include +#include + +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 */ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h deleted file mode 100644 index c40e0b4..0000000 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ /dev/null @@ -1,114 +0,0 @@ -/* 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 - * - 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 -#include - -/* 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 */ diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h deleted file mode 100644 index c3e2060..0000000 --- a/include/net/netfilter/nf_nat.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _NF_NAT_H -#define _NF_NAT_H -#include -#include - -#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 diff --git a/include/xtables-version.h.in b/include/xtables-version.h.in new file mode 100644 index 0000000..cb13827 --- /dev/null +++ b/include/xtables-version.h.in @@ -0,0 +1,2 @@ +#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" +#define XTABLES_VERSION_CODE @libxtables_vmajor@ diff --git a/include/xtables.h.in b/include/xtables.h similarity index 92% rename from include/xtables.h.in rename to include/xtables.h index 28e2933..c35a6e6 100644 --- a/include/xtables.h.in +++ b/include/xtables.h @@ -31,8 +31,7 @@ #define IPPROTO_UDPLITE 136 #endif -#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" -#define XTABLES_VERSION_CODE @libxtables_vmajor@ +#include struct in_addr; @@ -202,6 +201,10 @@ struct xtables_lmap { struct xtables_lmap *next; }; +enum xtables_ext_flags { + XTABLES_EXT_ALIAS = 1 << 0, +}; + /* Include file for additions: new matches and targets. */ struct xtables_match { @@ -214,10 +217,14 @@ 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. */ @@ -251,6 +258,9 @@ struct xtables_match /* 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; @@ -283,9 +293,15 @@ struct xtables_target 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; @@ -319,6 +335,9 @@ struct xtables_target 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; @@ -414,6 +433,8 @@ extern struct xtables_match *xtables_find_match(const char *name, 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); @@ -442,6 +463,7 @@ extern const char *xtables_ipaddr_to_anyname(const struct in_addr *); 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 **, @@ -451,6 +473,7 @@ extern struct in6_addr *xtables_numeric_to_ip6addr(const char *); 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 **, @@ -462,6 +485,22 @@ 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 diff --git a/iptables/.gitignore b/iptables/.gitignore index 5a08937..4fc63aa 100644 --- a/iptables/.gitignore +++ b/iptables/.gitignore @@ -5,6 +5,7 @@ /ip6tables-static /iptables /iptables.8 +/iptables-extensions.8 /iptables-save /iptables-restore /iptables-static diff --git a/iptables/Makefile.am b/iptables/Makefile.am index bdd4da1..61e78db 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -27,7 +27,7 @@ xtables_multi_LDADD += ../libxtables/libxtables.la -lm 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 @@ -38,11 +38,17 @@ if ENABLE_IPV6 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 diff --git a/iptables/Makefile.in b/iptables/Makefile.in index 44aba34..55eb9de 100644 --- a/iptables/Makefile.in +++ b/iptables/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -19,6 +19,23 @@ 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@ @@ -103,6 +120,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(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/||"`;; \ @@ -280,7 +302,7 @@ xtables_multi_LDADD = ../extensions/libext.a $(am__append_4) \ $(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 @@ -325,8 +347,11 @@ xtables.pc: $(top_builddir)/config.status $(srcdir)/xtables.pc.in 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; \ @@ -570,11 +595,18 @@ clean-libtool: -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"; \ @@ -606,11 +638,18 @@ uninstall-man1: 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"; \ @@ -642,8 +681,11 @@ uninstall-man8: 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"; \ @@ -886,11 +928,17 @@ uninstall-man: uninstall-man1 uninstall-man8 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: diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 59a3b2e..dbe19da 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,8 @@ .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 @@ -31,8 +32,23 @@ I/O redirection provided by your shell to read from a file \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. diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 3894d68..0e8252f 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -114,6 +114,70 @@ static void free_argv(void) { 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; @@ -325,11 +389,6 @@ int ip6tables_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; @@ -370,69 +429,7 @@ int ip6tables_restore_main(int argc, char *argv[]) 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); diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 65f3864..8634854 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -87,7 +87,7 @@ or a rule in a built-in chain with target \fBRETURN\fP 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 @@ -106,6 +106,13 @@ the built-in chains \fBINPUT\fP (for packets destined to local sockets), \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 @@ -240,6 +247,15 @@ Give a (currently very brief) description of the command syntax. 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, @@ -281,6 +297,13 @@ See the description of the \fB\-s\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 @@ -362,23 +385,8 @@ When adding or inserting rules into a chain, use \fIcommand\fP 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 @@ -405,6 +413,8 @@ There are several other changes in ip6tables. \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). diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index b191d5d..c8d34e2 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -52,21 +52,6 @@ #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 @@ -85,7 +70,7 @@ #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[] @@ -252,7 +237,7 @@ exit_printhelp(const struct xtables_rule_match *matches) "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" @@ -442,31 +427,6 @@ set_option(unsigned int *options, unsigned int option, uint8_t *invflg, } } -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) @@ -478,9 +438,9 @@ 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"); @@ -563,8 +523,8 @@ print_firewall(const struct ip6t_entry *fw, 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)) @@ -1040,7 +1000,8 @@ static int print_match_save(const struct xt_entry_match *e, 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) @@ -1061,7 +1022,7 @@ static void print_ip(const char *prefix, const struct in6_addr *ip, 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; @@ -1129,16 +1090,8 @@ void print_rule6(const struct ip6t_entry *e, 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 = @@ -1150,6 +1103,7 @@ void print_rule6(const struct ip6t_entry *e, exit(1); } + printf(" -j %s", target->alias ? target->alias(t) : target_name); if (target->save) target->save(&e->ipv6, t); else { @@ -1164,7 +1118,13 @@ void print_rule6(const struct ip6t_entry *e, 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"); } @@ -1249,27 +1209,6 @@ generate_entry(const struct ip6t_entry *fw, 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; @@ -1286,8 +1225,17 @@ static void command_jump(struct iptables_command_state *cs) 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, @@ -1314,8 +1262,16 @@ static void command_match(struct iptables_command_state *cs) 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; @@ -1948,7 +1904,7 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle if (verbose > 1) dump_entries6(*handle); - clear_rule_matches(&cs.matches); + xtables_rule_matches_free(&cs.matches); if (e != NULL) { free(e); diff --git a/iptables/iptables-apply.8 b/iptables/iptables-apply.8 index 8208fd0..66eaf57 100644 --- a/iptables/iptables-apply.8 +++ b/iptables/iptables-apply.8 @@ -18,7 +18,7 @@ connection, the user will not be able to answer affirmatively. In this 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 diff --git a/iptables/iptables-extensions.8.in b/iptables/iptables-extensions.8.in new file mode 100644 index 0000000..9ec3fb0 --- /dev/null +++ b/iptables/iptables-extensions.8.in @@ -0,0 +1,28 @@ +.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@ diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 0dd20cb..2b1d102 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,8 @@ .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 @@ -31,10 +32,23 @@ I/O redirection provided by your shell to read from a file \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. diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 034f960..0822513 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -113,6 +113,70 @@ static void free_argv(void) { 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[]) { @@ -325,11 +389,6 @@ 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; @@ -370,69 +429,7 @@ iptables_restore_main(int argc, char *argv[]) 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); diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 59d6e04..9643705 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -86,7 +86,7 @@ or a rule in a built-in chain with target \fBRETURN\fP 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 @@ -243,6 +243,15 @@ Give a (currently very brief) description of the command syntax. 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, @@ -277,6 +286,13 @@ See the description of the \fB\-s\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 @@ -355,25 +371,10 @@ corresponding to that rule's position in the chain. \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 @@ -408,8 +409,10 @@ seen previously. So the following options are handled differently: .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), diff --git a/iptables/iptables.c b/iptables/iptables.c index 03ac63b..79fa37b 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -48,21 +48,6 @@ #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 @@ -81,7 +66,7 @@ #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) @@ -186,22 +171,6 @@ static const int inverse_for_options[NUMBER_OF_OPT] = #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) { @@ -262,7 +231,7 @@ exit_printhelp(const struct xtables_rule_match *matches) "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" @@ -445,32 +414,6 @@ set_option(unsigned int *options, unsigned int option, uint8_t *invflg, } 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; @@ -480,9 +423,9 @@ 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"); @@ -567,8 +510,8 @@ print_firewall(const struct ipt_entry *fw, 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)) @@ -1048,7 +991,8 @@ static int print_match_save(const struct xt_entry_match *e, 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) @@ -1137,16 +1081,8 @@ void print_rule4(const struct ipt_entry *e, 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 = @@ -1158,6 +1094,7 @@ void print_rule4(const struct ipt_entry *e, exit(1); } + printf(" -j %s", target->alias ? target->alias(t) : target_name); if (target->save) target->save(&e->ip, t); else { @@ -1172,7 +1109,13 @@ void print_rule4(const struct ipt_entry *e, 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"); } @@ -1257,27 +1200,6 @@ generate_entry(const struct ipt_entry *fw, 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; @@ -1295,8 +1217,18 @@ static void command_jump(struct iptables_command_state *cs) 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) @@ -1324,8 +1256,16 @@ static void command_match(struct iptables_command_state *cs) 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; @@ -1963,7 +1903,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle if (verbose > 1) dump_entries(*handle); - clear_rule_matches(&cs.matches); + xtables_rule_matches_free(&cs.matches); if (e != NULL) { free(e); diff --git a/libipq/Makefile.in b/libipq/Makefile.in index 5b6fb34..935f071 100644 --- a/libipq/Makefile.in +++ b/libipq/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -19,6 +19,23 @@ 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@ @@ -98,6 +115,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(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) @@ -285,7 +307,6 @@ libipq.pc: $(top_builddir)/config.status $(srcdir)/libipq.pc.in 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 \ @@ -293,6 +314,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) 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)"; \ } @@ -353,11 +376,18 @@ clean-libtool: -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"; \ @@ -389,8 +419,11 @@ uninstall-man3: 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"; \ diff --git a/libiptc/Makefile.in b/libiptc/Makefile.in index e57112a..d1ffd44 100644 --- a/libiptc/Makefile.in +++ b/libiptc/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -19,6 +19,23 @@ 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@ @@ -115,6 +132,11 @@ SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES) \ $(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 @@ -304,7 +326,6 @@ libip6tc.pc: $(top_builddir)/config.status $(srcdir)/libip6tc.pc.in 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 \ @@ -312,6 +333,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) 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)"; \ } @@ -377,8 +400,11 @@ clean-libtool: -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"; \ diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 7128e1c..ca01bcb 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -113,7 +113,7 @@ typedef unsigned int socklen_t; #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; diff --git a/libxtables/Makefile.in b/libxtables/Makefile.in index a527487..59525ca 100644 --- a/libxtables/Makefile.in +++ b/libxtables/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -18,6 +18,23 @@ # -*- 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@ @@ -105,6 +122,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(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) @@ -284,7 +306,6 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(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 \ @@ -292,6 +313,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) 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)"; \ } diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 014e115..009ab91 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -862,14 +862,77 @@ void xtables_register_match(struct xtables_match *me) 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_ 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); @@ -877,16 +940,14 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) } /* 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. */ @@ -962,13 +1023,15 @@ void xtables_register_target(struct xtables_target *me) 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); @@ -976,16 +1039,14 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) } /* 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. */ @@ -1014,6 +1075,28 @@ void xtables_register_targets(struct xtables_target *target, unsigned int n) } 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 @@ -1133,28 +1216,43 @@ const char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 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; } @@ -1465,7 +1563,7 @@ const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 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; @@ -1492,7 +1590,7 @@ static int ip6addr_prefix_length(const struct in6_addr *k) 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, "/"); @@ -1814,6 +1912,35 @@ xtables_parse_protocol(const char *s) 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) diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c index 452e0fe..78e9abd 100644 --- a/libxtables/xtoptions.c +++ b/libxtables/xtoptions.c @@ -667,6 +667,33 @@ static void xtopt_parse_mport(struct xt_option_call *cb) 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. @@ -677,12 +704,17 @@ static void xtopt_parse_plen(struct xt_option_call *cb) 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; } diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 828104c..02b4bbe 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -1324,7 +1324,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) 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" @@ -1688,7 +1695,8 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl ;; *) 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 @@ -2512,17 +2520,6 @@ freebsd* | dragonfly*) 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 @@ -2639,7 +2636,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # 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 @@ -3255,10 +3252,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -3297,7 +3290,7 @@ irix5* | irix6* | nonstopux*) ;; # 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 ;; @@ -4049,7 +4042,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4348,7 +4341,7 @@ m4_if([$1], [CXX], [ _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*) @@ -6241,9 +6234,6 @@ if test "$_lt_caught_CXX_error" != yes; then _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 @@ -6405,7 +6395,7 @@ if test "$_lt_caught_CXX_error" != yes; then _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 diff --git a/tests/options-most.rules b/tests/options-most.rules index 30dac16..ef4e7f1 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -96,6 +96,9 @@ -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 diff --git a/utils/.gitignore b/utils/.gitignore index ccfd2ec..216d1e4 100644 --- a/utils/.gitignore +++ b/utils/.gitignore @@ -1 +1,2 @@ /nfnl_osf +/nfbpf_compile diff --git a/utils/Makefile.am b/utils/Makefile.am index f1bbfc5..c26aa64 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -4,7 +4,17 @@ AM_CFLAGS = ${regular_CFLAGS} 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 diff --git a/utils/Makefile.in b/utils/Makefile.in index ef7b7a4..0cd9a49 100644 --- a/utils/Makefile.in +++ b/utils/Makefile.in @@ -1,4 +1,4 @@ -# 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, @@ -19,6 +19,23 @@ 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@ @@ -36,7 +53,10 @@ PRE_UNINSTALL = : 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 @@ -50,11 +70,17 @@ mkinstalldirs = $(install_sh) -d 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 @@ -68,8 +94,13 @@ CCLD = $(CC) 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/||"`;; \ @@ -237,8 +268,9 @@ AM_CFLAGS = ${regular_CFLAGS} 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: @@ -275,8 +307,11 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(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; \ @@ -316,6 +351,9 @@ clean-sbinPROGRAMS: 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) @@ -326,6 +364,7 @@ mostlyclean-compile: 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: @@ -356,8 +395,11 @@ clean-libtool: -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"; \ diff --git a/utils/nfbpf_compile.c b/utils/nfbpf_compile.c new file mode 100644 index 0000000..2c46c7b --- /dev/null +++ b/utils/nfbpf_compile.c @@ -0,0 +1,55 @@ +/* + * 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 +#include + +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] ''\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; +} + -- 2.7.4