All of lore.kernel.org
 help / color / mirror / Atom feed
* [NETFILTER]: xt_conntrack: add port and direction matching
@ 2008-01-24 22:38 Jan Engelhardt
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
  2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy
  0 siblings, 2 replies; 4+ messages in thread
From: Jan Engelhardt @ 2008-01-24 22:38 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List

commit 7f1764fa749032eb8566226bbd1c5a58a8a5efc6
Author: Jan Engelhardt <jengelh@computergmbh.de>
Date:   Wed Jan 16 18:58:49 2008 +0100

    [NETFILTER]: xt_conntrack: add port and direction matching
    
    Extend the xt_conntrack match revision 1 by port matching (all four
    {orig,repl}{src,dst}) and by packet direction matching.
    
    Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>

diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index d2492a3..f3fd83e 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -6,9 +6,6 @@
 #define _XT_CONNTRACK_H
 
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
-#ifdef __KERNEL__
-#	include <linux/in.h>
-#endif
 
 #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define XT_CONNTRACK_STATE_INVALID (1 << 0)
@@ -18,14 +15,21 @@
 #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
 
 /* flags, invflags: */
-#define XT_CONNTRACK_STATE	0x01
-#define XT_CONNTRACK_PROTO	0x02
-#define XT_CONNTRACK_ORIGSRC	0x04
-#define XT_CONNTRACK_ORIGDST	0x08
-#define XT_CONNTRACK_REPLSRC	0x10
-#define XT_CONNTRACK_REPLDST	0x20
-#define XT_CONNTRACK_STATUS	0x40
-#define XT_CONNTRACK_EXPIRES	0x80
+enum {
+	XT_CONNTRACK_STATE        = 1 << 0,
+	XT_CONNTRACK_PROTO        = 1 << 1,
+	XT_CONNTRACK_ORIGSRC      = 1 << 2,
+	XT_CONNTRACK_ORIGDST      = 1 << 3,
+	XT_CONNTRACK_REPLSRC      = 1 << 4,
+	XT_CONNTRACK_REPLDST      = 1 << 5,
+	XT_CONNTRACK_STATUS       = 1 << 6,
+	XT_CONNTRACK_EXPIRES      = 1 << 7,
+	XT_CONNTRACK_ORIGSRC_PORT = 1 << 8,
+	XT_CONNTRACK_ORIGDST_PORT = 1 << 9,
+	XT_CONNTRACK_REPLSRC_PORT = 1 << 10,
+	XT_CONNTRACK_REPLDST_PORT = 1 << 11,
+	XT_CONNTRACK_DIRECTION    = 1 << 12,
+};
 
 /* This is exposed to userspace, so remains frozen in time. */
 struct ip_conntrack_old_tuple
@@ -70,8 +74,10 @@ struct xt_conntrack_mtinfo1 {
 	union nf_inet_addr repldst_addr, repldst_mask;
 	u_int32_t expires_min, expires_max;
 	u_int16_t l4proto;
+	__be16 origsrc_port, origdst_port;
+	__be16 replsrc_port, repldst_port;
+	u_int16_t match_flags, invert_flags;
 	u_int8_t state_mask, status_mask;
-	u_int8_t match_flags, invert_flags;
 };
 
 #endif /*_XT_CONNTRACK_H*/
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index e92190e..8533085 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -4,7 +4,6 @@
  *
  *	(C) 2001  Marc Boucher (marc@mbsi.ca).
  *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
- *	Jan Engelhardt <jengelh@computergmbh.de>
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2 as
@@ -20,6 +19,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
 MODULE_DESCRIPTION("Xtables: connection tracking state match");
 MODULE_ALIAS("ipt_conntrack");
 MODULE_ALIAS("ip6t_conntrack");
@@ -166,6 +166,44 @@ conntrack_mt_repldst(const struct nf_conn *ct,
 	       &info->repldst_addr, &info->repldst_mask, family);
 }
 
+static inline bool
+ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+                    const struct nf_conn *ct)
+{
+	const struct nf_conntrack_tuple *tuple;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+	    (tuple->dst.protonum == info->l4proto) ^
+	    !(info->invert_flags & XT_CONNTRACK_PROTO))
+		return false;
+
+	/* Shortcut to match all recognized protocols by using ->src.all. */
+	if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
+	    (tuple->src.u.all == info->origsrc_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
+	    (tuple->dst.u.all == info->origdst_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
+		return false;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
+	    (tuple->src.u.all == info->replsrc_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
+	    (tuple->dst.u.all == info->repldst_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
+		return false;
+
+	return true;
+}
+
 static bool
 conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
              const struct net_device *out, const struct xt_match *match,
@@ -200,10 +238,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
 
 	if (ct == NULL)
 		return info->match_flags & XT_CONNTRACK_STATE;
-
-	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
-	    ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
-	    info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO)))
+	if ((info->match_flags & XT_CONNTRACK_DIRECTION) &&
+	    (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^
+	    !!(info->invert_flags & XT_CONNTRACK_DIRECTION))
 		return false;
 
 	if (info->match_flags & XT_CONNTRACK_ORIGSRC)
@@ -226,6 +263,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
 		    !(info->invert_flags & XT_CONNTRACK_REPLDST))
 			return false;
 
+	if (!ct_proto_port_check(info, ct))
+		return false;
+
 	if ((info->match_flags & XT_CONNTRACK_STATUS) &&
 	    (!!(info->status_mask & ct->status) ^
 	    !(info->invert_flags & XT_CONNTRACK_STATUS)))

-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [IPTABLES]: libxt_conntrack revision 1
  2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
@ 2008-01-24 22:38 ` Jan Engelhardt
  2008-01-29 13:20   ` Patrick McHardy
  2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy
  1 sibling, 1 reply; 4+ messages in thread
From: Jan Engelhardt @ 2008-01-24 22:38 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List

Add support for xt_conntrack match revision 1.

Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>

---
 extensions/libxt_conntrack.c   |  575 ++++++++++++++++++++++++++++++++++++++++-
 extensions/libxt_conntrack.man |   18 -
 2 files changed, 576 insertions(+), 17 deletions(-)

Index: iptables/extensions/libxt_conntrack.c
===================================================================
--- iptables.orig/extensions/libxt_conntrack.c
+++ iptables/extensions/libxt_conntrack.c
@@ -1,10 +1,17 @@
-/* Shared library add-on to iptables for conntrack matching support.
- * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+/*
+ *	libxt_conntrack
+ *	Shared library add-on to iptables for conntrack matching support.
+ *
+ *	GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+ *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ *	Jan Engelhardt <jengelh@computergmbh.de>
  */
-
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <ctype.h>
 #include <getopt.h>
 #include <netdb.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -13,6 +20,7 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter/xt_conntrack.h>
 #include <linux/netfilter/nf_conntrack_common.h>
+#include <arpa/inet.h>
 
 /* Function which prints out usage message. */
 static void conntrack_mt_help(void)
@@ -27,14 +35,20 @@ static void conntrack_mt_help(void)
 "[!] --ctreplsrc address[/mask]\n"
 "[!] --ctrepldst address[/mask]\n"
 "                               Original/Reply source/destination address\n"
+"[!] --ctorigsrcport port\n"
+"[!] --ctorigdstport port\n"
+"[!] --ctreplsrcport port\n"
+"[!] --ctrepldstport port\n"
+"                               TCP/UDP/SCTP orig./reply source/destination port\n"
 "[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]\n"
 "                               Status(es) to match\n"
 "[!] --ctexpire time[:time]     Match remaining lifetime in seconds against\n"
 "                               value or range of values (inclusive)\n"
+"    --ctdir {ORIGINAL|REPLY}   Flow direction of packet\n"
 "\n");
 }
 
-static const struct option conntrack_mt_opts[] = {
+static const struct option conntrack_mt_opts_v0[] = {
 	{.name = "ctstate",   .has_arg = true, .val = '1'},
 	{.name = "ctproto",   .has_arg = true, .val = '2'},
 	{.name = "ctorigsrc", .has_arg = true, .val = '3'},
@@ -46,6 +60,23 @@ static const struct option conntrack_mt_
 	{},
 };
 
+static const struct option conntrack_mt_opts[] = {
+	{.name = "ctstate",       .has_arg = true, .val = '1'},
+	{.name = "ctproto",       .has_arg = true, .val = '2'},
+	{.name = "ctorigsrc",     .has_arg = true, .val = '3'},
+	{.name = "ctorigdst",     .has_arg = true, .val = '4'},
+	{.name = "ctreplsrc",     .has_arg = true, .val = '5'},
+	{.name = "ctrepldst",     .has_arg = true, .val = '6'},
+	{.name = "ctstatus",      .has_arg = true, .val = '7'},
+	{.name = "ctexpire",      .has_arg = true, .val = '8'},
+	{.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
+	{.name = "ctorigdstport", .has_arg = true, .val = 'b'},
+	{.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
+	{.name = "ctrepldstport", .has_arg = true, .val = 'd'},
+	{.name = "ctdir",         .has_arg = true, .val = 'e'},
+	{},
+};
+
 static int
 parse_state(const char *state, size_t strlen, struct xt_conntrack_info *sinfo)
 {
@@ -83,6 +114,45 @@ parse_states(const char *arg, struct xt_
 		exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
 }
 
+static bool
+conntrack_ps_state(struct xt_conntrack_mtinfo1 *info, const char *state,
+                   size_t z)
+{
+	if (strncasecmp(state, "INVALID", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_INVALID;
+	else if (strncasecmp(state, "NEW", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+	else if (strncasecmp(state, "ESTABLISHED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+	else if (strncasecmp(state, "RELATED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+	else if (strncasecmp(state, "UNTRACKED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_UNTRACKED;
+	else if (strncasecmp(state, "SNAT", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_SNAT;
+	else if (strncasecmp(state, "DNAT", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_DNAT;
+	else
+		return false;
+	return true;
+}
+
+static void
+conntrack_ps_states(struct xt_conntrack_mtinfo1 *info, const char *arg)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !conntrack_ps_state(info, arg, comma - arg))
+			exit_error(PARAMETER_PROBLEM,
+			           "Bad ctstate \"%s\"", arg);
+		arg = comma + 1;
+	}
+
+	if (strlen(arg) == 0 || !conntrack_ps_state(info, arg, strlen(arg)))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
+}
+
 static int
 parse_status(const char *status, size_t strlen, struct xt_conntrack_info *sinfo)
 {
@@ -96,7 +166,7 @@ parse_status(const char *status, size_t 
 		sinfo->statusmask |= IPS_ASSURED;
 #ifdef IPS_CONFIRMED
 	else if (strncasecmp(status, "CONFIRMED", strlen) == 0)
-		sinfo->stausmask |= IPS_CONFIRMED;
+		sinfo->statusmask |= IPS_CONFIRMED;
 #endif
 	else
 		return 0;
@@ -118,6 +188,41 @@ parse_statuses(const char *arg, struct x
 		exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
 }
 
+static bool
+conntrack_ps_status(struct xt_conntrack_mtinfo1 *info, const char *status,
+                    size_t z)
+{
+	if (strncasecmp(status, "NONE", z) == 0)
+		info->status_mask |= 0;
+	else if (strncasecmp(status, "EXPECTED", z) == 0)
+		info->status_mask |= IPS_EXPECTED;
+	else if (strncasecmp(status, "SEEN_REPLY", z) == 0)
+		info->status_mask |= IPS_SEEN_REPLY;
+	else if (strncasecmp(status, "ASSURED", z) == 0)
+		info->status_mask |= IPS_ASSURED;
+	else if (strncasecmp(status, "CONFIRMED", z) == 0)
+		info->status_mask |= IPS_CONFIRMED;
+	else
+		return false;
+	return true;
+}
+
+static void
+conntrack_ps_statuses(struct xt_conntrack_mtinfo1 *info, const char *arg)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !conntrack_ps_status(info, arg, comma - arg))
+			exit_error(PARAMETER_PROBLEM,
+			           "Bad ctstatus \"%s\"", arg);
+		arg = comma + 1;
+	}
+
+	if (strlen(arg) == 0 || !conntrack_ps_status(info, arg, strlen(arg)))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
+}
+
 static unsigned long
 parse_expire(const char *s)
 {
@@ -138,7 +243,8 @@ parse_expires(const char *s, struct xt_c
 
 	buffer = strdup(s);
 	if ((cp = strchr(buffer, ':')) == NULL)
-		sinfo->expires_min = sinfo->expires_max = parse_expire(buffer);
+		sinfo->expires_min = sinfo->expires_max =
+			parse_expire(buffer);
 	else {
 		*cp = '\0';
 		cp++;
@@ -154,6 +260,30 @@ parse_expires(const char *s, struct xt_c
 		           "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
 }
 
+static void
+conntrack_ps_expires(struct xt_conntrack_mtinfo1 *info, const char *s)
+{
+	unsigned int min, max;
+	char *end;
+
+	if (!strtonum(s, &end, &min, 0, ~0))
+		param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+	max = min;
+	if (*end == ':')
+		if (!strtonum(s, &end, &max, 0, ~0U))
+			param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+	if (*end != '\0')
+		param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+
+	if (min > max)
+		exit_error(PARAMETER_PROBLEM,
+		           "expire min. range value \"%u\" greater than max. "
+		           "range value \"%u\"", min, max);
+
+	info->expires_min = min;
+	info->expires_max = max;
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
@@ -305,10 +435,257 @@ static int conntrack_parse(int c, char *
 	return 1;
 }
 
+static int
+conntrack_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                   struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	unsigned int port;
+	char *p;
+
+	switch (c) {
+	case '1': /* --ctstate */
+		conntrack_ps_states(info, optarg);
+		info->match_flags |= XT_CONNTRACK_STATE;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_STATE;
+		break;
+
+	case '2': /* --ctproto */
+		/* Canonicalize into lower case */
+		for (p = optarg; *p != '\0'; ++p)
+			*p = tolower(*p);
+		info->l4proto = parse_protocol(optarg);
+
+		if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
+			exit_error(PARAMETER_PROBLEM, "conntrack: rule would "
+			           "never match protocol");
+
+		info->match_flags |= XT_CONNTRACK_PROTO;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_PROTO;
+		break;
+
+	case '7': /* --ctstatus */
+		conntrack_ps_statuses(info, optarg);
+		info->match_flags |= XT_CONNTRACK_STATUS;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_STATUS;
+		break;
+
+	case '8': /* --ctexpire */
+		conntrack_ps_expires(info, optarg);
+		info->match_flags |= XT_CONNTRACK_EXPIRES;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_EXPIRES;
+		break;
+
+	case 'a': /* --ctorigsrcport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctorigsrcport", optarg);
+		info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+		info->origsrc_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+		break;
+
+	case 'b': /* --ctorigdstport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctorigdstport", optarg);
+		info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
+		info->origdst_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
+		break;
+
+	case 'c': /* --ctreplsrcport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctreplsrcport", optarg);
+		info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
+		info->replsrc_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
+		break;
+
+	case 'd': /* --ctrepldstport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctrepldstport", optarg);
+		info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
+		info->repldst_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
+		break;
+
+	case 'e': /* --ctdir */
+		param_act(P_NO_INVERT, "conntrack", "--ctdir", invert);
+		if (strcasecmp(optarg, "ORIGINAL") == 0) {
+			info->match_flags  |= XT_CONNTRACK_DIRECTION;
+			info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
+		} else if (strcasecmp(optarg, "REPLY") == 0) {
+			info->match_flags  |= XT_CONNTRACK_DIRECTION;
+			info->invert_flags |= XT_CONNTRACK_DIRECTION;
+		} else {
+			param_act(P_BAD_VALUE, "conntrack", "--ctdir", optarg);
+		}
+		break;
+
+	default:
+		return false;
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
+static int
+conntrack_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+                    const void *entry, struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	struct in_addr *addr = NULL;
+	unsigned int naddrs = 0;
+
+	switch (c) {
+	case '3': /* --ctorigsrc */
+		ipparse_hostnetworkmask(optarg, &addr, &info->origsrc_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+
+	case '4': /* --ctorigdst */
+		ipparse_hostnetworkmask(optarg, &addr, &info->origdst_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST;
+		break;
+
+	case '5': /* --ctreplsrc */
+		ipparse_hostnetworkmask(optarg, &addr, &info->replsrc_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC;
+		break;
+
+	case '6': /* --ctrepldst */
+		ipparse_hostnetworkmask(optarg, &addr, &info->repldst_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST;
+		break;
+
+
+	default:
+		return conntrack_mt_parse(c, argv, invert, flags, match);
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
+static int
+conntrack_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+                    const void *entry, struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	struct in6_addr *addr = NULL;
+	unsigned int naddrs = 0;
+
+	switch (c) {
+	case '3': /* --ctorigsrc */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->origsrc_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+
+	case '4': /* --ctorigdst */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->origdst_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST;
+		break;
+
+	case '5': /* --ctreplsrc */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->replsrc_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC;
+		break;
+
+	case '6': /* --ctrepldst */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->repldst_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST;
+		break;
+
+
+	default:
+		return conntrack_mt_parse(c, argv, invert, flags, match);
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
 static void conntrack_mt_check(unsigned int flags)
 {
 	if (flags == 0)
-		exit_error(PARAMETER_PROBLEM, "You must specify one or more options");
+		exit_error(PARAMETER_PROBLEM, "conntrack: At least one option "
+		           "is required");
 }
 
 static void
@@ -364,20 +741,37 @@ print_status(unsigned int statusmask)
 		printf("%sASSURED", sep);
 		sep = ",";
 	}
-#ifdef IPS_CONFIRMED
 	if (statusmask & IPS_CONFIRMED) {
 		printf("%sCONFIRMED", sep);
-		sep =",";
-	}
-#endif
-	if (statusmask == 0) {
-		printf("%sNONE", sep);
 		sep = ",";
 	}
+	if (statusmask == 0)
+		printf("%sNONE", sep);
 	printf(" ");
 }
 
 static void
+conntrack_dump_addr(const union nf_inet_addr *addr,
+                    const union nf_inet_addr *mask,
+                    unsigned int family, bool numeric)
+{
+	if (family == AF_INET) {
+		if (!numeric && addr->ip == 0) {
+			printf("anywhere ");
+			return;
+		}
+		printf("%s ", ipaddr_to_anyname(&addr->in));
+	} else if (family == AF_INET6) {
+		if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
+		    addr->ip6[2] == 0 && addr->ip6[3] == 0) {
+			printf("anywhere ");
+			return;
+		}
+		printf("%s ", ip6addr_to_anyname(&addr->in6));
+	}
+}
+
+static void
 print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
 {
 	char buf[BUFSIZ];
@@ -484,6 +878,103 @@ matchinfo_print(const void *ip, const st
 	}
 }
 
+static void
+conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
+               unsigned int family, bool numeric)
+{
+	if (info->match_flags & XT_CONNTRACK_STATE) {
+		if (info->invert_flags & XT_CONNTRACK_STATE)
+			printf("! ");
+		printf("%sctstate ", prefix);
+		print_state(info->state_mask);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_PROTO) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctproto %u ", prefix, info->l4proto);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGSRC) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctorigsrc ", prefix);
+		conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGDST) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctorigdst ", prefix);
+		conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLSRC) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctreplsrc ", prefix);
+		conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLDST) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctrepldst ", prefix);
+		conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)
+			printf("! ");
+		printf("%sctorigsrcport %u ", prefix,
+		       ntohs(info->origsrc_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)
+			printf("! ");
+		printf("%sctorigdstport %u ", prefix,
+		       ntohs(info->origdst_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)
+			printf("! ");
+		printf("%sctreplsrcport %u ", prefix,
+		       ntohs(info->replsrc_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT)
+			printf("! ");
+		printf("%sctrepldstport %u ", prefix,
+		       ntohs(info->repldst_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_STATUS) {
+		if (info->invert_flags & XT_CONNTRACK_STATUS)
+			printf("! ");
+		printf("%sctstatus ", prefix);
+		print_status(info->status_mask);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_EXPIRES) {
+		if (info->invert_flags & XT_CONNTRACK_EXPIRES)
+			printf("! ");
+		printf("%sctexpire ", prefix);
+
+		if (info->expires_max == info->expires_min)
+			printf("%u ", (unsigned int)info->expires_min);
+		else
+			printf("%u:%u ", (unsigned int)info->expires_min,
+			       (unsigned int)info->expires_max);
+	}
+}
+
 /* Prints out the matchinfo. */
 static void conntrack_print(const void *ip, const struct xt_entry_match *match,
                             int numeric)
@@ -491,12 +982,38 @@ static void conntrack_print(const void *
 	matchinfo_print(ip, match, numeric, "");
 }
 
+static void
+conntrack_mt_print(const void *ip, const struct xt_entry_match *match,
+                   int numeric)
+{
+	conntrack_dump((const void *)match->data, "", AF_INET, numeric);
+}
+
+static void
+conntrack_mt6_print(const void *ip, const struct xt_entry_match *match,
+                    int numeric)
+{
+	conntrack_dump((const void *)match->data, "", AF_INET6, numeric);
+}
+
 /* Saves the matchinfo in parsable form to stdout. */
 static void conntrack_save(const void *ip, const struct xt_entry_match *match)
 {
 	matchinfo_print(ip, match, 1, "--");
 }
 
+static void conntrack_mt_save(const void *ip,
+                              const struct xt_entry_match *match)
+{
+	conntrack_dump((const void *)match->data, "--", AF_INET, true);
+}
+
+static void conntrack_mt6_save(const void *ip,
+                               const struct xt_entry_match *match)
+{
+	conntrack_dump((const void *)match->data, "--", AF_INET6, true);
+}
+
 static struct xtables_match conntrack_match = {
 	.version       = IPTABLES_VERSION,
 	.name          = "conntrack",
@@ -509,10 +1026,42 @@ static struct xtables_match conntrack_ma
 	.final_check   = conntrack_mt_check,
 	.print         = conntrack_print,
 	.save          = conntrack_save,
+	.extra_opts    = conntrack_mt_opts_v0,
+};
+
+static struct xtables_match conntrack_mt_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "conntrack",
+	.revision      = 1,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.help          = conntrack_mt_help,
+	.parse         = conntrack_mt4_parse,
+	.final_check   = conntrack_mt_check,
+	.print         = conntrack_mt_print,
+	.save          = conntrack_mt_save,
+	.extra_opts    = conntrack_mt_opts,
+};
+
+static struct xtables_match conntrack_mt6_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "conntrack",
+	.revision      = 1,
+	.family        = AF_INET6,
+	.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.help          = conntrack_mt_help,
+	.parse         = conntrack_mt6_parse,
+	.final_check   = conntrack_mt_check,
+	.print         = conntrack_mt6_print,
+	.save          = conntrack_mt6_save,
 	.extra_opts    = conntrack_mt_opts,
 };
 
 void _init(void)
 {
 	xtables_register_match(&conntrack_match);
+	xtables_register_match(&conntrack_mt_reg);
+	xtables_register_match(&conntrack_mt6_reg);
 }
Index: iptables/extensions/libxt_conntrack.man
===================================================================
--- iptables.orig/extensions/libxt_conntrack.man
+++ iptables/extensions/libxt_conntrack.man
@@ -9,16 +9,22 @@ Possible states are listed below.
 Layer-4 protocol to match (by number or name)
 .TP
 [\fB!\fR] \fB--ctorigsrc\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against original source address
 .TP
 [\fB!\fR] \fB--ctorigdst\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against original destination address
 .TP
 [\fB!\fR] \fB--ctreplsrc\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against reply source address
 .TP
 [\fB!\fR] \fB--ctrepldst\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against reply destination address
+Match against original/reply source/destination address
+.TP
+[\fB!\fR] \fB--ctorigsrcport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctorigdstport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctreplsrcport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctrepldstport\fR \fIport\fR
+Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key.
 .TP
 [\fB!\fR] \fB--ctstatus\fR \fIstatelist\fR
 \fIstatuslist\fR is a comma separated list of the connection statuses to match.
@@ -27,6 +33,10 @@ Possible statuses are listed below.
 [\fB!\fR] \fB--ctexpire\fR \fItime\fR[\fB:\fR\fItime\fR]
 Match remaining lifetime in seconds against given value or range of values
 (inclusive)
+.TP
+\fB--ctdir\fR {\fBORIGINAL\fR|\fBREPLY\fR}
+Match packets that are flowing in the specified direction. If this flag is not
+specified at all, matches packets in both directions.
 .PP
 States for \fB--ctstate\fR:
 .TP
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
@ 2008-01-29 13:08 ` Patrick McHardy
  1 sibling, 0 replies; 4+ messages in thread
From: Patrick McHardy @ 2008-01-29 13:08 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> commit 7f1764fa749032eb8566226bbd1c5a58a8a5efc6
> Author: Jan Engelhardt <jengelh@computergmbh.de>
> Date:   Wed Jan 16 18:58:49 2008 +0100
> 
>     [NETFILTER]: xt_conntrack: add port and direction matching
>     
>     Extend the xt_conntrack match revision 1 by port matching (all four
>     {orig,repl}{src,dst}) and by packet direction matching.

Applied, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [IPTABLES]: libxt_conntrack revision 1
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
@ 2008-01-29 13:20   ` Patrick McHardy
  0 siblings, 0 replies; 4+ messages in thread
From: Patrick McHardy @ 2008-01-29 13:20 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> Add support for xt_conntrack match revision 1.
> 
> Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>


Applied, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-01-29 13:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
2008-01-29 13:20   ` Patrick McHardy
2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.