summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-05-06 17:36:13 +0000
committer/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-05-06 17:36:13 +0000
commit37ef0a638d19ca5145f6d4868e42b7aa2c735d46 (patch)
tree15db83ddcc3a69847f092333174ebeb7f398c602
parent548e277890c2c06d9a1aa4a2536eb1601a918bc5 (diff)
downloadconntrack-tools-37ef0a638d19ca5145f6d4868e42b7aa2c735d46.tar.gz
conntrack-tools-37ef0a638d19ca5145f6d4868e42b7aa2c735d46.zip
- add warning note to ctnl_test.c: old API is deprecated
- split expect_api_test.c into small example files expect_*.c - introduce alias tags for original tuple attributes - introduce nfexp_sizeof and nfexp_maxsize - build expectation attributes iif they are set - fix l3num setting in expect/build.c
-rw-r--r--conntrack.89
-rw-r--r--examples/cli/test.sh11
-rw-r--r--extensions/Makefile.am4
-rw-r--r--extensions/libct_proto_icmp.c56
-rw-r--r--extensions/libct_proto_sctp.c164
-rw-r--r--extensions/libct_proto_tcp.c157
-rw-r--r--extensions/libct_proto_udp.c93
-rw-r--r--include/conntrack.h28
-rw-r--r--src/conntrack.c735
9 files changed, 643 insertions, 614 deletions
diff --git a/conntrack.8 b/conntrack.8
index 307180b..6c5d9d6 100644
--- a/conntrack.8
+++ b/conntrack.8
@@ -1,6 +1,7 @@
-.TH CONNTRACK 8 "Jun 23, 2005" "" ""
+.TH CONNTRACK 8 "May 6, 2007" "" ""
.\" Man page written by Harald Welte <laforge@netfilter.org (Jun 2005)
+.\" Maintained by Pablo Neira Ayuso <pablo@netfilter.org (May 2007)
.SH NAME
conntrack \- administration tool for netfilter connection tracking
@@ -74,6 +75,10 @@ Flush the whole given table
Atomically zero counters after reading them. This option is only valid in
combination with the "-L, --dump" command options.
.TP
+.BI "-x, --xml "
+Display output in XML format. This option is only valid in combination with
+the "-L, --dump", "-E, --event" and "-G, --get" command options.
+.TP
.BI "-e, --event-mask " "[ALL|NEW|UPDATES|DESTROY][,...]"
Set the bitmask of events that are to be generated by the in-kernel ctnetlink
event code. Using this parameter, you can reduce the event messages generated
@@ -139,4 +144,4 @@ Jay Schulist, Patrick McHardy, Harald Welte and Pablo Neira wrote the kernel-lev
.PP
Pablo Neira wrote the conntrack tool, Harald Welte added support for conntrack based accounting counters.
.PP
-Man page written by Harald Welte <laforge@netfilter.org>.
+Man page written by Harald Welte <laforge@netfilter.org> and Pablo Neira Ayuso <pablo@netfilter.org>.
diff --git a/examples/cli/test.sh b/examples/cli/test.sh
index 4694236..36c4826 100644
--- a/examples/cli/test.sh
+++ b/examples/cli/test.sh
@@ -32,7 +32,7 @@ case $1 in
echo "creating a new conntrack (NAT)"
$CONNTRACK -I --orig-src $SRC --orig-dst $DST \
-p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \
- --state LISTEN -u SEEN_REPLY,SRC_NAT -t 50 -a 8.8.8.8
+ --state LISTEN -u SEEN_REPLY -t 50 --dst-nat 8.8.8.8
;;
get)
echo "getting a conntrack"
@@ -78,18 +78,17 @@ case $1 in
--tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \
--mask-src 255.255.255.0 --mask-dst 255.255.255.255 \
-p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \
- -t 200 --tuple-port-src 10 --tuple-port-dst 300 \
+ -t 200 --tuple-port-src 10240 --tuple-port-dst 10241\
--mask-port-src 10 --mask-port-dst 300
;;
get-expect)
$CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \
- --p tcp --orig-port-src 0 --orig-port-dst 0 \
- --mask-port-src 10 --mask-port-dst 11
+ --p tcp --orig-port-src 10240 --orig-port-dst 10241
;;
delete-expect)
$CONNTRACK -D expect --orig-src 4.4.4.4 \
- --orig-dst 5.5.5.5 -p tcp --orig-port-src 0 \
- --orig-port-dst 0 --mask-port-src 10 --mask-port-dst 11
+ --orig-dst 5.5.5.5 -p tcp --orig-port-src 10240 \
+ --orig-port-dst 10241
;;
*)
echo "Usage: $0 [dump"
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 5366ee3..db97c4d 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -4,7 +4,7 @@ AM_CFLAGS=-fPIC -Wall
LIBS=
pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \
- ct_proto_icmp.la ct_proto_sctp.la
+ ct_proto_icmp.la
ct_proto_tcp_la_SOURCES = libct_proto_tcp.c
ct_proto_tcp_la_LDFLAGS = -module -avoid-version
@@ -12,5 +12,3 @@ ct_proto_udp_la_SOURCES = libct_proto_udp.c
ct_proto_udp_la_LDFLAGS = -module -avoid-version
ct_proto_icmp_la_SOURCES = libct_proto_icmp.c
ct_proto_icmp_la_LDFLAGS = -module -avoid-version
-ct_proto_sctp_la_SOURCES = libct_proto_sctp.c
-ct_proto_sctp_la_LDFLAGS = -module -avoid-version
diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c
index e7cb04d..7b02dec 100644
--- a/extensions/libct_proto_icmp.c
+++ b/extensions/libct_proto_icmp.c
@@ -1,6 +1,6 @@
/*
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
- * Harald Welte <laforge@netfilter.org>
+ * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * 2005 by Harald Welte <laforge@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
@@ -43,35 +43,42 @@ static u_int8_t invmap[]
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
static int parse(char c, char *argv[],
- struct nfct_tuple *orig,
- struct nfct_tuple *reply,
- struct nfct_tuple *exptuple,
- struct nfct_tuple *mask,
- union nfct_protoinfo *proto,
+ struct nf_conntrack *ct,
+ struct nf_conntrack *exptuple,
+ struct nf_conntrack *mask,
unsigned int *flags)
{
switch(c) {
case '1':
- if (optarg) {
- orig->l4dst.icmp.type = atoi(optarg);
- reply->l4dst.icmp.type =
- invmap[orig->l4dst.icmp.type] - 1;
- *flags |= ICMP_TYPE;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u8(ct,
+ ATTR_ICMP_TYPE,
+ atoi(optarg));
+ /* FIXME:
+ reply->l4dst.icmp.type =
+ invmap[orig->l4dst.icmp.type] - 1;
+ */
+ *flags |= ICMP_TYPE;
break;
case '2':
- if (optarg) {
- orig->l4dst.icmp.code = atoi(optarg);
- reply->l4dst.icmp.code = 0;
- *flags |= ICMP_CODE;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u8(ct,
+ ATTR_ICMP_CODE,
+ atoi(optarg));
+ *flags |= ICMP_CODE;
break;
case '3':
- if (optarg) {
- orig->l4src.icmp.id = htons(atoi(optarg));
- reply->l4dst.icmp.id = 0;
- *flags |= ICMP_ID;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_ICMP_ID,
+ htons(atoi(optarg)));
+ *flags |= ICMP_ID;
break;
}
return 1;
@@ -79,8 +86,7 @@ static int parse(char c, char *argv[],
static int final_check(unsigned int flags,
unsigned int command,
- struct nfct_tuple *orig,
- struct nfct_tuple *reply)
+ struct nf_conntrack *ct)
{
if (!(flags & ICMP_TYPE))
return 0;
diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c
deleted file mode 100644
index 1c8f0d1..0000000
--- a/extensions/libct_proto_sctp.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * (C) 2005 by Harald Welte <laforge@netfilter.org>
- * 2006 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.
- *
- */
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/in.h> /* For htons */
-#include "conntrack.h"
-#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
-#include <libnetfilter_conntrack/libnetfilter_conntrack_sctp.h>
-
-static struct option opts[] = {
- {"orig-port-src", 1, 0, '1'},
- {"orig-port-dst", 1, 0, '2'},
- {"reply-port-src", 1, 0, '3'},
- {"reply-port-dst", 1, 0, '4'},
- {"state", 1, 0, '5'},
- {"tuple-port-src", 1, 0, '6'},
- {"tuple-port-dst", 1, 0, '7'},
- {0, 0, 0, 0}
-};
-
-static const char *states[] = {
- "NONE",
- "CLOSED",
- "COOKIE_WAIT",
- "COOKIE_ECHOED",
- "ESTABLISHED",
- "SHUTDOWN_SENT",
- "SHUTDOWN_RECV",
- "SHUTDOWN_ACK_SENT",
-};
-
-static void help()
-{
- fprintf(stdout, "--orig-port-src original source port\n");
- fprintf(stdout, "--orig-port-dst original destination port\n");
- fprintf(stdout, "--reply-port-src reply source port\n");
- fprintf(stdout, "--reply-port-dst reply destination port\n");
- fprintf(stdout, "--state SCTP state, fe. ESTABLISHED\n");
- fprintf(stdout, "--tuple-port-src expectation tuple src port\n");
- fprintf(stdout, "--tuple-port-src expectation tuple dst port\n");
-}
-
-static int parse_options(char c, char *argv[],
- struct nfct_tuple *orig,
- struct nfct_tuple *reply,
- struct nfct_tuple *exptuple,
- struct nfct_tuple *mask,
- union nfct_protoinfo *proto,
- unsigned int *flags)
-{
- switch(c) {
- case '1':
- if (optarg) {
- orig->l4src.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_ORIG_SPORT;
- }
- break;
- case '2':
- if (optarg) {
- orig->l4dst.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_ORIG_DPORT;
- }
- break;
- case '3':
- if (optarg) {
- reply->l4src.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_REPL_SPORT;
- }
- break;
- case '4':
- if (optarg) {
- reply->l4dst.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_REPL_DPORT;
- }
- break;
- case '5':
- if (optarg) {
- int i;
- for (i=0; i<10; i++) {
- if (strcmp(optarg, states[i]) == 0) {
- /* FIXME: Add state to
- * nfct_protoinfo
- proto->sctp.state = i; */
- break;
- }
- }
- if (i == 10) {
- printf("doh?\n");
- return 0;
- }
- *flags |= SCTP_STATE;
- }
- break;
- case '6':
- if (optarg) {
- exptuple->l4src.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_EXPTUPLE_SPORT;
- }
- break;
- case '7':
- if (optarg) {
- exptuple->l4dst.sctp.port = htons(atoi(optarg));
- *flags |= SCTP_EXPTUPLE_DPORT;
- }
-
- }
- return 1;
-}
-
-static int final_check(unsigned int flags,
- unsigned int command,
- struct nfct_tuple *orig,
- struct nfct_tuple *reply)
-{
- int ret = 0;
-
- if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT))
- && !(flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) {
- reply->l4src.sctp.port = orig->l4dst.sctp.port;
- reply->l4dst.sctp.port = orig->l4src.sctp.port;
- ret = 1;
- } else if (!(flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT))
- && (flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) {
- orig->l4src.sctp.port = reply->l4dst.sctp.port;
- orig->l4dst.sctp.port = reply->l4src.sctp.port;
- ret = 1;
- }
- if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT))
- && ((flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))))
- ret = 1;
-
- /* --state is missing and we are trying to create a conntrack */
- if (ret && (command & CT_CREATE) && (!(flags & SCTP_STATE)))
- ret = 0;
-
- return ret;
-}
-
-static struct ctproto_handler sctp = {
- .name = "sctp",
- .protonum = IPPROTO_SCTP,
- .parse_opts = parse_options,
- .final_check = final_check,
- .help = help,
- .opts = opts,
- .version = VERSION,
-};
-
-static void __attribute__ ((constructor)) init(void);
-
-static void init(void)
-{
- register_proto(&sctp);
-}
diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c
index ee24206..736bcff 100644
--- a/extensions/libct_proto_tcp.c
+++ b/extensions/libct_proto_tcp.c
@@ -1,5 +1,5 @@
/*
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2007 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
@@ -56,78 +56,112 @@ static void help()
fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n");
}
-static int parse_options(char c, char *argv[],
- struct nfct_tuple *orig,
- struct nfct_tuple *reply,
- struct nfct_tuple *exptuple,
- struct nfct_tuple *mask,
- union nfct_protoinfo *proto,
+static int parse_options(char c, char *argv[],
+ struct nf_conntrack *ct,
+ struct nf_conntrack *exptuple,
+ struct nf_conntrack *mask,
unsigned int *flags)
{
+ int i;
+
switch(c) {
case '1':
- if (optarg) {
- orig->l4src.tcp.port = htons(atoi(optarg));
- *flags |= TCP_ORIG_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_ORIG_SPORT;
break;
case '2':
- if (optarg) {
- orig->l4dst.tcp.port = htons(atoi(optarg));
- *flags |= TCP_ORIG_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_ORIG_DPORT;
break;
case '3':
- if (optarg) {
- reply->l4src.tcp.port = htons(atoi(optarg));
- *flags |= TCP_REPL_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_REPL_SPORT;
break;
case '4':
- if (optarg) {
- reply->l4dst.tcp.port = htons(atoi(optarg));
- *flags |= TCP_REPL_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_REPL_DPORT;
break;
case '5':
- if (optarg) {
- mask->l4src.tcp.port = htons(atoi(optarg));
- *flags |= TCP_MASK_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(mask,
+ ATTR_ORIG_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_MASK_SPORT;
break;
case '6':
- if (optarg) {
- mask->l4dst.tcp.port = htons(atoi(optarg));
- *flags |= TCP_MASK_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(mask,
+ ATTR_ORIG_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_MASK_DPORT;
break;
case '7':
- if (optarg) {
- int i;
- for (i=0; i<10; i++) {
- if (strcmp(optarg, states[i]) == 0) {
- proto->tcp.state = i;
- break;
- }
- }
- if (i == 10) {
- printf("doh?\n");
- return 0;
+ if (!optarg)
+ break;
+
+ for (i=0; i<10; i++) {
+ if (strcmp(optarg, states[i]) == 0) {
+ nfct_set_attr_u8(ct,
+ ATTR_TCP_STATE,
+ i);
+ break;
}
- *flags |= TCP_STATE;
}
+ if (i == 10) {
+ printf("doh?\n");
+ return 0;
+ }
+ *flags |= TCP_STATE;
break;
case '8':
- if (optarg) {
- exptuple->l4src.tcp.port = htons(atoi(optarg));
- *flags |= TCP_EXPTUPLE_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(exptuple,
+ ATTR_ORIG_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_EXPTUPLE_SPORT;
break;
case '9':
- if (optarg) {
- exptuple->l4dst.tcp.port = htons(atoi(optarg));
- *flags |= TCP_EXPTUPLE_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(exptuple,
+ ATTR_ORIG_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= TCP_EXPTUPLE_DPORT;
break;
}
return 1;
@@ -135,20 +169,27 @@ static int parse_options(char c, char *argv[],
static int final_check(unsigned int flags,
unsigned int command,
- struct nfct_tuple *orig,
- struct nfct_tuple *reply)
+ struct nf_conntrack *ct)
{
int ret = 0;
-
+
if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
&& !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) {
- reply->l4src.tcp.port = orig->l4dst.tcp.port;
- reply->l4dst.tcp.port = orig->l4src.tcp.port;
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_SRC,
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_DST,
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
ret = 1;
} else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
&& (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) {
- orig->l4src.tcp.port = reply->l4dst.tcp.port;
- orig->l4dst.tcp.port = reply->l4src.tcp.port;
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_SRC,
+ nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_DST,
+ nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
ret = 1;
}
if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c
index 48079e0..1bc70d4 100644
--- a/extensions/libct_proto_udp.c
+++ b/extensions/libct_proto_udp.c
@@ -1,5 +1,5 @@
/*
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2007 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
@@ -10,11 +10,13 @@
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
+#include <string.h>
#include <netinet/in.h> /* For htons */
-#include "conntrack.h"
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_udp.h>
+#include "conntrack.h"
+
static struct option opts[] = {
{"orig-port-src", 1, 0, '1'},
{"orig-port-dst", 1, 0, '2'},
@@ -39,38 +41,54 @@ static void help()
fprintf(stdout, "--tuple-port-src expectation tuple dst port\n");
}
-static int parse_options(char c, char *argv[],
- struct nfct_tuple *orig,
- struct nfct_tuple *reply,
+static int parse_options(char c, char *argv[],
+ struct nf_conntrack *ct,
struct nfct_tuple *exptuple,
struct nfct_tuple *mask,
- union nfct_protoinfo *proto,
unsigned int *flags)
{
+ int i;
+
switch(c) {
case '1':
- if (optarg) {
- orig->l4src.udp.port = htons(atoi(optarg));
- *flags |= UDP_ORIG_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= UDP_ORIG_SPORT;
break;
case '2':
- if (optarg) {
- orig->l4dst.udp.port = htons(atoi(optarg));
- *flags |= UDP_ORIG_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= UDP_ORIG_DPORT;
break;
case '3':
- if (optarg) {
- reply->l4src.udp.port = htons(atoi(optarg));
- *flags |= UDP_REPL_SPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_SRC,
+ htons(atoi(optarg)));
+
+ *flags |= UDP_REPL_SPORT;
break;
case '4':
- if (optarg) {
- reply->l4dst.udp.port = htons(atoi(optarg));
- *flags |= UDP_REPL_DPORT;
- }
+ if (!optarg)
+ break;
+
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_DST,
+ htons(atoi(optarg)));
+
+ *flags |= UDP_REPL_DPORT;
break;
case '5':
if (optarg) {
@@ -95,32 +113,41 @@ static int parse_options(char c, char *argv[],
exptuple->l4dst.udp.port = htons(atoi(optarg));
*flags |= UDP_EXPTUPLE_DPORT;
}
-
+ break;
}
return 1;
}
static int final_check(unsigned int flags,
unsigned int command,
- struct nfct_tuple *orig,
- struct nfct_tuple *reply)
+ struct nf_conntrack *ct)
{
+ int ret = 0;
+
if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT))
&& !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) {
- reply->l4src.udp.port = orig->l4dst.udp.port;
- reply->l4dst.udp.port = orig->l4src.udp.port;
- return 1;
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_SRC,
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
+ nfct_set_attr_u16(ct,
+ ATTR_REPL_PORT_DST,
+ nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
+ ret = 1;
} else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT))
&& (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) {
- orig->l4src.udp.port = reply->l4dst.udp.port;
- orig->l4dst.udp.port = reply->l4src.udp.port;
- return 1;
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_SRC,
+ nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
+ nfct_set_attr_u16(ct,
+ ATTR_ORIG_PORT_DST,
+ nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
+ ret = 1;
}
if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT))
&& ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))))
- return 1;
+ ret = 1;
- return 0;
+ return ret;
}
static struct ctproto_handler udp = {
diff --git a/include/conntrack.h b/include/conntrack.h
index fb3b9b6..50aec19 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -1,10 +1,6 @@
#ifndef _CONNTRACK_H
#define _CONNTRACK_H
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
#include "linux_list.h"
#include <getopt.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
@@ -122,9 +118,18 @@ enum options {
CT_OPT_FAMILY_BIT = 16,
CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT),
- CT_OPT_MAX_BIT = 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_XML_BIT = 19,
+ CT_OPT_XML = (1 << CT_OPT_XML_BIT),
+
+ CT_OPT_MAX = CT_OPT_XML_BIT
};
-#define NUMBER_OF_OPT CT_OPT_MAX_BIT+1
+#define NUMBER_OF_OPT CT_OPT_MAX+1
struct ctproto_handler {
struct list_head head;
@@ -136,17 +141,14 @@ struct ctproto_handler {
enum ctattr_protoinfo protoinfo_attr;
int (*parse_opts)(char c, char *argv[],
- struct nfct_tuple *orig,
- struct nfct_tuple *reply,
- struct nfct_tuple *exptuple,
- struct nfct_tuple *mask,
- union nfct_protoinfo *proto,
+ struct nf_conntrack *ct,
+ struct nf_conntrack *exptuple,
+ struct nf_conntrack *mask,
unsigned int *flags);
int (*final_check)(unsigned int flags,
unsigned int command,
- struct nfct_tuple *orig,
- struct nfct_tuple *reply);
+ struct nf_conntrack *ct);
void (*help)();
diff --git a/src/conntrack.c b/src/conntrack.c
index b550c39..f3aa06f 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -1,5 +1,5 @@
/*
- * (C) 2005 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2005-2007 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
@@ -29,6 +29,8 @@
* Add support for expect creation
* 2005-09-24 Harald Welte <laforge@netfilter.org>:
* Remove remaints of "-A"
+ * 2007-04-22 Pablo Neira Ayuso <pablo@netfilter.org>:
+ * Ported to the new libnetfilter_conntrack API
*
*/
#include <stdio.h>
@@ -63,7 +65,7 @@ static const char cmd_need_param[NUMBER_OF_CMD]
= { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 };
static const char optflags[NUMBER_OF_OPT]
-= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'};
+= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f','n','g','x'};
static struct option original_opts[] = {
{"dump", 2, 0, 'L'},
@@ -88,10 +90,13 @@ static struct option original_opts[] = {
{"tuple-dst", 1, 0, ']'},
{"mask-src", 1, 0, '{'},
{"mask-dst", 1, 0, '}'},
- {"nat-range", 1, 0, 'a'},
+ {"nat-range", 1, 0, 'a'}, /* deprecated */
{"mark", 1, 0, 'm'},
- {"id", 2, 0, 'i'},
+ {"id", 2, 0, 'i'}, /* deprecated */
{"family", 1, 0, 'f'},
+ {"src-nat", 1, 0, 'n'},
+ {"dst-nat", 1, 0, 'g'},
+ {"xml", 0, 0, 'x'},
{0, 0, 0, 0}
};
@@ -113,28 +118,33 @@ 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 x y k l a m i f*/
-/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2},
-/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0},
-/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0},
-/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0},
-/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0},
-/*CT_FLUSH*/ {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},
-/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*HELP*/ {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,2,2},
-/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0},
-/*EXP_DELETE*/{1,1,2,2,1,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},
-/*EXP_FLUSH*/ {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},
+ /* s d r q p t u z e x y k l a m i f n g x */
+/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2,0,0,2},
+/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0},
+/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0},
+/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0},
+/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2},
+/*CT_FLUSH*/ {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,0,0,2},
+/*VERSION*/ {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,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,2,2,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},
+/*EXP_DELETE*/{1,1,2,2,1,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},
+/*EXP_FLUSH*/ {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},
};
static char *lib_dir = CONNTRACK_LIB_DIR;
static LIST_HEAD(proto_list);
+static unsigned int options;
+static unsigned int command;
+
+#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK)
+
void register_proto(struct ctproto_handler *h)
{
if (strcmp(h->version, VERSION) != 0) {
@@ -328,7 +338,7 @@ err2str(int err, enum action command)
return table[i].message;
}
- return strerror(err);
+ return strerror(-err);
}
#define PARSE_STATUS 0
@@ -340,9 +350,8 @@ static struct parse_parameter {
size_t size;
unsigned int value[6];
} parse_array[PARSE_MAX] = {
- { {"ASSURED", "SEEN_REPLY", "UNSET", "SRC_NAT", "DST_NAT","FIXED_TIMEOUT"}, 6,
- { IPS_ASSURED, IPS_SEEN_REPLY, 0,
- IPS_SRC_NAT_DONE, IPS_DST_NAT_DONE, IPS_FIXED_TIMEOUT} },
+ { {"ASSURED", "SEEN_REPLY", "UNSET", "FIXED_TIMEOUT"}, 4,
+ { IPS_ASSURED, IPS_SEEN_REPLY, 0, IPS_FIXED_TIMEOUT} },
{ {"ALL", "NEW", "UPDATES", "DESTROY"}, 4,
{~0U, NF_NETLINK_CONNTRACK_NEW, NF_NETLINK_CONNTRACK_UPDATE,
NF_NETLINK_CONNTRACK_DESTROY} },
@@ -354,7 +363,17 @@ do_parse_parameter(const char *str, size_t strlen, unsigned int *value,
{
int i, ret = 0;
struct parse_parameter *p = &parse_array[parse_type];
-
+
+ if (strncasecmp(str, "SRC_NAT", strlen) == 0) {
+ printf("skipping SRC_NAT, use --src-nat instead\n");
+ return 1;
+ }
+
+ if (strncasecmp(str, "DST_NAT", strlen) == 0) {
+ printf("skipping DST_NAT, use --dst-nat instead\n");
+ return 1;
+ }
+
for (i = 0; i < p->size; i++)
if (strncasecmp(str, p->parameter[i], strlen) == 0) {
*value |= p->value[i];
@@ -430,7 +449,7 @@ struct addr_parse {
unsigned int family;
};
-int __parse_inetaddr(const char *cp, struct addr_parse *parse)
+int parse_inetaddr(const char *cp, struct addr_parse *parse)
{
if (inet_aton(cp, &parse->addr))
return AF_INET;
@@ -442,12 +461,17 @@ int __parse_inetaddr(const char *cp, struct addr_parse *parse)
exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp);
}
-int parse_inetaddr(const char *cp, union nfct_address *address)
+union ct_address {
+ u_int32_t v4;
+ u_int32_t v6[4];
+};
+
+int parse_addr(const char *cp, union ct_address *address)
{
struct addr_parse parse;
int ret;
-
- if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET)
+
+ if ((ret = parse_inetaddr(cp, &parse)) == AF_INET)
address->v4 = parse.addr.s_addr;
else if (ret == AF_INET6)
memcpy(address->v6, &parse.addr6, sizeof(parse.addr6));
@@ -457,73 +481,43 @@ int parse_inetaddr(const char *cp, union nfct_address *address)
/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */
static void
-nat_parse(char *arg, int portok, struct nfct_nat *range)
+nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type)
{
char *colon, *dash, *error;
- struct addr_parse parse;
+ union ct_address parse;
- memset(range, 0, sizeof(range));
colon = strchr(arg, ':');
if (colon) {
- int port;
+ u_int16_t port;
if (!portok)
exit_error(PARAMETER_PROBLEM,
"Need TCP or UDP with port specification");
port = atoi(colon+1);
- if (port == 0 || port > 65535)
+ if (port == 0)
exit_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", colon+1);
error = strchr(colon+1, ':');
if (error)
exit_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
-
- dash = strchr(colon, '-');
- if (!dash) {
- range->l4min.tcp.port
- = range->l4max.tcp.port
- = htons(port);
- } else {
- int maxport;
-
- maxport = atoi(dash + 1);
- if (maxport == 0 || maxport > 65535)
- exit_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
- if (maxport < port)
- /* People are stupid. */
- exit_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
- range->l4min.tcp.port = htons(port);
- range->l4max.tcp.port = htons(maxport);
- }
- /* Starts with a colon? No IP info... */
- if (colon == arg)
- return;
- *colon = '\0';
- }
+ "Invalid port:port syntax\n");
- dash = strchr(arg, '-');
- if (colon && dash && dash > colon)
- dash = NULL;
-
- if (dash)
- *dash = '\0';
+ if (type == CT_OPT_SRC_NAT)
+ nfct_set_attr_u16(obj, ATTR_SNAT_PORT, port);
+ else if (type == CT_OPT_DST_NAT)
+ nfct_set_attr_u16(obj, ATTR_DNAT_PORT, port);
+ }
- if (__parse_inetaddr(arg, &parse) != AF_INET)
+ if (parse_addr(arg, &parse) != AF_INET)
return;
- range->min_ip = parse.addr.s_addr;
- if (dash) {
- if (__parse_inetaddr(dash+1, &parse) != AF_INET)
- return;
- range->max_ip = parse.addr.s_addr;
- } else
- range->max_ip = parse.addr.s_addr;
+ 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);
}
static void event_sighandler(int s)
@@ -548,10 +542,12 @@ static const char usage_tables[] =
static const char usage_conntrack_parameters[] =
"Conntrack parameters and options:\n"
- " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n"
+ " -n, --src-nat ip\tsource NAT ip\n"
+ " -g, --dst-nat ip\tdestination NAT ip\n"
" -m, --mark mark\t\t\tSet mark\n"
" -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n"
" -z, --zero \t\t\t\tZero counters while listing\n"
+ " -x, --xml \t\t\t\tDisplay output in XML format\n";
;
static const char usage_expectation_parameters[] =
@@ -571,7 +567,6 @@ static const char usage_parameters[] =
" -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"
- " -i, --id [id]\t\t\tShow or set conntrack ID\n"
;
@@ -586,33 +581,78 @@ void usage(char *prog) {
fprintf(stdout, "\n%s", usage_parameters);
}
-#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK)
+unsigned int output_flags = NFCT_O_DEFAULT;
+
+static int event_cb(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ char buf[1024];
+ struct nf_conntrack *obj = data;
+
+ if (options & CT_COMPARISON && !nfct_compare(obj, ct))
+ return NFCT_CB_CONTINUE;
+
+ nfct_snprintf(buf, 1024, ct, type, output_flags, 0);
+ printf("%s\n", buf);
+
+ return NFCT_CB_CONTINUE;
+}
+
+static int dump_cb(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ char buf[1024];
+ struct nf_conntrack *obj = data;
+
+ if (options & CT_COMPARISON && !nfct_compare(obj, ct))
+ return NFCT_CB_CONTINUE;
+
+ nfct_snprintf(buf, 1024, ct, NFCT_T_UNKNOWN, output_flags, 0);
+ printf("%s\n", buf);
+
+ return NFCT_CB_CONTINUE;
+}
+
+static int dump_exp_cb(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp,
+ void *data)
+{
+ char buf[1024];
+
+ nfexp_snprintf(buf, 1024, exp, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
+ printf("%s\n", buf);
+
+ return NFCT_CB_CONTINUE;
+}
-static struct nfct_tuple orig, reply, mask;
-static struct nfct_tuple exptuple;
static struct ctproto_handler *h;
-static union nfct_protoinfo proto;
-static struct nfct_nat range;
-static struct nfct_conntrack *ct;
-static struct nfct_expect *exp;
-static unsigned long timeout;
-static unsigned int status;
-static unsigned int mark;
-static unsigned int id = NFCT_ANY_ID;
-static struct nfct_conntrack_compare cmp;
int main(int argc, char *argv[])
{
int c;
- unsigned int command = 0, options = 0;
- unsigned int type = 0, event_mask = 0;
- unsigned int l3flags = 0, l4flags = 0, metaflags = 0;
+ unsigned int type = 0, event_mask = 0, l4flags = 0, status = 0;
int res = 0;
int family = AF_UNSPEC;
- struct nfct_conntrack_compare *pcmp;
+ char __obj[nfct_maxsize()];
+ char __exptuple[nfct_maxsize()];
+ char __mask[nfct_maxsize()];
+ struct nf_conntrack *obj = (struct nf_conntrack *) __obj;
+ struct nf_conntrack *exptuple = (struct nf_conntrack *) __exptuple;
+ struct nf_conntrack *mask = (struct nf_conntrack *) __mask;
+ char __exp[nfexp_maxsize()];
+ struct nf_expect *exp = (struct nf_expect *) __exp;
+ int l3protonum;
+ union ct_address ad;
+
+ memset(__obj, 0, sizeof(__obj));
+ memset(__exptuple, 0, sizeof(__exptuple));
+ memset(__mask, 0, sizeof(__mask));
+ memset(__exp, 0, sizeof(__exp));
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:",
+ "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:x",
opts, NULL)) != -1) {
switch(c) {
case 'L':
@@ -673,68 +713,99 @@ int main(int argc, char *argv[])
break;
case 's':
options |= CT_OPT_ORIG_SRC;
- if (optarg) {
- orig.l3protonum =
- parse_inetaddr(optarg, &orig.src);
- set_family(&family, orig.l3protonum);
- if (orig.l3protonum == AF_INET)
- l3flags |= IPV4_ORIG_SRC;
- else if (orig.l3protonum == AF_INET6)
- l3flags |= IPV6_ORIG_SRC;
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_SRC,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_SRC,
+ &ad.v6);
}
+ nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum);
break;
case 'd':
options |= CT_OPT_ORIG_DST;
- if (optarg) {
- orig.l3protonum =
- parse_inetaddr(optarg, &orig.dst);
- set_family(&family, orig.l3protonum);
- if (orig.l3protonum == AF_INET)
- l3flags |= IPV4_ORIG_DST;
- else if (orig.l3protonum == AF_INET6)
- l3flags |= IPV6_ORIG_DST;
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_DST,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_DST,
+ &ad.v6);
}
+ nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum);
break;
case 'r':
options |= CT_OPT_REPL_SRC;
- if (optarg) {
- reply.l3protonum =
- parse_inetaddr(optarg, &reply.src);
- set_family(&family, reply.l3protonum);
- if (orig.l3protonum == AF_INET)
- l3flags |= IPV4_REPL_SRC;
- else if (orig.l3protonum == AF_INET6)
- l3flags |= IPV6_REPL_SRC;
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_SRC,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_SRC,
+ &ad.v6);
}
+ nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum);
break;
case 'q':
options |= CT_OPT_REPL_DST;
- if (optarg) {
- reply.l3protonum =
- parse_inetaddr(optarg, &reply.dst);
- set_family(&family, reply.l3protonum);
- if (orig.l3protonum == AF_INET)
- l3flags |= IPV4_REPL_DST;
- else if (orig.l3protonum == AF_INET6)
- l3flags |= IPV6_REPL_DST;
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_DST,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_DST,
+ &ad.v6);
}
+ nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum);
break;
case 'p':
options |= CT_OPT_PROTO;
h = findproto(optarg);
if (!h)
exit_error(PARAMETER_PROBLEM, "proto needed\n");
- orig.protonum = h->protonum;
- reply.protonum = h->protonum;
- exptuple.protonum = h->protonum;
- mask.protonum = h->protonum;
- opts = merge_options(opts, h->opts,
- &h->option_offset);
+
+ nfct_set_attr_u8(obj, ATTR_ORIG_L4PROTO, h->protonum);
+ nfct_set_attr_u8(obj, ATTR_REPL_L4PROTO, h->protonum);
+ nfct_set_attr_u8(exptuple,
+ ATTR_ORIG_L4PROTO,
+ h->protonum);
+ nfct_set_attr_u8(mask,
+ ATTR_ORIG_L4PROTO,
+ h->protonum);
+ opts = merge_options(opts, h->opts, &h->option_offset);
break;
case 't':
options |= CT_OPT_TIMEOUT;
- if (optarg)
- timeout = atol(optarg);
+ if (!optarg)
+ continue;
+
+ nfct_set_attr_u32(obj, ATTR_TIMEOUT, atol(optarg));
+ nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, atol(optarg));
break;
case 'u': {
if (!optarg)
@@ -742,6 +813,7 @@ int main(int argc, char *argv[])
options |= CT_OPT_STATUS;
parse_parameter(optarg, &status, PARSE_STATUS);
+ nfct_set_attr_u32(obj, ATTR_STATUS, status);
break;
}
case 'e':
@@ -753,59 +825,102 @@ int main(int argc, char *argv[])
break;
case '{':
options |= CT_OPT_MASK_SRC;
- if (optarg) {
- mask.l3protonum =
- parse_inetaddr(optarg, &mask.src);
- set_family(&family, mask.l3protonum);
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(mask,
+ ATTR_ORIG_IPV4_SRC,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(mask,
+ ATTR_ORIG_IPV6_SRC,
+ &ad.v6);
}
+ nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
break;
case '}':
options |= CT_OPT_MASK_DST;
- if (optarg) {
- mask.l3protonum =
- parse_inetaddr(optarg, &mask.dst);
- set_family(&family, mask.l3protonum);
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(mask,
+ ATTR_ORIG_IPV4_DST,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(mask,
+ ATTR_ORIG_IPV6_DST,
+ &ad.v6);
}
+ nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
break;
case '[':
options |= CT_OPT_EXP_SRC;
- if (optarg) {
- exptuple.l3protonum =
- parse_inetaddr(optarg, &exptuple.src);
- set_family(&family, exptuple.l3protonum);
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(exptuple,
+ ATTR_ORIG_IPV4_SRC,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(exptuple,
+ ATTR_ORIG_IPV6_SRC,
+ &ad.v6);
}
+ nfct_set_attr_u8(exptuple,
+ ATTR_ORIG_L3PROTO,
+ l3protonum);
break;
case ']':
options |= CT_OPT_EXP_DST;
- if (optarg) {
- exptuple.l3protonum =
- parse_inetaddr(optarg, &exptuple.dst);
- set_family(&family, exptuple.l3protonum);
+ if (!optarg)
+ break;
+
+ l3protonum = parse_addr(optarg, &ad);
+ set_family(&family, l3protonum);
+ if (l3protonum == AF_INET) {
+ nfct_set_attr_u32(exptuple,
+ ATTR_ORIG_IPV4_DST,
+ ad.v4);
+ } else if (l3protonum == AF_INET6) {
+ nfct_set_attr(exptuple,
+ ATTR_ORIG_IPV6_DST,
+ &ad.v6);
}
+ nfct_set_attr_u8(exptuple,
+ ATTR_ORIG_L3PROTO,
+ l3protonum);
break;
case 'a':
- options |= CT_OPT_NATRANGE;
+ printf("warning: ignoring --nat-range, "
+ "use --src-nat or --dst-nat instead.\n");
+ break;
+ case 'n':
+ options |= CT_OPT_SRC_NAT;
set_family(&family, AF_INET);
- nat_parse(optarg, 1, &range);
+ nat_parse(optarg, 1, obj, CT_OPT_SRC_NAT);
break;
+ case 'g':
+ options |= CT_OPT_DST_NAT;
+ set_family(&family, AF_INET);
+ nat_parse(optarg, 1, obj, CT_OPT_DST_NAT);
case 'm':
options |= CT_OPT_MARK;
- mark = atol(optarg);
- metaflags |= NFCT_MARK;
+ if (!optarg)
+ continue;
+ nfct_set_attr_u32(obj, ATTR_MARK, atol(optarg));
break;
- case 'i': {
- char *s = NULL;
- options |= CT_OPT_ID;
- if (optarg)
- break;
- else if (optind < argc && argv[optind][0] != '-'
- && argv[optind][0] != '!')
- s = argv[optind++];
-
- if (s)
- id = atol(s);
+ case 'i':
+ printf("warning: ignoring --id. deprecated option.\n");
break;
- }
case 'f':
options |= CT_OPT_FAMILY;
if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0)
@@ -816,11 +931,14 @@ int main(int argc, char *argv[])
exit_error(PARAMETER_PROBLEM, "Unknown "
"protocol family\n");
break;
+ case 'x':
+ options |= CT_OPT_XML;
+ output_flags = NFCT_O_XML;
+ break;
default:
if (h && h->parse_opts
- &&!h->parse_opts(c - h->option_offset, argv, &orig,
- &reply, &exptuple, &mask, &proto,
- &l4flags))
+ &&!h->parse_opts(c - h->option_offset, argv, obj,
+ exptuple, mask, &l4flags))
exit_error(PARAMETER_PROBLEM, "parse error\n");
/* Unknown argument... */
@@ -842,7 +960,7 @@ int main(int argc, char *argv[])
if (!(command & CT_HELP)
&& h && h->final_check
- && !h->final_check(l4flags, command, &orig, &reply)) {
+ && !h->final_check(l4flags, command, obj)) {
usage(argv[0]);
extension_help(h);
exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n");
@@ -855,39 +973,18 @@ int main(int argc, char *argv[])
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- if (options & CT_COMPARISON) {
+ if (options & CT_COMPARISON &&
+ options & CT_OPT_ZERO)
+ exit_error(PARAMETER_PROBLEM, "Can't use -z with "
+ "filtering parameters");
- if (options & CT_OPT_ZERO)
- exit_error(PARAMETER_PROBLEM, "Can't use -z "
- "with filtering parameters");
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
- ct = nfct_conntrack_alloc(&orig, &reply, timeout,
- &proto, status, mark, id,
- NULL);
- if (!ct)
- exit_error(OTHER_PROBLEM, "Not enough memory");
-
- cmp.ct = ct;
- cmp.flags = metaflags;
- cmp.l3flags = l3flags;
- cmp.l4flags = l4flags;
- pcmp = &cmp;
- }
-
- if (options & CT_OPT_ID)
- nfct_register_callback(cth,
- nfct_default_conntrack_display_id,
- (void *) pcmp);
- else
- nfct_register_callback(cth,
- nfct_default_conntrack_display,
- (void *) pcmp);
-
if (options & CT_OPT_ZERO)
- res =
- nfct_dump_conntrack_table_reset_counters(cth, family);
+ res = nfct_query(cth, NFCT_Q_DUMP_RESET, &family);
else
- res = nfct_dump_conntrack_table(cth, family);
+ res = nfct_query(cth, NFCT_Q_DUMP, &family);
+
nfct_close(cth);
break;
@@ -895,96 +992,144 @@ int main(int argc, char *argv[])
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- if (options & CT_OPT_ID)
- nfct_register_callback(cth,
- nfct_default_expect_display_id,
- NULL);
- else
- nfct_register_callback(cth,
- nfct_default_expect_display,
- NULL);
- res = nfct_dump_expect_list(cth, family);
+
+ nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
+ res = nfexp_query(cth, NFCT_Q_DUMP, &family);
nfct_close(cth);
break;
case CT_CREATE:
if ((options & CT_OPT_ORIG)
&& !(options & CT_OPT_REPL)) {
- reply.l3protonum = orig.l3protonum;
- memcpy(&reply.src, &orig.dst, sizeof(reply.src));
- memcpy(&reply.dst, &orig.src, sizeof(reply.dst));
+ nfct_set_attr_u8(obj,
+ ATTR_REPL_L3PROTO,
+ nfct_get_attr_u8(obj,
+ ATTR_ORIG_L3PROTO));
+ if (family == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_SRC,
+ nfct_get_attr_u32(obj,
+ ATTR_ORIG_IPV4_DST));
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_DST,
+ nfct_get_attr_u32(obj,
+ ATTR_ORIG_IPV4_SRC));
+ } else if (family == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_SRC,
+ nfct_get_attr(obj,
+ ATTR_ORIG_IPV6_DST));
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_DST,
+ nfct_get_attr(obj,
+ ATTR_ORIG_IPV6_SRC));
+ }
} else if (!(options & CT_OPT_ORIG)
&& (options & CT_OPT_REPL)) {
- orig.l3protonum = reply.l3protonum;
- memcpy(&orig.src, &reply.dst, sizeof(orig.src));
- memcpy(&orig.dst, &reply.src, sizeof(orig.dst));
+ nfct_set_attr_u8(obj,
+ ATTR_ORIG_L3PROTO,
+ nfct_get_attr_u8(obj,
+ ATTR_REPL_L3PROTO));
+ if (family == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_SRC,
+ nfct_get_attr_u32(obj,
+ ATTR_REPL_IPV4_DST));
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_DST,
+ nfct_get_attr_u32(obj,
+ ATTR_REPL_IPV4_SRC));
+ } else if (family == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_SRC,
+ nfct_get_attr(obj,
+ ATTR_REPL_IPV6_DST));
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_DST,
+ nfct_get_attr(obj,
+ ATTR_REPL_IPV6_SRC));
+ }
}
- if (options & CT_OPT_NATRANGE)
- ct = nfct_conntrack_alloc(&orig, &reply, timeout,
- &proto, status, mark, id,
- &range);
- else
- ct = nfct_conntrack_alloc(&orig, &reply, timeout,
- &proto, status, mark, id,
- NULL);
- if (!ct)
- exit_error(OTHER_PROBLEM, "Not Enough memory");
-
+
cth = nfct_open(CONNTRACK, 0);
- if (!cth) {
- nfct_conntrack_free(ct);
+ if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- }
- res = nfct_create_conntrack(cth, ct);
+
+ res = nfct_query(cth, NFCT_Q_CREATE, obj);
nfct_close(cth);
- nfct_conntrack_free(ct);
break;
case EXP_CREATE:
- if (options & CT_OPT_ORIG)
- exp = nfct_expect_alloc(&orig, &exptuple,
- &mask, timeout, id);
- else if (options & CT_OPT_REPL)
- exp = nfct_expect_alloc(&reply, &exptuple,
- &mask, timeout, id);
- if (!exp)
- exit_error(OTHER_PROBLEM, "Not enough memory");
+ nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
+ nfexp_set_attr(exp, ATTR_EXP_EXPECTED, exptuple);
+ nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
cth = nfct_open(EXPECT, 0);
- if (!cth) {
- nfct_expect_free(exp);
+ if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- }
- res = nfct_create_expectation(cth, exp);
- nfct_expect_free(exp);
+
+ res = nfexp_query(cth, NFCT_Q_CREATE, exp);
nfct_close(cth);
break;
case CT_UPDATE:
if ((options & CT_OPT_ORIG)
&& !(options & CT_OPT_REPL)) {
- reply.l3protonum = orig.l3protonum;
- memcpy(&reply.src, &orig.dst, sizeof(reply.src));
- memcpy(&reply.dst, &orig.src, sizeof(reply.dst));
+ nfct_set_attr_u8(obj,
+ ATTR_REPL_L3PROTO,
+ nfct_get_attr_u8(obj,
+ ATTR_ORIG_L3PROTO));
+ if (family == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_SRC,
+ nfct_get_attr_u32(obj,
+ ATTR_ORIG_IPV4_DST));
+ nfct_set_attr_u32(obj,
+ ATTR_REPL_IPV4_DST,
+ nfct_get_attr_u32(obj,
+ ATTR_ORIG_IPV4_SRC));
+ } else if (family == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_SRC,
+ nfct_get_attr(obj,
+ ATTR_ORIG_IPV6_DST));
+ nfct_set_attr(obj,
+ ATTR_REPL_IPV6_DST,
+ nfct_get_attr(obj,
+ ATTR_ORIG_IPV6_SRC));
+ }
} else if (!(options & CT_OPT_ORIG)
&& (options & CT_OPT_REPL)) {
- orig.l3protonum = reply.l3protonum;
- memcpy(&orig.src, &reply.dst, sizeof(orig.src));
- memcpy(&orig.dst, &reply.src, sizeof(orig.dst));
+ nfct_set_attr_u8(obj,
+ ATTR_ORIG_L3PROTO,
+ nfct_get_attr_u8(obj,
+ ATTR_REPL_L3PROTO));
+ if (family == AF_INET) {
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_SRC,
+ nfct_get_attr_u32(obj,
+ ATTR_REPL_IPV4_DST));
+ nfct_set_attr_u32(obj,
+ ATTR_ORIG_IPV4_DST,
+ nfct_get_attr_u32(obj,
+ ATTR_REPL_IPV4_SRC));
+ } else if (family == AF_INET6) {
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_SRC,
+ nfct_get_attr(obj,
+ ATTR_REPL_IPV6_DST));
+ nfct_set_attr(obj,
+ ATTR_ORIG_IPV6_DST,
+ nfct_get_attr(obj,
+ ATTR_REPL_IPV6_SRC));
+ }
}
- ct = nfct_conntrack_alloc(&orig, &reply, timeout,
- &proto, status, mark, id,
- NULL);
- if (!ct)
- exit_error(OTHER_PROBLEM, "Not enough memory");
-
+
cth = nfct_open(CONNTRACK, 0);
- if (!cth) {
- nfct_conntrack_free(ct);
+ if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- }
- res = nfct_update_conntrack(cth, ct);
- nfct_conntrack_free(ct);
+
+ res = nfct_query(cth, NFCT_Q_UPDATE, obj);
nfct_close(cth);
break;
@@ -995,25 +1140,19 @@ int main(int argc, char *argv[])
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- if (options & CT_OPT_ORIG)
- res = nfct_delete_conntrack(cth, &orig,
- NFCT_DIR_ORIGINAL,
- id);
- else if (options & CT_OPT_REPL)
- res = nfct_delete_conntrack(cth, &reply,
- NFCT_DIR_REPLY,
- id);
+
+ res = nfct_query(cth, NFCT_Q_DESTROY, obj);
nfct_close(cth);
break;
case EXP_DELETE:
+ nfexp_set_attr(exp, ATTR_EXP_EXPECTED, obj);
+
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- if (options & CT_OPT_ORIG)
- res = nfct_delete_expectation(cth, &orig, id);
- else if (options & CT_OPT_REPL)
- res = nfct_delete_expectation(cth, &reply, id);
+
+ res = nfexp_query(cth, NFCT_Q_DESTROY, exp);
nfct_close(cth);
break;
@@ -1021,27 +1160,21 @@ int main(int argc, char *argv[])
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_register_callback(cth, nfct_default_conntrack_display,
- NULL);
- if (options & CT_OPT_ORIG)
- res = nfct_get_conntrack(cth, &orig,
- NFCT_DIR_ORIGINAL, id);
- else if (options & CT_OPT_REPL)
- res = nfct_get_conntrack(cth, &reply,
- NFCT_DIR_REPLY, id);
+
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
+ res = nfct_query(cth, NFCT_Q_GET, obj);
nfct_close(cth);
break;
case EXP_GET:
+ nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
+
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_register_callback(cth, nfct_default_expect_display,
- NULL);
- if (options & CT_OPT_ORIG)
- res = nfct_get_expectation(cth, &orig, id);
- else if (options & CT_OPT_REPL)
- res = nfct_get_expectation(cth, &reply, id);
+
+ nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
+ res = nfexp_query(cth, NFCT_Q_GET, exp);
nfct_close(cth);
break;
@@ -1049,7 +1182,7 @@ int main(int argc, char *argv[])
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfct_flush_conntrack_table(cth, AF_INET);
+ res = nfct_query(cth, NFCT_Q_FLUSH, &family);
nfct_close(cth);
break;
@@ -1057,7 +1190,7 @@ int main(int argc, char *argv[])
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfct_flush_expectation_table(cth, AF_INET);
+ res = nfexp_query(cth, NFCT_Q_FLUSH, &family);
nfct_close(cth);
break;
@@ -1070,25 +1203,8 @@ int main(int argc, char *argv[])
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
signal(SIGINT, event_sighandler);
-
- if (options & CT_COMPARISON) {
- ct = nfct_conntrack_alloc(&orig, &reply, timeout,
- &proto, status, mark, id,
- NULL);
- if (!ct)
- exit_error(OTHER_PROBLEM, "Not enough memory");
-
- cmp.ct = ct;
- cmp.flags = metaflags;
- cmp.l3flags = l3flags;
- cmp.l4flags = l4flags;
- pcmp = &cmp;
- }
-
- nfct_register_callback(cth,
- nfct_default_conntrack_event_display,
- (void *) pcmp);
- res = nfct_event_conntrack(cth);
+ nfct_callback_register(cth, NFCT_T_ALL, event_cb, obj);
+ res = nfct_catch(cth);
nfct_close(cth);
break;
@@ -1097,9 +1213,8 @@ int main(int argc, char *argv[])
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
signal(SIGINT, event_sighandler);
- nfct_register_callback(cth, nfct_default_expect_display,
- NULL);
- res = nfct_event_expectation(cth);
+ nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
+ res = nfexp_catch(cth);
nfct_close(cth);
break;
@@ -1123,7 +1238,7 @@ int main(int argc, char *argv[])
}
if (res < 0) {
- fprintf(stderr, "Operation failed: %s\n", err2str(res, command));
+ fprintf(stderr, "Operation failed: %s\n", err2str(-errno, command));
exit(OTHER_PROBLEM);
}