I have some small issues with the conntrack match in it's current incarnation

a) Very hard to extend with new features as there is no extra flag bits

b) Missing the ability to match conntrack ports.

c) Some errors in iptables-save output


Attached to this message is an extension patch to the conntrack match to

a) Be able to match conntrack source/destination ports.

b) The flags words extended to 32 bits to make room for the new options and 
leave some allowing for future extensions such as the ability to match 
original ICMP, new conntrack state bits, master connection etc without having 
to totally break binary compability.

c) Corrected iptables-save output

Attached is an incremental diff to the current CVS version.

Note: Due to the extension and addition of new fields in the match structure 
it is not binary compatible with the current "pending" version.

Regards
Henrik Norström
MARA Systems AB
? extensions/.BALANCE-test
? extensions/.CONFIRMED-test
? extensions/.CONNMARK-test
? extensions/.FTOS-test
? extensions/.IPV4OPTSSTRIP-test
? extensions/.NETLINK.test
? extensions/.NETMAP-test
? extensions/.REJECT-test6
? extensions/.ROUTE-test
? extensions/.ah-test6
? extensions/.confirmed-test
? extensions/.connmark-test
? extensions/.conntrack2-test
? extensions/.esp-test6
? extensions/.frag-test6
? extensions/.helper-test
? extensions/.ipv4options-test
? extensions/.ipv6header-test6
? extensions/.mport-test
? extensions/.nth-test
? extensions/.opts-test6
? extensions/.pool-test
? extensions/.psd-test
? extensions/.quota-test
? extensions/.random-test
? extensions/.realm-test
? extensions/.recent-test
? extensions/.record-rpc-test
? extensions/.rt-test6
? extensions/.string-test
? extensions/.time-test
? patch-o-matic/pending/.conntrack.patch.swp
Index: extensions/libipt_conntrack.c
===================================================================
RCS file: /cvspublic/netfilter/userspace/extensions/libipt_conntrack.c,v
retrieving revision 1.4
diff -u -r1.4 libipt_conntrack.c
--- extensions/libipt_conntrack.c	29 May 2002 13:08:16 -0000	1.4
+++ extensions/libipt_conntrack.c	1 Jul 2002 13:32:29 -0000
@@ -30,6 +30,14 @@
 "				Reply source specification\n"
 "     --ctrepldst  [!] address[/mask]\n"
 "				Reply destination specification\n"
+"     --ctorigsrcport [!] port[:port]\n"
+"				Original source port specification\n"
+"     --ctorigdstport [!] port[:port]\n"
+"				Original destination port specification\n"
+"     --ctreplsrcport [!] port[:port]\n"
+"				Reply source port specification\n"
+"     --ctrepldstport [!] port[:port]\n"
+"				Reply destination port specification\n"
 " [!] --ctstatus [NONE|EXPECTED|SEEN_REPLY|ASSURED][,...]\n"
 "				Status(es) to match\n"
 " [!] --ctexpire time[:time]	Match remaining lifetime in seconds against\n"
@@ -48,6 +56,10 @@
 	{ "ctrepldst", 1, 0, '6' },
 	{ "ctstatus", 1, 0, '7' },
 	{ "ctexpire", 1, 0, '8' },
+	{ "ctorigsrcport", 1, 0, '9' },
+	{ "ctorigdstport", 1, 0, 'a' },
+	{ "ctreplsrcport", 1, 0, 'b' },
+	{ "ctrepldstport", 1, 0, 'c' },
 	{0}
 };
 
@@ -163,6 +175,54 @@
 	
 }
 
+
+static int
+service_to_port(const char *name)
+{
+	struct servent *service;
+
+	if ((service = getservbyname(name, "tcp")) != NULL)
+		return ntohs((unsigned short) service->s_port);
+
+	if ((service = getservbyname(name, "udp")) != NULL)
+		return ntohs((unsigned short) service->s_port);
+
+	return -1;
+}
+
+static u_int16_t
+parse_port(const char *port)
+{
+	unsigned int portnum;
+
+	if (string_to_number(port, 0, 65535, &portnum) != -1 ||
+	    (portnum = service_to_port(port)) != -1)
+		return (u_int16_t)portnum;
+
+	exit_error(PARAMETER_PROBLEM,
+		   "invalid port/service `%s' specified", port);
+}
+
+static void
+parse_ports(const char *portstring, u_int16_t *ports)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(portstring);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		ports[0] = ports[1] = parse_port(buffer);
+	else {
+		*cp = '\0';
+		cp++;
+
+		ports[0] = buffer[0] ? parse_port(buffer) : 0;
+		ports[1] = cp[0] ? parse_port(cp) : 0xFFFF;
+	}
+	free(buffer);
+}
+
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -309,6 +369,46 @@
 		sinfo->flags |= IPT_CONNTRACK_EXPIRES;
 		break;
 
+	case '9':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_ports(argv[optind-1], sinfo->srcports[IP_CT_DIR_ORIGINAL]);
+		if (invert) {
+			sinfo->invflags |= IPT_CONNTRACK_ORIGSRCPORT;
+		}
+		sinfo->flags |= IPT_CONNTRACK_ORIGSRCPORT;
+		break;
+
+	case 'a':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_ports(argv[optind-1], sinfo->dstports[IP_CT_DIR_ORIGINAL]);
+		if (invert) {
+			sinfo->invflags |= IPT_CONNTRACK_ORIGDSTPORT;
+		}
+		sinfo->flags |= IPT_CONNTRACK_ORIGDSTPORT;
+		break;
+
+	case 'b':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_ports(argv[optind-1], sinfo->srcports[IP_CT_DIR_REPLY]);
+		if (invert) {
+			sinfo->invflags |= IPT_CONNTRACK_REPLSRCPORT;
+		}
+		sinfo->flags |= IPT_CONNTRACK_REPLSRCPORT;
+		break;
+
+	case 'c':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_ports(argv[optind-1], sinfo->dstports[IP_CT_DIR_REPLY]);
+		if (invert) {
+			sinfo->invflags |= IPT_CONNTRACK_REPLDSTPORT;
+		}
+		sinfo->flags |= IPT_CONNTRACK_REPLDSTPORT;
+		break;
+
 	default:
 		return 0;
 	}
@@ -386,7 +486,7 @@
 	char buf[BUFSIZ];
 
         if (inv)
-               	fputc('!', stdout);
+               	printf("! ");
 
 	if (mask->s_addr == 0L && !numeric)
 		printf("%s ", "anywhere");
@@ -409,7 +509,7 @@
 	if(sinfo->flags & IPT_CONNTRACK_STATE) {
 		printf("%sctstate ", optpfx);
         	if (sinfo->invflags & IPT_CONNTRACK_STATE)
-                	fputc('!', stdout);
+			printf("! ");
 		print_state(sinfo->statemask);
 	}
 
@@ -434,7 +534,7 @@
 	}
 
 	if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
-		printf("%sctorigsrc ", optpfx);
+		printf("%sctreplsrc ", optpfx);
 
 		print_addr(
 		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
@@ -444,7 +544,7 @@
 	}
 
 	if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
-		printf("%sctorigdst ", optpfx);
+		printf("%sctrepldst ", optpfx);
 
 		print_addr(
 		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
@@ -453,18 +553,45 @@
 		    numeric);
 	}
 
+	if(sinfo->flags & IPT_CONNTRACK_ORIGSRCPORT) {
+		printf("%sctorigsrcport ", optpfx);
+        	if (sinfo->invflags & IPT_CONNTRACK_ORIGSRCPORT)
+			printf("! ");
+		printf("%u:%u ", (unsigned)sinfo->srcports[IP_CT_DIR_ORIGINAL][0], (unsigned)sinfo->srcports[IP_CT_DIR_ORIGINAL][1]);
+	}
+
+	if(sinfo->flags & IPT_CONNTRACK_ORIGDSTPORT) {
+		printf("%sctorigdstport ", optpfx);
+        	if (sinfo->invflags & IPT_CONNTRACK_ORIGDSTPORT)
+			printf("! ");
+		printf("%u:%u ", (unsigned)sinfo->dstports[IP_CT_DIR_ORIGINAL][0], (unsigned)sinfo->dstports[IP_CT_DIR_ORIGINAL][1]);
+	}
+
+	if(sinfo->flags & IPT_CONNTRACK_REPLSRCPORT) {
+		printf("%sctreplsrcport ", optpfx);
+        	if (sinfo->invflags & IPT_CONNTRACK_REPLSRCPORT)
+			printf("! ");
+		printf("%u:%u ", (unsigned)sinfo->srcports[IP_CT_DIR_REPLY][0], (unsigned)sinfo->srcports[IP_CT_DIR_REPLY][1]);
+	}
+
+	if(sinfo->flags & IPT_CONNTRACK_REPLDSTPORT) {
+		printf("%sctrepldstport ", optpfx);
+        	if (sinfo->invflags & IPT_CONNTRACK_REPLDSTPORT)
+			printf("! ");
+		printf("%u:%u ", (unsigned)sinfo->dstports[IP_CT_DIR_REPLY][0], (unsigned)sinfo->dstports[IP_CT_DIR_REPLY][1]);
+	}
+
 	if(sinfo->flags & IPT_CONNTRACK_STATUS) {
 		printf("%sctstatus ", optpfx);
         	if (sinfo->invflags & IPT_CONNTRACK_STATE)
-                	fputc('!', stdout);
+			printf("! ");
 		print_status(sinfo->statusmask);
 	}
 
 	if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
 		printf("%sctexpire ", optpfx);
         	if (sinfo->invflags & IPT_CONNTRACK_EXPIRES)
-                	fputc('!', stdout);
-
+			printf("! ");
         	if (sinfo->expires_max == sinfo->expires_min)
                 	printf("%lu ", sinfo->expires_min);
         	else
Index: patch-o-matic/pending/conntrack.patch
===================================================================
RCS file: /cvspublic/netfilter/userspace/patch-o-matic/pending/conntrack.patch,v
retrieving revision 1.1
diff -u -r1.1 conntrack.patch
--- patch-o-matic/pending/conntrack.patch	19 Jan 2002 12:29:21 -0000	1.1
+++ patch-o-matic/pending/conntrack.patch	1 Jul 2002 13:32:29 -0000
@@ -1,7 +1,7 @@
 diff -urN linux-2.4.18-pre4/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.4.18-pre4-mb/include/linux/netfilter_ipv4/ipt_conntrack.h
 --- linux-2.4.18-pre4/include/linux/netfilter_ipv4/ipt_conntrack.h	Thu Jan  1 01:00:00 1970
 +++ linux-2.4.18-pre4-mb/include/linux/netfilter_ipv4/ipt_conntrack.h	Sat Jan 19 12:21:55 2002
-@@ -0,0 +1,38 @@
+@@ -0,0 +1,46 @@
 +/* Header file for kernel module to match connection tracking information.
 + * GPL (C) 2001  Marc Boucher ([EMAIL PROTECTED]).
 + */
@@ -16,14 +16,18 @@
 +#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
 +
 +/* flags, invflags: */
-+#define IPT_CONNTRACK_STATE	0x01
-+#define IPT_CONNTRACK_PROTO	0x02
-+#define IPT_CONNTRACK_ORIGSRC	0x04
-+#define IPT_CONNTRACK_ORIGDST	0x08
-+#define IPT_CONNTRACK_REPLSRC	0x10
-+#define IPT_CONNTRACK_REPLDST	0x20
-+#define IPT_CONNTRACK_STATUS	0x40
-+#define IPT_CONNTRACK_EXPIRES	0x80
++#define IPT_CONNTRACK_STATE		0x00000001
++#define IPT_CONNTRACK_PROTO		0x00000002
++#define IPT_CONNTRACK_ORIGSRC		0x00000004
++#define IPT_CONNTRACK_ORIGDST		0x00000008
++#define IPT_CONNTRACK_REPLSRC		0x00000010
++#define IPT_CONNTRACK_REPLDST		0x00000020
++#define IPT_CONNTRACK_STATUS		0x00000040
++#define IPT_CONNTRACK_EXPIRES		0x00000080
++#define IPT_CONNTRACK_ORIGSRCPORT	0x00000100
++#define IPT_CONNTRACK_ORIGDSTPORT	0x00000200
++#define IPT_CONNTRACK_REPLSRCPORT	0x00000400
++#define IPT_CONNTRACK_REPLDSTPORT	0x00000800
 +
 +struct ipt_conntrack_info
 +{
@@ -34,16 +38,20 @@
 +
 +	unsigned long expires_min, expires_max;
 +
++	/* The port fields in the tuple is not used */
++	u_int16_t srcports[IP_CT_DIR_MAX][2];
++	u_int16_t dstports[IP_CT_DIR_MAX][2];
++
 +	/* Flags word */
-+	u_int8_t flags;
++	u_int32_t flags;
 +	/* Inverse flags */
-+	u_int8_t invflags;
++	u_int32_t invflags;
 +};
 +#endif /*_IPT_CONNTRACK_H*/
 diff -urN linux-2.4.18-pre4/net/ipv4/netfilter/ipt_conntrack.c linux-2.4.18-pre4-mb/net/ipv4/netfilter/ipt_conntrack.c
 --- linux-2.4.18-pre4/net/ipv4/netfilter/ipt_conntrack.c	Thu Jan  1 01:00:00 1970
 +++ linux-2.4.18-pre4-mb/net/ipv4/netfilter/ipt_conntrack.c	Sat Jan 19 12:21:55 2002
-@@ -0,0 +1,123 @@
+@@ -0,0 +1,154 @@
 +/* Kernel module to match connection tracking information.
 + * Superset of Rusty's minimalistic state match.
 + * GPL (C) 2001  Marc Boucher ([EMAIL PROTECTED]).
@@ -54,6 +62,17 @@
 +#include <linux/netfilter_ipv4/ip_tables.h>
 +#include <linux/netfilter_ipv4/ipt_conntrack.h>
 +
++/* Returns 1 if the port is matched by the range, 0 otherwise */
++static inline int
++port_match(u_int16_t min, u_int16_t max, u_int16_t port)
++{
++	int ret;
++
++	ret = port >= min && port <= max;
++	return ret;
++}
++
++
 +static int
 +match(const struct sk_buff *skb,
 +      const struct net_device *in,
@@ -111,6 +130,26 @@
 +
 +	if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
 +		if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST))
++			return 0;
++	}
++
++	if(sinfo->flags & IPT_CONNTRACK_ORIGSRCPORT) {
++		if (!ct || FWINV(!port_match(sinfo->srcports[IP_CT_DIR_ORIGINAL][0], sinfo->srcports[IP_CT_DIR_ORIGINAL][1], ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port)), IPT_CONNTRACK_ORIGSRCPORT))
++			return 0;
++	}
++
++	if(sinfo->flags & IPT_CONNTRACK_ORIGDSTPORT) {
++		if (!ct || FWINV(!port_match(sinfo->dstports[IP_CT_DIR_ORIGINAL][0], sinfo->dstports[IP_CT_DIR_ORIGINAL][1], ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port)), IPT_CONNTRACK_ORIGDSTPORT))
++			return 0;
++	}
++
++	if(sinfo->flags & IPT_CONNTRACK_REPLSRCPORT) {
++		if (!ct || FWINV(!port_match(sinfo->srcports[IP_CT_DIR_REPLY][0], sinfo->srcports[IP_CT_DIR_REPLY][1], ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.tcp.port)), IPT_CONNTRACK_REPLSRCPORT))
++			return 0;
++	}
++
++	if(sinfo->flags & IPT_CONNTRACK_REPLDSTPORT) {
++		if (!ct || FWINV(!port_match(sinfo->dstports[IP_CT_DIR_REPLY][0], sinfo->dstports[IP_CT_DIR_REPLY][1], ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port)), IPT_CONNTRACK_REPLDSTPORT))
 +			return 0;
 +	}
 +
Index: patch-o-matic/pending/conntrack.patch.help
===================================================================
RCS file: /cvspublic/netfilter/userspace/patch-o-matic/pending/conntrack.patch.help,v
retrieving revision 1.1
diff -u -r1.1 conntrack.patch.help
--- patch-o-matic/pending/conntrack.patch.help	19 Jan 2002 12:29:21 -0000	1.1
+++ patch-o-matic/pending/conntrack.patch.help	1 Jul 2002 13:32:29 -0000
@@ -1,4 +1,4 @@
-Author: Marc Boucher <[EMAIL PROTECTED]>
+Author: Marc Boucher <[EMAIL PROTECTED]>, Henrik Nordstrom <[EMAIL PROTECTED]>
 Status: Works For Me.
 
 This is a general conntrack match module, a superset of the state match.
@@ -23,6 +23,11 @@
                                 Reply source specification
      --ctrepldst  [!] address[/mask]
                                 Reply destination specification
+     --ctorigsrcport [!] port	Original source port specification
+     --ctorigdstport [!] port	Original destination port specification
+     --ctreplsrcport [!] port	Reply source port specification
+     --ctrepldstport [!] port	Reply destination port specification
+
  [!] --ctstatus [NONE|EXPECTED|SEEN_REPLY|ASSURED][,...]
                                 Status(es) to match
  [!] --ctexpire  time[:time]    Match remaining lifetime in seconds against

Reply via email to