netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/11] Line-based makefile
@ 2007-12-22  2:44 Jan Engelhardt
  2007-12-22  2:44 ` [PATCH 2/11] strtonum Jan Engelhardt
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:44 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Transform the extensions' Makefile into a linear form to reduce
conflicts for patch stacks (very helpful during development).
Ideally, I'd just push in the automake patch, though,
which uses wildcards ;-)

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

---
 extensions/Makefile |   92 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 88 insertions(+), 4 deletions(-)

Index: iptables-modules/extensions/Makefile
===================================================================
--- iptables-modules.orig/extensions/Makefile
+++ iptables-modules/extensions/Makefile
@@ -5,13 +5,97 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah addrtype conntrack ecn icmp iprange owner policy realm recent tos ttl unclean CLUSTERIP DNAT ECN LOG MASQUERADE MIRROR NETMAP REDIRECT REJECT SAME SNAT TOS TTL ULOG
-PF6_EXT_SLIB:=ah dst eui64 frag hbh hl icmp6 ipv6header mh owner policy rt HL LOG REJECT
-PFX_EXT_SLIB:=connbytes connmark connlimit comment dccp dscp esp hashlimit helper length limit mac mark multiport physdev pkttype quota sctp state statistic standard string tcp tcpmss time u32 udp CLASSIFY CONNMARK DSCP MARK NFLOG NFQUEUE NOTRACK TCPMSS TRACE
+a :=
+a += CLUSTERIP
+a += DNAT
+a += ECN
+a += LOG
+a += MASQUERADE
+a += MIRROR
+a += NETMAP
+a += REDIRECT
+a += REJECT
+a += SAME
+a += SNAT
+a += TOS
+a += TTL
+a += ULOG
+a += addrtype
+a += ah
+a += conntrack
+a += ecn
+a += icmp
+a += iprange
+a += owner
+a += policy
+a += realm
+a += recent
+a += tos
+a += ttl
+a += unclean
+PF_EXT_SLIB := ${a}
+a :=
+a += HL
+a += LOG
+a += REJECT
+a += ah
+a += dst
+a += eui64
+a += frag
+a += hbh
+a += hl
+a += icmp6
+a += ipv6header
+a += mh
+a += owner
+a += policy
+a += rt
+PF6_EXT_SLIB := ${a}
+a :=
+a += CLASSIFY
+a += CONNMARK
+a += DSCP
+a += MARK
+a += NFLOG
+a += NFQUEUE
+a += NOTRACK
+a += TCPMSS
+a += TRACE
+a += comment
+a += connbytes
+a += connlimit
+a += connmark
+a += dccp
+a += dscp
+a += esp
+a += hashlimit
+a += helper
+a += length
+a += limit
+a += mac
+a += mark
+a += multiport
+a += physdev
+a += pkttype
+a += quota
+a += sctp
+a += standard
+a += state
+a += statistic
+a += string
+a += tcp
+a += tcpmss
+a += time
+a += u32
+a += udp
+PFX_EXT_SLIB := ${a}
 
 PF_EXT_SELINUX_SLIB:=
 PF6_EXT_SELINUX_SLIB:=
-PFX_EXT_SELINUX_SLIB:=CONNSECMARK SECMARK
+a :=
+a += CONNSECMARK
+a += SECMARK
+PFX_EXT_SELINUX_SLIB := ${a}
 
 ifeq ($(DO_SELINUX), 1)
 PF_EXT_SE_SLIB:=$(PF_EXT_SELINUX_SLIB)


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

* [PATCH 2/11] strtonum
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
@ 2007-12-22  2:44 ` Jan Engelhardt
  2007-12-22  2:44 ` [PATCH 3/11] Common error strings Jan Engelhardt
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:44 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Introduce strtonum(), which works like string_to_number(), but passes
back the 'end' pointer. It is useful where you want to do boundary
checking yet work with strings that are not entirely slurped by
strtoul(), e.g.:

	s = "1/2";
	if (!strtonum(s, &end, &value, 0, 5))
		error("Zero-length string, or value out of bounds");
	if (*end != '/')
		error("Malformed string");
	info->param1 = value;
	if (!strtonum(end + 1, &end, &value, 2, 4))
		error("..");
	if (*end != '\0')
		error("Malformed string");
	info->param2 = value;

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

---
 include/xtables.h |    5 +++++
 xtables.c         |   44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

Index: iptables-modules/include/xtables.h
===================================================================
--- iptables-modules.orig/include/xtables.h
+++ iptables-modules/include/xtables.h
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/netfilter/x_tables.h>
 #include <libiptc/libxtc.h>
+#include <stdbool.h>
 
 #ifndef XT_LIB_DIR
 #define XT_LIB_DIR "/usr/local/lib/iptables"
@@ -206,6 +207,10 @@ extern int string_to_number(const char *
 			    unsigned int min,
 			    unsigned int max,
 			    unsigned int *ret);
+extern bool strtonuml(const char *, char **, unsigned long *,
+	unsigned long, unsigned long);
+extern bool strtonum(const char *, char **, unsigned int *,
+	unsigned int, unsigned int);
 extern int service_to_port(const char *name, const char *proto);
 extern u_int16_t parse_port(const char *port, const char *proto);
 extern void
Index: iptables-modules/xtables.c
===================================================================
--- iptables-modules.orig/xtables.c
+++ iptables-modules/xtables.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -199,6 +200,49 @@ int string_to_number(const char *s, unsi
 	return result;
 }
 
+/*
+ * strtonum{,l} - string to number conversion
+ *
+ * If @end is NULL, we assume the caller does not want
+ * a case like "15a", so reject it.
+ */
+bool strtonuml(const char *s, char **end, unsigned long *value,
+               unsigned long min, unsigned long max)
+{
+	unsigned long v;
+	char *my_end;
+
+	errno = 0;
+	v = strtoul(s, &my_end, 0);
+
+	if (my_end == s)
+		return false;
+	if (end != NULL)
+		*end = my_end;
+
+	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
+		if (value != NULL)
+			*value = v;
+		if (end == NULL)
+			return *my_end == '\0';
+		return true;
+	}
+
+	return false;
+}
+
+bool strtonum(const char *s, char **end, unsigned int *value,
+                  unsigned int min, unsigned int max)
+{
+	unsigned long v;
+	bool ret;
+
+	ret = strtonuml(s, end, &v, min, max);
+	if (value != NULL)
+		*value = v;
+	return ret;
+}
+
 int service_to_port(const char *name, const char *proto)
 {
 	struct servent *service;

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

* [PATCH 3/11] Common error strings
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
  2007-12-22  2:44 ` [PATCH 2/11] strtonum Jan Engelhardt
@ 2007-12-22  2:44 ` Jan Engelhardt
  2007-12-22  2:45 ` [PATCH 4/11] libxt_owner match Jan Engelhardt
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:44 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Error messages vary wildly among modules, and there is a lot of
reundance in it too. Introduce a helper function that does all of
the parameter checking boilerplate and gives unique messages.

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

---
 include/xtables.h |    9 ++++++++-
 xtables.c         |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletion(-)

Index: iptables-modules/include/xtables.h
===================================================================
--- iptables-modules.orig/include/xtables.h
+++ iptables-modules/include/xtables.h
@@ -220,7 +220,13 @@ enum exittype {
 	OTHER_PROBLEM = 1,
 	PARAMETER_PROBLEM,
 	VERSION_PROBLEM,
-	RESOURCE_PROBLEM
+	RESOURCE_PROBLEM,
+	P_ONLY_ONCE,
+	P_NO_INVERT,
+	P_BAD_VALUE,
+	P_NEED_MATCH,
+	P_NEED_ACTION,
+	P_ONE_ACTION,
 };
 
 /* this is a special 64bit data type that is 8-byte aligned */
@@ -229,6 +235,7 @@ enum exittype {
 int check_inverse(const char option[], int *invert, int *optind, int argc);
 void exit_error(enum exittype, const char *, ...)__attribute__((noreturn,
 							  format(printf,2,3)));
+extern void param_act(enum exittype, const char *, ...);
 extern const char *program_name, *program_version;
 
 #define _init __attribute__((constructor)) my_init
Index: iptables-modules/xtables.c
===================================================================
--- iptables-modules.orig/xtables.c
+++ iptables-modules/xtables.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -639,3 +640,52 @@ void xtables_register_target(struct xtab
 	me->t = NULL;
 	me->tflags = 0;
 }
+
+void param_act(enum exittype status, const char *p1, ...)
+{
+	const char *p2, *p3;
+	va_list args;
+	bool b3;
+
+	va_start(args, msg);
+
+	switch (status) {
+	case P_ONLY_ONCE:
+		exit_error(PARAMETER_PROBLEM,
+		           "%s: \"%s\" option may only be specified once\n",
+		           p1, va_arg(args, const char *));
+		break;
+	case P_NO_INVERT:
+		p2 = va_arg(args, const char *);
+		b3 = va_arg(args, bool);
+		if (!b3)
+			return;
+		exit_error(PARAMETER_PROBLEM,
+		           "%s: Unexpected \"!\" after \"%s\" option",
+		           p1, va_arg(args, const char *));
+		break;
+	case P_BAD_VALUE:
+		p2 = va_arg(args, const char *);
+		p3 = va_arg(args, const char *);
+		exit_error(PARAMETER_PROBLEM,
+		           "%s: Bad value for \"%s\" option: \"%s\"",
+		           p1, p2, p3);
+		break;
+	case P_NEED_MATCH:
+		exit_error(PARAMETER_PROBLEM,
+		           "%s: Need at least one match option", p1);
+		break;
+	case P_NEED_ACTION:
+		exit_error(PARAMETER_PROBLEM,
+		           "%s: Need at least one action option", p1);
+		break;
+	case P_ONE_ACTION:
+		exit_error(PARAMETER_PROBLEM,
+		             "%s: At most one action is possible", p1);
+		break;
+	default:
+		exit_error(status, msg, args);
+	}
+
+	va_end(args);
+}

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

* [PATCH 4/11] libxt_owner match
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
  2007-12-22  2:44 ` [PATCH 2/11] strtonum Jan Engelhardt
  2007-12-22  2:44 ` [PATCH 3/11] Common error strings Jan Engelhardt
@ 2007-12-22  2:45 ` Jan Engelhardt
  2007-12-22  2:45 ` [PATCH 5/11] libxt_tos match revision 1 Jan Engelhardt
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:45 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Import libxt_owner into iptables


libxt_owner merges libipt_owner and libip6t_owner, and adds support
for the new xt_owner match v1.

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

---
 Delete libipt_owner.c
 Delete libip6t_owner.c

 extensions/Makefile                |    3 
 extensions/libxt_owner.c           |  582 +++++++++++++++++++++++++++++++++++++
 extensions/libxt_owner.man         |   16 +
 include/linux/netfilter/xt_owner.h |   16 +
 4 files changed, 615 insertions(+), 2 deletions(-)

Index: iptables-modules/extensions/Makefile
===================================================================
--- iptables-modules.orig/extensions/Makefile
+++ iptables-modules/extensions/Makefile
@@ -26,7 +26,6 @@ a += conntrack
 a += ecn
 a += icmp
 a += iprange
-a += owner
 a += policy
 a += realm
 a += recent
@@ -47,7 +46,6 @@ a += hl
 a += icmp6
 a += ipv6header
 a += mh
-a += owner
 a += policy
 a += rt
 PF6_EXT_SLIB := ${a}
@@ -75,6 +73,7 @@ a += limit
 a += mac
 a += mark
 a += multiport
+a += owner
 a += physdev
 a += pkttype
 a += quota
Index: iptables-modules/extensions/libxt_owner.c
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_owner.c
@@ -0,0 +1,582 @@
+/*
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <grp.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_owner.h>
+#include <linux/netfilter_ipv4/ipt_owner.h>
+#include <linux/netfilter_ipv6/ip6t_owner.h>
+
+enum {
+	FLAG_UID_OWNER     = 1 << 0,
+	FLAG_GID_OWNER     = 1 << 1,
+	FLAG_SOCKET_EXISTS = 1 << 2,
+	FLAG_PID_OWNER     = 1 << 3,
+	FLAG_SID_OWNER     = 1 << 4,
+	FLAG_COMM          = 1 << 5,
+};
+
+static void owner_mt_help_v0(void)
+{
+#ifdef IPT_OWNER_COMM
+	printf(
+"owner match options:\n"
+"[!] --uid-owner userid       Match local UID\n"
+"[!] --gid-owner groupid      Match local GID\n"
+"[!] --pid-owner processid    Match local PID\n"
+"[!] --sid-owner sessionid    Match local SID\n"
+"[!] --cmd-owner name         Match local command name\n"
+"NOTE: PID, SID and command matching are broken on SMP\n"
+"\n");
+#else
+	printf(
+"owner match options:\n"
+"[!] --uid-owner userid       Match local UID\n"
+"[!] --gid-owner groupid      Match local GID\n"
+"[!] --pid-owner processid    Match local PID\n"
+"[!] --sid-owner sessionid    Match local SID\n"
+"NOTE: PID and SID matching are broken on SMP\n"
+"\n");
+#endif /* IPT_OWNER_COMM */
+}
+
+static void owner_mt6_help_v0(void)
+{
+	printf(
+"owner match options:\n"
+"[!] --uid-owner userid       Match local UID\n"
+"[!] --gid-owner groupid      Match local GID\n"
+"[!] --pid-owner processid    Match local PID\n"
+"[!] --sid-owner sessionid    Match local SID\n"
+"NOTE: PID and SID matching are broken on SMP\n"
+"\n");
+}
+
+static void owner_mt_help(void)
+{
+	printf(
+"owner match options:\n"
+"[!] --uid-owner userid     Match local UID\n"
+"[!] --gid-owner groupid    Match local GID\n"
+"[!] --socket-exists        Match if socket exists\n"
+"\n");
+}
+
+static const struct option owner_mt_opts_v0[] = {
+	{.name = "uid-owner", .has_arg = true, .val = 'u'},
+	{.name = "gid-owner", .has_arg = true, .val = 'g'},
+	{.name = "pid-owner", .has_arg = true, .val = 'p'},
+	{.name = "sid-owner", .has_arg = true, .val = 's'},
+#ifdef IPT_OWNER_COMM
+	{.name = "cmd-owner", .has_arg = true, .val = 'c'},
+#endif
+	{},
+};
+
+static const struct option owner_mt6_opts_v0[] = {
+	{.name = "uid-owner", .has_arg = true, .val = 'u'},
+	{.name = "gid-owner", .has_arg = true, .val = 'g'},
+	{.name = "pid-owner", .has_arg = true, .val = 'p'},
+	{.name = "sid-owner", .has_arg = true, .val = 's'},
+	{},
+};
+
+static const struct option owner_mt_opts[] = {
+	{.name = "uid-owner",     .has_arg = true,  .val = 'u'},
+	{.name = "gid-owner",     .has_arg = true,  .val = 'g'},
+	{.name = "socket-exists", .has_arg = false, .val = 'k'},
+	{},
+};
+
+static int
+owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+                  const void *entry, struct xt_entry_match **match)
+{
+	struct ipt_owner_info *info = (void *)(*match)->data;
+	struct passwd *pwd;
+	struct group *grp;
+	unsigned int id;
+
+	switch (c) {
+	case 'u':
+		param_act(P_ONLY_ONCE, "owner", "--uid-owner", *flags & FLAG_UID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((pwd = getpwnam(optarg)) != NULL)
+			id = pwd->pw_uid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(uid_t)0))
+			param_act(P_BAD_VALUE, "owner", "--uid-owner", optarg);
+		if (invert)
+			info->invert |= IPT_OWNER_UID;
+		info->match |= IPT_OWNER_UID;
+		info->uid    = id;
+		*flags      |= FLAG_UID_OWNER;
+		return true;
+
+	case 'g':
+		param_act(P_ONLY_ONCE, "owner", "--gid-owner", *flags & FLAG_GID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((grp = getgrnam(optarg)) != NULL)
+			id = grp->gr_gid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(gid_t)0))
+			param_act(P_BAD_VALUE, "owner", "--gid-owner", optarg);
+		if (invert)
+			info->invert |= IPT_OWNER_GID;
+		info->match |= IPT_OWNER_GID;
+		info->gid    = id;
+		*flags      |= FLAG_GID_OWNER;
+		return true;
+
+	case 'p':
+		param_act(P_ONLY_ONCE, "owner", "--pid-owner", *flags & FLAG_PID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!strtonum(optarg, NULL, &id, 0, INT_MAX))
+			param_act(P_BAD_VALUE, "owner", "--pid-owner", optarg);
+		if (invert)
+			info->invert |= IPT_OWNER_PID;
+		info->match |= IPT_OWNER_PID;
+		info->pid    = id;
+		*flags      |= FLAG_PID_OWNER;
+		return true;
+
+	case 's':
+		param_act(P_ONLY_ONCE, "owner", "--sid-owner", *flags & FLAG_SID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!strtonum(optarg, NULL, &id, 0, INT_MAX))
+			param_act(P_BAD_VALUE, "owner", "--sid-value", optarg);
+		if (invert)
+			info->invert |= IPT_OWNER_SID;
+		info->match |= IPT_OWNER_SID;
+		info->sid    = id;
+		*flags      |= FLAG_SID_OWNER;
+		return true;
+
+#ifdef IPT_OWNER_COMM
+	case 'c':
+		param_act(P_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (strlen(optarg) > sizeof(info->comm))
+			exit_error(PARAMETER_PROBLEM, "owner match: command "
+			           "\"%s\" too long, max. %zu characters",
+			           optarg, sizeof(info->comm));
+
+		info->comm[sizeof(info->comm)-1] = '\0';
+		strncpy(info->comm, optarg, sizeof(info->comm));
+
+		if (invert)
+			info->invert |= IPT_OWNER_COMM;
+		info->match |= IPT_OWNER_COMM;
+		*flags      |= FLAG_COMM;
+		return true;
+#endif
+	}
+	return false;
+}
+
+static int
+owner_mt6_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+                   const void *entry, struct xt_entry_match **match)
+{
+	struct ip6t_owner_info *info = (void *)(*match)->data;
+	struct passwd *pwd;
+	struct group *grp;
+	unsigned int id;
+
+	switch (c) {
+	case 'u':
+		param_act(P_ONLY_ONCE, "owner", "--uid-owner",
+		          *flags & FLAG_UID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((pwd = getpwnam(optarg)) != NULL)
+			id = pwd->pw_uid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(uid_t)0))
+			param_act(P_BAD_VALUE, "owner", "--uid-owner", optarg);
+		if (invert)
+			info->invert |= IP6T_OWNER_UID;
+		info->match |= IP6T_OWNER_UID;
+		info->uid    = id;
+		*flags      |= FLAG_UID_OWNER;
+		return true;
+
+	case 'g':
+		param_act(P_ONLY_ONCE, "owner", "--gid-owner",
+		          *flags & FLAG_GID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((grp = getgrnam(optarg)) != NULL)
+			id = grp->gr_gid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(gid_t)0))
+			param_act(P_BAD_VALUE, "owner", "--gid-owner", optarg);
+		if (invert)
+			info->invert |= IP6T_OWNER_GID;
+		info->match |= IP6T_OWNER_GID;
+		info->gid    = id;
+		*flags      |= FLAG_GID_OWNER;
+		return true;
+
+	case 'p':
+		param_act(P_ONLY_ONCE, "owner", "--pid-owner",
+		          *flags & FLAG_PID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!strtonum(optarg, NULL, &id, 0, INT_MAX))
+			param_act(P_BAD_VALUE, "owner", "--pid-owner", optarg);
+		if (invert)
+			info->invert |= IP6T_OWNER_PID;
+		info->match |= IP6T_OWNER_PID;
+		info->pid    = id;
+		*flags      |= FLAG_PID_OWNER;
+		return true;
+
+	case 's':
+		param_act(P_ONLY_ONCE, "owner", "--sid-owner",
+		          *flags & FLAG_SID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!strtonum(optarg, NULL, &id, 0, INT_MAX))
+			param_act(P_BAD_VALUE, "owner", "--sid-owner", optarg);
+		if (invert)
+			info->invert |= IP6T_OWNER_SID;
+		info->match |= IP6T_OWNER_SID;
+		info->sid    = id;
+		*flags      |= FLAG_SID_OWNER;
+		return true;
+	}
+	return false;
+}
+
+static int owner_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                          const void *entry, struct xt_entry_match **match)
+{
+	struct xt_owner_match_info *info = (void *)(*match)->data;
+	struct passwd *pwd;
+	struct group *grp;
+	unsigned int id;
+
+	switch (c) {
+	case 'u':
+		param_act(P_ONLY_ONCE, "owner", "--uid-owner",
+		          *flags & FLAG_UID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((pwd = getpwnam(optarg)) != NULL)
+			id = pwd->pw_uid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(uid_t)0))
+			param_act(P_BAD_VALUE, "owner", "--uid-owner", optarg);
+		if (invert)
+			info->invert |= XT_OWNER_UID;
+		info->match |= XT_OWNER_UID;
+		info->uid    = id;
+		*flags      |= FLAG_UID_OWNER;
+		return true;
+
+	case 'g':
+		param_act(P_ONLY_ONCE, "owner", "--gid-owner",
+		          *flags & FLAG_GID_OWNER);
+		check_inverse(optarg, &invert, &optind, 0);
+		if ((grp = getgrnam(optarg)) != NULL)
+			id = grp->gr_gid;
+		else if (!strtonum(optarg, NULL, &id, 0, ~(gid_t)0))
+			param_invalid("owner", "--gid-owner", optarg);
+		if (invert)
+			info->invert |= XT_OWNER_GID;
+		info->match |= XT_OWNER_GID;
+		info->gid    = id;
+		*flags      |= FLAG_GID_OWNER;
+		return true;
+
+	case 'k':
+		param_act(P_ONLY_ONCE, "owner", "--socket-exists",
+		          *flags & FLAG_SOCKET_EXISTS);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (invert)
+			info->invert |= XT_OWNER_SOCKET;
+		info->match |= XT_OWNER_SOCKET;
+		*flags |= FLAG_SOCKET_EXISTS;
+		return true;
+
+	}
+	return false;
+}
+
+static void owner_mt_check(unsigned int flags)
+{
+	if (flags == 0)
+		param_act(P_NEED_MATCH, "owner");
+}
+
+static void
+owner_mt_print_item_v0(const struct ipt_owner_info *info, const char *label,
+                       u_int8_t flag, bool numeric)
+{
+	if (!(info->match & flag))
+		return;
+	if (info->invert & flag)
+		printf("! ");
+	printf(label);
+
+	switch (info->match & flag) {
+	case IPT_OWNER_UID:
+		if (!numeric) {
+			struct passwd *pwd = getpwuid(info->uid);
+
+			if (pwd != NULL && pwd->pw_name != NULL) {
+				printf("%s ", pwd->pw_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->uid);
+		break;
+
+	case IPT_OWNER_GID:
+		if (!numeric) {
+			struct group *grp = getgrgid(info->gid);
+
+			if (grp != NULL && grp->gr_name != NULL) {
+				printf("%s ", grp->gr_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->gid);
+		break;
+
+	case IPT_OWNER_PID:
+		printf("%u ", (unsigned int)info->pid);
+		break;
+
+	case IPT_OWNER_SID:
+		printf("%u ", (unsigned int)info->sid);
+		break;
+
+#ifdef IPT_OWNER_COMM
+	case IPT_OWNER_COMM:
+		printf("%.*s ", (int)sizeof(info->comm), info->comm);
+		break;
+#endif
+	}
+}
+
+static void
+owner_mt6_print_item_v0(const struct ip6t_owner_info *info, const char *label,
+                        u_int8_t flag, bool numeric)
+{
+	if (!(info->match & flag))
+		return;
+	if (info->invert & flag)
+		printf("! ");
+	printf(label);
+
+	switch (info->match & flag) {
+	case IP6T_OWNER_UID:
+		if (!numeric) {
+			struct passwd *pwd = getpwuid(info->uid);
+
+			if (pwd != NULL && pwd->pw_name != NULL) {
+				printf("%s ", pwd->pw_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->uid);
+		break;
+
+	case IP6T_OWNER_GID:
+		if (!numeric) {
+			struct group *grp = getgrgid(info->gid);
+
+			if (grp != NULL && grp->gr_name != NULL) {
+				printf("%s ", grp->gr_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->gid);
+		break;
+
+	case IP6T_OWNER_PID:
+		printf("%u ", (unsigned int)info->pid);
+		break;
+
+	case IP6T_OWNER_SID:
+		printf("%u ", (unsigned int)info->sid);
+		break;
+	}
+}
+
+static void
+owner_mt_print_item(const struct xt_owner_match_info *info, const char *label,
+                    u_int8_t flag, bool numeric)
+{
+	if (!(info->match & flag))
+		return;
+	if (info->invert & flag)
+		printf("! ");
+	printf(label);
+
+	switch (info->match & flag) {
+	case XT_OWNER_UID:
+		if (!numeric) {
+			const struct passwd *pwd = getpwuid(info->uid);
+
+			if (pwd != NULL && pwd->pw_name != NULL) {
+				printf("%s ", pwd->pw_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->uid);
+		break;
+
+	case XT_OWNER_GID:
+		if (!numeric) {
+			const struct group *grp = getgrgid(info->gid);
+
+			if (grp != NULL && grp->gr_name != NULL) {
+				printf("%s ", grp->gr_name);
+				break;
+			}
+		}
+		printf("%u ", (unsigned int)info->gid);
+		break;
+	}
+}
+
+static void
+owner_mt_print_v0(const void *ip, const struct xt_entry_match *match,
+                  int numeric)
+{
+	const struct ipt_owner_info *info = (void *)match->data;
+
+	owner_mt_print_item_v0(info, "owner UID match ", IPT_OWNER_UID, numeric);
+	owner_mt_print_item_v0(info, "owner GID match ", IPT_OWNER_GID, numeric);
+	owner_mt_print_item_v0(info, "owner PID match ", IPT_OWNER_PID, numeric);
+	owner_mt_print_item_v0(info, "owner SID match ", IPT_OWNER_SID, numeric);
+#ifdef IPT_OWNER_COMM
+	owner_mt_print_item_v0(info, "owner CMD match ", IPT_OWNER_COMM, numeric);
+#endif
+}
+
+static void
+owner_mt6_print_v0(const void *ip, const struct xt_entry_match *match,
+                   int numeric)
+{
+	const struct ip6t_owner_info *info = (void *)match->data;
+
+	owner_mt6_print_item_v0(info, "owner UID match ", IPT_OWNER_UID, numeric);
+	owner_mt6_print_item_v0(info, "owner GID match ", IPT_OWNER_GID, numeric);
+	owner_mt6_print_item_v0(info, "owner PID match ", IPT_OWNER_PID, numeric);
+	owner_mt6_print_item_v0(info, "owner SID match ", IPT_OWNER_SID, numeric);
+}
+
+static void owner_mt_print(const void *ip, const struct xt_entry_match *match,
+                           int numeric)
+{
+	const struct xt_owner_match_info *info = (void *)match->data;
+
+	owner_mt_print_item(info, "owner socket exists ", XT_OWNER_SOCKET, numeric);
+	owner_mt_print_item(info, "owner UID match ",     XT_OWNER_UID,    numeric);
+	owner_mt_print_item(info, "owner GID match ",     XT_OWNER_GID,    numeric);
+}
+
+static void
+owner_mt_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+	const struct ipt_owner_info *info = (void *)match->data;
+
+	owner_mt_print_item_v0(info, "owner UID match ", IPT_OWNER_UID, true);
+	owner_mt_print_item_v0(info, "owner GID match ", IPT_OWNER_GID, true);
+	owner_mt_print_item_v0(info, "owner PID match ", IPT_OWNER_PID, true);
+	owner_mt_print_item_v0(info, "owner SID match ", IPT_OWNER_SID, true);
+#ifdef IPT_OWNER_COMM
+	owner_mt_print_item_v0(info, "owner CMD match ", IPT_OWNER_COMM, true);
+#endif
+}
+
+static void
+owner_mt6_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+	const struct ip6t_owner_info *info = (void *)match->data;
+
+	owner_mt6_print_item_v0(info, "owner UID match ", IPT_OWNER_UID, true);
+	owner_mt6_print_item_v0(info, "owner GID match ", IPT_OWNER_GID, true);
+	owner_mt6_print_item_v0(info, "owner PID match ", IPT_OWNER_PID, true);
+	owner_mt6_print_item_v0(info, "owner SID match ", IPT_OWNER_SID, true);
+}
+
+static void owner_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+	const struct xt_owner_match_info *info = (void *)match->data;
+
+	owner_mt_print_item(info, "--socket-exists ", XT_OWNER_SOCKET, false);
+	owner_mt_print_item(info, "--uid-owner",      XT_OWNER_UID,    false);
+	owner_mt_print_item(info, "--gid-owner",      XT_OWNER_GID,    false);
+}
+
+static struct xtables_match owner_mt_reg_v0 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "owner",
+	.revision      = 0,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct ipt_owner_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)),
+	.help          = owner_mt_help_v0,
+	.parse         = owner_mt_parse_v0,
+	.final_check   = owner_mt_check,
+	.print         = owner_mt_print_v0,
+	.save          = owner_mt_save_v0,
+	.extra_opts    = owner_mt_opts_v0,
+};
+
+static struct xtables_match owner_mt6_reg_v0 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "owner",
+	.revision      = 0,
+	.family        = AF_INET6,
+	.size          = XT_ALIGN(sizeof(struct ip6t_owner_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)),
+	.help          = owner_mt6_help_v0,
+	.parse         = owner_mt6_parse_v0,
+	.final_check   = owner_mt_check,
+	.print         = owner_mt6_print_v0,
+	.save          = owner_mt6_save_v0,
+	.extra_opts    = owner_mt6_opts_v0,
+};
+
+static struct xtables_match owner_mt_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "owner",
+	.revision      = 1,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+	.help          = owner_mt_help,
+	.parse         = owner_mt_parse,
+	.final_check   = owner_mt_check,
+	.print         = owner_mt_print,
+	.save          = owner_mt_save,
+	.extra_opts    = owner_mt_opts,
+};
+
+static struct xtables_match owner_mt6_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "owner",
+	.revision      = 1,
+	.family        = AF_INET6,
+	.size          = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+	.help          = owner_mt_help,
+	.parse         = owner_mt_parse,
+	.final_check   = owner_mt_check,
+	.print         = owner_mt_print,
+	.save          = owner_mt_save,
+	.extra_opts    = owner_mt_opts,
+};
+
+void _init(void)
+{
+	xtables_register_match(&owner_mt_reg_v0);
+	xtables_register_match(&owner_mt6_reg_v0);
+	xtables_register_match(&owner_mt_reg);
+	xtables_register_match(&owner_mt6_reg);
+}
Index: iptables-modules/extensions/libxt_owner.man
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_owner.man
@@ -0,0 +1,16 @@
+This module attempts to match various characteristics of the packet creator,
+for locally generated packets. This match is only valid in the OUTPUT and
+POSTROUTING chains. Forwarded packets do not have any socket associated with
+them. Packets from kernel threads do have a socket, but usually no owner.
+.TP
+\fB--uid-owner\fR \fIuserid\fR
+Matches if the packet socket's file structure (if it has one) is owned by the
+given user ID. A user name may be specified in place of \fIuserid\fR, in which
+case iptables will try to look it up.
+.TP
+\fB--gid-owner\fR \fIgroupid\fR
+Matches if the packet socket's file structure is owned by the given group ID.
+A group name may be specified in place of \fIgroupid\fR.
+.TP
+\fB--socket-exists\fR
+Matches if the packet is associated with a socket.
Index: iptables-modules/include/linux/netfilter/xt_owner.h
===================================================================
--- /dev/null
+++ iptables-modules/include/linux/netfilter/xt_owner.h
@@ -0,0 +1,16 @@
+#ifndef _XT_OWNER_MATCH_H
+#define _XT_OWNER_MATCH_H
+
+enum {
+	XT_OWNER_UID    = 1 << 0,
+	XT_OWNER_GID    = 1 << 1,
+	XT_OWNER_SOCKET = 1 << 2,
+};
+
+struct xt_owner_match_info {
+	u_int32_t uid;
+	u_int32_t gid;
+	u_int8_t match, invert;
+};
+
+#endif /* _XT_OWNER_MATCH_H */
-
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] 13+ messages in thread

* [PATCH 5/11] libxt_tos match revision 1
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (2 preceding siblings ...)
  2007-12-22  2:45 ` [PATCH 4/11] libxt_owner match Jan Engelhardt
@ 2007-12-22  2:45 ` Jan Engelhardt
  2007-12-22  2:45 ` [PATCH 6/11] libxt_TOS target " Jan Engelhardt
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:45 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Moves libipt_tos revision 0 to libxt_tos revision 0.
xt_tos revision 1 support.

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

---
 extensions/Makefile               |    2 
 extensions/libipt_tos.c           |  163 --------------------------------
 extensions/libipt_tos.man         |    9 -
 extensions/libxt_tos.c            |  192 ++++++++++++++++++++++++++++++++++++++
 extensions/libxt_tos.man          |   12 ++
 extensions/tos_values.c           |   91 ++++++++++++++++++
 include/linux/netfilter/xt_dscp.h |    6 +
 7 files changed, 302 insertions(+), 173 deletions(-)

Index: iptables-modules/extensions/Makefile
===================================================================
--- iptables-modules.orig/extensions/Makefile
+++ iptables-modules/extensions/Makefile
@@ -29,7 +29,6 @@ a += iprange
 a += policy
 a += realm
 a += recent
-a += tos
 a += ttl
 a += unclean
 PF_EXT_SLIB := ${a}
@@ -85,6 +84,7 @@ a += string
 a += tcp
 a += tcpmss
 a += time
+a += tos
 a += u32
 a += udp
 PFX_EXT_SLIB := ${a}
Index: iptables-modules/extensions/libipt_tos.c
===================================================================
--- iptables-modules.orig/extensions/libipt_tos.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Shared library add-on to iptables to add TOS matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_tos.h>
-
-/* TOS names and values. */
-static const
-struct TOS_value
-{
-	unsigned char TOS;
-	const char *name;
-} TOS_values[] = {
-	{ IPTOS_LOWDELAY,    "Minimize-Delay" },
-	{ IPTOS_THROUGHPUT,  "Maximize-Throughput" },
-	{ IPTOS_RELIABILITY, "Maximize-Reliability" },
-	{ IPTOS_MINCOST,     "Minimize-Cost" },
-	{ IPTOS_NORMALSVC,   "Normal-Service" },
-};
-
-/* Function which prints out usage message. */
-static void tos_help(void)
-{
-	unsigned int i;
-
-	printf(
-"TOS match v%s options:\n"
-"[!] --tos value                 Match Type of Service field from one of the\n"
-"                                following numeric or descriptive values:\n",
-IPTABLES_VERSION);
-
-	for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
-		printf("                                     %s %u (0x%02x)\n",
-		       TOS_values[i].name,
-                       TOS_values[i].TOS,
-                       TOS_values[i].TOS);
-	fputc('\n', stdout);
-}
-
-static const struct option tos_opts[] = {
-	{ "tos", 1, NULL, '1' },
-	{ }
-};
-
-static void
-parse_tos(const char *s, struct ipt_tos_info *info)
-{
-	unsigned int i;
-	unsigned int tos;
-
-	if (string_to_number(s, 0, 255, &tos) != -1) {
-		if (tos == IPTOS_LOWDELAY
-		    || tos == IPTOS_THROUGHPUT
-		    || tos == IPTOS_RELIABILITY
-		    || tos == IPTOS_MINCOST
-		    || tos == IPTOS_NORMALSVC) {
-		    	info->tos = (u_int8_t )tos;
-		    	return;
-		}
-	} else {
-		for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
-			if (strcasecmp(s,TOS_values[i].name) == 0) {
-				info->tos = TOS_values[i].TOS;
-				return;
-			}
-	}
-	exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int tos_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
-{
-	struct ipt_tos_info *tosinfo = (struct ipt_tos_info *)(*match)->data;
-
-	switch (c) {
-	case '1':
-		/* Ensure that `--tos' haven't been used yet. */
-		if (*flags == 1)
-			exit_error(PARAMETER_PROBLEM,
-					"tos match: only use --tos once!");
-
-		check_inverse(optarg, &invert, &optind, 0);
-		parse_tos(argv[optind-1], tosinfo);
-		if (invert)
-			tosinfo->invert = 1;
-		*flags = 1;
-		break;
-
-	default:
-		return 0;
-	}
-	return 1;
-}
-
-static void
-print_tos(u_int8_t tos, int numeric)
-{
-	unsigned int i;
-
-	if (!numeric) {
-		for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
-			if (TOS_values[i].TOS == tos) {
-				printf("%s ", TOS_values[i].name);
-				return;
-			}
-	}
-	printf("0x%02x ", tos);
-}
-
-/* Final check; must have specified --tos. */
-static void tos_check(unsigned int flags)
-{
-	if (!flags)
-		exit_error(PARAMETER_PROBLEM,
-			   "TOS match: You must specify `--tos'");
-}
-
-/* Prints out the matchinfo. */
-static void tos_print(const void *ip, const struct xt_entry_match *match,
-                      int numeric)
-{
-	const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-    
-	printf("TOS match ");
-	if (info->invert)
-		printf("!");
-	print_tos(info->tos, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void tos_save(const void *ip, const struct xt_entry_match *match)
-{
-	const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-    
-	if (info->invert)
-		printf("! ");
-	printf("--tos ");
-	print_tos(info->tos, 0);
-}
-
-static struct iptables_match tos_match = {
-	.name		= "tos",
-	.version	= IPTABLES_VERSION,
-	.size		= IPT_ALIGN(sizeof(struct ipt_tos_info)),
-	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_tos_info)),
-	.help		= tos_help,
-	.parse		= tos_parse,
-	.final_check	= tos_check,
-	.print		= tos_print,
-	.save		= tos_save,
-	.extra_opts	= tos_opts,
-};
-
-void _init(void)
-{
-	register_match(&tos_match);
-}
Index: iptables-modules/extensions/libipt_tos.man
===================================================================
--- iptables-modules.orig/extensions/libipt_tos.man
+++ /dev/null
@@ -1,9 +0,0 @@
-This module matches the 8 bits of Type of Service field in the IP
-header (ie. including the precedence bits).
-.TP
-.BI "--tos " "tos"
-The argument is either a standard name, (use
-.br
- iptables -m tos -h
-.br
-to see the list), or a numeric value to match.
Index: iptables-modules/extensions/libxt_tos.c
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_tos.c
@@ -0,0 +1,192 @@
+/*
+ * Shared library add-on to iptables to add tos match support
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_dscp.h>
+#include <linux/netfilter_ipv4/ipt_tos.h>
+#include "tos_values.c"
+
+enum {
+	FLAG_TOS = 1 << 0,
+};
+
+static const struct option tos_mt_opts[] = {
+	{.name = "tos", .has_arg = true, .val = 't'},
+	{},
+};
+
+static void tos_mt_help(void)
+{
+	const struct tos_symbol_info *symbol;
+
+	printf(
+"tos match options:\n"
+"[!] --tos value[/mask]    Match Type of Service/Priority field value\n"
+"[!] --tos symbol          Match TOS field (IPv4 only) by symbol\n"
+"                          Accepted symbolic names for value are:\n");
+
+	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+		printf("                          (0x%02x) %2u %s\n",
+		       symbol->value, symbol->value, symbol->name);
+
+	printf("\n");
+}
+
+static int tos_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+                           const void *entry, struct xt_entry_match **match)
+{
+	struct ipt_tos_info *info = (void *)(*match)->data;
+	struct tos_value_mask tvm;
+
+	switch (c) {
+	case 't':
+		param_act(P_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
+			param_act(P_BAD_VALUE, "tos", "--tos", optarg);
+		if (tvm.mask != 0xFF)
+			exit_error(PARAMETER_PROBLEM, "tos: Your kernel is "
+			           "too old to support anything besides /0xFF "
+				   "as a mask.");
+		info->tos = tvm.value;
+		if (invert)
+			info->invert = true;
+		*flags |= FLAG_TOS;
+		return true;
+	}
+	return false;
+}
+
+static int tos_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                        const void *entry, struct xt_entry_match **match)
+{
+	struct xt_tos_match_info *info = (void *)(*match)->data;
+	struct tos_value_mask tvm = {.mask = 0xFF};
+
+	switch (c) {
+	case 't':
+		param_act(P_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
+			param_act(P_BAD_VALUE, "tos", "--tos", optarg);
+		info->tos_value = tvm.value;
+		info->tos_mask  = tvm.mask;
+		if (invert)
+			info->invert = true;
+		*flags |= FLAG_TOS;
+		return true;
+	}
+	return false;
+}
+
+static void tos_mt_check(unsigned int flags)
+{
+	if (flags == 0)
+		exit_error(PARAMETER_PROBLEM,
+		           "tos: --tos parameter required");
+}
+
+static void tos_mt_print_v0(const void *ip, const struct xt_entry_match *match,
+                            int numeric)
+{
+	const struct ipt_tos_info *info = (const void *)match->data;
+
+	printf("tos match ");
+	if (info->invert)
+		printf("!");
+	if (numeric || !tos_try_print_symbolic("", info->tos, 0x3F))
+		printf("0x%02x ", info->tos);
+}
+
+static void tos_mt_print(const void *ip, const struct xt_entry_match *match,
+                         int numeric)
+{
+	const struct xt_tos_match_info *info = (const void *)match->data;
+
+	printf("tos match ");
+	if (info->invert)
+		printf("!");
+	if (numeric ||
+	    !tos_try_print_symbolic("", info->tos_value, info->tos_mask))
+		printf("0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static void tos_mt_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+	const struct ipt_tos_info *info = (const void *)match->data;
+
+	if (info->invert)
+		printf("! ");
+	printf("--tos 0x%02x ", info->tos);
+}
+
+static void tos_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+	const struct xt_tos_match_info *info = (const void *)match->data;
+
+	if (info->invert)
+		printf("! ");
+	printf("--tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static struct xtables_match tos_mt_reg_v0 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "tos",
+	.family        = AF_INET,
+	.revision      = 0,
+	.size          = XT_ALIGN(sizeof(struct ipt_tos_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)),
+	.help          = tos_mt_help,
+	.parse         = tos_mt_parse_v0,
+	.final_check   = tos_mt_check,
+	.print         = tos_mt_print_v0,
+	.save          = tos_mt_save_v0,
+	.extra_opts    = tos_mt_opts,
+};
+
+static struct xtables_match tos_mt_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "tos",
+	.family        = AF_INET,
+	.revision      = 1,
+	.size          = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+	.help          = tos_mt_help,
+	.parse         = tos_mt_parse,
+	.final_check   = tos_mt_check,
+	.print         = tos_mt_print,
+	.save          = tos_mt_save,
+	.extra_opts    = tos_mt_opts,
+};
+
+static struct xtables_match tos_mt6_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "tos",
+	.family        = AF_INET6,
+	.revision      = 1,
+	.size          = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+	.help          = tos_mt_help,
+	.parse         = tos_mt_parse,
+	.final_check   = tos_mt_check,
+	.print         = tos_mt_print,
+	.save          = tos_mt_save,
+	.extra_opts    = tos_mt_opts,
+};
+
+void _init(void)
+{
+	xtables_register_match(&tos_mt_reg_v0);
+	xtables_register_match(&tos_mt_reg);
+	xtables_register_match(&tos_mt6_reg);
+}
Index: iptables-modules/extensions/libxt_tos.man
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_tos.man
@@ -0,0 +1,12 @@
+This module matches the 8-bit Type of Service field in the IPv4 header (i.e.
+including the "Precedence" bits) or the (also 8-bit) Priority field in the IPv6
+header.
+.TP
+\fB--tos\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Matches packets with the given TOS mark value. If a mask is specified, it is
+logically ANDed with the TOS mark before the comparison.
+.TP
+\fB--tos\fR \fIsymbol\fR
+You can specify a symbolic name when using the tos match for IPv4. The list of
+recognized TOS names can be obtained by calling iptables with \fB-m tos -h\fR.
+Note that this implies a mask of 0x3F, i.e. all but the ECN bits.
Index: iptables-modules/extensions/tos_values.c
===================================================================
--- /dev/null
+++ iptables-modules/extensions/tos_values.c
@@ -0,0 +1,91 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+struct tos_value_mask {
+	uint8_t value, mask;
+};
+
+static const struct tos_symbol_info {
+	unsigned char value;
+	const char *name;
+} tos_symbol_names[] = {
+	{IPTOS_LOWDELAY,    "Minimize-Delay"},
+	{IPTOS_THROUGHPUT,  "Maximize-Throughput"},
+	{IPTOS_RELIABILITY, "Maximize-Reliability"},
+	{IPTOS_MINCOST,     "Minimize-Cost"},
+	{IPTOS_NORMALSVC,   "Normal-Service"},
+	{},
+};
+
+/*
+ * tos_parse_numeric - parse sth. like "15/255"
+ *
+ * @s:		input string
+ * @info:	accompanying structure
+ * @bits:	number of bits that are allowed
+ *		(8 for IPv4 TOS field, 4 for IPv6 Priority Field)
+ */
+static bool tos_parse_numeric(const char *str, struct tos_value_mask *tvm,
+                              unsigned int bits)
+{
+	const unsigned int max = (1 << bits) - 1;
+	unsigned int value;
+	char *end;
+
+	strtonum(str, &end, &value, 0, max);
+	tvm->value = value;
+	tvm->mask  = max;
+
+	if (*end == '/') {
+		const char *p = end + 1;
+
+		if (!strtonum(p, &end, &value, 0, max))
+			exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
+			           str);
+		tvm->mask = value;
+	}
+
+	if (*end != '\0')
+		exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
+	return true;
+}
+
+static bool tos_parse_symbolic(const char *str, struct tos_value_mask *tvm,
+    unsigned int def_mask)
+{
+	const static unsigned int bits = 8;
+	const unsigned int max = (1 << bits) - 1;
+	const struct tos_symbol_info *symbol;
+
+	if (strtonum(str, NULL, NULL, 0, max))
+		return tos_parse_numeric(str, tvm, max);
+
+	/* Do not consider ECN bits */
+	tvm->mask = def_mask;
+	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+		if (strcasecmp(str, symbol->name) == 0) {
+			tvm->value = symbol->value;
+			return true;
+		}
+
+	exit_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", str);
+	return false;
+}
+
+static bool tos_try_print_symbolic(const char *prefix,
+    u_int8_t value, u_int8_t mask)
+{
+	const struct tos_symbol_info *symbol;
+
+	if (mask != 0x3F)
+		return false;
+
+	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+		if (value == symbol->value) {
+			printf("%s%s ", prefix, symbol->name);
+			return true;
+		}
+
+	return false;
+}
Index: iptables-modules/include/linux/netfilter/xt_dscp.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter/xt_dscp.h
+++ iptables-modules/include/linux/netfilter/xt_dscp.h
@@ -20,4 +20,10 @@ struct xt_dscp_info {
 	u_int8_t invert;
 };
 
+struct xt_tos_match_info {
+	u_int8_t tos_mask;
+	u_int8_t tos_value;
+	u_int8_t invert;
+};
+
 #endif /* _XT_DSCP_H */
-
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] 13+ messages in thread

* [PATCH 6/11] libxt_TOS target revision 1
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (3 preceding siblings ...)
  2007-12-22  2:45 ` [PATCH 5/11] libxt_tos match revision 1 Jan Engelhardt
@ 2007-12-22  2:45 ` Jan Engelhardt
  2007-12-22  2:46 ` [PATCH 7/11] libxt_MARK target revision 2 Jan Engelhardt
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:45 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Moves libipt_TOS revision 0 to libxt_TOS revision 0.
xt_TOS revision 1 support.

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

---
 extensions/Makefile               |    2 
 extensions/libipt_TOS.c           |  159 -----------------------
 extensions/libipt_TOS.man         |   11 -
 extensions/libxt_TOS.c            |  261 ++++++++++++++++++++++++++++++++++++++
 extensions/libxt_TOS.man          |   27 +++
 include/linux/netfilter/xt_DSCP.h |    5 
 6 files changed, 294 insertions(+), 171 deletions(-)

Index: iptables-modules/extensions/Makefile
===================================================================
--- iptables-modules.orig/extensions/Makefile
+++ iptables-modules/extensions/Makefile
@@ -17,7 +17,6 @@ a += REDIRECT
 a += REJECT
 a += SAME
 a += SNAT
-a += TOS
 a += TTL
 a += ULOG
 a += addrtype
@@ -57,6 +56,7 @@ a += NFLOG
 a += NFQUEUE
 a += NOTRACK
 a += TCPMSS
+a += TOS
 a += TRACE
 a += comment
 a += connbytes
Index: iptables-modules/extensions/libipt_TOS.c
===================================================================
--- iptables-modules.orig/extensions/libipt_TOS.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Shared library add-on to iptables to add TOS target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_TOS.h>
-
-struct tosinfo {
-	struct xt_entry_target t;
-	struct ipt_tos_target_info tos;
-};
-
-/* TOS names and values. */
-static const
-struct TOS_value
-{
-	unsigned char TOS;
-	const char *name;
-} TOS_values[] = {
-	{ IPTOS_LOWDELAY,    "Minimize-Delay" },
-	{ IPTOS_THROUGHPUT,  "Maximize-Throughput" },
-	{ IPTOS_RELIABILITY, "Maximize-Reliability" },
-	{ IPTOS_MINCOST,     "Minimize-Cost" },
-	{ IPTOS_NORMALSVC,   "Normal-Service" },
-};
-
-/* Function which prints out usage message. */
-static void TOS_help(void)
-{
-	unsigned int i;
-
-	printf(
-"TOS target v%s options:\n"
-"  --set-tos value                   Set Type of Service field to one of the\n"
-"                                following numeric or descriptive values:\n",
-IPTABLES_VERSION);
-
-	for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
-		printf("                                     %s %u (0x%02x)\n",
-		       TOS_values[i].name,
-                       TOS_values[i].TOS,
-                       TOS_values[i].TOS);
-	fputc('\n', stdout);
-}
-
-static const struct option TOS_opts[] = {
-	{ "set-tos", 1, NULL, '1' },
-	{ }
-};
-
-static void
-parse_tos(const char *s, struct ipt_tos_target_info *info)
-{
-	unsigned int i, tos;
-
-	if (string_to_number(s, 0, 255, &tos) != -1) {
-		if (tos == IPTOS_LOWDELAY
-		    || tos == IPTOS_THROUGHPUT
-		    || tos == IPTOS_RELIABILITY
-		    || tos == IPTOS_MINCOST
-		    || tos == IPTOS_NORMALSVC) {
-		    	info->tos = (u_int8_t )tos;
-		    	return;
-		}
-	} else {
-		for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
-			if (strcasecmp(s,TOS_values[i].name) == 0) {
-				info->tos = TOS_values[i].TOS;
-				return;
-			}
-	}
-	exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int TOS_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_target **target)
-{
-	struct ipt_tos_target_info *tosinfo
-		= (struct ipt_tos_target_info *)(*target)->data;
-
-	switch (c) {
-	case '1':
-		if (*flags)
-			exit_error(PARAMETER_PROBLEM,
-			           "TOS target: Cant specify --set-tos twice");
-		parse_tos(optarg, tosinfo);
-		*flags = 1;
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 1;
-}
-
-static void TOS_check(unsigned int flags)
-{
-	if (!flags)
-		exit_error(PARAMETER_PROBLEM,
-		           "TOS target: Parameter --set-tos is required");
-}
-
-static void
-print_tos(u_int8_t tos, int numeric)
-{
-	unsigned int i;
-
-	if (!numeric) {
-		for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
-			if (TOS_values[i].TOS == tos) {
-				printf("%s ", TOS_values[i].name);
-				return;
-			}
-	}
-	printf("0x%02x ", tos);
-}
-
-/* Prints out the targinfo. */
-static void TOS_print(const void *ip, const struct xt_entry_target *target,
-                      int numeric)
-{
-	const struct ipt_tos_target_info *tosinfo =
-		(const struct ipt_tos_target_info *)target->data;
-	printf("TOS set ");
-	print_tos(tosinfo->tos, numeric);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void TOS_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct ipt_tos_target_info *tosinfo =
-		(const struct ipt_tos_target_info *)target->data;
-
-	printf("--set-tos 0x%02x ", tosinfo->tos);
-}
-
-static struct iptables_target tos_target = {
-	.name		= "TOS",
-	.version	= IPTABLES_VERSION,
-	.size		= IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
-	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
-	.help		= TOS_help,
-	.parse		= TOS_parse,
-	.final_check	= TOS_check,
-	.print		= TOS_print,
-	.save		= TOS_save,
-	.extra_opts	= TOS_opts,
-};
-
-void _init(void)
-{
-	register_target(&tos_target);
-}
Index: iptables-modules/extensions/libipt_TOS.man
===================================================================
--- iptables-modules.orig/extensions/libipt_TOS.man
+++ /dev/null
@@ -1,11 +0,0 @@
-This is used to set the 8-bit Type of Service field in the IP header.
-It is only valid in the
-.B mangle
-table.
-.TP
-.BI "--set-tos " "tos"
-You can use a numeric TOS values, or use
-.nf
- iptables -j TOS -h
-.fi
-to see the list of valid TOS names.
Index: iptables-modules/extensions/libxt_TOS.c
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_TOS.c
@@ -0,0 +1,261 @@
+/*
+ * Shared library add-on to iptables to add TOS target support
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_DSCP.h>
+#include <linux/netfilter_ipv4/ipt_TOS.h>
+#include "tos_values.c"
+
+enum {
+	FLAG_TOS = 1 << 0,
+};
+
+static const struct option tos_tg_opts_v0[] = {
+	{.name = "set-tos", .has_arg = true, .val = '='},
+	{},
+};
+
+static const struct option tos_tg_opts[] = {
+	{.name = "set-tos", .has_arg = true, .val = '='},
+	{.name = "and-tos", .has_arg = true, .val = '&'},
+	{.name = "or-tos",  .has_arg = true, .val = '|'},
+	{.name = "xor-tos", .has_arg = true, .val = '^'},
+	{},
+};
+
+static void tos_tg_help_v0(void)
+{
+	const struct tos_symbol_info *symbol;
+
+	printf(
+"TOS target options:\n"
+"  --set-tos value     Set Type of Service/Priority field to value\n"
+"  --set-tos symbol    Set TOS field (IPv4 only) by symbol\n"
+"                      Accepted symbolic names for value are:\n");
+
+	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+		printf("                        (0x%02x) %2u %s\n",
+		       symbol->value, symbol->value, symbol->name);
+
+	printf("\n");
+}
+
+static void tos_tg_help(void)
+{
+	const struct tos_symbol_info *symbol;
+
+	printf(
+"TOS target v%s options:\n"
+"  --set-tos value[/mask]  Set Type of Service/Priority field to value\n"
+"                          (Zero out bits in mask and XOR value into TOS)\n"
+"  --set-tos symbol        Set TOS field (IPv4 only) by symbol\n"
+"                          (this zeroes the 4-bit Precedence part!)\n"
+"                          Accepted symbolic names for value are:\n",
+IPTABLES_VERSION);
+
+	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+		printf("                            (0x%02x) %2u %s\n",
+		       symbol->value, symbol->value, symbol->name);
+
+	printf(
+"\n"
+"  --and-tos bits          Binary AND the TOS value with bits\n"
+"  --or-tos  bits          Binary OR the TOS value with bits\n"
+"  --xor-tos bits          Binary XOR the TOS value with bits\n"
+);
+}
+
+static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+                           const void *entry, struct xt_entry_target **target)
+{
+	struct ipt_tos_target_info *info = (void *)(*target)->data;
+	struct tos_value_mask tvm;
+
+	switch (c) {
+	case '=':
+		param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		param_act(P_NO_INVERT, "TOS", "--set-tos", invert);
+		if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
+			param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg);
+		if (tvm.mask != 0xFF)
+			exit_error(PARAMETER_PROBLEM, "tos match: Your kernel "
+			           "is too old to support anything besides "
+				   "/0xFF as a mask.");
+		info->tos = tvm.value;
+		*flags |= FLAG_TOS;
+		return true;
+	}
+
+	return false;
+}
+
+static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+                         const void *entry, struct xt_entry_target **target)
+{
+	struct xt_tos_target_info *info = (void *)(*target)->data;
+	struct tos_value_mask tvm;
+	unsigned int bits;
+
+	switch (c) {
+	case '=': /* --set-tos */
+		param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		param_act(P_NO_INVERT, "TOS", "--set-tos", invert);
+		if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
+			param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg);
+		info->tos_value = tvm.value;
+		info->tos_mask  = tvm.mask;
+		break;
+
+	case '&': /* --and-tos */
+		param_act(P_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		param_act(P_NO_INVERT, "TOS", "--and-tos", invert);
+		if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
+			param_act(P_BAD_VALUE, "TOS", "--and-tos", optarg);
+		info->tos_value = 0;
+		info->tos_mask  = ~bits;
+		break;
+
+	case '|': /* --or-tos */
+		param_one_only("TOS", "--or-tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		param_act(P_NO_INVERT, "TOS", "--or-tos", invert);
+		if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
+			param_act(P_BAD_VALUE, "TOS", "--or-tos", optarg);
+		info->tos_value = bits;
+		info->tos_mask  = bits;
+		break;
+
+	case '^': /* --xor-tos */
+		param_act(P_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS);
+		check_inverse(optarg, &invert, &optind, 0);
+		param_act(P_NO_INVERT, "TOS", "--xor-tos", invert);
+		if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
+			param_invalid("TOS", "--xor-tos", optarg);
+		info->tos_value = bits;
+		info->tos_mask  = 0;
+		break;
+
+	default:
+		return false;
+	}
+
+	*flags |= FLAG_TOS;
+	return true;
+}
+
+static void tos_tg_check(unsigned int flags)
+{
+	if (flags == 0)
+		param_act(P_NEED_ACTION, "TOS");
+}
+
+static void tos_tg_print_v0(const void *ip,
+                            const struct xt_entry_target *target, int numeric)
+{
+	const struct ipt_tos_target_info *info = (const void *)target->data;
+
+	printf("TOS set ");
+	if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF))
+		printf("0x%02x ", info->tos);
+}
+
+static void tos_tg_print(const void *ip, const struct xt_entry_target *target,
+                         int numeric)
+{
+	const struct xt_tos_target_info *info = (const void *)target->data;
+
+	if (numeric)
+		printf("TOS set 0x%02x/0x%02x ",
+		       info->tos_value, info->tos_mask);
+	else if (tos_try_print_symbolic("TOS set ",
+	    info->tos_value, info->tos_mask))
+		/* already printed by call */
+		return;
+	else if (info->tos_value == 0)
+		printf("TOS and 0x%02x ",
+		       (unsigned int)(u_int8_t)~info->tos_mask);
+	else if (info->tos_value == info->tos_mask)
+		printf("TOS or 0x%02x ", info->tos_value);
+	else if (info->tos_mask == 0)
+		printf("TOS xor 0x%02x ", info->tos_value);
+	else
+		printf("TOS set 0x%02x/0x%02x ",
+		       info->tos_value, info->tos_mask);
+}
+
+static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target)
+{
+	const struct ipt_tos_target_info *info = (const void *)target->data;
+
+	printf("--set-tos 0x%02x ", info->tos);
+}
+
+static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+	const struct xt_tos_target_info *info = (const void *)target->data;
+
+	printf("--set-tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static struct xtables_target tos_tg_reg_v0 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "TOS",
+	.revision      = 0,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.help          = tos_tg_help_v0,
+	.parse         = tos_tg_parse_v0,
+	.final_check   = tos_tg_check,
+	.print         = tos_tg_print_v0,
+	.save          = tos_tg_save_v0,
+	.extra_opts    = tos_tg_opts_v0,
+};
+
+static struct xtables_target tos_tg_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "TOS",
+	.revision      = 1,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.help          = tos_tg_help,
+	.parse         = tos_tg_parse,
+	.final_check   = tos_tg_check,
+	.print         = tos_tg_print,
+	.save          = tos_tg_save,
+	.extra_opts    = tos_tg_opts,
+};
+
+static struct xtables_target tos_tg6_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "TOS",
+	.family        = AF_INET6,
+	.revision      = 1,
+	.size          = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+	.help          = tos_tg_help,
+	.parse         = tos_tg_parse,
+	.final_check   = tos_tg_check,
+	.print         = tos_tg_print,
+	.save          = tos_tg_save,
+	.extra_opts    = tos_tg_opts,
+};
+
+void _init(void)
+{
+	xtables_register_target(&tos_tg_reg_v0);
+	xtables_register_target(&tos_tg_reg);
+	xtables_register_target(&tos_tg6_reg);
+}
Index: iptables-modules/extensions/libxt_TOS.man
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_TOS.man
@@ -0,0 +1,27 @@
+This module sets the Type of Service field in the IPv4 header (including the
+'precedence' bits) or the Priority field in the IPv6 header. Note that TOS
+shares the same bits as DSCP and ECN. The TOS target is only valid in the
+\fBmangle\fR table.
+.TP
+\fB--set-tos\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the
+TOS/Priority field. If \fImask\fR is omitted, 0xFF is assumed.
+.TP
+\fB--set-tos\fR \fIsymbol\fR
+You can specify a symbolic name when using the TOS target for IPv4. It implies
+a mask of 0xFF. The list of recognized TOS names can be obtained by calling
+iptables with \fB-j TOS -h\fR.
+.PP
+The following mnemonics are available:
+.TP
+\fB--and-tos\fR \fIbits\fR
+Binary AND the TOS value with \fIbits\fR. (Mnemonic for \fB--set-tos
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB--or-tos\fR \fIbits\fR
+Binary OR the TOS value with \fIbits\fR. (Mnemonic for \fB--set-tos\fR
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB--xor-tos\fR \fIbits\fR
+Binary XOR the TOS value with \fIbits\fR. (Mnemonic for \fB--set-tos\fR
+\fIbits\fR\fB/0\fR.)
Index: iptables-modules/include/linux/netfilter/xt_DSCP.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter/xt_DSCP.h
+++ iptables-modules/include/linux/netfilter/xt_DSCP.h
@@ -17,4 +17,9 @@ struct xt_DSCP_info {
 	u_int8_t dscp;
 };
 
+struct xt_tos_target_info {
+	u_int8_t tos_value;
+	u_int8_t tos_mask;
+};
+
 #endif /* _XT_DSCP_TARGET_H */
-
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] 13+ messages in thread

* [PATCH 7/11] libxt_MARK target revision 2
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (4 preceding siblings ...)
  2007-12-22  2:45 ` [PATCH 6/11] libxt_TOS target " Jan Engelhardt
@ 2007-12-22  2:46 ` Jan Engelhardt
  2007-12-22  2:46 ` [PATCH 8/11] libxt_connmark match Jan Engelhardt
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:46 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


libxt_MARK revision 2 support.
Also consolidate libip6t_MARK.man and libipt_MARK.man.

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

---
 extensions/libip6t_MARK.man       |    6 -
 extensions/libipt_MARK.man        |   13 ---
 extensions/libxt_MARK.c           |  158 ++++++++++++++++++++++++++++++++++++++
 extensions/libxt_MARK.man         |   25 ++++++
 include/linux/netfilter/xt_MARK.h |    4 
 5 files changed, 187 insertions(+), 19 deletions(-)

Index: iptables-modules/extensions/libip6t_MARK.man
===================================================================
--- iptables-modules.orig/extensions/libip6t_MARK.man
+++ /dev/null
@@ -1,6 +0,0 @@
-This is used to set the netfilter mark value associated with the
-packet.  It is only valid in the
-.B mangle
-table.
-.TP
-.BI "--set-mark " "mark"
Index: iptables-modules/extensions/libipt_MARK.man
===================================================================
--- iptables-modules.orig/extensions/libipt_MARK.man
+++ /dev/null
@@ -1,13 +0,0 @@
-This is used to set the netfilter mark value associated with the
-packet.  It is only valid in the
-.B mangle
-table.  It can for example be used in conjunction with iproute2.
-.TP
-.BI "--set-mark " "value"
-Set nfmark value
-.TP
-.BI "--and-mark " "value"
-Binary AND the nfmark with value
-.TP
-.BI "--or-mark " "value"
-Binary OR  the nfmark with value
Index: iptables-modules/extensions/libxt_MARK.c
===================================================================
--- iptables-modules.orig/extensions/libxt_MARK.c
+++ iptables-modules/extensions/libxt_MARK.c
@@ -1,4 +1,5 @@
 /* Shared library add-on to iptables to add MARK target support. */
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -8,6 +9,10 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_MARK.h>
 
+enum {
+	F_MARK = 1 << 0,
+};
+
 /* Function which prints out usage message. */
 static void MARK_help(void)
 {
@@ -27,6 +32,27 @@ static const struct option MARK_opts[] =
 	{ }
 };
 
+static const struct option mark_tg_opts[] = {
+	{.name = "set-xmark", .has_arg = true, .val = 'X'},
+	{.name = "set-mark",  .has_arg = true, .val = '='},
+	{.name = "and-mark",  .has_arg = true, .val = '&'},
+	{.name = "or-mark",   .has_arg = true, .val = '|'},
+	{.name = "xor-mark",  .has_arg = true, .val = '^'},
+	{},
+};
+
+static void mark_tg_help(void)
+{
+	printf(
+"MARK target options:\n"
+"  --set-xmark value[/mask]  Clear bits in mask and XOR value into nfmark\n"
+"  --set-mark value[/mask]   Clear bits in mask and OR value into nfmark\n"
+"  --and-mark bits           Binary AND the nfmark with bits\n"
+"  --or-mark bits            Binary OR the nfmark with bits\n"
+"  --xor-mask bits           Binary XOR the nfmark with bits\n"
+"\n");
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -101,6 +127,84 @@ MARK_parse_v1(int c, char **argv, int in
 	return 1;
 }
 
+static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+                         const void *entry, struct xt_entry_target **target)
+{
+	struct xt_mark_target_info_v2 *info = (void *)(*target)->data;
+	unsigned int value, mask = ~0U;
+	char *end;
+
+	switch (c) {
+	case 'X': /* --set-xmark */
+	case '=': /* --set-mark */
+		if (*flags & F_MARK)
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Only one MARK operation allowed\n");
+		if (!bound_strtou(optarg, &end, &value, 0, ~0U))
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Illegal value");
+		if (*end == '/')
+			if (!bound_strtou(end + 1, &end, &mask, 0, ~0U))
+				exit_error(PARAMETER_PROBLEM,
+				           "MARK target: Illegal mask");
+		if (*end != '\0')
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Illegal specifcation");
+		info->mark = value;
+		info->mask = mask;
+
+		if (c == '=')
+			info->mask = value | mask;
+		break;
+
+	case '&': /* --and-mark */
+		if (*flags & F_MARK)
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Only one MARK operation allowed\n");
+		if (!bound_strtou(optarg, &end, &mask, 0, ~0U) || *end != '\0')
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Illegal value");
+		info->mark = 0;
+		info->mask = ~mask;
+		break;
+
+	case '|': /* --or-mark */
+		if (*flags & F_MARK)
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Only one MARK operation allowed\n");
+		if (!bound_strtou(optarg, &end, &value, 0, ~0U) || *end != '\0')
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Illegal value");
+		info->mark = value;
+		info->mask = value;
+		break;
+
+	case '^': /* --xor-mark */
+		if (*flags & F_MARK)
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Only one MARK operation allowed\n");
+		if (!bound_strtou(optarg, &end, &value, 0, ~0U) || *end != '\0')
+			exit_error(PARAMETER_PROBLEM,
+			           "MARK target: Illegal value");
+		info->mark = value;
+		info->mask = 0;
+		break;
+
+	default:
+		return false;
+	}
+
+	*flags |= F_MARK;
+	return true;
+}
+
+static void mark_tg_check(unsigned int flags)
+{
+	if (!(flags & F_MARK))
+		exit_error(PARAMETER_PROBLEM,
+		           "MARK target: a MARK operation is required");
+}
+
 static void
 print_mark(unsigned long mark)
 {
@@ -148,6 +252,21 @@ static void MARK_print_v1(const void *ip
 	print_mark(markinfo->mark);
 }
 
+static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
+                          int numeric)
+{
+	const struct xt_mark_target_info_v2 *info = (const void *)target->data;
+
+	if (info->mark == 0)
+		printf("MARK and 0x%x ", (unsigned int)(u_int32_t)~info->mask);
+	else if (info->mark == info->mask)
+		printf("MARK or 0x%x ", info->mark);
+	else if (info->mask == 0)
+		printf("MARK xor 0x%x ", info->mark);
+	else
+		printf("MARK xset 0x%x/0x%x ", info->mark, info->mask);
+}
+
 /* Saves the union ipt_targinfo in parsable form to stdout. */
 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
 {
@@ -168,6 +287,13 @@ static void MARK_save_v1(const void *ip,
 	print_mark(markinfo->mark);
 }
 
+static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+	const struct xt_mark_target_info_v2 *info = (const void *)target->data;
+
+	printf("--set-xmark 0x%x/0x%x ", info->mark, info->mask);
+}
+
 static struct xtables_target mark_target_v0 = {
 	.family		= AF_INET,
 	.name		= "MARK",
@@ -213,9 +339,41 @@ static struct xtables_target mark_target
 	.extra_opts	= MARK_opts,
 };
 
+static struct xtables_target mark_tg_reg_v2 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "MARK",
+	.revision      = 2,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v2)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v2)),
+	.help          = mark_tg_help,
+	.parse         = mark_tg_parse,
+	.final_check   = mark_tg_check,
+	.print         = mark_tg_print,
+	.save          = mark_tg_save,
+	.extra_opts    = mark_tg_opts,
+};
+
+static struct xtables_target mark_tg6_reg_v2 = {
+	.version       = IPTABLES_VERSION,
+	.name          = "MARK",
+	.revision      = 2,
+	.family        = AF_INET6,
+	.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v2)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v2)),
+	.help          = mark_tg_help,
+	.parse         = mark_tg_parse,
+	.final_check   = mark_tg_check,
+	.print         = mark_tg_print,
+	.save          = mark_tg_save,
+	.extra_opts    = mark_tg_opts,
+};
+
 void _init(void)
 {
 	xtables_register_target(&mark_target_v0);
 	xtables_register_target(&mark_target_v1);
 	xtables_register_target(&mark_target6_v0);
+	xtables_register_target(&mark_tg_reg_v2);
+	xtables_register_target(&mark_tg6_reg_v2);
 }
Index: iptables-modules/extensions/libxt_MARK.man
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_MARK.man
@@ -0,0 +1,25 @@
+This target is used to set the Netfilter mark value associated with the packet.
+The target can only be used in the \fBmangle\fR table. It can, for example, be
+used in conjunction with routing based on fwmark (needs iproute2).
+.TP
+\fB--set-xmark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the packet
+mark ("nfmark"). If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.TP
+\fB--set-mark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Zeroes out the bits given by \fImask\fR and ORs \fIvalue\fR into the packet
+mark. If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.PP
+The following mnemonics are available:
+.TP
+\fB--and-mark\fR \fIbits\fR
+Binary AND the nfmark with \fIbits\fR. (Mnemonic for \fB--set-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB--or-mark\fR \fIbits\fR
+Binary OR the nfmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB--xor-mark\fR \fIbits\fR
+Binary XOR the nfmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/0\fR.)
Index: iptables-modules/include/linux/netfilter/xt_MARK.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter/xt_MARK.h
+++ iptables-modules/include/linux/netfilter/xt_MARK.h
@@ -18,4 +18,8 @@ struct xt_mark_target_info_v1 {
 	u_int8_t mode;
 };
 
+struct xt_mark_target_info_v2 {
+	u_int32_t mark, mask;
+};
+
 #endif /*_XT_MARK_H_target */

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

* [PATCH 8/11] libxt_connmark match
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (5 preceding siblings ...)
  2007-12-22  2:46 ` [PATCH 7/11] libxt_MARK target revision 2 Jan Engelhardt
@ 2007-12-22  2:46 ` Jan Engelhardt
  2007-12-22  2:47 ` [PATCH 9/11] libxt_CONNMARK target revision 1 Jan Engelhardt
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:46 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


xt_connmark revision 1 support.

---
 extensions/libxt_connmark.c           |  122 +++++++++++++++++++++++++++++-----
 extensions/libxt_connmark.man         |    9 --
 include/linux/netfilter/xt_connmark.h |    5 +
 3 files changed, 113 insertions(+), 23 deletions(-)

Index: iptables-modules/extensions/libxt_connmark.c
===================================================================
--- iptables-modules.orig/extensions/libxt_connmark.c
+++ iptables-modules/extensions/libxt_connmark.c
@@ -28,21 +28,54 @@
 #include <xtables.h>
 #include <linux/netfilter/xt_connmark.h>
 
+enum {
+	F_MARK = 1 << 0,
+};
+
 /* Function which prints out usage message. */
 static void connmark_help(void)
 {
 	printf(
 "CONNMARK match v%s options:\n"
-"[!] --mark value[/mask]         Match nfmark value with optional mask\n"
+"[!] --mark value[/mask]    Match ctmark value with optional mask\n"
 "\n",
 IPTABLES_VERSION);
 }
 
 static const struct option connmark_opts[] = {
-	{ "mark", 1, NULL, '1' },
-	{ }
+	{.name = "mark", .has_arg = true, .val = '1'},
+	{},
 };
 
+static int
+connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                  const void *entry, struct xt_entry_match **match)
+{
+	struct xt_connmark_match_info *info = (void *)(*match)->data;
+	unsigned int mark, mask = ~0U;
+	char *end;
+
+	switch (c) {
+	case '1': /* --mark */
+		param_act(P_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
+		if (!strtonum(optarg, &end, &mark, 0, ~0U))
+			param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
+		if (*end == '/')
+			if (!strtonum(end + 1, &end, &mask, 0, ~0U))
+				param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
+		if (*end != '\0')
+			param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
+
+		if (invert)
+			info->invert = true;
+		info->mark = mark;
+		info->mask = mask;
+		*flags    |= F_MARK;
+		return true;
+	}
+	return false;
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -75,21 +108,19 @@ connmark_parse(int c, char **argv, int i
 	return 1;
 }
 
-static void
-print_mark(unsigned long mark, unsigned long mask, int numeric)
+static void print_mark(unsigned int mark, unsigned int mask)
 {
-	if(mask != 0xffffffffUL)
-		printf("0x%lx/0x%lx ", mark, mask);
+	if (mask != 0xffffffffU)
+		printf("0x%x/0x%x ", mark, mask);
 	else
-		printf("0x%lx ", mark);
+		printf("0x%x ", mark);
 }
 
 /* Final check; must have specified --mark. */
 static void connmark_check(unsigned int flags)
 {
-	if (!flags)
-		exit_error(PARAMETER_PROBLEM,
-			   "MARK match: You must specify `--mark'");
+	if (flags == 0)
+		param_act(P_NEED_MATCH, "connmark");
 }
 
 /* Prints out the matchinfo. */
@@ -101,7 +132,18 @@ connmark_print(const void *ip, const str
 	printf("CONNMARK match ");
 	if (info->invert)
 		printf("!");
-	print_mark(info->mark, info->mask, numeric);
+	print_mark(info->mark, info->mask);
+}
+
+static void
+connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+	struct xt_connmark_match_info *info = (void *)match->data;
+
+	printf("connmark match ");
+	if (info->invert)
+		printf("!");
+	print_mark(info->mark, info->mask);
 }
 
 /* Saves the matchinfo in parsable form to stdout. */
@@ -113,12 +155,25 @@ static void connmark_save(const void *ip
 		printf("! ");
 
 	printf("--mark ");
-	print_mark(info->mark, info->mask, 0);
+	print_mark(info->mark, info->mask);
 }
 
-static struct xtables_match connmark_match = {
+static void
+connmark_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+	struct xt_connmark_match_info *info = (void *)match->data;
+
+	if (info->invert)
+		printf("! ");
+
+	printf("--mark ");
+	print_mark(info->mark, info->mask);
+}
+
+static struct xtables_match connmark_mt_reg_v0 = {
 	.family		= AF_INET,
 	.name		= "connmark",
+	.revision	= 0,
 	.version	= IPTABLES_VERSION,
 	.size		= XT_ALIGN(sizeof(struct xt_connmark_info)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_info)),
@@ -130,9 +185,10 @@ static struct xtables_match connmark_mat
 	.extra_opts	= connmark_opts,
 };
 
-static struct xtables_match connmark_match6 = {
+static struct xtables_match connmark_mt6_reg_v0 = {
 	.family		= AF_INET6,
 	.name		= "connmark",
+	.revision	= 0,
 	.version	= IPTABLES_VERSION,
 	.size		= XT_ALIGN(sizeof(struct xt_connmark_info)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_info)),
@@ -144,8 +200,40 @@ static struct xtables_match connmark_mat
 	.extra_opts	= connmark_opts,
 };
 
+static struct xtables_match connmark_mt_reg = {
+	.version	= IPTABLES_VERSION,
+	.name		= "connmark",
+	.revision	= 1,
+	.family		= AF_INET,
+	.size		= XT_ALIGN(sizeof(struct xt_connmark_match_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_match_info)),
+	.help		= connmark_help,
+	.parse		= connmark_mt_parse,
+	.final_check	= connmark_check,
+	.print		= connmark_mt_print,
+	.save		= connmark_mt_save,
+	.extra_opts	= connmark_opts,
+};
+
+static struct xtables_match connmark_mt6_reg = {
+	.version	= IPTABLES_VERSION,
+	.name		= "connmark",
+	.revision	= 1,
+	.family		= AF_INET6,
+	.size		= XT_ALIGN(sizeof(struct xt_connmark_match_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_match_info)),
+	.help		= connmark_help,
+	.parse		= connmark_mt_parse,
+	.final_check	= connmark_check,
+	.print		= connmark_mt_print,
+	.save		= connmark_mt_save,
+	.extra_opts	= connmark_opts,
+};
+
 void _init(void)
 {
-	xtables_register_match(&connmark_match);
-	xtables_register_match(&connmark_match6);
+	xtables_register_match(&connmark_mt_reg_v0);
+	xtables_register_match(&connmark_mt6_reg_v0);
+	xtables_register_match(&connmark_mt_reg);
+	xtables_register_match(&connmark_mt6_reg);
 }
Index: iptables-modules/extensions/libxt_connmark.man
===================================================================
--- iptables-modules.orig/extensions/libxt_connmark.man
+++ iptables-modules/extensions/libxt_connmark.man
@@ -1,9 +1,6 @@
 This module matches the netfilter mark field associated with a connection
-(which can be set using the
-.B CONNMARK
-target below).
+(which can be set using the \fBCONNMARK\fR target below).
 .TP
-.BI "--mark " "value[/mask]"
+\fB--mark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
 Matches packets in connections with the given mark value (if a mask is
-specified, this is logically ANDed with the mark before the
-comparison).
+specified, this is logically ANDed with the mark before the comparison).
Index: iptables-modules/include/linux/netfilter/xt_connmark.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter/xt_connmark.h
+++ iptables-modules/include/linux/netfilter/xt_connmark.h
@@ -15,4 +15,9 @@ struct xt_connmark_info {
 	u_int8_t invert;
 };
 
+struct xt_connmark_match_info {
+	u_int32_t mark, mask;
+	u_int8_t invert;
+};
+
 #endif /*_XT_CONNMARK_H*/

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

* [PATCH 9/11] libxt_CONNMARK target revision 1
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (6 preceding siblings ...)
  2007-12-22  2:46 ` [PATCH 8/11] libxt_connmark match Jan Engelhardt
@ 2007-12-22  2:47 ` Jan Engelhardt
  2007-12-22  2:48 ` [PATCH 10/11] libxt_connmark match revision 0 Jan Engelhardt
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:47 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


xt_CONNMARK revision 1 support.

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

---
 extensions/libxt_CONNMARK.c           |  243 ++++++++++++++++++++++++++++++++--
 extensions/libxt_CONNMARK.man         |   51 +++++--
 include/linux/netfilter/xt_CONNMARK.h |    5 
 3 files changed, 277 insertions(+), 22 deletions(-)

Index: iptables-modules/extensions/libxt_CONNMARK.c
===================================================================
--- iptables-modules.orig/extensions/libxt_CONNMARK.c
+++ iptables-modules/extensions/libxt_CONNMARK.c
@@ -28,12 +28,11 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CONNMARK.h>
 
-#if 0
-struct markinfo {
-	struct xt_entry_target t;
-	struct ipt_connmark_target_info mark;
+enum {
+	F_MARK  = 1 << 0,
+	F_1HALF = 1 << 1,
+	F_2HALF = 1 << 2,
 };
-#endif
 
 /* Function which prints out usage message. */
 static void CONNMARK_help(void)
@@ -55,6 +54,52 @@ static const struct option CONNMARK_opts
 	{ }
 };
 
+static const struct option connmark_tg_opts[] = {
+	{.name = "set-xmark",     .has_arg = true,  .val = '='},
+	{.name = "set-mark",      .has_arg = true,  .val = '-'},
+	{.name = "and-mark",      .has_arg = true,  .val = '&'},
+	{.name = "or-mark",       .has_arg = true,  .val = '|'},
+	{.name = "xor-mark",      .has_arg = true,  .val = '^'},
+	{.name = "save-mark",     .has_arg = false, .val = 'S'},
+	{.name = "restore-mark",  .has_arg = false, .val = 'R'},
+	{.name = "ctmask",        .has_arg = true,  .val = 'c'},
+	{.name = "nfmask",        .has_arg = true,  .val = 'n'},
+	{.name = "mask",          .has_arg = true,  .val = 'm'},
+	{},
+};
+
+static void connmark_tg_help(void)
+{
+	printf(
+"CONNMARK target options:\n"
+"  XOR-based operations:\n"
+"  --set-xmark value[/ctmask]    Zero mask bits and XOR ctmark with value\n"
+"  --save-mark [--ctmask mask] [--nfmask mask]\n"
+"                                Copy ctmark to nfmark using masks\n"
+"  --restore-mark [--ctmask mask] [--nfmask mask]\n"
+"                                Copy nfmark to ctmark using masks\n"
+"  --and-mark bits\n"
+"  --or-mark bits\n"
+"  --xor-mark bits\n"
+"  OR-based operations (deprecated):\n"
+"  --set-mark value[/mask]       Set conntrack mark value\n"
+"  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
+"  --restore-mark [--mask mask]  Restore saved nfmark value\n"
+);
+}
+
+static void connmark_tg_init(struct xt_entry_target *target)
+{
+	struct xt_connmark_target_info_v1 *info = (void *)target->data;
+
+	/*
+	 * Need these defualts for --save-mark/--restore-mark if no
+	 * --ctmark or --nfmask is given.
+	 */
+	info->ctmask = ~0U;
+	info->nfmask = ~0U;
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -112,7 +157,115 @@ CONNMARK_parse(int c, char **argv, int i
 	return 1;
 }
 
-static void CONNMARK_check(unsigned int flags)
+static int connmark_tg_parse(int c, char **argv, int invert,
+                             unsigned int *flags, const void *entry,
+                             struct xt_entry_target **target)
+{
+	struct xt_connmark_target_info_v1 *info = (void *)(*target)->data;
+	unsigned int value, mask = ~0U;
+	char *end;
+
+	switch (c) {
+	case '=': /* --set-xmark */
+	case '-': /* --set-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		if (!strtonum(optarg, &end, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+		if (*end == '/')
+			if (!strtonum(end + 1, &end, &mask, 0, ~0U))
+				param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+		if (*end != '\0')
+			param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+		info->mode   = XT_CONNMARK_SET;
+		info->ctmark = value;
+		info->ctmask = mask;
+		if (c == '-')
+			info->ctmask = value | mask;
+		*flags |= F_MARK;
+		return true;
+
+	case '&': /* --and-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		if (!strtonum(optarg, NULL, &mask, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
+		info->mode   = XT_CONNMARK_SET;
+		info->ctmark = 0;
+		info->ctmask = ~mask;
+		*flags      |= F_MARK;
+		return true;
+
+	case '|': /* --or-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		if (!strtonum(optarg, NULL, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
+		info->mode   = XT_CONNMARK_SET;
+		info->ctmark = value;
+		info->ctmask = value;
+		*flags      |= F_MARK;
+		return true;
+
+	case '^': /* --xor-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		if (!strtonum(optarg, NULL, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
+		info->mode   = XT_CONNMARK_SET;
+		info->ctmark = value;
+		info->ctmask = 0;
+		*flags      |= F_MARK;
+		return true;
+
+	case 'S': /* --save-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		info->mode = XT_CONNMARK_SAVE;
+		*flags |= F_MARK | F_SR_MARK;
+		return true;
+
+	case 'R': /* --restore-mark */
+		param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+		info->mode = XT_CONNMARK_RESTORE;
+		*flags |= F_MARK | F_SR_MARK;
+		return true;
+
+	case 'n': /* --nfmask */
+		if (!(*flags & F_SR_MASK))
+			exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+			           "or --restore-mark is required for "
+			           "--nfmask");
+		if (!strtonum(optarg, NULL, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
+		info->nfmask = value;
+		return true;
+
+	case 'c': /* --ctmask */
+		if (!(*flags & F_SR_MASK))
+			exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+			           "or --restore-mark is required for "
+			           "--ctmask");
+		if (!strtonum(optarg, NULL, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
+		info->ctmask = value;
+		return true;
+
+	case 'm': /* --mask */
+		if (!(*flags & F_SR_MASK))
+			exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+			           "or --restore-mark is required for "
+			           "--mask");
+		if (!strtonum(optarg, NULL, &value, 0, ~0U))
+			param_act(P_BAD_VALUE, "CONNMARK", "--mask", optarg);
+		info->nfmask = info->ctmask = value;
+		return true;
+
+	default:
+		return false;
+		break;
+	}
+
+	*flags |= F_MARK;
+	return true;
+}
+
+static void connmark_tg_check(unsigned int flags)
 {
 	if (!flags)
 		exit_error(PARAMETER_PROBLEM,
@@ -161,6 +314,38 @@ static void CONNMARK_print(const void *i
 	}
 }
 
+static void
+connmark_tg_print(const void *ip, const struct xt_entry_target *target,
+                  int numeric)
+{
+	struct xt_connmark_target_info_v1 *info = (void *)target->data;
+
+	switch (info->mode) {
+	case XT_CONNMARK_SET:
+		if (info->ctmark == 0)
+			printf("CONNMARK and 0x%x ",
+			       (unsigned int)(u_int32_t)~info->ctmask);
+		else if (info->ctmark == info->ctmask)
+			printf("CONNMARK or 0x%x ", info->ctmark);
+		else if (info->ctmask == 0)
+			printf("CONNMARK xor 0x%x ", info->ctmark);
+		else
+			printf("CONNMARK xset 0x%x/0x%x ",
+			       info->ctmark, info->ctmask);
+		break;
+	case XT_CONNMARK_SAVE:
+		printf("CONNMARK nfmask 0x%x -> ctmask ~0x%x ",
+		       info->nfmask, info->ctmask);
+		break;
+	case XT_CONNMARK_RESTORE:
+		printf("CONNMARK ctmask 0x%x -> nfmask ~0x%x ",
+		       info->ctmask, info->nfmask);
+	default:
+		printf("ERROR: UNKNOWN CONNMARK MODE");
+		break;
+	}
+}
+
 /* Saves the target into in parsable form to stdout. */
 static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
 {
@@ -188,15 +373,39 @@ static void CONNMARK_save(const void *ip
 	}
 }
 
+static void
+connmark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+	const struct xt_connmark_target_info_v1 *info = (void *)target->data;
+
+	switch (info->mode) {
+	case XT_CONNMARK_SET:
+		printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
+		break;
+	case XT_CONNMARK_SAVE:
+		printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
+		       info->nfmask, info->ctmask);
+		break;
+	case XT_CONNMARK_RESTORE:
+		printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
+		       info->nfmask, info->ctmask);
+		break;
+	default:
+		printf("ERROR: UNKNOWN CONNMARK MODE");
+		break;
+	}
+}
+
 static struct xtables_target connmark_target = {
 	.family		= AF_INET,
 	.name		= "CONNMARK",
+	.revision	= 0,
 	.version	= IPTABLES_VERSION,
 	.size		= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
 	.help		= CONNMARK_help,
 	.parse		= CONNMARK_parse,
-	.final_check	= CONNMARK_check,
+	.final_check	= connmark_tg_check,
 	.print		= CONNMARK_print,
 	.save		= CONNMARK_save,
 	.extra_opts	= CONNMARK_opts,
@@ -205,19 +414,37 @@ static struct xtables_target connmark_ta
 static struct xtables_target connmark_target6 = {
 	.family		= AF_INET6,
 	.name		= "CONNMARK",
+	.revision	= 0,
 	.version	= IPTABLES_VERSION,
 	.size		= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
 	.help		= CONNMARK_help,
 	.parse		= CONNMARK_parse,
-	.final_check	= CONNMARK_check,
+	.final_check	= connmark_tg_check,
 	.print		= CONNMARK_print,
 	.save		= CONNMARK_save,
 	.extra_opts	= CONNMARK_opts,
 };
 
+static struct xtables_target connmark_tg_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "CONNMARK",
+	.revision      = 1,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_connmark_target_info_v1)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info_v1)),
+	.help          = connmark_tg_help,
+	.init          = connmark_tg_init,
+	.parse         = connmark_tg_parse,
+	.final_check   = connmark_tg_check,
+	.print         = connmark_tg_print,
+	.save          = connmark_tg_save,
+	.extra_opts    = connmark_tg_opts,
+};
+
 void _init(void)
 {
 	xtables_register_target(&connmark_target);
 	xtables_register_target(&connmark_target6);
+	xtables_register_target(&connmark_tg_reg);
 }
Index: iptables-modules/extensions/libxt_CONNMARK.man
===================================================================
--- iptables-modules.orig/extensions/libxt_CONNMARK.man
+++ iptables-modules/extensions/libxt_CONNMARK.man
@@ -1,15 +1,38 @@
-This module sets the netfilter mark value associated with a connection
+This module sets the netfilter mark value associated with a connection.
 .TP
-.B --set-mark mark[/mask]
-Set connection mark. If a mask is specified then only those bits set in the
-mask is modified.
-.TP
-.B --save-mark [--mask mask]
-Copy the netfilter packet mark value to the connection mark. If a mask
-is specified then only those bits are copied.
-.TP
-.B --restore-mark [--mask mask]
-Copy the connection mark value to the packet. If a mask is specified
-then only those bits are copied. This is only valid in the
-.B mangle
-table.
+\fB--set-xmark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Zero out the bits given by \fImask\fR and XOR \fIvalue\fR into the ctmark.
+.TP
+\fB--save-mark\fR [\fB--nfmask\fR \fInfmask\fR] [\fB--ctmask\fR \fIctmask\fR]
+Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
+masks. The new nfmark value is determined as follows:
+.IP
+ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+.TP
+i.e. \fIctmask\fR defines what bits to clear and \fInfmask\fR what bits of the
+nfmark to XOR into the ctmark.
+.TP
+\fB--restore-mark\fR [\fB--nfmask\fR \fInfmask\fR] [\fB--ctmask\fR \fIctmask\fR]
+Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
+masks. The new ctmark value is determined as follows:
+.IP
+nfmark = (nfmark & ~\fInfmask\fR) ^ (ctmark & \fIctmask\fR);
+.TP
+i.e. \fInfmask\fR defines what bits to clear and \fIctmask\fR what bits of the
+ctmark to XOR into the nfmark.
+.TP
+\fB--restore-mark\fR is only valid in the \fBmangle\fR table.
+.PP
+The following mnemonics are available for \fB--set-xmark\fR:
+.TP
+\fB--and-mark\fR \fIbits\fR
+Binary AND the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB--or-mark\fR \fIbits\fR
+Binary OR the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB--xor-mark\fR \fIbits\fR
+Binary XOR the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/0\fR.)
Index: iptables-modules/include/linux/netfilter/xt_CONNMARK.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter/xt_CONNMARK.h
+++ iptables-modules/include/linux/netfilter/xt_CONNMARK.h
@@ -22,4 +22,9 @@ struct xt_connmark_target_info {
 	u_int8_t mode;
 };
 
+struct xt_connmark_target_info_v1 {
+	u_int32_t ctmark, ctmask, nfmask;
+	u_int8_t mode;
+};
+
 #endif /*_XT_CONNMARK_H_target*/

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

* [PATCH 10/11] libxt_connmark match revision 0
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (7 preceding siblings ...)
  2007-12-22  2:47 ` [PATCH 9/11] libxt_CONNMARK target revision 1 Jan Engelhardt
@ 2007-12-22  2:48 ` Jan Engelhardt
  2007-12-22  2:49 ` [PATCH 11/11] libxt_connmark match revision 1 Jan Engelhardt
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:48 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Move libipt_conntrack to xt_conntrack.
Spice up the manpage.
Build with regular kernel headers (not that ipt_conntrack sauce).

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

---
 extensions/Makefile                          |    2 
 extensions/libipt_conntrack.c                |  514 ---------------------------
 extensions/libipt_conntrack.man              |   49 --
 extensions/libxt_conntrack.c                 |  512 ++++++++++++++++++++++++++
 extensions/libxt_conntrack.man               |   48 ++
 include/linux/netfilter/xt_conntrack.h       |   77 ++++
 include/linux/netfilter_ipv4/ipt_conntrack.h |   77 ----
 7 files changed, 638 insertions(+), 641 deletions(-)

Index: iptables-modules/extensions/Makefile
===================================================================
--- iptables-modules.orig/extensions/Makefile
+++ iptables-modules/extensions/Makefile
@@ -21,7 +21,6 @@ a += TTL
 a += ULOG
 a += addrtype
 a += ah
-a += conntrack
 a += ecn
 a += icmp
 a += iprange
@@ -62,6 +61,7 @@ a += comment
 a += connbytes
 a += connlimit
 a += connmark
+a += conntrack
 a += dccp
 a += dscp
 a += esp
Index: iptables-modules/extensions/libipt_conntrack.c
===================================================================
--- iptables-modules.orig/extensions/libipt_conntrack.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/* Shared library add-on to iptables for conntrack matching support.
- * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <iptables.h>
-#include <linux/netfilter/nf_conntrack_common.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_conntrack.h"
-
-#ifndef IPT_CONNTRACK_STATE_UNTRACKED
-#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
-#endif
-
-/* Function which prints out usage message. */
-static void conntrack_help(void)
-{
-	printf(
-"conntrack match v%s options:\n"
-" [!] --ctstate [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT][,...]\n"
-"				State(s) to match\n"
-" [!] --ctproto	proto		Protocol to match; by number or name, eg. `tcp'\n"
-"     --ctorigsrc  [!] address[/mask]\n"
-"				Original source specification\n"
-"     --ctorigdst  [!] address[/mask]\n"
-"				Original destination specification\n"
-"     --ctreplsrc  [!] address[/mask]\n"
-"				Reply source specification\n"
-"     --ctrepldst  [!] address[/mask]\n"
-"				Reply destination specification\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"
-"\n", IPTABLES_VERSION);
-}
-
-static const struct option conntrack_opts[] = {
-	{ "ctstate", 1, NULL, '1' },
-	{ "ctproto", 1, NULL, '2' },
-	{ "ctorigsrc", 1, NULL, '3' },
-	{ "ctorigdst", 1, NULL, '4' },
-	{ "ctreplsrc", 1, NULL, '5' },
-	{ "ctrepldst", 1, NULL, '6' },
-	{ "ctstatus", 1, NULL, '7' },
-	{ "ctexpire", 1, NULL, '8' },
-	{ }
-};
-
-static int
-parse_state(const char *state, size_t strlen, struct ipt_conntrack_info *sinfo)
-{
-	if (strncasecmp(state, "INVALID", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_INVALID;
-	else if (strncasecmp(state, "NEW", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_NEW);
-	else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
-	else if (strncasecmp(state, "RELATED", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
-	else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_UNTRACKED;
-	else if (strncasecmp(state, "SNAT", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_SNAT;
-	else if (strncasecmp(state, "DNAT", strlen) == 0)
-		sinfo->statemask |= IPT_CONNTRACK_STATE_DNAT;
-	else
-		return 0;
-	return 1;
-}
-
-static void
-parse_states(const char *arg, struct ipt_conntrack_info *sinfo)
-{
-	const char *comma;
-
-	while ((comma = strchr(arg, ',')) != NULL) {
-		if (comma == arg || !parse_state(arg, comma-arg, sinfo))
-			exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
-		arg = comma+1;
-	}
-
-	if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
-		exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
-}
-
-static int
-parse_status(const char *status, size_t strlen, struct ipt_conntrack_info *sinfo)
-{
-	if (strncasecmp(status, "NONE", strlen) == 0)
-		sinfo->statusmask |= 0;
-	else if (strncasecmp(status, "EXPECTED", strlen) == 0)
-		sinfo->statusmask |= IPS_EXPECTED;
-	else if (strncasecmp(status, "SEEN_REPLY", strlen) == 0)
-		sinfo->statusmask |= IPS_SEEN_REPLY;
-	else if (strncasecmp(status, "ASSURED", strlen) == 0)
-		sinfo->statusmask |= IPS_ASSURED;
-#ifdef IPS_CONFIRMED
-	else if (strncasecmp(status, "CONFIRMED", strlen) == 0)
-		sinfo->stausmask |= IPS_CONFIRMED;
-#endif
-	else
-		return 0;
-	return 1;
-}
-
-static void
-parse_statuses(const char *arg, struct ipt_conntrack_info *sinfo)
-{
-	const char *comma;
-
-	while ((comma = strchr(arg, ',')) != NULL) {
-		if (comma == arg || !parse_status(arg, comma-arg, sinfo))
-			exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
-		arg = comma+1;
-	}
-
-	if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
-		exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
-}
-
-static unsigned long
-parse_expire(const char *s)
-{
-	unsigned int len;
-	
-	if (string_to_number(s, 0, 0, &len) == -1)
-		exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", s);
-	else
-		return len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_expires(const char *s, struct ipt_conntrack_info *sinfo)
-{
-	char *buffer;
-	char *cp;
-
-	buffer = strdup(s);
-	if ((cp = strchr(buffer, ':')) == NULL)
-		sinfo->expires_min = sinfo->expires_max = parse_expire(buffer);
-	else {
-		*cp = '\0';
-		cp++;
-
-		sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
-		sinfo->expires_max = cp[0] ? parse_expire(cp) : -1;
-	}
-	free(buffer);
-	
-	if (sinfo->expires_min > sinfo->expires_max)
-		exit_error(PARAMETER_PROBLEM,
-		           "expire min. range value `%lu' greater than max. "
-		           "range value `%lu'", sinfo->expires_min, sinfo->expires_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,
-                           const void *entry, struct xt_entry_match **match)
-{
-	struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)(*match)->data;
-	char *protocol = NULL;
-	unsigned int naddrs = 0;
-	struct in_addr *addrs = NULL;
-
-
-	switch (c) {
-	case '1':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		parse_states(argv[optind-1], sinfo);
-		if (invert) {
-			sinfo->invflags |= IPT_CONNTRACK_STATE;
-		}
-		sinfo->flags |= IPT_CONNTRACK_STATE;
-		break;
-
-	case '2':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		if(invert)
-			sinfo->invflags |= IPT_CONNTRACK_PROTO;
-
-		/* Canonicalize into lower case */
-		for (protocol = argv[optind-1]; *protocol; protocol++)
-			*protocol = tolower(*protocol);
-
-		protocol = argv[optind-1];
-		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);
-
-		if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
-		    && (sinfo->invflags & IPT_INV_PROTO))
-			exit_error(PARAMETER_PROBLEM,
-				   "rule would never match protocol");
-
-		sinfo->flags |= IPT_CONNTRACK_PROTO;
-		break;
-
-	case '3':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		if (invert)
-			sinfo->invflags |= IPT_CONNTRACK_ORIGSRC;
-
-		parse_hostnetworkmask(argv[optind-1], &addrs,
-					&sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
-					&naddrs);
-		if(naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
-		}
-
-		sinfo->flags |= IPT_CONNTRACK_ORIGSRC;
-		break;
-
-	case '4':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		if (invert)
-			sinfo->invflags |= IPT_CONNTRACK_ORIGDST;
-
-		parse_hostnetworkmask(argv[optind-1], &addrs,
-					&sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
-					&naddrs);
-		if(naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
-		}
-
-		sinfo->flags |= IPT_CONNTRACK_ORIGDST;
-		break;
-
-	case '5':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		if (invert)
-			sinfo->invflags |= IPT_CONNTRACK_REPLSRC;
-
-		parse_hostnetworkmask(argv[optind-1], &addrs,
-					&sinfo->sipmsk[IP_CT_DIR_REPLY],
-					&naddrs);
-		if(naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
-		}
-
-		sinfo->flags |= IPT_CONNTRACK_REPLSRC;
-		break;
-
-	case '6':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		if (invert)
-			sinfo->invflags |= IPT_CONNTRACK_REPLDST;
-
-		parse_hostnetworkmask(argv[optind-1], &addrs,
-					&sinfo->dipmsk[IP_CT_DIR_REPLY],
-					&naddrs);
-		if(naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
-		}
-
-		sinfo->flags |= IPT_CONNTRACK_REPLDST;
-		break;
-
-	case '7':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		parse_statuses(argv[optind-1], sinfo);
-		if (invert) {
-			sinfo->invflags |= IPT_CONNTRACK_STATUS;
-		}
-		sinfo->flags |= IPT_CONNTRACK_STATUS;
-		break;
-
-	case '8':
-		check_inverse(optarg, &invert, &optind, 0);
-
-		parse_expires(argv[optind-1], sinfo);
-		if (invert) {
-			sinfo->invflags |= IPT_CONNTRACK_EXPIRES;
-		}
-		sinfo->flags |= IPT_CONNTRACK_EXPIRES;
-		break;
-
-	default:
-		return 0;
-	}
-
-	*flags = sinfo->flags;
-	return 1;
-}
-
-static void conntrack_check(unsigned int flags)
-{
-	if (!flags)
-		exit_error(PARAMETER_PROBLEM, "You must specify one or more options");
-}
-
-static void
-print_state(unsigned int statemask)
-{
-	const char *sep = "";
-
-	if (statemask & IPT_CONNTRACK_STATE_INVALID) {
-		printf("%sINVALID", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
-		printf("%sNEW", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
-		printf("%sRELATED", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
-		printf("%sESTABLISHED", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_UNTRACKED) {
-		printf("%sUNTRACKED", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_SNAT) {
-		printf("%sSNAT", sep);
-		sep = ",";
-	}
-	if (statemask & IPT_CONNTRACK_STATE_DNAT) {
-		printf("%sDNAT", sep);
-		sep = ",";
-	}
-	printf(" ");
-}
-
-static void
-print_status(unsigned int statusmask)
-{
-	const char *sep = "";
-
-	if (statusmask & IPS_EXPECTED) {
-		printf("%sEXPECTED", sep);
-		sep = ",";
-	}
-	if (statusmask & IPS_SEEN_REPLY) {
-		printf("%sSEEN_REPLY", sep);
-		sep = ",";
-	}
-	if (statusmask & IPS_ASSURED) {
-		printf("%sASSURED", sep);
-		sep = ",";
-	}
-#ifdef IPS_CONFIRMED
-	if (statusmask & IPS_CONFIRMED) {
-		printf("%sCONFIRMED", sep);
-		sep =",";
-	}
-#endif
-	if (statusmask == 0) {
-		printf("%sNONE", sep);
-		sep = ",";
-	}
-	printf(" ");
-}
-
-static void
-print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
-{
-	char buf[BUFSIZ];
-
-        if (inv) 
-               	printf("! ");
-
-	if (mask->s_addr == 0L && !numeric)
-		printf("%s ", "anywhere");
-	else {
-		if (numeric)
-			sprintf(buf, "%s", addr_to_dotted(addr));
-		else
-			sprintf(buf, "%s", addr_to_anyname(addr));
-		strcat(buf, mask_to_dotted(mask));
-		printf("%s ", buf);
-	}
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void
-matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, const char *optpfx)
-{
-	struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)match->data;
-
-	if(sinfo->flags & IPT_CONNTRACK_STATE) {
-		printf("%sctstate ", optpfx);
-        	if (sinfo->invflags & IPT_CONNTRACK_STATE)
-                	printf("! ");
-		print_state(sinfo->statemask);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_PROTO) {
-		printf("%sctproto ", optpfx);
-        	if (sinfo->invflags & IPT_CONNTRACK_PROTO)
-                	printf("! ");
-		printf("%u ", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
-		printf("%sctorigsrc ", optpfx);
-
-		print_addr(
-		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
-		    &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
-		    sinfo->invflags & IPT_CONNTRACK_ORIGSRC,
-		    numeric);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
-		printf("%sctorigdst ", optpfx);
-
-		print_addr(
-		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
-		    &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
-		    sinfo->invflags & IPT_CONNTRACK_ORIGDST,
-		    numeric);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
-		printf("%sctreplsrc ", optpfx);
-
-		print_addr(
-		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
-		    &sinfo->sipmsk[IP_CT_DIR_REPLY],
-		    sinfo->invflags & IPT_CONNTRACK_REPLSRC,
-		    numeric);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
-		printf("%sctrepldst ", optpfx);
-
-		print_addr(
-		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
-		    &sinfo->dipmsk[IP_CT_DIR_REPLY],
-		    sinfo->invflags & IPT_CONNTRACK_REPLDST,
-		    numeric);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_STATUS) {
-		printf("%sctstatus ", optpfx);
-        	if (sinfo->invflags & IPT_CONNTRACK_STATUS)
-                	printf("! ");
-		print_status(sinfo->statusmask);
-	}
-
-	if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
-		printf("%sctexpire ", optpfx);
-        	if (sinfo->invflags & IPT_CONNTRACK_EXPIRES)
-                	printf("! ");
-
-        	if (sinfo->expires_max == sinfo->expires_min)
-                	printf("%lu ", sinfo->expires_min);
-        	else
-                	printf("%lu:%lu ", sinfo->expires_min, sinfo->expires_max);
-	}
-}
-
-/* Prints out the matchinfo. */
-static void conntrack_print(const void *ip, const struct xt_entry_match *match,
-                            int numeric)
-{
-	matchinfo_print(ip, match, 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 struct iptables_match conntrack_match = {
-	.name		= "conntrack",
-	.version	= IPTABLES_VERSION,
-	.size		= IPT_ALIGN(sizeof(struct ipt_conntrack_info)),
-	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_conntrack_info)),
-	.help		= conntrack_help,
-	.parse		= conntrack_parse,
-	.final_check	= conntrack_check,
-	.print		= conntrack_print,
-	.save		= conntrack_save,
-	.extra_opts	= conntrack_opts,
-};
-
-void _init(void)
-{
-	register_match(&conntrack_match);
-}
Index: iptables-modules/extensions/libipt_conntrack.man
===================================================================
--- iptables-modules.orig/extensions/libipt_conntrack.man
+++ /dev/null
@@ -1,49 +0,0 @@
-This module, when combined with connection tracking, allows access to
-more connection tracking information than the "state" match.
-(this module is present only if iptables was compiled under a kernel
-supporting this feature)
-.TP
-.BI "--ctstate " "state"
-Where state is a comma separated list of the connection states to
-match.  Possible states are
-.B INVALID
-meaning that the packet is associated with no known connection,
-.B ESTABLISHED
-meaning that the packet is associated with a connection which has seen
-packets in both directions,
-.B NEW
-meaning that the packet has started a new connection, or otherwise
-associated with a connection which has not seen packets in both
-directions, and
-.B RELATED
-meaning that the packet is starting a new connection, but is
-associated with an existing connection, such as an FTP data transfer,
-or an ICMP error.
-.B SNAT
-A virtual state, matching if the original source address differs from
-the reply destination.
-.B DNAT
-A virtual state, matching if the original destination differs from the
-reply source.
-.TP
-.BI "--ctproto " "proto"
-Protocol to match (by number or name)
-.TP
-.BI "--ctorigsrc " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against original source address
-.TP
-.BI "--ctorigdst " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against original destination address
-.TP
-.BI "--ctreplsrc " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against reply source address
-.TP
-.BI "--ctrepldst " "[!] \fIaddress\fB[/\fImask\fP]"
-Match against reply destination address
-.TP
-.BI "--ctstatus " "[\fINONE|EXPECTED|SEEN_REPLY|ASSURED\fP][,...]"
-Match against internal conntrack states
-.TP
-.BI "--ctexpire " "\fItime\fP[\fI:time\fP]"
-Match remaining lifetime in seconds against given value
-or range of values (inclusive)
Index: iptables-modules/extensions/libxt_conntrack.c
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_conntrack.c
@@ -0,0 +1,512 @@
+/* Shared library add-on to iptables for conntrack matching support.
+ * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+ */
+
+#include <ctype.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iptables.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/xt_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+
+/* Function which prints out usage message. */
+static void conntrack_mt_help(void)
+{
+	printf(
+"conntrack match v%s options:\n"
+"[!] --ctstate [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT][,...]\n"
+"				State(s) to match\n"
+"[!] --ctproto proto		Protocol to match; by number or name, e.g. \"tcp\"\n"
+"[!] --ctorigsrc address[/mask]\n"
+"				Original source specification\n"
+"[!] --ctorigdst address[/mask]\n"
+"				Original destination specification\n"
+"[!] --ctreplsrc address[/mask]\n"
+"				Reply source specification\n"
+"[!] --ctrepldst address[/mask]\n"
+"				Reply destination specification\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"
+"\n", IPTABLES_VERSION);
+}
+
+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'},
+	{},
+};
+
+static int
+parse_state(const char *state, size_t strlen, struct xt_conntrack_info *sinfo)
+{
+	if (strncasecmp(state, "INVALID", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_INVALID;
+	else if (strncasecmp(state, "NEW", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+	else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+	else if (strncasecmp(state, "RELATED", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+	else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_UNTRACKED;
+	else if (strncasecmp(state, "SNAT", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_SNAT;
+	else if (strncasecmp(state, "DNAT", strlen) == 0)
+		sinfo->statemask |= XT_CONNTRACK_STATE_DNAT;
+	else
+		return 0;
+	return 1;
+}
+
+static void
+parse_states(const char *arg, struct xt_conntrack_info *sinfo)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !parse_state(arg, comma-arg, sinfo))
+			exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
+		arg = comma+1;
+	}
+
+	if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
+}
+
+static int
+parse_status(const char *status, size_t strlen, struct xt_conntrack_info *sinfo)
+{
+	if (strncasecmp(status, "NONE", strlen) == 0)
+		sinfo->statusmask |= 0;
+	else if (strncasecmp(status, "EXPECTED", strlen) == 0)
+		sinfo->statusmask |= IPS_EXPECTED;
+	else if (strncasecmp(status, "SEEN_REPLY", strlen) == 0)
+		sinfo->statusmask |= IPS_SEEN_REPLY;
+	else if (strncasecmp(status, "ASSURED", strlen) == 0)
+		sinfo->statusmask |= IPS_ASSURED;
+#ifdef IPS_CONFIRMED
+	else if (strncasecmp(status, "CONFIRMED", strlen) == 0)
+		sinfo->stausmask |= IPS_CONFIRMED;
+#endif
+	else
+		return 0;
+	return 1;
+}
+
+static void
+parse_statuses(const char *arg, struct xt_conntrack_info *sinfo)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !parse_status(arg, comma-arg, sinfo))
+			exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
+		arg = comma+1;
+	}
+
+	if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
+}
+
+static unsigned long
+parse_expire(const char *s)
+{
+	unsigned int len;
+
+	if (string_to_number(s, 0, 0, &len) == -1)
+		exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", s);
+	else
+		return len;
+}
+
+/* If a single value is provided, min and max are both set to the value */
+static void
+parse_expires(const char *s, struct xt_conntrack_info *sinfo)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(s);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		sinfo->expires_min = sinfo->expires_max = parse_expire(buffer);
+	else {
+		*cp = '\0';
+		cp++;
+
+		sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
+		sinfo->expires_max = cp[0] ? parse_expire(cp) : -1;
+	}
+	free(buffer);
+
+	if (sinfo->expires_min > sinfo->expires_max)
+		exit_error(PARAMETER_PROBLEM,
+		           "expire min. range value `%lu' greater than max. "
+		           "range value `%lu'", sinfo->expires_min, sinfo->expires_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,
+                           const void *entry, struct xt_entry_match **match)
+{
+	struct xt_conntrack_info *sinfo = (void *)(*match)->data;
+	char *protocol = NULL;
+	unsigned int naddrs = 0;
+	struct in_addr *addrs = NULL;
+
+
+	switch (c) {
+	case '1':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_states(argv[optind-1], sinfo);
+		if (invert) {
+			sinfo->invflags |= XT_CONNTRACK_STATE;
+		}
+		sinfo->flags |= XT_CONNTRACK_STATE;
+		break;
+
+	case '2':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if(invert)
+			sinfo->invflags |= XT_CONNTRACK_PROTO;
+
+		/* Canonicalize into lower case */
+		for (protocol = argv[optind-1]; *protocol; protocol++)
+			*protocol = tolower(*protocol);
+
+		protocol = argv[optind-1];
+		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);
+
+		if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
+		    && (sinfo->invflags & XT_INV_PROTO))
+			exit_error(PARAMETER_PROBLEM,
+				   "rule would never match protocol");
+
+		sinfo->flags |= XT_CONNTRACK_PROTO;
+		break;
+
+	case '3':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if (invert)
+			sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
+
+		parse_hostnetworkmask(argv[optind-1], &addrs,
+					&sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
+					&naddrs);
+		if(naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+				"multiple IP addresses not allowed");
+
+		if(naddrs == 1) {
+			sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
+		}
+
+		sinfo->flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+
+	case '4':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if (invert)
+			sinfo->invflags |= XT_CONNTRACK_ORIGDST;
+
+		parse_hostnetworkmask(argv[optind-1], &addrs,
+					&sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
+					&naddrs);
+		if(naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+				"multiple IP addresses not allowed");
+
+		if(naddrs == 1) {
+			sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
+		}
+
+		sinfo->flags |= XT_CONNTRACK_ORIGDST;
+		break;
+
+	case '5':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if (invert)
+			sinfo->invflags |= XT_CONNTRACK_REPLSRC;
+
+		parse_hostnetworkmask(argv[optind-1], &addrs,
+					&sinfo->sipmsk[IP_CT_DIR_REPLY],
+					&naddrs);
+		if(naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+				"multiple IP addresses not allowed");
+
+		if(naddrs == 1) {
+			sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
+		}
+
+		sinfo->flags |= XT_CONNTRACK_REPLSRC;
+		break;
+
+	case '6':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if (invert)
+			sinfo->invflags |= XT_CONNTRACK_REPLDST;
+
+		parse_hostnetworkmask(argv[optind-1], &addrs,
+					&sinfo->dipmsk[IP_CT_DIR_REPLY],
+					&naddrs);
+		if(naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+				"multiple IP addresses not allowed");
+
+		if(naddrs == 1) {
+			sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
+		}
+
+		sinfo->flags |= XT_CONNTRACK_REPLDST;
+		break;
+
+	case '7':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_statuses(argv[optind-1], sinfo);
+		if (invert) {
+			sinfo->invflags |= XT_CONNTRACK_STATUS;
+		}
+		sinfo->flags |= XT_CONNTRACK_STATUS;
+		break;
+
+	case '8':
+		check_inverse(optarg, &invert, &optind, 0);
+
+		parse_expires(argv[optind-1], sinfo);
+		if (invert) {
+			sinfo->invflags |= XT_CONNTRACK_EXPIRES;
+		}
+		sinfo->flags |= XT_CONNTRACK_EXPIRES;
+		break;
+
+	default:
+		return 0;
+	}
+
+	*flags = sinfo->flags;
+	return 1;
+}
+
+static void conntrack_mt_check(unsigned int flags)
+{
+	if (flags == 0)
+		exit_error(PARAMETER_PROBLEM, "You must specify one or more options");
+}
+
+static void
+print_state(unsigned int statemask)
+{
+	const char *sep = "";
+
+	if (statemask & XT_CONNTRACK_STATE_INVALID) {
+		printf("%sINVALID", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
+		printf("%sNEW", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
+		printf("%sRELATED", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
+		printf("%sESTABLISHED", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
+		printf("%sUNTRACKED", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_SNAT) {
+		printf("%sSNAT", sep);
+		sep = ",";
+	}
+	if (statemask & XT_CONNTRACK_STATE_DNAT) {
+		printf("%sDNAT", sep);
+		sep = ",";
+	}
+	printf(" ");
+}
+
+static void
+print_status(unsigned int statusmask)
+{
+	const char *sep = "";
+
+	if (statusmask & IPS_EXPECTED) {
+		printf("%sEXPECTED", sep);
+		sep = ",";
+	}
+	if (statusmask & IPS_SEEN_REPLY) {
+		printf("%sSEEN_REPLY", sep);
+		sep = ",";
+	}
+	if (statusmask & IPS_ASSURED) {
+		printf("%sASSURED", sep);
+		sep = ",";
+	}
+#ifdef IPS_CONFIRMED
+	if (statusmask & IPS_CONFIRMED) {
+		printf("%sCONFIRMED", sep);
+		sep =",";
+	}
+#endif
+	if (statusmask == 0) {
+		printf("%sNONE", sep);
+		sep = ",";
+	}
+	printf(" ");
+}
+
+static void
+print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
+{
+	char buf[BUFSIZ];
+
+        if (inv)
+               	printf("! ");
+
+	if (mask->s_addr == 0L && !numeric)
+		printf("%s ", "anywhere");
+	else {
+		if (numeric)
+			sprintf(buf, "%s", addr_to_dotted(addr));
+		else
+			sprintf(buf, "%s", addr_to_anyname(addr));
+		strcat(buf, mask_to_dotted(mask));
+		printf("%s ", buf);
+	}
+}
+
+/* Saves the matchinfo in parsable form to stdout. */
+static void
+matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, const char *optpfx)
+{
+	struct xt_conntrack_info *sinfo = (void *)match->data;
+
+	if(sinfo->flags & XT_CONNTRACK_STATE) {
+        	if (sinfo->invflags & XT_CONNTRACK_STATE)
+                	printf("! ");
+		printf("%sctstate ", optpfx);
+		print_state(sinfo->statemask);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_PROTO) {
+        	if (sinfo->invflags & XT_CONNTRACK_PROTO)
+                	printf("! ");
+		printf("%sctproto ", optpfx);
+		printf("%u ", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
+		printf("%sctorigsrc ", optpfx);
+
+		print_addr(
+		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
+		    &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
+		    sinfo->invflags & XT_CONNTRACK_ORIGSRC,
+		    numeric);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
+		printf("%sctorigdst ", optpfx);
+
+		print_addr(
+		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
+		    &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
+		    sinfo->invflags & XT_CONNTRACK_ORIGDST,
+		    numeric);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
+		printf("%sctreplsrc ", optpfx);
+
+		print_addr(
+		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
+		    &sinfo->sipmsk[IP_CT_DIR_REPLY],
+		    sinfo->invflags & XT_CONNTRACK_REPLSRC,
+		    numeric);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_REPLDST) {
+		printf("%sctrepldst ", optpfx);
+
+		print_addr(
+		    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
+		    &sinfo->dipmsk[IP_CT_DIR_REPLY],
+		    sinfo->invflags & XT_CONNTRACK_REPLDST,
+		    numeric);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_STATUS) {
+        	if (sinfo->invflags & XT_CONNTRACK_STATUS)
+                	printf("! ");
+		printf("%sctstatus ", optpfx);
+		print_status(sinfo->statusmask);
+	}
+
+	if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
+        	if (sinfo->invflags & XT_CONNTRACK_EXPIRES)
+                	printf("! ");
+		printf("%sctexpire ", optpfx);
+
+        	if (sinfo->expires_max == sinfo->expires_min)
+                	printf("%lu ", sinfo->expires_min);
+        	else
+                	printf("%lu:%lu ", sinfo->expires_min, sinfo->expires_max);
+	}
+}
+
+/* Prints out the matchinfo. */
+static void conntrack_print(const void *ip, const struct xt_entry_match *match,
+                            int numeric)
+{
+	matchinfo_print(ip, match, 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 struct xtables_match conntrack_match = {
+	.version       = IPTABLES_VERSION,
+	.name          = "conntrack",
+	.revision      = 0,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_conntrack_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
+	.help          = conntrack_mt_help,
+	.parse         = conntrack_parse,
+	.final_check   = conntrack_mt_check,
+	.print         = conntrack_print,
+	.save          = conntrack_save,
+	.extra_opts    = conntrack_mt_opts,
+};
+
+void _init(void)
+{
+	xtables_register_match(&conntrack_match);
+}
Index: iptables-modules/extensions/libxt_conntrack.man
===================================================================
--- /dev/null
+++ iptables-modules/extensions/libxt_conntrack.man
@@ -0,0 +1,48 @@
+This module, when combined with connection tracking, allows access to the
+connection tracking state for this packet/connection.
+.TP
+\fB--ctstate\fR \fIstate\fR
+Where \fIstate\fR is a comma separated list of the connection states to match.
+Possible states are listed below.
+.TP
+\fB--ctproto\fR \fIl4proto\fR
+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
+.TP
+\fB--ctstatus\fR [\fINONE\fR|\fIEXPECTED\fR|\fISEEN_REPLY\fR|\fIASSURED\fR][\fB,\fR...]
+Match against internal conntrack states
+.TP
+\fB--ctexpire\fR \fItime\fR[\fB:\fR\fItime\fR]
+Match remaining lifetime in seconds against given value or range of values
+(inclusive)
+.PP
+States for \fB--ctstate\fR:
+.TP
+\fBINVALID\fR
+meaning that the packet is associated with no known connection
+\fBNEW\fR
+meaning that the packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions, and
+\fBESTABLISHED\fR
+meaning that the packet is associated with a connection which has seen packets
+in both directions,
+\fBRELATED\fR
+meaning that the packet is starting a new connection, but is associated with an
+existing connection, such as an FTP data transfer, or an ICMP error.
+\fBSNAT\fR
+A virtual state, matching if the original source address differs from the reply
+destination.
+\fBDNAT\fR
+A virtual state, matching if the original destination differs from the reply
+source.
Index: iptables-modules/include/linux/netfilter/xt_conntrack.h
===================================================================
--- /dev/null
+++ iptables-modules/include/linux/netfilter/xt_conntrack.h
@@ -0,0 +1,77 @@
+/* Header file for kernel module to match connection tracking information.
+ * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+ */
+
+#ifndef _XT_CONNTRACK_H
+#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)
+
+#define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
+#define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
+#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
+
+/* This is exposed to userspace, so remains frozen in time. */
+struct ip_conntrack_old_tuple
+{
+	struct {
+		__be32 ip;
+		union {
+			__u16 all;
+		} u;
+	} src;
+
+	struct {
+		__be32 ip;
+		union {
+			__u16 all;
+		} u;
+
+		/* The protocol. */
+		__u16 protonum;
+	} dst;
+};
+
+struct xt_conntrack_info
+{
+	unsigned int statemask, statusmask;
+
+	struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
+	struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
+
+	unsigned long expires_min, expires_max;
+
+	/* Flags word */
+	u_int8_t flags;
+	/* Inverse flags */
+	u_int8_t invflags;
+};
+
+struct xt_conntrack_match_info {
+	union nf_inet_addr origsrc_addr, origsrc_mask;
+	union nf_inet_addr origdst_addr, origdst_mask;
+	union nf_inet_addr replsrc_addr, replsrc_mask;
+	union nf_inet_addr repldst_addr, repldst_mask;
+	u_int32_t expires_min, expires_max;
+	u_int16_t l4proto;
+	u_int8_t state_mask, status_mask;
+	u_int8_t match_flags, invert_flags;
+};
+
+#endif /*_XT_CONNTRACK_H*/
Index: iptables-modules/include/linux/netfilter_ipv4/ipt_conntrack.h
===================================================================
--- iptables-modules.orig/include/linux/netfilter_ipv4/ipt_conntrack.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Header file for kernel module to match connection tracking information.
- * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
- */
-
-#ifndef _IPT_CONNTRACK_H
-#define _IPT_CONNTRACK_H
-
-#include <linux/netfilter/nf_conntrack_common.h>
-
-/* backwards compatibility crap. only exists in userspace - HW */
-#include <linux/version.h>
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c))
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)) || !defined IPS_EXPECTED
-#define IPS_EXPECTED	(1 << 0)
-#define IPS_SEEN_REPLY	(1 << 1)
-#define IPS_ASSURED	(1 << 2)
-#define IP_CT_DIR_ORIGINAL	0
-#define IP_CT_DIR_REPLY		1
-#define IP_CT_DIR_MAX		2
-#endif
-
-#define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
-#define IPT_CONNTRACK_STATE_INVALID (1 << 0)
-
-#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
-#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
-#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
-
-/* 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
-
-/* This is exposed to userspace, so remains frozen in time. */
-struct ip_conntrack_old_tuple
-{
-	struct {
-		u_int32_t ip;
-		union {
-			u_int16_t all;
-		} u;
-	} src;
-
-	struct {
-		u_int32_t ip;
-		union {
-			u_int16_t all;
-		} u;
-
-		/* The protocol. */
-		u_int16_t protonum;
-	} dst;
-};
-
-struct ipt_conntrack_info
-{
-	unsigned int statemask, statusmask;
-
-	struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
-	struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
-
-	unsigned long expires_min, expires_max;
-
-	/* Flags word */
-	u_int8_t flags;
-	/* Inverse flags */
-	u_int8_t invflags;
-};
-#endif /*_IPT_CONNTRACK_H*/

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

* [PATCH 11/11] libxt_connmark match revision 1
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (8 preceding siblings ...)
  2007-12-22  2:48 ` [PATCH 10/11] libxt_connmark match revision 0 Jan Engelhardt
@ 2007-12-22  2:49 ` Jan Engelhardt
  2007-12-22  2:52 ` [PATCH 0/11] Overview of all the packs Jan Engelhardt
  2007-12-24 14:29 ` [PATCH 1/11] Line-based makefile Laszlo Attila Toth
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:49 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


Had not finished this patch yet I just noticed.

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

* [PATCH 0/11] Overview of all the packs
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (9 preceding siblings ...)
  2007-12-22  2:49 ` [PATCH 11/11] libxt_connmark match revision 1 Jan Engelhardt
@ 2007-12-22  2:52 ` Jan Engelhardt
  2007-12-24 14:29 ` [PATCH 1/11] Line-based makefile Laszlo Attila Toth
  11 siblings, 0 replies; 13+ messages in thread
From: Jan Engelhardt @ 2007-12-22  2:52 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List


I have retouched my quilt packs, find them here
in case any of the sent patches went AWOL:

http://dev.computergmbh.de/f/netfilter.tar.bz2
http://dev.computergmbh.de/f/iptables.tar.bz2
(also contains other patches from my stack)



thanks,
Jan

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

* Re: [PATCH 1/11] Line-based makefile
  2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
                   ` (10 preceding siblings ...)
  2007-12-22  2:52 ` [PATCH 0/11] Overview of all the packs Jan Engelhardt
@ 2007-12-24 14:29 ` Laszlo Attila Toth
  11 siblings, 0 replies; 13+ messages in thread
From: Laszlo Attila Toth @ 2007-12-24 14:29 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: kaber, Netfilter Developer Mailing List



Jan Engelhardt írta:
> Transform the extensions' Makefile into a linear form to reduce
> conflicts for patch stacks (very helpful during development).
> Ideally, I'd just push in the automake patch, though,
> which uses wildcards ;-)
> 
> Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
> 
> ---
>  extensions/Makefile |   92 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 88 insertions(+), 4 deletions(-)
> 
> Index: iptables-modules/extensions/Makefile
> ===================================================================
> --- iptables-modules.orig/extensions/Makefile
> +++ iptables-modules/extensions/Makefile
> @@ -5,13 +5,97 @@
>  # header files are present in the include/linux directory of this iptables
>  # package (HW)
>  #
> -PF_EXT_SLIB:=ah addrtype conntrack ecn icmp iprange owner policy realm recent tos ttl unclean CLUSTERIP DNAT ECN LOG MASQUERADE MIRROR NETMAP REDIRECT REJECT SAME SNAT TOS TTL ULOG
> -PF6_EXT_SLIB:=ah dst eui64 frag hbh hl icmp6 ipv6header mh owner policy rt HL LOG REJECT
> -PFX_EXT_SLIB:=connbytes connmark connlimit comment dccp dscp esp hashlimit helper length limit mac mark multiport physdev pkttype quota sctp state statistic standard string tcp tcpmss time u32 udp CLASSIFY CONNMARK DSCP MARK NFLOG NFQUEUE NOTRACK TCPMSS TRACE
> +a :=
..
> +a += rt
> +PF6_EXT_SLIB := ${a}
> +a :=
...
> +a += udp
> +PFX_EXT_SLIB := ${a}
>  
>  PF_EXT_SELINUX_SLIB:=
>  PF6_EXT_SELINUX_SLIB:=
> -PFX_EXT_SELINUX_SLIB:=CONNSECMARK SECMARK
> +a :=
> +a += CONNSECMARK
> +a += SECMARK
> +PFX_EXT_SELINUX_SLIB := ${a}
> 

That would be better as
PF_EXT_SLIB :=
PF_EXT_SLIB += ah
and so on.

The other one uses the same variable for every PF_*SLIB also patch
command  may fail.

--
Attila


> 
> -
> 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
-
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] 13+ messages in thread

end of thread, other threads:[~2007-12-24 14:31 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-22  2:44 [PATCH 1/11] Line-based makefile Jan Engelhardt
2007-12-22  2:44 ` [PATCH 2/11] strtonum Jan Engelhardt
2007-12-22  2:44 ` [PATCH 3/11] Common error strings Jan Engelhardt
2007-12-22  2:45 ` [PATCH 4/11] libxt_owner match Jan Engelhardt
2007-12-22  2:45 ` [PATCH 5/11] libxt_tos match revision 1 Jan Engelhardt
2007-12-22  2:45 ` [PATCH 6/11] libxt_TOS target " Jan Engelhardt
2007-12-22  2:46 ` [PATCH 7/11] libxt_MARK target revision 2 Jan Engelhardt
2007-12-22  2:46 ` [PATCH 8/11] libxt_connmark match Jan Engelhardt
2007-12-22  2:47 ` [PATCH 9/11] libxt_CONNMARK target revision 1 Jan Engelhardt
2007-12-22  2:48 ` [PATCH 10/11] libxt_connmark match revision 0 Jan Engelhardt
2007-12-22  2:49 ` [PATCH 11/11] libxt_connmark match revision 1 Jan Engelhardt
2007-12-22  2:52 ` [PATCH 0/11] Overview of all the packs Jan Engelhardt
2007-12-24 14:29 ` [PATCH 1/11] Line-based makefile Laszlo Attila Toth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).