All of lore.kernel.org
 help / color / mirror / Atom feed
* [NETFILTER]: ip6_tables: Support MH match.
@ 2007-01-26  9:53 Yasuyuki KOZAKAI
  2007-01-27 15:34 ` Rémi Denis-Courmont
  0 siblings, 1 reply; 9+ messages in thread
From: Yasuyuki KOZAKAI @ 2007-01-26  9:53 UTC (permalink / raw)
  To: kaber, netfilter-devel; +Cc: usagi-core

[-- Attachment #1: Type: Text/Plain, Size: 6123 bytes --]


Hi, Patrick and all,

This introduces match for Mobility Header (MH) described by Mobile IPv6
specification (RFC3775). User can specify the MH type or its range to be
matched.

MH is defined as extention header in RFC3775, but this patch handles it
as layer 4 protocol header like ICMPv6 header.

The reasons are
- The reason why it's defined as extentin header is mainly for
  'piggy back'. But that feature was not specified in RFC3775 after all.
- No header follow MH. RFC3775 says
	Implementations conforming to this specification SHOULD set
	the payload protocol type to IPPROTO_NONE (59 decimal).  
- Many parts in RFCs assume that it's like layer 4 protocol header.
- Actually Linux IPv6 stack, XFRM, setkey, iproute2... handle it as if
  it's layer4 protocol.

So we concludes people expect to do 'ip6tables -p mh ...', not
'ip6tables -m mh ...'.

Please consider to apply this. If no objection, I'll commit
attached the patch for ip6tables as well.

-- Yasuyuki Kozakai

[NETFILTER]: ip6_tables: Support MH match.

This introduces match for Mobility Header (MH) described by Mobile IPv6
specification (RFC3775). User can specify the MH type or its range to be
matched.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: Yasuyuki Kozakai <kozakai@linux-ipv6.org>
---
 include/linux/netfilter_ipv6/ip6t_mh.h |   15 +++++
 net/ipv6/netfilter/Kconfig             |    8 +++
 net/ipv6/netfilter/Makefile            |    1 +
 net/ipv6/netfilter/ip6t_mh.c           |  108 ++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/include/linux/netfilter_ipv6/ip6t_mh.h b/include/linux/netfilter_ipv6/ip6t_mh.h
new file mode 100644
index 0000000..b9ca9a5
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_mh.h
@@ -0,0 +1,15 @@
+#ifndef _IP6T_MH_H
+#define _IP6T_MH_H
+
+/* MH matching stuff */
+struct ip6t_mh
+{
+	u_int8_t types[2];	/* MH type range */
+	u_int8_t invflags;	/* Inverse flags */
+};
+
+/* Values for "invflags" field in struct ip6t_mh. */
+#define IP6T_MH_INV_TYPE	0x01	/* Invert the sense of type. */
+#define IP6T_MH_INV_MASK	0x01	/* All possible flags. */
+
+#endif /*_IP6T_MH_H*/
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index adcd613..cd549ae 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -114,6 +114,14 @@ config IP6_NF_MATCH_AH
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_MH
+	tristate "MH match support"
+	depends on IP6_NF_IPTABLES
+	help
+	  This module allows one to match MH packets.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP6_NF_MATCH_EUI64
 	tristate "EUI64 address check"
 	depends on IP6_NF_IPTABLES
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index ac1dfeb..4513eab 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
+obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
 
 # objects for l3 independent conntrack
 nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
new file mode 100644
index 0000000..2c7efc6
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * 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.
+ *
+ * Author:
+ *	Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on net/netfilter/xt_tcpudp.c
+ *
+ */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <net/mip6.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+MODULE_DESCRIPTION("ip6t_tables match for MH");
+MODULE_LICENSE("GPL");
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the type is matched by the range, 0 otherwise */
+static inline int
+type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert)
+{
+	int ret;
+
+	ret = (type >= min && type <= max) ^ invert;
+	return ret;
+}
+
+static int
+match(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,
+	 int *hotdrop)
+{
+	struct ip6_mh _mh, *mh;
+	const struct ip6t_mh *mhinfo = matchinfo;
+
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh);
+	if (mh == NULL) {
+		/* We've been asked to examine this packet, and we
+		   can't.  Hence, no choice but to drop. */
+		duprintf("Dropping evil MH tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
+			  !!(mhinfo->invflags & IP6T_MH_INV_TYPE));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+mh_checkentry(const char *tablename,
+	      const void *entry,
+	      const struct xt_match *match,
+	      void *matchinfo,
+	      unsigned int hook_mask)
+{
+	const struct ip6t_mh *mhinfo = matchinfo;
+
+	/* Must specify no unknown invflags */
+	return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static struct xt_match mh_match = {
+	.name		= "mh",
+	.family		= AF_INET6,
+	.checkentry	= mh_checkentry,
+	.match		= match,
+	.matchsize	= sizeof(struct ip6t_mh),
+	.proto		= IPPROTO_MH,
+	.me		= THIS_MODULE,
+};
+
+static int __init ip6t_mh_init(void)
+{
+	return xt_register_match(&mh_match);
+}
+
+static void __exit ip6t_mh_fini(void)
+{
+	xt_unregister_match(&mh_match);
+}
+
+module_init(ip6t_mh_init);
+module_exit(ip6t_mh_fini);
-- 
1.4.4


[-- Attachment #2: 0001-add-support-to-Mobility-Header-match-to-ip6tables.txt --]
[-- Type: Text/Plain, Size: 14357 bytes --]

add support for Mobility Header match to ip6tables

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: Yasuyuki Kozakai <kozakai@linux-ipv6.org>
---
 extensions/.mh-test6      |    2 +
 extensions/libip6t_mh.c   |  252 +++++++++++++++++++++++++++++++++++++++++++++
 extensions/libip6t_mh.man |   12 ++
 ip6tables.c               |    5 +
 libip6t_mh.c              |  252 +++++++++++++++++++++++++++++++++++++++++++++
 libip6t_mh.man            |   12 ++
 6 files changed, 535 insertions(+), 0 deletions(-)

diff --git a/extensions/.mh-test6 b/extensions/.mh-test6
new file mode 100755
index 0000000..1142096
--- /dev/null
+++ b/extensions/.mh-test6
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_mh.h ] && echo mh
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
new file mode 100644
index 0000000..2475b4d
--- /dev/null
+++ b/extensions/libip6t_mh.c
@@ -0,0 +1,252 @@
+/* Shared library add-on to ip6tables to add mobility header support. */
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * 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.
+ *
+ * Author:
+ *	Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on libip6t_{icmpv6,udp}.c
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+struct mh_name {
+	const char *name;
+	u_int8_t type;
+};
+
+static const struct mh_name mh_names[] = {
+	{ "binding-refresh-request", 0, },
+	/* Alias */ { "brr", 0, },
+	{ "home-test-init", 1, },
+	/* Alias */ { "hoti", 1, },
+	{ "careof-test-init", 2, },
+	/* Alias */ { "coti", 2, },
+	{ "home-test", 3, },
+	/* Alias */ { "hot", 3, },
+	{ "careof-test", 4, },
+	/* Alias */ { "cot", 4, },
+	{ "binding-update", 5, },
+	/* Alias */ { "bu", 5, },
+	{ "binding-acknowledgement", 6, },
+	/* Alias */ { "ba", 6, },
+	{ "binding-error", 7, },
+	/* Alias */ { "be", 7, },
+};
+
+static void print_types_all(void)
+{
+	unsigned int i;
+	printf("Valid MH types:");
+
+	for (i = 0; i < sizeof(mh_names)/sizeof(struct mh_name); i++) {
+		if (i && mh_names[i].type == mh_names[i-1].type)
+			printf(" (%s)", mh_names[i].name);
+		else
+			printf("\n%s", mh_names[i].name);
+	}
+	printf("\n");
+}
+
+static void help(void)
+{
+	printf(
+"MH v%s options:\n"
+" --mh-type [!] type[:type]	match mh type\n",
+IPTABLES_VERSION);
+	print_types_all();
+}
+
+static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+	struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
+
+	mhinfo->types[1] = 0xFF;
+}
+
+static unsigned int name_to_type(const char *name)
+{
+	int namelen = strlen(name);
+	unsigned int limit = sizeof(mh_names)/sizeof(struct mh_name);
+	unsigned int match = limit;
+	unsigned int i;
+
+	for (i = 0; i < limit; i++) {
+		if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
+			int len = strlen(mh_names[i].name);
+			if (match == limit || len == namelen)
+				match = i;
+		}
+	}
+
+	if (match != limit) {
+		return mh_names[match].type;
+	} else {
+		unsigned int number;
+
+		if (string_to_number(name, 0, 255, &number) == -1)
+			exit_error(PARAMETER_PROBLEM,
+				   "Invalid MH type `%s'\n", name);
+		return number;
+	}
+}
+
+static void parse_mh_types(const char *mhtype, u_int8_t *types)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(mhtype);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		types[0] = types[1] = name_to_type(buffer);
+	else {
+		*cp = '\0';
+		cp++;
+
+		types[0] = buffer[0] ? name_to_type(buffer) : 0;
+		types[1] = cp[0] ? name_to_type(cp) : 0xFF;
+
+		if (types[0] > types[1])
+			exit_error(PARAMETER_PROBLEM,
+				   "Invalid MH type range (min > max)");
+	}
+	free(buffer);
+}
+
+#define MH_TYPES 0x01
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+		 const struct ip6t_entry *entry,
+		 unsigned int *nfcache,
+		 struct ip6t_entry_match **match)
+{
+	struct ip6t_mh *mhinfo = (struct ip6t_mh *)(*match)->data;
+
+	switch (c) {
+	case '1':
+		if (*flags & MH_TYPES)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--mh-type' allowed");
+		check_inverse(optarg, &invert, &optind, 0);
+		parse_mh_types(argv[optind-1], mhinfo->types);
+		if (invert)
+			mhinfo->invflags |= IP6T_MH_INV_TYPE;
+		*flags |= MH_TYPES;
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Final check; we don't care. */
+static void final_check(unsigned int flags)
+{
+}
+
+static const char *type_to_name(u_int8_t type)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(mh_names)/sizeof(struct mh_name); i++) {
+		if (mh_names[i].type == type)
+			return mh_names[i].name;
+	}
+
+	return NULL;
+}
+
+static void print_type(u_int8_t type, int numeric)
+{
+	const char *name;
+	if (numeric || !(name = type_to_name(type)))
+		printf("%u", type);
+	else
+		printf("%s", name);
+}
+
+static void print_types(u_int8_t min, u_int8_t max, int invert, int numeric)
+{
+	const char *inv = invert ? "!" : "";
+
+	if (min != 0 || max != 0xFF || invert) {
+		if (min == max) {
+			printf("%s", inv);
+			print_type(min, numeric);
+		} else {
+			printf("%s", inv);
+			print_type(min, numeric);
+			printf(":");
+			print_type(max, numeric);
+		}
+		printf(" ");
+	}
+}
+
+static void print(const struct ip6t_ip6 *ip,
+		  const struct ip6t_entry_match *match,
+		  int numeric)
+{
+	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+	printf("mh ");
+	print_types(mhinfo->types[0], mhinfo->types[1],
+		    mhinfo->invflags & IP6T_MH_INV_TYPE,
+		    numeric);
+	if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
+		printf("Unknown invflags: 0x%X ",
+		       mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static void save(const struct ip6t_ip6 *ip,
+		 const struct ip6t_entry_match *match)
+{
+	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+	if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
+		return;
+
+	if (mhinfo->invflags & IP6T_MH_INV_TYPE)
+		printf("! ");
+
+	if (mhinfo->types[0] != mhinfo->types[1])
+		printf("--mh-type %u:%u ", mhinfo->types[0], mhinfo->types[1]);
+	else
+		printf("--mh-type %u ", mhinfo->types[0]);
+}
+
+static struct option opts[] = {
+	{ "mh-type", 1, 0, '1' },
+	{0}
+};
+
+static struct ip6tables_match mh = {
+	.name		= "mh",
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct ip6t_mh)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_mh)),
+	.help		= &help,
+	.init		= &init,
+	.parse		= &parse,
+	.final_check	= &final_check,
+	.print		= &print,
+	.save		= &save,
+	.extra_opts	= opts,
+};
+
+void _init(void)
+{
+	register_match6(&mh);
+}
diff --git a/extensions/libip6t_mh.man b/extensions/libip6t_mh.man
new file mode 100644
index 0000000..14f1c64
--- /dev/null
+++ b/extensions/libip6t_mh.man
@@ -0,0 +1,12 @@
+This extension is loaded if `--protocol ipv6-mh' or `--protocol mh' is
+specified. It provides the following option:
+.TP
+.BR "--mh-type " "[!] \fItype\fP[:\fItype\fP]"
+This allows specification of the Mobility Header(MH) type, which can be
+a numeric MH
+.IR type ,
+.IR type
+or one of the MH type names shown by the command
+.nf
+ ip6tables -p ipv6-mh -h
+.fi
diff --git a/ip6tables.c b/ip6tables.c
index 211b81a..ebdaa62 100644
--- a/ip6tables.c
+++ b/ip6tables.c
@@ -219,6 +219,9 @@ struct pprot {
 #define IPPROTO_AH 51
 #endif
 #endif
+#ifndef IPPROTO_MH
+#define IPPROTO_MH 135
+#endif
 
 static const struct pprot chain_protos[] = {
 	{ "tcp", IPPROTO_TCP },
@@ -228,6 +231,8 @@ static const struct pprot chain_protos[]
 	{ "ipv6-icmp", IPPROTO_ICMPV6 },
 	{ "esp", IPPROTO_ESP },
 	{ "ah", IPPROTO_AH },
+	{ "ipv6-mh", IPPROTO_MH },
+	{ "mh", IPPROTO_MH },
 };
 
 static char *
diff --git a/libip6t_mh.c b/libip6t_mh.c
new file mode 100644
index 0000000..7cdfaf1
--- /dev/null
+++ b/libip6t_mh.c
@@ -0,0 +1,252 @@
+/* Shared library add-on to ip6tables to add mobility header support. */
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * 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.
+ *
+ * Author:
+ *	Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on libip6t_{icmpv6,udp}.c
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+struct mh_name {
+	const char *name;
+	u_int8_t type;
+};
+
+static const struct mh_name mh_names[] = {
+	{ "binding-refresh-request", 0, },
+	/* Alias */ { "brr", 0, },
+	{ "home-test-init", 1, },
+	/* Alias */ { "hoti", 1, },
+	{ "careof-test-init", 2, },
+	/* Alias */ { "coti", 2, },
+	{ "home-test", 3, },
+	/* Alias */ { "hot", 3, },
+	{ "careof-test", 4, },
+	/* Alias */ { "cot", 4, },
+	{ "binding-update", 5, },
+	/* Alias */ { "bu", 5, },
+	{ "binding-acknowledgement", 6, },
+	/* Alias */ { "ba", 6, },
+	{ "binding-error", 7, },
+	/* Alias */ { "be", 7 },
+};
+
+static void print_types_all(void)
+{
+	unsigned int i;
+	printf("Valid MH types:");
+
+	for (i = sizeof(mh_names)/sizeof(struct mh_name) - 1; i >= 0; i--) {
+		if (i && mh_names[i].type == mh_names[i-1].type)
+			printf(" (%s)", mh_names[i].name);
+		else
+			printf("\n%s", mh_names[i].name);
+	}
+	printf("\n");
+}
+
+static void help(void)
+{
+	printf(
+"MH v%s options:\n"
+" --mh-type [!] type[:type]	match mh type\n",
+IPTABLES_VERSION);
+	print_types_all();
+}
+
+static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+	struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
+
+	mhinfo->types[1] = 0xFF;
+}
+
+static unsigned int name_to_type(const char *name)
+{
+	int namelen = strlen(name);
+	unsigned int limit = sizeof(mh_names)/sizeof(struct mh_name);
+	unsigned int match = limit;
+	unsigned int i;
+
+	for (i = 0; i < limit; i++) {
+		if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
+			int len = strlen(mh_names[i].name);
+			if (match == limit || len == namelen)
+				match = i;
+		}
+	}
+
+	if (match != limit) {
+		return mh_names[match].type;
+	} else {
+		unsigned int number;
+
+		if (string_to_number(name, 0, 255, &number) == -1)
+			exit_error(PARAMETER_PROBLEM,
+				   "Invalid MH type `%s'\n", name);
+		return number;
+	}
+}
+
+static void parse_mh_types(const char *mhtype, u_int8_t *types)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(mhtype);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		types[0] = types[1] = name_to_type(buffer);
+	else {
+		*cp = '\0';
+		cp++;
+
+		types[0] = buffer[0] ? name_to_type(buffer) : 0;
+		types[1] = cp[0] ? name_to_type(cp) : 0xFF;
+
+		if (types[0] > types[1])
+			exit_error(PARAMETER_PROBLEM,
+				   "Invalid MH type range (min > max)");
+	}
+	free(buffer);
+}
+
+#define MH_TYPES 0x01
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+		 const struct ip6t_entry *entry,
+		 unsigned int *nfcache,
+		 struct ip6t_entry_match **match)
+{
+	struct ip6t_mh *mhinfo = (struct ip6t_mh *)(*match)->data;
+
+	switch (c) {
+	case '1':
+		if (*flags & MH_TYPES)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--mh-type' allowed");
+		check_inverse(optarg, &invert, &optind, 0);
+		parse_mh_types(argv[optind-1], mhinfo->types);
+		if (invert)
+			mhinfo->invflags |= IP6T_MH_INV_TYPE;
+		*flags |= MH_TYPES;
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Final check; we don't care. */
+static void final_check(unsigned int flags)
+{
+}
+
+static const char *type_to_name(u_int8_t type)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(mh_names)/sizeof(struct mh_name); i++) {
+		if (mh_names[i].type == type)
+			return mh_names[i].name;
+	}
+
+	return NULL;
+}
+
+static void print_type(u_int8_t type, int numeric)
+{
+	const char *name;
+	if (numeric || !(name = type_to_name(type)))
+		printf("%u", type);
+	else
+		printf("%s", name);
+}
+
+static void print_types(u_int8_t min, u_int8_t max, int invert, int numeric)
+{
+	const char *inv = invert ? "!" : "";
+
+	if (min != 0 || max != 0xFF || invert) {
+		if (min == max) {
+			printf("%s", inv);
+			print_type(min, numeric);
+		} else {
+			printf("%s", inv);
+			print_type(min, numeric);
+			printf(":");
+			print_type(max, numeric);
+		}
+		printf(" ");
+	}
+}
+
+static void print(const struct ip6t_ip6 *ip,
+		  const struct ip6t_entry_match *match,
+		  int numeric)
+{
+	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+	printf("mh ");
+	print_types(mhinfo->types[0], mhinfo->types[1],
+		    mhinfo->invflags & IP6T_MH_INV_TYPE,
+		    numeric);
+	if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
+		printf("Unknown invflags: 0x%X ",
+		       mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static void save(const struct ip6t_ip6 *ip,
+		 const struct ip6t_entry_match *match)
+{
+	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+	if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
+		return;
+
+	if (mhinfo->invflags & IP6T_MH_INV_TYPE)
+		printf("! ");
+
+	if (mhinfo->types[0] != mhinfo->types[1])
+		printf("--mh-type %u:%u ", mhinfo->types[0], mhinfo->types[1]);
+	else
+		printf("--mh-type %u ", mhinfo->types[0]);
+}
+
+static struct option opts[] = {
+	{ "mh-type", 1, 0, '1' },
+	{0}
+};
+
+static struct ip6tables_match mh = {
+	.name		= "mh",
+	.version	= IPTABLES_VERSION,
+	.size		= IP6T_ALIGN(sizeof(struct ip6t_mh)),
+	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_mh)),
+	.help		= &help,
+	.init		= &init,
+	.parse		= &parse,
+	.final_check	= &final_check,
+	.print		= &print,
+	.save		= &save,
+	.extra_opts	= opts,
+};
+
+void _init(void)
+{
+	register_match6(&mh);
+}
diff --git a/libip6t_mh.man b/libip6t_mh.man
new file mode 100644
index 0000000..14f1c64
--- /dev/null
+++ b/libip6t_mh.man
@@ -0,0 +1,12 @@
+This extension is loaded if `--protocol ipv6-mh' or `--protocol mh' is
+specified. It provides the following option:
+.TP
+.BR "--mh-type " "[!] \fItype\fP[:\fItype\fP]"
+This allows specification of the Mobility Header(MH) type, which can be
+a numeric MH
+.IR type ,
+.IR type
+or one of the MH type names shown by the command
+.nf
+ ip6tables -p ipv6-mh -h
+.fi
-- 
1.4.4


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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-01-26  9:53 [NETFILTER]: ip6_tables: Support MH match Yasuyuki KOZAKAI
@ 2007-01-27 15:34 ` Rémi Denis-Courmont
       [not found]   ` <200701290507.l0T57mwf015698@toshiba.co.jp>
  2007-02-01  1:41   ` Yasuyuki KOZAKAI
  0 siblings, 2 replies; 9+ messages in thread
From: Rémi Denis-Courmont @ 2007-01-27 15:34 UTC (permalink / raw)
  To: netfilter-devel, Yasuyuki KOZAKAI

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

	Hello,

Le vendredi 26 janvier 2007 11:53, Yasuyuki KOZAKAI a écrit :
> MH is defined as extention header in RFC3775, but this patch handles
> it as layer 4 protocol header like ICMPv6 header.
>
> The reasons are
> - The reason why it's defined as extentin header is mainly for
>   'piggy back'. But that feature was not specified in RFC3775 after
> all. - No header follow MH. RFC3775 says
> 	Implementations conforming to this specification SHOULD set
> 	the payload protocol type to IPPROTO_NONE (59 decimal).

What happens if a node (including a non-Linux one) receives a MH packet 
with a non-none next protocol? I might be wrong, but I would assume it 
parses it, at least in some cases.

If this is trye, this patch might introduce a trivial way to evade 
firewall rules, as firewall admins will assume the next protocol is 
none, while it might not be.

Of course, I could be plain wrong, since I do not know MH.

> - Many parts in RFCs assume that it's like layer 4 protocol header.
> - Actually Linux IPv6 stack, XFRM, setkey, iproute2... handle it as
> if it's layer4 protocol.

Slightly off-topic, but anyway, what about socket() syscall - can you 
create a IPPROTO_MH raw socket with it?

-- 
Rémi Denis-Courmont
http://www.remlab.net/

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
       [not found]   ` <200701290507.l0T57mwf015698@toshiba.co.jp>
@ 2007-01-30  4:23     ` Masahide NAKAMURA
  0 siblings, 0 replies; 9+ messages in thread
From: Masahide NAKAMURA @ 2007-01-30  4:23 UTC (permalink / raw)
  To: rdenis; +Cc: netfilter-devel, usagi-core, Yasuyuki KOZAKAI

Hello,

When you reply, can you include my address because I've not subscribed the
netfilter-devel list?

Please find my answer inline.

 > From: Remi Denis-Courmont <rdenis@simphalempin.com>
 > > Date: Sat, 27 Jan 2007 17:34:42 +0200
 > >
 >> > > 	Hello,
 >> > >
 >> > > Le vendredi 26 janvier 2007 11:53, Yasuyuki KOZAKAI a ecrit :
 >>> > > > MH is defined as extention header in RFC3775, but this patch handles
 >>> > > > it as layer 4 protocol header like ICMPv6 header.
 >>> > > >
 >>> > > > The reasons are
 >>> > > > - The reason why it's defined as extentin header is mainly for
 >>> > > >   'piggy back'. But that feature was not specified in RFC3775 after
 >>> > > > all. - No header follow MH. RFC3775 says
 >>> > > > 	Implementations conforming to this specification SHOULD set
 >>> > > > 	the payload protocol type to IPPROTO_NONE (59 decimal).
 >> > >
 >> > > What happens if a node (including a non-Linux one) receives a MH packet
 >> > > with a non-none next protocol? I might be wrong, but I would assume it
 >> > > parses it, at least in some cases.

The node will send ICMP parameter problem back with code depending on
whether the node supports MH or not.
If it supports, the code is 0 (erroneous header field) as RFC3775.
Otherwise, the code 1 (unrecognized Next Header).


 >> > > If this is trye, this patch might introduce a trivial way to evade
 >> > > firewall rules, as firewall admins will assume the next protocol is
 >> > > none, while it might not be.
 >> > >
 >> > > Of course, I could be plain wrong, since I do not know MH.

If the sender creates MH with nexthdr=TCP for example,
it may go through the firewall which is configured even MH=ACCEPT
TCP=DROP. However, the receiver cannot handle it as TCP.

Can I add nexthdr check, or should I rewrite it as "-m" module
to treat MH as an extension header?


 >>> > > > - Many parts in RFCs assume that it's like layer 4 protocol header.
 >>> > > > - Actually Linux IPv6 stack, XFRM, setkey, iproute2... handle it as
 >>> > > > if it's layer4 protocol.
 >> > >
 >> > > Slightly off-topic, but anyway, what about socket() syscall - can you
 >> > > create a IPPROTO_MH raw socket with it?

Yes we can. Actually kernel never originates MH but application
creates MH to send it through the raw socket.


Thanks,


-- 
Masahide NAKAMURA

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-01-27 15:34 ` Rémi Denis-Courmont
       [not found]   ` <200701290507.l0T57mwf015698@toshiba.co.jp>
@ 2007-02-01  1:41   ` Yasuyuki KOZAKAI
  2007-02-02 11:05     ` Jozsef Kadlecsik
  1 sibling, 1 reply; 9+ messages in thread
From: Yasuyuki KOZAKAI @ 2007-02-01  1:41 UTC (permalink / raw)
  To: rdenis; +Cc: nakam, netfilter-devel, yasuyuki.kozakai


Mh, Nakamura-san's reply seems to reach this list.
Then I forward that.

========================================================================

Hello,

When you reply, can you include my address because I've not subscribed the
netfilter-devel list?

Please find my answer inline.

 > From: Remi Denis-Courmont <rdenis@simphalempin.com>
 > > Date: Sat, 27 Jan 2007 17:34:42 +0200
 > >
 >> > > 	Hello,
 >> > >
 >> > > Le vendredi 26 janvier 2007 11:53, Yasuyuki KOZAKAI a ecrit :
 >>> > > > MH is defined as extention header in RFC3775, but this patch handles
 >>> > > > it as layer 4 protocol header like ICMPv6 header.
 >>> > > >
 >>> > > > The reasons are
 >>> > > > - The reason why it's defined as extentin header is mainly for
 >>> > > >   'piggy back'. But that feature was not specified in RFC3775 after
 >>> > > > all. - No header follow MH. RFC3775 says
 >>> > > > 	Implementations conforming to this specification SHOULD set
 >>> > > > 	the payload protocol type to IPPROTO_NONE (59 decimal).
 >> > >
 >> > > What happens if a node (including a non-Linux one) receives a MH packet
 >> > > with a non-none next protocol? I might be wrong, but I would assume it
 >> > > parses it, at least in some cases.

The node will send ICMP parameter problem back with code depending on
whether the node supports MH or not.
If it supports, the code is 0 (erroneous header field) as RFC3775.
Otherwise, the code 1 (unrecognized Next Header).


 >> > > If this is trye, this patch might introduce a trivial way to evade
 >> > > firewall rules, as firewall admins will assume the next protocol is
 >> > > none, while it might not be.
 >> > >
 >> > > Of course, I could be plain wrong, since I do not know MH.

If the sender creates MH with nexthdr=TCP for example,
it may go through the firewall which is configured even MH=ACCEPT
TCP=DROP. However, the receiver cannot handle it as TCP.

Can I add nexthdr check, or should I rewrite it as "-m" module
to treat MH as an extension header?


 >>> > > > - Many parts in RFCs assume that it's like layer 4 protocol header.
 >>> > > > - Actually Linux IPv6 stack, XFRM, setkey, iproute2... handle it as
 >>> > > > if it's layer4 protocol.
 >> > >
 >> > > Slightly off-topic, but anyway, what about socket() syscall - can you
 >> > > create a IPPROTO_MH raw socket with it?

Yes we can. Actually kernel never originates MH but application
creates MH to send it through the raw socket.


Thanks,


-- 
Masahide NAKAMURA

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-02-01  1:41   ` Yasuyuki KOZAKAI
@ 2007-02-02 11:05     ` Jozsef Kadlecsik
  2007-02-09  6:22       ` Masahide NAKAMURA
  0 siblings, 1 reply; 9+ messages in thread
From: Jozsef Kadlecsik @ 2007-02-02 11:05 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: nakam, rdenis, netfilter-devel

Hi,

On Thu, 1 Feb 2007, Yasuyuki KOZAKAI wrote:

> >> > > What happens if a node (including a non-Linux one) receives a MH packet
> >> > > with a non-none next protocol? I might be wrong, but I would assume it
> >> > > parses it, at least in some cases.
>
> The node will send ICMP parameter problem back with code depending on
> whether the node supports MH or not.
> If it supports, the code is 0 (erroneous header field) as RFC3775.
> Otherwise, the code 1 (unrecognized Next Header).
>
>
> >> > > If this is trye, this patch might introduce a trivial way to evade
> >> > > firewall rules, as firewall admins will assume the next protocol is
> >> > > none, while it might not be.
> >> > >
> >> > > Of course, I could be plain wrong, since I do not know MH.
>
> If the sender creates MH with nexthdr=TCP for example,
> it may go through the firewall which is configured even MH=ACCEPT
> TCP=DROP. However, the receiver cannot handle it as TCP.
>
> Can I add nexthdr check, or should I rewrite it as "-m" module
> to treat MH as an extension header?

Personally, I'd prefer a check in the MH match that makes sure there is no 
more header, simply because we cannot assume that the sender keeps the 
rules.

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-02-02 11:05     ` Jozsef Kadlecsik
@ 2007-02-09  6:22       ` Masahide NAKAMURA
  2007-02-10  8:32         ` Masahide NAKAMURA
  0 siblings, 1 reply; 9+ messages in thread
From: Masahide NAKAMURA @ 2007-02-09  6:22 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: nakam, rdenis, netfilter-devel, Yasuyuki KOZAKAI

Hi Jozsef,

# FYI, now I've subscribed the netfilter-devel list.

> > >> > > What happens if a node (including a non-Linux one) receives a MH packet
> > >> > > with a non-none next protocol? I might be wrong, but I would assume it
> > >> > > parses it, at least in some cases.
> >
> > The node will send ICMP parameter problem back with code depending on
> > whether the node supports MH or not.
> > If it supports, the code is 0 (erroneous header field) as RFC3775.
> > Otherwise, the code 1 (unrecognized Next Header).
> >
> >
> > >> > > If this is trye, this patch might introduce a trivial way to evade
> > >> > > firewall rules, as firewall admins will assume the next protocol is
> > >> > > none, while it might not be.
> > >> > >
> > >> > > Of course, I could be plain wrong, since I do not know MH.
> >
> > If the sender creates MH with nexthdr=TCP for example,
> > it may go through the firewall which is configured even MH=ACCEPT
> > TCP=DROP. However, the receiver cannot handle it as TCP.
> >
> > Can I add nexthdr check, or should I rewrite it as "-m" module
> > to treat MH as an extension header?
> 
> Personally, I'd prefer a check in the MH match that makes sure there is no 
> more header, simply because we cannot assume that the sender keeps the 
> rules.

Thanks for your comment.
OK, I'll write additional patch to check no more header.



-- 
Masahide NAKAMURA

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-02-09  6:22       ` Masahide NAKAMURA
@ 2007-02-10  8:32         ` Masahide NAKAMURA
  2007-02-12 10:09           ` Patrick McHardy
  0 siblings, 1 reply; 9+ messages in thread
From: Masahide NAKAMURA @ 2007-02-10  8:32 UTC (permalink / raw)
  To: netfilter-devel; +Cc: rdenis, usagi-core, Yasuyuki KOZAKAI, Jozsef Kadlecsik

Hi,

> > > >> > > What happens if a node (including a non-Linux one) receives a MH packet
> > > >> > > with a non-none next protocol? I might be wrong, but I would assume it
> > > >> > > parses it, at least in some cases.
> > >
> > > The node will send ICMP parameter problem back with code depending on
> > > whether the node supports MH or not.
> > > If it supports, the code is 0 (erroneous header field) as RFC3775.
> > > Otherwise, the code 1 (unrecognized Next Header).
> > >
> > >
> > > >> > > If this is trye, this patch might introduce a trivial way to evade
> > > >> > > firewall rules, as firewall admins will assume the next protocol is
> > > >> > > none, while it might not be.
> > > >> > >
> > > >> > > Of course, I could be plain wrong, since I do not know MH.
> > >
> > > If the sender creates MH with nexthdr=TCP for example,
> > > it may go through the firewall which is configured even MH=ACCEPT
> > > TCP=DROP. However, the receiver cannot handle it as TCP.
> > >
> > > Can I add nexthdr check, or should I rewrite it as "-m" module
> > > to treat MH as an extension header?
> > 
> > Personally, I'd prefer a check in the MH match that makes sure there is no 
> > more header, simply because we cannot assume that the sender keeps the 
> > rules.
> 
> Thanks for your comment.
> OK, I'll write additional patch to check no more header.
> 

Please find my patch (can be applied for net-2.6 tree) below.

Thanks,

-- 
Masahide NAKAMURA


From 457af7826fc1f3ae7e0c7b554b61a002e702a4cb Mon Sep 17 00:00:00 2001
From: Masahide NAKAMURA <nakam@linux-ipv6.org>
Date: Sat, 10 Feb 2007 14:46:05 +0900
Subject: [PATCH] [NETFILTER]: ip6_tables: Drop piggyback payload packet on MH.

Regarding RFC3775, MH payload proto field should be IPPROTO_NONE. Otherwise
it must be discarded (and the receiver should send ICMP error).

We assume filter should drop such piggyback everytime to disallow slipping through
firewall rules, even the final receiver will discard it.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
---
 net/ipv6/netfilter/ip6t_mh.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
index 2c7efc6..c2a9098 100644
--- a/net/ipv6/netfilter/ip6t_mh.c
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -66,6 +66,13 @@ match(const struct sk_buff *skb,
 		return 0;
 	}
 
+	if (mh->ip6mh_proto != IPPROTO_NONE) {
+		duprintf("Dropping invalid MH Payload Proto: %u\n",
+			 mh->ip6mh_proto);
+		*hotdrop = 1;
+		return 0;
+	}
+
 	return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
 			  !!(mhinfo->invflags & IP6T_MH_INV_TYPE));
 }
-- 
1.4.2

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
  2007-02-10  8:32         ` Masahide NAKAMURA
@ 2007-02-12 10:09           ` Patrick McHardy
  0 siblings, 0 replies; 9+ messages in thread
From: Patrick McHardy @ 2007-02-12 10:09 UTC (permalink / raw)
  To: Masahide NAKAMURA
  Cc: rdenis, netfilter-devel, usagi-core, Yasuyuki KOZAKAI, Jozsef Kadlecsik

Masahide NAKAMURA wrote:´
> Please find my patch (can be applied for net-2.6 tree) below.

Applied, thanks Masahide.

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

* Re: [NETFILTER]: ip6_tables: Support MH match.
       [not found] <200701260953.l0Q9rvV8006278@toshiba.co.jp>
@ 2007-01-26 14:26 ` Patrick McHardy
  0 siblings, 0 replies; 9+ messages in thread
From: Patrick McHardy @ 2007-01-26 14:26 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: netfilter-devel, usagi-core

Yasuyuki KOZAKAI wrote:
> Hi, Patrick and all,
> 
> This introduces match for Mobility Header (MH) described by Mobile IPv6
> specification (RFC3775). User can specify the MH type or its range to be
> matched.
> 
> MH is defined as extention header in RFC3775, but this patch handles it
> as layer 4 protocol header like ICMPv6 header.
> 
> The reasons are
> - The reason why it's defined as extentin header is mainly for
>   'piggy back'. But that feature was not specified in RFC3775 after all.
> - No header follow MH. RFC3775 says
> 	Implementations conforming to this specification SHOULD set
> 	the payload protocol type to IPPROTO_NONE (59 decimal).  
> - Many parts in RFCs assume that it's like layer 4 protocol header.
> - Actually Linux IPv6 stack, XFRM, setkey, iproute2... handle it as if
>   it's layer4 protocol.
> 
> So we concludes people expect to do 'ip6tables -p mh ...', not
> 'ip6tables -m mh ...'.
> 
> Please consider to apply this. If no objection, I'll commit
> attached the patch for ip6tables as well.

Looks good, I've queued it for 2.6.21. Thanks.

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

end of thread, other threads:[~2007-02-12 10:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-26  9:53 [NETFILTER]: ip6_tables: Support MH match Yasuyuki KOZAKAI
2007-01-27 15:34 ` Rémi Denis-Courmont
     [not found]   ` <200701290507.l0T57mwf015698@toshiba.co.jp>
2007-01-30  4:23     ` Masahide NAKAMURA
2007-02-01  1:41   ` Yasuyuki KOZAKAI
2007-02-02 11:05     ` Jozsef Kadlecsik
2007-02-09  6:22       ` Masahide NAKAMURA
2007-02-10  8:32         ` Masahide NAKAMURA
2007-02-12 10:09           ` Patrick McHardy
     [not found] <200701260953.l0Q9rvV8006278@toshiba.co.jp>
2007-01-26 14:26 ` 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.