summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CONTRIBUTORS3
-rw-r--r--Make_global.am5
-rw-r--r--Makefile.am7
-rw-r--r--Makefile.in58
-rw-r--r--aclocal.m4112
-rwxr-xr-xautogen.sh4
-rwxr-xr-xconfigure1211
-rw-r--r--configure.ac116
-rw-r--r--conntrack.825
-rw-r--r--conntrackd.812
-rw-r--r--doc/manual/conntrack-tools.tmpl465
-rw-r--r--doc/stats/conntrackd.conf25
-rw-r--r--doc/sync/alarm/conntrackd.conf30
-rw-r--r--doc/sync/ftfw/conntrackd.conf28
-rw-r--r--doc/sync/notrack/conntrackd.conf30
-rwxr-xr-xdoc/sync/primary-backup.sh10
-rw-r--r--extensions/Makefile.in94
-rw-r--r--extensions/libct_proto_tcp.c9
-rw-r--r--include/Makefile.in25
-rw-r--r--include/cache.h69
-rw-r--r--include/conntrack.h143
-rw-r--r--include/conntrackd.h66
-rw-r--r--include/external.h29
-rw-r--r--include/filter.h9
-rw-r--r--include/internal.h48
-rw-r--r--include/log.h2
-rw-r--r--include/netlink.h7
-rw-r--r--include/network.h59
-rw-r--r--m4/ltversion.m410
-rw-r--r--qa/test-conntrack.c94
-rw-r--r--qa/testsuite/00create20
-rw-r--r--qa/testsuite/01delete6
-rw-r--r--qa/testsuite/02filter23
-rw-r--r--qa/testsuite/03nat40
-rw-r--r--qa/testsuite/04zone8
-rw-r--r--qa/testsuite/05mark27
-rw-r--r--src/.gitignore6
-rw-r--r--src/Makefile.am11
-rw-r--r--src/Makefile.in134
-rw-r--r--src/build.c191
-rw-r--r--src/cache-ct.c356
-rw-r--r--src/cache-exp.c308
-rw-r--r--src/cache.c163
-rw-r--r--src/conntrack.c915
-rw-r--r--src/external_cache.c130
-rw-r--r--src/external_inject.c134
-rw-r--r--src/filter.c98
-rw-r--r--src/internal_bypass.c222
-rw-r--r--src/internal_cache.c287
-rw-r--r--src/lock.c0
-rw-r--r--src/log.c37
-rw-r--r--src/main.c81
-rw-r--r--src/netlink.c139
-rw-r--r--src/network.c24
-rw-r--r--src/parse.c293
-rw-r--r--src/read_config_lex.l5
-rw-r--r--src/read_config_yy.y87
-rw-r--r--src/run.c449
-rw-r--r--src/stats-mode.c50
-rw-r--r--src/sync-alarm.c22
-rw-r--r--src/sync-ftfw.c49
-rw-r--r--src/sync-mode.c265
-rw-r--r--src/sync-notrack.c47
64 files changed, 5452 insertions, 1981 deletions
diff --git a/.gitignore b/.gitignore
index 25b47c6..e255bf5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ src/conntrackd
src/read_config_lex.c
src/read_config_yy.c
src/read_config_yy.h
+/build-aux/
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..c5e40b4
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,3 @@
+Maik Hentsche <netfilter@mm-double.de>:
+ - Feedback & Brainstorming
+ - Bug hunting
diff --git a/Make_global.am b/Make_global.am
index 810253a..e8f603a 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -1,5 +1,6 @@
-AM_CPPFLAGS=$(all_includes) -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CFLAGS = -std=gnu99 -W -Wall \
-Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \
- -Wno-unused-parameter
+ -Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} \
+ ${LIBNETFILTER_CONNTRACK_CFLAGS}
diff --git a/Makefile.am b/Makefile.am
index 70c1bd0..afb4595 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,9 +1,6 @@
include Make_global.am
-# not a GNU package. You can remove this line, if
-# have all needed files, that a GNU package needs
ACLOCAL_AMFLAGS = -I m4
-AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
man_MANS = conntrack.8 conntrackd.8
EXTRA_DIST = $(man_MANS) Make_global.am doc m4
@@ -12,9 +9,5 @@ SUBDIRS = extensions src
DIST_SUBDIRS = include src extensions
LIBS = @LIBNETFILTER_CONNTRACK_LIBS@
-$(OBJECTS): libtool
-libtool: $(LIBTOOL_DEPS)
- $(SHELL) ./config.status --recheck
-
dist-hook:
rm -rf `find $(distdir)/doc -name .svn`
diff --git a/Makefile.in b/Makefile.in
index f42f51f..f7c9656 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -33,18 +33,19 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
DIST_COMMON = $(am__configure_deps) $(srcdir)/Make_global.am \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/configure AUTHORS COPYING INSTALL TODO \
- config.guess config.sub depcomp install-sh ltmain.sh missing \
- ylwrap
+ build-aux/config.guess build-aux/config.sub build-aux/depcomp \
+ build-aux/install-sh build-aux/ltmain.sh build-aux/missing \
+ build-aux/ylwrap config.guess config.sub depcomp install-sh \
+ ltmain.sh missing ylwrap
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -52,6 +53,12 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -125,12 +132,13 @@ am__relativize = \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
-DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
GZIP_ENV = --best
+DIST_ARCHIVES = $(distdir).tar.bz2
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -153,7 +161,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
-HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -191,14 +198,14 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
-XLEX = @XLEX@
-XYACC = @XYACC@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
@@ -249,24 +256,17 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CFLAGS = -std=gnu99 -W -Wall \
-Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \
- -Wno-unused-parameter
+ -Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} \
+ ${LIBNETFILTER_CONNTRACK_CFLAGS}
-
-# not a GNU package. You can remove this line, if
-# have all needed files, that a GNU package needs
ACLOCAL_AMFLAGS = -I m4
-AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
man_MANS = conntrack.8 conntrackd.8
EXTRA_DIST = $(man_MANS) Make_global.am doc m4
SUBDIRS = extensions src
@@ -363,7 +363,7 @@ uninstall-man8:
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
@@ -388,7 +388,7 @@ $(RECURSIVE_TARGETS):
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
@@ -568,7 +568,8 @@ distdir: $(DISTFILES)
top_distdir="$(top_distdir)" distdir="$(distdir)" \
dist-hook
-test -n "$(am__skip_mode_fix)" \
- || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
@@ -602,7 +603,6 @@ dist-zip: distdir
$(am__remove_distdir)
dist dist-all: distdir
- tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
@@ -612,17 +612,17 @@ dist dist-all: distdir
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
- GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
- bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
- unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
- GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
@@ -807,10 +807,6 @@ uninstall-man: uninstall-man8
uninstall uninstall-am uninstall-man uninstall-man8
-$(OBJECTS): libtool
-libtool: $(LIBTOOL_DEPS)
- $(SHELL) ./config.status --recheck
-
dist-hook:
rm -rf `find $(distdir)/doc -name .svn`
diff --git a/aclocal.m4 b/aclocal.m4
index 3eebbac..418c8f1 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.11 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
@@ -13,13 +13,14 @@
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
-[m4_warning([this file was generated for autoconf 2.64.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
+[m4_warning([this file was generated for autoconf 2.67.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
@@ -47,7 +48,10 @@ To do so, use the procedure documented by the package, typically `autoreconf'.])
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
-AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
@@ -60,7 +64,6 @@ if test -n "$PKG_CONFIG"; then
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
-
fi[]dnl
])# PKG_PROG_PKG_CONFIG
@@ -69,34 +72,31 @@ fi[]dnl
# Check to see whether a particular set of modules exists. Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
-#
-# Similar to PKG_CHECK_MODULES, make sure that the first instance of
-# this or PKG_CHECK_MODULES is called, or make sure to call
-# PKG_CHECK_EXISTS manually
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
- m4_ifval([$2], [$2], [:])
+ m4_default([$2], [:])
m4_ifvaln([$3], [else
$3])dnl
fi])
-
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
m4_define([_PKG_CONFIG],
-[if test -n "$PKG_CONFIG"; then
- if test -n "$$1"; then
- pkg_cv_[]$1="$$1"
- else
- PKG_CHECK_EXISTS([$3],
- [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
- [pkg_failed=yes])
- fi
-else
- pkg_failed=untried
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
@@ -138,16 +138,17 @@ and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
- ifelse([$4], , [AC_MSG_ERROR(dnl
+ m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
@@ -155,25 +156,24 @@ $$1_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
-_PKG_TEXT
-])],
- [AC_MSG_RESULT([no])
- $4])
+_PKG_TEXT])[]dnl
+ ])
elif test $pkg_failed = untried; then
- ifelse([$4], , [AC_MSG_FAILURE(dnl
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
_PKG_TEXT
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
- [$4])
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
- ifelse([$3], , :, [$3])
+ $3
fi[]dnl
])# PKG_CHECK_MODULES
@@ -192,7 +192,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], [],
+m4_if([$1], [1.11.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -208,7 +208,7 @@ 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])dnl
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -920,6 +920,23 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
@@ -985,6 +1002,33 @@ Check your system clock])
fi
AC_MSG_RESULT(yes)])
+# Copyright (C) 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# (`yes' being less verbose, `no' or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules],
+[ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')])
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..36b2a2a
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+autoreconf -fi;
+rm -Rf autom4te.cache;
diff --git a/configure b/configure
index 05a90bd..0af1c2e 100755
--- a/configure
+++ b/configure
@@ -1,13 +1,15 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for conntrack-tools 0.9.14.
+# Generated by GNU Autoconf 2.67 for conntrack-tools 1.0.1.
#
# Report bugs to <pablo@netfilter.org>.
#
+#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
# Foundation, Inc.
#
+#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
@@ -317,7 +319,7 @@ $as_echo X"$as_dir" |
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
@@ -357,19 +359,19 @@ else
fi # as_fn_arith
-# as_fn_error ERROR [LINENO LOG_FD]
-# ---------------------------------
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with status $?, using 1 if that was 0.
+# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
- as_status=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $1" >&2
+ $as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -676,10 +678,11 @@ fi
-exec 7<&0 </dev/null 6>&1
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
@@ -698,8 +701,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='conntrack-tools'
PACKAGE_TARNAME='conntrack-tools'
-PACKAGE_VERSION='0.9.14'
-PACKAGE_STRING='conntrack-tools 0.9.14'
+PACKAGE_VERSION='1.0.1'
+PACKAGE_STRING='conntrack-tools 1.0.1'
PACKAGE_BUGREPORT='pablo@netfilter.org'
PACKAGE_URL=''
@@ -743,14 +746,13 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
-XLEX
-XYACC
LIBNETFILTER_CONNTRACK_LIBS
LIBNETFILTER_CONNTRACK_CFLAGS
LIBNFNETLINK_LIBS
LIBNFNETLINK_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
PKG_CONFIG
-HAVE_PKG_CONFIG
YFLAGS
YACC
LEXLIB
@@ -792,6 +794,8 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
am__untar
am__tar
AMTAR
@@ -815,10 +819,6 @@ am__isrc
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
-target_os
-target_vendor
-target_cpu
-target
host_os
host_vendor
host_cpu
@@ -868,9 +868,10 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+enable_silent_rules
enable_dependency_tracking
-enable_shared
enable_static
+enable_shared
with_pic
enable_fast_install
with_gnu_ld
@@ -888,6 +889,8 @@ CPP
YACC
YFLAGS
PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
LIBNFNETLINK_CFLAGS
LIBNFNETLINK_LIBS
LIBNETFILTER_CONNTRACK_CFLAGS
@@ -954,8 +957,9 @@ do
fi
case $ac_option in
- *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *) ac_optarg=yes ;;
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
@@ -1000,7 +1004,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1026,7 +1030,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1230,7 +1234,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1246,7 +1250,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1276,8 +1280,8 @@ do
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
- -*) as_fn_error "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information."
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
;;
*=*)
@@ -1285,7 +1289,7 @@ Try \`$0 --help' for more information."
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
- as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
@@ -1303,13 +1307,13 @@ done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- as_fn_error "missing argument to $ac_option"
+ as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
- fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
*) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1332,7 +1336,7 @@ do
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
- as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
@@ -1346,8 +1350,8 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
- $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1362,9 +1366,9 @@ test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- as_fn_error "working directory cannot be determined"
+ as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- as_fn_error "pwd does not report name of working directory"
+ as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
@@ -1403,11 +1407,11 @@ else
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
@@ -1433,7 +1437,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 conntrack-tools 0.9.14 to adapt to many kinds of systems.
+\`configure' configures conntrack-tools 1.0.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1447,7 +1451,7 @@ Configuration:
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
+ -q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
@@ -1498,13 +1502,12 @@ Program names:
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
- --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of conntrack-tools 0.9.14:";;
+ short | recursive ) echo "Configuration of conntrack-tools 1.0.1:";;
esac
cat <<\_ACEOF
@@ -1512,10 +1515,12 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
+ --enable-static[=PKGS] build static libraries [default=no]
--enable-shared[=PKGS] build shared libraries [default=yes]
- --enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
@@ -1533,7 +1538,7 @@ Some influential environment variables:
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
- CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
YACC The `Yet Another C Compiler' implementation to use. Defaults to
@@ -1542,6 +1547,10 @@ Some influential environment variables:
This script will default YFLAGS to the empty string to avoid a
default value of `-d' given by some make applications.
PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
LIBNFNETLINK_CFLAGS
C compiler flags for LIBNFNETLINK, overriding pkg-config
LIBNFNETLINK_LIBS
@@ -1618,10 +1627,10 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-conntrack-tools configure 0.9.14
-generated by GNU Autoconf 2.64
+conntrack-tools configure 1.0.1
+generated by GNU Autoconf 2.67
-Copyright (C) 2009 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1666,7 +1675,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
+ as_fn_set_status $ac_retval
} # ac_fn_c_try_compile
@@ -1712,7 +1721,7 @@ fi
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
+ as_fn_set_status $ac_retval
} # ac_fn_c_try_link
@@ -1725,7 +1734,7 @@ ac_fn_c_check_header_compile ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1768,7 +1777,7 @@ $as_echo "$ac_try_echo"; } >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } >/dev/null && {
+ test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then :
@@ -1780,7 +1789,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
+ as_fn_set_status $ac_retval
} # ac_fn_c_try_cpp
@@ -1822,7 +1831,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
+ as_fn_set_status $ac_retval
} # ac_fn_c_try_run
@@ -1834,7 +1843,7 @@ ac_fn_c_check_func ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1901,10 +1910,10 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ if eval "test \"\${$3+set}\"" = set; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
@@ -1940,7 +1949,7 @@ if ac_fn_c_try_cpp "$LINENO"; then :
else
ac_header_preproc=no
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }
@@ -1963,17 +1972,15 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( cat <<\_ASBOX
-## ---------------------------------- ##
+( $as_echo "## ---------------------------------- ##
## Report this to pablo@netfilter.org ##
-## ---------------------------------- ##
-_ASBOX
+## ---------------------------------- ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
@@ -1989,8 +1996,8 @@ 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 conntrack-tools $as_me 0.9.14, which was
-generated by GNU Autoconf 2.64. Invocation command line was
+It was created by conntrack-tools $as_me 1.0.1, which was
+generated by GNU Autoconf 2.67. Invocation command line was
$ $0 $@
@@ -2100,11 +2107,9 @@ trap 'exit_status=$?
{
echo
- cat <<\_ASBOX
-## ---------------- ##
+ $as_echo "## ---------------- ##
## Cache variables. ##
-## ---------------- ##
-_ASBOX
+## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
@@ -2138,11 +2143,9 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- cat <<\_ASBOX
-## ----------------- ##
+ $as_echo "## ----------------- ##
## Output variables. ##
-## ----------------- ##
-_ASBOX
+## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
@@ -2155,11 +2158,9 @@ _ASBOX
echo
if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------------- ##
+ $as_echo "## ------------------- ##
## File substitutions. ##
-## ------------------- ##
-_ASBOX
+## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
@@ -2173,11 +2174,9 @@ _ASBOX
fi
if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
+ $as_echo "## ----------- ##
## confdefs.h. ##
-## ----------- ##
-_ASBOX
+## ----------- ##"
echo
cat confdefs.h
echo
@@ -2232,7 +2231,12 @@ _ACEOF
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- ac_site_file1=$CONFIG_SITE
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
elif test "x$prefix" != xNONE; then
ac_site_file1=$prefix/share/config.site
ac_site_file2=$prefix/etc/config.site
@@ -2243,18 +2247,22 @@ fi
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
do
test "x$ac_site_file" = xNONE && continue
- if test -r "$ac_site_file"; then
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
done
if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
@@ -2323,7 +2331,7 @@ if $ac_cache_corrupted; then
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2336,19 +2344,24 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- for ac_t in install-sh install.sh shtool; do
- if test -f "$ac_dir/$ac_t"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/$ac_t -c"
- break 2
- fi
- done
+for ac_dir in build-aux "$srcdir"/build-aux; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
done
if test -z "$ac_aux_dir"; then
- as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5
fi
# These three variables are undocumented and unsupported,
@@ -2360,9 +2373,10 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
$as_echo_n "checking build system type... " >&6; }
@@ -2373,16 +2387,16 @@ else
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
test "x$ac_build_alias" = x &&
- as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
$as_echo "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
-*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
@@ -2407,7 +2421,7 @@ else
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
fi
fi
@@ -2415,7 +2429,7 @@ fi
$as_echo "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
-*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
@@ -2431,47 +2445,6 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
-$as_echo_n "checking target system type... " >&6; }
-if test "${ac_cv_target+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$target_alias" = x; then
- ac_cv_target=$ac_cv_host
-else
- ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
- as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
-$as_echo "$ac_cv_target" >&6; }
-case $ac_cv_target in
-*-*-*) ;;
-*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
-esac
-target=$ac_cv_target
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_target
-shift
-target_cpu=$1
-target_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-target_os=$*
-IFS=$ac_save_IFS
-case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-
-
-# The aliases save the names the user supplied, while $host etc.
-# will get canonicalized.
-test -n "$target_alias" &&
- test "$program_prefix$program_suffix$program_transform_name" = \
- NONENONEs,x,x, &&
- program_prefix=${target_alias}-
-
-
am__api_version='1.11'
@@ -2579,11 +2552,11 @@ am_lf='
'
case `pwd` in
*[\\\"\#\$\&\'\`$am_lf]*)
- as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5 ;;
esac
case $srcdir in
*[\\\"\#\$\&\'\`$am_lf\ \ ]*)
- as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5 ;;
esac
# Do `set' in a subshell so we don't clobber the current shell's
@@ -2605,7 +2578,7 @@ if (
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
- as_fn_error "ls -t appears to fail. Make sure there is not a broken
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
alias in your environment" "$LINENO" 5
fi
@@ -2615,7 +2588,7 @@ then
# Ok.
:
else
- as_fn_error "newly created file is older than distributed files!
+ as_fn_error $? "newly created file is older than distributed files!
Check your system clock" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
@@ -2787,6 +2760,7 @@ IFS=$as_save_IFS
fi
+ test -d ./--version && rmdir ./--version
if test "${ac_cv_path_mkdir+set}" = set; then
MKDIR_P="$ac_cv_path_mkdir -p"
else
@@ -2794,7 +2768,6 @@ fi
# value for MKDIR_P within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
- test -d ./--version && rmdir ./--version
MKDIR_P="$ac_install_sh -d"
fi
fi
@@ -2853,7 +2826,7 @@ done
$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat >conftest.make <<\_ACEOF
@@ -2861,7 +2834,7 @@ SHELL = /bin/sh
all:
@echo '@@@%%%=$(MAKE)=@@@%%%'
_ACEOF
-# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
case `${MAKE-make} -f conftest.make 2>/dev/null` in
*@@@%%%=?*=@@@%%%*)
eval ac_cv_prog_make_${ac_make}_set=yes;;
@@ -2895,7 +2868,7 @@ if test "`cd $srcdir && pwd`" != "`pwd`"; then
am__isrc=' -I$(srcdir)'
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
- as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
fi
fi
@@ -2911,7 +2884,7 @@ fi
# Define the identity of the package.
PACKAGE='conntrack-tools'
- VERSION='0.9.14'
+ VERSION='1.0.1'
cat >>confdefs.h <<_ACEOF
@@ -2945,13 +2918,107 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
AMTAR=${AMTAR-"${am_missing_run}tar"}
-am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5
+$as_echo_n "checking how to create a pax tar archive... " >&6; }
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar pax cpio none'
+_am_tools=${am_cv_prog_tar_pax-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ { echo "$as_me:$LINENO: $_am_tar --version" >&5
+ ($_am_tar --version) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && break
+ done
+ am__tar="$_am_tar --format=posix -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=posix -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x pax -w "$$tardir"'
+ am__tar_='pax -L -x pax -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H pax -L'
+ am__tar_='find "$tardir" -print | cpio -o -H pax -L'
+ am__untar='cpio -i -H pax -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_pax}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+ (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+ ($am__untar <conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+if test "${am_cv_prog_tar_pax+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_prog_tar_pax=$_am_tool
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5
+$as_echo "$am_cv_prog_tar_pax" >&6; }
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=0;;
+esac
+AM_BACKSLASH='\'
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3252,8 +3319,8 @@ fi
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "no acceptable C compiler found in \$PATH
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5 ; }
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3274,32 +3341,30 @@ $as_echo "$ac_try_echo"; } >&5
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
- rm -f conftest.er1 conftest.err
fi
+ rm -f conftest.er1 conftest.err
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdio.h>
+
int
main ()
{
-FILE *f = fopen ("conftest.out", "w");
- return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
@@ -3361,62 +3426,28 @@ test "$ac_cv_exeext" = no && ac_cv_exeext=
else
ac_file=''
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
if test -z "$ac_file"; then :
- $as_echo "$as_me: failed program was:" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "C compiler cannot create executables
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5 ; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." "$LINENO" 5; }
- fi
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
@@ -3446,16 +3477,75 @@ done
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
-rm -f conftest$ac_cv_exeext
+rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5 ; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if test "${ac_cv_objext+set}" = set; then :
@@ -3498,8 +3588,8 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
@@ -3908,6 +3998,37 @@ else
fi
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=no
+fi
+
+
+
+
+
+
+
+
+
case `pwd` in
*\ * | *\ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -3916,8 +4037,8 @@ esac
-macro_version='2.2.6'
-macro_revision='1.3012'
+macro_version='2.2.6b'
+macro_revision='1.3017'
@@ -3990,7 +4111,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_SED"; then
- as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
fi
else
ac_cv_path_SED=$SED
@@ -4066,7 +4187,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
- as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
@@ -4132,7 +4253,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
- as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
@@ -4199,7 +4320,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_FGREP"; then
- as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_FGREP=$FGREP
@@ -4315,7 +4436,7 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
if test "${lt_cv_prog_gnu_ld+set}" = set; then :
@@ -4517,13 +4638,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:4520: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:4641: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:4523: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:4644: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:4526: output\"" >&5)
+ (eval echo "\"\$as_me:4647: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5729,7 +5850,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5732 "configure"' > conftest.$ac_ext
+ echo '#line 5853 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6518,7 +6639,7 @@ else
# Broken: fails on valid input.
continue
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
@@ -6534,11 +6655,11 @@ else
ac_preproc_ok=:
break
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
break
fi
@@ -6577,7 +6698,7 @@ else
# Broken: fails on valid input.
continue
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
@@ -6593,18 +6714,18 @@ else
ac_preproc_ok=:
break
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
ac_ext=c
@@ -6733,8 +6854,7 @@ do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
@@ -6800,36 +6920,6 @@ fi
- # Check whether --enable-static was given.
-if test "${enable_static+set}" = set; then :
- enableval=$enable_static; p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_static=yes
-fi
-
-
-
-
-
-
-
-
# Check whether --with-pic was given.
@@ -7259,11 +7349,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7262: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7352: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7266: \$? = $ac_status" >&5
+ echo "$as_me:7356: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7598,11 +7688,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7601: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7691: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7605: \$? = $ac_status" >&5
+ echo "$as_me:7695: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7703,11 +7793,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7706: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7796: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7710: \$? = $ac_status" >&5
+ echo "$as_me:7800: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7758,11 +7848,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7761: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7851: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7765: \$? = $ac_status" >&5
+ echo "$as_me:7855: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10141,7 +10231,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10144 "configure"
+#line 10234 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10237,7 +10327,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10240 "configure"
+#line 10330 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10561,7 +10651,7 @@ if test -f lex.yy.c; then
elif test -f lexyy.c; then
ac_cv_prog_lex_root=lexyy
else
- as_fn_error "cannot find output from $LEX; giving up" "$LINENO" 5
+ as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
@@ -10680,57 +10770,48 @@ done
test -n "$YACC" || YACC="yacc"
-case $target in
+case "$host" in
*-*-linux*) ;;
-*) as_fn_error "Linux only, dude!" "$LINENO" 5;;
+*) as_fn_error $? "Linux only, dude!" "$LINENO" 5 ;;
esac
-LIBNFNETLINK_REQUIRED=1.0.0
-LIBNETFILTER_CONNTRACK_REQUIRED=0.0.101
-
-# Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_HAVE_PKG_CONFIG+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$HAVE_PKG_CONFIG"; then
- ac_cv_prog_HAVE_PKG_CONFIG="$HAVE_PKG_CONFIG" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_HAVE_PKG_CONFIG="yes"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
+if test -z "$ac_cv_prog_YACC"
+then
+ echo "*** Error: No suitable bison/yacc found. ***"
+ echo " Please install the 'bison' package."
+ exit 1
fi
+if test -z "$ac_cv_prog_LEX"
+then
+ echo "*** Error: No suitable flex/lex found. ***"
+ echo " Please install the 'flex' package."
+ exit 1
fi
-HAVE_PKG_CONFIG=$ac_cv_prog_HAVE_PKG_CONFIG
-if test -n "$HAVE_PKG_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_PKG_CONFIG" >&5
-$as_echo "$HAVE_PKG_CONFIG" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking flex version" >&5
+$as_echo_n "checking flex version... " >&6; }
+flex_version=`$ac_cv_prog_LEX --version | sed 's/version//g' | awk '/flex/ {print $2}'`
+flex_major=`echo $flex_version| cut -d . -f 1`
+flex_minor=`echo $flex_version| cut -d . -f 2`
+flex_rev=`echo $flex_version| cut -d . -f 3`
+
+if test "$flex_major" -eq "2" && test "$flex_minor" -eq "5" && test "$flex_rev" -ge "33"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flex_version. OK" >&5
+$as_echo "$flex_version. OK" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: flex version $flex_version found.
+ Version 2.5.33 or greater is required. You may experience problems
+ while compilating the conntrack-tools. Please, consider to upgrade
+ flex." >&5
+$as_echo "$as_me: WARNING: flex version $flex_version found.
+ Version 2.5.33 or greater is required. You may experience problems
+ while compilating the conntrack-tools. Please, consider to upgrade
+ flex." >&2;}
fi
-if test "x$HAVE_PKG_CONFIG" = "x"
-then
- echo "*** Error: No suitable pkg-config found. ***"
- echo " Please install the 'pkg-config' package."
- exit 1
-fi
+
+
@@ -10846,53 +10927,50 @@ $as_echo "yes" >&6; }
$as_echo "no" >&6; }
PKG_CONFIG=""
fi
-
fi
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBNFNETLINK" >&5
$as_echo_n "checking for LIBNFNETLINK... " >&6; }
-if test -n "$PKG_CONFIG"; then
- if test -n "$LIBNFNETLINK_CFLAGS"; then
- pkg_cv_LIBNFNETLINK_CFLAGS="$LIBNFNETLINK_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= \$LIBNFNETLINK_REQUIRED\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= $LIBNFNETLINK_REQUIRED") 2>&5
+if test -n "$LIBNFNETLINK_CFLAGS"; then
+ pkg_cv_LIBNFNETLINK_CFLAGS="$LIBNFNETLINK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_LIBNFNETLINK_CFLAGS=`$PKG_CONFIG --cflags "libnfnetlink >= $LIBNFNETLINK_REQUIRED" 2>/dev/null`
+ pkg_cv_LIBNFNETLINK_CFLAGS=`$PKG_CONFIG --cflags "libnfnetlink >= 1.0.0" 2>/dev/null`
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$LIBNFNETLINK_LIBS"; then
- pkg_cv_LIBNFNETLINK_LIBS="$LIBNFNETLINK_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= \$LIBNFNETLINK_REQUIRED\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= $LIBNFNETLINK_REQUIRED") 2>&5
+if test -n "$LIBNFNETLINK_LIBS"; then
+ pkg_cv_LIBNFNETLINK_LIBS="$LIBNFNETLINK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_LIBNFNETLINK_LIBS=`$PKG_CONFIG --libs "libnfnetlink >= $LIBNFNETLINK_REQUIRED" 2>/dev/null`
+ pkg_cv_LIBNFNETLINK_LIBS=`$PKG_CONFIG --libs "libnfnetlink >= 1.0.0" 2>/dev/null`
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
@@ -10900,71 +10978,88 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- LIBNFNETLINK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libnfnetlink >= $LIBNFNETLINK_REQUIRED"`
+ LIBNFNETLINK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libnfnetlink >= 1.0.0" 2>&1`
else
- LIBNFNETLINK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libnfnetlink >= $LIBNFNETLINK_REQUIRED"`
+ LIBNFNETLINK_PKG_ERRORS=`$PKG_CONFIG --print-errors "libnfnetlink >= 1.0.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBNFNETLINK_PKG_ERRORS" >&5
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- as_fn_error "Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED" "$LINENO" 5
+ as_fn_error $? "Package requirements (libnfnetlink >= 1.0.0) were not met:
+
+$LIBNFNETLINK_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBNFNETLINK_CFLAGS
+and LIBNFNETLINK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then
- as_fn_error "Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED" "$LINENO" 5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables LIBNFNETLINK_CFLAGS
+and LIBNFNETLINK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5 ; }
else
LIBNFNETLINK_CFLAGS=$pkg_cv_LIBNFNETLINK_CFLAGS
LIBNFNETLINK_LIBS=$pkg_cv_LIBNFNETLINK_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- :
-fi
+fi
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBNETFILTER_CONNTRACK" >&5
$as_echo_n "checking for LIBNETFILTER_CONNTRACK... " >&6; }
-if test -n "$PKG_CONFIG"; then
- if test -n "$LIBNETFILTER_CONNTRACK_CFLAGS"; then
- pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS="$LIBNETFILTER_CONNTRACK_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_conntrack >= \$LIBNETFILTER_CONNTRACK_REQUIRED\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED") 2>&5
+if test -n "$LIBNETFILTER_CONNTRACK_CFLAGS"; then
+ pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS="$LIBNETFILTER_CONNTRACK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_conntrack >= 1.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnetfilter_conntrack >= 1.0.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS=`$PKG_CONFIG --cflags "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED" 2>/dev/null`
+ pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS=`$PKG_CONFIG --cflags "libnetfilter_conntrack >= 1.0.0" 2>/dev/null`
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$LIBNETFILTER_CONNTRACK_LIBS"; then
- pkg_cv_LIBNETFILTER_CONNTRACK_LIBS="$LIBNETFILTER_CONNTRACK_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_conntrack >= \$LIBNETFILTER_CONNTRACK_REQUIRED\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED") 2>&5
+if test -n "$LIBNETFILTER_CONNTRACK_LIBS"; then
+ pkg_cv_LIBNETFILTER_CONNTRACK_LIBS="$LIBNETFILTER_CONNTRACK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_conntrack >= 1.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libnetfilter_conntrack >= 1.0.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_LIBNETFILTER_CONNTRACK_LIBS=`$PKG_CONFIG --libs "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED" 2>/dev/null`
+ pkg_cv_LIBNETFILTER_CONNTRACK_LIBS=`$PKG_CONFIG --libs "libnetfilter_conntrack >= 1.0.0" 2>/dev/null`
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
@@ -10972,144 +11067,44 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- LIBNETFILTER_CONNTRACK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED"`
+ LIBNETFILTER_CONNTRACK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libnetfilter_conntrack >= 1.0.0" 2>&1`
else
- LIBNETFILTER_CONNTRACK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED"`
+ LIBNETFILTER_CONNTRACK_PKG_ERRORS=`$PKG_CONFIG --print-errors "libnetfilter_conntrack >= 1.0.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBNETFILTER_CONNTRACK_PKG_ERRORS" >&5
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- as_fn_error "Cannot find libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED" "$LINENO" 5
-elif test $pkg_failed = untried; then
- as_fn_error "Cannot find libnetfilter_conntrack >= $LIBNETFILTER_CONNTRACK_REQUIRED" "$LINENO" 5
-else
- LIBNETFILTER_CONNTRACK_CFLAGS=$pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS
- LIBNETFILTER_CONNTRACK_LIBS=$pkg_cv_LIBNETFILTER_CONNTRACK_LIBS
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- :
-fi
+ as_fn_error $? "Package requirements (libnetfilter_conntrack >= 1.0.0) were not met:
-for ac_prog in $YACC bison yacc
-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 test "${ac_cv_prog_XYACC+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$XYACC"; then
- ac_cv_prog_XYACC="$XYACC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_XYACC="$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
-XYACC=$ac_cv_prog_XYACC
-if test -n "$XYACC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XYACC" >&5
-$as_echo "$XYACC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$XYACC" && break
-done
-test -n "$XYACC" || XYACC="none"
+$LIBNETFILTER_CONNTRACK_PKG_ERRORS
-if test "$XYACC" = "none"
-then
- echo "*** Error: No suitable bison/yacc found. ***"
- echo " Please install the 'bison' package."
- exit 1
-fi
-for ac_prog in $LEX flex lex
-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 test "${ac_cv_prog_XLEX+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$XLEX"; then
- ac_cv_prog_XLEX="$XLEX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_XLEX="$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
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
-fi
-fi
-XLEX=$ac_cv_prog_XLEX
-if test -n "$XLEX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XLEX" >&5
-$as_echo "$XLEX" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+Alternatively, you may set the environment variables LIBNETFILTER_CONNTRACK_CFLAGS
+and LIBNETFILTER_CONNTRACK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
-fi
-
-
- test -n "$XLEX" && break
-done
-test -n "$XLEX" || XLEX="none"
-
-if test "$XLEX" = "none"
-then
- echo "*** Error: No suitable flex/lex found. ***"
- echo " Please install the 'flex' package."
- exit 1
-fi
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking flex version" >&5
-$as_echo_n "checking flex version... " >&6; }
-flex_version=`$LEX --version | sed 's/version//g' | awk '/flex/ {print $2}'`
-flex_major=`echo $flex_version| cut -d . -f 1`
-flex_minor=`echo $flex_version| cut -d . -f 2`
-flex_rev=`echo $flex_version| cut -d . -f 3`
+Alternatively, you may set the environment variables LIBNETFILTER_CONNTRACK_CFLAGS
+and LIBNETFILTER_CONNTRACK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
-if test "$flex_major" -eq "2" && test "$flex_minor" -eq "5" && test "$flex_rev" -ge "33"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flex_version. OK" >&5
-$as_echo "$flex_version. OK" >&6; }
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5 ; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: flex version $flex_version found.
- Version 2.5.33 or greater is required. You may experience problems
- while compilating the conntrack-tools. Please, consider to upgrade
- flex." >&5
-$as_echo "$as_me: WARNING: flex version $flex_version found.
- Version 2.5.33 or greater is required. You may experience problems
- while compilating the conntrack-tools. Please, consider to upgrade
- flex." >&2;}
+ LIBNETFILTER_CONNTRACK_CFLAGS=$pkg_cv_LIBNETFILTER_CONNTRACK_CFLAGS
+ LIBNETFILTER_CONNTRACK_LIBS=$pkg_cv_LIBNETFILTER_CONNTRACK_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
fi
for ac_header in linux/capability.h
@@ -11121,7 +11116,7 @@ if test "x$ac_cv_header_linux_capability_h" = x""yes; then :
_ACEOF
else
- as_fn_error "Cannot find linux/capabibility.h" "$LINENO" 5
+ as_fn_error $? "Cannot find linux/capabibility.h" "$LINENO" 5
fi
done
@@ -11131,97 +11126,6 @@ done
# FIXME: Replace `main' with a function in `-lc':
# FIXME: Replace `main' with a function in `-ldl':
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nfnl_query in -lnfnetlink" >&5
-$as_echo_n "checking for nfnl_query in -lnfnetlink... " >&6; }
-if test "${ac_cv_lib_nfnetlink_nfnl_query_+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnfnetlink -lnfnetlink $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char nfnl_query ();
-int
-main ()
-{
-return nfnl_query ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_nfnetlink_nfnl_query_=yes
-else
- ac_cv_lib_nfnetlink_nfnl_query_=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nfnetlink_nfnl_query_" >&5
-$as_echo "$ac_cv_lib_nfnetlink_nfnl_query_" >&6; }
-if test "x$ac_cv_lib_nfnetlink_nfnl_query_" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNFNETLINK 1
-_ACEOF
-
- LIBS="-lnfnetlink $LIBS"
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nfct_query in -lnetfilter_conntrack" >&5
-$as_echo_n "checking for nfct_query in -lnetfilter_conntrack... " >&6; }
-if test "${ac_cv_lib_netfilter_conntrack_nfct_query_+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnetfilter_conntrack -lnetfilter_conntrack $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char nfct_query ();
-int
-main ()
-{
-return nfct_query ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_netfilter_conntrack_nfct_query_=yes
-else
- ac_cv_lib_netfilter_conntrack_nfct_query_=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netfilter_conntrack_nfct_query_" >&5
-$as_echo "$ac_cv_lib_netfilter_conntrack_nfct_query_" >&6; }
-if test "x$ac_cv_lib_netfilter_conntrack_nfct_query_" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNETFILTER_CONNTRACK 1
-_ACEOF
-
- LIBS="-lnetfilter_conntrack $LIBS"
-
-fi
-
-
for ac_header in arpa/inet.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default"
@@ -11303,10 +11207,6 @@ fi
# Checks for library functions.
-CFLAGS="$CFLAGS $LIBNETFILTER_CONNTRACK_CFLAGS"
-
-
-
ac_config_files="$ac_config_files Makefile src/Makefile include/Makefile extensions/Makefile"
cat >confcache <<\_ACEOF
@@ -11428,6 +11328,7 @@ DEFS=`sed -n "$ac_script" confdefs.h`
ac_libobjs=
ac_ltlibobjs=
+U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
@@ -11451,11 +11352,11 @@ else
fi
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
- as_fn_error "conditional \"AMDEP\" was never defined.
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
- as_fn_error "conditional \"am__fastdepCC\" was never defined.
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
@@ -11605,19 +11506,19 @@ export LANGUAGE
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-# as_fn_error ERROR [LINENO LOG_FD]
-# ---------------------------------
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with status $?, using 1 if that was 0.
+# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
- as_status=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $1" >&2
+ $as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -11813,7 +11714,7 @@ $as_echo X"$as_dir" |
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
@@ -11866,8 +11767,8 @@ 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 conntrack-tools $as_me 0.9.14, which was
-generated by GNU Autoconf 2.64. Invocation command line was
+This file was extended by conntrack-tools $as_me 1.0.1, which was
+generated by GNU Autoconf 2.67. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -11903,6 +11804,7 @@ Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
-V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
-q, --quiet, --silent
do not print progress messages
-d, --debug don't remove temporary files
@@ -11920,12 +11822,13 @@ Report bugs to <pablo@netfilter.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-conntrack-tools config.status 0.9.14
-configured by $0, generated by GNU Autoconf 2.64,
- with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+conntrack-tools config.status 1.0.1
+configured by $0, generated by GNU Autoconf 2.67,
+ with options \\"\$ac_cs_config\\"
-Copyright (C) 2009 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -11943,11 +11846,16 @@ ac_need_defaults=:
while test $# != 0
do
case $1 in
- --*=*)
+ --*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
*)
ac_option=$1
ac_optarg=$2
@@ -11961,12 +11869,15 @@ do
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
$as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
@@ -11977,7 +11888,7 @@ do
ac_cs_silent=: ;;
# This is an error.
- -*) as_fn_error "unrecognized option: \`$1'
+ -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
@@ -12031,10 +11942,10 @@ AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
+enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
-enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
@@ -12293,7 +12204,7 @@ do
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"extensions/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/Makefile" ;;
- *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
esac
done
@@ -12330,7 +12241,7 @@ $debug ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
-} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
@@ -12347,7 +12258,7 @@ if test "x$ac_cr" = x; then
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
- ac_cs_awk_cr='\r'
+ ac_cs_awk_cr='\\r'
else
ac_cs_awk_cr=$ac_cr
fi
@@ -12361,18 +12272,18 @@ _ACEOF
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
@@ -12394,7 +12305,7 @@ s/'"$ac_delim"'$//
t delim
:nl
h
-s/\(.\{148\}\).*/\1/
+s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
@@ -12408,7 +12319,7 @@ s/.\{148\}//
t nl
:delim
h
-s/\(.\{148\}\).*/\1/
+s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
@@ -12461,20 +12372,28 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
else
cat
fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
- || as_fn_error "could not setup config files machinery" "$LINENO" 5
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
s/^[^=]*=[ ]*$//
}'
fi
@@ -12492,7 +12411,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
- :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -12520,7 +12439,7 @@ do
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
- as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
@@ -12547,7 +12466,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
case $ac_tag in
*:-:* | *:-) cat >"$tmp/stdin" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
@@ -12684,22 +12603,22 @@ s&@MKDIR_P@&$ac_MKDIR_P&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&5
+which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&2;}
+which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$tmp/stdin"
case $ac_file in
-) cat "$tmp/out" && rm -f "$tmp/out";;
*) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
esac \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
@@ -12858,6 +12777,9 @@ available_tags=""
# ### BEGIN LIBTOOL CONFIG
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
# Which release of libtool.m4 was used?
macro_version=$macro_version
macro_revision=$macro_revision
@@ -12865,9 +12787,6 @@ macro_revision=$macro_revision
# Whether or not to build shared libraries.
build_libtool_libs=$enable_shared
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
# What type of objects to build.
pic_mode=$pic_mode
@@ -13450,7 +13369,7 @@ _ACEOF
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
- as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
@@ -13471,7 +13390,7 @@ if test "$no_create" != yes; then
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
- $ac_cs_success || as_fn_exit $?
+ $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..26a7e02
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,116 @@
+AC_INIT(conntrack-tools, 1.0.1, pablo@netfilter.org)
+AC_CONFIG_AUX_DIR([build-aux])
+
+AC_CANONICAL_HOST
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE([-Wall foreign subdir-objects
+ tar-pax no-dist-gzip dist-bzip2 1.6])
+
+dnl kernel style compile messages
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_PROG_CC
+AC_DISABLE_STATIC
+AM_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AM_PROG_LEX
+AC_PROG_YACC
+
+case "$host" in
+*-*-linux*) ;;
+*) AC_MSG_ERROR([Linux only, dude!]);;
+esac
+
+dnl Dependencies
+if test -z "$ac_cv_prog_YACC"
+then
+ echo "*** Error: No suitable bison/yacc found. ***"
+ echo " Please install the 'bison' package."
+ exit 1
+fi
+if test -z "$ac_cv_prog_LEX"
+then
+ echo "*** Error: No suitable flex/lex found. ***"
+ echo " Please install the 'flex' package."
+ exit 1
+fi
+
+AC_MSG_CHECKING(flex version)
+flex_version=`$ac_cv_prog_LEX --version | sed 's/version//g' | awk '/flex/ {print $2}'`
+flex_major=`echo $flex_version| cut -d . -f 1`
+flex_minor=`echo $flex_version| cut -d . -f 2`
+flex_rev=`echo $flex_version| cut -d . -f 3`
+
+if test "$flex_major" -eq "2" && test "$flex_minor" -eq "5" && test "$flex_rev" -ge "33"; then
+ AC_MSG_RESULT([$flex_version. OK])
+else
+ AC_MSG_WARN([flex version $flex_version found.
+ Version 2.5.33 or greater is required. You may experience problems
+ while compilating the conntrack-tools. Please, consider to upgrade
+ flex.])
+fi
+
+PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 1.0.0])
+PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.0])
+
+AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])])
+
+# Checks for libraries.
+# FIXME: Replace `main' with a function in `-lc':
+dnl AC_CHECK_LIB([c], [main])
+# FIXME: Replace `main' with a function in `-ldl':
+
+AC_CHECK_HEADERS(arpa/inet.h)
+dnl check for inet_pton
+AC_CHECK_FUNCS(inet_pton)
+dnl Some systems have it, but not IPv6
+if test "$ac_cv_func_inet_pton" = "yes" ; then
+AC_MSG_CHECKING(if inet_pton supports IPv6)
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+int main()
+ {
+ struct in6_addr addr6;
+ if (inet_pton(AF_INET6, "::1", &addr6) < 1)
+ exit(1);
+ else
+ exit(0);
+ }
+ ]])],[ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.])
+ ],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)])
+fi
+
+# Checks for header files.
+dnl AC_HEADER_STDC
+dnl AC_CHECK_HEADERS([netinet/in.h stdlib.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+dnl AC_C_CONST
+dnl AC_C_INLINE
+
+# Checks for library functions.
+dnl AC_FUNC_MALLOC
+dnl AC_FUNC_VPRINTF
+dnl AC_CHECK_FUNCS([memset])
+
+dnl AC_CONFIG_FILES([Makefile
+dnl debug/Makefile
+dnl debug/src/Makefile
+dnl extensions/Makefile
+dnl src/Makefile])
+
+AC_CONFIG_FILES([Makefile src/Makefile include/Makefile extensions/Makefile])
+AC_OUTPUT
diff --git a/conntrack.8 b/conntrack.8
index 0e7c410..6525123 100644
--- a/conntrack.8
+++ b/conntrack.8
@@ -1,4 +1,4 @@
-.TH CONNTRACK 8 "Apr 11, 2009" "" ""
+.TH CONNTRACK 8 "Jul 5, 2010" "" ""
.\" Man page written by Harald Welte <laforge@netfilter.org (Jun 2005)
.\" Maintained by Pablo Neira Ayuso <pablo@netfilter.org (May 2007)
@@ -88,8 +88,11 @@ Show the in-kernel connection tracking system statistics.
Atomically zero counters after reading them. This option is only valid in
combination with the "-L, --dump" command options.
.TP
-.BI "-o, --output [extended,xml,timestamp,id] "
-Display output in a certain format.
+.BI "-o, --output [extended,xml,timestamp,id,ktimestamp] "
+Display output in a certain format. With the extended output option, this tool
+displays the layer 3 information. With ktimestamp, it displays the in-kernel
+timestamp available since 2.6.38 (you can enable it via echo 1 >
+/proc/sys/net/netfilter/nf_conntrack_timestamp).
.TP
.BI "-e, --event-mask " "[ALL|NEW|UPDATES|DESTROY][,...]"
Set the bitmask of events that are to be generated by the in-kernel ctnetlink
@@ -97,6 +100,7 @@ event code. Using this parameter, you can reduce the event messages generated
by the kernel to those types to those that you are actually interested in.
.
This option can only be used in conjunction with "-E, --event".
+.TP
.BI "-b, --buffer-size " "value (in bytes)"
Set the Netlink socket buffer size. This option is useful if the command line
tool reports ENOBUFS errors. If you do not pass this option, the default value
@@ -130,8 +134,13 @@ This option is only required in conjunction with "-L, --dump". If this option is
.TP
.BI "-t, --timeout " "TIMEOUT"
Specify the timeout.
-.BI "-m, --mark " "MARK"
-Specify the conntrack mark.
+.TP
+.BI "-m, --mark " "MARK[/MASK]"
+Specify the conntrack mark. Optionally, a mask value can be specified.
+In "--update" mode, this mask specifies the bits that should be zeroed before XORing
+the MARK value into the ctmark.
+Otherwise, the mask is logically ANDed with the existing mark before the comparision.
+In "--create" mode, the mask is ignored.
.TP
.BI "-c, --secmark " "SECMARK"
Specify the conntrack selinux security mark.
@@ -145,6 +154,12 @@ Filter source NAT connections.
.BI "-g, --dst-nat "
Filter destination NAT connections.
.TP
+.BI "-j, --any-nat "
+Filter any NAT connections.
+.TP
+.BI "-w, --zone "
+Filter by conntrack zone. See iptables CT target for more information.
+.TP
.BI "--tuple-src " IP_ADDRESS
Specify the tuple source address of an expectation.
.TP
diff --git a/conntrackd.8 b/conntrackd.8
index 0c9054e..f07ad7a 100644
--- a/conntrackd.8
+++ b/conntrackd.8
@@ -24,10 +24,10 @@ Run conntrackd in daemon mode.
.B conntrackd
can be used in client mode to request several information and operations to a running daemon
.TP
-.BI "-i "
+.BI "-i "[ct|expect]"
Dump the internal cache, i.e. show local states
.TP
-.BI "-e "
+.BI "-e "[ct|expect]"
Dump the external cache, i.e. show foreign states
.TP
.BI "-x "
@@ -37,7 +37,7 @@ with "-i" and "-e" parameters.
.BI "-f " "[|internal|external]"
Flush the internal and/or external cache
.TP
-.BI "-F "
+.BI "-F [ct|expect]"
Flush the kernel conntrack table (if you use a Linux kernel >= 2.6.29, this
option will not flush your internal and external cache).
.TP
@@ -48,15 +48,17 @@ ask conntrackd to send the state-entries that it owns to others.
.BI "-k "
Kill the daemon
.TP
-.BI "-s " "[|network|cache|runtime|link|rsqueue|process|queue]"
+.BI "-s " "[|network|cache|runtime|link|rsqueue|process|queue|ct|expect]"
Dump statistics. If no parameter is passed, it displays the general statistics.
If "network" is passed as parameter it displays the networking statistics.
If "cache" is passed as parameter, it shows the extended cache statistics.
If "runtime" is passed as parameter, it shows the run-time statistics.
If "process" is passed as parameter, it shows existing child processes (if any).
If "queue" is passed as parameter, it shows queue statistics.
+If "ct" is passed, it displays the general statistics.
+If "expect" is passed as parameter, it shows expectation statistics.
.TP
-.BI "-R "
+.BI "-R " "[ct|expect]"
Force a resync against the kernel connection tracking table
.TP
.BI "-t "
diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl
index b897318..4936a76 100644
--- a/doc/manual/conntrack-tools.tmpl
+++ b/doc/manual/conntrack-tools.tmpl
@@ -19,7 +19,7 @@
</authorgroup>
<copyright>
- <year>2008</year>
+ <year>2008-2011</year>
<holder>Pablo Neira Ayuso</holder>
</copyright>
@@ -37,9 +37,8 @@
<releaseinfo>
This document details how to install and configure the
<ulink url="http://conntrack-tools.netfilter.org">conntrack-tools</ulink>
- 0.9.8. This software is under development, for that reason, it is likely
- that this document will evolve in the future to cover new features and
- changes.</releaseinfo>
+ &gt;= 1.0.0. This document will evolve in the future to cover new features
+ and changes.</releaseinfo>
</bookinfo>
@@ -198,7 +197,12 @@ conntrack v0.9.7 (conntrack-tools): 1 flow entries have been shown.
conntrack v0.9.7 (conntrack-tools): 1 flow entries has been updated.
</programlisting>
-<para>Delete one entry, this can be used to block traffic (you have to set <emphasis>/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal</emphasis> to zero).</para>
+<para>Delete one entry, this can be used to block traffic if:</para>
+<itemizedlist>
+ <listitem><para>You have a stateful rule-set that blocks traffic in INVALID state.</para></listitem>
+ <listitem><para>You have set <emphasis>/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_loose</emphasis> or <emphasis>/proc/sys/net/netfilter/nf_conntrack_tcp_loose</emphasis>, depending on your kernel version, to zero.</para></listitem>
+</itemizedlist>
+
<programlisting>
# conntrack -D -p tcp --dport 3486
tcp 6 431982 ESTABLISHED src=192.168.2.100 dst=123.59.27.117 sport=34846 dport=993 packets=169 bytes=14322 src=123.59.27.117 dst=192.168.2.100 sport=993 dport=34846 packets=113 bytes=34787 [ASSURED] mark=1 secmark=0 use=1
@@ -341,6 +345,11 @@ conntrack v0.9.7 (conntrack-tools): 1 flow entries has been deleted.
<sect2 id="sync-pb"><title>Active-Backup setup</title>
+ <note><title>Stateful firewall architectures</title>
+ <para>A good reading to extend the information about firewall architectures is <ulink url="http://1984.lsi.us.es/~pablo/docs/intcomp09.pdf">Demystifying cluster-based fault-tolerant firewalls</ulink> published in IEEE Internet Computing magazine.
+ </para>
+ </note>
+
<para>In the Active-Backup setup, one of the stateful firewall replicas
filters traffic and the other acts as backup. If you use this approach,
you have to copy the script <emphasis>primary-backup.sh</emphasis> to:
@@ -507,6 +516,307 @@ conntrack v0.9.7 (conntrack-tools): 1 flow entries has been deleted.
</sect2>
+<sect2 id="sync-options"><title>Other configuration options</title>
+
+ <para>The daemon allows several configuration options that you may want to
+ enable. This section contains some information about them.</para>
+
+<sect3 id="sync-disable-external"><title>Disabling external cache</title>
+
+ <para>It is possible to disable the external cache. Thus,
+ <emphasis>conntrackd</emphasis> directly injects the flow-states into the
+ in-kernel Connection Tracking System of the backup firewall. You can do it
+ by enabling the <emphasis>DisableExternalCache</emphasis> option in the
+ <emphasis>conntrackd.conf</emphasis> configuration file:
+ </para>
+
+ <programlisting>
+Sync {
+ Mode FTFW {
+ [...]
+ DisableExternalCache Off
+ }
+}
+ </programlisting>
+
+ <para>You can also use this option with the NOTRACK and ALARM modes. This
+ increases CPU consumption in the backup firewall but now you do not need
+ to commit the flow-states during the master failures since they are already
+ in the in-kernel Connection Tracking table. Moreover, you save memory in
+ the backup firewall since you do not need to store the foreign flow-states
+ anymore.
+ </para>
+
+</sect3>
+
+<sect3 id="sync-disable-internal"><title>Disabling internal cache</title>
+
+ <para>You can also disable the internal cache by means of the
+ <emphasis>DisableInternalCache</emphasis> option in the
+ <emphasis>conntrackd.conf</emphasis> configuration file:
+ </para>
+
+ <programlisting>
+Sync {
+ Mode NOTRACK {
+ [...]
+ DisableInternalCache Off
+ }
+}
+ </programlisting>
+
+ <para>However, this option is only available for the NOTRACK mode. This
+ mode provides unreliable flow-state synchronization between firewalls.
+ Thus, if flow-states are lost during the synchronization, the protocol
+ provides no way to recover them.</para>
+
+</sect3>
+
+<sect3 id="sync-transport-protocol">
+<title>Using UDP, TCP or multicast for flow-state synchronization</title>
+
+ <para>You can use up to three different transport layer protocols to
+ synchronize flow-state changes between the firewalls: UDP, TCP and
+ Multicast. UDP and multicast are unreliable but together with the FT-FW
+ mode provide partial reliable flow-state synchronization.
+ </para>
+
+ <para>The preferred choice is FT-FW over UDP, or multicast alternatively.
+ TCP introduces latency in the flow-state synchronization due to the
+ congestion control. Under flow-state message are lost, the FIFO delivery
+ becomes also a problem since the backup firewall quickly gets out of
+ sync. For that reason, its use is discouraged. Note that using TCP only
+ makes sense with the NOTRACK mode.
+ </para>
+
+</sect3>
+
+<sect3 id="sync-redundant-link"><title>Redundant dedicated links</title>
+
+ <para>You can set redundant dedicated links without using bonding, you have
+ to configure as many redundant links as you want in the configuration file.
+ In case of failure of the master dedicated link, conntrackd failovers to one
+ of the backups. An example of this configuration is the following:
+ </para>
+
+ <programlisting>
+Sync {
+ Mode FTFW {
+ [...]
+ }
+ # default master dedicated link
+ UDP Default {
+ IPv4_address 192.168.2.1
+ IPv4_Destination_Address 192.168.2.2
+ Port 3780
+ Interface eth3
+ SndSocketBuffer 24985600
+ RcvSocketBuffer 24985600
+ Checksum on
+ }
+ # backup dedicated link
+ UDP {
+ IPv4_address 192.168.1.3
+ IPv4_Destination_Address 192.168.1.4
+ Port 3780
+ Interface eth2
+ SndSocketBuffer 24985600
+ RcvSocketBuffer 24985600
+ Checksum on
+ }
+ [...]
+}
+ </programlisting>
+
+</sect3>
+
+<sect3 id="sync-iptables-filtering">
+<title>Filtering Connection tracking events with iptables</title>
+
+ <para>Since Linux kernel &gt;= 2.6.34, iptables provides the
+ <emphasis>CT</emphasis> iptables target that allows to reduce the
+ amount of Connection Tracking events that are delivered to user-space.
+ However, you will have to use a Linux kernel &gt;= 2.6.38 to profit
+ from this feature, since several aspects of the event filtering were
+ broken.</para>
+
+ <para>The following example shows how to only generate the
+ <emphasis>assured</emphasis> event:</para>
+
+ <programlisting>
+ # iptables -I PREROUTING -t raw -j CT --ctevents assured
+ </programlisting>
+
+ <note><title>Assured flows</title>
+ <para>One flow is assured if the firewall has seen traffic for it in
+ both directions.</para>
+ </note>
+
+ <para>Reducing the amount of events generated helps to reduce CPU
+ consumption in the active firewall.</para>
+
+</sect3>
+
+<sect3 id="sync-expect"><title>Synchronization of expectations</title>
+
+ <para>The connection tracking system provides helpers that allows you to
+ filter multi-flow application protocols like FTP, H.323 and SIP among many
+ others. These protocols usually split the control and data traffic in
+ different flows. Moreover, the control flow usually announces layer 3 and
+ 4 information to let the other peer know where the data flows will be
+ open. This sort of protocols require that the firewall inspects the
+ content of the packet, otherwise filtering by layer 3 and 4 selectors
+ like addresses and ports become a real nightmare. Netfilter already
+ provides the so-called <emphasis>helpers</emphasis> that track this
+ protocol aspects to allow deploying appropriate filtering. These
+ helpers create <emphasis>expectation</emphasis> entries that
+ represent expected traffic that will arrive to the firewall according
+ to the inspected packets.</para>
+
+ <para>In case that you have enabled tracking of these protocols, you
+ may want to enable the state-synchronization of expectation as well.
+ Thus, established flows for this specific protocols will not suffer
+ any disruption.</para>
+
+ <para>To enable the expectation support in the configuration file, you
+ have to use the following option:</para>
+
+ <programlisting>
+Sync {
+ ...
+ Options {
+ ExpectationSync {
+ ftp
+ sip
+ h323
+ }
+ }
+}</programlisting>
+
+ <para>The example above enables the synchronization of the expectations
+ for the FTP, SIP and H.323 helpers.</para>
+
+ <para>In my testbed, there are two firewalls in a primary-backup
+ configuration running keepalived. They use a couple of floating cluster
+ IP address (192.168.0.100 and 192.168.1.100) that are used by the client.
+ These firewalls protect one FTP server (192.168.1.2) that will be accessed
+ by one client.</para>
+
+ <para>In ASCII art, it looks like this:</para>
+
+ <programlisting>
+ 192.168.0.100 192.168.1.100
+ eth1 eth2
+ fw-1
+ / \ FTP
+ client ------ ------ server
+ 192.168.0.2 \ / 192.168.1.2
+ fw-2
+ </programlisting>
+
+ <para>This is the rule-set for the firewalls:</para>
+
+ <programlisting>
+ -A FORWARD -m state --state RELATED -j ACCEPT
+ -A FORWARD -i eth2 -m state --state ESTABLISHED -j ACCEPT
+ -A FORWARD -i eth1 -p tcp -m tcp --dport 21 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT
+ -A FORWARD -i eth1 -p tcp -m state --state ESTABLISHED -j ACCEPT
+ -A FORWARD -m state --state INVALID -j LOG --log-prefix "invalid: "</programlisting>
+
+ <para>Before going ahead, make sure <emphasis>nf_conntrack_ftp</emphasis> is
+ loaded.</para>
+
+ <para>The following steps detail how to check that the expectation support
+ works fine with FTP traffic:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Switch to the client. Start one FTP control connection to one
+ server that is protected by the firewalls, enter passive mode:</para>
+
+ <programlisting>
+ (term-1) user@client$ nc 192.168.1.2 21
+ 220 dummy FTP server
+ USER anonymous
+ 331 Please specify the password.
+ PASS nothing
+ 230 Login successful.
+ PASV
+ 227 Entering Passive Mode (192,168,1,2,163,11).</programlisting>
+
+ <para>This means that port 163*256+11=41739 will be used for the data
+ traffic. I suggest you to read <ulink url="http://www.freefire.org/articles/ftpexample.php">djb's FTP protocol description</ulink> in case that you
+ don't understand how this calculation is done.</para>
+ </listitem>
+
+ <listitem>
+ <para> Switch to fw-1 (primary) to check that the expectation is in the
+ internal cache.</para>
+
+ <programlisting>
+ root@fw1# conntrackd -i exp
+ proto=6 src=192.168.0.2 dst=192.168.1.2 sport=0 dport=41739 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.0.2 master-dst=192.168.1.2 sport=36390 dport=21 helper=ftp [active since 5s]
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para> Switch to fw-2 (backup) to check that the expectation has been
+ successfully replicated.</para>
+
+ <programlisting>
+ root@fw2# conntrackd -e exp
+ proto=6 src=192.168.0.2 dst=192.168.1.2 sport=0 dport=41739 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.0.2 master-dst=192.168.1.2 sport=36390 dport=21 [active since 8s]
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>Make the primary firewall fw-1 fail. Now fw-2 becomes primary.</para>
+ </listitem>
+
+ <listitem>
+ <para>Switch to fw-2 (primary) to commit the external cache into the
+ kernel. The logs should display that the commit was successful:</para>
+
+ <programlisting>
+ root@fw2# tail -100f /var/log/conntrackd.log
+ [Wed Dec 7 22:16:31 2011] (pid=19195) [notice] committing external cache: expectations
+ [Wed Dec 7 22:16:31 2011] (pid=19195) [notice] Committed 1 new entries
+ [Wed Dec 7 22:16:31 2011] (pid=19195) [notice] commit has taken 0.000366 seconds</programlisting>
+ </listitem>
+
+ <listitem>
+ <para> Switch to the client. Open a new terminal and connect to the port that
+ has been announced by the server:</para>
+
+ <programlisting>
+ (term-2) user@client$ nc -vvv 192.168.1.2 41739
+ (UNKNOWN) [192.168.1.2] 41739 (?) open</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>Switch to term-1 and ask for the file listing:</para>
+
+ <programlisting>
+ [...]
+ 227 Entering Passive Mode (192,168,1,2,163,11).
+ LIST</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>Switch to term-2, it should display the listing. That means
+ everything has worked fine.</para>
+ </listitem>
+
+ </orderedlist>
+
+ <para>You may want to try disabling the expectation support and
+ repeating the steps to check that <emphasis>it does not work</emphasis>
+ without the state-synchronization.</para>
+
+</sect3>
+
+</sect2>
+
<sect2 id="sync-trouble"><title>Troubleshooting</title>
<para>Problems with <emphasis>conntrackd</emphasis>? The following list
@@ -566,6 +876,151 @@ conntrack v0.9.7 (conntrack-tools): 1 flow entries has been deleted.
</answer>
</qandaentry>
+ <qandaentry>
+ <question>
+ <para>
+ Does conntrackd support TCP flow-recovery with window tracking enabled?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Yes, but you require a Linux kernel &gt;= 2.6.36 and the conntrack-tools &gt;= 0.9.15. To enable it, check the TCPWindowTracking clause in the example configuration files.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Does conntrackd support the H.323 and SIP connection tracking helpers?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Yes, conntrackd includes expectation support since version 1.2.0.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Is there any way to set up a more verbose mode in the log message for debugging?
+ </para>
+ </question>
+ <answer>
+ <para>
+ No, but conntrackd provides lots of information that you can look up in
+ runtime via -s option.</para>
+
+ <para>You can check network statistics to find anomalies:</para>
+ <programlisting>
+# conntrackd -s network
+ network statistics:
+ recv:
+ Malformed messages: 0
+ Wrong protocol version: 0
+ Malformed header: 0
+ Malformed payload: 0
+ Bad message type: 0
+ Truncated message: 0
+ Bad message size: 0
+ send:
+ Malformed messages: 0
+
+sequence tracking statistics:
+ recv:
+ Packets lost: 42726
+ Packets before: 0
+
+UDP traffic (active device=eth3):
+ 564232 Bytes sent 1979844 Bytes recv
+ 2844 Pckts sent 8029 Pckts recv
+ 0 Error send 0 Error recv
+ </programlisting>
+
+ <para>You can check cache statistics:</para>
+ <programlisting>
+# conntrackd -s cache
+cache:internal active objects: 0
+ active/total entries: 0/ 0
+ creation OK/failed: 11068/ 0
+ no memory available: 0
+ no space left in cache: 0
+ update OK/failed: 4128/ 0
+ entry not found: 0
+ deletion created/failed: 11068/ 0
+ entry not found: 0
+
+cache:external active objects: 0
+ active/total entries: 0/ 0
+ creation OK/failed: 10521/ 0
+ no memory available: 0
+ no space left in cache: 0
+ update OK/failed: 8832/ 0
+ entry not found: 0
+ deletion created/failed: 10521/ 0
+ entry not found: 0
+ </programlisting>
+
+ <para>You can check runtime miscelaneous statistics:</para>
+ <programlisting>
+# conntrackd -s runtime
+daemon uptime: 14 min
+
+netlink stats:
+ events received: 24736
+ events filtered: 0
+ events unknown type: 0
+ catch event failed: 0
+ dump unknown type: 0
+ netlink overrun: 0
+ flush kernel table: 1
+ resync with kernel table: 0
+ current buffer size (in bytes): 8000000
+
+runtime stats:
+ child process failed: 0
+ child process segfault: 0
+ child process termsig: 0
+ select failed: 0
+ wait failed: 0
+ local read failed: 0
+ local unknown request: 0
+ </programlisting>
+
+ <para>You can check dedicated link statistics:</para>
+ <programlisting>
+# conntrackd -s link
+UDP traffic device=eth3 status=RUNNING role=ACTIVE:
+ 566848 Bytes sent 1982612 Bytes recv
+ 3018 Pckts sent 8203 Pckts recv
+ 0 Error send 0 Error recv
+ </programlisting>
+
+ <para>You can check network queue statistics:</para>
+ <programlisting>
+# conntrackd -s queue
+allocated queue nodes: 1
+
+queue txqueue:
+current elements: 0
+maximum elements: 2147483647
+not enough space errors: 0
+
+queue errorq:
+current elements: 0
+maximum elements: 128
+not enough space errors: 0
+
+queue rsqueue:
+current elements: 1
+maximum elements: 131072
+not enough space errors: 0
+ </programlisting>
+ </answer>
+ </qandaentry>
+
</qandaset>
</sect2>
diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf
index 0941f64..16d7a80 100644
--- a/doc/stats/conntrackd.conf
+++ b/doc/stats/conntrackd.conf
@@ -67,6 +67,18 @@ General {
#
NetlinkBufferSizeMaxGrowth 655355
+ #
+ # By default, the daemon receives state updates following an
+ # event-driven model. You can modify this behaviour by switching to
+ # polling mode with the PollSecs clause. This clause tells conntrackd
+ # to dump the states in the kernel every N seconds. With regards to
+ # synchronization mode, the polling mode can only guarantee that
+ # long-lifetime states are recovered. The main advantage of this method
+ # is the reduction in the state replication at the cost of reducing the
+ # chances of recovering connections.
+ #
+ # PollSecs 15
+
#
# Event filtering: This clause allows you to filter certain traffic,
# There are currently three filter-sets: Protocol, Address and
@@ -81,6 +93,7 @@ General {
#
Protocol Accept {
TCP
+ # UDP
}
#
@@ -118,18 +131,6 @@ Stats {
#
# NetlinkEventsReliable Off
- #
- # By default, the daemon receives state updates following an
- # event-driven model. You can modify this behaviour by switching to
- # polling mode with the PollSecs clause. This clause tells conntrackd
- # to dump the states in the kernel every N seconds. With regards to
- # synchronization mode, the polling mode can only guarantee that
- # long-lifetime states are recovered. The main advantage of this method
- # is the reduction in the state replication at the cost of reducing the
- # chances of recovering connections.
- #
- # PollSecs 15
-
#
# Enable connection logging via Syslog. Default is off.
# Syslog: on, off or a facility name (daemon (default) or local0..7)
diff --git a/doc/sync/alarm/conntrackd.conf b/doc/sync/alarm/conntrackd.conf
index 3424e39..deed291 100644
--- a/doc/sync/alarm/conntrackd.conf
+++ b/doc/sync/alarm/conntrackd.conf
@@ -180,6 +180,34 @@ Sync {
#
# Checksum on
# }
+
+ #
+ # Other unsorted options that are related to the synchronization.
+ #
+ # Options {
+ #
+ # TCP state-entries have window tracking disabled by default,
+ # you can enable it with this option. As said, default is off.
+ # This feature requires a Linux kernel >= 2.6.36.
+ #
+ # TCPWindowTracking Off
+
+ # Set this option on if you want to enable the synchronization
+ # of expectations. You have to specify the list of helpers that
+ # you want to enable. Default is off.
+ #
+ # ExpectationSync {
+ # ftp
+ # h323
+ # sip
+ # }
+ #
+ # You can use this alternatively:
+ #
+ # ExpectationSync On
+ #
+ # If you want to synchronize expectations of all helpers.
+ # }
}
#
@@ -332,7 +360,9 @@ General {
TCP
SCTP
DCCP
+ # UDP
# ICMP # This requires a Linux kernel >= 2.6.31
+ # IPv6-ICMP # This requires a Linux kernel >= 2.6.31
}
#
diff --git a/doc/sync/ftfw/conntrackd.conf b/doc/sync/ftfw/conntrackd.conf
index 877ed68..0304f0f 100644
--- a/doc/sync/ftfw/conntrackd.conf
+++ b/doc/sync/ftfw/conntrackd.conf
@@ -204,6 +204,33 @@ Sync {
# Checksum on
# }
+ #
+ # Other unsorted options that are related to the synchronization.
+ #
+ # Options {
+ #
+ # TCP state-entries have window tracking disabled by default,
+ # you can enable it with this option. As said, default is off.
+ # This feature requires a Linux kernel >= 2.6.36.
+ #
+ # TCPWindowTracking Off
+
+ # Set this option on if you want to enable the synchronization
+ # of expectations. You have to specify the list of helpers that
+ # you want to enable. Default is off.
+ #
+ # ExpectationSync {
+ # ftp
+ # h323
+ # sip
+ # }
+ #
+ # You can use this alternatively:
+ #
+ # ExpectationSync On
+ #
+ # If you want to synchronize expectations of all helpers.
+ # }
}
#
@@ -359,6 +386,7 @@ General {
DCCP
# UDP
# ICMP # This requires a Linux kernel >= 2.6.31
+ # IPv6-ICMP # This requires a Linux kernel >= 2.6.31
}
#
diff --git a/doc/sync/notrack/conntrackd.conf b/doc/sync/notrack/conntrackd.conf
index f8bccc4..34e7b32 100644
--- a/doc/sync/notrack/conntrackd.conf
+++ b/doc/sync/notrack/conntrackd.conf
@@ -242,6 +242,34 @@ Sync {
#
# Checksum on
# }
+
+ #
+ # Other unsorted options that are related to the synchronization.
+ #
+ # Options {
+ #
+ # TCP state-entries have window tracking disabled by default,
+ # you can enable it with this option. As said, default is off.
+ # This feature requires a Linux kernel >= 2.6.36.
+ #
+ # TCPWindowTracking Off
+
+ # Set this option on if you want to enable the synchronization
+ # of expectations. You have to specify the list of helpers that
+ # you want to enable. Default is off.
+ #
+ # ExpectationSync {
+ # ftp
+ # h323
+ # sip
+ # }
+ #
+ # You can use this alternatively:
+ #
+ # ExpectationSync On
+ #
+ # If you want to synchronize expectations of all helpers.
+ # }
}
#
@@ -394,7 +422,9 @@ General {
TCP
SCTP
DCCP
+ # UDP
# ICMP # This requires a Linux kernel >= 2.6.31
+ # IPv6-ICMP # This requires a Linux kernel >= 2.6.31
}
#
diff --git a/doc/sync/primary-backup.sh b/doc/sync/primary-backup.sh
index 34c1cfa..fb74adc 100755
--- a/doc/sync/primary-backup.sh
+++ b/doc/sync/primary-backup.sh
@@ -1,9 +1,11 @@
#!/bin/sh
-#
-# (C) 2008 by Pablo Neira Ayuso <pablo@netfilter.org>
#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
+# (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
#
# Description:
#
diff --git a/extensions/Makefile.in b/extensions/Makefile.in
index ea3b62f..5f01bcf 100644
--- a/extensions/Makefile.in
+++ b/extensions/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -34,7 +34,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/Make_global.am
subdir = extensions
@@ -42,7 +41,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -52,6 +51,9 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
libct_proto_dccp_la_LIBADD =
am_libct_proto_dccp_la_OBJECTS = libct_proto_dccp.lo
libct_proto_dccp_la_OBJECTS = $(am_libct_proto_dccp_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
libct_proto_gre_la_LIBADD =
am_libct_proto_gre_la_OBJECTS = libct_proto_gre.lo
libct_proto_gre_la_OBJECTS = $(am_libct_proto_gre_la_OBJECTS)
@@ -77,18 +79,31 @@ libct_proto_unknown_la_LIBADD =
am_libct_proto_unknown_la_OBJECTS = libct_proto_unknown.lo
libct_proto_unknown_la_OBJECTS = $(am_libct_proto_unknown_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/depcomp
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libct_proto_dccp_la_SOURCES) $(libct_proto_gre_la_SOURCES) \
$(libct_proto_icmp_la_SOURCES) \
$(libct_proto_icmpv6_la_SOURCES) \
@@ -108,6 +123,7 @@ CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -130,7 +146,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
-HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -168,14 +183,14 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
-XLEX = @XLEX@
-XYACC = @XYACC@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
@@ -226,18 +241,15 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CFLAGS = -std=gnu99 -W -Wall \
-Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \
- -Wno-unused-parameter
+ -Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} \
+ ${LIBNETFILTER_CONNTRACK_CFLAGS}
noinst_LTLIBRARIES = libct_proto_tcp.la libct_proto_udp.la \
libct_proto_icmp.la libct_proto_icmpv6.la \
@@ -267,9 +279,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/Make_global.am $(am_
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu extensions/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu extensions/Makefile
+ $(AUTOMAKE) --foreign extensions/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -298,23 +310,23 @@ clean-noinstLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libct_proto_dccp.la: $(libct_proto_dccp_la_OBJECTS) $(libct_proto_dccp_la_DEPENDENCIES)
- $(LINK) $(libct_proto_dccp_la_OBJECTS) $(libct_proto_dccp_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_dccp_la_OBJECTS) $(libct_proto_dccp_la_LIBADD) $(LIBS)
libct_proto_gre.la: $(libct_proto_gre_la_OBJECTS) $(libct_proto_gre_la_DEPENDENCIES)
- $(LINK) $(libct_proto_gre_la_OBJECTS) $(libct_proto_gre_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_gre_la_OBJECTS) $(libct_proto_gre_la_LIBADD) $(LIBS)
libct_proto_icmp.la: $(libct_proto_icmp_la_OBJECTS) $(libct_proto_icmp_la_DEPENDENCIES)
- $(LINK) $(libct_proto_icmp_la_OBJECTS) $(libct_proto_icmp_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_icmp_la_OBJECTS) $(libct_proto_icmp_la_LIBADD) $(LIBS)
libct_proto_icmpv6.la: $(libct_proto_icmpv6_la_OBJECTS) $(libct_proto_icmpv6_la_DEPENDENCIES)
- $(LINK) $(libct_proto_icmpv6_la_OBJECTS) $(libct_proto_icmpv6_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_icmpv6_la_OBJECTS) $(libct_proto_icmpv6_la_LIBADD) $(LIBS)
libct_proto_sctp.la: $(libct_proto_sctp_la_OBJECTS) $(libct_proto_sctp_la_DEPENDENCIES)
- $(LINK) $(libct_proto_sctp_la_OBJECTS) $(libct_proto_sctp_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_sctp_la_OBJECTS) $(libct_proto_sctp_la_LIBADD) $(LIBS)
libct_proto_tcp.la: $(libct_proto_tcp_la_OBJECTS) $(libct_proto_tcp_la_DEPENDENCIES)
- $(LINK) $(libct_proto_tcp_la_OBJECTS) $(libct_proto_tcp_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_tcp_la_OBJECTS) $(libct_proto_tcp_la_LIBADD) $(LIBS)
libct_proto_udp.la: $(libct_proto_udp_la_OBJECTS) $(libct_proto_udp_la_DEPENDENCIES)
- $(LINK) $(libct_proto_udp_la_OBJECTS) $(libct_proto_udp_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_udp_la_OBJECTS) $(libct_proto_udp_la_LIBADD) $(LIBS)
libct_proto_udplite.la: $(libct_proto_udplite_la_OBJECTS) $(libct_proto_udplite_la_DEPENDENCIES)
- $(LINK) $(libct_proto_udplite_la_OBJECTS) $(libct_proto_udplite_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_udplite_la_OBJECTS) $(libct_proto_udplite_la_LIBADD) $(LIBS)
libct_proto_unknown.la: $(libct_proto_unknown_la_OBJECTS) $(libct_proto_unknown_la_DEPENDENCIES)
- $(LINK) $(libct_proto_unknown_la_OBJECTS) $(libct_proto_unknown_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libct_proto_unknown_la_OBJECTS) $(libct_proto_unknown_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -333,22 +345,28 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libct_proto_unknown.Plo@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c
index cb573d0..0b43bf5 100644
--- a/extensions/libct_proto_tcp.c
+++ b/extensions/libct_proto_tcp.c
@@ -82,7 +82,8 @@ static const char *tcp_states[TCP_CONNTRACK_MAX] = {
[TCP_CONNTRACK_LAST_ACK] = "LAST_ACK",
[TCP_CONNTRACK_TIME_WAIT] = "TIME_WAIT",
[TCP_CONNTRACK_CLOSE] = "CLOSE",
- [TCP_CONNTRACK_LISTEN] = "LISTEN"
+ /* Since Linux kernel 2.6.31, LISTEN is SYN_SENT2. */
+ [TCP_CONNTRACK_SYN_SENT2] = "SYN_SENT2"
};
static void help(void)
@@ -151,7 +152,11 @@ static int parse_options(char c,
break;
}
}
- if (i == TCP_CONNTRACK_MAX)
+ /* For backward compatibility with Linux kernel < 2.6.31. */
+ if (strcmp(optarg, "LISTEN") == 0) {
+ nfct_set_attr_u8(ct, ATTR_TCP_STATE,
+ TCP_CONNTRACK_LISTEN);
+ } else if (i == TCP_CONNTRACK_MAX)
exit_error(PARAMETER_PROBLEM,
"unknown TCP state `%s'", optarg);
*flags |= CT_TCP_STATE;
diff --git a/include/Makefile.in b/include/Makefile.in
index 5a38ca1..edf1d83 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -34,7 +34,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
subdir = include
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
@@ -42,12 +41,18 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
SOURCES =
DIST_SOURCES =
HEADERS = $(noinst_HEADERS)
@@ -56,6 +61,7 @@ CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -78,7 +84,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
-HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -116,14 +121,14 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
-XLEX = @XLEX@
-XYACC = @XYACC@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
@@ -174,11 +179,7 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@@ -201,9 +202,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu include/Makefile
+ $(AUTOMAKE) --foreign include/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/include/cache.h b/include/cache.h
index 28917f2..3af2741 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -21,13 +21,14 @@ enum {
C_OBJ_NONE = 0, /* not in the cache */
C_OBJ_NEW, /* just added to the cache */
C_OBJ_ALIVE, /* in the cache, alive */
- C_OBJ_DEAD /* still in the cache, but dead */
+ C_OBJ_DEAD, /* still in the cache, but dead */
+ C_OBJ_MAX
};
struct cache;
struct cache_object {
struct hashtable_node hashnode;
- struct nf_conntrack *ct;
+ void *ptr;
struct cache *cache;
int status;
int refcnt;
@@ -48,14 +49,23 @@ extern struct cache_feature timer_feature;
#define CACHE_MAX_NAMELEN 32
+enum cache_type {
+ CACHE_T_NONE = 0,
+ CACHE_T_CT,
+ CACHE_T_EXP,
+ CACHE_T_MAX
+};
+
struct cache {
char name[CACHE_MAX_NAMELEN];
+ enum cache_type type;
struct hashtable *h;
unsigned int num_features;
struct cache_feature **features;
unsigned int feature_type[CACHE_MAX_FEATURE];
unsigned int *feature_offset;
+ struct cache_ops *ops;
struct cache_extra *extra;
unsigned int extra_offset;
size_t object_size;
@@ -94,34 +104,73 @@ struct cache_extra {
void (*destroy)(struct cache_object *obj, void *data);
};
+struct nfct_handle;
+
+/* cache options depends on the object type: conntrack or expectation. */
+struct cache_ops {
+ /* hashing and comparison of objects. */
+ uint32_t (*hash)(const void *data, const struct hashtable *table);
+ int (*cmp)(const void *data1, const void *data2);
+
+ /* object allocation, copy and release. */
+ void *(*alloc)(void);
+ void (*copy)(void *dst, void *src, unsigned int flags);
+ void (*free)(void *ptr);
+
+ /* dump and commit. */
+ int (*dump_step)(void *data1, void *n);
+ int (*commit)(struct cache *c, struct nfct_handle *h, int clientfd);
+
+ /* build network message from object. */
+ struct nethdr *(*build_msg)(const struct cache_object *obj, int type);
+};
+
+/* templates to configure conntrack caching. */
+extern struct cache_ops cache_sync_internal_ct_ops;
+extern struct cache_ops cache_sync_external_ct_ops;
+extern struct cache_ops cache_stats_ct_ops;
+/* templates to configure expectation caching. */
+extern struct cache_ops cache_sync_internal_exp_ops;
+extern struct cache_ops cache_sync_external_exp_ops;
+
struct nf_conntrack;
-struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra);
+struct cache *cache_create(const char *name, enum cache_type type, unsigned int features, struct cache_extra *extra, struct cache_ops *ops);
void cache_destroy(struct cache *e);
-struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct);
+struct cache_object *cache_object_new(struct cache *c, void *ptr);
void cache_object_free(struct cache_object *obj);
void cache_object_get(struct cache_object *obj);
int cache_object_put(struct cache_object *obj);
void cache_object_set_status(struct cache_object *obj, int status);
int cache_add(struct cache *c, struct cache_object *obj, int id);
-void cache_update(struct cache *c, struct cache_object *obj, int id, struct nf_conntrack *ct);
-struct cache_object *cache_update_force(struct cache *c, struct nf_conntrack *ct);
+void cache_update(struct cache *c, struct cache_object *obj, int id, void *ptr);
+struct cache_object *cache_update_force(struct cache *c, void *ptr);
void cache_del(struct cache *c, struct cache_object *obj);
-struct cache_object *cache_find(struct cache *c, struct nf_conntrack *ct, int *pos);
+struct cache_object *cache_find(struct cache *c, void *ptr, int *pos);
void cache_stats(const struct cache *c, int fd);
void cache_stats_extended(const struct cache *c, int fd);
-struct cache_object *cache_data_get_object(struct cache *c, void *data);
-void *cache_get_extra(struct cache *, void *);
+void *cache_get_extra(struct cache_object *);
void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2));
void cache_iterate_limit(struct cache *c, void *data, uint32_t from, uint32_t steps, int (*iterate)(void *data1, void *data2));
/* iterators */
struct nfct_handle;
+struct __dump_container {
+ int fd;
+ int type;
+};
+
void cache_dump(struct cache *c, int fd, int type);
-void cache_commit(struct cache *c, struct nfct_handle *h, int clientfd);
+
+struct __commit_container {
+ struct nfct_handle *h;
+ struct cache *c;
+};
+
+int cache_commit(struct cache *c, struct nfct_handle *h, int clientfd);
void cache_flush(struct cache *c);
void cache_bulk(struct cache *c);
diff --git a/include/conntrack.h b/include/conntrack.h
index 61e7581..3882de7 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -9,149 +9,8 @@
#include <netinet/in.h>
-enum action {
- CT_NONE = 0,
-
- CT_LIST_BIT = 0,
- CT_LIST = (1 << CT_LIST_BIT),
-
- CT_CREATE_BIT = 1,
- CT_CREATE = (1 << CT_CREATE_BIT),
-
- CT_UPDATE_BIT = 2,
- CT_UPDATE = (1 << CT_UPDATE_BIT),
-
- CT_DELETE_BIT = 3,
- CT_DELETE = (1 << CT_DELETE_BIT),
-
- CT_GET_BIT = 4,
- CT_GET = (1 << CT_GET_BIT),
-
- CT_FLUSH_BIT = 5,
- CT_FLUSH = (1 << CT_FLUSH_BIT),
-
- CT_EVENT_BIT = 6,
- CT_EVENT = (1 << CT_EVENT_BIT),
-
- CT_VERSION_BIT = 7,
- CT_VERSION = (1 << CT_VERSION_BIT),
-
- CT_HELP_BIT = 8,
- CT_HELP = (1 << CT_HELP_BIT),
-
- EXP_LIST_BIT = 9,
- EXP_LIST = (1 << EXP_LIST_BIT),
-
- EXP_CREATE_BIT = 10,
- EXP_CREATE = (1 << EXP_CREATE_BIT),
-
- EXP_DELETE_BIT = 11,
- EXP_DELETE = (1 << EXP_DELETE_BIT),
-
- EXP_GET_BIT = 12,
- EXP_GET = (1 << EXP_GET_BIT),
-
- EXP_FLUSH_BIT = 13,
- EXP_FLUSH = (1 << EXP_FLUSH_BIT),
-
- EXP_EVENT_BIT = 14,
- EXP_EVENT = (1 << EXP_EVENT_BIT),
-
- CT_COUNT_BIT = 15,
- CT_COUNT = (1 << CT_COUNT_BIT),
-
- EXP_COUNT_BIT = 16,
- EXP_COUNT = (1 << EXP_COUNT_BIT),
-
- X_STATS_BIT = 17,
- X_STATS = (1 << X_STATS_BIT),
-};
#define NUMBER_OF_CMD 18
-
-enum options {
- CT_OPT_ORIG_SRC_BIT = 0,
- CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT),
-
- CT_OPT_ORIG_DST_BIT = 1,
- CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT),
-
- CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST),
-
- CT_OPT_REPL_SRC_BIT = 2,
- CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT),
-
- CT_OPT_REPL_DST_BIT = 3,
- CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT),
-
- CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST),
-
- CT_OPT_PROTO_BIT = 4,
- CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT),
-
- CT_OPT_TUPLE_ORIG = (CT_OPT_ORIG | CT_OPT_PROTO),
- CT_OPT_TUPLE_REPL = (CT_OPT_REPL | CT_OPT_PROTO),
-
- CT_OPT_TIMEOUT_BIT = 5,
- CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT),
-
- CT_OPT_STATUS_BIT = 6,
- CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT),
-
- CT_OPT_ZERO_BIT = 7,
- CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT),
-
- CT_OPT_EVENT_MASK_BIT = 8,
- CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT),
-
- CT_OPT_EXP_SRC_BIT = 9,
- CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT),
-
- CT_OPT_EXP_DST_BIT = 10,
- CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT),
-
- CT_OPT_MASK_SRC_BIT = 11,
- CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT),
-
- CT_OPT_MASK_DST_BIT = 12,
- CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT),
-
- CT_OPT_NATRANGE_BIT = 13,
- CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT),
-
- CT_OPT_MARK_BIT = 14,
- CT_OPT_MARK = (1 << CT_OPT_MARK_BIT),
-
- CT_OPT_ID_BIT = 15,
- CT_OPT_ID = (1 << CT_OPT_ID_BIT),
-
- CT_OPT_FAMILY_BIT = 16,
- CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT),
-
- CT_OPT_SRC_NAT_BIT = 17,
- CT_OPT_SRC_NAT = (1 << CT_OPT_SRC_NAT_BIT),
-
- CT_OPT_DST_NAT_BIT = 18,
- CT_OPT_DST_NAT = (1 << CT_OPT_DST_NAT_BIT),
-
- CT_OPT_OUTPUT_BIT = 19,
- CT_OPT_OUTPUT = (1 << CT_OPT_OUTPUT_BIT),
-
- CT_OPT_SECMARK_BIT = 20,
- CT_OPT_SECMARK = (1 << CT_OPT_SECMARK_BIT),
-
- CT_OPT_BUFFERSIZE_BIT = 21,
- CT_OPT_BUFFERSIZE = (1 << CT_OPT_BUFFERSIZE_BIT),
-
- CT_OPT_MAX = CT_OPT_BUFFERSIZE_BIT
-};
-#define NUMBER_OF_OPT CT_OPT_MAX+1
-
-enum {
- _O_XML = (1 << 0),
- _O_EXT = (1 << 1),
- _O_TMS = (1 << 2),
- _O_ID = (1 << 3),
-};
+#define NUMBER_OF_OPT 24
struct ctproto_handler {
struct list_head head;
diff --git a/include/conntrackd.h b/include/conntrackd.h
index c7f33f0..8baa088 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -14,29 +14,39 @@
#include <syslog.h>
/* UNIX facilities */
-#define FLUSH_MASTER 0 /* flush kernel conntrack table */
-#define RESYNC_MASTER 1 /* resync with kernel conntrack table */
-#define DUMP_INTERNAL 16 /* dump internal cache */
-#define DUMP_EXTERNAL 17 /* dump external cache */
-#define COMMIT 18 /* commit external cache */
-#define FLUSH_CACHE 19 /* flush cache */
-#define KILL 20 /* kill conntrackd */
-#define STATS 21 /* dump statistics */
-#define SEND_BULK 22 /* send a bulk */
-#define REQUEST_DUMP 23 /* request dump */
-#define DUMP_INT_XML 24 /* dump internal cache in XML */
-#define DUMP_EXT_XML 25 /* dump external cache in XML */
-#define RESET_TIMERS 26 /* reset kernel timers */
-#define DEBUG_INFO 27 /* unused */
-#define STATS_NETWORK 28 /* extended network stats */
-#define STATS_CACHE 29 /* extended cache stats */
-#define STATS_RUNTIME 30 /* extended runtime stats */
-#define STATS_LINK 31 /* dedicated link stats */
-#define STATS_RSQUEUE 32 /* resend queue stats */
-#define FLUSH_INT_CACHE 33 /* flush internal cache */
-#define FLUSH_EXT_CACHE 34 /* flush external cache */
-#define STATS_PROCESS 35 /* child process stats */
-#define STATS_QUEUE 36 /* queue stats */
+#define CT_FLUSH_MASTER 0 /* flush kernel conntrack table */
+#define CT_RESYNC_MASTER 1 /* resync with kernel ct table */
+#define CT_DUMP_INTERNAL 16 /* dump internal cache */
+#define CT_DUMP_EXTERNAL 17 /* dump external cache */
+#define CT_COMMIT 18 /* commit external cache */
+#define CT_FLUSH_CACHE 19 /* flush cache */
+#define KILL 20 /* kill conntrackd */
+#define STATS 21 /* dump statistics */
+#define SEND_BULK 22 /* send a bulk */
+#define REQUEST_DUMP 23 /* request dump */
+#define CT_DUMP_INT_XML 24 /* dump internal cache in XML */
+#define CT_DUMP_EXT_XML 25 /* dump external cache in XML */
+#define RESET_TIMERS 26 /* reset kernel timers */
+#define DEBUG_INFO 27 /* unused */
+#define STATS_NETWORK 28 /* extended network stats */
+#define STATS_CACHE 29 /* extended cache stats */
+#define STATS_RUNTIME 30 /* extended runtime stats */
+#define STATS_LINK 31 /* dedicated link stats */
+#define STATS_RSQUEUE 32 /* resend queue stats */
+#define CT_FLUSH_INT_CACHE 33 /* flush internal cache */
+#define CT_FLUSH_EXT_CACHE 34 /* flush external cache */
+#define STATS_PROCESS 35 /* child process stats */
+#define STATS_QUEUE 36 /* queue stats */
+#define EXP_STATS 37 /* dump statistics */
+#define EXP_FLUSH_MASTER 38 /* flush kernel expect table */
+#define EXP_RESYNC_MASTER 39 /* resync with kernel exp table */
+#define EXP_DUMP_INTERNAL 40 /* dump internal expect cache */
+#define EXP_DUMP_EXTERNAL 41 /* dump external expect cache */
+#define EXP_COMMIT 42 /* commit expectations */
+#define ALL_FLUSH_MASTER 43 /* flush all kernel tables */
+#define ALL_RESYNC_MASTER 44 /* resync w/all kernel tables */
+#define ALL_FLUSH_CACHE 45 /* flush all caches */
+#define ALL_COMMIT 46 /* commit all tables */
#define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf"
#define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock"
@@ -56,6 +66,7 @@
#define CTD_SYNC_ALARM (1UL << 3)
#define CTD_SYNC_NOTRACK (1UL << 4)
#define CTD_POLL (1UL << 5)
+#define CTD_EXPECT (1UL << 6)
/* FILENAME_MAX is 4096 on my system, perhaps too much? */
#ifndef FILENAME_MAXLEN
@@ -102,8 +113,11 @@ struct ct_conf {
struct {
int internal_cache_disable;
int external_cache_disable;
+ int tcp_window_tracking;
} sync;
struct {
+ int subsys_id;
+ int groups;
int events_reliable;
} netlink;
struct {
@@ -129,6 +143,7 @@ struct ct_general_state {
struct local_server local;
struct ct_mode *mode;
struct ct_filter *us_filter;
+ struct exp_filter *exp_filter;
struct nfct_handle *event; /* event handler */
struct nfct_filter *filter; /* event filter */
@@ -176,6 +191,10 @@ struct ct_general_state {
} stats;
};
+struct commit_runqueue {
+ int (*cb)(struct nfct_handle *h, int step);
+};
+
#define STATE_SYNC(x) state.sync->x
struct ct_sync_state {
@@ -195,6 +214,7 @@ struct ct_sync_state {
struct nfct_handle *h;
struct evfd *evfd;
int current;
+ struct commit_runqueue rq[2];
struct {
int ok;
int fail;
diff --git a/include/external.h b/include/external.h
index 938941a..70f0c5c 100644
--- a/include/external.h
+++ b/include/external.h
@@ -7,15 +7,28 @@ struct external_handler {
int (*init)(void);
void (*close)(void);
- void (*new)(struct nf_conntrack *ct);
- void (*update)(struct nf_conntrack *ct);
- void (*destroy)(struct nf_conntrack *ct);
+ struct {
+ void (*new)(struct nf_conntrack *ct);
+ void (*upd)(struct nf_conntrack *ct);
+ void (*del)(struct nf_conntrack *ct);
- void (*dump)(int fd, int type);
- void (*flush)(void);
- void (*commit)(struct nfct_handle *h, int fd);
- void (*stats)(int fd);
- void (*stats_ext)(int fd);
+ void (*dump)(int fd, int type);
+ void (*flush)(void);
+ int (*commit)(struct nfct_handle *h, int fd);
+ void (*stats)(int fd);
+ void (*stats_ext)(int fd);
+ } ct;
+ struct {
+ void (*new)(struct nf_expect *exp);
+ void (*upd)(struct nf_expect *exp);
+ void (*del)(struct nf_expect *exp);
+
+ void (*dump)(int fd, int type);
+ void (*flush)(void);
+ int (*commit)(struct nfct_handle *h, int fd);
+ void (*stats)(int fd);
+ void (*stats_ext)(int fd);
+ } exp;
};
extern struct external_handler external_cache;
diff --git a/include/filter.h b/include/filter.h
index 72c2aa4..3c7c8cc 100644
--- a/include/filter.h
+++ b/include/filter.h
@@ -50,6 +50,13 @@ void ct_filter_add_state(struct ct_filter *f, int protonum, int state);
void ct_filter_set_logic(struct ct_filter *f,
enum ct_filter_type type,
enum ct_filter_logic logic);
-int ct_filter_conntrack(struct nf_conntrack *ct, int userspace);
+int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace);
+
+struct exp_filter;
+struct nf_expect;
+
+struct exp_filter *exp_filter_create(void);
+int exp_filter_add(struct exp_filter *f, const char *helper_name);
+int exp_filter_find(struct exp_filter *f, const struct nf_expect *exp);
#endif
diff --git a/include/internal.h b/include/internal.h
index 1f11340..2ba9714 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -12,25 +12,45 @@ enum {
};
struct internal_handler {
- void *data;
unsigned int flags;
int (*init)(void);
void (*close)(void);
- void (*new)(struct nf_conntrack *ct, int origin_type);
- void (*update)(struct nf_conntrack *ct, int origin_type);
- int (*destroy)(struct nf_conntrack *ct, int origin_type);
-
- void (*dump)(int fd, int type);
- void (*populate)(struct nf_conntrack *ct);
- void (*purge)(void);
- int (*resync)(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct, void *data);
- void (*flush)(void);
-
- void (*stats)(int fd);
- void (*stats_ext)(int fd);
+ struct {
+ void *data;
+
+ void (*new)(struct nf_conntrack *ct, int origin_type);
+ void (*upd)(struct nf_conntrack *ct, int origin_type);
+ int (*del)(struct nf_conntrack *ct, int origin_type);
+
+ void (*dump)(int fd, int type);
+ void (*populate)(struct nf_conntrack *ct);
+ void (*purge)(void);
+ int (*resync)(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct, void *data);
+ void (*flush)(void);
+
+ void (*stats)(int fd);
+ void (*stats_ext)(int fd);
+ } ct;
+ struct {
+ void *data;
+
+ void (*new)(struct nf_expect *exp, int origin_type);
+ void (*upd)(struct nf_expect *exp, int origin_type);
+ int (*del)(struct nf_expect *exp, int origin_type);
+
+ void (*dump)(int fd, int type);
+ void (*populate)(struct nf_expect *exp);
+ void (*purge)(void);
+ int (*resync)(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data);
+ void (*flush)(void);
+
+ void (*stats)(int fd);
+ void (*stats_ext)(int fd);
+ } exp;
};
extern struct internal_handler internal_cache;
diff --git a/include/log.h b/include/log.h
index f5c5b4f..ae58e79 100644
--- a/include/log.h
+++ b/include/log.h
@@ -4,10 +4,12 @@
#include <stdio.h>
struct nf_conntrack;
+struct nf_expect;
int init_log(void);
void dlog(int priority, const char *format, ...);
void dlog_ct(FILE *fd, struct nf_conntrack *ct, unsigned int type);
+void dlog_exp(FILE *fd, struct nf_expect *exp, unsigned int type);
void close_log(void);
#endif
diff --git a/include/netlink.h b/include/netlink.h
index 0df0cbb..3bde30c 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -30,4 +30,11 @@ static inline int ct_is_related(const struct nf_conntrack *ct)
nfct_attr_is_set(ct, ATTR_MASTER_PORT_DST));
}
+int nl_create_expect(struct nfct_handle *h, const struct nf_expect *orig, int timeout);
+int nl_destroy_expect(struct nfct_handle *h, const struct nf_expect *exp);
+int nl_get_expect(struct nfct_handle *h, const struct nf_expect *exp);
+int nl_dump_expect_table(struct nfct_handle *h);
+int nl_flush_expect_table(struct nfct_handle *h);
+int nl_send_expect_resync(struct nfct_handle *h);
+
#endif
diff --git a/include/network.h b/include/network.h
index 70812b1..ab95499 100644
--- a/include/network.h
+++ b/include/network.h
@@ -4,9 +4,10 @@
#include <stdint.h>
#include <sys/types.h>
-#define CONNTRACKD_PROTOCOL_VERSION 0
+#define CONNTRACKD_PROTOCOL_VERSION 1
struct nf_conntrack;
+struct nf_expect;
struct nethdr {
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -25,10 +26,13 @@ struct nethdr {
#define NETHDR_SIZ nethdr_align(sizeof(struct nethdr))
enum nethdr_type {
- NET_T_STATE_NEW = 0,
- NET_T_STATE_UPD,
- NET_T_STATE_DEL,
- NET_T_STATE_MAX = NET_T_STATE_DEL,
+ NET_T_STATE_CT_NEW = 0,
+ NET_T_STATE_CT_UPD,
+ NET_T_STATE_CT_DEL,
+ NET_T_STATE_EXP_NEW = 3,
+ NET_T_STATE_EXP_UPD,
+ NET_T_STATE_EXP_DEL,
+ NET_T_STATE_MAX = NET_T_STATE_EXP_DEL,
NET_T_CTL = 10,
};
@@ -37,7 +41,9 @@ int nethdr_size(int len);
void nethdr_set(struct nethdr *net, int type);
void nethdr_set_ack(struct nethdr *net);
void nethdr_set_ctl(struct nethdr *net);
-int object_status_to_network_type(int status);
+
+struct cache_object;
+int object_status_to_network_type(struct cache_object *obj);
#define NETHDR_DATA(x) \
(struct netattr *)(((char *)x) + NETHDR_SIZ)
@@ -79,13 +85,24 @@ enum {
MSG_BAD,
};
-#define BUILD_NETMSG(ct, query) \
+#define BUILD_NETMSG_FROM_CT(ct, query) \
({ \
static char __net[4096]; \
struct nethdr *__hdr = (struct nethdr *) __net; \
memset(__hdr, 0, NETHDR_SIZ); \
nethdr_set(__hdr, query); \
- build_payload(ct, __hdr); \
+ ct2msg(ct, __hdr); \
+ HDR_HOST2NETWORK(__hdr); \
+ __hdr; \
+})
+
+#define BUILD_NETMSG_FROM_EXP(exp, query) \
+({ \
+ static char __net[4096]; \
+ struct nethdr *__hdr = (struct nethdr *) __net; \
+ memset(__hdr, 0, NETHDR_SIZ); \
+ nethdr_set(__hdr, query); \
+ exp2msg(exp, __hdr); \
HDR_HOST2NETWORK(__hdr); \
__hdr; \
})
@@ -220,6 +237,8 @@ enum nta_attr {
NTA_ICMP_TYPE, /* uint8_t */
NTA_ICMP_CODE, /* uint8_t */
NTA_ICMP_ID, /* uint16_t */
+ NTA_TCP_WSCALE_ORIG, /* uint8_t */
+ NTA_TCP_WSCALE_REPL, /* uint8_t */
NTA_MAX
};
@@ -232,8 +251,28 @@ struct nta_attr_natseqadj {
uint32_t repl_seq_offset_after;
};
-void build_payload(const struct nf_conntrack *ct, struct nethdr *n);
+void ct2msg(const struct nf_conntrack *ct, struct nethdr *n);
+int msg2ct(struct nf_conntrack *ct, struct nethdr *n, size_t remain);
+
+enum nta_exp_attr {
+ NTA_EXP_MASTER_IPV4 = 0, /* struct nfct_attr_grp_ipv4 */
+ NTA_EXP_MASTER_IPV6, /* struct nfct_attr_grp_ipv6 */
+ NTA_EXP_MASTER_L4PROTO, /* uint8_t */
+ NTA_EXP_MASTER_PORT, /* struct nfct_attr_grp_port */
+ NTA_EXP_EXPECT_IPV4 = 4, /* struct nfct_attr_grp_ipv4 */
+ NTA_EXP_EXPECT_IPV6, /* struct nfct_attr_grp_ipv6 */
+ NTA_EXP_EXPECT_L4PROTO, /* uint8_t */
+ NTA_EXP_EXPECT_PORT, /* struct nfct_attr_grp_port */
+ NTA_EXP_MASK_IPV4 = 8, /* struct nfct_attr_grp_ipv4 */
+ NTA_EXP_MASK_IPV6, /* struct nfct_attr_grp_ipv6 */
+ NTA_EXP_MASK_L4PROTO, /* uint8_t */
+ NTA_EXP_MASK_PORT, /* struct nfct_attr_grp_port */
+ NTA_EXP_TIMEOUT, /* uint32_t */
+ NTA_EXP_FLAGS, /* uint32_t */
+ NTA_EXP_MAX
+};
-int parse_payload(struct nf_conntrack *ct, struct nethdr *n, size_t remain);
+void exp2msg(const struct nf_expect *exp, struct nethdr *n);
+int msg2exp(struct nf_expect *exp, struct nethdr *n, size_t remain);
#endif
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
index b8e154f..f3c5309 100644
--- a/m4/ltversion.m4
+++ b/m4/ltversion.m4
@@ -9,15 +9,15 @@
# Generated from ltversion.in.
-# serial 3012 ltversion.m4
+# serial 3017 ltversion.m4
# This file is part of GNU Libtool
-m4_define([LT_PACKAGE_VERSION], [2.2.6])
-m4_define([LT_PACKAGE_REVISION], [1.3012])
+m4_define([LT_PACKAGE_VERSION], [2.2.6b])
+m4_define([LT_PACKAGE_REVISION], [1.3017])
AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.2.6'
-macro_revision='1.3012'
+[macro_version='2.2.6b'
+macro_revision='1.3017'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
diff --git a/qa/test-conntrack.c b/qa/test-conntrack.c
new file mode 100644
index 0000000..c9097b6
--- /dev/null
+++ b/qa/test-conntrack.c
@@ -0,0 +1,94 @@
+/*
+ * Very simple test-tool for the command line tool `conntrack'.
+ * This code is released under GPLv2 or any later at your option.
+ *
+ * gcc test-conntrack.c -o test
+ *
+ * Do not forget that you need *root* or CAP_NET_ADMIN capabilities ;-)
+ *
+ * (c) 2008 Pablo Neira Ayuso <pablo@netfilter.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+
+#define CT_PROG "/usr/sbin/conntrack"
+
+int main()
+{
+ int ret, ok = 0, bad = 0, line;
+ FILE *fp;
+ DIR *d;
+ char buf[1024];
+ struct dirent *dent;
+ char file[1024];
+
+ d = opendir("testsuite");
+
+ while ((dent = readdir(d)) != NULL) {
+
+ sprintf(file, "testsuite/%s", dent->d_name);
+
+ line = 0;
+
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ perror("cannot find testsuite file");
+ exit(EXIT_FAILURE);
+ }
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ char tmp[1024] = CT_PROG, *res;
+ tmp[strlen(CT_PROG)] = ' ';
+
+ line++;
+
+ if (buf[0] == '#' || buf[0] == ' ')
+ continue;
+
+ res = strchr(buf, ';');
+ if (!res) {
+ printf("malformed file %s at line %d\n",
+ dent->d_name, line);
+ exit(EXIT_FAILURE);
+ }
+ *res = '\0';
+ res+=2;
+
+ strcpy(tmp + strlen(CT_PROG) + 1, buf);
+ printf("(%d) Executing: %s\n", line, tmp);
+
+ ret = system(tmp);
+
+ if (WIFEXITED(ret) &&
+ WEXITSTATUS(ret) == EXIT_SUCCESS) {
+ if (res[0] == 'O' &&
+ res[1] == 'K')
+ ok++;
+ else {
+ bad++;
+ printf("^----- BAD\n");
+ }
+ } else {
+ if (res[0] == 'B' &&
+ res[1] == 'A' &&
+ res[2] == 'D')
+ ok++;
+ else {
+ bad++;
+ printf("^----- BAD\n");
+ }
+ }
+ printf("=====\n");
+ }
+ fclose(fp);
+ }
+ closedir(d);
+
+ fprintf(stdout, "OK: %d BAD: %d\n", ok, bad);
+}
diff --git a/qa/testsuite/00create b/qa/testsuite/00create
new file mode 100644
index 0000000..40e2c19
--- /dev/null
+++ b/qa/testsuite/00create
@@ -0,0 +1,20 @@
+#missing destination
+-I -s 1.1.1.1 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing source
+-I -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing protocol
+-I -s 1.1.1.1 -d 2.2.2.2 --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing source port
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing timeout
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY ; BAD
+# create a conntrack
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# create again
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+# delete
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK
+# create from reply
+-I -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# delete reverse
+-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; OK
diff --git a/qa/testsuite/01delete b/qa/testsuite/01delete
new file mode 100644
index 0000000..3c38ac5
--- /dev/null
+++ b/qa/testsuite/01delete
@@ -0,0 +1,6 @@
+# create dummy
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# delete bad source
+-D -s 2.2.2.2 -p tcp --sport 10 --dport 20 ; BAD
+# delete by source
+-D -s 1.1.1.1 ; OK
diff --git a/qa/testsuite/02filter b/qa/testsuite/02filter
new file mode 100644
index 0000000..204c4e8
--- /dev/null
+++ b/qa/testsuite/02filter
@@ -0,0 +1,23 @@
+# create dummy
+conntrack -I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# filter by source
+conntrack -L -s 1.1.1.1 ; OK
+# filter by destination
+conntrack -L -d 2.2.2.2 ; OK
+# filter by protocol
+conntrack -L -p tcp ; OK
+# filter by status
+conntrack -L -u SEEN_REPLY ; OK
+# filter by TCP protocol state
+conntrack -L -p tcp --state LISTEN ; OK
+# update mark of dummy conntrack
+conntrack -U -s 1.1.1.1 -m 1 ; OK
+# filter by mark
+conntrack -L -m 1 ; OK
+# filter by layer 3 protocol
+conntrack -L -f ipv4 ; OK
+# filter by mark
+conntrack -L --mark 0 ; OK
+conntrack -L --mark 0/0xffffffff; OK
+# delete dummy
+conntrack -D -d 2.2.2.2 ; OK
diff --git a/qa/testsuite/03nat b/qa/testsuite/03nat
new file mode 100644
index 0000000..f94e8ff
--- /dev/null
+++ b/qa/testsuite/03nat
@@ -0,0 +1,40 @@
+# create dummy
+-I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# show
+-L --dst-nat ; OK
+# show
+-L --dst-nat 3.3.3.3 ; OK
+# show
+-L --src-nat ; OK
+# delete
+-D -s 1.1.1.1 ; OK
+# create dummy again
+-I -s 1.1.1.1 -d 2.2.2.2 --src-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# show
+-L --src-nat ; OK
+# show
+-L --src-nat 3.3.3.3 ; OK
+# show
+-L --dst-nat ; OK
+# show any-nat
+-L --any-nat ; OK
+# delete
+-D -s 1.1.1.1 ; OK
+# bad combination
+-L --dst-nat --any-nat ; BAD
+# bad combination
+-L --src-nat --any-nat ; BAD
+# bad combination
+-L --src-nat --dst-nat --any-nat ; BAD
+# create
+-I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3:80 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# show
+-L --dst-nat 3.3.3.3:80 ; OK
+# show
+-L --any-nat 3.3.3.3:80 ; OK
+# show
+-L --dst-nat 3.3.3.3:81 ; OK
+# show
+-L --dst-nat 1.1.1.1:80 ; OK
+# delete
+-D -s 1.1.1.1 ; OK
diff --git a/qa/testsuite/04zone b/qa/testsuite/04zone
new file mode 100644
index 0000000..4ff3d34
--- /dev/null
+++ b/qa/testsuite/04zone
@@ -0,0 +1,8 @@
+# create dummy
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --zone 1; OK
+# display dummy
+-L --zone 1; OK
+# display dummy
+-L --zone 0; OK
+# delete dummy
+-D --zone 1; OK
diff --git a/qa/testsuite/05mark b/qa/testsuite/05mark
new file mode 100644
index 0000000..4d99dea
--- /dev/null
+++ b/qa/testsuite/05mark
@@ -0,0 +1,27 @@
+# create with a mark
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42 ; OK
+# find it again using mark
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK
+-L --mark 42; OK
+# ct already exists
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42/0xffffffff ; BAD
+# delete by mark
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffffffff ; OK
+# try again after del
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 417889/0xffffffff ; OK
+# delete by mark
+-D --mark 417889 ; OK
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 0xffffffff ; OK
+# zap top 16.
+-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0/0xffff0000 ; OK
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0x0000ffff ; OK
+-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffff ; OK
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0x0000ffff ; OK
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/42 ; OK
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/2 ; OK
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/3 ; OK
+# OK, but no flow entries should be shown here:
+-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/0xf ; OK
+# BAD, because no updates done (mark is already 42).
+-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; BAD
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..6e6763d
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,6 @@
+/conntrack
+/conntrackd
+
+/read_config_lex.c
+/read_config_yy.c
+/read_config_yy.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 76f0e73..7d7b2ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,19 +1,18 @@
include $(top_srcdir)/Make_global.am
-YACC=@YACC@ -d
+AM_YFLAGS = -d
CLEANFILES = read_config_yy.c read_config_lex.c
sbin_PROGRAMS = conntrack conntrackd
conntrack_SOURCES = conntrack.c
-conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la
-conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
+conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la ${LIBNETFILTER_CONNTRACK_LIBS}
conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
local.c log.c mcast.c udp.c netlink.c vector.c \
filter.c fds.c event.c process.c origin.c date.c \
- cache.c cache_iterators.c \
+ cache.c cache-ct.c cache-exp.c \
cache_timer.c \
sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \
traffic_stats.c stats-mode.c \
@@ -22,12 +21,12 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
channel.c multichannel.c channel_mcast.c channel_udp.c \
tcp.c channel_tcp.c \
external_cache.c external_inject.c \
- internal_cache.c internal_bypass.c \
+ internal_cache.c internal_bypass.c \
read_config_yy.y read_config_lex.l
# yacc and lex generate dirty code
read_config_yy.o read_config_lex.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-missing-declarations -Wno-implicit-function-declaration -Wno-nested-externs -Wno-undef -Wno-redundant-decls
-conntrackd_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
+conntrackd_LDADD = ${LIBNETFILTER_CONNTRACK_LIBS}
EXTRA_DIST = read_config_yy.h
diff --git a/src/Makefile.in b/src/Makefile.in
index 94c36c3..571a811 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -34,17 +34,16 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/Make_global.am read_config_lex.c \
- read_config_yy.c
+ read_config_yy.c read_config_yy.h
sbin_PROGRAMS = conntrack$(EXEEXT) conntrackd$(EXEEXT)
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -54,6 +53,7 @@ am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am_conntrack_OBJECTS = conntrack.$(OBJEXT)
conntrack_OBJECTS = $(am_conntrack_OBJECTS)
+am__DEPENDENCIES_1 =
conntrack_DEPENDENCIES = ../extensions/libct_proto_tcp.la \
../extensions/libct_proto_udp.la \
../extensions/libct_proto_udplite.la \
@@ -62,17 +62,17 @@ conntrack_DEPENDENCIES = ../extensions/libct_proto_tcp.la \
../extensions/libct_proto_sctp.la \
../extensions/libct_proto_dccp.la \
../extensions/libct_proto_gre.la \
- ../extensions/libct_proto_unknown.la
-conntrack_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(conntrack_LDFLAGS) $(LDFLAGS) -o $@
+ ../extensions/libct_proto_unknown.la $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
am_conntrackd_OBJECTS = alarm.$(OBJEXT) main.$(OBJEXT) run.$(OBJEXT) \
hash.$(OBJEXT) queue.$(OBJEXT) rbtree.$(OBJEXT) \
local.$(OBJEXT) log.$(OBJEXT) mcast.$(OBJEXT) udp.$(OBJEXT) \
netlink.$(OBJEXT) vector.$(OBJEXT) filter.$(OBJEXT) \
fds.$(OBJEXT) event.$(OBJEXT) process.$(OBJEXT) \
origin.$(OBJEXT) date.$(OBJEXT) cache.$(OBJEXT) \
- cache_iterators.$(OBJEXT) cache_timer.$(OBJEXT) \
+ cache-ct.$(OBJEXT) cache-exp.$(OBJEXT) cache_timer.$(OBJEXT) \
sync-mode.$(OBJEXT) sync-alarm.$(OBJEXT) sync-ftfw.$(OBJEXT) \
sync-notrack.$(OBJEXT) traffic_stats.$(OBJEXT) \
stats-mode.$(OBJEXT) network.$(OBJEXT) cidr.$(OBJEXT) \
@@ -83,30 +83,46 @@ am_conntrackd_OBJECTS = alarm.$(OBJEXT) main.$(OBJEXT) run.$(OBJEXT) \
internal_cache.$(OBJEXT) internal_bypass.$(OBJEXT) \
read_config_yy.$(OBJEXT) read_config_lex.$(OBJEXT)
conntrackd_OBJECTS = $(am_conntrackd_OBJECTS)
-conntrackd_LDADD = $(LDADD)
-conntrackd_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(conntrackd_LDFLAGS) $(LDFLAGS) -o $@
+conntrackd_DEPENDENCIES = $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/depcomp
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
-LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
-YLWRAP = $(top_srcdir)/ylwrap
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+AM_V_LEX = $(am__v_LEX_$(V))
+am__v_LEX_ = $(am__v_LEX_$(AM_DEFAULT_VERBOSITY))
+am__v_LEX_0 = @echo " LEX " $@;
+YLWRAP = $(top_srcdir)/build-aux/ylwrap
YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
-LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+AM_V_YACC = $(am__v_YACC_$(V))
+am__v_YACC_ = $(am__v_YACC_$(AM_DEFAULT_VERBOSITY))
+am__v_YACC_0 = @echo " YACC " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(conntrack_SOURCES) $(conntrackd_SOURCES)
DIST_SOURCES = $(conntrack_SOURCES) $(conntrackd_SOURCES)
ETAGS = etags
@@ -114,6 +130,7 @@ CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -136,7 +153,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
-HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -174,15 +190,15 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
-XLEX = @XLEX@
-XYACC = @XYACC@
-YACC = @YACC@ -d
+YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
@@ -232,27 +248,24 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CFLAGS = -std=gnu99 -W -Wall \
-Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \
- -Wno-unused-parameter
+ -Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} \
+ ${LIBNETFILTER_CONNTRACK_CFLAGS}
+AM_YFLAGS = -d
CLEANFILES = read_config_yy.c read_config_lex.c
conntrack_SOURCES = conntrack.c
-conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la
-conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
+conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la ${LIBNETFILTER_CONNTRACK_LIBS}
conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
local.c log.c mcast.c udp.c netlink.c vector.c \
filter.c fds.c event.c process.c origin.c date.c \
- cache.c cache_iterators.c \
+ cache.c cache-ct.c cache-exp.c \
cache_timer.c \
sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \
traffic_stats.c stats-mode.c \
@@ -264,7 +277,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
internal_cache.c internal_bypass.c \
read_config_yy.y read_config_lex.l
-conntrackd_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
+conntrackd_LDADD = ${LIBNETFILTER_CONNTRACK_LIBS}
EXTRA_DIST = read_config_yy.h
all: all-am
@@ -279,9 +292,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/Make_global.am $(am_
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/Makefile
+ $(AUTOMAKE) --foreign src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -345,10 +358,15 @@ clean-sbinPROGRAMS:
rm -f $$list
conntrack$(EXEEXT): $(conntrack_OBJECTS) $(conntrack_DEPENDENCIES)
@rm -f conntrack$(EXEEXT)
- $(conntrack_LINK) $(conntrack_OBJECTS) $(conntrack_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(conntrack_OBJECTS) $(conntrack_LDADD) $(LIBS)
+read_config_yy.h: read_config_yy.c
+ @if test ! -f $@; then \
+ rm -f read_config_yy.c; \
+ $(MAKE) $(AM_MAKEFLAGS) read_config_yy.c; \
+ else :; fi
conntrackd$(EXEEXT): $(conntrackd_OBJECTS) $(conntrackd_DEPENDENCIES)
@rm -f conntrackd$(EXEEXT)
- $(conntrackd_LINK) $(conntrackd_OBJECTS) $(conntrackd_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(conntrackd_OBJECTS) $(conntrackd_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -358,8 +376,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alarm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/build.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache-ct.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache-exp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_iterators.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_timer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_mcast.Po@am__quote@
@@ -402,31 +421,37 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vector.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
.l.c:
- $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+ $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
.y.c:
- $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+ $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
mostlyclean-libtool:
-rm -f *.lo
@@ -551,6 +576,7 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
-rm -f read_config_lex.c
-rm -f read_config_yy.c
+ -rm -f read_config_yy.h
clean: clean-am
clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
diff --git a/src/build.c b/src/build.c
index 8f9d0b1..3193884 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -42,14 +43,14 @@ addattr(struct nethdr *n, int attr, const void *data, size_t len)
}
static inline void
-__build_u8(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
+ct_build_u8(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
{
void *ptr = put_header(n, b, sizeof(uint8_t));
memcpy(ptr, nfct_get_attr(ct, a), sizeof(uint8_t));
}
static inline void
-__build_u16(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
+ct_build_u16(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
{
uint16_t data = nfct_get_attr_u16(ct, a);
data = htons(data);
@@ -57,7 +58,7 @@ __build_u16(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
}
static inline void
-__build_u32(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
+ct_build_u32(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
{
uint32_t data = nfct_get_attr_u32(ct, a);
data = htonl(data);
@@ -65,7 +66,7 @@ __build_u32(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
}
static inline void
-__build_group(const struct nf_conntrack *ct, int a, struct nethdr *n,
+ct_build_group(const struct nf_conntrack *ct, int a, struct nethdr *n,
int b, int size)
{
void *ptr = put_header(n, b, size);
@@ -73,7 +74,7 @@ __build_group(const struct nf_conntrack *ct, int a, struct nethdr *n,
}
static inline void
-__build_natseqadj(const struct nf_conntrack *ct, struct nethdr *n)
+ct_build_natseqadj(const struct nf_conntrack *ct, struct nethdr *n)
{
struct nta_attr_natseqadj data = {
.orig_seq_correction_pos =
@@ -99,51 +100,55 @@ static enum nf_conntrack_attr nat_type[] =
static void build_l4proto_tcp(const struct nf_conntrack *ct, struct nethdr *n)
{
- __build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
- sizeof(struct nfct_attr_grp_port));
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
+ sizeof(struct nfct_attr_grp_port));
if (!nfct_attr_is_set(ct, ATTR_TCP_STATE))
return;
- __build_u8(ct, ATTR_TCP_STATE, n, NTA_TCP_STATE);
+ ct_build_u8(ct, ATTR_TCP_STATE, n, NTA_TCP_STATE);
+ if (CONFIG(sync).tcp_window_tracking) {
+ ct_build_u8(ct, ATTR_TCP_WSCALE_ORIG, n, NTA_TCP_WSCALE_ORIG);
+ ct_build_u8(ct, ATTR_TCP_WSCALE_REPL, n, NTA_TCP_WSCALE_REPL);
+ }
}
static void build_l4proto_sctp(const struct nf_conntrack *ct, struct nethdr *n)
{
- __build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
- sizeof(struct nfct_attr_grp_port));
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
+ sizeof(struct nfct_attr_grp_port));
if (!nfct_attr_is_set(ct, ATTR_SCTP_STATE))
return;
- __build_u8(ct, ATTR_SCTP_STATE, n, NTA_SCTP_STATE);
- __build_u32(ct, ATTR_SCTP_VTAG_ORIG, n, NTA_SCTP_VTAG_ORIG);
- __build_u32(ct, ATTR_SCTP_VTAG_REPL, n, NTA_SCTP_VTAG_REPL);
+ ct_build_u8(ct, ATTR_SCTP_STATE, n, NTA_SCTP_STATE);
+ ct_build_u32(ct, ATTR_SCTP_VTAG_ORIG, n, NTA_SCTP_VTAG_ORIG);
+ ct_build_u32(ct, ATTR_SCTP_VTAG_REPL, n, NTA_SCTP_VTAG_REPL);
}
static void build_l4proto_dccp(const struct nf_conntrack *ct, struct nethdr *n)
{
- __build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
- sizeof(struct nfct_attr_grp_port));
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
+ sizeof(struct nfct_attr_grp_port));
if (!nfct_attr_is_set(ct, ATTR_DCCP_STATE))
return;
- __build_u8(ct, ATTR_DCCP_STATE, n, NTA_DCCP_STATE);
- __build_u8(ct, ATTR_DCCP_ROLE, n, NTA_DCCP_ROLE);
+ ct_build_u8(ct, ATTR_DCCP_STATE, n, NTA_DCCP_STATE);
+ ct_build_u8(ct, ATTR_DCCP_ROLE, n, NTA_DCCP_ROLE);
}
static void build_l4proto_icmp(const struct nf_conntrack *ct, struct nethdr *n)
{
- __build_u8(ct, ATTR_ICMP_TYPE, n, NTA_ICMP_TYPE);
- __build_u8(ct, ATTR_ICMP_CODE, n, NTA_ICMP_CODE);
- __build_u16(ct, ATTR_ICMP_ID, n, NTA_ICMP_ID);
+ ct_build_u8(ct, ATTR_ICMP_TYPE, n, NTA_ICMP_TYPE);
+ ct_build_u8(ct, ATTR_ICMP_CODE, n, NTA_ICMP_CODE);
+ ct_build_u16(ct, ATTR_ICMP_ID, n, NTA_ICMP_ID);
}
static void build_l4proto_udp(const struct nf_conntrack *ct, struct nethdr *n)
{
- __build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
- sizeof(struct nfct_attr_grp_port));
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT,
+ sizeof(struct nfct_attr_grp_port));
}
#ifndef IPPROTO_DCCP
@@ -157,48 +162,49 @@ static struct build_l4proto {
[IPPROTO_SCTP] = { .build = build_l4proto_sctp },
[IPPROTO_DCCP] = { .build = build_l4proto_dccp },
[IPPROTO_ICMP] = { .build = build_l4proto_icmp },
- [IPPROTO_UDP] = { .build = build_l4proto_udp },
+ [IPPROTO_ICMPV6] = { .build = build_l4proto_icmp },
+ [IPPROTO_UDP] = { .build = build_l4proto_udp },
};
-void build_payload(const struct nf_conntrack *ct, struct nethdr *n)
+void ct2msg(const struct nf_conntrack *ct, struct nethdr *n)
{
uint8_t l4proto = nfct_get_attr_u8(ct, ATTR_L4PROTO);
if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) {
- __build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_IPV4,
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_IPV4,
sizeof(struct nfct_attr_grp_ipv4));
} else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) {
- __build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_IPV6,
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_IPV6,
sizeof(struct nfct_attr_grp_ipv6));
}
- __build_u32(ct, ATTR_STATUS, n, NTA_STATUS);
- __build_u8(ct, ATTR_L4PROTO, n, NTA_L4PROTO);
+ ct_build_u32(ct, ATTR_STATUS, n, NTA_STATUS);
+ ct_build_u8(ct, ATTR_L4PROTO, n, NTA_L4PROTO);
if (l4proto_fcn[l4proto].build)
l4proto_fcn[l4proto].build(ct, n);
if (!CONFIG(commit_timeout) && nfct_attr_is_set(ct, ATTR_TIMEOUT))
- __build_u32(ct, ATTR_TIMEOUT, n, NTA_TIMEOUT);
+ ct_build_u32(ct, ATTR_TIMEOUT, n, NTA_TIMEOUT);
if (nfct_attr_is_set(ct, ATTR_MARK))
- __build_u32(ct, ATTR_MARK, n, NTA_MARK);
+ ct_build_u32(ct, ATTR_MARK, n, NTA_MARK);
/* setup the master conntrack */
if (nfct_attr_grp_is_set(ct, ATTR_GRP_MASTER_IPV4)) {
- __build_group(ct, ATTR_GRP_MASTER_IPV4, n, NTA_MASTER_IPV4,
+ ct_build_group(ct, ATTR_GRP_MASTER_IPV4, n, NTA_MASTER_IPV4,
sizeof(struct nfct_attr_grp_ipv4));
- __build_u8(ct, ATTR_MASTER_L4PROTO, n, NTA_MASTER_L4PROTO);
+ ct_build_u8(ct, ATTR_MASTER_L4PROTO, n, NTA_MASTER_L4PROTO);
if (nfct_attr_grp_is_set(ct, ATTR_GRP_MASTER_PORT)) {
- __build_group(ct, ATTR_GRP_MASTER_PORT,
+ ct_build_group(ct, ATTR_GRP_MASTER_PORT,
n, NTA_MASTER_PORT,
sizeof(struct nfct_attr_grp_port));
}
} else if (nfct_attr_grp_is_set(ct, ATTR_GRP_MASTER_IPV6)) {
- __build_group(ct, ATTR_GRP_MASTER_IPV6, n, NTA_MASTER_IPV6,
+ ct_build_group(ct, ATTR_GRP_MASTER_IPV6, n, NTA_MASTER_IPV6,
sizeof(struct nfct_attr_grp_ipv6));
- __build_u8(ct, ATTR_MASTER_L4PROTO, n, NTA_MASTER_L4PROTO);
+ ct_build_u8(ct, ATTR_MASTER_L4PROTO, n, NTA_MASTER_L4PROTO);
if (nfct_attr_grp_is_set(ct, ATTR_GRP_MASTER_PORT)) {
- __build_group(ct, ATTR_GRP_MASTER_PORT,
+ ct_build_group(ct, ATTR_GRP_MASTER_PORT,
n, NTA_MASTER_PORT,
sizeof(struct nfct_attr_grp_port));
}
@@ -206,15 +212,114 @@ void build_payload(const struct nf_conntrack *ct, struct nethdr *n)
/* NAT */
if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT))
- __build_u32(ct, ATTR_REPL_IPV4_DST, n, NTA_SNAT_IPV4);
+ ct_build_u32(ct, ATTR_REPL_IPV4_DST, n, NTA_SNAT_IPV4);
if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT))
- __build_u32(ct, ATTR_REPL_IPV4_SRC, n, NTA_DNAT_IPV4);
+ ct_build_u32(ct, ATTR_REPL_IPV4_SRC, n, NTA_DNAT_IPV4);
if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT))
- __build_u16(ct, ATTR_REPL_PORT_DST, n, NTA_SPAT_PORT);
+ ct_build_u16(ct, ATTR_REPL_PORT_DST, n, NTA_SPAT_PORT);
if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT))
- __build_u16(ct, ATTR_REPL_PORT_SRC, n, NTA_DPAT_PORT);
+ ct_build_u16(ct, ATTR_REPL_PORT_SRC, n, NTA_DPAT_PORT);
/* NAT sequence adjustment */
if (nfct_attr_is_set_array(ct, nat_type, 6))
- __build_natseqadj(ct, n);
+ ct_build_natseqadj(ct, n);
+}
+
+static void
+exp_build_l4proto_tcp(const struct nf_conntrack *ct, struct nethdr *n, int a)
+{
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a,
+ sizeof(struct nfct_attr_grp_port));
+}
+
+static void
+exp_build_l4proto_sctp(const struct nf_conntrack *ct, struct nethdr *n, int a)
+{
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a,
+ sizeof(struct nfct_attr_grp_port));
+}
+
+static void
+exp_build_l4proto_dccp(const struct nf_conntrack *ct, struct nethdr *n, int a)
+{
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a,
+ sizeof(struct nfct_attr_grp_port));
+}
+
+static void
+exp_build_l4proto_udp(const struct nf_conntrack *ct, struct nethdr *n, int a)
+{
+ ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a,
+ sizeof(struct nfct_attr_grp_port));
+}
+
+static struct exp_build_l4proto {
+ void (*build)(const struct nf_conntrack *, struct nethdr *n, int a);
+} exp_l4proto_fcn[IPPROTO_MAX] = {
+ [IPPROTO_TCP] = { .build = exp_build_l4proto_tcp },
+ [IPPROTO_SCTP] = { .build = exp_build_l4proto_sctp },
+ [IPPROTO_DCCP] = { .build = exp_build_l4proto_dccp },
+ [IPPROTO_UDP] = { .build = exp_build_l4proto_udp },
+};
+
+static inline void
+exp_build_u32(const struct nf_expect *exp, int a, struct nethdr *n, int b)
+{
+ uint32_t data = nfexp_get_attr_u32(exp, a);
+ data = htonl(data);
+ addattr(n, b, &data, sizeof(uint32_t));
+}
+
+void exp2msg(const struct nf_expect *exp, struct nethdr *n)
+{
+ const struct nf_conntrack *ct = nfexp_get_attr(exp, ATTR_EXP_MASTER);
+ uint8_t l4proto = nfct_get_attr_u8(ct, ATTR_L4PROTO);
+
+ /* master conntrack for this expectation. */
+ if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_MASTER_IPV4,
+ sizeof(struct nfct_attr_grp_ipv4));
+ } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_MASTER_IPV6,
+ sizeof(struct nfct_attr_grp_ipv6));
+ }
+ ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_MASTER_L4PROTO);
+
+ if (exp_l4proto_fcn[l4proto].build)
+ exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_MASTER_PORT);
+
+ /* the expectation itself. */
+ ct = nfexp_get_attr(exp, ATTR_EXP_EXPECTED);
+
+ if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_EXPECT_IPV4,
+ sizeof(struct nfct_attr_grp_ipv4));
+ } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_EXPECT_IPV6,
+ sizeof(struct nfct_attr_grp_ipv6));
+ }
+ ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_EXPECT_L4PROTO);
+
+ if (exp_l4proto_fcn[l4proto].build)
+ exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_EXPECT_PORT);
+
+ /* mask for the expectation. */
+ ct = nfexp_get_attr(exp, ATTR_EXP_MASK);
+
+ if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_MASK_IPV4,
+ sizeof(struct nfct_attr_grp_ipv4));
+ } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) {
+ ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_MASK_IPV6,
+ sizeof(struct nfct_attr_grp_ipv6));
+ }
+ ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_MASK_L4PROTO);
+
+ if (exp_l4proto_fcn[l4proto].build)
+ exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_MASK_PORT);
+
+ if (!CONFIG(commit_timeout) && nfexp_attr_is_set(exp, ATTR_EXP_TIMEOUT))
+ exp_build_u32(exp, ATTR_EXP_TIMEOUT, n, NTA_EXP_TIMEOUT);
+
+ exp_build_u32(exp, ATTR_EXP_FLAGS, n, NTA_EXP_FLAGS);
}
diff --git a/src/cache-ct.c b/src/cache-ct.c
new file mode 100644
index 0000000..0ad8d2a
--- /dev/null
+++ b/src/cache-ct.c
@@ -0,0 +1,356 @@
+/*
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cache.h"
+#include "hash.h"
+#include "log.h"
+#include "conntrackd.h"
+#include "netlink.h"
+#include "event.h"
+#include "jhash.h"
+#include "network.h"
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+static uint32_t
+cache_hash4_ct(const struct nf_conntrack *ct, const struct hashtable *table)
+{
+ uint32_t a[4] = {
+ [0] = nfct_get_attr_u32(ct, ATTR_IPV4_SRC),
+ [1] = nfct_get_attr_u32(ct, ATTR_IPV4_DST),
+ [2] = nfct_get_attr_u8(ct, ATTR_L3PROTO) << 16 |
+ nfct_get_attr_u8(ct, ATTR_L4PROTO),
+ [3] = nfct_get_attr_u16(ct, ATTR_PORT_SRC) << 16 |
+ nfct_get_attr_u16(ct, ATTR_PORT_DST),
+ };
+
+ /*
+ * Instead of returning hash % table->hashsize (implying a divide)
+ * we return the high 32 bits of the (hash * table->hashsize) that will
+ * give results between [0 and hashsize-1] and same hash distribution,
+ * but using a multiply, less expensive than a divide. See:
+ * http://www.mail-archive.com/netdev@vger.kernel.org/msg56623.html
+ */
+ return ((uint64_t)jhash2(a, 4, 0) * table->hashsize) >> 32;
+}
+
+static uint32_t
+cache_hash6_ct(const struct nf_conntrack *ct, const struct hashtable *table)
+{
+ uint32_t a[10];
+
+ memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
+ memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
+ a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 |
+ nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
+ a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 |
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
+
+ return ((uint64_t)jhash2(a, 10, 0) * table->hashsize) >> 32;
+}
+
+static uint32_t
+cache_ct_hash(const void *data, const struct hashtable *table)
+{
+ int ret = 0;
+ const struct nf_conntrack *ct = data;
+
+ switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
+ case AF_INET:
+ ret = cache_hash4_ct(ct, table);
+ break;
+ case AF_INET6:
+ ret = cache_hash6_ct(ct, table);
+ break;
+ default:
+ dlog(LOG_ERR, "unknown layer 3 proto in hash");
+ break;
+ }
+ return ret;
+}
+
+static int cache_ct_cmp(const void *data1, const void *data2)
+{
+ const struct cache_object *obj = data1;
+ const struct nf_conntrack *ct = data2;
+
+ return nfct_cmp(obj->ptr, ct, NFCT_CMP_ORIG) &&
+ nfct_get_attr_u32(obj->ptr, ATTR_ID) ==
+ nfct_get_attr_u32(ct, ATTR_ID);
+}
+
+static void *cache_ct_alloc(void)
+{
+ return nfct_new();
+}
+
+static void cache_ct_free(void *ptr)
+{
+ nfct_destroy(ptr);
+}
+
+static void cache_ct_copy(void *dst, void *src, unsigned int flags)
+{
+ nfct_copy(dst, src, flags);
+}
+
+static int cache_ct_dump_step(void *data1, void *n)
+{
+ char buf[1024];
+ int size;
+ struct __dump_container *container = data1;
+ struct cache_object *obj = n;
+ char *data = obj->data;
+ unsigned i;
+
+ /*
+ * XXX: Do not dump the entries that are scheduled to expire.
+ * These entries talk about already destroyed connections
+ * that we keep for some time just in case that we have to
+ * resent some lost messages. We do not show them to the
+ * user as he may think that the firewall replicas are not
+ * in sync. The branch below is a hack as it is quite
+ * specific and it breaks conntrackd modularity. Probably
+ * there's a nicer way to do this but until I come up with it...
+ */
+ if (CONFIG(flags) & CTD_SYNC_FTFW && obj->status == C_OBJ_DEAD)
+ return 0;
+
+ /* do not show cached timeout, this may confuse users */
+ if (nfct_attr_is_set(obj->ptr, ATTR_TIMEOUT))
+ nfct_attr_unset(obj->ptr, ATTR_TIMEOUT);
+
+ memset(buf, 0, sizeof(buf));
+ size = nfct_snprintf(buf,
+ sizeof(buf),
+ obj->ptr,
+ NFCT_T_UNKNOWN,
+ container->type,
+ 0);
+
+ for (i = 0; i < obj->cache->num_features; i++) {
+ if (obj->cache->features[i]->dump) {
+ size += obj->cache->features[i]->dump(obj,
+ data,
+ buf+size,
+ container->type);
+ data += obj->cache->features[i]->size;
+ }
+ }
+ if (container->type != NFCT_O_XML) {
+ long tm = time(NULL);
+ size += sprintf(buf+size, " [active since %lds]",
+ tm - obj->lifetime);
+ }
+ size += sprintf(buf+size, "\n");
+ if (send(container->fd, buf, size, 0) == -1) {
+ if (errno != EPIPE)
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+cache_ct_commit_step(struct __commit_container *tmp, struct cache_object *obj)
+{
+ int ret, retry = 1, timeout;
+ struct nf_conntrack *ct = obj->ptr;
+
+ if (CONFIG(commit_timeout)) {
+ timeout = CONFIG(commit_timeout);
+ } else {
+ timeout = time(NULL) - obj->lastupdate;
+ if (timeout < 0) {
+ /* XXX: Arbitrarily set the timer to one minute, how
+ * can this happen? For example, an adjustment due to
+ * daylight-saving. Probably other situations can
+ * trigger this. */
+ timeout = 60;
+ }
+ /* calculate an estimation of the current timeout */
+ timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT) - timeout;
+ if (timeout < 0) {
+ timeout = 60;
+ }
+ }
+
+retry:
+ if (nl_create_conntrack(tmp->h, ct, timeout) == -1) {
+ if (errno == EEXIST && retry == 1) {
+ ret = nl_destroy_conntrack(tmp->h, ct);
+ if (ret == 0 || (ret == -1 && errno == ENOENT)) {
+ if (retry) {
+ retry = 0;
+ goto retry;
+ }
+ }
+ dlog(LOG_ERR, "commit-destroy: %s", strerror(errno));
+ dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
+ tmp->c->stats.commit_fail++;
+ } else {
+ dlog(LOG_ERR, "commit-create: %s", strerror(errno));
+ dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
+ tmp->c->stats.commit_fail++;
+ }
+ } else {
+ tmp->c->stats.commit_ok++;
+ }
+}
+
+static int cache_ct_commit_related(void *data, void *n)
+{
+ struct cache_object *obj = n;
+
+ if (ct_is_related(obj->ptr))
+ cache_ct_commit_step(data, obj);
+
+ /* keep iterating even if we have found errors */
+ return 0;
+}
+
+static int cache_ct_commit_master(void *data, void *n)
+{
+ struct cache_object *obj = n;
+
+ if (ct_is_related(obj->ptr))
+ return 0;
+
+ cache_ct_commit_step(data, obj);
+ return 0;
+}
+
+static int cache_ct_commit(struct cache *c, struct nfct_handle *h, int clientfd)
+{
+ unsigned int commit_ok, commit_fail;
+ struct __commit_container tmp = {
+ .h = h,
+ .c = c,
+ };
+ struct timeval commit_stop, res;
+
+ /* we already have one commit in progress, skip this. The clientfd
+ * descriptor has to be closed by the caller. */
+ if (clientfd && STATE_SYNC(commit).clientfd != -1)
+ return -1;
+
+ switch(STATE_SYNC(commit).state) {
+ case COMMIT_STATE_INACTIVE:
+ gettimeofday(&STATE_SYNC(commit).stats.start, NULL);
+ STATE_SYNC(commit).stats.ok = c->stats.commit_ok;
+ STATE_SYNC(commit).stats.fail = c->stats.commit_fail;
+ STATE_SYNC(commit).clientfd = clientfd;
+ case COMMIT_STATE_MASTER:
+ STATE_SYNC(commit).current =
+ hashtable_iterate_limit(c->h, &tmp,
+ STATE_SYNC(commit).current,
+ CONFIG(general).commit_steps,
+ cache_ct_commit_master);
+ if (STATE_SYNC(commit).current < CONFIG(hashsize)) {
+ STATE_SYNC(commit).state = COMMIT_STATE_MASTER;
+ /* give it another step as soon as possible */
+ write_evfd(STATE_SYNC(commit).evfd);
+ return 1;
+ }
+ STATE_SYNC(commit).current = 0;
+ STATE_SYNC(commit).state = COMMIT_STATE_RELATED;
+ case COMMIT_STATE_RELATED:
+ STATE_SYNC(commit).current =
+ hashtable_iterate_limit(c->h, &tmp,
+ STATE_SYNC(commit).current,
+ CONFIG(general).commit_steps,
+ cache_ct_commit_related);
+ if (STATE_SYNC(commit).current < CONFIG(hashsize)) {
+ STATE_SYNC(commit).state = COMMIT_STATE_RELATED;
+ /* give it another step as soon as possible */
+ write_evfd(STATE_SYNC(commit).evfd);
+ return 1;
+ }
+ /* calculate the time that commit has taken */
+ gettimeofday(&commit_stop, NULL);
+ timersub(&commit_stop, &STATE_SYNC(commit).stats.start, &res);
+
+ /* calculate new entries committed */
+ commit_ok = c->stats.commit_ok - STATE_SYNC(commit).stats.ok;
+ commit_fail =
+ c->stats.commit_fail - STATE_SYNC(commit).stats.fail;
+
+ /* log results */
+ dlog(LOG_NOTICE, "Committed %u new entries", commit_ok);
+
+ if (commit_fail)
+ dlog(LOG_NOTICE, "%u entries can't be "
+ "committed", commit_fail);
+
+ dlog(LOG_NOTICE, "commit has taken %lu.%06lu seconds",
+ res.tv_sec, res.tv_usec);
+
+ /* prepare the state machine for new commits */
+ STATE_SYNC(commit).current = 0;
+ STATE_SYNC(commit).state = COMMIT_STATE_INACTIVE;
+
+ return 0;
+ }
+ return 1;
+}
+
+static struct nethdr *
+cache_ct_build_msg(const struct cache_object *obj, int type)
+{
+ return BUILD_NETMSG_FROM_CT(obj->ptr, type);
+}
+
+/* template to cache conntracks coming from the kernel. */
+struct cache_ops cache_sync_internal_ct_ops = {
+ .hash = cache_ct_hash,
+ .cmp = cache_ct_cmp,
+ .alloc = cache_ct_alloc,
+ .free = cache_ct_free,
+ .copy = cache_ct_copy,
+ .dump_step = cache_ct_dump_step,
+ .commit = NULL,
+ .build_msg = cache_ct_build_msg,
+};
+
+/* template to cache conntracks coming from the network. */
+struct cache_ops cache_sync_external_ct_ops = {
+ .hash = cache_ct_hash,
+ .cmp = cache_ct_cmp,
+ .alloc = cache_ct_alloc,
+ .free = cache_ct_free,
+ .copy = cache_ct_copy,
+ .dump_step = cache_ct_dump_step,
+ .commit = cache_ct_commit,
+ .build_msg = NULL,
+};
+
+/* template to cache conntracks for the statistics mode. */
+struct cache_ops cache_stats_ct_ops = {
+ .hash = cache_ct_hash,
+ .cmp = cache_ct_cmp,
+ .alloc = cache_ct_alloc,
+ .free = cache_ct_free,
+ .copy = cache_ct_copy,
+ .dump_step = cache_ct_dump_step,
+ .commit = NULL,
+ .build_msg = NULL,
+};
diff --git a/src/cache-exp.c b/src/cache-exp.c
new file mode 100644
index 0000000..e88877a
--- /dev/null
+++ b/src/cache-exp.c
@@ -0,0 +1,308 @@
+/*
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cache.h"
+#include "hash.h"
+#include "log.h"
+#include "conntrackd.h"
+#include "netlink.h"
+#include "event.h"
+#include "jhash.h"
+#include "network.h"
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+static uint32_t
+cache_hash4_exp(const struct nf_conntrack *ct, const struct hashtable *table)
+{
+ uint32_t a[4] = {
+ [0] = nfct_get_attr_u32(ct, ATTR_IPV4_SRC),
+ [1] = nfct_get_attr_u32(ct, ATTR_IPV4_DST),
+ [2] = nfct_get_attr_u8(ct, ATTR_L3PROTO) << 16 |
+ nfct_get_attr_u8(ct, ATTR_L4PROTO),
+ [3] = nfct_get_attr_u16(ct, ATTR_PORT_SRC) << 16 |
+ nfct_get_attr_u16(ct, ATTR_PORT_DST),
+ };
+
+ /*
+ * Instead of returning hash % table->hashsize (implying a divide)
+ * we return the high 32 bits of the (hash * table->hashsize) that will
+ * give results between [0 and hashsize-1] and same hash distribution,
+ * but using a multiply, less expensive than a divide. See:
+ * http://www.mail-archive.com/netdev@vger.kernel.org/msg56623.html
+ */
+ return ((uint64_t)jhash2(a, 4, 0) * table->hashsize) >> 32;
+}
+
+static uint32_t
+cache_hash6_exp(const struct nf_conntrack *ct, const struct hashtable *table)
+{
+ uint32_t a[10];
+
+ memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
+ memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
+ a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 |
+ nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
+ a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 |
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
+
+ return ((uint64_t)jhash2(a, 10, 0) * table->hashsize) >> 32;
+}
+
+static uint32_t
+cache_exp_hash(const void *data, const struct hashtable *table)
+{
+ int ret = 0;
+ const struct nf_expect *exp = data;
+ const struct nf_conntrack *ct = nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
+ case AF_INET:
+ ret = cache_hash4_exp(ct, table);
+ break;
+ case AF_INET6:
+ ret = cache_hash6_exp(ct, table);
+ break;
+ default:
+ dlog(LOG_ERR, "unknown layer 3 proto in hash");
+ break;
+ }
+ return ret;
+}
+
+static int cache_exp_cmp(const void *data1, const void *data2)
+{
+ const struct cache_object *obj = data1;
+ const struct nf_expect *exp = data2;
+
+ return nfexp_cmp(obj->ptr, exp, 0);
+}
+
+static void *cache_exp_alloc(void)
+{
+ return nfexp_new();
+}
+
+static void cache_exp_free(void *ptr)
+{
+ nfexp_destroy(ptr);
+}
+
+static void cache_exp_copy(void *dst, void *src, unsigned int flags)
+{
+ /* XXX: add nfexp_copy(...) to libnetfilter_conntrack. */
+ memcpy(dst, src, nfexp_maxsize());
+}
+
+static int cache_exp_dump_step(void *data1, void *n)
+{
+ char buf[1024];
+ int size;
+ struct __dump_container *container = data1;
+ struct cache_object *obj = n;
+ char *data = obj->data;
+ unsigned i;
+
+ /*
+ * XXX: Do not dump the entries that are scheduled to expire.
+ * These entries talk about already destroyed connections
+ * that we keep for some time just in case that we have to
+ * resent some lost messages. We do not show them to the
+ * user as he may think that the firewall replicas are not
+ * in sync. The branch below is a hack as it is quite
+ * specific and it breaks conntrackd modularity. Probably
+ * there's a nicer way to do this but until I come up with it...
+ */
+ if (CONFIG(flags) & CTD_SYNC_FTFW && obj->status == C_OBJ_DEAD)
+ return 0;
+
+ /* do not show cached timeout, this may confuse users */
+ if (nfexp_attr_is_set(obj->ptr, ATTR_EXP_TIMEOUT))
+ nfexp_attr_unset(obj->ptr, ATTR_EXP_TIMEOUT);
+
+ memset(buf, 0, sizeof(buf));
+ size = nfexp_snprintf(buf, sizeof(buf),obj->ptr,
+ NFCT_T_UNKNOWN, container->type, 0);
+
+ for (i = 0; i < obj->cache->num_features; i++) {
+ if (obj->cache->features[i]->dump) {
+ size += obj->cache->features[i]->dump(obj, data,
+ buf+size,
+ container->type);
+ data += obj->cache->features[i]->size;
+ }
+ }
+ if (container->type != NFCT_O_XML) {
+ long tm = time(NULL);
+ size += sprintf(buf+size, " [active since %lds]",
+ tm - obj->lifetime);
+ }
+ size += sprintf(buf+size, "\n");
+ if (send(container->fd, buf, size, 0) == -1) {
+ if (errno != EPIPE)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int cache_exp_commit_step(void *data, void *n)
+{
+ struct cache_object *obj = n;
+ struct __commit_container *tmp = data;
+ int ret, retry = 1, timeout;
+ struct nf_expect *exp = obj->ptr;
+
+ if (CONFIG(commit_timeout)) {
+ timeout = CONFIG(commit_timeout);
+ } else {
+ timeout = time(NULL) - obj->lastupdate;
+ if (timeout < 0) {
+ /* XXX: Arbitrarily set the timer to one minute, how
+ * can this happen? For example, an adjustment due to
+ * daylight-saving. Probably other situations can
+ * trigger this. */
+ timeout = 60;
+ }
+ /* calculate an estimation of the current timeout */
+ timeout = nfexp_get_attr_u32(exp, ATTR_EXP_TIMEOUT) - timeout;
+ if (timeout < 0) {
+ timeout = 60;
+ }
+ }
+
+retry:
+ if (nl_create_expect(tmp->h, exp, timeout) == -1) {
+ if (errno == EEXIST && retry == 1) {
+ ret = nl_destroy_expect(tmp->h, exp);
+ if (ret == 0 || (ret == -1 && errno == ENOENT)) {
+ if (retry) {
+ retry = 0;
+ goto retry;
+ }
+ }
+ dlog(LOG_ERR, "commit-destroy: %s", strerror(errno));
+ dlog_exp(STATE(log), exp, NFCT_O_PLAIN);
+ tmp->c->stats.commit_fail++;
+ } else {
+ dlog(LOG_ERR, "commit-create: %s", strerror(errno));
+ dlog_exp(STATE(log), exp, NFCT_O_PLAIN);
+ tmp->c->stats.commit_fail++;
+ }
+ } else {
+ tmp->c->stats.commit_ok++;
+ }
+ /* keep iterating even if we have found errors */
+ return 0;
+}
+
+static int
+cache_exp_commit(struct cache *c, struct nfct_handle *h, int clientfd)
+{
+ unsigned int commit_ok, commit_fail;
+ struct timeval commit_stop, res;
+ struct __commit_container tmp = {
+ .h = h,
+ .c = c,
+ };
+
+ /* we already have one commit in progress, skip this. The clientfd
+ * descriptor has to be closed by the caller. */
+ if (clientfd && STATE_SYNC(commit).clientfd != -1)
+ return -1;
+
+ switch(STATE_SYNC(commit).state) {
+ case COMMIT_STATE_INACTIVE:
+ gettimeofday(&STATE_SYNC(commit).stats.start, NULL);
+ STATE_SYNC(commit).stats.ok = c->stats.commit_ok;
+ STATE_SYNC(commit).stats.fail = c->stats.commit_fail;
+ STATE_SYNC(commit).clientfd = clientfd;
+ case COMMIT_STATE_MASTER:
+ STATE_SYNC(commit).current =
+ hashtable_iterate_limit(c->h, &tmp,
+ STATE_SYNC(commit).current,
+ CONFIG(general).commit_steps,
+ cache_exp_commit_step);
+ if (STATE_SYNC(commit).current < CONFIG(hashsize)) {
+ STATE_SYNC(commit).state = COMMIT_STATE_MASTER;
+ /* give it another step as soon as possible */
+ write_evfd(STATE_SYNC(commit).evfd);
+ return 1;
+ }
+
+ /* calculate the time that commit has taken */
+ gettimeofday(&commit_stop, NULL);
+ timersub(&commit_stop, &STATE_SYNC(commit).stats.start, &res);
+
+ /* calculate new entries committed */
+ commit_ok = c->stats.commit_ok - STATE_SYNC(commit).stats.ok;
+ commit_fail =
+ c->stats.commit_fail - STATE_SYNC(commit).stats.fail;
+
+ /* log results */
+ dlog(LOG_NOTICE, "Committed %u new expectations", commit_ok);
+
+ if (commit_fail)
+ dlog(LOG_NOTICE, "%u expectations can't be "
+ "committed", commit_fail);
+
+ dlog(LOG_NOTICE, "commit has taken %lu.%06lu seconds",
+ res.tv_sec, res.tv_usec);
+
+ /* prepare the state machine for new commits */
+ STATE_SYNC(commit).current = 0;
+ STATE_SYNC(commit).state = COMMIT_STATE_INACTIVE;
+
+ return 0;
+ }
+ return 1;
+}
+
+static struct nethdr *
+cache_exp_build_msg(const struct cache_object *obj, int type)
+{
+ return BUILD_NETMSG_FROM_EXP(obj->ptr, type);
+}
+
+/* template to cache expectations coming from the kernel. */
+struct cache_ops cache_sync_internal_exp_ops = {
+ .hash = cache_exp_hash,
+ .cmp = cache_exp_cmp,
+ .alloc = cache_exp_alloc,
+ .free = cache_exp_free,
+ .copy = cache_exp_copy,
+ .dump_step = cache_exp_dump_step,
+ .commit = NULL,
+ .build_msg = cache_exp_build_msg,
+};
+
+/* template to cache expectations coming from the network. */
+struct cache_ops cache_sync_external_exp_ops = {
+ .hash = cache_exp_hash,
+ .cmp = cache_exp_cmp,
+ .alloc = cache_exp_alloc,
+ .free = cache_exp_free,
+ .copy = cache_exp_copy,
+ .dump_step = cache_exp_dump_step,
+ .commit = cache_exp_commit,
+ .build_msg = NULL,
+};
diff --git a/src/cache.c b/src/cache.c
index 74c5c4b..7c41e54 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1,5 +1,6 @@
/*
- * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
*
* 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
@@ -28,80 +29,14 @@
#include <string.h>
#include <time.h>
-static uint32_t
-__hash4(const struct nf_conntrack *ct, const struct hashtable *table)
-{
- uint32_t a[4] = {
- [0] = nfct_get_attr_u32(ct, ATTR_IPV4_SRC),
- [1] = nfct_get_attr_u32(ct, ATTR_IPV4_DST),
- [2] = nfct_get_attr_u8(ct, ATTR_L3PROTO) << 16 |
- nfct_get_attr_u8(ct, ATTR_L4PROTO),
- [3] = nfct_get_attr_u16(ct, ATTR_PORT_SRC) << 16 |
- nfct_get_attr_u16(ct, ATTR_PORT_DST),
- };
-
- /*
- * Instead of returning hash % table->hashsize (implying a divide)
- * we return the high 32 bits of the (hash * table->hashsize) that will
- * give results between [0 and hashsize-1] and same hash distribution,
- * but using a multiply, less expensive than a divide. See:
- * http://www.mail-archive.com/netdev@vger.kernel.org/msg56623.html
- */
- return ((uint64_t)jhash2(a, 4, 0) * table->hashsize) >> 32;
-}
-
-static uint32_t
-__hash6(const struct nf_conntrack *ct, const struct hashtable *table)
-{
- uint32_t a[10];
-
- memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
- memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4);
- a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 |
- nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
- a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 |
- nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
-
- return ((uint64_t)jhash2(a, 10, 0) * table->hashsize) >> 32;
-}
-
-static uint32_t hash(const void *data, const struct hashtable *table)
-{
- int ret = 0;
- const struct nf_conntrack *ct = data;
-
- switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
- case AF_INET:
- ret = __hash4(ct, table);
- break;
- case AF_INET6:
- ret = __hash6(ct, table);
- break;
- default:
- dlog(LOG_ERR, "unknown layer 3 proto in hash");
- break;
- }
-
- return ret;
-}
-
-static int compare(const void *data1, const void *data2)
-{
- const struct cache_object *obj = data1;
- const struct nf_conntrack *ct = data2;
-
- return nfct_cmp(obj->ct, ct, NFCT_CMP_ORIG) &&
- nfct_get_attr_u32(obj->ct, ATTR_ID) ==
- nfct_get_attr_u32(ct, ATTR_ID);
-}
-
struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = {
[TIMER_FEATURE] = &timer_feature,
};
-struct cache *cache_create(const char *name,
+struct cache *cache_create(const char *name, enum cache_type type,
unsigned int features,
- struct cache_extra *extra)
+ struct cache_extra *extra,
+ struct cache_ops *ops)
{
size_t size = sizeof(struct cache_object);
int i, j = 0;
@@ -110,12 +45,16 @@ struct cache *cache_create(const char *name,
unsigned int feature_offset[CACHE_MAX_FEATURE] = {};
unsigned int feature_type[CACHE_MAX_FEATURE] = {};
+ if (type == CACHE_T_NONE || type >= CACHE_T_MAX)
+ return NULL;
+
c = malloc(sizeof(struct cache));
if (!c)
return NULL;
memset(c, 0, sizeof(struct cache));
strcpy(c->name, name);
+ c->type = type;
for (i = 0; i < CACHE_MAX_FEATURE; i++) {
if ((1 << i) & features) {
@@ -150,11 +89,19 @@ struct cache *cache_create(const char *name,
}
memcpy(c->feature_offset, feature_offset, sizeof(unsigned int) * j);
+ if (!ops || !ops->hash || !ops->cmp ||
+ !ops->alloc || !ops->copy || !ops->free) {
+ free(c->feature_offset);
+ free(c->features);
+ free(c);
+ return NULL;
+ }
+ c->ops = ops;
+
c->h = hashtable_create(CONFIG(hashsize),
CONFIG(limit),
- hash,
- compare);
-
+ c->ops->hash,
+ c->ops->cmp);
if (!c->h) {
free(c->features);
free(c->feature_offset);
@@ -175,7 +122,7 @@ void cache_destroy(struct cache *c)
free(c);
}
-struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct)
+struct cache_object *cache_object_new(struct cache *c, void *ptr)
{
struct cache_object *obj;
@@ -187,13 +134,14 @@ struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct)
}
obj->cache = c;
- if ((obj->ct = nfct_new()) == NULL) {
+ obj->ptr = c->ops->alloc();
+ if (obj->ptr == NULL) {
free(obj);
errno = ENOMEM;
c->stats.add_fail_enomem++;
return NULL;
}
- memcpy(obj->ct, ct, nfct_sizeof(ct));
+ c->ops->copy(obj->ptr, ptr, NFCT_CP_OVERRIDE);
obj->status = C_OBJ_NONE;
c->stats.objects++;
@@ -203,7 +151,8 @@ struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct)
void cache_object_free(struct cache_object *obj)
{
obj->cache->stats.objects--;
- nfct_destroy(obj->ct);
+ obj->cache->ops->free(obj->ptr);
+
free(obj);
}
@@ -271,13 +220,12 @@ int cache_add(struct cache *c, struct cache_object *obj, int id)
return 0;
}
-void cache_update(struct cache *c, struct cache_object *obj, int id,
- struct nf_conntrack *ct)
+void cache_update(struct cache *c, struct cache_object *obj, int id, void *ptr)
{
char *data = obj->data;
unsigned int i;
- nfct_copy(obj->ct, ct, NFCT_CP_META);
+ c->ops->copy(obj->ptr, ptr, NFCT_CP_META);
for (i = 0; i < c->num_features; i++) {
c->features[i]->update(obj, data);
@@ -322,23 +270,22 @@ void cache_del(struct cache *c, struct cache_object *obj)
__del(c, obj);
}
-struct cache_object *
-cache_update_force(struct cache *c, struct nf_conntrack *ct)
+struct cache_object *cache_update_force(struct cache *c, void *ptr)
{
struct cache_object *obj;
int id;
- obj = cache_find(c, ct, &id);
+ obj = cache_find(c, ptr, &id);
if (obj) {
if (obj->status != C_OBJ_DEAD) {
- cache_update(c, obj, id, ct);
+ cache_update(c, obj, id, ptr);
return obj;
} else {
cache_del(c, obj);
cache_object_free(obj);
}
}
- obj = cache_object_new(c, ct);
+ obj = cache_object_new(c, ptr);
if (obj == NULL)
return NULL;
@@ -350,21 +297,15 @@ cache_update_force(struct cache *c, struct nf_conntrack *ct)
return obj;
}
-struct cache_object *
-cache_find(struct cache *c, struct nf_conntrack *ct, int *id)
+struct cache_object *cache_find(struct cache *c, void *ptr, int *id)
{
- *id = hashtable_hash(c->h, ct);
- return ((struct cache_object *) hashtable_find(c->h, ct, *id));
+ *id = hashtable_hash(c->h, ptr);
+ return ((struct cache_object *) hashtable_find(c->h, ptr, *id));
}
-struct cache_object *cache_data_get_object(struct cache *c, void *data)
+void *cache_get_extra(struct cache_object *obj)
{
- return (struct cache_object *)((char*)data - c->extra_offset);
-}
-
-void *cache_get_extra(struct cache *c, void *data)
-{
- return (char*)data + c->extra_offset;
+ return (char*)obj + obj->cache->extra_offset;
}
void cache_stats(const struct cache *c, int fd)
@@ -432,3 +373,33 @@ void cache_iterate_limit(struct cache *c, void *data,
{
hashtable_iterate_limit(c->h, data, from, steps, iterate);
}
+
+void cache_dump(struct cache *c, int fd, int type)
+{
+ struct __dump_container tmp = {
+ .fd = fd,
+ .type = type
+ };
+ hashtable_iterate(c->h, (void *) &tmp, c->ops->dump_step);
+}
+
+int cache_commit(struct cache *c, struct nfct_handle *h, int clientfd)
+{
+ return c->ops->commit(c, h, clientfd);
+}
+
+static int do_flush(void *data, void *n)
+{
+ struct cache *c = data;
+ struct cache_object *obj = n;
+
+ cache_del(c, obj);
+ cache_object_free(obj);
+ return 0;
+}
+
+void cache_flush(struct cache *c)
+{
+ hashtable_iterate(c->h, c, do_flush);
+ c->stats.flush++;
+}
diff --git a/src/conntrack.c b/src/conntrack.c
index b8806bd..f0c47db 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -58,10 +58,219 @@
#include <fcntl.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+struct u32_mask {
+ uint32_t value;
+ uint32_t mask;
+};
+
+/* These are the template objects that are used to send commands. */
+static struct {
+ struct nf_conntrack *ct;
+ struct nf_expect *exp;
+ /* Expectations require the expectation tuple and the mask. */
+ struct nf_conntrack *exptuple, *mask;
+
+ /* Allows filtering/setting specific bits in the ctmark */
+ struct u32_mask mark;
+} tmpl;
+
+static int alloc_tmpl_objects(void)
+{
+ tmpl.ct = nfct_new();
+ tmpl.exptuple = nfct_new();
+ tmpl.mask = nfct_new();
+ tmpl.exp = nfexp_new();
+
+ memset(&tmpl.mark, 0, sizeof(tmpl.mark));
+
+ return tmpl.ct != NULL && tmpl.exptuple != NULL &&
+ tmpl.mask != NULL && tmpl.exp != NULL;
+}
+
+static void free_tmpl_objects(void)
+{
+ if (tmpl.ct)
+ nfct_destroy(tmpl.ct);
+ if (tmpl.exptuple)
+ nfct_destroy(tmpl.exptuple);
+ if (tmpl.mask)
+ nfct_destroy(tmpl.mask);
+ if (tmpl.exp)
+ nfexp_destroy(tmpl.exp);
+}
+
+enum ct_command {
+ CT_NONE = 0,
+
+ CT_LIST_BIT = 0,
+ CT_LIST = (1 << CT_LIST_BIT),
+
+ CT_CREATE_BIT = 1,
+ CT_CREATE = (1 << CT_CREATE_BIT),
+
+ CT_UPDATE_BIT = 2,
+ CT_UPDATE = (1 << CT_UPDATE_BIT),
+
+ CT_DELETE_BIT = 3,
+ CT_DELETE = (1 << CT_DELETE_BIT),
+
+ CT_GET_BIT = 4,
+ CT_GET = (1 << CT_GET_BIT),
+
+ CT_FLUSH_BIT = 5,
+ CT_FLUSH = (1 << CT_FLUSH_BIT),
+
+ CT_EVENT_BIT = 6,
+ CT_EVENT = (1 << CT_EVENT_BIT),
+
+ CT_VERSION_BIT = 7,
+ CT_VERSION = (1 << CT_VERSION_BIT),
+
+ CT_HELP_BIT = 8,
+ CT_HELP = (1 << CT_HELP_BIT),
+
+ EXP_LIST_BIT = 9,
+ EXP_LIST = (1 << EXP_LIST_BIT),
+
+ EXP_CREATE_BIT = 10,
+ EXP_CREATE = (1 << EXP_CREATE_BIT),
+
+ EXP_DELETE_BIT = 11,
+ EXP_DELETE = (1 << EXP_DELETE_BIT),
+
+ EXP_GET_BIT = 12,
+ EXP_GET = (1 << EXP_GET_BIT),
+
+ EXP_FLUSH_BIT = 13,
+ EXP_FLUSH = (1 << EXP_FLUSH_BIT),
+
+ EXP_EVENT_BIT = 14,
+ EXP_EVENT = (1 << EXP_EVENT_BIT),
+
+ CT_COUNT_BIT = 15,
+ CT_COUNT = (1 << CT_COUNT_BIT),
+
+ EXP_COUNT_BIT = 16,
+ EXP_COUNT = (1 << EXP_COUNT_BIT),
+
+ X_STATS_BIT = 17,
+ X_STATS = (1 << X_STATS_BIT),
+};
+/* If you add a new command, you have to update NUMBER_OF_CMD in conntrack.h */
+
+enum ct_options {
+ CT_OPT_ORIG_SRC_BIT = 0,
+ CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT),
+
+ CT_OPT_ORIG_DST_BIT = 1,
+ CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT),
+
+ CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST),
+
+ CT_OPT_REPL_SRC_BIT = 2,
+ CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT),
+
+ CT_OPT_REPL_DST_BIT = 3,
+ CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT),
+
+ CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST),
+
+ CT_OPT_PROTO_BIT = 4,
+ CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT),
+
+ CT_OPT_TUPLE_ORIG = (CT_OPT_ORIG | CT_OPT_PROTO),
+ CT_OPT_TUPLE_REPL = (CT_OPT_REPL | CT_OPT_PROTO),
+
+ CT_OPT_TIMEOUT_BIT = 5,
+ CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT),
+
+ CT_OPT_STATUS_BIT = 6,
+ CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT),
+
+ CT_OPT_ZERO_BIT = 7,
+ CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT),
+
+ CT_OPT_EVENT_MASK_BIT = 8,
+ CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT),
+
+ CT_OPT_EXP_SRC_BIT = 9,
+ CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT),
+
+ CT_OPT_EXP_DST_BIT = 10,
+ CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT),
+
+ CT_OPT_MASK_SRC_BIT = 11,
+ CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT),
+
+ CT_OPT_MASK_DST_BIT = 12,
+ CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT),
+
+ CT_OPT_NATRANGE_BIT = 13,
+ CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT),
+
+ CT_OPT_MARK_BIT = 14,
+ CT_OPT_MARK = (1 << CT_OPT_MARK_BIT),
+
+ CT_OPT_ID_BIT = 15,
+ CT_OPT_ID = (1 << CT_OPT_ID_BIT),
+
+ CT_OPT_FAMILY_BIT = 16,
+ CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT),
+
+ CT_OPT_SRC_NAT_BIT = 17,
+ CT_OPT_SRC_NAT = (1 << CT_OPT_SRC_NAT_BIT),
+
+ CT_OPT_DST_NAT_BIT = 18,
+ CT_OPT_DST_NAT = (1 << CT_OPT_DST_NAT_BIT),
+
+ CT_OPT_OUTPUT_BIT = 19,
+ CT_OPT_OUTPUT = (1 << CT_OPT_OUTPUT_BIT),
+
+ CT_OPT_SECMARK_BIT = 20,
+ CT_OPT_SECMARK = (1 << CT_OPT_SECMARK_BIT),
+
+ CT_OPT_BUFFERSIZE_BIT = 21,
+ CT_OPT_BUFFERSIZE = (1 << CT_OPT_BUFFERSIZE_BIT),
+
+ CT_OPT_ANY_NAT_BIT = 22,
+ CT_OPT_ANY_NAT = (1 << CT_OPT_ANY_NAT_BIT),
+
+ CT_OPT_ZONE_BIT = 23,
+ CT_OPT_ZONE = (1 << CT_OPT_ZONE_BIT),
+};
+/* If you add a new option, you have to update NUMBER_OF_OPT in conntrack.h */
+
+/* Update this mask to allow to filter based on new options. */
+#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | \
+ CT_OPT_MARK | CT_OPT_SECMARK | CT_OPT_STATUS | \
+ CT_OPT_ID | CT_OPT_ZONE)
+
static const char *optflags[NUMBER_OF_OPT] = {
-"src","dst","reply-src","reply-dst","protonum","timeout","status","zero",
-"event-mask","tuple-src","tuple-dst","mask-src","mask-dst","nat-range","mark",
-"id","family","src-nat","dst-nat","output","secmark","buffersize"};
+ [CT_OPT_ORIG_SRC_BIT] = "src",
+ [CT_OPT_ORIG_DST_BIT] = "dst",
+ [CT_OPT_REPL_SRC_BIT] = "reply-src",
+ [CT_OPT_REPL_DST_BIT] = "reply-dst",
+ [CT_OPT_PROTO_BIT] = "protonum",
+ [CT_OPT_TIMEOUT_BIT] = "timeout",
+ [CT_OPT_STATUS_BIT] = "status",
+ [CT_OPT_ZERO_BIT] = "zero",
+ [CT_OPT_EVENT_MASK_BIT] = "event-mask",
+ [CT_OPT_EXP_SRC_BIT] = "tuple-src",
+ [CT_OPT_EXP_DST_BIT] = "tuple-dst",
+ [CT_OPT_MASK_SRC_BIT] = "mask-src",
+ [CT_OPT_MASK_DST_BIT] = "mask-dst",
+ [CT_OPT_NATRANGE_BIT] = "nat-range",
+ [CT_OPT_MARK_BIT] = "mark",
+ [CT_OPT_ID_BIT] = "id",
+ [CT_OPT_FAMILY_BIT] = "family",
+ [CT_OPT_SRC_NAT_BIT] = "src-nat",
+ [CT_OPT_DST_NAT_BIT] = "dst-nat",
+ [CT_OPT_OUTPUT_BIT] = "output",
+ [CT_OPT_SECMARK_BIT] = "secmark",
+ [CT_OPT_BUFFERSIZE_BIT] = "buffer-size",
+ [CT_OPT_ANY_NAT_BIT] = "any-nat",
+ [CT_OPT_ZONE_BIT] = "zone",
+};
static struct option original_opts[] = {
{"dump", 2, 0, 'L'},
@@ -99,14 +308,14 @@ static struct option original_opts[] = {
{"dst-nat", 2, 0, 'g'},
{"output", 1, 0, 'o'},
{"buffer-size", 1, 0, 'b'},
+ {"any-nat", 2, 0, 'j'},
+ {"zone", 1, 0, 'w'},
{0, 0, 0, 0}
};
-#define OPTION_OFFSET 256
-
-static struct nfct_handle *cth, *ith;
-static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
+static const char *getopt_str = "L::I::U::D::G::E::F::hVs:d:r:q:"
+ "p:t:u:e:a:z[:]:{:}:m:i:f:o:n::"
+ "g::c:b:C::Sj::w:";
/* Table of legal combinations of commands and options. If any of the
* given commands make an option legal, that option is legal (applies to
@@ -121,27 +330,143 @@ static unsigned int global_option_offset = 0;
static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
/* Well, it's better than "Re: Linux vs FreeBSD" */
{
- /* s d r q p t u z e [ ] { } a m i f n g o c b*/
-/*CT_LIST*/ {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0},
-/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0},
-/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0},
-/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0},
-/*CT_GET*/ {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0},
-/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2},
-/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0},
-/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0},
-/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*X_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ /* s d r q p t u z e [ ] { } a m i f n g o c b j w*/
+/*CT_LIST*/ {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2},
+/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2},
+/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0},
+/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2},
+/*CT_GET*/ {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0},
+/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2},
+/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0},
+/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*CT_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*X_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+};
+
+static const int cmd2type[][2] = {
+ ['L'] = { CT_LIST, EXP_LIST },
+ ['I'] = { CT_CREATE, EXP_CREATE },
+ ['D'] = { CT_DELETE, EXP_DELETE },
+ ['G'] = { CT_GET, EXP_GET },
+ ['F'] = { CT_FLUSH, EXP_FLUSH },
+ ['E'] = { CT_EVENT, EXP_EVENT },
+ ['V'] = { CT_VERSION, CT_VERSION },
+ ['h'] = { CT_HELP, CT_HELP },
+ ['C'] = { CT_COUNT, EXP_COUNT },
+};
+
+static const int opt2type[] = {
+ ['s'] = CT_OPT_ORIG_SRC,
+ ['d'] = CT_OPT_ORIG_DST,
+ ['r'] = CT_OPT_REPL_SRC,
+ ['q'] = CT_OPT_REPL_DST,
+ ['{'] = CT_OPT_MASK_SRC,
+ ['}'] = CT_OPT_MASK_DST,
+ ['['] = CT_OPT_EXP_SRC,
+ [']'] = CT_OPT_EXP_DST,
+ ['n'] = CT_OPT_SRC_NAT,
+ ['g'] = CT_OPT_DST_NAT,
+ ['m'] = CT_OPT_MARK,
+ ['c'] = CT_OPT_SECMARK,
+ ['i'] = CT_OPT_ID,
+ ['j'] = CT_OPT_ANY_NAT,
+ ['w'] = CT_OPT_ZONE,
+};
+
+static const int opt2family_attr[][2] = {
+ ['s'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
+ ['d'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
+ ['r'] = { ATTR_REPL_IPV4_SRC, ATTR_REPL_IPV6_SRC },
+ ['q'] = { ATTR_REPL_IPV4_DST, ATTR_REPL_IPV6_DST },
+ ['{'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
+ ['}'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
+ ['['] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
+ [']'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
};
+static const int opt2attr[] = {
+ ['s'] = ATTR_ORIG_L3PROTO,
+ ['d'] = ATTR_ORIG_L3PROTO,
+ ['r'] = ATTR_REPL_L3PROTO,
+ ['q'] = ATTR_REPL_L3PROTO,
+ ['m'] = ATTR_MARK,
+ ['c'] = ATTR_SECMARK,
+ ['i'] = ATTR_ID,
+ ['w'] = ATTR_ZONE,
+};
+
+static char exit_msg[NUMBER_OF_CMD][64] = {
+ [CT_LIST_BIT] = "%d flow entries have been shown.\n",
+ [CT_CREATE_BIT] = "%d flow entries have been created.\n",
+ [CT_UPDATE_BIT] = "%d flow entries have been updated.\n",
+ [CT_DELETE_BIT] = "%d flow entries have been deleted.\n",
+ [CT_GET_BIT] = "%d flow entries have been shown.\n",
+ [CT_EVENT_BIT] = "%d flow events have been shown.\n",
+ [EXP_LIST_BIT] = "%d expectations have been shown.\n",
+ [EXP_DELETE_BIT] = "%d expectations have been shown.\n",
+};
+
+static const char usage_commands[] =
+ "Commands:\n"
+ " -L [table] [options]\t\tList conntrack or expectation table\n"
+ " -G [table] parameters\t\tGet conntrack or expectation\n"
+ " -D [table] parameters\t\tDelete conntrack or expectation\n"
+ " -I [table] parameters\t\tCreate a conntrack or expectation\n"
+ " -U [table] parameters\t\tUpdate a conntrack\n"
+ " -E [table] [options]\t\tShow events\n"
+ " -F [table]\t\t\tFlush table\n"
+ " -C [table]\t\t\tShow counter\n"
+ " -S\t\t\t\tShow statistics\n";
+
+static const char usage_tables[] =
+ "Tables: conntrack, expect\n";
+
+static const char usage_conntrack_parameters[] =
+ "Conntrack parameters and options:\n"
+ " -n, --src-nat ip\t\t\tsource NAT ip\n"
+ " -g, --dst-nat ip\t\t\tdestination NAT ip\n"
+ " -j, --any-nat ip\t\t\tsource or destination NAT ip\n"
+ " -m, --mark mark\t\t\tSet mark\n"
+ " -c, --secmark secmark\t\t\tSet selinux secmark\n"
+ " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n"
+ " -z, --zero \t\t\t\tZero counters while listing\n"
+ " -o, --output type[,...]\t\tOutput format, eg. xml\n";
+
+static const char usage_expectation_parameters[] =
+ "Expectation parameters and options:\n"
+ " --tuple-src ip\tSource address in expect tuple\n"
+ " --tuple-dst ip\tDestination address in expect tuple\n"
+ " --mask-src ip\t\tSource mask address\n"
+ " --mask-dst ip\t\tDestination mask address\n";
+
+static const char usage_parameters[] =
+ "Common parameters and options:\n"
+ " -s, --orig-src ip\t\tSource address from original direction\n"
+ " -d, --orig-dst ip\t\tDestination address from original direction\n"
+ " -r, --reply-src ip\t\tSource addres from reply direction\n"
+ " -q, --reply-dst ip\t\tDestination address from reply direction\n"
+ " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n"
+ " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n"
+ " -t, --timeout timeout\t\tSet timeout\n"
+ " -u, --status status\t\tSet status, eg. ASSURED\n"
+ " -w, --zone value\t\tSet conntrack zone\n"
+ " -b, --buffer-size\t\tNetlink socket buffer size\n"
+ ;
+
+#define OPTION_OFFSET 256
+
+static struct nfct_handle *cth, *ith;
+static struct option *opts = original_opts;
+static unsigned int global_option_offset = 0;
+
#define ADDR_VALID_FLAGS_MAX 2
static unsigned int addr_valid_flags[ADDR_VALID_FLAGS_MAX] = {
CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST,
@@ -152,9 +477,6 @@ static LIST_HEAD(proto_list);
static unsigned int options;
-#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK |\
- CT_OPT_SECMARK | CT_OPT_STATUS | CT_OPT_ID)
-
void register_proto(struct ctproto_handler *h)
{
if (strcmp(h->version, VERSION) != 0) {
@@ -348,11 +670,11 @@ merge_options(struct option *oldopts, const struct option *newopts,
/* Translates errno numbers into more human-readable form than strerror. */
static const char *
-err2str(int err, enum action command)
+err2str(int err, enum ct_command command)
{
unsigned int i;
struct table_struct {
- enum action act;
+ enum ct_command act;
int err;
const char *message;
} table [] =
@@ -378,11 +700,32 @@ err2str(int err, enum action command)
return strerror(err);
}
+static int mark_cmp(const struct u32_mask *m, const struct nf_conntrack *ct)
+{
+ return nfct_attr_is_set(ct, ATTR_MARK) &&
+ (nfct_get_attr_u32(ct, ATTR_MARK) & m->mask) == m->value;
+}
+
#define PARSE_STATUS 0
#define PARSE_EVENT 1
#define PARSE_OUTPUT 2
#define PARSE_MAX 3
+enum {
+ _O_XML = (1 << 0),
+ _O_EXT = (1 << 1),
+ _O_TMS = (1 << 2),
+ _O_ID = (1 << 3),
+ _O_KTMS = (1 << 4),
+};
+
+enum {
+ CT_EVENT_F_NEW = (1 << 0),
+ CT_EVENT_F_UPD = (1 << 1),
+ CT_EVENT_F_DEL = (1 << 2),
+ CT_EVENT_F_ALL = CT_EVENT_F_NEW | CT_EVENT_F_UPD | CT_EVENT_F_DEL,
+};
+
static struct parse_parameter {
const char *parameter[6];
size_t size;
@@ -391,10 +734,9 @@ static struct parse_parameter {
{ {"ASSURED", "SEEN_REPLY", "UNSET", "FIXED_TIMEOUT", "EXPECTED"}, 5,
{ IPS_ASSURED, IPS_SEEN_REPLY, 0, IPS_FIXED_TIMEOUT, IPS_EXPECTED} },
{ {"ALL", "NEW", "UPDATES", "DESTROY"}, 4,
- {~0U, NF_NETLINK_CONNTRACK_NEW, NF_NETLINK_CONNTRACK_UPDATE,
- NF_NETLINK_CONNTRACK_DESTROY} },
- { {"xml", "extended", "timestamp", "id" }, 4,
- { _O_XML, _O_EXT, _O_TMS, _O_ID },
+ { CT_EVENT_F_ALL, CT_EVENT_F_NEW, CT_EVENT_F_UPD, CT_EVENT_F_DEL } },
+ { {"xml", "extended", "timestamp", "id", "ktimestamp"}, 5,
+ { _O_XML, _O_EXT, _O_TMS, _O_ID, _O_KTMS },
},
};
@@ -446,6 +788,19 @@ parse_parameter(const char *arg, unsigned int *status, int parse_type)
}
static void
+parse_u32_mask(const char *arg, struct u32_mask *m)
+{
+ char *end;
+
+ m->value = (uint32_t) strtoul(arg, &end, 0);
+
+ if (*end == '/')
+ m->mask = (uint32_t) strtoul(end+1, NULL, 0);
+ else
+ m->mask = ~0;
+}
+
+static void
add_command(unsigned int *cmd, const int newcmd)
{
if (*cmd)
@@ -503,8 +858,7 @@ parse_inetaddr(const char *cp, struct addr_parse *parse)
else if (inet_pton(AF_INET6, cp, &parse->addr6) > 0)
return AF_INET6;
#endif
-
- exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'", cp);
+ return AF_UNSPEC;
}
union ct_address {
@@ -526,9 +880,8 @@ parse_addr(const char *cp, union ct_address *address)
return ret;
}
-/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */
static void
-nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type)
+nat_parse(char *arg, struct nf_conntrack *obj, int type)
{
char *colon, *error;
union ct_address parse;
@@ -538,14 +891,18 @@ nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type)
if (colon) {
uint16_t port;
- if (!portok)
- exit_error(PARAMETER_PROBLEM,
- "Need TCP or UDP with port specification");
+ *colon = '\0';
port = (uint16_t)atoi(colon+1);
- if (port == 0)
- exit_error(PARAMETER_PROBLEM,
- "Port `%s' not valid", colon+1);
+ if (port == 0) {
+ if (strlen(colon+1) == 0) {
+ exit_error(PARAMETER_PROBLEM,
+ "No port specified after `:'");
+ } else {
+ exit_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid", colon+1);
+ }
+ }
error = strchr(colon+1, ':');
if (error)
@@ -553,66 +910,30 @@ nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type)
"Invalid port:port syntax");
if (type == CT_OPT_SRC_NAT)
- nfct_set_attr_u16(obj, ATTR_SNAT_PORT, port);
+ nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
else if (type == CT_OPT_DST_NAT)
- nfct_set_attr_u16(obj, ATTR_DNAT_PORT, port);
+ nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
+ else if (type == CT_OPT_ANY_NAT) {
+ nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
+ nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
+ }
}
- if (parse_addr(arg, &parse) != AF_INET)
- return;
+ if (parse_addr(arg, &parse) == AF_UNSPEC) {
+ if (strlen(arg) == 0) {
+ exit_error(PARAMETER_PROBLEM, "No IP specified");
+ } else {
+ exit_error(PARAMETER_PROBLEM,
+ "Invalid IP address `%s'", arg);
+ }
+ }
- if (type == CT_OPT_SRC_NAT)
- nfct_set_attr_u32(obj, ATTR_SNAT_IPV4, parse.v4);
- else if (type == CT_OPT_DST_NAT)
- nfct_set_attr_u32(obj, ATTR_DNAT_IPV4, parse.v4);
+ if (type == CT_OPT_SRC_NAT || type == CT_OPT_ANY_NAT)
+ nfct_set_attr_u32(tmpl.ct, ATTR_SNAT_IPV4, parse.v4);
+ else if (type == CT_OPT_DST_NAT || type == CT_OPT_ANY_NAT)
+ nfct_set_attr_u32(tmpl.ct, ATTR_DNAT_IPV4, parse.v4);
}
-static const char usage_commands[] =
- "Commands:\n"
- " -L [table] [options]\t\tList conntrack or expectation table\n"
- " -G [table] parameters\t\tGet conntrack or expectation\n"
- " -D [table] parameters\t\tDelete conntrack or expectation\n"
- " -I [table] parameters\t\tCreate a conntrack or expectation\n"
- " -U [table] parameters\t\tUpdate a conntrack\n"
- " -E [table] [options]\t\tShow events\n"
- " -F [table]\t\t\tFlush table\n"
- " -C [table]\t\t\tShow counter\n"
- " -S\t\t\t\tShow statistics\n";
-
-static const char usage_tables[] =
- "Tables: conntrack, expect\n";
-
-static const char usage_conntrack_parameters[] =
- "Conntrack parameters and options:\n"
- " -n, --src-nat ip\t\t\tsource NAT ip\n"
- " -g, --dst-nat ip\t\t\tdestination NAT ip\n"
- " -m, --mark mark\t\t\tSet mark\n"
- " -c, --secmark secmark\t\t\tSet selinux secmark\n"
- " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n"
- " -z, --zero \t\t\t\tZero counters while listing\n"
- " -o, --output type[,...]\t\tOutput format, eg. xml\n";
-
-static const char usage_expectation_parameters[] =
- "Expectation parameters and options:\n"
- " --tuple-src ip\tSource address in expect tuple\n"
- " --tuple-dst ip\tDestination address in expect tuple\n"
- " --mask-src ip\t\tSource mask address\n"
- " --mask-dst ip\t\tDestination mask address\n";
-
-static const char usage_parameters[] =
- "Common parameters and options:\n"
- " -s, --orig-src ip\t\tSource address from original direction\n"
- " -d, --orig-dst ip\t\tDestination address from original direction\n"
- " -r, --reply-src ip\t\tSource addres from reply direction\n"
- " -q, --reply-dst ip\t\tDestination address from reply direction\n"
- " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n"
- " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n"
- " -t, --timeout timeout\t\tSet timeout\n"
- " -u, --status status\t\tSet status, eg. ASSURED\n"
- " -b, --buffer-size\t\tNetlink socket buffer size\n"
- ;
-
-
static void
usage(char *prog)
{
@@ -629,41 +950,97 @@ usage(char *prog)
static unsigned int output_mask;
+
+static int
+filter_mark(const struct nf_conntrack *ct)
+{
+ if ((options & CT_OPT_MARK) &&
+ !mark_cmp(&tmpl.mark, ct))
+ return 1;
+ return 0;
+}
+
+
static int
filter_nat(const struct nf_conntrack *obj, const struct nf_conntrack *ct)
{
+ int check_srcnat = options & CT_OPT_SRC_NAT ? 1 : 0;
+ int check_dstnat = options & CT_OPT_DST_NAT ? 1 : 0;
+ int has_srcnat = 0, has_dstnat = 0;
uint32_t ip;
+ uint16_t port;
- if ((options & CT_OPT_SRC_NAT) && (options & CT_OPT_DST_NAT)) {
- if (nfct_attr_is_set(obj, ATTR_SNAT_IPV4) &&
- nfct_attr_is_set(obj, ATTR_DNAT_IPV4)) {
- uint32_t ip2;
+ if (options & CT_OPT_ANY_NAT)
+ check_srcnat = check_dstnat = 1;
+
+ if (check_srcnat) {
+ int check_address = 0, check_port = 0;
- ip = nfct_get_attr_u32(obj, ATTR_SNAT_IPV4);
- ip2 = nfct_get_attr_u32(obj, ATTR_DNAT_IPV4);
- if (ip == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST) &&
- ip2 == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC)) {
- return 0;
- }
- } else if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT) &&
- nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
- return 0;
- }
- } else if (options & CT_OPT_SRC_NAT) {
if (nfct_attr_is_set(obj, ATTR_SNAT_IPV4)) {
+ check_address = 1;
ip = nfct_get_attr_u32(obj, ATTR_SNAT_IPV4);
- if (ip == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST))
- return 0;
- } else if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT))
- return 0;
- } else if (options & CT_OPT_DST_NAT) {
+ if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT) &&
+ ip == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST))
+ has_srcnat = 1;
+ }
+ if (nfct_attr_is_set(obj, ATTR_SNAT_PORT)) {
+ int ret = 0;
+
+ check_port = 1;
+ port = nfct_get_attr_u16(obj, ATTR_SNAT_PORT);
+ if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT) &&
+ port == nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST))
+ ret = 1;
+
+ /* the address matches but the port does not. */
+ if (check_address && has_srcnat && !ret)
+ has_srcnat = 0;
+ if (!check_address && ret)
+ has_srcnat = 1;
+ }
+ if (!check_address && !check_port &&
+ (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT) ||
+ nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT)))
+ has_srcnat = 1;
+ }
+ if (check_dstnat) {
+ int check_address = 0, check_port = 0;
+
if (nfct_attr_is_set(obj, ATTR_DNAT_IPV4)) {
+ check_address = 1;
ip = nfct_get_attr_u32(obj, ATTR_DNAT_IPV4);
- if (ip == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC))
- return 0;
- } else if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT))
- return 0;
+ if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT) &&
+ ip == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC))
+ has_dstnat = 1;
+ }
+ if (nfct_attr_is_set(obj, ATTR_DNAT_PORT)) {
+ int ret = 0;
+
+ check_port = 1;
+ port = nfct_get_attr_u16(obj, ATTR_DNAT_PORT);
+ if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT) &&
+ port == nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC))
+ ret = 1;
+
+ /* the address matches but the port does not. */
+ if (check_address && has_dstnat && !ret)
+ has_dstnat = 0;
+ if (!check_address && ret)
+ has_dstnat = 1;
+ }
+ if (!check_address && !check_port &&
+ (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT) ||
+ nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT)))
+ has_dstnat = 1;
}
+ if (options & CT_OPT_ANY_NAT)
+ return !(has_srcnat || has_dstnat);
+ else if ((options & CT_OPT_SRC_NAT) && (options & CT_OPT_DST_NAT))
+ return !(has_srcnat && has_dstnat);
+ else if (options & CT_OPT_SRC_NAT)
+ return !has_srcnat;
+ else if (options & CT_OPT_DST_NAT)
+ return !has_dstnat;
return (options & (CT_OPT_SRC_NAT | CT_OPT_DST_NAT)) ? 1 : 0;
}
@@ -697,6 +1074,9 @@ static int event_cb(enum nf_conntrack_msg_type type,
if (filter_nat(obj, ct))
return NFCT_CB_CONTINUE;
+ if (filter_mark(ct))
+ return NFCT_CB_CONTINUE;
+
if (options & CT_COMPARISON &&
!nfct_cmp(obj, ct, NFCT_CMP_ALL | NFCT_CMP_MASK))
return NFCT_CB_CONTINUE;
@@ -719,6 +1099,8 @@ static int event_cb(enum nf_conntrack_msg_type type,
} else
op_flags |= NFCT_OF_TIME;
}
+ if (output_mask & _O_KTMS)
+ op_flags |= NFCT_OF_TIMESTAMP;
if (output_mask & _O_ID)
op_flags |= NFCT_OF_ID;
@@ -744,6 +1126,9 @@ static int dump_cb(enum nf_conntrack_msg_type type,
if (filter_nat(obj, ct))
return NFCT_CB_CONTINUE;
+ if (filter_mark(ct))
+ return NFCT_CB_CONTINUE;
+
if (options & CT_COMPARISON &&
!nfct_cmp(obj, ct, NFCT_CMP_ALL | NFCT_CMP_MASK))
return NFCT_CB_CONTINUE;
@@ -758,6 +1143,8 @@ static int dump_cb(enum nf_conntrack_msg_type type,
}
if (output_mask & _O_EXT)
op_flags = NFCT_OF_SHOW_LAYER3;
+ if (output_mask & _O_KTMS)
+ op_flags |= NFCT_OF_TIMESTAMP;
if (output_mask & _O_ID)
op_flags |= NFCT_OF_ID;
@@ -782,6 +1169,9 @@ static int delete_cb(enum nf_conntrack_msg_type type,
if (filter_nat(obj, ct))
return NFCT_CB_CONTINUE;
+ if (filter_mark(ct))
+ return NFCT_CB_CONTINUE;
+
if (options & CT_COMPARISON &&
!nfct_cmp(obj, ct, NFCT_CMP_ALL | NFCT_CMP_MASK))
return NFCT_CB_CONTINUE;
@@ -828,16 +1218,23 @@ static int print_cb(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static void copy_mark(struct nf_conntrack *tmp,
+ const struct nf_conntrack *ct,
+ const struct u32_mask *m)
+{
+ if (options & CT_OPT_MARK) {
+ uint32_t mark = nfct_get_attr_u32(ct, ATTR_MARK);
+ mark = (mark & ~m->mask) ^ m->value;
+ nfct_set_attr_u32(tmp, ATTR_MARK, mark);
+ }
+}
+
static int update_cb(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
{
int res;
- struct nf_conntrack *obj = data;
- char __tmp[nfct_maxsize()];
- struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp;
-
- memset(tmp, 0, sizeof(__tmp));
+ struct nf_conntrack *obj = data, *tmp;
if (filter_nat(obj, ct))
return NFCT_CB_CONTINUE;
@@ -851,30 +1248,42 @@ static int update_cb(enum nf_conntrack_msg_type type,
if (options & CT_OPT_TUPLE_REPL && !nfct_cmp(obj, ct, NFCT_CMP_REPL))
return NFCT_CB_CONTINUE;
+ tmp = nfct_new();
+ if (tmp == NULL)
+ exit_error(OTHER_PROBLEM, "out of memory");
+
nfct_copy(tmp, ct, NFCT_CP_ORIG);
nfct_copy(tmp, obj, NFCT_CP_META);
+ copy_mark(tmp, ct, &tmpl.mark);
+
+ /* do not send NFCT_Q_UPDATE if ct appears unchanged */
+ if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) {
+ nfct_destroy(tmp);
+ return NFCT_CB_CONTINUE;
+ }
res = nfct_query(ith, NFCT_Q_UPDATE, tmp);
- if (res < 0)
+ if (res < 0) {
+ nfct_destroy(tmp);
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
err2str(errno, CT_UPDATE));
-
+ }
nfct_callback_register(ith, NFCT_T_ALL, print_cb, NULL);
res = nfct_query(ith, NFCT_Q_GET, tmp);
if (res < 0) {
+ nfct_destroy(tmp);
/* the entry has vanish in middle of the update */
if (errno == ENOENT) {
nfct_callback_unregister(ith);
return NFCT_CB_CONTINUE;
}
-
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
err2str(errno, CT_UPDATE));
}
-
+ nfct_destroy(tmp);
nfct_callback_unregister(ith);
counter++;
@@ -895,6 +1304,18 @@ static int dump_exp_cb(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int event_exp_cb(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ char buf[1024];
+
+ nfexp_snprintf(buf,sizeof(buf), exp, type, NFCT_O_DEFAULT, 0);
+ printf("%s\n", buf);
+ counter++;
+
+ return NFCT_CB_CONTINUE;
+}
+
static int count_exp_cb(enum nf_conntrack_msg_type type,
struct nf_expect *exp,
void *data)
@@ -936,10 +1357,9 @@ static int display_proc_conntrack_stats(void)
/* trim off trailing \n */
nl = strchr(buf, '\n');
- if (nl != NULL) {
+ if (nl != NULL)
*nl = '\0';
- nl = strchr(buf, '\n');
- }
+
token = strtok(buf, " ");
for (i=0; token != NULL && i<CT_STATS_ENTRIES_MAX; i++) {
strncpy(output[i], token, CT_STATS_STRING_MAX);
@@ -974,66 +1394,6 @@ out_err:
static struct ctproto_handler *h;
-static const int cmd2type[][2] = {
- ['L'] = { CT_LIST, EXP_LIST },
- ['I'] = { CT_CREATE, EXP_CREATE },
- ['D'] = { CT_DELETE, EXP_DELETE },
- ['G'] = { CT_GET, EXP_GET },
- ['F'] = { CT_FLUSH, EXP_FLUSH },
- ['E'] = { CT_EVENT, EXP_EVENT },
- ['V'] = { CT_VERSION, CT_VERSION },
- ['h'] = { CT_HELP, CT_HELP },
- ['C'] = { CT_COUNT, EXP_COUNT },
-};
-
-static const int opt2type[] = {
- ['s'] = CT_OPT_ORIG_SRC,
- ['d'] = CT_OPT_ORIG_DST,
- ['r'] = CT_OPT_REPL_SRC,
- ['q'] = CT_OPT_REPL_DST,
- ['{'] = CT_OPT_MASK_SRC,
- ['}'] = CT_OPT_MASK_DST,
- ['['] = CT_OPT_EXP_SRC,
- [']'] = CT_OPT_EXP_DST,
- ['n'] = CT_OPT_SRC_NAT,
- ['g'] = CT_OPT_DST_NAT,
- ['m'] = CT_OPT_MARK,
- ['c'] = CT_OPT_SECMARK,
- ['i'] = CT_OPT_ID,
-};
-
-static const int opt2family_attr[][2] = {
- ['s'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
- ['d'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
- ['r'] = { ATTR_REPL_IPV4_SRC, ATTR_REPL_IPV6_SRC },
- ['q'] = { ATTR_REPL_IPV4_DST, ATTR_REPL_IPV6_DST },
- ['{'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
- ['}'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
- ['['] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
- [']'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
-};
-
-static const int opt2attr[] = {
- ['s'] = ATTR_ORIG_L3PROTO,
- ['d'] = ATTR_ORIG_L3PROTO,
- ['r'] = ATTR_REPL_L3PROTO,
- ['q'] = ATTR_REPL_L3PROTO,
- ['m'] = ATTR_MARK,
- ['c'] = ATTR_SECMARK,
- ['i'] = ATTR_ID,
-};
-
-static char exit_msg[NUMBER_OF_CMD][64] = {
- [CT_LIST_BIT] = "%d flow entries have been shown.\n",
- [CT_CREATE_BIT] = "%d flow entries have been created.\n",
- [CT_UPDATE_BIT] = "%d flow entries have been updated.\n",
- [CT_DELETE_BIT] = "%d flow entries have been deleted.\n",
- [CT_GET_BIT] = "%d flow entries have been shown.\n",
- [CT_EVENT_BIT] = "%d flow events have been shown.\n",
- [EXP_LIST_BIT] = "%d expectations have been shown.\n",
- [EXP_DELETE_BIT] = "%d expectations have been shown.\n",
-};
-
int main(int argc, char *argv[])
{
int c, cmd;
@@ -1041,23 +1401,13 @@ int main(int argc, char *argv[])
int res = 0, partial;
size_t socketbuffersize = 0;
int family = AF_UNSPEC;
- char __obj[nfct_maxsize()];
- char __exptuple[nfct_maxsize()];
- char __mask[nfct_maxsize()];
- struct nf_conntrack *obj = (struct nf_conntrack *)(void*) __obj;
- struct nf_conntrack *exptuple =
- (struct nf_conntrack *)(void*) __exptuple;
- struct nf_conntrack *mask = (struct nf_conntrack *)(void*) __mask;
- char __exp[nfexp_maxsize()];
- struct nf_expect *exp = (struct nf_expect *)(void*) __exp;
int l3protonum, protonum = 0;
union ct_address ad;
unsigned int command = 0;
- memset(__obj, 0, sizeof(__obj));
- memset(__exptuple, 0, sizeof(__exptuple));
- memset(__mask, 0, sizeof(__mask));
- memset(__exp, 0, sizeof(__exp));
+ /* we release these objects in the exit_error() path. */
+ if (!alloc_tmpl_objects())
+ exit_error(OTHER_PROBLEM, "out of memory");
register_tcp();
register_udp();
@@ -1072,10 +1422,7 @@ int main(int argc, char *argv[])
/* disable explicit missing arguments error output from getopt_long */
opterr = 0;
- while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:"
- "p:t:u:e:a:z[:]:{:}:m:i:f:o:n::"
- "g::c:b:C::S",
- opts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, getopt_str, opts, NULL)) != -1) {
switch(c) {
/* commands */
case 'L':
@@ -1109,17 +1456,21 @@ int main(int argc, char *argv[])
options |= opt2type[c];
l3protonum = parse_addr(optarg, &ad);
+ if (l3protonum == AF_UNSPEC) {
+ exit_error(PARAMETER_PROBLEM,
+ "Invalid IP address `%s'", optarg);
+ }
set_family(&family, l3protonum);
if (l3protonum == AF_INET) {
- nfct_set_attr_u32(obj,
+ nfct_set_attr_u32(tmpl.ct,
opt2family_attr[c][0],
ad.v4);
} else if (l3protonum == AF_INET6) {
- nfct_set_attr(obj,
+ nfct_set_attr(tmpl.ct,
opt2family_attr[c][1],
&ad.v6);
}
- nfct_set_attr_u8(obj, opt2attr[c], l3protonum);
+ nfct_set_attr_u8(tmpl.ct, opt2attr[c], l3protonum);
break;
case '{':
case '}':
@@ -1127,17 +1478,22 @@ int main(int argc, char *argv[])
case ']':
options |= opt2type[c];
l3protonum = parse_addr(optarg, &ad);
+ if (l3protonum == AF_UNSPEC) {
+ exit_error(PARAMETER_PROBLEM,
+ "Invalid IP address `%s'", optarg);
+ }
set_family(&family, l3protonum);
if (l3protonum == AF_INET) {
- nfct_set_attr_u32(mask,
+ nfct_set_attr_u32(tmpl.mask,
opt2family_attr[c][0],
ad.v4);
} else if (l3protonum == AF_INET6) {
- nfct_set_attr(mask,
+ nfct_set_attr(tmpl.mask,
opt2family_attr[c][1],
&ad.v6);
}
- nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
+ nfct_set_attr_u8(tmpl.mask,
+ ATTR_ORIG_L3PROTO, l3protonum);
break;
case 'p':
options |= CT_OPT_PROTO;
@@ -1151,17 +1507,18 @@ int main(int argc, char *argv[])
if (opts == NULL)
exit_error(OTHER_PROBLEM, "out of memory");
- nfct_set_attr_u8(obj, ATTR_L4PROTO, protonum);
+ nfct_set_attr_u8(tmpl.ct, ATTR_L4PROTO, protonum);
break;
case 't':
options |= CT_OPT_TIMEOUT;
- nfct_set_attr_u32(obj, ATTR_TIMEOUT, atol(optarg));
- nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, atol(optarg));
+ nfct_set_attr_u32(tmpl.ct, ATTR_TIMEOUT, atol(optarg));
+ nfexp_set_attr_u32(tmpl.exp,
+ ATTR_EXP_TIMEOUT, atol(optarg));
break;
case 'u':
options |= CT_OPT_STATUS;
parse_parameter(optarg, &status, PARSE_STATUS);
- nfct_set_attr_u32(obj, ATTR_STATUS, status);
+ nfct_set_attr_u32(tmpl.ct, ATTR_STATUS, status);
break;
case 'e':
options |= CT_OPT_EVENT_MASK;
@@ -1175,7 +1532,8 @@ int main(int argc, char *argv[])
options |= CT_OPT_ZERO;
break;
case 'n':
- case 'g': {
+ case 'g':
+ case 'j': {
char *tmp = NULL;
options |= opt2type[c];
@@ -1190,17 +1548,26 @@ int main(int argc, char *argv[])
continue;
set_family(&family, AF_INET);
- nat_parse(tmp, 1, obj, opt2type[c]);
+ nat_parse(tmp, tmpl.ct, opt2type[c]);
break;
}
+ case 'w':
+ options |= opt2type[c];
+ nfct_set_attr_u16(tmpl.ct,
+ opt2attr[c],
+ strtoul(optarg, NULL, 0));
+ break;
case 'i':
- case 'm':
case 'c':
options |= opt2type[c];
- nfct_set_attr_u32(obj,
+ nfct_set_attr_u32(tmpl.ct,
opt2attr[c],
strtoul(optarg, NULL, 0));
break;
+ case 'm':
+ options |= opt2type[c];
+ parse_u32_mask(optarg, &tmpl.mark);
+ break;
case 'a':
fprintf(stderr, "WARNING: ignoring -%c, "
"deprecated option.\n", c);
@@ -1232,8 +1599,9 @@ int main(int argc, char *argv[])
break;
default:
if (h && h->parse_opts
- &&!h->parse_opts(c - h->option_offset, obj,
- exptuple, mask, &l4flags))
+ &&!h->parse_opts(c - h->option_offset, tmpl.ct,
+ tmpl.exptuple, tmpl.mask,
+ &l4flags))
exit_error(PARAMETER_PROBLEM, "parse error");
break;
}
@@ -1243,6 +1611,12 @@ int main(int argc, char *argv[])
if (family == AF_UNSPEC)
family = AF_INET;
+ /* we cannot check this combination with generic_opt_check. */
+ if (options & CT_OPT_ANY_NAT &&
+ ((options & CT_OPT_SRC_NAT) || (options & CT_OPT_DST_NAT))) {
+ exit_error(PARAMETER_PROBLEM, "cannot specify `--src-nat' or "
+ "`--dst-nat' with `--any-nat'");
+ }
cmd = bit2cmd(command);
res = generic_opt_check(options, NUMBER_OF_OPT,
commands_v_options[cmd], optflags,
@@ -1263,7 +1637,7 @@ int main(int argc, char *argv[])
}
}
if (!(command & CT_HELP) && h && h->final_check)
- h->final_check(l4flags, cmd, obj);
+ h->final_check(l4flags, cmd, tmpl.ct);
switch(command) {
@@ -1277,7 +1651,7 @@ int main(int argc, char *argv[])
exit_error(PARAMETER_PROBLEM, "Can't use -z with "
"filtering parameters");
- nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, tmpl.ct);
if (options & CT_OPT_ZERO)
res = nfct_query(cth, NFCT_Q_DUMP_RESET, &family);
@@ -1304,30 +1678,33 @@ int main(int argc, char *argv[])
case CT_CREATE:
if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL))
- nfct_setobjopt(obj, NFCT_SOPT_SETUP_REPLY);
+ nfct_setobjopt(tmpl.ct, NFCT_SOPT_SETUP_REPLY);
else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL))
- nfct_setobjopt(obj, NFCT_SOPT_SETUP_ORIGINAL);
+ nfct_setobjopt(tmpl.ct, NFCT_SOPT_SETUP_ORIGINAL);
+
+ if (options & CT_OPT_MARK)
+ nfct_set_attr_u32(tmpl.ct, ATTR_MARK, tmpl.mark.value);
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfct_query(cth, NFCT_Q_CREATE, obj);
+ res = nfct_query(cth, NFCT_Q_CREATE, tmpl.ct);
if (res != -1)
counter++;
nfct_close(cth);
break;
case EXP_CREATE:
- nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
- nfexp_set_attr(exp, ATTR_EXP_EXPECTED, exptuple);
- nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASTER, tmpl.ct);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_EXPECTED, tmpl.exptuple);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASK, tmpl.mask);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfexp_query(cth, NFCT_Q_CREATE, exp);
+ res = nfexp_query(cth, NFCT_Q_CREATE, tmpl.exp);
nfct_close(cth);
break;
@@ -1338,7 +1715,7 @@ int main(int argc, char *argv[])
if (!cth || !ith)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, update_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, update_cb, tmpl.ct);
res = nfct_query(cth, NFCT_Q_DUMP, &family);
nfct_close(ith);
@@ -1351,7 +1728,7 @@ int main(int argc, char *argv[])
if (!cth || !ith)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, delete_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, delete_cb, tmpl.ct);
res = nfct_query(cth, NFCT_Q_DUMP, &family);
nfct_close(ith);
@@ -1359,13 +1736,13 @@ int main(int argc, char *argv[])
break;
case EXP_DELETE:
- nfexp_set_attr(exp, ATTR_EXP_EXPECTED, obj);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_EXPECTED, tmpl.ct);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfexp_query(cth, NFCT_Q_DESTROY, exp);
+ res = nfexp_query(cth, NFCT_Q_DESTROY, tmpl.exp);
nfct_close(cth);
break;
@@ -1374,20 +1751,20 @@ int main(int argc, char *argv[])
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
- res = nfct_query(cth, NFCT_Q_GET, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, tmpl.ct);
+ res = nfct_query(cth, NFCT_Q_GET, tmpl.ct);
nfct_close(cth);
break;
case EXP_GET:
- nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASTER, tmpl.ct);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
- res = nfexp_query(cth, NFCT_Q_GET, exp);
+ res = nfexp_query(cth, NFCT_Q_GET, tmpl.exp);
nfct_close(cth);
break;
@@ -1407,14 +1784,28 @@ int main(int argc, char *argv[])
exit_error(OTHER_PROBLEM, "Can't open handler");
res = nfexp_query(cth, NFCT_Q_FLUSH, &family);
nfct_close(cth);
+ fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION);
+ fprintf(stderr,"expectation table has been emptied.\n");
break;
case CT_EVENT:
- if (options & CT_OPT_EVENT_MASK)
+ if (options & CT_OPT_EVENT_MASK) {
+ unsigned int nl_events = 0;
+
+ if (event_mask & CT_EVENT_F_NEW)
+ nl_events |= NF_NETLINK_CONNTRACK_NEW;
+ if (event_mask & CT_EVENT_F_UPD)
+ nl_events |= NF_NETLINK_CONNTRACK_UPDATE;
+ if (event_mask & CT_EVENT_F_DEL)
+ nl_events |= NF_NETLINK_CONNTRACK_DESTROY;
+
+ cth = nfct_open(CONNTRACK, nl_events);
+ } else {
cth = nfct_open(CONNTRACK,
- event_mask & NFCT_ALL_CT_GROUPS);
- else
- cth = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
+ NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY);
+ }
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
@@ -1427,7 +1818,7 @@ int main(int argc, char *argv[])
}
signal(SIGINT, event_sighandler);
signal(SIGTERM, event_sighandler);
- nfct_callback_register(cth, NFCT_T_ALL, event_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, event_cb, tmpl.ct);
res = nfct_catch(cth);
if (res == -1) {
if (errno == ENOBUFS) {
@@ -1444,12 +1835,29 @@ int main(int argc, char *argv[])
break;
case EXP_EVENT:
- cth = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW);
+ if (options & CT_OPT_EVENT_MASK) {
+ unsigned int nl_events = 0;
+
+ if (event_mask & CT_EVENT_F_NEW)
+ nl_events |= NF_NETLINK_CONNTRACK_EXP_NEW;
+ if (event_mask & CT_EVENT_F_UPD)
+ nl_events |= NF_NETLINK_CONNTRACK_EXP_UPDATE;
+ if (event_mask & CT_EVENT_F_DEL)
+ nl_events |= NF_NETLINK_CONNTRACK_EXP_DESTROY;
+
+ cth = nfct_open(CONNTRACK, nl_events);
+ } else {
+ cth = nfct_open(EXPECT,
+ NF_NETLINK_CONNTRACK_EXP_NEW |
+ NF_NETLINK_CONNTRACK_EXP_UPDATE |
+ NF_NETLINK_CONNTRACK_EXP_DESTROY);
+ }
+
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
signal(SIGINT, event_sighandler);
signal(SIGTERM, event_sighandler);
- nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
+ nfexp_callback_register(cth, NFCT_T_ALL, event_exp_cb, NULL);
res = nfexp_catch(cth);
nfct_close(cth);
break;
@@ -1501,6 +1909,7 @@ int main(int argc, char *argv[])
exit_error(OTHER_PROBLEM, "Operation failed: %s",
err2str(errno, command));
+ free_tmpl_objects();
free_options();
if (command && exit_msg[cmd][0]) {
diff --git a/src/external_cache.c b/src/external_cache.c
index c70c818..e290249 100644
--- a/src/external_cache.c
+++ b/src/external_cache.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -25,25 +26,35 @@
#include <stdlib.h>
static struct cache *external;
+static struct cache *external_exp;
static int external_cache_init(void)
{
- external = cache_create("external",
+ external = cache_create("external", CACHE_T_CT,
STATE_SYNC(sync)->external_cache_flags,
- NULL);
+ NULL, &cache_sync_external_ct_ops);
if (external == NULL) {
dlog(LOG_ERR, "can't allocate memory for the external cache");
return -1;
}
+ external_exp = cache_create("external", CACHE_T_EXP,
+ STATE_SYNC(sync)->external_cache_flags,
+ NULL, &cache_sync_external_exp_ops);
+ if (external_exp == NULL) {
+ dlog(LOG_ERR, "can't allocate memory for the external cache");
+ return -1;
+ }
+
return 0;
}
static void external_cache_close(void)
{
cache_destroy(external);
+ cache_destroy(external_exp);
}
-static void external_cache_new(struct nf_conntrack *ct)
+static void external_cache_ct_new(struct nf_conntrack *ct)
{
struct cache_object *obj;
int id;
@@ -66,12 +77,12 @@ retry:
}
}
-static void external_cache_upd(struct nf_conntrack *ct)
+static void external_cache_ct_upd(struct nf_conntrack *ct)
{
cache_update_force(external, ct);
}
-static void external_cache_del(struct nf_conntrack *ct)
+static void external_cache_ct_del(struct nf_conntrack *ct)
{
struct cache_object *obj;
int id;
@@ -83,40 +94,117 @@ static void external_cache_del(struct nf_conntrack *ct)
}
}
-static void external_cache_dump(int fd, int type)
+static void external_cache_ct_dump(int fd, int type)
{
cache_dump(external, fd, type);
}
-static void external_cache_commit(struct nfct_handle *h, int fd)
+static int external_cache_ct_commit(struct nfct_handle *h, int fd)
{
- cache_commit(external, h, fd);
+ return cache_commit(external, h, fd);
}
-static void external_cache_flush(void)
+static void external_cache_ct_flush(void)
{
cache_flush(external);
}
-static void external_cache_stats(int fd)
+static void external_cache_ct_stats(int fd)
{
cache_stats(external, fd);
}
-static void external_cache_stats_ext(int fd)
+static void external_cache_ct_stats_ext(int fd)
{
cache_stats_extended(external, fd);
}
+static void external_cache_exp_new(struct nf_expect *exp)
+{
+ struct cache_object *obj;
+ int id;
+
+ obj = cache_find(external_exp, exp, &id);
+ if (obj == NULL) {
+retry:
+ obj = cache_object_new(external_exp, exp);
+ if (obj == NULL)
+ return;
+
+ if (cache_add(external_exp, obj, id) == -1) {
+ cache_object_free(obj);
+ return;
+ }
+ } else {
+ cache_del(external_exp, obj);
+ cache_object_free(obj);
+ goto retry;
+ }
+}
+
+static void external_cache_exp_upd(struct nf_expect *exp)
+{
+ cache_update_force(external_exp, exp);
+}
+
+static void external_cache_exp_del(struct nf_expect *exp)
+{
+ struct cache_object *obj;
+ int id;
+
+ obj = cache_find(external_exp, exp, &id);
+ if (obj) {
+ cache_del(external_exp, obj);
+ cache_object_free(obj);
+ }
+}
+
+static void external_cache_exp_dump(int fd, int type)
+{
+ cache_dump(external_exp, fd, type);
+}
+
+static int external_cache_exp_commit(struct nfct_handle *h, int fd)
+{
+ return cache_commit(external_exp, h, fd);
+}
+
+static void external_cache_exp_flush(void)
+{
+ cache_flush(external_exp);
+}
+
+static void external_cache_exp_stats(int fd)
+{
+ cache_stats(external_exp, fd);
+}
+
+static void external_cache_exp_stats_ext(int fd)
+{
+ cache_stats_extended(external_exp, fd);
+}
+
struct external_handler external_cache = {
.init = external_cache_init,
.close = external_cache_close,
- .new = external_cache_new,
- .update = external_cache_upd,
- .destroy = external_cache_del,
- .dump = external_cache_dump,
- .commit = external_cache_commit,
- .flush = external_cache_flush,
- .stats = external_cache_stats,
- .stats_ext = external_cache_stats_ext,
+ .ct = {
+ .new = external_cache_ct_new,
+ .upd = external_cache_ct_upd,
+ .del = external_cache_ct_del,
+ .dump = external_cache_ct_dump,
+ .commit = external_cache_ct_commit,
+ .flush = external_cache_ct_flush,
+ .stats = external_cache_ct_stats,
+ .stats_ext = external_cache_ct_stats_ext,
+ },
+ .exp = {
+ .new = external_cache_exp_new,
+ .upd = external_cache_exp_upd,
+ .del = external_cache_exp_del,
+ .dump = external_cache_exp_dump,
+ .commit = external_cache_exp_commit,
+ .flush = external_cache_exp_flush,
+ .stats = external_cache_exp_stats,
+ .stats_ext = external_cache_exp_stats_ext,
+ },
};
diff --git a/src/external_inject.c b/src/external_inject.c
index a54bb13..0ad3478 100644
--- a/src/external_inject.c
+++ b/src/external_inject.c
@@ -1,6 +1,7 @@
/*
- * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -41,7 +42,7 @@ struct {
static int external_inject_init(void)
{
/* handler to directly inject conntracks into kernel-space */
- inject = nfct_open(CONNTRACK, 0);
+ inject = nfct_open(CONFIG(netlink).subsys_id, 0);
if (inject == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -59,7 +60,7 @@ static void external_inject_close(void)
nfct_close(inject);
}
-static void external_inject_new(struct nf_conntrack *ct)
+static void external_inject_ct_new(struct nf_conntrack *ct)
{
int ret, retry = 1;
@@ -87,7 +88,7 @@ retry:
}
}
-static void external_inject_upd(struct nf_conntrack *ct)
+static void external_inject_ct_upd(struct nf_conntrack *ct)
{
int ret;
@@ -128,7 +129,7 @@ static void external_inject_upd(struct nf_conntrack *ct)
dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
}
-static void external_inject_del(struct nf_conntrack *ct)
+static void external_inject_ct_del(struct nf_conntrack *ct)
{
if (nl_destroy_conntrack(inject, ct) == -1) {
if (errno != ENOENT) {
@@ -141,19 +142,21 @@ static void external_inject_del(struct nf_conntrack *ct)
}
}
-static void external_inject_dump(int fd, int type)
+static void external_inject_ct_dump(int fd, int type)
{
}
-static void external_inject_commit(struct nfct_handle *h, int fd)
+static int external_inject_ct_commit(struct nfct_handle *h, int fd)
{
+ /* close the commit socket. */
+ return LOCAL_RET_OK;
}
-static void external_inject_flush(void)
+static void external_inject_ct_flush(void)
{
}
-static void external_inject_stats(int fd)
+static void external_inject_ct_stats(int fd)
{
char buf[512];
int size;
@@ -172,15 +175,110 @@ static void external_inject_stats(int fd)
send(fd, buf, size, 0);
}
+struct {
+ uint32_t add_ok;
+ uint32_t add_fail;
+ uint32_t upd_ok;
+ uint32_t upd_fail;
+ uint32_t del_ok;
+ uint32_t del_fail;
+} exp_external_inject_stat;
+
+static void external_inject_exp_new(struct nf_expect *exp)
+{
+ int ret, retry = 1;
+
+retry:
+ if (nl_create_expect(inject, exp, 0) == -1) {
+ /* if the state entry exists, we delete and try again */
+ if (errno == EEXIST && retry == 1) {
+ ret = nl_destroy_expect(inject, exp);
+ if (ret == 0 || (ret == -1 && errno == ENOENT)) {
+ if (retry) {
+ retry = 0;
+ goto retry;
+ }
+ }
+ exp_external_inject_stat.add_fail++;
+ dlog(LOG_ERR, "inject-add1: %s", strerror(errno));
+ dlog_exp(STATE(log), exp, NFCT_O_PLAIN);
+ return;
+ }
+ exp_external_inject_stat.add_fail++;
+ dlog(LOG_ERR, "inject-add2: %s", strerror(errno));
+ dlog_exp(STATE(log), exp, NFCT_O_PLAIN);
+ } else {
+ exp_external_inject_stat.add_ok++;
+ }
+}
+
+static void external_inject_exp_del(struct nf_expect *exp)
+{
+ if (nl_destroy_expect(inject, exp) == -1) {
+ if (errno != ENOENT) {
+ exp_external_inject_stat.del_fail++;
+ dlog(LOG_ERR, "inject-del: %s", strerror(errno));
+ dlog_exp(STATE(log), exp, NFCT_O_PLAIN);
+ }
+ } else {
+ exp_external_inject_stat.del_ok++;
+ }
+}
+
+static void external_inject_exp_dump(int fd, int type)
+{
+}
+
+static int external_inject_exp_commit(struct nfct_handle *h, int fd)
+{
+ /* close the commit socket. */
+ return LOCAL_RET_OK;
+}
+
+static void external_inject_exp_flush(void)
+{
+}
+
+static void external_inject_exp_stats(int fd)
+{
+ char buf[512];
+ int size;
+
+ size = sprintf(buf, "external inject:\n"
+ "connections created:\t\t%12u\tfailed:\t%12u\n"
+ "connections updated:\t\t%12u\tfailed:\t%12u\n"
+ "connections destroyed:\t\t%12u\tfailed:\t%12u\n\n",
+ exp_external_inject_stat.add_ok,
+ exp_external_inject_stat.add_fail,
+ exp_external_inject_stat.upd_ok,
+ exp_external_inject_stat.upd_fail,
+ exp_external_inject_stat.del_ok,
+ exp_external_inject_stat.del_fail);
+
+ send(fd, buf, size, 0);
+}
+
struct external_handler external_inject = {
.init = external_inject_init,
.close = external_inject_close,
- .new = external_inject_new,
- .update = external_inject_upd,
- .destroy = external_inject_del,
- .dump = external_inject_dump,
- .commit = external_inject_commit,
- .flush = external_inject_flush,
- .stats = external_inject_stats,
- .stats_ext = external_inject_stats,
+ .ct = {
+ .new = external_inject_ct_new,
+ .upd = external_inject_ct_upd,
+ .del = external_inject_ct_del,
+ .dump = external_inject_ct_dump,
+ .commit = external_inject_ct_commit,
+ .flush = external_inject_ct_flush,
+ .stats = external_inject_ct_stats,
+ .stats_ext = external_inject_ct_stats,
+ },
+ .exp = {
+ .new = external_inject_exp_new,
+ .upd = external_inject_exp_new,
+ .del = external_inject_exp_del,
+ .dump = external_inject_exp_dump,
+ .commit = external_inject_exp_commit,
+ .flush = external_inject_exp_flush,
+ .stats = external_inject_exp_stats,
+ .stats_ext = external_inject_exp_stats,
+ },
};
diff --git a/src/filter.c b/src/filter.c
index 6a09c77..e8515d6 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -235,7 +235,7 @@ void ct_filter_add_state(struct ct_filter *f, int protonum, int val)
}
static inline int
-__ct_filter_test_ipv4(struct ct_filter *f, struct nf_conntrack *ct)
+__ct_filter_test_ipv4(struct ct_filter *f, const struct nf_conntrack *ct)
{
int id_src, id_dst;
uint32_t src, dst;
@@ -252,7 +252,7 @@ __ct_filter_test_ipv4(struct ct_filter *f, struct nf_conntrack *ct)
}
static inline int
-__ct_filter_test_ipv6(struct ct_filter *f, struct nf_conntrack *ct)
+__ct_filter_test_ipv6(struct ct_filter *f, const struct nf_conntrack *ct)
{
int id_src, id_dst;
const uint32_t *src, *dst;
@@ -295,7 +295,8 @@ __ct_filter_test_mask6(const void *ptr, const void *ct)
(elem->ip[3] & elem->mask[3]) == (dst[3] & elem->mask[3])));
}
-static int __ct_filter_test_state(struct ct_filter *f, struct nf_conntrack *ct)
+static int
+__ct_filter_test_state(struct ct_filter *f, const struct nf_conntrack *ct)
{
uint16_t val = 0;
uint8_t protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO);
@@ -314,7 +315,8 @@ static int __ct_filter_test_state(struct ct_filter *f, struct nf_conntrack *ct)
return test_bit_u16(val, &f->statemap[protonum]);
}
-static int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct)
+static int
+ct_filter_check(struct ct_filter *f, const struct nf_conntrack *ct)
{
int ret, protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO);
@@ -361,7 +363,7 @@ static int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct)
return 1;
}
-static inline int ct_filter_sanity_check(struct nf_conntrack *ct)
+static inline int ct_filter_sanity_check(const struct nf_conntrack *ct)
{
if (!nfct_attr_is_set(ct, ATTR_L3PROTO)) {
dlog(LOG_ERR, "missing layer 3 protocol");
@@ -371,9 +373,7 @@ static inline int ct_filter_sanity_check(struct nf_conntrack *ct)
switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
case AF_INET:
if (!nfct_attr_is_set(ct, ATTR_IPV4_SRC) ||
- !nfct_attr_is_set(ct, ATTR_IPV4_DST) ||
- !nfct_attr_is_set(ct, ATTR_REPL_IPV4_SRC) ||
- !nfct_attr_is_set(ct, ATTR_REPL_IPV4_DST)) {
+ !nfct_attr_is_set(ct, ATTR_IPV4_DST)) {
dlog(LOG_ERR, "missing IPv4 address. "
"You forgot to load "
"nf_conntrack_ipv4?");
@@ -382,9 +382,7 @@ static inline int ct_filter_sanity_check(struct nf_conntrack *ct)
break;
case AF_INET6:
if (!nfct_attr_is_set(ct, ATTR_IPV6_SRC) ||
- !nfct_attr_is_set(ct, ATTR_IPV6_DST) ||
- !nfct_attr_is_set(ct, ATTR_REPL_IPV6_SRC) ||
- !nfct_attr_is_set(ct, ATTR_REPL_IPV6_DST)) {
+ !nfct_attr_is_set(ct, ATTR_IPV6_DST)) {
dlog(LOG_ERR, "missing IPv6 address. "
"You forgot to load "
"nf_conntrack_ipv6?");
@@ -396,7 +394,7 @@ static inline int ct_filter_sanity_check(struct nf_conntrack *ct)
}
/* we do user-space filtering for dump and resyncs */
-int ct_filter_conntrack(struct nf_conntrack *ct, int userspace)
+int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace)
{
/* missing mandatory attributes in object */
if (!ct_filter_sanity_check(ct))
@@ -407,3 +405,79 @@ int ct_filter_conntrack(struct nf_conntrack *ct, int userspace)
return 0;
}
+
+struct exp_filter {
+ struct list_head list;
+};
+
+struct exp_filter *exp_filter_create(void)
+{
+ struct exp_filter *f;
+
+ f = calloc(1, sizeof(struct exp_filter));
+ if (f == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&f->list);
+ return f;
+}
+
+struct exp_filter_item {
+ struct list_head head;
+ char helper_name[NFCT_HELPER_NAME_MAX];
+};
+
+/* this is ugly, but it simplifies read_config_yy.y */
+static struct exp_filter *exp_filter_alloc(void)
+{
+ if (STATE(exp_filter) == NULL) {
+ STATE(exp_filter) = exp_filter_create();
+ if (STATE(exp_filter) == NULL) {
+ fprintf(stderr, "Can't init expectation filtering!\n");
+ return NULL;
+ }
+ }
+ return STATE(exp_filter);;
+}
+
+int exp_filter_add(struct exp_filter *f, const char *helper_name)
+{
+ struct exp_filter_item *item;
+
+ f = exp_filter_alloc();
+ if (f == NULL)
+ return -1;
+
+ list_for_each_entry(item, &f->list, head) {
+ if (strncmp(item->helper_name, helper_name,
+ NFCT_HELPER_NAME_MAX) == 0) {
+ return -1;
+ }
+ }
+ item = calloc(1, sizeof(struct exp_filter_item));
+ if (item == NULL)
+ return -1;
+
+ strncpy(item->helper_name, helper_name, NFCT_HELPER_NAME_MAX);
+ list_add(&item->head, &f->list);
+ return 0;
+}
+
+int exp_filter_find(struct exp_filter *f, const struct nf_expect *exp)
+{
+ struct exp_filter_item *item;
+
+ if (f == NULL)
+ return 0;
+
+ list_for_each_entry(item, &f->list, head) {
+ const char *name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME);
+
+ /* we allow partial matching to support things like sip-PORT. */
+ if (strncmp(item->helper_name, name,
+ strlen(item->helper_name)) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/src/internal_bypass.c b/src/internal_bypass.c
index 4caaf4f..5c83c21 100644
--- a/src/internal_bypass.c
+++ b/src/internal_bypass.c
@@ -1,6 +1,7 @@
/*
- * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -16,21 +17,25 @@
#include "network.h"
#include "origin.h"
-static int _init(void)
+static int internal_bypass_init(void)
{
return 0;
}
-static void _close(void)
+static void internal_bypass_close(void)
{
}
-static int dump_cb(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct, void *data)
+static int
+internal_bypass_ct_dump_cb(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct, void *data)
{
char buf[1024];
int size, *fd = data;
+ if (ct_filter_conntrack(ct, 1))
+ return NFCT_CB_CONTINUE;
+
size = nfct_snprintf(buf, 1024, ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
if (size < 1024) {
buf[size] = '\n';
@@ -41,18 +46,18 @@ static int dump_cb(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
-static void dump(int fd, int type)
+static void internal_bypass_ct_dump(int fd, int type)
{
struct nfct_handle *h;
u_int32_t family = AF_UNSPEC;
int ret;
- h = nfct_open(CONNTRACK, 0);
+ h = nfct_open(CONFIG(netlink).subsys_id, 0);
if (h == NULL) {
dlog(LOG_ERR, "can't allocate memory for the internal cache");
return;
}
- nfct_callback_register(h, NFCT_T_ALL, dump_cb, &fd);
+ nfct_callback_register(h, NFCT_T_ALL, internal_bypass_ct_dump_cb, &fd);
ret = nfct_query(h, NFCT_Q_DUMP, &family);
if (ret == -1) {
dlog(LOG_ERR, "can't dump kernel table");
@@ -60,7 +65,7 @@ static void dump(int fd, int type)
nfct_close(h);
}
-static void flush(void)
+static void internal_bypass_ct_flush(void)
{
nl_flush_conntrack_table(STATE(flush));
}
@@ -71,7 +76,7 @@ struct {
uint32_t del;
} internal_bypass_stats;
-static void stats(int fd)
+static void internal_bypass_ct_stats(int fd)
{
char buf[512];
int size;
@@ -88,25 +93,24 @@ static void stats(int fd)
}
/* unused, INTERNAL_F_POPULATE is unset. No cache, nothing to populate. */
-static void populate(struct nf_conntrack *ct)
+static void internal_bypass_ct_populate(struct nf_conntrack *ct)
{
}
/* unused, INTERNAL_F_RESYNC is unset. */
-static void purge(void)
+static void internal_bypass_ct_purge(void)
{
}
/* unused, INTERNAL_F_RESYNC is unset. Nothing to resync, we have no cache. */
-static int resync(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
+static int
+internal_bypass_ct_resync(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct, void *data)
{
return NFCT_CB_CONTINUE;
}
-static void
-event_new_sync(struct nf_conntrack *ct, int origin)
+static void internal_bypass_ct_event_new(struct nf_conntrack *ct, int origin)
{
struct nethdr *net;
@@ -114,13 +118,12 @@ event_new_sync(struct nf_conntrack *ct, int origin)
if (origin != CTD_ORIGIN_NOT_ME)
return;
- net = BUILD_NETMSG(ct, NET_T_STATE_NEW);
+ net = BUILD_NETMSG_FROM_CT(ct, NET_T_STATE_CT_NEW);
multichannel_send(STATE_SYNC(channel), net);
internal_bypass_stats.new++;
}
-static void
-event_update_sync(struct nf_conntrack *ct, int origin)
+static void internal_bypass_ct_event_upd(struct nf_conntrack *ct, int origin)
{
struct nethdr *net;
@@ -128,13 +131,12 @@ event_update_sync(struct nf_conntrack *ct, int origin)
if (origin != CTD_ORIGIN_NOT_ME)
return;
- net = BUILD_NETMSG(ct, NET_T_STATE_UPD);
+ net = BUILD_NETMSG_FROM_CT(ct, NET_T_STATE_CT_UPD);
multichannel_send(STATE_SYNC(channel), net);
internal_bypass_stats.upd++;
}
-static int
-event_destroy_sync(struct nf_conntrack *ct, int origin)
+static int internal_bypass_ct_event_del(struct nf_conntrack *ct, int origin)
{
struct nethdr *net;
@@ -142,24 +144,170 @@ event_destroy_sync(struct nf_conntrack *ct, int origin)
if (origin != CTD_ORIGIN_NOT_ME)
return 1;
- net = BUILD_NETMSG(ct, NET_T_STATE_DEL);
+ net = BUILD_NETMSG_FROM_CT(ct, NET_T_STATE_CT_DEL);
multichannel_send(STATE_SYNC(channel), net);
internal_bypass_stats.del++;
return 1;
}
+static int
+internal_bypass_exp_dump_cb(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ char buf[1024];
+ int size, *fd = data;
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ size = nfexp_snprintf(buf, 1024, exp,
+ NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
+ if (size < 1024) {
+ buf[size] = '\n';
+ size++;
+ }
+ send(*fd, buf, size, 0);
+
+ return NFCT_CB_CONTINUE;
+}
+
+static void internal_bypass_exp_dump(int fd, int type)
+{
+ struct nfct_handle *h;
+ u_int32_t family = AF_UNSPEC;
+ int ret;
+
+ h = nfct_open(CONFIG(netlink).subsys_id, 0);
+ if (h == NULL) {
+ dlog(LOG_ERR, "can't allocate memory for the internal cache");
+ return;
+ }
+ nfexp_callback_register(h, NFCT_T_ALL,
+ internal_bypass_exp_dump_cb, &fd);
+ ret = nfexp_query(h, NFCT_Q_DUMP, &family);
+ if (ret == -1) {
+ dlog(LOG_ERR, "can't dump kernel table");
+ }
+ nfct_close(h);
+}
+
+static void internal_bypass_exp_flush(void)
+{
+ nl_flush_expect_table(STATE(flush));
+}
+
+struct {
+ uint32_t new;
+ uint32_t upd;
+ uint32_t del;
+} exp_internal_bypass_stats;
+
+static void internal_bypass_exp_stats(int fd)
+{
+ char buf[512];
+ int size;
+
+ size = sprintf(buf, "internal bypass:\n"
+ "connections new:\t\t%12u\n"
+ "connections updated:\t\t%12u\n"
+ "connections destroyed:\t\t%12u\n\n",
+ exp_internal_bypass_stats.new,
+ exp_internal_bypass_stats.upd,
+ exp_internal_bypass_stats.del);
+
+ send(fd, buf, size, 0);
+}
+
+/* unused, INTERNAL_F_POPULATE is unset. No cache, nothing to populate. */
+static void internal_bypass_exp_populate(struct nf_expect *exp)
+{
+}
+
+/* unused, INTERNAL_F_RESYNC is unset. */
+static void internal_bypass_exp_purge(void)
+{
+}
+
+/* unused, INTERNAL_F_RESYNC is unset. Nothing to resync, we have no cache. */
+static int
+internal_bypass_exp_resync(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ return NFCT_CB_CONTINUE;
+}
+
+static void internal_bypass_exp_event_new(struct nf_expect *exp, int origin)
+{
+ struct nethdr *net;
+
+ /* this event has been triggered by me, skip */
+ if (origin != CTD_ORIGIN_NOT_ME)
+ return;
+
+ net = BUILD_NETMSG_FROM_EXP(exp, NET_T_STATE_EXP_NEW);
+ multichannel_send(STATE_SYNC(channel), net);
+ exp_internal_bypass_stats.new++;
+}
+
+static void internal_bypass_exp_event_upd(struct nf_expect *exp, int origin)
+{
+ struct nethdr *net;
+
+ /* this event has been triggered by me, skip */
+ if (origin != CTD_ORIGIN_NOT_ME)
+ return;
+
+ net = BUILD_NETMSG_FROM_EXP(exp, NET_T_STATE_EXP_UPD);
+ multichannel_send(STATE_SYNC(channel), net);
+ exp_internal_bypass_stats.upd++;
+}
+
+static int internal_bypass_exp_event_del(struct nf_expect *exp, int origin)
+{
+ struct nethdr *net;
+
+ /* this event has been triggered by me, skip */
+ if (origin != CTD_ORIGIN_NOT_ME)
+ return 1;
+
+ net = BUILD_NETMSG_FROM_EXP(exp, NET_T_STATE_EXP_DEL);
+ multichannel_send(STATE_SYNC(channel), net);
+ exp_internal_bypass_stats.del++;
+
+ return 1;
+}
+
struct internal_handler internal_bypass = {
- .init = _init,
- .close = _close,
- .dump = dump,
- .flush = flush,
- .stats = stats,
- .stats_ext = stats,
- .populate = populate,
- .purge = purge,
- .resync = resync,
- .new = event_new_sync,
- .update = event_update_sync,
- .destroy = event_destroy_sync,
+ .init = internal_bypass_init,
+ .close = internal_bypass_close,
+ .ct = {
+ .dump = internal_bypass_ct_dump,
+ .flush = internal_bypass_ct_flush,
+ .stats = internal_bypass_ct_stats,
+ .stats_ext = internal_bypass_ct_stats,
+ .populate = internal_bypass_ct_populate,
+ .purge = internal_bypass_ct_purge,
+ .resync = internal_bypass_ct_resync,
+ .new = internal_bypass_ct_event_new,
+ .upd = internal_bypass_ct_event_upd,
+ .del = internal_bypass_ct_event_del,
+ },
+ .exp = {
+ .dump = internal_bypass_exp_dump,
+ .flush = internal_bypass_exp_flush,
+ .stats = internal_bypass_exp_stats,
+ .stats_ext = internal_bypass_exp_stats,
+ .populate = internal_bypass_exp_populate,
+ .purge = internal_bypass_exp_purge,
+ .resync = internal_bypass_exp_resync,
+ .new = internal_bypass_exp_event_new,
+ .upd = internal_bypass_exp_event_upd,
+ .del = internal_bypass_exp_event_del,
+ },
};
diff --git a/src/internal_cache.c b/src/internal_cache.c
index e50e1db..ba2d74b 100644
--- a/src/internal_cache.c
+++ b/src/internal_cache.c
@@ -1,6 +1,7 @@
/*
- * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -19,46 +20,60 @@ static inline void sync_send(struct cache_object *obj, int query)
STATE_SYNC(sync)->enqueue(obj, query);
}
-static int _init(void)
+static int internal_cache_init(void)
{
- STATE(mode)->internal->data =
- cache_create("internal",
+ STATE(mode)->internal->ct.data =
+ cache_create("internal", CACHE_T_CT,
STATE_SYNC(sync)->internal_cache_flags,
- STATE_SYNC(sync)->internal_cache_extra);
+ STATE_SYNC(sync)->internal_cache_extra,
+ &cache_sync_internal_ct_ops);
- if (!STATE(mode)->internal->data) {
+ if (!STATE(mode)->internal->ct.data) {
dlog(LOG_ERR, "can't allocate memory for the internal cache");
return -1;
}
+
+ STATE(mode)->internal->exp.data =
+ cache_create("internal", CACHE_T_EXP,
+ STATE_SYNC(sync)->internal_cache_flags,
+ STATE_SYNC(sync)->internal_cache_extra,
+ &cache_sync_internal_exp_ops);
+
+ if (!STATE(mode)->internal->exp.data) {
+ dlog(LOG_ERR, "can't allocate memory for the internal cache");
+ return -1;
+ }
+
return 0;
}
-static void _close(void)
+static void internal_cache_close(void)
{
- cache_destroy(STATE(mode)->internal->data);
+ cache_destroy(STATE(mode)->internal->ct.data);
+ cache_destroy(STATE(mode)->internal->exp.data);
}
-static void dump(int fd, int type)
+static void internal_cache_ct_dump(int fd, int type)
{
- cache_dump(STATE(mode)->internal->data, fd, type);
+ cache_dump(STATE(mode)->internal->ct.data, fd, type);
}
-static void flush(void)
+static void internal_cache_ct_flush(void)
{
- cache_flush(STATE(mode)->internal->data);
+ cache_flush(STATE(mode)->internal->ct.data);
}
-static void stats(int fd)
+static void internal_cache_ct_stats(int fd)
{
- cache_stats(STATE(mode)->internal->data, fd);
+ cache_stats(STATE(mode)->internal->ct.data, fd);
}
-static void stats_ext(int fd)
+static void internal_cache_ct_stats_ext(int fd)
{
- cache_stats_extended(STATE(mode)->internal->data, fd);
+ cache_stats_extended(STATE(mode)->internal->ct.data, fd);
}
-static void populate(struct nf_conntrack *ct)
+static void internal_cache_ct_populate(struct nf_conntrack *ct)
{
/* This is required by kernels < 2.6.20 */
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
@@ -67,19 +82,19 @@ static void populate(struct nf_conntrack *ct)
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_USE);
- cache_update_force(STATE(mode)->internal->data, ct);
+ cache_update_force(STATE(mode)->internal->ct.data, ct);
}
-static int purge_step(void *data1, void *data2)
+static int internal_cache_ct_purge_step(void *data1, void *data2)
{
struct cache_object *obj = data2;
STATE(get_retval) = 0;
- nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */
+ nl_get_conntrack(STATE(get), obj->ptr); /* modifies STATE(get_reval) */
if (!STATE(get_retval)) {
if (obj->status != C_OBJ_DEAD) {
cache_object_set_status(obj, C_OBJ_DEAD);
- sync_send(obj, NET_T_STATE_DEL);
+ sync_send(obj, NET_T_STATE_CT_DEL);
cache_object_put(obj);
}
}
@@ -87,14 +102,15 @@ static int purge_step(void *data1, void *data2)
return 0;
}
-static void purge(void)
+static void internal_cache_ct_purge(void)
{
- cache_iterate(STATE(mode)->internal->data, NULL, purge_step);
+ cache_iterate(STATE(mode)->internal->ct.data, NULL,
+ internal_cache_ct_purge_step);
}
-static int resync(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
+static int
+internal_cache_ct_resync(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct, void *data)
{
struct cache_object *obj;
@@ -108,23 +124,22 @@ static int resync(enum nf_conntrack_msg_type type,
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_USE);
- obj = cache_update_force(STATE(mode)->internal->data, ct);
+ obj = cache_update_force(STATE(mode)->internal->ct.data, ct);
if (obj == NULL)
return NFCT_CB_CONTINUE;
switch (obj->status) {
case C_OBJ_NEW:
- sync_send(obj, NET_T_STATE_NEW);
+ sync_send(obj, NET_T_STATE_CT_NEW);
break;
case C_OBJ_ALIVE:
- sync_send(obj, NET_T_STATE_UPD);
+ sync_send(obj, NET_T_STATE_CT_UPD);
break;
}
return NFCT_CB_CONTINUE;
}
-static void
-event_new_sync(struct nf_conntrack *ct, int origin)
+static void internal_cache_ct_event_new(struct nf_conntrack *ct, int origin)
{
struct cache_object *obj;
int id;
@@ -139,13 +154,13 @@ event_new_sync(struct nf_conntrack *ct, int origin)
nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
- obj = cache_find(STATE(mode)->internal->data, ct, &id);
+ obj = cache_find(STATE(mode)->internal->ct.data, ct, &id);
if (obj == NULL) {
retry:
- obj = cache_object_new(STATE(mode)->internal->data, ct);
+ obj = cache_object_new(STATE(mode)->internal->ct.data, ct);
if (obj == NULL)
return;
- if (cache_add(STATE(mode)->internal->data, obj, id) == -1) {
+ if (cache_add(STATE(mode)->internal->ct.data, obj, id) == -1) {
cache_object_free(obj);
return;
}
@@ -153,16 +168,15 @@ retry:
* processes or the kernel, but don't propagate events that
* have been triggered by conntrackd itself, eg. commits. */
if (origin == CTD_ORIGIN_NOT_ME)
- sync_send(obj, NET_T_STATE_NEW);
+ sync_send(obj, NET_T_STATE_CT_NEW);
} else {
- cache_del(STATE(mode)->internal->data, obj);
+ cache_del(STATE(mode)->internal->ct.data, obj);
cache_object_free(obj);
goto retry;
}
}
-static void
-event_update_sync(struct nf_conntrack *ct, int origin)
+static void internal_cache_ct_event_upd(struct nf_conntrack *ct, int origin)
{
struct cache_object *obj;
@@ -170,16 +184,163 @@ event_update_sync(struct nf_conntrack *ct, int origin)
if (origin == CTD_ORIGIN_INJECT)
return;
- obj = cache_update_force(STATE(mode)->internal->data, ct);
+ obj = cache_update_force(STATE(mode)->internal->ct.data, ct);
if (obj == NULL)
return;
if (origin == CTD_ORIGIN_NOT_ME)
- sync_send(obj, NET_T_STATE_UPD);
+ sync_send(obj, NET_T_STATE_CT_UPD);
+}
+
+static int internal_cache_ct_event_del(struct nf_conntrack *ct, int origin)
+{
+ struct cache_object *obj;
+ int id;
+
+ /* this event has been triggered by a direct inject, skip */
+ if (origin == CTD_ORIGIN_INJECT)
+ return 0;
+
+ /* we don't synchronize events for objects that are not in the cache */
+ obj = cache_find(STATE(mode)->internal->ct.data, ct, &id);
+ if (obj == NULL)
+ return 0;
+
+ if (obj->status != C_OBJ_DEAD) {
+ cache_object_set_status(obj, C_OBJ_DEAD);
+ if (origin == CTD_ORIGIN_NOT_ME) {
+ sync_send(obj, NET_T_STATE_CT_DEL);
+ }
+ cache_object_put(obj);
+ }
+ return 1;
+}
+
+static void internal_cache_exp_dump(int fd, int type)
+{
+ cache_dump(STATE(mode)->internal->exp.data, fd, type);
+}
+
+static void internal_cache_exp_flush(void)
+{
+ cache_flush(STATE(mode)->internal->exp.data);
+}
+
+static void internal_cache_exp_stats(int fd)
+{
+ cache_stats(STATE(mode)->internal->exp.data, fd);
+}
+
+static void internal_cache_exp_stats_ext(int fd)
+{
+ cache_stats_extended(STATE(mode)->internal->exp.data, fd);
+}
+
+static void internal_cache_exp_populate(struct nf_expect *exp)
+{
+ cache_update_force(STATE(mode)->internal->exp.data, exp);
+}
+
+static int internal_cache_exp_purge_step(void *data1, void *data2)
+{
+ struct cache_object *obj = data2;
+
+ STATE(get_retval) = 0;
+ nl_get_expect(STATE(get), obj->ptr); /* modifies STATE(get_reval) */
+ if (!STATE(get_retval)) {
+ if (obj->status != C_OBJ_DEAD) {
+ cache_object_set_status(obj, C_OBJ_DEAD);
+ sync_send(obj, NET_T_STATE_EXP_DEL);
+ cache_object_put(obj);
+ }
+ }
+
+ return 0;
+}
+
+static void internal_cache_exp_purge(void)
+{
+ cache_iterate(STATE(mode)->internal->exp.data, NULL,
+ internal_cache_exp_purge_step);
}
static int
-event_destroy_sync(struct nf_conntrack *ct, int origin)
+internal_cache_exp_resync(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ struct cache_object *obj;
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ obj = cache_update_force(STATE(mode)->internal->exp.data, exp);
+ if (obj == NULL)
+ return NFCT_CB_CONTINUE;
+
+ switch (obj->status) {
+ case C_OBJ_NEW:
+ sync_send(obj, NET_T_STATE_EXP_NEW);
+ break;
+ case C_OBJ_ALIVE:
+ sync_send(obj, NET_T_STATE_EXP_UPD);
+ break;
+ }
+ return NFCT_CB_CONTINUE;
+}
+
+static void internal_cache_exp_event_new(struct nf_expect *exp, int origin)
+{
+ struct cache_object *obj;
+ int id;
+
+ /* this event has been triggered by a direct inject, skip */
+ if (origin == CTD_ORIGIN_INJECT)
+ return;
+
+ obj = cache_find(STATE(mode)->internal->exp.data, exp, &id);
+ if (obj == NULL) {
+retry:
+ obj = cache_object_new(STATE(mode)->internal->exp.data, exp);
+ if (obj == NULL)
+ return;
+ if (cache_add(STATE(mode)->internal->exp.data, obj, id) == -1) {
+ cache_object_free(obj);
+ return;
+ }
+ /* only synchronize events that have been triggered by other
+ * processes or the kernel, but don't propagate events that
+ * have been triggered by conntrackd itself, eg. commits. */
+ if (origin == CTD_ORIGIN_NOT_ME)
+ sync_send(obj, NET_T_STATE_EXP_NEW);
+ } else {
+ cache_del(STATE(mode)->internal->exp.data, obj);
+ cache_object_free(obj);
+ goto retry;
+ }
+}
+
+static void internal_cache_exp_event_upd(struct nf_expect *exp, int origin)
+{
+ struct cache_object *obj;
+
+ /* this event has been triggered by a direct inject, skip */
+ if (origin == CTD_ORIGIN_INJECT)
+ return;
+
+ obj = cache_update_force(STATE(mode)->internal->exp.data, exp);
+ if (obj == NULL)
+ return;
+
+ if (origin == CTD_ORIGIN_NOT_ME)
+ sync_send(obj, NET_T_STATE_EXP_UPD);
+}
+
+static int internal_cache_exp_event_del(struct nf_expect *exp, int origin)
{
struct cache_object *obj;
int id;
@@ -189,14 +350,14 @@ event_destroy_sync(struct nf_conntrack *ct, int origin)
return 0;
/* we don't synchronize events for objects that are not in the cache */
- obj = cache_find(STATE(mode)->internal->data, ct, &id);
+ obj = cache_find(STATE(mode)->internal->exp.data, exp, &id);
if (obj == NULL)
return 0;
if (obj->status != C_OBJ_DEAD) {
cache_object_set_status(obj, C_OBJ_DEAD);
if (origin == CTD_ORIGIN_NOT_ME) {
- sync_send(obj, NET_T_STATE_DEL);
+ sync_send(obj, NET_T_STATE_EXP_DEL);
}
cache_object_put(obj);
}
@@ -205,16 +366,30 @@ event_destroy_sync(struct nf_conntrack *ct, int origin)
struct internal_handler internal_cache = {
.flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC,
- .init = _init,
- .close = _close,
- .dump = dump,
- .flush = flush,
- .stats = stats,
- .stats_ext = stats_ext,
- .populate = populate,
- .purge = purge,
- .resync = resync,
- .new = event_new_sync,
- .update = event_update_sync,
- .destroy = event_destroy_sync,
+ .init = internal_cache_init,
+ .close = internal_cache_close,
+ .ct = {
+ .dump = internal_cache_ct_dump,
+ .flush = internal_cache_ct_flush,
+ .stats = internal_cache_ct_stats,
+ .stats_ext = internal_cache_ct_stats_ext,
+ .populate = internal_cache_ct_populate,
+ .purge = internal_cache_ct_purge,
+ .resync = internal_cache_ct_resync,
+ .new = internal_cache_ct_event_new,
+ .upd = internal_cache_ct_event_upd,
+ .del = internal_cache_ct_event_del,
+ },
+ .exp = {
+ .dump = internal_cache_exp_dump,
+ .flush = internal_cache_exp_flush,
+ .stats = internal_cache_exp_stats,
+ .stats_ext = internal_cache_exp_stats_ext,
+ .populate = internal_cache_exp_populate,
+ .purge = internal_cache_exp_purge,
+ .resync = internal_cache_exp_resync,
+ .new = internal_cache_exp_event_new,
+ .upd = internal_cache_exp_event_upd,
+ .del = internal_cache_exp_event_del,
+ },
};
diff --git a/src/lock.c b/src/lock.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lock.c
diff --git a/src/log.c b/src/log.c
index 9fe5119..d4de111 100644
--- a/src/log.c
+++ b/src/log.c
@@ -145,6 +145,43 @@ void dlog_ct(FILE *fd, struct nf_conntrack *ct, unsigned int type)
}
}
+void dlog_exp(FILE *fd, struct nf_expect *exp, unsigned int type)
+{
+ time_t t;
+ char buf[1024];
+ char *tmp;
+ unsigned int flags = 0;
+
+ buf[0]='\0';
+
+ switch(type) {
+ case NFCT_O_PLAIN:
+ t = time(NULL);
+ ctime_r(&t, buf);
+ tmp = buf + strlen(buf);
+ buf[strlen(buf)-1]='\t';
+ break;
+ default:
+ return;
+ }
+ nfexp_snprintf(buf+strlen(buf), 1024-strlen(buf), exp, 0, type, flags);
+
+ if (fd) {
+ snprintf(buf+strlen(buf), 1024-strlen(buf), "\n");
+ fputs(buf, fd);
+ }
+
+ if (fd == STATE(log)) {
+ /* error reporting */
+ if (CONFIG(syslog_facility) != -1)
+ syslog(LOG_ERR, "%s", tmp);
+ } else if (fd == STATE(stats_log)) {
+ /* connection logging */
+ if (CONFIG(stats).syslog_facility != -1)
+ syslog(LOG_INFO, "%s", tmp);
+ }
+}
+
void close_log(void)
{
if (STATE(log) != NULL)
diff --git a/src/main.c b/src/main.c
index 4ead2ea..342ed45 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
*
* 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
@@ -38,14 +39,15 @@ static const char usage_daemon_commands[] =
static const char usage_client_commands[] =
"Client mode commands:\n"
- " -c, commit external cache to conntrack table\n"
+ " -c [ct|expect], commit external cache to conntrack table\n"
" -f [|internal|external], flush internal and external cache\n"
- " -F, flush kernel conntrack table\n"
- " -i, display content of the internal cache\n"
- " -e, display the content of the external cache\n"
+ " -F [ct|expect], flush kernel conntrack table\n"
+ " -i [ct|expect], display content of the internal cache\n"
+ " -e [ct|expect], display the content of the external cache\n"
" -k, kill conntrack daemon\n"
- " -s [|network|cache|runtime|link|rsqueue|queue], dump statistics\n"
- " -R, resync with kernel conntrack table\n"
+ " -s [|network|cache|runtime|link|rsqueue|queue|ct|expect], "
+ "dump statistics\n"
+ " -R [ct|expect], resync with kernel conntrack table\n"
" -n, request resync with other node (only FT-FW and NOTRACK modes)\n"
" -x, dump cache in XML format (requires -i or -e)\n"
" -t, reset the kernel timeout (see PurgeTimeout clause)\n"
@@ -89,6 +91,25 @@ set_operation_mode(int *current, int want, char *argv[])
}
}
+static int
+set_action_by_table(int i, int argc, char *argv[],
+ int ct_action, int exp_action, int dfl_action, int *action)
+{
+ if (i+1 < argc && argv[i+1][0] != '-') {
+ if (strncmp(argv[i+1], "ct", strlen(argv[i+1])) == 0) {
+ *action = ct_action;
+ i++;
+ } else if (strncmp(argv[i+1], "expect",
+ strlen(argv[i+1])) == 0) {
+ *action = exp_action;
+ i++;
+ }
+ } else
+ *action = dfl_action;
+
+ return i;
+}
+
int main(int argc, char *argv[])
{
int ret, i, action = -1;
@@ -115,15 +136,23 @@ int main(int argc, char *argv[])
break;
case 'c':
set_operation_mode(&type, REQUEST, argv);
- action = COMMIT;
+ i = set_action_by_table(i, argc, argv,
+ CT_COMMIT, EXP_COMMIT,
+ ALL_COMMIT, &action);
break;
case 'i':
set_operation_mode(&type, REQUEST, argv);
- action = DUMP_INTERNAL;
+ i = set_action_by_table(i, argc, argv,
+ CT_DUMP_INTERNAL,
+ EXP_DUMP_INTERNAL,
+ CT_DUMP_INTERNAL, &action);
break;
case 'e':
set_operation_mode(&type, REQUEST, argv);
- action = DUMP_EXTERNAL;
+ i = set_action_by_table(i, argc, argv,
+ CT_DUMP_EXTERNAL,
+ EXP_DUMP_EXTERNAL,
+ CT_DUMP_EXTERNAL, &action);
break;
case 'C':
if (++i < argc) {
@@ -142,18 +171,21 @@ int main(int argc, char *argv[])
break;
case 'F':
set_operation_mode(&type, REQUEST, argv);
- action = FLUSH_MASTER;
+ i = set_action_by_table(i, argc, argv,
+ CT_FLUSH_MASTER,
+ EXP_FLUSH_MASTER,
+ ALL_FLUSH_MASTER, &action);
break;
case 'f':
set_operation_mode(&type, REQUEST, argv);
if (i+1 < argc && argv[i+1][0] != '-') {
if (strncmp(argv[i+1], "internal",
strlen(argv[i+1])) == 0) {
- action = FLUSH_INT_CACHE;
+ action = CT_FLUSH_INT_CACHE;
i++;
} else if (strncmp(argv[i+1], "external",
strlen(argv[i+1])) == 0) {
- action = FLUSH_EXT_CACHE;
+ action = CT_FLUSH_EXT_CACHE;
i++;
} else {
fprintf(stderr, "ERROR: unknown "
@@ -164,12 +196,15 @@ int main(int argc, char *argv[])
}
} else {
/* default to general flushing */
- action = FLUSH_CACHE;
+ action = ALL_FLUSH_CACHE;
}
break;
case 'R':
set_operation_mode(&type, REQUEST, argv);
- action = RESYNC_MASTER;
+ i = set_action_by_table(i, argc, argv,
+ CT_RESYNC_MASTER,
+ EXP_RESYNC_MASTER,
+ ALL_RESYNC_MASTER, &action);
break;
case 'B':
set_operation_mode(&type, REQUEST, argv);
@@ -222,6 +257,14 @@ int main(int argc, char *argv[])
strlen(argv[i+1])) == 0) {
action = STATS_QUEUE;
i++;
+ } else if (strncmp(argv[i+1], "ct",
+ strlen(argv[i+1])) == 0) {
+ action = STATS;
+ i++;
+ } else if (strncmp(argv[i+1], "expect",
+ strlen(argv[i+1])) == 0) {
+ action = EXP_STATS;
+ i++;
} else {
fprintf(stderr, "ERROR: unknown "
"parameter `%s' for "
@@ -243,10 +286,10 @@ int main(int argc, char *argv[])
action = REQUEST_DUMP;
break;
case 'x':
- if (action == DUMP_INTERNAL)
- action = DUMP_INT_XML;
- else if (action == DUMP_EXTERNAL)
- action = DUMP_EXT_XML;
+ if (action == CT_DUMP_INTERNAL)
+ action = CT_DUMP_INT_XML;
+ else if (action == CT_DUMP_EXTERNAL)
+ action = CT_DUMP_EXT_XML;
else {
show_usage(argv[0]);
fprintf(stderr, "Error: Invalid parameters\n");
diff --git a/src/netlink.c b/src/netlink.c
index 079a5c7..fe979e3 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1,5 +1,6 @@
/*
- * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
*
* 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
@@ -32,10 +33,23 @@ struct nfct_handle *nl_init_event_handler(void)
{
struct nfct_handle *h;
- h = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
+ h = nfct_open(CONFIG(netlink).subsys_id, CONFIG(netlink).groups);
if (h == NULL)
return NULL;
+ if (CONFIG(netlink).events_reliable) {
+ int on = 1;
+
+ setsockopt(nfct_fd(h), SOL_NETLINK,
+ NETLINK_BROADCAST_SEND_ERROR, &on, sizeof(int));
+
+ setsockopt(nfct_fd(h), SOL_NETLINK,
+ NETLINK_NO_ENOBUFS, &on, sizeof(int));
+
+ dlog(LOG_NOTICE, "reliable ctnetlink event delivery "
+ "is ENABLED.");
+ }
+
if (STATE(filter)) {
if (CONFIG(filter_from_kernelspace)) {
if (nfct_filter_attach(nfct_fd(h),
@@ -54,14 +68,16 @@ struct nfct_handle *nl_init_event_handler(void)
/* set up socket buffer size */
if (CONFIG(netlink_buffer_size) &&
- CONFIG(netlink_buffer_size) <= CONFIG(netlink_buffer_size_max_grown)) {
+ CONFIG(netlink_buffer_size) <=
+ CONFIG(netlink_buffer_size_max_grown)) {
/* we divide netlink_buffer_size by 2 here since value passed
to kernel gets doubled in SO_RCVBUF; see net/core/sock.c */
CONFIG(netlink_buffer_size) =
- nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)/2);
+ nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)/2);
} else {
- dlog(LOG_NOTICE, "NetlinkBufferSize is either not set or is greater "
- "than NetlinkBufferSizeMaxGrowth. Using current system buffer size");
+ dlog(LOG_NOTICE, "NetlinkBufferSize is either not set or "
+ "is greater than NetlinkBufferSizeMaxGrowth. "
+ "Using current system buffer size");
socklen_t socklen = sizeof(unsigned int);
unsigned int read_size;
@@ -76,18 +92,6 @@ struct nfct_handle *nl_init_event_handler(void)
dlog(LOG_NOTICE, "netlink event socket buffer size has been set "
"to %u bytes", CONFIG(netlink_buffer_size));
- if (CONFIG(netlink).events_reliable) {
- int on = 1;
-
- setsockopt(nfct_fd(h), SOL_NETLINK,
- NETLINK_BROADCAST_SEND_ERROR, &on, sizeof(int));
-
- setsockopt(nfct_fd(h), SOL_NETLINK,
- NETLINK_NO_ENOBUFS, &on, sizeof(int));
-
- dlog(LOG_NOTICE, "reliable ctnetlink event delivery "
- "is ENABLED.");
- }
return h;
}
@@ -161,20 +165,21 @@ int nl_send_resync(struct nfct_handle *h)
/* if the handle has no callback, check for existence, otherwise, update */
int nl_get_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct)
{
- int ret;
- char __tmp[nfct_maxsize()];
- struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp;
+ int ret = 1;
+ struct nf_conntrack *tmp;
- memset(__tmp, 0, sizeof(__tmp));
+ tmp = nfct_new();
+ if (tmp == NULL)
+ return -1;
/* use the original tuple to check if it is there */
nfct_copy(tmp, ct, NFCT_CP_ORIG);
- ret = nfct_query(h, NFCT_Q_GET, tmp);
- if (ret == -1)
- return errno == ENOENT ? 0 : -1;
+ if (nfct_query(h, NFCT_Q_GET, tmp) == -1)
+ ret = (errno == ENOENT) ? 0 : -1;
- return 1;
+ nfct_destroy(tmp);
+ return ret;
}
int nl_create_conntrack(struct nfct_handle *h,
@@ -200,12 +205,14 @@ int nl_create_conntrack(struct nfct_handle *h,
nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);
- /*
- * TCP flags to overpass window tracking for recovered connections
- */
+ /* disable TCP window tracking for recovered connections if required */
if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
- uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL |
- IP_CT_TCP_FLAG_SACK_PERM;
+ uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM;
+
+ if (!CONFIG(sync).tcp_window_tracking)
+ flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ else
+ flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;
/* FIXME: workaround, we should send TCP flags in updates */
if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
@@ -265,12 +272,14 @@ int nl_update_conntrack(struct nfct_handle *h,
nfct_attr_unset(ct, ATTR_MASTER_PORT_DST);
}
- /*
- * TCP flags to overpass window tracking for recovered connections
- */
+ /* disable TCP window tracking for recovered connections if required */
if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
- uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL |
- IP_CT_TCP_FLAG_SACK_PERM;
+ uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM;
+
+ if (!CONFIG(sync).tcp_window_tracking)
+ flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ else
+ flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;
/* FIXME: workaround, we should send TCP flags in updates */
if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
@@ -293,3 +302,61 @@ int nl_destroy_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct)
{
return nfct_query(h, NFCT_Q_DESTROY, ct);
}
+
+int nl_create_expect(struct nfct_handle *h, const struct nf_expect *orig,
+ int timeout)
+{
+ int ret;
+ struct nf_expect *exp;
+
+ exp = nfexp_clone(orig);
+ if (exp == NULL)
+ return -1;
+
+ if (timeout > 0)
+ nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, timeout);
+
+ ret = nfexp_query(h, NFCT_Q_CREATE, exp);
+ nfexp_destroy(exp);
+
+ return ret;
+}
+
+int nl_destroy_expect(struct nfct_handle *h, const struct nf_expect *exp)
+{
+ return nfexp_query(h, NFCT_Q_DESTROY, exp);
+}
+
+/* if the handle has no callback, check for existence, otherwise, update */
+int nl_get_expect(struct nfct_handle *h, const struct nf_expect *exp)
+{
+ int ret = 1;
+ struct nf_expect *tmp;
+
+ /* XXX: we only need the expectation, not the mask and the master. */
+ tmp = nfexp_clone(exp);
+ if (tmp == NULL)
+ return -1;
+
+ if (nfexp_query(h, NFCT_Q_GET, tmp) == -1)
+ ret = (errno == ENOENT) ? 0 : -1;
+
+ nfexp_destroy(tmp);
+ return ret;
+}
+
+int nl_dump_expect_table(struct nfct_handle *h)
+{
+ return nfexp_query(h, NFCT_Q_DUMP, &CONFIG(family));
+}
+
+int nl_flush_expect_table(struct nfct_handle *h)
+{
+ return nfexp_query(h, NFCT_Q_FLUSH, &CONFIG(family));
+}
+
+int nl_send_expect_resync(struct nfct_handle *h)
+{
+ int family = CONFIG(family);
+ return nfexp_send(h, NFCT_Q_DUMP, &family);
+}
diff --git a/src/network.c b/src/network.c
index 6a66a2b..13db37c 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -119,13 +120,20 @@ int nethdr_track_is_seq_set()
#include "cache.h"
-static int status2type[] = {
- [C_OBJ_NEW] = NET_T_STATE_NEW,
- [C_OBJ_ALIVE] = NET_T_STATE_UPD,
- [C_OBJ_DEAD] = NET_T_STATE_DEL,
+static int status2type[CACHE_T_MAX][C_OBJ_MAX] = {
+ [CACHE_T_CT] = {
+ [C_OBJ_NEW] = NET_T_STATE_CT_NEW,
+ [C_OBJ_ALIVE] = NET_T_STATE_CT_UPD,
+ [C_OBJ_DEAD] = NET_T_STATE_CT_DEL,
+ },
+ [CACHE_T_EXP] = {
+ [C_OBJ_NEW] = NET_T_STATE_EXP_NEW,
+ [C_OBJ_ALIVE] = NET_T_STATE_EXP_UPD,
+ [C_OBJ_DEAD] = NET_T_STATE_EXP_DEL,
+ },
};
-int object_status_to_network_type(int status)
+int object_status_to_network_type(struct cache_object *obj)
{
- return status2type[status];
+ return status2type[obj->cache->type][obj->status];
}
diff --git a/src/parse.c b/src/parse.c
index e6eefe4..81e9c6b 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -24,191 +25,201 @@
#define ssizeof(x) (int)sizeof(x)
#endif
-static void parse_u8(struct nf_conntrack *ct, int attr, void *data);
-static void parse_u16(struct nf_conntrack *ct, int attr, void *data);
-static void parse_u32(struct nf_conntrack *ct, int attr, void *data);
-static void parse_group(struct nf_conntrack *ct, int attr, void *data);
-static void parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data);
+static void ct_parse_u8(struct nf_conntrack *ct, int attr, void *data);
+static void ct_parse_u16(struct nf_conntrack *ct, int attr, void *data);
+static void ct_parse_u32(struct nf_conntrack *ct, int attr, void *data);
+static void ct_parse_group(struct nf_conntrack *ct, int attr, void *data);
+static void ct_parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data);
-struct parser {
+struct ct_parser {
void (*parse)(struct nf_conntrack *ct, int attr, void *data);
int attr;
int size;
};
-static struct parser h[NTA_MAX] = {
+static struct ct_parser h[NTA_MAX] = {
[NTA_IPV4] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_ORIG_IPV4,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv4)),
},
[NTA_IPV6] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_ORIG_IPV6,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv6)),
},
[NTA_PORT] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_ORIG_PORT,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_port)),
},
[NTA_L4PROTO] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_L4PROTO,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_TCP_STATE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_TCP_STATE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_STATUS] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_STATUS,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_MARK] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_MARK,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_TIMEOUT] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_TIMEOUT,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_MASTER_IPV4] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_MASTER_IPV4,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv4)),
},
[NTA_MASTER_IPV6] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_MASTER_IPV6,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv6)),
},
[NTA_MASTER_L4PROTO] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_MASTER_L4PROTO,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_MASTER_PORT] = {
- .parse = parse_group,
+ .parse = ct_parse_group,
.attr = ATTR_GRP_MASTER_PORT,
.size = NTA_SIZE(sizeof(struct nfct_attr_grp_port)),
},
[NTA_SNAT_IPV4] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_SNAT_IPV4,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_DNAT_IPV4] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_DNAT_IPV4,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_SPAT_PORT] = {
- .parse = parse_u16,
+ .parse = ct_parse_u16,
.attr = ATTR_SNAT_PORT,
.size = NTA_SIZE(sizeof(uint16_t)),
},
[NTA_DPAT_PORT] = {
- .parse = parse_u16,
+ .parse = ct_parse_u16,
.attr = ATTR_DNAT_PORT,
.size = NTA_SIZE(sizeof(uint16_t)),
},
[NTA_NAT_SEQ_ADJ] = {
- .parse = parse_nat_seq_adj,
+ .parse = ct_parse_nat_seq_adj,
.size = NTA_SIZE(sizeof(struct nta_attr_natseqadj)),
},
[NTA_SCTP_STATE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_SCTP_STATE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_SCTP_VTAG_ORIG] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_SCTP_VTAG_ORIG,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_SCTP_VTAG_REPL] = {
- .parse = parse_u32,
+ .parse = ct_parse_u32,
.attr = ATTR_SCTP_VTAG_REPL,
.size = NTA_SIZE(sizeof(uint32_t)),
},
[NTA_DCCP_STATE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_DCCP_STATE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_DCCP_ROLE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_DCCP_ROLE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_ICMP_TYPE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_ICMP_TYPE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_ICMP_CODE] = {
- .parse = parse_u8,
+ .parse = ct_parse_u8,
.attr = ATTR_ICMP_CODE,
.size = NTA_SIZE(sizeof(uint8_t)),
},
[NTA_ICMP_ID] = {
- .parse = parse_u16,
+ .parse = ct_parse_u16,
.attr = ATTR_ICMP_ID,
.size = NTA_SIZE(sizeof(uint16_t)),
},
+ [NTA_TCP_WSCALE_ORIG] = {
+ .parse = ct_parse_u8,
+ .attr = ATTR_TCP_WSCALE_ORIG,
+ .size = NTA_SIZE(sizeof(uint8_t)),
+ },
+ [NTA_TCP_WSCALE_REPL] = {
+ .parse = ct_parse_u8,
+ .attr = ATTR_TCP_WSCALE_REPL,
+ .size = NTA_SIZE(sizeof(uint8_t)),
+ },
};
static void
-parse_u8(struct nf_conntrack *ct, int attr, void *data)
+ct_parse_u8(struct nf_conntrack *ct, int attr, void *data)
{
uint8_t *value = (uint8_t *) data;
nfct_set_attr_u8(ct, h[attr].attr, *value);
}
static void
-parse_u16(struct nf_conntrack *ct, int attr, void *data)
+ct_parse_u16(struct nf_conntrack *ct, int attr, void *data)
{
uint16_t *value = (uint16_t *) data;
nfct_set_attr_u16(ct, h[attr].attr, ntohs(*value));
}
static void
-parse_u32(struct nf_conntrack *ct, int attr, void *data)
+ct_parse_u32(struct nf_conntrack *ct, int attr, void *data)
{
uint32_t *value = (uint32_t *) data;
nfct_set_attr_u32(ct, h[attr].attr, ntohl(*value));
}
static void
-parse_group(struct nf_conntrack *ct, int attr, void *data)
+ct_parse_group(struct nf_conntrack *ct, int attr, void *data)
{
nfct_set_attr_grp(ct, h[attr].attr, data);
}
static void
-parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data)
+ct_parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data)
{
struct nta_attr_natseqadj *this = data;
nfct_set_attr_u32(ct, ATTR_ORIG_NAT_SEQ_CORRECTION_POS,
ntohl(this->orig_seq_correction_pos));
nfct_set_attr_u32(ct, ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE,
- ntohl(this->orig_seq_correction_pos));
+ ntohl(this->orig_seq_offset_before));
nfct_set_attr_u32(ct, ATTR_ORIG_NAT_SEQ_OFFSET_AFTER,
- ntohl(this->orig_seq_correction_pos));
+ ntohl(this->orig_seq_offset_after));
nfct_set_attr_u32(ct, ATTR_REPL_NAT_SEQ_CORRECTION_POS,
- ntohl(this->orig_seq_correction_pos));
+ ntohl(this->repl_seq_correction_pos));
nfct_set_attr_u32(ct, ATTR_REPL_NAT_SEQ_OFFSET_BEFORE,
- ntohl(this->orig_seq_correction_pos));
+ ntohl(this->repl_seq_offset_before));
nfct_set_attr_u32(ct, ATTR_REPL_NAT_SEQ_OFFSET_AFTER,
- ntohl(this->orig_seq_correction_pos));
+ ntohl(this->repl_seq_offset_after));
}
-int parse_payload(struct nf_conntrack *ct, struct nethdr *net, size_t remain)
+int msg2ct(struct nf_conntrack *ct, struct nethdr *net, size_t remain)
{
int len;
struct netattr *attr;
@@ -237,3 +248,195 @@ int parse_payload(struct nf_conntrack *ct, struct nethdr *net, size_t remain)
return 0;
}
+
+static void exp_parse_ct_group(void *ct, int attr, void *data);
+static void exp_parse_ct_u8(void *ct, int attr, void *data);
+static void exp_parse_u32(void *exp, int attr, void *data);
+
+static struct exp_parser {
+ void (*parse)(void *obj, int attr, void *data);
+ int exp_attr;
+ int ct_attr;
+ int size;
+} exp_h[NTA_EXP_MAX] = {
+ [NTA_EXP_MASTER_IPV4] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASTER,
+ .ct_attr = ATTR_GRP_ORIG_IPV4,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv4)),
+ },
+ [NTA_EXP_MASTER_IPV6] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASTER,
+ .ct_attr = ATTR_GRP_ORIG_IPV6,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv6)),
+ },
+ [NTA_EXP_MASTER_L4PROTO] = {
+ .parse = exp_parse_ct_u8,
+ .exp_attr = ATTR_EXP_MASTER,
+ .ct_attr = ATTR_L4PROTO,
+ .size = NTA_SIZE(sizeof(uint8_t)),
+ },
+ [NTA_EXP_MASTER_PORT] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASTER,
+ .ct_attr = ATTR_GRP_ORIG_PORT,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_port)),
+ },
+ [NTA_EXP_EXPECT_IPV4] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_EXPECTED,
+ .ct_attr = ATTR_GRP_ORIG_IPV4,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv4)),
+ },
+ [NTA_EXP_EXPECT_IPV6] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_EXPECTED,
+ .ct_attr = ATTR_GRP_ORIG_IPV6,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv6)),
+ },
+ [NTA_EXP_EXPECT_L4PROTO] = {
+ .parse = exp_parse_ct_u8,
+ .exp_attr = ATTR_EXP_EXPECTED,
+ .ct_attr = ATTR_L4PROTO,
+ .size = NTA_SIZE(sizeof(uint8_t)),
+ },
+ [NTA_EXP_EXPECT_PORT] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_EXPECTED,
+ .ct_attr = ATTR_GRP_ORIG_PORT,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_port)),
+ },
+ [NTA_EXP_MASK_IPV4] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASK,
+ .ct_attr = ATTR_GRP_ORIG_IPV4,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv4)),
+ },
+ [NTA_EXP_MASK_IPV6] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASK,
+ .ct_attr = ATTR_GRP_ORIG_IPV6,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_ipv6)),
+ },
+ [NTA_EXP_MASK_L4PROTO] = {
+ .parse = exp_parse_ct_u8,
+ .exp_attr = ATTR_EXP_MASK,
+ .ct_attr = ATTR_L4PROTO,
+ .size = NTA_SIZE(sizeof(uint8_t)),
+ },
+ [NTA_EXP_MASK_PORT] = {
+ .parse = exp_parse_ct_group,
+ .exp_attr = ATTR_EXP_MASK,
+ .ct_attr = ATTR_GRP_ORIG_PORT,
+ .size = NTA_SIZE(sizeof(struct nfct_attr_grp_port)),
+ },
+ [NTA_EXP_TIMEOUT] = {
+ .parse = exp_parse_u32,
+ .exp_attr = ATTR_EXP_TIMEOUT,
+ .size = NTA_SIZE(sizeof(uint32_t)),
+ },
+ [NTA_EXP_FLAGS] = {
+ .parse = exp_parse_u32,
+ .exp_attr = ATTR_EXP_FLAGS,
+ .size = NTA_SIZE(sizeof(uint32_t)),
+ },
+};
+
+static void exp_parse_ct_group(void *ct, int attr, void *data)
+{
+ nfct_set_attr_grp(ct, exp_h[attr].ct_attr, data);
+}
+
+static void exp_parse_ct_u8(void *ct, int attr, void *data)
+{
+ uint8_t *value = (uint8_t *) data;
+ nfct_set_attr_u8(ct, exp_h[attr].ct_attr, *value);
+}
+
+static void exp_parse_u32(void *exp, int attr, void *data)
+{
+ uint32_t *value = (uint32_t *) data;
+ nfexp_set_attr_u32(exp, exp_h[attr].exp_attr, ntohl(*value));
+}
+
+int msg2exp(struct nf_expect *exp, struct nethdr *net, size_t remain)
+{
+ int len;
+ struct netattr *attr;
+ struct nf_conntrack *master, *expected, *mask;
+
+ if (remain < net->len)
+ return -1;
+
+ len = net->len - NETHDR_SIZ;
+ attr = NETHDR_DATA(net);
+
+ master = nfct_new();
+ if (master == NULL)
+ goto err_master;
+
+ expected = nfct_new();
+ if (expected == NULL)
+ goto err_expected;
+
+ mask = nfct_new();
+ if (mask == NULL)
+ goto err_mask;
+
+ while (len > ssizeof(struct netattr)) {
+ ATTR_NETWORK2HOST(attr);
+ if (attr->nta_len > len)
+ goto err;
+ if (attr->nta_attr > NTA_MAX)
+ goto err;
+ if (attr->nta_len != exp_h[attr->nta_attr].size)
+ goto err;
+ if (exp_h[attr->nta_attr].parse == NULL) {
+ attr = NTA_NEXT(attr, len);
+ continue;
+ }
+ switch(exp_h[attr->nta_attr].exp_attr) {
+ case ATTR_EXP_MASTER:
+ exp_h[attr->nta_attr].parse(master, attr->nta_attr,
+ NTA_DATA(attr));
+ case ATTR_EXP_EXPECTED:
+ exp_h[attr->nta_attr].parse(expected, attr->nta_attr,
+ NTA_DATA(attr));
+ case ATTR_EXP_MASK:
+ exp_h[attr->nta_attr].parse(mask, attr->nta_attr,
+ NTA_DATA(attr));
+ break;
+ case ATTR_EXP_TIMEOUT:
+ case ATTR_EXP_FLAGS:
+ exp_h[attr->nta_attr].parse(exp, attr->nta_attr,
+ NTA_DATA(attr));
+ break;
+ }
+ attr = NTA_NEXT(attr, len);
+ }
+
+ nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
+ nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
+ nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
+
+ /* We can release the conntrack objects at this point because the
+ * setter makes a copy of them. This is not efficient, it would be
+ * better to save that extra copy but this is how the library works.
+ * I'm sorry, I cannot change it without breaking backward
+ * compatibility. Probably it is a good idea to think of adding new
+ * interfaces in the near future to get it better. */
+ nfct_destroy(mask);
+ nfct_destroy(expected);
+ nfct_destroy(master);
+
+ return 0;
+err:
+ nfct_destroy(mask);
+err_mask:
+ nfct_destroy(expected);
+err_expected:
+ nfct_destroy(master);
+err_master:
+ return -1;
+}
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index b2d4bdb..01fe4fc 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -47,7 +47,7 @@ ip6_part {hex_255}":"?
ip6_form1 {ip6_part}{0,16}"::"{ip6_part}{0,16}
ip6_form2 ({hex_255}":"){16}{hex_255}
ip6 {ip6_form1}{ip6_cidr}?|{ip6_form2}{ip6_cidr}?
-string [a-zA-Z][a-zA-Z0-9\.]*
+string [a-zA-Z][a-zA-Z0-9\.\-]*
persistent [P|p][E|e][R|r][S|s][I|i][S|s][T|t][E|e][N|n][T|T]
nack [N|n][A|a][C|c][K|k]
alarm [A|a][L|l][A|a][R|r][M|m]
@@ -138,6 +138,9 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k]
"NetlinkEventsReliable" { return T_NETLINK_EVENTS_RELIABLE; }
"DisableInternalCache" { return T_DISABLE_INTERNAL_CACHE; }
"DisableExternalCache" { return T_DISABLE_EXTERNAL_CACHE; }
+"Options" { return T_OPTIONS; }
+"TCPWindowTracking" { return T_TCP_WINDOW_TRACKING; }
+"ExpectationSync" { return T_EXPECT_SYNC; }
"ErrorQueueLength" { return T_ERROR_QUEUE_LENGTH; }
{is_on} { return T_ON; }
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 5f4e6be..d94bd85 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -73,6 +73,7 @@ static void __max_dedicated_links_reached(void);
%token T_NETLINK_OVERRUN_RESYNC T_NICE T_IPV4_DEST_ADDR T_IPV6_DEST_ADDR
%token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE
%token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH
+%token T_OPTIONS T_TCP_WINDOW_TRACKING T_EXPECT_SYNC
%token <string> T_IP T_PATH_VAL
%token <val> T_NUMBER
@@ -808,8 +809,65 @@ sync_line: refreshtime
| state_replication
| cache_writethrough
| destroy_timeout
+ | option_line
;
+option_line: T_OPTIONS '{' options '}';
+
+options:
+ | options option
+ ;
+
+option: T_TCP_WINDOW_TRACKING T_ON
+{
+ CONFIG(sync).tcp_window_tracking = 1;
+};
+
+option: T_TCP_WINDOW_TRACKING T_OFF
+{
+ CONFIG(sync).tcp_window_tracking = 0;
+};
+
+option: T_EXPECT_SYNC T_ON
+{
+ CONFIG(flags) |= CTD_EXPECT;
+ CONFIG(netlink).subsys_id = NFNL_SUBSYS_NONE;
+ CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY |
+ NF_NETLINK_CONNTRACK_EXP_NEW |
+ NF_NETLINK_CONNTRACK_EXP_UPDATE |
+ NF_NETLINK_CONNTRACK_EXP_DESTROY;
+};
+
+option: T_EXPECT_SYNC T_OFF
+{
+ CONFIG(netlink).subsys_id = NFNL_SUBSYS_CTNETLINK;
+ CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY;
+};
+
+option: T_EXPECT_SYNC '{' expect_list '}'
+{
+ CONFIG(flags) |= CTD_EXPECT;
+ CONFIG(netlink).subsys_id = NFNL_SUBSYS_NONE;
+ CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY |
+ NF_NETLINK_CONNTRACK_EXP_NEW |
+ NF_NETLINK_CONNTRACK_EXP_UPDATE |
+ NF_NETLINK_CONNTRACK_EXP_DESTROY;
+};
+
+expect_list:
+ | expect_list expect_item ;
+
+expect_item: T_STRING
+{
+ exp_filter_add(STATE(exp_filter), $1);
+}
+
sync_mode_alarm: T_SYNC_MODE T_ALARM '{' sync_mode_alarm_list '}'
{
conf.flags |= CTD_SYNC_ALARM;
@@ -1240,6 +1298,25 @@ filter_protocol_item : T_UDP
pent->p_proto);
};
+filter_protocol_item : T_UDP
+{
+ struct protoent *pent;
+
+ pent = getprotobyname("udp");
+ if (pent == NULL) {
+ print_err(CTD_CFG_WARN, "getprotobyname() cannot find "
+ "protocol `udp' in /etc/protocols");
+ break;
+ }
+ ct_filter_add_proto(STATE(us_filter), pent->p_proto);
+
+ __kernel_filter_start();
+
+ nfct_filter_add_attr_u32(STATE(filter),
+ NFCT_FILTER_L4PROTO,
+ pent->p_proto);
+};
+
filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}'
{
ct_filter_set_logic(STATE(us_filter),
@@ -1580,6 +1657,7 @@ init_config(char *filename)
/* Zero may be a valid facility */
CONFIG(syslog_facility) = -1;
CONFIG(stats).syslog_facility = -1;
+ CONFIG(netlink).subsys_id = -1;
yyrestart(fp);
yyparse();
@@ -1618,7 +1696,7 @@ init_config(char *filename)
/* default number of bucket of the hashtable that are committed in
one run loop. XXX: no option available to tune this value yet. */
if (CONFIG(general).commit_steps == 0)
- CONFIG(general).commit_steps = 64;
+ CONFIG(general).commit_steps = 8192;
/* if overrun, automatically resync with kernel after 30 seconds */
if (CONFIG(nl_overrun_resync) == 0)
@@ -1628,5 +1706,12 @@ init_config(char *filename)
if (CONFIG(channelc).error_queue_length == 0)
CONFIG(channelc).error_queue_length = 128;
+ if (CONFIG(netlink).subsys_id == -1) {
+ CONFIG(netlink).subsys_id = NFNL_SUBSYS_CTNETLINK;
+ CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY;
+ }
+
return 0;
}
diff --git a/src/run.c b/src/run.c
index 803bbcc..159ef30 100644
--- a/src/run.c
+++ b/src/run.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -186,40 +187,91 @@ static void dump_stats_runtime(int fd)
send(fd, buf, size, 0);
}
+static void local_flush_master(void)
+{
+ STATE(stats).nl_kernel_table_flush++;
+ dlog(LOG_NOTICE, "flushing kernel conntrack table");
+
+ /* fork a child process that performs the flush operation,
+ * meanwhile the parent process handles events. */
+ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL,
+ NULL, NULL) == 0) {
+ nl_flush_conntrack_table(STATE(flush));
+ exit(EXIT_SUCCESS);
+ }
+}
+
+static void local_resync_master(void)
+{
+ if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
+ STATE(stats).nl_kernel_table_resync++;
+ dlog(LOG_NOTICE, "resync with master conntrack table");
+ nl_dump_conntrack_table(STATE(dump));
+ } else {
+ dlog(LOG_NOTICE, "resync is unsupported in this mode");
+ }
+}
+
+static void local_exp_flush_master(void)
+{
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ return;
+
+ STATE(stats).nl_kernel_table_flush++;
+ dlog(LOG_NOTICE, "flushing kernel expect table");
+
+ /* fork a child process that performs the flush operation,
+ * meanwhile the parent process handles events. */
+ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL,
+ NULL, NULL) == 0) {
+ nl_flush_expect_table(STATE(flush));
+ exit(EXIT_SUCCESS);
+ }
+}
+
+static void local_exp_resync_master(void)
+{
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ return;
+
+ if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
+ STATE(stats).nl_kernel_table_resync++;
+ dlog(LOG_NOTICE, "resync with master expect table");
+ nl_dump_expect_table(STATE(dump));
+ } else {
+ dlog(LOG_NOTICE, "resync is unsupported in this mode");
+ }
+}
+
static int local_handler(int fd, void *data)
{
int ret = LOCAL_RET_OK;
int type;
- ret = read(fd, &type, sizeof(type));
- if (ret == -1) {
+ if (read(fd, &type, sizeof(type)) <= 0) {
STATE(stats).local_read_failed++;
return LOCAL_RET_OK;
}
- if (ret == 0)
- return LOCAL_RET_OK;
-
switch(type) {
- case FLUSH_MASTER:
- STATE(stats).nl_kernel_table_flush++;
- dlog(LOG_NOTICE, "flushing kernel conntrack table");
-
- /* fork a child process that performs the flush operation,
- * meanwhile the parent process handles events. */
- if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL,
- NULL, NULL) == 0) {
- nl_flush_conntrack_table(STATE(flush));
- exit(EXIT_SUCCESS);
- }
+ case CT_FLUSH_MASTER:
+ local_flush_master();
break;
- case RESYNC_MASTER:
- if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
- STATE(stats).nl_kernel_table_resync++;
- dlog(LOG_NOTICE, "resync with master table");
- nl_dump_conntrack_table(STATE(dump));
- } else {
- dlog(LOG_NOTICE, "resync is unsupported in this mode");
- }
+ case CT_RESYNC_MASTER:
+ local_resync_master();
+ break;
+ case EXP_FLUSH_MASTER:
+ local_exp_flush_master();
+ break;
+ case EXP_RESYNC_MASTER:
+ local_exp_resync_master();
+ break;
+ case ALL_FLUSH_MASTER:
+ local_flush_master();
+ local_exp_flush_master();
+ break;
+ case ALL_RESYNC_MASTER:
+ local_resync_master();
+ local_exp_resync_master();
break;
case STATS_RUNTIME:
dump_stats_runtime(fd);
@@ -245,10 +297,14 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data)
static void do_polling_alarm(struct alarm_block *a, void *data)
{
- if (STATE(mode)->internal->purge)
- STATE(mode)->internal->purge();
+ if (STATE(mode)->internal->ct.purge)
+ STATE(mode)->internal->ct.purge();
+
+ if (STATE(mode)->internal->exp.purge)
+ STATE(mode)->internal->exp.purge();
nl_send_resync(STATE(resync));
+ nl_send_expect_resync(STATE(resync));
add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
}
@@ -271,13 +327,13 @@ static int event_handler(const struct nlmsghdr *nlh,
switch(type) {
case NFCT_T_NEW:
- STATE(mode)->internal->new(ct, origin_type);
+ STATE(mode)->internal->ct.new(ct, origin_type);
break;
case NFCT_T_UPDATE:
- STATE(mode)->internal->update(ct, origin_type);
+ STATE(mode)->internal->ct.upd(ct, origin_type);
break;
case NFCT_T_DESTROY:
- if (STATE(mode)->internal->destroy(ct, origin_type))
+ if (STATE(mode)->internal->ct.del(ct, origin_type))
update_traffic_stats(ct);
break;
default:
@@ -286,10 +342,52 @@ static int event_handler(const struct nlmsghdr *nlh,
}
out:
- if (STATE(event_iterations_limit)-- <= 0) {
- STATE(event_iterations_limit) = CONFIG(event_iterations_limit);
+ if (STATE(event_iterations_limit)-- <= 0)
return NFCT_CB_STOP;
- } else
+ else
+ return NFCT_CB_CONTINUE;
+}
+
+static int exp_event_handler(const struct nlmsghdr *nlh,
+ enum nf_conntrack_msg_type type,
+ struct nf_expect *exp,
+ void *data)
+{
+ int origin_type;
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ STATE(stats).nl_events_received++;
+
+ if (!exp_filter_find(STATE(exp_filter), exp)) {
+ STATE(stats).nl_events_filtered++;
+ goto out;
+ }
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ origin_type = origin_find(nlh);
+
+ switch(type) {
+ case NFCT_T_NEW:
+ STATE(mode)->internal->exp.new(exp, origin_type);
+ break;
+ case NFCT_T_UPDATE:
+ STATE(mode)->internal->exp.upd(exp, origin_type);
+ break;
+ case NFCT_T_DESTROY:
+ STATE(mode)->internal->exp.del(exp, origin_type);
+ break;
+ default:
+ STATE(stats).nl_events_unknown_type++;
+ break;
+ }
+
+out:
+ /* we reset the iteration limiter in the main select loop. */
+ if (STATE(event_iterations_limit)-- <= 0)
+ return NFCT_CB_STOP;
+ else
return NFCT_CB_CONTINUE;
}
@@ -302,7 +400,30 @@ static int dump_handler(enum nf_conntrack_msg_type type,
switch(type) {
case NFCT_T_UPDATE:
- STATE(mode)->internal->populate(ct);
+ STATE(mode)->internal->ct.populate(ct);
+ break;
+ default:
+ STATE(stats).nl_dump_unknown_type++;
+ break;
+ }
+ return NFCT_CB_CONTINUE;
+}
+
+static int exp_dump_handler(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ switch(type) {
+ case NFCT_T_UPDATE:
+ STATE(mode)->internal->exp.populate(exp);
break;
default:
STATE(stats).nl_dump_unknown_type++;
@@ -322,9 +443,27 @@ static int get_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int exp_get_handler(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ STATE(get_retval) = 1;
+ return NFCT_CB_CONTINUE;
+}
+
int
init(void)
{
+ do_gettimeofday();
+
if (CONFIG(flags) & CTD_STATS_MODE)
STATE(mode) = &stats_mode;
else if (CONFIG(flags) & CTD_SYNC_MODE)
@@ -355,21 +494,8 @@ init(void)
}
register_fd(STATE(local).fd, STATE(fds));
- if (!(CONFIG(flags) & CTD_POLL)) {
- STATE(event) = nl_init_event_handler();
- if (STATE(event) == NULL) {
- dlog(LOG_ERR, "can't open netlink handler: %s",
- strerror(errno));
- dlog(LOG_ERR, "no ctnetlink kernel support?");
- return -1;
- }
- nfct_callback_register2(STATE(event), NFCT_T_ALL,
- event_handler, NULL);
- register_fd(nfct_fd(STATE(event)), STATE(fds));
- }
-
/* resynchronize (like 'dump' socket) but it also purges old entries */
- STATE(resync) = nfct_open(CONNTRACK, 0);
+ STATE(resync) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(resync)== NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -378,13 +504,13 @@ init(void)
}
nfct_callback_register(STATE(resync),
NFCT_T_ALL,
- STATE(mode)->internal->resync,
+ STATE(mode)->internal->ct.resync,
NULL);
register_fd(nfct_fd(STATE(resync)), STATE(fds));
fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
- STATE(dump) = nfct_open(CONNTRACK, 0);
+ STATE(dump) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(dump) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -394,13 +520,26 @@ init(void)
nfct_callback_register(STATE(dump), NFCT_T_ALL,
dump_handler, NULL);
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register(STATE(dump), NFCT_T_ALL,
+ exp_dump_handler, NULL);
+ }
+
if (nl_dump_conntrack_table(STATE(dump)) == -1) {
dlog(LOG_ERR, "can't get kernel conntrack table");
return -1;
}
+
+ if (CONFIG(flags) & CTD_EXPECT) {
+ if (nl_dump_expect_table(STATE(dump)) == -1) {
+ dlog(LOG_ERR, "can't get kernel "
+ "expect table");
+ return -1;
+ }
+ }
}
- STATE(get) = nfct_open(CONNTRACK, 0);
+ STATE(get) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(get) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -409,7 +548,12 @@ init(void)
}
nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL);
- STATE(flush) = nfct_open(CONNTRACK, 0);
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register(STATE(get), NFCT_T_ALL,
+ exp_get_handler, NULL);
+ }
+
+ STATE(flush) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(flush) == NULL) {
dlog(LOG_ERR, "cannot open flusher handler");
return -1;
@@ -423,6 +567,29 @@ init(void)
dlog(LOG_NOTICE, "running in polling mode");
} else {
init_alarm(&STATE(resync_alarm), NULL, do_overrun_resync_alarm);
+ /*
+ * The last nfct handler that we register is the event handler.
+ * The reason to do this is that we may receive events while
+ * populating the internal cache. Thus, we hit ENOBUFS
+ * prematurely. However, if we open the event handler before
+ * populating the internal cache, we may still lose events
+ * that have occured during the population.
+ */
+ STATE(event) = nl_init_event_handler();
+ if (STATE(event) == NULL) {
+ dlog(LOG_ERR, "can't open netlink handler: %s",
+ strerror(errno));
+ dlog(LOG_ERR, "no ctnetlink kernel support?");
+ return -1;
+ }
+ nfct_callback_register2(STATE(event), NFCT_T_ALL,
+ event_handler, NULL);
+
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register2(STATE(event), NFCT_T_ALL,
+ exp_event_handler, NULL);
+ }
+ register_fd(nfct_fd(STATE(event)), STATE(fds));
}
/* Signals handling */
@@ -451,7 +618,7 @@ init(void)
return 0;
}
-static void __run(struct timeval *next_alarm)
+static void run_events(struct timeval *next_alarm)
{
int ret;
fd_set readfds = STATE(fds)->readfds;
@@ -473,77 +640,70 @@ static void __run(struct timeval *next_alarm)
if (FD_ISSET(STATE(local).fd, &readfds))
do_local_server_step(&STATE(local), NULL, local_handler);
- if (!(CONFIG(flags) & CTD_POLL)) {
- /* conntrack event has happened */
- if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
- ret = nfct_catch(STATE(event));
- /* reset event iteration limit counter */
- STATE(event_iterations_limit) =
- CONFIG(event_iterations_limit);
- if (ret == -1) {
- switch(errno) {
- case ENOBUFS:
- /* We have hit ENOBUFS, it's likely that we are
- * losing events. Two possible situations may
- * trigger this error:
- *
- * 1) The netlink receiver buffer is too small:
- * increasing the netlink buffer size should
- * be enough. However, some event messages
- * got lost. We have to resync ourselves
- * with the kernel table conntrack table to
- * resolve the inconsistency.
- *
- * 2) The receiver is too slow to process the
- * netlink messages so that the queue gets
- * full quickly. This generally happens
- * if the system is under heavy workload
- * (busy CPU). In this case, increasing the
- * size of the netlink receiver buffer
- * would not help anymore since we would
- * be delaying the overrun. Moreover, we
- * should avoid resynchronizations. We
- * should do our best here and keep
- * replicating as much states as possible.
- * If workload lowers at some point,
- * we resync ourselves.
- */
- nl_resize_socket_buffer(STATE(event));
- if (CONFIG(nl_overrun_resync) > 0 &&
- STATE(mode)->internal->flags &
- INTERNAL_F_RESYNC) {
- add_alarm(&STATE(resync_alarm),
- CONFIG(nl_overrun_resync),0);
- }
- STATE(stats).nl_catch_event_failed++;
- STATE(stats).nl_overrun++;
- break;
- case ENOENT:
- /*
- * We received a message from another
- * netfilter subsystem that we are not
- * interested in. Just ignore it.
- */
- break;
- case EAGAIN:
- break;
- default:
- STATE(stats).nl_catch_event_failed++;
- break;
- }
+ /* we have receive an event from ctnetlink */
+ if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
+ ret = nfct_catch(STATE(event));
+ /* reset event iteration limit counter */
+ STATE(event_iterations_limit) = CONFIG(event_iterations_limit);
+ if (ret == -1) {
+ switch(errno) {
+ case ENOBUFS:
+ /* We have hit ENOBUFS, it's likely that we are
+ * losing events. Two possible situations may
+ * trigger this error:
+ *
+ * 1) The netlink receiver buffer is too small:
+ * increasing the netlink buffer size should
+ * be enough. However, some event messages
+ * got lost. We have to resync ourselves
+ * with the kernel table conntrack table to
+ * resolve the inconsistency.
+ *
+ * 2) The receiver is too slow to process the
+ * netlink messages so that the queue gets
+ * full quickly. This generally happens
+ * if the system is under heavy workload
+ * (busy CPU). In this case, increasing the
+ * size of the netlink receiver buffer
+ * would not help anymore since we would
+ * be delaying the overrun. Moreover, we
+ * should avoid resynchronizations. We
+ * should do our best here and keep
+ * replicating as much states as possible.
+ * If workload lowers at some point,
+ * we resync ourselves.
+ */
+ nl_resize_socket_buffer(STATE(event));
+ if (CONFIG(nl_overrun_resync) > 0 &&
+ STATE(mode)->internal->flags & INTERNAL_F_RESYNC) {
+ add_alarm(&STATE(resync_alarm),
+ CONFIG(nl_overrun_resync),0);
}
+ STATE(stats).nl_catch_event_failed++;
+ STATE(stats).nl_overrun++;
+ break;
+ case ENOENT:
+ /*
+ * We received a message from another
+ * netfilter subsystem that we are not
+ * interested in. Just ignore it.
+ */
+ break;
+ case EAGAIN:
+ /* No more events to receive, try later. */
+ break;
+ default:
+ STATE(stats).nl_catch_event_failed++;
+ break;
}
- if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
- nfct_catch(STATE(resync));
- if (STATE(mode)->internal->purge)
- STATE(mode)->internal->purge();
- }
- } else {
- /* using polling mode */
- if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
- nfct_catch(STATE(resync));
}
}
+ /* we previously requested a resync due to buffer overrun. */
+ if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
+ nfct_catch(STATE(resync));
+ if (STATE(mode)->internal->ct.purge)
+ STATE(mode)->internal->ct.purge();
+ }
if (STATE(mode)->run)
STATE(mode)->run(&readfds);
@@ -551,8 +711,40 @@ static void __run(struct timeval *next_alarm)
sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
}
-void __attribute__((noreturn))
-run(void)
+static void run_polling(struct timeval *next_alarm)
+{
+ int ret;
+ fd_set readfds = STATE(fds)->readfds;
+
+ ret = select(STATE(fds)->maxfd + 1, &readfds, NULL, NULL, next_alarm);
+ if (ret == -1) {
+ /* interrupted syscall, retry */
+ if (errno == EINTR)
+ return;
+
+ STATE(stats).select_failed++;
+ return;
+ }
+
+ /* signals are racy */
+ sigprocmask(SIG_BLOCK, &STATE(block), NULL);
+
+ /* order received via UNIX socket */
+ if (FD_ISSET(STATE(local).fd, &readfds))
+ do_local_server_step(&STATE(local), NULL, local_handler);
+
+ /* we requested a dump from the kernel via polling_alarm */
+ if (FD_ISSET(nfct_fd(STATE(resync)), &readfds))
+ nfct_catch(STATE(resync));
+
+ if (STATE(mode)->run)
+ STATE(mode)->run(&readfds);
+
+ sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
+}
+
+static void __attribute__((noreturn))
+do_run(void (*run_step)(struct timeval *next_alarm))
{
struct timeval next_alarm;
struct timeval *next = NULL;
@@ -567,6 +759,15 @@ run(void)
next = get_next_alarm_run(&next_alarm);
sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
- __run(next);
+ run_step(next);
+ }
+}
+
+void run(void)
+{
+ if (CONFIG(flags) & CTD_POLL) {
+ do_run(run_polling);
+ } else {
+ do_run(run_events);
}
}
diff --git a/src/stats-mode.c b/src/stats-mode.c
index 0403ce2..b768033 100644
--- a/src/stats-mode.c
+++ b/src/stats-mode.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -37,7 +38,9 @@ static int init_stats(void)
}
memset(state.stats, 0, sizeof(struct ct_stats_state));
- STATE_STATS(cache) = cache_create("stats", NO_FEATURES, NULL);
+ STATE_STATS(cache) = cache_create("stats", CACHE_T_CT,
+ NO_FEATURES, NULL,
+ &cache_stats_ct_ops);
if (!STATE_STATS(cache)) {
dlog(LOG_ERR, "can't allocate memory for the "
"external cache");
@@ -59,14 +62,14 @@ static int local_handler_stats(int fd, int type, void *data)
int ret = LOCAL_RET_OK;
switch(type) {
- case DUMP_INTERNAL:
+ case CT_DUMP_INTERNAL:
cache_dump(STATE_STATS(cache), fd, NFCT_O_PLAIN);
break;
- case DUMP_INT_XML:
+ case CT_DUMP_INT_XML:
cache_dump(STATE_STATS(cache), fd, NFCT_O_XML);
break;
- case FLUSH_CACHE:
- case FLUSH_INT_CACHE:
+ case CT_FLUSH_CACHE:
+ case CT_FLUSH_INT_CACHE:
dlog(LOG_NOTICE, "flushing caches");
cache_flush(STATE_STATS(cache));
break;
@@ -88,7 +91,7 @@ static int local_handler_stats(int fd, int type, void *data)
return ret;
}
-static void populate_stats(struct nf_conntrack *ct)
+static void stats_populate(struct nf_conntrack *ct)
{
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
@@ -100,7 +103,7 @@ static void populate_stats(struct nf_conntrack *ct)
cache_update_force(STATE_STATS(cache), ct);
}
-static int resync_stats(enum nf_conntrack_msg_type type,
+static int stats_resync(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
{
@@ -125,23 +128,22 @@ static int purge_step(void *data1, void *data2)
struct cache_object *obj = data2;
STATE(get_retval) = 0;
- nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */
+ nl_get_conntrack(STATE(get), obj->ptr); /* modifies STATE(get_retval) */
if (!STATE(get_retval)) {
cache_del(STATE_STATS(cache), obj);
- dlog_ct(STATE(stats_log), obj->ct, NFCT_O_PLAIN);
+ dlog_ct(STATE(stats_log), obj->ptr, NFCT_O_PLAIN);
cache_object_free(obj);
}
return 0;
}
-static void purge_stats(void)
+static void stats_purge(void)
{
cache_iterate(STATE_STATS(cache), NULL, purge_step);
}
-static void
-event_new_stats(struct nf_conntrack *ct, int origin)
+static void stats_event_new(struct nf_conntrack *ct, int origin)
{
int id;
struct cache_object *obj;
@@ -162,15 +164,13 @@ event_new_stats(struct nf_conntrack *ct, int origin)
return;
}
-static void
-event_update_stats(struct nf_conntrack *ct, int origin)
+static void stats_event_upd(struct nf_conntrack *ct, int origin)
{
nfct_attr_unset(ct, ATTR_TIMEOUT);
cache_update_force(STATE_STATS(cache), ct);
}
-static int
-event_destroy_stats(struct nf_conntrack *ct, int origin)
+static int stats_event_del(struct nf_conntrack *ct, int origin)
{
int id;
struct cache_object *obj;
@@ -189,12 +189,14 @@ event_destroy_stats(struct nf_conntrack *ct, int origin)
static struct internal_handler internal_cache_stats = {
.flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC,
- .populate = populate_stats,
- .resync = resync_stats,
- .purge = purge_stats,
- .new = event_new_stats,
- .update = event_update_stats,
- .destroy = event_destroy_stats
+ .ct = {
+ .populate = stats_populate,
+ .resync = stats_resync,
+ .purge = stats_purge,
+ .new = stats_event_new,
+ .upd = stats_event_upd,
+ .del = stats_event_del,
+ },
};
struct ct_mode stats_mode = {
diff --git a/src/sync-alarm.c b/src/sync-alarm.c
index 0fc7943..acaf5e6 100644
--- a/src/sync-alarm.c
+++ b/src/sync-alarm.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -28,6 +29,7 @@
struct cache_alarm {
struct queue_node qnode;
+ struct cache_object *obj;
struct alarm_block alarm;
};
@@ -41,7 +43,7 @@ static void refresher(struct alarm_block *a, void *data)
random() % CONFIG(refresh) + 1,
((random() % 5 + 1) * 200000) - 1);
- alarm_enqueue(obj, NET_T_STATE_UPD);
+ alarm_enqueue(obj, NET_T_STATE_CT_UPD);
}
static void cache_alarm_add(struct cache_object *obj, void *data)
@@ -49,6 +51,7 @@ static void cache_alarm_add(struct cache_object *obj, void *data)
struct cache_alarm *ca = data;
queue_node_init(&ca->qnode, Q_ELEM_OBJ);
+ ca->obj = obj;
init_alarm(&ca->alarm, obj, refresher);
add_alarm(&ca->alarm,
random() % CONFIG(refresh) + 1,
@@ -109,9 +112,8 @@ static int alarm_recv(const struct nethdr *net)
static void alarm_enqueue(struct cache_object *obj, int query)
{
- struct cache_alarm *ca =
- cache_get_extra(STATE(mode)->internal->data, obj);
- if (queue_add(STATE_SYNC(tx_queue), &ca->qnode))
+ struct cache_alarm *ca = cache_get_extra(obj);
+ if (queue_add(STATE_SYNC(tx_queue), &ca->qnode) > 0)
cache_object_get(obj);
}
@@ -131,15 +133,13 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
break;
case Q_ELEM_OBJ: {
struct cache_alarm *ca;
- struct cache_object *obj;
int type;
ca = (struct cache_alarm *)n;
- obj = cache_data_get_object(STATE(mode)->internal->data, ca);
- type = object_status_to_network_type(obj->status);
- net = BUILD_NETMSG(obj->ct, type);
+ type = object_status_to_network_type(ca->obj);
+ net = ca->obj->cache->ops->build_msg(ca->obj, type);
multichannel_send(STATE_SYNC(channel), net);
- cache_object_put(obj);
+ cache_object_put(ca->obj);
break;
}
}
diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c
index 86edeab..1bc2d9f 100644
--- a/src/sync-ftfw.c
+++ b/src/sync-ftfw.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -54,12 +55,14 @@ static int say_hello_back;
struct cache_ftfw {
struct queue_node qnode;
+ struct cache_object *obj;
uint32_t seq;
};
static void cache_ftfw_add(struct cache_object *obj, void *data)
{
struct cache_ftfw *cn = data;
+ cn->obj = obj;
/* These nodes are not inserted in the list */
queue_node_init(&cn->qnode, Q_ELEM_OBJ);
}
@@ -107,7 +110,8 @@ static void tx_queue_add_ctlmsg(uint32_t flags, uint32_t from, uint32_t to)
ack->from = from;
ack->to = to;
- queue_add(STATE_SYNC(tx_queue), &qobj->qnode);
+ if (queue_add(STATE_SYNC(tx_queue), &qobj->qnode) < 0)
+ queue_object_free(qobj);
}
static void tx_queue_add_ctlmsg2(uint32_t flags)
@@ -123,7 +127,8 @@ static void tx_queue_add_ctlmsg2(uint32_t flags)
ctl->type = NET_T_CTL;
ctl->flags = flags;
- queue_add(STATE_SYNC(tx_queue), &qobj->qnode);
+ if (queue_add(STATE_SYNC(tx_queue), &qobj->qnode) < 0)
+ queue_object_free(qobj);
}
/* this function is called from the alarm framework */
@@ -166,14 +171,13 @@ static void ftfw_kill(void)
static int do_cache_to_tx(void *data1, void *data2)
{
struct cache_object *obj = data2;
- struct cache_ftfw *cn =
- cache_get_extra(STATE(mode)->internal->data, obj);
+ struct cache_ftfw *cn = cache_get_extra(obj);
if (queue_in(rs_queue, &cn->qnode)) {
queue_del(&cn->qnode);
queue_add(STATE_SYNC(tx_queue), &cn->qnode);
} else {
- if (queue_add(STATE_SYNC(tx_queue), &cn->qnode))
+ if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0)
cache_object_get(obj);
}
return 0;
@@ -225,7 +229,9 @@ static int ftfw_local(int fd, int type, void *data)
break;
case SEND_BULK:
dlog(LOG_NOTICE, "sending bulk update");
- cache_iterate(STATE(mode)->internal->data,
+ cache_iterate(STATE(mode)->internal->ct.data,
+ NULL, do_cache_to_tx);
+ cache_iterate(STATE(mode)->internal->exp.data,
NULL, do_cache_to_tx);
break;
case STATS_RSQUEUE:
@@ -300,13 +306,11 @@ static int rs_queue_empty(struct queue_node *n, const void *data)
}
case Q_ELEM_OBJ: {
struct cache_ftfw *cn;
- struct cache_object *obj;
cn = (struct cache_ftfw *) n;
if (h == NULL) {
queue_del(n);
- obj = cache_data_get_object(STATE(mode)->internal->data, cn);
- cache_object_put(obj);
+ cache_object_put(cn->obj);
return 0;
}
if (before(cn->seq, h->from))
@@ -316,8 +320,7 @@ static int rs_queue_empty(struct queue_node *n, const void *data)
dp("queue: deleting from queue (seq=%u)\n", cn->seq);
queue_del(n);
- obj = cache_data_get_object(STATE(mode)->internal->data, cn);
- cache_object_put(obj);
+ cache_object_put(cn->obj);
break;
}
}
@@ -349,7 +352,10 @@ static int digest_msg(const struct nethdr *net)
} else if (IS_RESYNC(net)) {
dp("RESYNC ALL\n");
- cache_iterate(STATE(mode)->internal->data, NULL, do_cache_to_tx);
+ cache_iterate(STATE(mode)->internal->ct.data, NULL,
+ do_cache_to_tx);
+ cache_iterate(STATE(mode)->internal->exp.data, NULL,
+ do_cache_to_tx);
return MSG_CTL;
} else if (IS_ALIVE(net))
@@ -463,11 +469,9 @@ static void rs_queue_purge_full(void)
}
case Q_ELEM_OBJ: {
struct cache_ftfw *cn;
- struct cache_object *obj;
cn = (struct cache_ftfw *)n;
- obj = cache_data_get_object(STATE(mode)->internal->data, cn);
- cache_object_put(obj);
+ cache_object_put(cn->obj);
break;
}
}
@@ -509,14 +513,12 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
}
case Q_ELEM_OBJ: {
struct cache_ftfw *cn;
- struct cache_object *obj;
int type;
struct nethdr *net;
cn = (struct cache_ftfw *)n;
- obj = cache_data_get_object(STATE(mode)->internal->data, cn);
- type = object_status_to_network_type(obj->status);
- net = BUILD_NETMSG(obj->ct, type);
+ type = object_status_to_network_type(cn->obj);
+ net = cn->obj->cache->ops->build_msg(cn->obj, type);
nethdr_set_hello(net);
dp("tx_list sq: %u fl:%u len:%u\n",
@@ -548,13 +550,12 @@ static void ftfw_xmit(void)
static void ftfw_enqueue(struct cache_object *obj, int type)
{
- struct cache_ftfw *cn =
- cache_get_extra(STATE(mode)->internal->data, obj);
+ struct cache_ftfw *cn = cache_get_extra(obj);
if (queue_in(rs_queue, &cn->qnode)) {
queue_del(&cn->qnode);
queue_add(STATE_SYNC(tx_queue), &cn->qnode);
} else {
- if (queue_add(STATE_SYNC(tx_queue), &cn->qnode))
+ if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0)
cache_object_get(obj);
}
}
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 3fa0d11..2505631 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -40,11 +41,47 @@
#include <net/if.h>
#include <fcntl.h>
+static struct nf_conntrack *msg2ct_alloc(struct nethdr *net, size_t remain)
+{
+ struct nf_conntrack *ct;
+
+ /* TODO: add stats on ENOMEM errors in the future. */
+ ct = nfct_new();
+ if (ct == NULL)
+ return NULL;
+
+ if (msg2ct(ct, net, remain) == -1) {
+ STATE_SYNC(error).msg_rcv_malformed++;
+ STATE_SYNC(error).msg_rcv_bad_payload++;
+ nfct_destroy(ct);
+ return NULL;
+ }
+ return ct;
+}
+
+static struct nf_expect *msg2exp_alloc(struct nethdr *net, size_t remain)
+{
+ struct nf_expect *exp;
+
+ /* TODO: add stats on ENOMEM errors in the future. */
+ exp = nfexp_new();
+ if (exp == NULL)
+ return NULL;
+
+ if (msg2exp(exp, net, remain) == -1) {
+ STATE_SYNC(error).msg_rcv_malformed++;
+ STATE_SYNC(error).msg_rcv_bad_payload++;
+ nfexp_destroy(exp);
+ return NULL;
+ }
+ return exp;
+}
+
static void
do_channel_handler_step(int i, struct nethdr *net, size_t remain)
{
- char __ct[nfct_maxsize()];
- struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct;
+ struct nf_conntrack *ct = NULL;
+ struct nf_expect *exp = NULL;
if (net->version != CONNTRACKD_PROTOCOL_VERSION) {
STATE_SYNC(error).msg_rcv_malformed++;
@@ -74,29 +111,53 @@ do_channel_handler_step(int i, struct nethdr *net, size_t remain)
STATE_SYNC(error).msg_rcv_bad_type++;
return;
}
- memset(ct, 0, sizeof(__ct));
-
- if (parse_payload(ct, net, remain) == -1) {
- STATE_SYNC(error).msg_rcv_malformed++;
- STATE_SYNC(error).msg_rcv_bad_payload++;
- return;
- }
switch(net->type) {
- case NET_T_STATE_NEW:
- STATE_SYNC(external)->new(ct);
+ case NET_T_STATE_CT_NEW:
+ ct = msg2ct_alloc(net, remain);
+ if (ct == NULL)
+ return;
+ STATE_SYNC(external)->ct.new(ct);
+ break;
+ case NET_T_STATE_CT_UPD:
+ ct = msg2ct_alloc(net, remain);
+ if (ct == NULL)
+ return;
+ STATE_SYNC(external)->ct.upd(ct);
break;
- case NET_T_STATE_UPD:
- STATE_SYNC(external)->update(ct);
+ case NET_T_STATE_CT_DEL:
+ ct = msg2ct_alloc(net, remain);
+ if (ct == NULL)
+ return;
+ STATE_SYNC(external)->ct.del(ct);
break;
- case NET_T_STATE_DEL:
- STATE_SYNC(external)->destroy(ct);
+ case NET_T_STATE_EXP_NEW:
+ exp = msg2exp_alloc(net, remain);
+ if (exp == NULL)
+ return;
+ STATE_SYNC(external)->exp.new(exp);
+ break;
+ case NET_T_STATE_EXP_UPD:
+ exp = msg2exp_alloc(net, remain);
+ if (exp == NULL)
+ return;
+ STATE_SYNC(external)->exp.upd(exp);
+ break;
+ case NET_T_STATE_EXP_DEL:
+ exp = msg2exp_alloc(net, remain);
+ if (exp == NULL)
+ return;
+ STATE_SYNC(external)->exp.del(exp);
break;
default:
STATE_SYNC(error).msg_rcv_malformed++;
STATE_SYNC(error).msg_rcv_bad_type++;
break;
}
+ if (ct != NULL)
+ nfct_destroy(ct);
+ if (exp != NULL)
+ nfexp_destroy(exp);
}
static char __net[65536]; /* XXX: maximum MTU for IPv4 */
@@ -247,7 +308,7 @@ static void do_reset_cache_alarm(struct alarm_block *a, void *data)
exit(EXIT_SUCCESS);
}
/* this is not required if events don't get lost */
- STATE(mode)->internal->flush();
+ STATE(mode)->internal->ct.flush();
}
static int init_sync(void)
@@ -330,7 +391,7 @@ static int init_sync(void)
STATE(fds)) == -1)
return -1;
- STATE_SYNC(commit).h = nfct_open(CONNTRACK, 0);
+ STATE_SYNC(commit).h = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE_SYNC(commit).h == NULL) {
dlog(LOG_ERR, "can't create handler to commit");
return -1;
@@ -346,6 +407,7 @@ static int init_sync(void)
STATE(fds)) == -1) {
return -1;
}
+ STATE_SYNC(commit).clientfd = -1;
init_alarm(&STATE_SYNC(reset_cache_alarm), NULL, do_reset_cache_alarm);
@@ -380,8 +442,30 @@ static void run_sync(fd_set *readfds)
interface_handler();
if (FD_ISSET(get_read_evfd(STATE_SYNC(commit).evfd), readfds)) {
+ int ret;
+
read_evfd(STATE_SYNC(commit).evfd);
- STATE_SYNC(external)->commit(STATE_SYNC(commit).h, 0);
+
+ ret = STATE_SYNC(commit).rq[0].cb(STATE_SYNC(commit).h, 0);
+ if (ret == 0) {
+ /* we still have things in the callback queue. */
+ if (STATE_SYNC(commit).rq[1].cb) {
+ int fd = STATE_SYNC(commit).clientfd;
+
+ STATE_SYNC(commit).rq[0].cb =
+ STATE_SYNC(commit).rq[1].cb;
+
+ STATE_SYNC(commit).rq[1].cb = NULL;
+
+ STATE_SYNC(commit).clientfd = -1;
+ STATE_SYNC(commit).rq[0].cb(
+ STATE_SYNC(commit).h, fd);
+ } else {
+ /* Close the client socket now, we're done. */
+ close(STATE_SYNC(commit).clientfd);
+ STATE_SYNC(commit).clientfd = -1;
+ }
+ }
}
/* flush pending messages */
@@ -458,48 +542,62 @@ static void dump_stats_sync_extended(int fd)
send(fd, buf, size, 0);
}
+static int local_commit(int fd)
+{
+ int ret;
+
+ /* delete the reset alarm if any before committing */
+ del_alarm(&STATE_SYNC(reset_cache_alarm));
+
+ ret = STATE_SYNC(commit).rq[0].cb(STATE_SYNC(commit).h, fd);
+ if (ret == -1) {
+ dlog(LOG_NOTICE, "commit already in progress, skipping");
+ ret = LOCAL_RET_OK;
+ } else if (ret == 0) {
+ /* we've finished the commit. */
+ ret = LOCAL_RET_OK;
+ } else {
+ /* Keep open the client, we want synchronous commit. */
+ ret = LOCAL_RET_STOLEN;
+ }
+ return ret;
+}
+
/* handler for requests coming via UNIX socket */
static int local_handler_sync(int fd, int type, void *data)
{
int ret = LOCAL_RET_OK;
switch(type) {
- case DUMP_INTERNAL:
- ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
- if (ret == 0) {
- STATE(mode)->internal->dump(fd, NFCT_O_PLAIN);
+ case CT_DUMP_INTERNAL:
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE(mode)->internal->ct.dump(fd, NFCT_O_PLAIN);
exit(EXIT_SUCCESS);
}
break;
- case DUMP_EXTERNAL:
- ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
- if (ret == 0) {
- STATE_SYNC(external)->dump(fd, NFCT_O_PLAIN);
+ case CT_DUMP_EXTERNAL:
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE_SYNC(external)->ct.dump(fd, NFCT_O_PLAIN);
exit(EXIT_SUCCESS);
}
break;
- case DUMP_INT_XML:
- ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
- if (ret == 0) {
- STATE(mode)->internal->dump(fd, NFCT_O_XML);
+ case CT_DUMP_INT_XML:
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE(mode)->internal->ct.dump(fd, NFCT_O_XML);
exit(EXIT_SUCCESS);
}
break;
- case DUMP_EXT_XML:
- ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
- if (ret == 0) {
- STATE_SYNC(external)->dump(fd, NFCT_O_XML);
+ case CT_DUMP_EXT_XML:
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE_SYNC(external)->ct.dump(fd, NFCT_O_XML);
exit(EXIT_SUCCESS);
}
break;
- case COMMIT:
- /* delete the reset alarm if any before committing */
- del_alarm(&STATE_SYNC(reset_cache_alarm));
-
- dlog(LOG_NOTICE, "committing external cache");
- STATE_SYNC(external)->commit(STATE_SYNC(commit).h, fd);
- /* Keep the client socket open, we want synchronous commits. */
- ret = LOCAL_RET_STOLEN;
+ case CT_COMMIT:
+ dlog(LOG_NOTICE, "committing conntrack cache");
+ STATE_SYNC(commit).rq[0].cb = STATE_SYNC(external)->ct.commit;
+ STATE_SYNC(commit).rq[1].cb = NULL;
+ ret = local_commit(fd);
break;
case RESET_TIMERS:
if (!alarm_pending(&STATE_SYNC(reset_cache_alarm))) {
@@ -509,29 +607,29 @@ static int local_handler_sync(int fd, int type, void *data)
CONFIG(purge_timeout), 0);
}
break;
- case FLUSH_CACHE:
+ case CT_FLUSH_CACHE:
/* inmediate flush, remove pending flush scheduled if any */
del_alarm(&STATE_SYNC(reset_cache_alarm));
dlog(LOG_NOTICE, "flushing caches");
- STATE(mode)->internal->flush();
- STATE_SYNC(external)->flush();
+ STATE(mode)->internal->ct.flush();
+ STATE_SYNC(external)->ct.flush();
break;
- case FLUSH_INT_CACHE:
+ case CT_FLUSH_INT_CACHE:
/* inmediate flush, remove pending flush scheduled if any */
del_alarm(&STATE_SYNC(reset_cache_alarm));
dlog(LOG_NOTICE, "flushing internal cache");
- STATE(mode)->internal->flush();
+ STATE(mode)->internal->ct.flush();
break;
- case FLUSH_EXT_CACHE:
+ case CT_FLUSH_EXT_CACHE:
dlog(LOG_NOTICE, "flushing external cache");
- STATE_SYNC(external)->flush();
+ STATE_SYNC(external)->ct.flush();
break;
case KILL:
killer(0);
break;
case STATS:
- STATE(mode)->internal->stats(fd);
- STATE_SYNC(external)->stats(fd);
+ STATE(mode)->internal->ct.stats(fd);
+ STATE_SYNC(external)->ct.stats(fd);
dump_traffic_stats(fd);
multichannel_stats(STATE_SYNC(channel), fd);
dump_stats_sync(fd);
@@ -541,8 +639,8 @@ static int local_handler_sync(int fd, int type, void *data)
multichannel_stats(STATE_SYNC(channel), fd);
break;
case STATS_CACHE:
- STATE(mode)->internal->stats_ext(fd);
- STATE_SYNC(external)->stats_ext(fd);
+ STATE(mode)->internal->ct.stats_ext(fd);
+ STATE_SYNC(external)->ct.stats_ext(fd);
break;
case STATS_LINK:
multichannel_stats_extended(STATE_SYNC(channel),
@@ -551,6 +649,63 @@ static int local_handler_sync(int fd, int type, void *data)
case STATS_QUEUE:
queue_stats_show(fd);
break;
+ case EXP_STATS:
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ break;
+
+ STATE(mode)->internal->exp.stats(fd);
+ STATE_SYNC(external)->exp.stats(fd);
+ dump_traffic_stats(fd);
+ multichannel_stats(STATE_SYNC(channel), fd);
+ dump_stats_sync(fd);
+ break;
+ case EXP_DUMP_INTERNAL:
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ break;
+
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE(mode)->internal->exp.dump(fd, NFCT_O_PLAIN);
+ exit(EXIT_SUCCESS);
+ }
+ break;
+ case EXP_DUMP_EXTERNAL:
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ break;
+
+ if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) {
+ STATE_SYNC(external)->exp.dump(fd, NFCT_O_PLAIN);
+ exit(EXIT_SUCCESS);
+ }
+ break;
+ case EXP_COMMIT:
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ break;
+
+ dlog(LOG_NOTICE, "committing expectation cache");
+ STATE_SYNC(commit).rq[0].cb = STATE_SYNC(external)->exp.commit;
+ STATE_SYNC(commit).rq[1].cb = NULL;
+ local_commit(fd);
+ break;
+ case ALL_FLUSH_CACHE:
+ dlog(LOG_NOTICE, "flushing caches");
+ STATE(mode)->internal->ct.flush();
+ STATE_SYNC(external)->ct.flush();
+ if (CONFIG(flags) & CTD_EXPECT) {
+ STATE(mode)->internal->exp.flush();
+ STATE_SYNC(external)->exp.flush();
+ }
+ break;
+ case ALL_COMMIT:
+ dlog(LOG_NOTICE, "committing all external caches");
+ STATE_SYNC(commit).rq[0].cb = STATE_SYNC(external)->ct.commit;
+ if (CONFIG(flags) & CTD_EXPECT) {
+ STATE_SYNC(commit).rq[1].cb =
+ STATE_SYNC(external)->exp.commit;
+ } else {
+ STATE_SYNC(commit).rq[1].cb = NULL;
+ }
+ local_commit(fd);
+ break;
default:
if (STATE_SYNC(sync)->local)
ret = STATE_SYNC(sync)->local(fd, type, data);
diff --git a/src/sync-notrack.c b/src/sync-notrack.c
index c4ad941..a7df4e7 100644
--- a/src/sync-notrack.c
+++ b/src/sync-notrack.c
@@ -1,6 +1,7 @@
/*
- * (C) 2008 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011 by Vyatta Inc. <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -33,12 +34,14 @@ static struct alarm_block alive_alarm;
struct cache_notrack {
struct queue_node qnode;
+ struct cache_object *obj;
};
static void cache_notrack_add(struct cache_object *obj, void *data)
{
struct cache_notrack *cn = data;
queue_node_init(&cn->qnode, Q_ELEM_OBJ);
+ cn->obj = obj;
}
static void cache_notrack_del(struct cache_object *obj, void *data)
@@ -68,15 +71,15 @@ static void tx_queue_add_ctlmsg(uint32_t flags, uint32_t from, uint32_t to)
ack->from = from;
ack->to = to;
- queue_add(STATE_SYNC(tx_queue), &qobj->qnode);
+ if (queue_add(STATE_SYNC(tx_queue), &qobj->qnode) < 0)
+ queue_object_free(qobj);
}
static int do_cache_to_tx(void *data1, void *data2)
{
struct cache_object *obj = data2;
- struct cache_notrack *cn =
- cache_get_extra(STATE(mode)->internal->data, obj);
- if (queue_add(STATE_SYNC(tx_queue), &cn->qnode))
+ struct cache_notrack *cn = cache_get_extra(obj);
+ if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0)
cache_object_get(obj);
return 0;
}
@@ -86,7 +89,7 @@ static int kernel_resync_cb(enum nf_conntrack_msg_type type,
{
struct nethdr *net;
- net = BUILD_NETMSG(ct, NET_T_STATE_NEW);
+ net = BUILD_NETMSG_FROM_CT(ct, NET_T_STATE_CT_NEW);
multichannel_send(STATE_SYNC(channel), net);
return NFCT_CB_CONTINUE;
@@ -99,7 +102,7 @@ static void kernel_resync(void)
u_int32_t family = AF_UNSPEC;
int ret;
- h = nfct_open(CONNTRACK, 0);
+ h = nfct_open(CONFIG(netlink).subsys_id, 0);
if (h == NULL) {
dlog(LOG_ERR, "can't allocate memory for the internal cache");
return;
@@ -126,7 +129,9 @@ static int notrack_local(int fd, int type, void *data)
if (CONFIG(sync).internal_cache_disable) {
kernel_resync();
} else {
- cache_iterate(STATE(mode)->internal->data,
+ cache_iterate(STATE(mode)->internal->ct.data,
+ NULL, do_cache_to_tx);
+ cache_iterate(STATE(mode)->internal->exp.data,
NULL, do_cache_to_tx);
}
break;
@@ -147,7 +152,9 @@ static int digest_msg(const struct nethdr *net)
if (CONFIG(sync).internal_cache_disable) {
kernel_resync();
} else {
- cache_iterate(STATE(mode)->internal->data,
+ cache_iterate(STATE(mode)->internal->ct.data,
+ NULL, do_cache_to_tx);
+ cache_iterate(STATE(mode)->internal->exp.data,
NULL, do_cache_to_tx);
}
return MSG_CTL;
@@ -190,19 +197,17 @@ static int tx_queue_xmit(struct queue_node *n, const void *data2)
break;
}
case Q_ELEM_OBJ: {
- struct cache_ftfw *cn;
- struct cache_object *obj;
+ struct cache_notrack *cn;
int type;
struct nethdr *net;
- cn = (struct cache_ftfw *)n;
- obj = cache_data_get_object(STATE(mode)->internal->data, cn);
- type = object_status_to_network_type(obj->status);;
- net = BUILD_NETMSG(obj->ct, type);
+ cn = (struct cache_notrack *)n;
+ type = object_status_to_network_type(cn->obj);
+ net = cn->obj->cache->ops->build_msg(cn->obj, type);
multichannel_send(STATE_SYNC(channel), net);
queue_del(n);
- cache_object_put(obj);
+ cache_object_put(cn->obj);
break;
}
}
@@ -217,9 +222,8 @@ static void notrack_xmit(void)
static void notrack_enqueue(struct cache_object *obj, int query)
{
- struct cache_notrack *cn =
- cache_get_extra(STATE(mode)->internal->data, obj);
- if (queue_add(STATE_SYNC(tx_queue), &cn->qnode))
+ struct cache_notrack *cn = cache_get_extra(obj);
+ if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0)
cache_object_get(obj);
}
@@ -236,7 +240,8 @@ static void tx_queue_add_ctlmsg2(uint32_t flags)
ctl->type = NET_T_CTL;
ctl->flags = flags;
- queue_add(STATE_SYNC(tx_queue), &qobj->qnode);
+ if (queue_add(STATE_SYNC(tx_queue), &qobj->qnode) < 0)
+ queue_object_free(qobj);
}
static void do_alive_alarm(struct alarm_block *a, void *data)