All of lore.kernel.org
 help / color / mirror / Atom feed
From: Phil Oester <kernel@linuxace.com>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH,RFC] Route match
Date: Wed, 2 Jul 2008 17:39:42 -0700	[thread overview]
Message-ID: <20080703003942.GA2012@linuxace.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1337 bytes --]

Attached is a new "route" match, which matches against entries
in the kernel routing table.  I've had a need for this functionality
for quite some time, and finally decided to code it up.  

TODO: add IPv6 support to kernel side

Options

[!] --route-src-exists      Route for src exists
    --route-src-eq value    Route for src exists with prefix-length == value
    --route-src-gt value    Route for src exists with prefix-length  > value
    --route-src-lt value    Route for src exists with prefix-length  < value
[!] --route-dst-exists      Route for dst exists
    --route-dst-eq value    Route for dst exists with prefix-length == value
    --route-dst-gt value    Route for dst exists with prefix-length  > value
    --route-dst-lt value    Route for dst exists with prefix-length  < value

Examples:

	Egress filtering:
		iptables -A FORWARD -m route ! --route-src-exists -j DROP

	Ingress filtering:
		iptables -A FORWARD -i $EXTERNAL_IF -m route --route-src-exists -j DROP

	Allow a user to only browse internal websites:
		iptables -A FORWARD -p tcp --dport 80 -m route --route-dst-exists -j ACCEPT

	Allow an SNMP collector to reach all internal routers (/30 or /32 interfaces)
		iptables -A FORWARD -p udp --dport 161 -m route --route-dst-gt 29 -j ACCEPT


Please let me know if anyone else finds this match useful.

Phil

[-- Attachment #2: patch-route-kernel --]
[-- Type: text/plain, Size: 6206 bytes --]

diff --git a/include/linux/netfilter/xt_route.h b/include/linux/netfilter/xt_route.h
new file mode 100644
index 0000000..0c90494
--- /dev/null
+++ b/include/linux/netfilter/xt_route.h
@@ -0,0 +1,21 @@
+#ifndef _XT_ROUTE_H
+#define _XT_ROUTE_H
+
+enum {
+	XT_ROUTE_SRC_EXISTS = 0,
+	XT_ROUTE_SRC_EQ,
+	XT_ROUTE_SRC_GT,
+	XT_ROUTE_SRC_LT,
+	XT_ROUTE_DST_EXISTS,
+	XT_ROUTE_DST_EQ,
+	XT_ROUTE_DST_GT,
+	XT_ROUTE_DST_LT,
+};
+
+struct xt_route_info {
+	u_int8_t	invert;
+	u_int8_t	mode;
+	u_int8_t	prefixlen;
+};
+
+#endif /*_XT_ROUTE_H*/
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 0d4d728..22bbdd5 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -156,6 +156,8 @@ void free_fib_info(struct fib_info *fi)
 	kfree(fi);
 }
 
+EXPORT_SYMBOL_GPL(free_fib_info);
+
 void fib_release_info(struct fib_info *fi)
 {
 	spin_lock_bh(&fib_info_lock);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index aa8d80c..128b186 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -724,6 +724,16 @@ config NETFILTER_XT_MATCH_REALM
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_ROUTE
+	tristate '"route" match support'
+	depends on NETFILTER_XTABLES
+	depends on NETFILTER_ADVANCED
+	help
+	  This option adds a `route' match, which allows you to match on
+	  the kernel routing table.  
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_SCTP
 	tristate  '"sctp" protocol match support (EXPERIMENTAL)'
 	depends on NETFILTER_XTABLES && EXPERIMENTAL
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5c4b183..1035372 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_ROUTE) += xt_route.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
diff --git a/net/netfilter/xt_route.c b/net/netfilter/xt_route.c
new file mode 100644
index 0000000..c6e9f94
--- /dev/null
+++ b/net/netfilter/xt_route.c
@@ -0,0 +1,141 @@
+/* Kernel module to match against the kernel routing table. */
+/* (C) 2008 Phil Oester <kernel@linuxace.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <net/ip.h>
+#include <net/flow.h>
+#include <net/ip_fib.h>
+
+#include <linux/netfilter/xt_route.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_AUTHOR("Phil Oester <kernel@linuxace.com>");
+MODULE_DESCRIPTION("Xtables: Routing table match");
+MODULE_LICENSE("GPL");
+
+static bool
+route_mt(const struct sk_buff *skb, const struct net_device *in,
+          const struct net_device *out, const struct xt_match *match,
+          const void *matchinfo, int offset, unsigned int protoff,
+          bool *hotdrop)
+{
+	const struct xt_route_info *info = matchinfo;
+	const struct iphdr *iph = ip_hdr(skb);
+	struct fib_result res = {0};
+	struct flowi fl = {0};
+	int ret;
+
+	switch (info->mode) {
+	case XT_ROUTE_SRC_EXISTS:
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen != 0) {
+			fib_res_put(&res);
+			return true ^ info->invert;
+		}
+	case XT_ROUTE_SRC_EQ:
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen == info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	case XT_ROUTE_SRC_GT:
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen > info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	case XT_ROUTE_SRC_LT:
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen < info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	case XT_ROUTE_DST_EXISTS:
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen != 0) {
+			fib_res_put(&res);
+			return true ^ info->invert;
+		}
+		break;
+	case XT_ROUTE_DST_EQ:
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen == info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	case XT_ROUTE_DST_GT:
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen > info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	case XT_ROUTE_DST_LT:
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		ret = fib_lookup(dev_net(in), &fl, &res);
+		if (ret == 0 && res.prefixlen < info->prefixlen) {
+			fib_res_put(&res);
+			return true;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static bool
+route_mt6(const struct sk_buff *skb, const struct net_device *in,
+           const struct net_device *out, const struct xt_match *match,
+           const void *matchinfo, int offset, unsigned int protoff,
+           bool *hotdrop)
+{
+	return 1;
+}
+
+static struct xt_match route_mt_reg[] __read_mostly = {
+	{
+		.name		= "route",
+		.family		= AF_INET,
+		.match		= route_mt,
+		.matchsize	= sizeof(struct xt_route_info),
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "route",
+		.family		= AF_INET6,
+		.match		= route_mt6,
+		.matchsize	= sizeof(struct xt_route_info),
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init route_mt_init(void)
+{
+	return xt_register_matches(route_mt_reg, ARRAY_SIZE(route_mt_reg));
+}
+
+static void __exit route_mt_exit(void)
+{
+	xt_unregister_matches(route_mt_reg, ARRAY_SIZE(route_mt_reg));
+}
+
+module_init(route_mt_init);
+module_exit(route_mt_exit);

[-- Attachment #3: patch-route-user --]
[-- Type: text/plain, Size: 10259 bytes --]

diff --git a/extensions/libxt_route.c b/extensions/libxt_route.c
new file mode 100644
index 0000000..a2187cb
--- /dev/null
+++ b/extensions/libxt_route.c
@@ -0,0 +1,371 @@
+/* Shared library add-on to iptables to add route matching support 
+ * (C) 2008 by Phil Oester <kernel@linuxace.com>
+ *
+ * This program is released under the terms of GNU GPL */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <iptables.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_route.h>
+
+static void route_help(void)
+{
+	printf(
+"route match options:\n"
+"  [!] --route-src-exists	Route for src exists\n"
+"      --route-src-eq value	Route for src exists with prefix-length == value\n"
+"      --route-src-gt value	Route for src exists with prefix-length  > value\n"
+"      --route-src-lt value	Route for src exists with prefix-length  < value\n"
+"  [!] --route-dst-exists	Route for dst exists\n"
+"      --route-dst-eq value	Route for dst exists with prefix-length == value\n"
+"      --route-dst-gt value	Route for dst exists with prefix-length  > value\n"
+"      --route-dst-lt value	Route for dst exists with prefix-length  < value\n");
+}
+
+static const struct option route_opts[] = {
+	{ "route-src-exists", 0, NULL, '1' },
+	{ "route-src-eq", 1, NULL, '2' },
+	{ "route-src-gt", 1, NULL, '3' },
+	{ "route-src-lt", 1, NULL, '4' },
+	{ "route-dst-exists", 0, NULL, '5' },
+	{ "route-dst-eq", 1, NULL, '6' },
+	{ "route-dst-gt", 1, NULL, '7' },
+	{ "route-dst-lt", 1, NULL, '8' },
+	{ .name = NULL }
+};
+
+static int route_parse(int c, char **argv, int invert, unsigned int *flags,
+                       const void *entry, struct xt_entry_match **match)
+{
+	struct xt_route_info *info = (struct xt_route_info *) (*match)->data;
+	unsigned int value;
+
+	check_inverse(optarg, &invert, &optind, 0);
+
+	switch (c) {
+		case '1':
+			if (invert)
+				info->invert = 1;
+
+			info->mode = XT_ROUTE_SRC_EXISTS;			
+			break;
+		case '2':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 1, 32, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 1 and 32");
+
+			info->mode = XT_ROUTE_SRC_EQ;
+			info->value = value;
+			break;
+		case '3':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 0, 31, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 0 and 31");
+
+			info->mode = XT_ROUTE_SRC_GT;
+			info->value = value;
+			break;
+		case '4':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 2, 32, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 2 and 32");
+
+			info->mode = XT_ROUTE_SRC_LT;
+			info->value = value;
+			break;
+		case '5':
+			if (invert)
+				info->invert = 1;
+
+			info->mode = XT_ROUTE_DST_EXISTS;			
+			break;
+		case '6':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 1, 32, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 1 and 32");
+
+			info->mode = XT_ROUTE_DST_EQ;
+			info->value = value;
+			break;
+		case '7':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 0, 31, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 0 and 31");
+
+			info->mode = XT_ROUTE_DST_GT;
+			info->value = value;
+			break;
+		case '8':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 2, 32, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 2 and 32");
+
+			info->mode = XT_ROUTE_DST_LT;
+			info->value = value;
+			break;
+		default:
+			return 0;
+
+	}
+
+	if (*flags) 
+		exit_error(PARAMETER_PROBLEM, 
+				"Can't specify route match twice");
+	*flags = 1;
+
+	return 1;
+}
+
+static int route_parse6(int c, char **argv, int invert, unsigned int *flags,
+                       const void *entry, struct xt_entry_match **match)
+{
+	struct xt_route_info *info = (struct xt_route_info *) (*match)->data;
+	unsigned int value;
+
+	check_inverse(optarg, &invert, &optind, 0);
+
+	switch (c) {
+		case '1':
+			if (invert)
+				info->invert = 1;
+
+			info->mode = XT_ROUTE_SRC_EXISTS;			
+			break;
+		case '2':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 1, 128, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 1 and 128");
+
+			info->mode = XT_ROUTE_SRC_EQ;
+			info->value = value;
+			break;
+		case '3':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 0, 127, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 0 and 127");
+
+			info->mode = XT_ROUTE_SRC_GT;
+			info->value = value;
+			break;
+		case '4':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 2, 128, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 2 and 128");
+
+			info->mode = XT_ROUTE_SRC_LT;
+			info->value = value;
+			break;
+		case '5':
+			if (invert)
+				info->invert = 1;
+
+			info->mode = XT_ROUTE_DST_EXISTS;			
+			break;
+		case '6':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 1, 128, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 1 and 128");
+
+			info->mode = XT_ROUTE_DST_EQ;
+			info->value = value;
+			break;
+		case '7':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 0, 127, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 0 and 127");
+
+			info->mode = XT_ROUTE_DST_GT;
+			info->value = value;
+			break;
+		case '8':
+			if (invert) 
+				exit_error(PARAMETER_PROBLEM,
+						"route: unexpected `!'");
+
+			if (string_to_number(optarg, 2, 128, &value) == -1)
+				exit_error(PARAMETER_PROBLEM,
+				           "route: Expected prefix between 2 and 128");
+
+			info->mode = XT_ROUTE_DST_LT;
+			info->value = value;
+			break;
+		default:
+			return 0;
+
+	}
+
+	if (*flags) 
+		exit_error(PARAMETER_PROBLEM, 
+				"Can't specify route match twice");
+	*flags = 1;
+
+	return 1;
+}
+
+static void route_check(unsigned int flags)
+{
+	if (!flags) 
+		exit_error(PARAMETER_PROBLEM,
+			"Route match: You must specify an option");
+}
+
+static void route_print(const void *ip, const struct xt_entry_match *match,
+                      int numeric)
+{
+	const struct xt_route_info *info = 
+		(struct xt_route_info *) match->data;
+
+	printf("Route: ");
+	switch (info->mode) {
+		case XT_ROUTE_SRC_EXISTS:
+			if (info->invert)
+				printf("! ");
+			printf("Src exists ");
+			break;
+		case XT_ROUTE_SRC_EQ:
+			printf("Src prefix == %u ", info->value);
+			break;
+		case XT_ROUTE_SRC_GT:
+			printf("Src prefix > %u ", info->value);
+			break;
+		case XT_ROUTE_SRC_LT:
+			printf("Src prefix < %u ", info->value);
+			break;
+		case XT_ROUTE_DST_EXISTS:
+			if (info->invert)
+				printf("! ");
+			printf("Dst exists ");
+			break;
+		case XT_ROUTE_DST_EQ:
+			printf("Dst prefix == %u ", info->value);
+			break;
+		case XT_ROUTE_DST_GT:
+			printf("Dst prefix > %u ", info->value);
+			break;
+		case XT_ROUTE_DST_LT:
+			printf("Dst prefix < %u ", info->value);
+			break;
+	}
+}
+
+static void route_save(const void *ip, const struct xt_entry_match *match)
+{
+	const struct xt_route_info *info =
+		(struct xt_route_info *) match->data;
+
+	switch (info->mode) {
+		case XT_ROUTE_SRC_EXISTS:
+			if (info->invert)
+				printf("! ");
+			printf("--route-src-exists ");
+			break;
+		case XT_ROUTE_SRC_EQ:
+			printf("--route-src-eq %u ", info->value);
+			break;
+		case XT_ROUTE_SRC_GT:
+			printf("--route-src-gt %u ", info->value);
+			break;
+		case XT_ROUTE_SRC_LT:
+			printf("--route-src-lt %u ", info->value);
+			break;
+		case XT_ROUTE_DST_EXISTS:
+			if (info->invert)
+				printf("! ");
+			printf("--route-dst-exists ");
+			break;
+		case XT_ROUTE_DST_EQ:
+			printf("--route-dst-eq %u ", info->value);
+			break;
+		case XT_ROUTE_DST_GT:
+			printf("--route-dst-gt < %u ", info->value);
+			break;
+		case XT_ROUTE_DST_LT:
+			printf("--route-dst-lt > %u ", info->value);
+			break;
+		default:
+			break;
+	}
+}
+
+static struct xtables_match route_mt = {
+	.name		= "route",
+	.version	= XTABLES_VERSION,
+	.family		= AF_INET,
+	.size		= XT_ALIGN(sizeof(struct xt_route_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_route_info)),
+	.help		= route_help,
+	.parse		= route_parse,
+	.final_check	= route_check,
+	.print		= route_print,
+	.save		= route_save,
+	.extra_opts	= route_opts,
+};
+
+static struct xtables_match route_mt6 = {
+	.name		= "route",
+	.version	= XTABLES_VERSION,
+	.family		= AF_INET6,
+	.size		= XT_ALIGN(sizeof(struct xt_route_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_route_info)),
+	.help		= route_help,
+	.parse		= route_parse6,
+	.final_check	= route_check,
+	.print		= route_print,
+	.save		= route_save,
+	.extra_opts	= route_opts,
+};
+
+
+void _init(void) 
+{
+	xtables_register_match(&route_mt);
+	xtables_register_match(&route_mt6);
+}
diff --git a/include/linux/netfilter/xt_route.h b/include/linux/netfilter/xt_route.h
new file mode 100644
index 0000000..0c90494
--- /dev/null
+++ b/include/linux/netfilter/xt_route.h
@@ -0,0 +1,21 @@
+#ifndef _XT_ROUTE_H
+#define _XT_ROUTE_H
+
+enum {
+	XT_ROUTE_SRC_EXISTS = 0,
+	XT_ROUTE_SRC_EQ,
+	XT_ROUTE_SRC_GT,
+	XT_ROUTE_SRC_LT,
+	XT_ROUTE_DST_EXISTS,
+	XT_ROUTE_DST_EQ,
+	XT_ROUTE_DST_GT,
+	XT_ROUTE_DST_LT,
+};
+
+struct xt_route_info {
+	u_int8_t	invert;
+	u_int8_t	mode;
+	u_int8_t	prefixlen;
+};
+
+#endif /*_XT_ROUTE_H*/

             reply	other threads:[~2008-07-03  0:46 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-03  0:39 Phil Oester [this message]
2008-07-03  7:18 ` [PATCH,RFC] Route match Jan Engelhardt
2008-07-03  9:50   ` Jozsef Kadlecsik
2008-07-03 11:22     ` Jan Engelhardt
2008-07-03 12:39       ` Jozsef Kadlecsik
2008-07-03 13:13         ` Jan Engelhardt
2008-07-03 13:31           ` Jozsef Kadlecsik
2008-07-03 14:15             ` Jan Engelhardt
2008-07-03 22:02               ` Jozsef Kadlecsik
2008-07-03 23:02                 ` Jan Engelhardt
2008-07-04  0:19                   ` James King
2008-07-04  0:37                     ` Jan Engelhardt
2008-07-03 15:51       ` Krzysztof Oledzki
2008-07-03 16:07         ` Jan Engelhardt
2008-07-03 16:10           ` Patrick McHardy
2008-07-03 16:14           ` Krzysztof Oledzki
2008-07-03 16:14         ` Jan Engelhardt
2008-07-04 13:47           ` Benny Amorsen
2008-07-04 15:15       ` Henrik Nordstrom
2008-07-03 18:53     ` Patrick McHardy
2008-07-03 22:21       ` Jozsef Kadlecsik
2008-07-04 20:26         ` Jozsef Kadlecsik
2008-07-03  7:22 ` [PATCH,RFC] Route match, kernel Jan Engelhardt
2008-07-03 16:27   ` Phil Oester
2008-07-03  7:26 ` [PATCH,RFC] Route match, user Jan Engelhardt
2008-07-03 16:29   ` Phil Oester
2008-07-03 16:55     ` Jan Engelhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080703003942.GA2012@linuxace.com \
    --to=kernel@linuxace.com \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.