netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] TCPOPTSTRIP target
@ 2007-09-28  6:56 Sven Schnelle
  2007-09-28 14:16 ` Jan Engelhardt
  0 siblings, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-09-28  6:56 UTC (permalink / raw)
  To: netfilter-devel


[-- Attachment #1.1: Type: text/plain, Size: 399 bytes --]

Hi,

i stumbled across a sitiuation where i had to strip of a specific TCP
option from the TCP Header. As i've found no target in current xtables,
i wrote an TCPOPTSTRIP target, that does this.

Maybe this is useful for others (or for integration in the current
xtables) i'm attaching it to this mail. Comments?

Cheers,

Sven.

-- 
Signed-Of-By: Sven Schnelle <svens@bitebene.org>


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: iptables-tcpoptstrip.diff --]
[-- Type: text/x-diff, Size: 4474 bytes --]

Index: extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- extensions/libxt_TCPOPTSTRIP.c	(revision 0)
+++ extensions/libxt_TCPOPTSTRIP.c	(revision 0)
@@ -0,0 +1,120 @@
+/* Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ *
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+struct optinfo {
+	struct xt_entry_target t;
+	struct xt_tcpoptstrip_info option;
+};
+
+/* Function which prints out usage message. */
+static void help(void)
+{
+    printf("TCPOPTSTRIP target options:\n"
+	   "  --strip-tcp-option value      strip tcp option 'value' from TCP Header\n");
+}
+
+static const struct option opts[] = {
+	{ "strip-tcp-option", 1, NULL, '1' },
+	{ }
+};
+
+/* Initialize the target. */
+static void init(struct xt_entry_target *t)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+      const void *entry, struct xt_entry_target **target)
+{
+    struct xt_tcpoptstrip_info *optinfo
+	= (struct xt_tcpoptstrip_info *)(*target)->data;
+
+	switch (c) {
+		unsigned int option;
+
+	case '1':
+	    if (string_to_number(optarg, 0, 255, &option) == -1)
+		exit_error(PARAMETER_PROBLEM, "Bad TCPOPTSTRIP value `%s'", optarg);
+	    optinfo->tcpoption = option;
+	    *flags = 1;
+	    break;
+
+	default:
+	    return 0;
+	}
+
+	return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+    if (!flags)
+	exit_error(PARAMETER_PROBLEM,
+		   "TCPOPTSTRIP target: At least one parameter is required");
+}
+
+/* Prints out the targinfo. */
+static void print(const void *ip,const struct xt_entry_target *target,
+      int numeric)
+{
+	const struct xt_tcpoptstrip_info *optinfo =
+		(const struct xt_tcpoptstrip_info *)target->data;
+	printf("TCPOPTSTRIP option %u ", optinfo->tcpoption);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void save(const void *ip, const struct xt_entry_target *target)
+{
+    const struct xt_tcpoptstrip_info *optinfo =
+	(const struct xt_tcpoptstrip_info *)target->data;
+
+    printf("--strip-tcp-option %u ", optinfo->tcpoption);
+}
+
+static struct xtables_target tcpopt = {
+	.family		= AF_INET,
+	.name		= "TCPOPTSTRIP",
+	.version	= IPTABLES_VERSION,
+	.size		= XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+	.help		= &help,
+	.init		= &init,
+	.parse		= &parse,
+	.final_check	= &final_check,
+	.print		= &print,
+	.save		= &save,
+	.extra_opts	= opts
+};
+
+static struct xtables_target tcpopt6 = {
+	.family		= AF_INET6,
+	.name		= "TCPOPTSTRIP",
+	.version	= IPTABLES_VERSION,
+	.size		= XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+	.help		= &help,
+	.init		= &init,
+	.parse		= &parse,
+	.final_check	= &final_check,
+	.print		= &print,
+	.save		= &save,
+	.extra_opts	= opts
+};
+
+void _init(void)
+{
+    xtables_register_target(&tcpopt);
+    xtables_register_target(&tcpopt6);
+}
Index: extensions/Makefile
===================================================================
--- extensions/Makefile	(revision 7050)
+++ extensions/Makefile	(working copy)
@@ -7,7 +7,7 @@
 #
 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
+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 TCPOPTSTRIP
 
 PF_EXT_SELINUX_SLIB:=
 PF6_EXT_SELINUX_SLIB:=

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: xtables-tcpoptstrip.diff --]
[-- Type: text/x-diff, Size: 6672 bytes --]

diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
new file mode 100644
index 0000000..97678e8
--- /dev/null
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,9 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+struct xt_tcpoptstrip_info {
+	int tcpoption;
+};
+
+
+#endif /* _XT_TCPOPTSTRIP_H */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3599770..44c6e17 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -411,6 +411,13 @@ config NETFILTER_XT_TARGET_TCPMSS
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_TCPOPTSTRIP
+	tristate '"TCPOPTSTRIP" target support'
+	depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
+	---help---
+	  This option adds a `TCPOPTSTRIP' target, which allows you to strip
+	  a specific tcp option from TCP packets.
+
 config NETFILTER_XT_MATCH_COMMENT
 	tristate  '"comment" match support'
 	depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 0c054bf..fe5ac6e 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
 
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
new file mode 100644
index 0000000..c3c1420
--- /dev/null
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,170 @@
+/*
+ * This is a module which is used for stripping a specific tcp option 
+ * from TCP packets.
+ *
+ * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org>
+ *
+ * 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/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>");
+MODULE_DESCRIPTION("x_tables TCPOPTSTRIP module");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSRIP");
+
+static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
+{
+	/* Beware zero-length options: make finite progress */
+	if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
+		return 1;
+	else
+		return opt[offset+1];
+}
+
+static void fast_csum(__sum16 *csum,
+		      const u8 *optr,
+		      const u8 *nptr,
+		      const int offset)
+{
+	u8 s[4];
+
+	if (offset & 1) {
+		s[0] = s[2] = 0;
+		s[1] = ~*optr;
+		s[3] = *nptr;
+	} else {
+		s[1] = s[3] = 0;
+		s[0] = ~*optr;
+		s[2] = *nptr;
+	}
+
+	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
+}
+
+
+static int tcpoptstrip_mangle_packet(struct sk_buff **pskb, const void *info,
+				    unsigned int tcphoff, unsigned int minlen)
+{
+    struct xt_tcpoptstrip_info *tinfo = (struct xt_tcpoptstrip_info *)info;
+    struct tcphdr *tcph;
+    const u8 newopt = TCPOPT_NOP;
+    unsigned int optl, tcplen, i,j;
+    u8 *opt;
+
+    if (!skb_make_writable(pskb, (*pskb)->len))
+	return -1;
+
+    tcplen = (*pskb)->len - tcphoff;
+    tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+
+    if (tcplen != tcph->doff*4 && net_ratelimit()) {
+	printk(KERN_ERR "xt_TCPOPTSTRIP: bad length (%u bytes)\n", (*pskb)->len);
+	return -1;
+    }
+
+    opt = (u_int8_t *)tcph;
+
+    for(i = sizeof(struct tcphdr); i < tcph->doff*4; i += optl) {
+	optl = optlen(opt, i);
+
+	if(optl + i > tcph->doff*4)
+	    break;
+
+	if (opt[i] == tinfo->tcpoption) {
+	    for(j = 0; j < optl; j++)
+		fast_csum(&tcph->check, opt+i+j, &newopt, i+j);
+	    if(optl & 1)
+		fast_csum(&tcph->check, &newopt, &newopt, i+j);
+	    memset(opt+i, newopt, optl);
+	    break;
+	}
+    }
+    return 0;
+}
+
+static unsigned int xt_tcpoptstrip_target4(struct sk_buff **pskb,
+		  const struct net_device *in, const struct net_device *out,
+		  unsigned int hooknum, const struct xt_target *target, const void *targinfo)
+{
+    struct iphdr *iph = ip_hdr(*pskb);
+
+
+    tcpoptstrip_mangle_packet(pskb, targinfo, iph->ihl * 4,
+			     sizeof(*iph) + sizeof(struct tcphdr));
+    return XT_CONTINUE;
+}
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+static unsigned int
+xt_tcpoptstrip_target6(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out,
+		  unsigned int hooknum, const struct xt_target *target, const void *targinfo)
+{
+    struct ipv6hdr *ipv6h = ipv6_hdr(*pskb);
+    u8 nexthdr;
+    int tcphoff;
+
+    nexthdr = ipv6h->nexthdr;
+    tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+    if (tcphoff < 0) {
+	WARN_ON(1);
+	return NF_DROP;
+    }
+
+    tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+			     sizeof(*ipv6h) + sizeof(struct tcphdr));
+    return XT_CONTINUE;
+}
+#endif
+
+static struct xt_target xt_tcpoptstrip_reg[] __read_mostly = {
+    {
+	.family		= AF_INET,
+	.name		= "TCPOPTSTRIP",
+	.target		= xt_tcpoptstrip_target4,
+	.targetsize	= sizeof(struct xt_tcpoptstrip_info),
+	.proto		= IPPROTO_TCP,
+	.table          = "mangle",
+	.me		= THIS_MODULE,
+    },
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+    {
+	.family		= AF_INET6,
+	.name		= "TCPOPTSTRIP",
+	.target		= xt_tcpoptstrip_target6,
+	.targetsize	= sizeof(struct xt_tcpoptstrip_info),
+	.proto		= IPPROTO_TCP,
+	.table          = "mangle",
+	.me		= THIS_MODULE,
+    },
+#endif
+};
+
+static int __init xt_tcpoptstrip_init(void)
+{
+    return xt_register_targets(xt_tcpoptstrip_reg, ARRAY_SIZE(xt_tcpoptstrip_reg));
+}
+
+static void __exit xt_tcpoptstrip_fini(void)
+{
+    xt_unregister_targets(xt_tcpoptstrip_reg, ARRAY_SIZE(xt_tcpoptstrip_reg));
+}
+
+module_init(xt_tcpoptstrip_init);
+module_exit(xt_tcpoptstrip_fini);

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

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

end of thread, other threads:[~2007-10-08 16:42 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-28  6:56 [RFC] TCPOPTSTRIP target Sven Schnelle
2007-09-28 14:16 ` Jan Engelhardt
2007-09-28 14:44   ` Jan Engelhardt
2007-09-28 14:57     ` Jan Engelhardt
2007-09-28 15:02     ` Patrick McHardy
2007-09-28 15:33       ` Jan Engelhardt
2007-09-28 15:34         ` Jan Engelhardt
2007-09-28 15:44         ` Patrick McHardy
2007-09-28 16:04           ` Jan Engelhardt
2007-09-28 16:07             ` Patrick McHardy
2007-09-29  9:04       ` Sven Schnelle
2007-09-29  9:16         ` Jan Engelhardt
2007-09-29 14:33         ` Patrick McHardy
2007-09-29 17:23         ` Krzysztof Oledzki
2007-10-02 14:09         ` Sven Schnelle
2007-10-02 17:32           ` [RFC] TCPOPTSTRIP target (netfilter) Jan Engelhardt
2007-10-02 17:56             ` Krzysztof Oledzki
2007-10-02 17:57               ` Jan Engelhardt
2007-10-02 18:01                 ` Jan Engelhardt
2007-10-04  5:04             ` Patrick McHardy
2007-10-02 14:09         ` [RFC] TCPOPTSTRIP target Sven Schnelle
2007-10-02 14:20           ` Sven Schnelle
2007-10-02 17:49             ` Krzysztof Oledzki
2007-10-02 17:51             ` [RFC] TCPOPTSTRIP target (iptables) Jan Engelhardt
2007-10-06 14:10               ` Sven Schnelle
2007-10-06 14:33                 ` Jan Engelhardt
2007-10-06 14:53                   ` Sven Schnelle
2007-10-06 15:00                   ` [PATCH] xt_TCPOPTSTRIP 20071006 (kernel) Jan Engelhardt
2007-10-06 15:19                     ` Sven Schnelle
2007-10-06 15:21                       ` Jan Engelhardt
2007-10-08  5:05                         ` Patrick McHardy
2007-10-08  5:00                     ` Patrick McHardy
2007-10-08  7:58                       ` Sven Schnelle
2007-10-08  8:20                         ` Patrick McHardy
2007-10-08 15:55                       ` Jan Engelhardt
2007-10-08 16:27                         ` Patrick McHardy
2007-10-08 16:42                           ` Jan Engelhardt
2007-10-06 15:01                   ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Jan Engelhardt
2007-10-06 15:37                     ` Krzysztof Oledzki
2007-10-06 15:52                       ` [PATCH 1/1] TCPOPTSTRIP 20071006 descriptions (iptables) Jan Engelhardt
2007-10-08  8:22                     ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Patrick McHardy
2007-09-29  9:05     ` [RFC] TCPOPTSTRIP target Sven Schnelle
2007-10-02 17:22   ` Sven Schnelle
2007-10-02 17:31     ` Jan Engelhardt

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).