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

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

This patch adds a new match "secpath". It is used to match stuff from
the secpath of a decapsulated packet. It can be used for matching if a
packet came from a specific tunnel, tunnel endpoints, spis, protos, ...
and can also match complex descriptions like "ah transport + esp tunnel
from 192.168.0.0/24".

Regards,
Patrick

[-- Attachment #2: nf-secpath.diff --]
[-- Type: text/plain, Size: 15916 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-26 17:45:50.000000000 +0200
@@ -0,0 +1,193 @@
+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	Tue Aug 26 16:09:24 2003
+@@ -0,0 +1,43 @@
++#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,
++	         reqid: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_int32_t reqid;
++	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_int8_t len;
++	u_int8_t flags;
++};
++
++#endif
+diff -Nru a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
+--- a/net/ipv4/netfilter/Kconfig	Tue Aug 26 16:09:24 2003
++++ b/net/ipv4/netfilter/Kconfig	Tue Aug 26 16:09:24 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	Tue Aug 26 16:09:24 2003
++++ b/net/ipv4/netfilter/Makefile	Tue Aug 26 16:09:24 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	Tue Aug 26 16:09:24 2003
+@@ -0,0 +1,110 @@
++/* IP tables module for matching various secpath attributes
++ *
++ * (C) 2003 by Patrick McHardy <kaber@trash.net>
++ *
++ * This software is distributed under the terms of the GNU GPL version 2.
++ */
++
++#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("IPtables secpath attribute matching module");
++MODULE_LICENSE("GPL");
++
++static int match_secpath(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.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;
++	}
++	if (e->match.spi) {
++		if ((e->spi != x->id.spi) ^ e->invert.spi)
++			return 0;
++	}
++	if (e->match.reqid) {
++		if ((e->reqid != x->props.reqid) ^ e->invert.reqid)
++			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 (match_secpath(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-26 17:47:51.000000000 +0200
@@ -0,0 +1,57 @@
+uthor: 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:
+
+	[!] --reqid reqid               Match reqid
+	[!] --spi spi                   Match SPI
+	[!] --proto proto               Match protocol (ah/esp/ipcomp)
+	[!] --mode mode                 Match mode (transport/tunnel)
+	[!] --local addr/mask           Match local tunnel endpoint
+	[!] --remote addr/mask          Match remote tunnel endpoint
+	  --path                        Match path instead of single element at
+	                                any position
+	  --next                        Begin next element in path
+
+
+
+Examples:
+
+	# match everything coming out of an esp tunnel from 
+	# 192.168.0.0/24 to 192.168.0.1
+
+	iptables .. -m secpath --proto esp \
+			       --mode tunnel \
+			       --local 192.168.0.1 \
+			       --remote 192.168.0.0/24
+	
+
+	# match 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 .. -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
+
+
+	# accept everything coming from a specific tunnel. The policy is
+	# given like this:
+
+	spdadd 192.168.0.23/32 192.168.0.1/32 any -P in
+		esp/tunnel/192.168.0.23-192.168.0.1/unique:100
+		ah/transport//unique:100;
+
+	# the iptables rule:
+
+	iptables .. -m secpath --reqid 100 ..
+
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-26 17:45:50.000000000 +0200
@@ -0,0 +1,352 @@
+#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"
+"[!] --reqid reqid		Match reqid\n"
+"[!] --spi spi			Match SPI\n"
+"[!] --proto proto		Match protocol (ah/esp/ipcomp)\n"
+"[!] --mode mode 		Match mode (transport/tunnel)\n"
+"[!] --local addr/mask		Match local tunnel endpoint\n"
+"[!] --remote addr/mask		Match remote tunnel endpoint\n"
+"  --path 			Match path instead of single element at\n"
+"				any position\n"
+"  --next 			Begin next element in path\n",
+	IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{
+		.name		= "reqid",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '1',
+	},
+	{
+		.name		= "spi",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '2'
+	},
+	{
+		.name		= "local",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '3'
+	},
+	{
+		.name		= "remote",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '4'
+	},
+	{
+		.name		= "proto",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '5'
+	},
+	{
+		.name		= "mode",
+		.has_arg	= 1,
+		.flag		= 0,
+		.val		= '6'
+	},
+	{
+		.name		= "path",
+		.has_arg	= 0,
+		.flag		= 0,
+		.val		= '7'
+	},
+	{
+		.name		= "next",
+		.has_arg	= 0,
+		.flag		= 0,
+		.val		= '8'
+	},
+	{ 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.reqid)
+			exit_error(PARAMETER_PROBLEM,
+			           "Can't specify --reqid twice");
+
+		e->match.reqid = 1;
+		e->invert.reqid = invert;
+		e->reqid = strtol(argv[optind-1], NULL, 10);
+		break;
+	case '2':
+		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 '3':
+		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 '4':
+		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 '5':
+		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 '6':
+		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 '7':
+		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 '8':
+		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.reqid) {
+		PRINT_INVERT(e->invert.reqid);
+		printf("%sreqid %u ", prefix, e->reqid);
+	}
+	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-26 17:45:50.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-09-03 11:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-03 11:08 [PATCH][RESEND]: secpath match 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.