All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH, RFC]: new match 'secpath'
@ 2003-08-25 13:36 Patrick McHardy
  0 siblings, 0 replies; only message in thread
From: Patrick McHardy @ 2003-08-25 13:36 UTC (permalink / raw)
  To: Netfilter Development Mailinglist

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

This patch adds a new match secpath which can be used to
match if a packet came out of an ipsec tunnel and various
other related stuff (please see the helptext for more info).
Comments are welcome.

Bye
Patrick

[-- Attachment #2: pom-secpath.diff --]
[-- Type: text/plain, Size: 14814 bytes --]

diff -urN a/patch-o-matic_2.5/extra/secpath.patch b/patch-o-matic_2.5/extra/secpath.patch
--- a/patch-o-matic_2.5/extra/secpath.patch	1970-01-01 01:00:00.000000000 +0100
+++ b/patch-o-matic_2.5/extra/secpath.patch	2003-08-25 15:07:40.000000000 +0200
@@ -0,0 +1,188 @@
+diff -Nru a/include/linux/netfilter_ipv4/ipt_secpath.h b/include/linux/netfilter_ipv4/ipt_secpath.h
+--- /dev/null	Wed Dec 31 16:00:00 1969
++++ b/include/linux/netfilter_ipv4/ipt_secpath.h	Mon Aug 25 15:07:40 2003
+@@ -0,0 +1,41 @@
++#ifndef _IPT_SECPATH_H
++#define _IPT_SECPATH_H
++
++#define SECPATH_MAX_DEPTH	4		/* must match XFRM_MAX_DEPTH */
++
++#define MATCH_PATH		0x1
++
++#define SECPATH_MODE_TRANSPORT	0
++#define SECPATH_MODE_TUNNEL	1
++
++struct ipt_secpath_flags
++{
++	u_int8_t saddr:1,
++	         daddr:1,
++	         spi:1,
++	         proto:1,
++	         mode:1;
++};
++
++struct ipt_secpath_elem
++{
++	u_int32_t saddr;
++	u_int32_t smask;
++	u_int32_t daddr;
++	u_int32_t dmask;
++	u_int32_t spi;
++	u_int8_t proto;
++	u_int8_t mode;
++
++	struct ipt_secpath_flags match;
++	struct ipt_secpath_flags invert;
++};
++
++struct ipt_secpath_info
++{
++	struct ipt_secpath_elem path[SECPATH_MAX_DEPTH];
++	u_int16_t len;
++	u_int16_t flags;
++};
++
++#endif
+diff -Nru a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
+--- a/net/ipv4/netfilter/Kconfig	Mon Aug 25 15:07:40 2003
++++ b/net/ipv4/netfilter/Kconfig	Mon Aug 25 15:07:40 2003
+@@ -301,6 +301,17 @@
+ 	  If you want to compile it as a module, say M here and read
+ 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+ 
++config IP_NF_MATCH_SECPATH
++	tristate "Secpath match support"
++	depends on EXPERIMENTAL && IP_NF_IPTABLES
++	help
++	  Secpath packet matching allows you to match various attributes
++	  of a packets secpath which describes the path a packet took through
++	  the (ipsec) transformers during decapsulation.
++
++	  If you want to compile it as a module, say M here and read
++	  <file:Documentation/modules.txt>.  If unsure, say `N'.
++
+ # The targets
+ config IP_NF_FILTER
+ 	tristate "Packet filtering"
+diff -Nru a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
+--- a/net/ipv4/netfilter/Makefile	Mon Aug 25 15:07:40 2003
++++ b/net/ipv4/netfilter/Makefile	Mon Aug 25 15:07:40 2003
+@@ -65,6 +65,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+ 
+ obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
++obj-$(CONFIG_IP_NF_MATCH_SECPATH) += ipt_secpath.o
+ 
+ # targets
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+diff -Nru a/net/ipv4/netfilter/ipt_secpath.c b/net/ipv4/netfilter/ipt_secpath.c
+--- /dev/null	Wed Dec 31 16:00:00 1969
++++ b/net/ipv4/netfilter/ipt_secpath.c	Mon Aug 25 15:07:40 2003
+@@ -0,0 +1,107 @@
++/* IP tables module for matching various secpath attributes
++ *
++ * (C) 2003 by Patrick McHardy <kaber@trash.net>
++ *
++ * This software is distributed under the terms  GNU GPL
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <net/xfrm.h>
++
++#include <linux/netfilter_ipv4/ipt_secpath.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
++MODULE_DESCRIPTION("IP secpath atttribute matching module");
++MODULE_LICENSE("GPL");
++
++static int secpath_match(struct xfrm_state *x, const struct ipt_secpath_elem *e)
++{
++	if (e->match.saddr) {
++		if ((e->saddr != ((u32) x->props.saddr.a4 & e->smask)) ^
++		    e->invert.saddr)
++			return 0;
++	}
++	if (e->match.daddr) {
++		if ((e->daddr != ((u32) x->id.daddr.a4 & e->dmask)) ^
++		    e->invert.daddr)
++			return 0;
++	}
++	if (e->match.spi) {
++		if ((e->spi != x->id.spi) ^ e->invert.spi)
++			return 0;
++	}
++	if (e->match.proto) {
++		if ((e->proto != x->id.proto) ^ e->invert.proto)
++			return 0;
++	}
++	if (e->match.mode) {
++		if ((e->mode != x->props.mode) ^ e->invert.mode)
++			return 0;
++	}
++	return 1;
++}
++
++static int match(const struct sk_buff *skb,
++                 const struct net_device *in,
++                 const struct net_device *out,
++                 const void *matchinfo,
++		 int offset, int *hotdrop)
++{
++	const struct ipt_secpath_info *info = matchinfo;
++	struct sec_path *sp = skb->sp;
++	unsigned int i;
++	int strict = info->flags & MATCH_PATH;
++
++	if (sp == NULL)
++		return 0;
++
++	if (strict && info->len != sp->len)
++		return 0;
++	
++	for (i = 0; i < sp->len; i++) {
++		if (secpath_match(sp->x[i].xvec, &info->path[strict ? i : 0])) {
++			if (!strict)
++				return 1;
++		} else if (strict)
++			return 0;
++	}
++
++	return strict ? 1 : 0;
++}
++
++static int checkentry(const char *tablename, const struct ipt_ip *ip,
++		      void *matchinfo, unsigned int matchsize,
++		      unsigned int hook_mask)
++{
++	if (matchsize != IPT_ALIGN(sizeof(struct ipt_secpath_info))) {
++		printk(KERN_ERR "ipt_secpath: matchsize %u != %u.\n",
++		       matchsize, IPT_ALIGN(sizeof(struct ipt_secpath_info)));
++		return 0;
++	}
++
++	return 1;
++}
++
++static struct ipt_match secpath_match = {
++	.name		= "secpath",
++	.match		= &match,
++	.checkentry	= &checkentry,
++	.me		= THIS_MODULE,
++};
++
++static int __init init(void)
++{
++	return ipt_register_match(&secpath_match);
++}
++
++static void __exit fini(void)
++{
++	ipt_unregister_match(&secpath_match);
++
++}
++
++module_init(init);
++module_exit(fini);
diff -urN a/patch-o-matic_2.5/extra/secpath.patch.help b/patch-o-matic_2.5/extra/secpath.patch.help
--- a/patch-o-matic_2.5/extra/secpath.patch.help	1970-01-01 01:00:00.000000000 +0100
+++ b/patch-o-matic_2.5/extra/secpath.patch.help	2003-08-25 15:23:31.000000000 +0200
@@ -0,0 +1,45 @@
+Author: Patrick McHardy <kaber@trash.net>
+Status: Experimental
+
+This patch adds a new match 'secpath' which is used to match attributes of the
+secpath of a decapsulated packet. The secpath describes a packets path through
+the (ipsec) transformers during decapsulation.
+
+Options:
+
+	--spi SPI			Match SPI
+	--proto ah/esp/ipcomp		Match protocol
+	--mode transport/tunnel		Match mode
+	--local IP			Match local tunnel endpoint
+	--remote IP			Match remote tunnel endpoint
+
+	--path 				Match path instead of single element
+					at any position
+	--next 				Begin next element in path
+
+Examples:
+
+	# accept everything coming out of an esp tunnel from 
+	# 192.168.0.0/24 to 192.168.0.1
+
+	iptables -I INPUT -m secpath --proto esp \
+				     --mode tunnel \
+	                             --local 192.168.0.1 \
+				     --remote 192.168.0.0/24 \
+				     -j ACCEPT
+	
+	# accept all tcp packets coming out of a tunnel from 192.168.0.0/24 
+	# to 192.168.0.1 which looks like this:
+	# <ip> <ah> <esp> <ip>
+
+	iptables -I INPUT -p tcp \
+			  -m secpath --path \
+				     --proto ah \
+				     --mode transport \
+				     --next \
+				     --proto esp \
+				     --mode tunnel \
+				     --local 192.168.0.1 \
+				     --remote 192.168.0.0/24 \
+				     -j ACCEPT
+
diff -urN a/userspace/extensions/libipt_secpath.c b/userspace/extensions/libipt_secpath.c
--- a/userspace/extensions/libipt_secpath.c	1970-01-01 01:00:00.000000000 +0100
+++ b/userspace/extensions/libipt_secpath.c	2003-08-25 15:06:23.000000000 +0200
@@ -0,0 +1,331 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <iptables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_secpath.h>
+
+static void help(void)
+{
+	printf(
+"secpath v%s options:\n"
+" --spi SPI			Match SPI\n"
+" --proto ah/esp/ipcomp		Match protocol\n"
+" --mode transport/tunnel	Match mode\n"
+" --local IP			Match local tunnel endpoint\n"
+" --remote IP			Match remote tunnel endpoint\n"
+" --path			Match path instead of single element at any position\n"
+" --next			Begin next element in path\n",
+	IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{
+		.name		= "spi",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '1'
+	},
+	{
+		.name		= "local",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '2'
+	},
+	{
+		.name		= "remote",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '3'
+	},
+	{
+		.name		= "proto",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '4'
+	},
+	{
+		.name		= "mode",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '5'
+	},
+	{
+		.name		= "path",
+		.has_arg	= 0,
+		.flag		= 0,
+		.val		= '6'
+	},
+	{
+		.name		= "next",
+		.has_arg	= 0,
+		.flag		= 0,
+		.val		= '7'
+	},
+	{ 0 }
+};
+
+static void init(struct ipt_entry_match *m, unsigned int *nfcache)
+{
+	*nfcache |= NFC_UNKNOWN;
+}
+
+static int parse_mode(char *s)
+{
+	if (strcmp(s, "transport") == 0)
+		return SECPATH_MODE_TRANSPORT;
+	if (strcmp(s, "tunnel") == 0)
+		return SECPATH_MODE_TUNNEL;
+	return -EINVAL;
+}
+
+static int parse(int c, char **argv, int invert, unsigned int *i,
+                 const struct ipt_entry *entry,
+                 unsigned int *nfcache,
+                 struct ipt_entry_match **match)
+{
+	struct ipt_secpath_info *info = (void *)(*match)->data;
+	struct ipt_secpath_elem *e = &info->path[*i];
+	struct in_addr *addr = NULL, mask;
+	struct protoent *p;
+	unsigned int naddr = 0;
+	int mode, proto;
+
+	check_inverse(optarg, &invert, &optind, 0);
+
+	switch (c) {
+	case '1':
+		if (e->match.spi)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --spi twice");
+		
+		e->match.spi = 1;
+		e->invert.spi = invert;
+		e->spi = strtol(argv[optind-1], NULL, 0x10);
+		break;
+	case '2':
+		if (e->match.daddr)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --local twice");
+		
+		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+		if (naddr > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "Multiple IP addresses are not allowed");
+
+		e->match.daddr = 1;
+		e->invert.daddr = invert;
+		e->daddr = addr[0].s_addr;
+		e->dmask = mask.s_addr;
+		break;
+	case '3':
+		if (e->match.saddr)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --remote twice");
+
+		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+		if (naddr > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "Multiple IP addresses are not allowed");
+
+		e->match.saddr = 1;
+		e->invert.saddr = invert;
+		e->saddr = addr[0].s_addr;
+		e->smask = mask.s_addr;
+                break;
+	case '4':
+		if (e->match.proto)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --proto twice");
+
+		p = getprotobyname(argv[optind-1]);
+		if (p != NULL)
+			proto = p->p_proto;
+		else if (!(proto = atoi(argv[optind-1])))
+			exit_error(PARAMETER_PROBLEM,
+			           "Unknown protocol `%s'\n",
+			           argv[optind-1]);
+
+		e->match.proto = 1;
+		e->invert.proto = invert;
+		e->proto = proto;
+		break;
+	case '5':
+		if (e->match.mode)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --mode twice");
+		
+		mode = parse_mode(argv[optind-1]);
+		if (mode < 0)
+			exit_error(PARAMETER_PROBLEM,
+			           "Unknown mode `%s'\n",
+			           argv[optind-1]);
+
+		e->match.mode = 1;
+		e->invert.mode = invert;
+		e->mode = mode;
+		break;
+	case '6':
+		if (info->flags & MATCH_PATH)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --path twice");
+
+		if (invert)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't invert `--path' option");
+
+		info->flags |= MATCH_PATH;
+		break;
+	case '7':
+		if (invert)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't invert `--next' option");
+
+		if (++(*i) == SECPATH_MAX_DEPTH)
+			exit_error(PARAMETER_PROBLEM,
+			           "Maximum path depth reached");
+
+		break;
+	default:
+		return 0;
+	}
+
+	info->len = *i + 1;
+	return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+	return;
+}
+
+static void print_proto(char *prefix, u_int8_t proto, int numeric)
+{
+	struct protoent *p = NULL;
+
+	if (!numeric)
+		p = getprotobynumber(proto);
+	if (p == NULL)
+		printf("%sproto %u ", prefix, proto);
+	else
+		printf("%sproto %s ", prefix, p->p_name);
+}
+
+static void print_mode(char *prefix, u_int8_t mode, int numeric)
+{
+	printf("%smode ", prefix);
+
+	switch (mode) {
+	case SECPATH_MODE_TRANSPORT:
+		printf("transport ");
+		break;
+	case SECPATH_MODE_TUNNEL:
+		printf("tunnel ");
+		break;
+	default:
+		printf("??? ");
+		break;
+	}
+}
+
+#define PRINT_INVERT(x)		\
+do {				\
+	if (x)			\
+		printf("! ");	\
+} while(0)
+
+static void print_entry(char *prefix, const struct ipt_secpath_elem *e,
+                        int numeric)
+{
+	if (e->match.spi) {
+		PRINT_INVERT(e->invert.spi);
+		printf("%sspi 0x%x ", prefix, e->spi);
+	}
+	if (e->match.proto) {
+		PRINT_INVERT(e->invert.proto);
+		print_proto(prefix, e->proto, numeric);
+	}
+	if (e->match.mode) {
+		PRINT_INVERT(e->invert.mode);
+		print_mode(prefix, e->mode, numeric);
+	}
+	if (e->match.daddr) {
+		PRINT_INVERT(e->invert.daddr);
+		printf("%slocal %s%s ", prefix,
+		       addr_to_dotted((struct in_addr *)&e->daddr),
+		       mask_to_dotted((struct in_addr *)&e->dmask));
+	}
+	if (e->match.saddr) {
+		PRINT_INVERT(e->invert.saddr);
+		printf("%sremote %s%s ", prefix,
+		       addr_to_dotted((struct in_addr *)&e->saddr),
+		       mask_to_dotted((struct in_addr *)&e->smask));
+	}
+}
+
+static void print(const struct ipt_ip *ip,
+                  const struct ipt_entry_match *match,
+		  int numeric)
+{
+	const struct ipt_secpath_info *info = (void *)match->data;
+	unsigned int i;
+
+	printf ("secpath match ");
+	if (info->flags & MATCH_PATH)
+		printf("path ");
+
+	for (i = 0; i < info->len; i++) {
+		if (info->len > 1)
+			printf("[%u] ", i);
+		print_entry("", &info->path[i], numeric);
+	}
+
+	printf("\n");
+}
+
+static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+{
+	const struct ipt_secpath_info *info = (void *)match->data;
+	unsigned int i;
+
+	if (info->flags & MATCH_PATH)
+		printf("--path ");
+
+	for (i = 0; i < info->len; i++) {
+		print_entry("--", &info->path[i], 0);
+		if (i + 1 < info->len)
+			printf("--next ");
+	}
+
+	printf("\n");
+}
+
+struct iptables_match secpath =
+{
+	NULL,
+	"secpath",
+	IPTABLES_VERSION,
+	IPT_ALIGN(sizeof(struct ipt_secpath_info)),
+	IPT_ALIGN(sizeof(struct ipt_secpath_info)),
+	&help,
+	&init,
+	&parse,
+	&final_check,
+	&print,
+	&save,
+	opts
+};
+
+void _init(void)
+{
+	register_match(&secpath);
+}
diff -urN a/userspace/extensions/.secpath-test b/userspace/extensions/.secpath-test
--- a/userspace/extensions/.secpath-test	1970-01-01 01:00:00.000000000 +0100
+++ b/userspace/extensions/.secpath-test	2003-08-25 15:06:53.000000000 +0200
@@ -0,0 +1,3 @@
+#!/bin/sh
+# True if secpath match patch is applied.
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_secpath.h ] && echo secpath

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-08-25 13:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-08-25 13:36 [PATCH, RFC]: new match 'secpath' Patrick McHardy

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