* [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
* Re: [RFC] TCPOPTSTRIP target
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-10-02 17:22 ` Sven Schnelle
0 siblings, 2 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 14:16 UTC (permalink / raw)
To: Sven Schnelle; +Cc: netfilter-devel
On Sep 28 2007 08:56, Sven Schnelle wrote:
>
>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?
>
Send patches preferably inline.
>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.
There is a "IPV4OPTSSTRIP" module in POM-NG.
Perhaps you could call yours TCPOPTSSTRIP? Just a thought,
I am kind of impartial whether it should be two S or one S.
>+struct optinfo {
>+ struct xt_entry_target t;
>+ struct xt_tcpoptstrip_info option;
>+};
Not sure what this is supposed to do.
>+
>+/* 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;
struct xt_tcpoptstrip_info *info = (void *)(*target)->data;
>+ switch (c) {
>+ unsigned int option;
>+
Huh, what's that option doing there? It looks out of place.
>+ 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;
How about allowing to strip multiple TCP options at once?
(Which perhaps then decies whether it is OPTSTRIP or OPTSSTRIP :-)
>+/* 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;
(const void *) makes it shorter and does the same. Try it.
>+ 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
>+};
Better name these tcpoptstrip_help (no need for the &), tcpoptstrip_init,
etc. so these symbols can be unambiguously resolved when attaching gdb.
--- 8< ---
>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;
>+};
Should be a fixed type (uint8_t, uint16_t, uint32_t...etc)
>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)
I do not think the IPv6 splitoff is necessary. Only a few other
(stray?) modules do it and I am not sure why. Take xt_string.c
for example, there is no #ifdef ipv6 or so.
>+#include <linux/netfilter_ipv4/ip_tables.h>
>+#include <linux/netfilter_ipv6/ip6_tables.h>
Not sure, but I think these can go - you have x_tables.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");
"SRIP" seems not quite right.
>+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;
>+}
Try CodingStyle.
>+
>+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);
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 14:16 ` Jan Engelhardt
@ 2007-09-28 14:44 ` Jan Engelhardt
2007-09-28 14:57 ` Jan Engelhardt
` (2 more replies)
2007-10-02 17:22 ` Sven Schnelle
1 sibling, 3 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 14:44 UTC (permalink / raw)
To: Sven Schnelle; +Cc: netfilter-devel
Since I had nothing better to do, I did a cleanup :)
---
include/linux/netfilter/xt_TCPOPTSTRIP.h | 8 +
net/netfilter/Kconfig | 7 +
net/netfilter/Makefile | 1
net/netfilter/xt_TCPOPTSTRIP.c | 155 +++++++++++++++++++++++++++++++
4 files changed, 171 insertions(+)
Index: linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,8 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+struct xt_tcpoptstrip_info {
+ u_int8_t tcpoption;
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
Index: linux-2.6.23/net/netfilter/Kconfig
===================================================================
--- linux-2.6.23.orig/net/netfilter/Kconfig
+++ linux-2.6.23/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
+ ---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
Index: linux-2.6.23/net/netfilter/Makefile
===================================================================
--- linux-2.6.23.orig/net/netfilter/Makefile
+++ linux-2.6.23/net/netfilter/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE)
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
Index: linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,155 @@
+/*
+ * A module 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/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+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 u_int8_t *optr,
+ const u_int8_t *nptr, const int offset)
+{
+ u_int8_t 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 unsigned int
+tcpoptstrip_mangle_packet(struct sk_buff **pskb,
+ const struct xt_tcpoptstrip_info *info,
+ unsigned int tcphoff, unsigned int minlen)
+{
+ const u_int8_t newopt = TCPOPT_NOP;
+ unsigned int optl, tcplen, i, j;
+ struct tcphdr *tcph;
+ u_int8_t *opt;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ tcplen = (*pskb)->len - tcphoff;
+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+
+ if (tcplen != 4 * tcph->doff)
+ return NF_DROP;
+
+ opt = (u_int8_t *)tcph;
+
+ for (i = sizeof(struct tcphdr); i < 4 * tcph->doff; i += optl) {
+ optl = optlen(opt, i);
+
+ if (optl + i > tcph->doff*4)
+ break;
+
+ if (opt[i] == info->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 XT_CONTINUE;
+}
+
+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)
+{
+ return tcpoptstrip_mangle_packet(pskb, targinfo, ip_hdrlen(*pskb),
+ sizeof(struct iphdr) + sizeof(struct tcphdr));
+}
+
+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);
+ unsigned int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+ if (tcphoff < 0)
+ return NF_DROP;
+
+ return tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+
+static struct xt_target tcpoptstrip_reg[] __read_mostly = {
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target4,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target6,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_tcpoptstrip_init(void)
+{
+ return xt_register_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+static void __exit xt_tcpoptstrip_exit(void)
+{
+ xt_unregister_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+module_init(xt_tcpoptstrip_init);
+module_exit(xt_tcpoptstrip_exit);
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>");
+MODULE_DESCRIPTION("x_tables TCPOPTSTRIP module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSTRIP");
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 14:44 ` Jan Engelhardt
@ 2007-09-28 14:57 ` Jan Engelhardt
2007-09-28 15:02 ` Patrick McHardy
2007-09-29 9:05 ` [RFC] TCPOPTSTRIP target Sven Schnelle
2 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 14:57 UTC (permalink / raw)
To: Sven Schnelle; +Cc: netfilter-devel
>Since I had nothing better to do, I did a cleanup :)
iptables part.
---
extensions/Makefile | 2
extensions/libxt_TCPOPTSTRIP.c | 108 +++++++++++++++++++++++++++++++
include/linux/netfilter/xt_TCPOPTSTRIP.h | 8 ++
3 files changed, 117 insertions(+), 1 deletion(-)
Index: iptables/extensions/Makefile
===================================================================
--- iptables.orig/extensions/Makefile
+++ iptables/extensions/Makefile
@@ -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 TCPOPTSTRIP TRACE
PF_EXT_SELINUX_SLIB:=
PF6_EXT_SELINUX_SLIB:=
Index: iptables/extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ iptables/extensions/libxt_TCPOPTSTRIP.c
@@ -0,0 +1,108 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+static void tcpoptstrip_help(void)
+{
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-tcp-option value strip TCP option denoted by \"value\"\n"
+" from TCP header\n");
+}
+
+static const struct option tcpoptstrip_opts[] = {
+ {"strip-tcp-option", true, NULL, '1'},
+ {NULL},
+};
+
+static void tcpoptstrip_init(struct xt_entry_target *t)
+{
+}
+
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_info *info = (void *)(*target)->data;
+ unsigned int option;
+
+ switch (c) {
+ case '1':
+ if (string_to_number(optarg, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM,
+ "Bad TCPOPTSTRIP value \"%s\"", optarg);
+ info->tcpoption = option;
+ *flags |= 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void tcpoptstrip_check(unsigned int flags)
+{
+ if (flags != 1)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: --value is required");
+}
+
+static void tcpoptstrip_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+
+ printf("TCPOPTSTRIP option %u ", info->tcpoption);
+}
+
+static void tcpoptstrip_save(const void *ip,
+ const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+
+ printf("--strip-tcp-option %u ", info->tcpoption);
+}
+
+static struct xtables_target tcpoptstrip_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+static struct xtables_target tcpoptstrip6_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_reg);
+ xtables_register_target(&tcpoptstrip6_reg);
+}
Index: iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,8 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+struct xt_tcpoptstrip_info {
+ u_int8_t tcpoption;
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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-29 9:04 ` Sven Schnelle
2007-09-29 9:05 ` [RFC] TCPOPTSTRIP target Sven Schnelle
2 siblings, 2 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-09-28 15:02 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> Since I had nothing better to do, I did a cleanup :)
Great :) My main question is what the use case of this is.
> @@ -0,0 +1,155 @@
> +/*
> + * A module 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/x_tables.h>
> +#include <linux/netfilter/xt_tcpudp.h>
tcpudp.h? Shouldn't be needed.
> +#include <linux/netfilter/xt_TCPOPTSTRIP.h>
> +
> +static void fast_csum(__sum16 *csum, const u_int8_t *optr,
> + const u_int8_t *nptr, const int offset)
> +{
> + u_int8_t 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)));
> +}
Please use the generic checksumming helpers.
> +
> +static unsigned int
> +tcpoptstrip_mangle_packet(struct sk_buff **pskb,
> + const struct xt_tcpoptstrip_info *info,
> + unsigned int tcphoff, unsigned int minlen)
> +{
> + const u_int8_t newopt = TCPOPT_NOP;
> + unsigned int optl, tcplen, i, j;
> + struct tcphdr *tcph;
> + u_int8_t *opt;
> +
> + if (!skb_make_writable(pskb, (*pskb)->len))
> + return NF_DROP;
> +
> + tcplen = (*pskb)->len - tcphoff;
> + tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
> +
> + if (tcplen != 4 * tcph->doff)
> + return NF_DROP;
Seems to be copied from TCPMSS - but I don't see why you shouldn't allow
stripping options from packets with data.
> +
> + opt = (u_int8_t *)tcph;
> +
> + for (i = sizeof(struct tcphdr); i < 4 * tcph->doff; i += optl) {
> + optl = optlen(opt, i);
> +
> + if (optl + i > tcph->doff*4)
> + break;
> +
> + if (opt[i] == info->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);
For TCPOPTSTRIP I would expect either real stripping or replacement
by TCPOPT_NOP. In which cases does replacement by something else
make sense?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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-29 9:04 ` Sven Schnelle
1 sibling, 2 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 15:33 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Sven Schnelle, netfilter-devel
On Sep 28 2007 17:02, Patrick McHardy wrote:
>
>For TCPOPTSTRIP I would expect either real stripping or replacement
>by TCPOPT_NOP. In which cases does replacement by something else
>make sense?
>
In case sends the layer4, layer3 or layer2 size of a packet in
layer7 data.
Come to think of it, replacing by NOP is needed during
PMTUD where packets have to-be-stripped options.
Consider a three-machine setup with sender, iptables and receiver,
connected through MTU=1500 Ethernet. Assume a hypothethical TCP SYN
packet with lots of strip-me options that totals up at 2000 bytes.
Because of -j TCPOPTSTRIP, the packet will be reduced to, say, 80
bytes. The packet will pass, and the receiving end will confirm the
SYN. Now, the sending side believes the minimum MTU is 1600, since
its initial SYN was successfully replied to with SYN ACK. => Problem.
Makes sense?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 15:33 ` Jan Engelhardt
@ 2007-09-28 15:34 ` Jan Engelhardt
2007-09-28 15:44 ` Patrick McHardy
1 sibling, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 15:34 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Sven Schnelle, netfilter-devel
On Sep 28 2007 17:33, Jan Engelhardt wrote:
>>
>>For TCPOPTSTRIP I would expect either real stripping or replacement
>>by TCPOPT_NOP. In which cases does replacement by something else
>>make sense?
>>
>In case sends the layer4, layer3 or layer2 size of a packet in
>layer7 data.
>
>Come to think of it, replacing by NOP is needed during
>PMTUD where packets have to-be-stripped options.
>
>Consider a three-machine setup with sender, iptables and receiver,
>connected through MTU=1500 Ethernet. Assume a hypothethical TCP SYN
>packet with lots of strip-me options that totals up at 2000 bytes.
>Because of -j TCPOPTSTRIP, the packet will be reduced to, say, 80
>bytes. The packet will pass, and the receiving end will confirm the
>SYN. Now, the sending side believes the minimum MTU is 1600, since
>its initial SYN was successfully replied to with SYN ACK. => Problem.
er, 2000. Whatever, just something >1500.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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
1 sibling, 1 reply; 44+ messages in thread
From: Patrick McHardy @ 2007-09-28 15:44 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> On Sep 28 2007 17:02, Patrick McHardy wrote:
>
>>For TCPOPTSTRIP I would expect either real stripping or replacement
>>by TCPOPT_NOP. In which cases does replacement by something else
>>make sense?
>>
>
> In case sends the layer4, layer3 or layer2 size of a packet in
> layer7 data.
Thats a reason for using NOPs, but whats the reason for allowing
to use something different?
> Come to think of it, replacing by NOP is needed during
> PMTUD where packets have to-be-stripped options.
>
> Consider a three-machine setup with sender, iptables and receiver,
> connected through MTU=1500 Ethernet. Assume a hypothethical TCP SYN
> packet with lots of strip-me options that totals up at 2000 bytes.
> Because of -j TCPOPTSTRIP, the packet will be reduced to, say, 80
> bytes. The packet will pass, and the receiving end will confirm the
> SYN. Now, the sending side believes the minimum MTU is 1600, since
> its initial SYN was successfully replied to with SYN ACK. => Problem.
>
> Makes sense?
Hardly, the TCP header can contain a maximum of 40 bytes options :)
Besides that: if the options are contained in every packet (lets
say timestamp option) and is always stripped, the sender *should*
assume the bigger MTU. And if it really overestimates it will
receive a frag. needed message and learn the correct one.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 15:44 ` Patrick McHardy
@ 2007-09-28 16:04 ` Jan Engelhardt
2007-09-28 16:07 ` Patrick McHardy
0 siblings, 1 reply; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-28 16:04 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Sven Schnelle, netfilter-devel
On Sep 28 2007 17:44, Patrick McHardy wrote:
>
>> Come to think of it, replacing by NOP is needed during
>> PMTUD where packets have to-be-stripped options.
>>
>> Consider a three-machine setup with sender, iptables and receiver,
>> connected through MTU=1500 Ethernet. Assume a hypothethical TCP SYN
>> packet with lots of strip-me options that totals up at 2000 bytes.
>> Because of -j TCPOPTSTRIP, the packet will be reduced to, say, 80
>> bytes. The packet will pass, and the receiving end will confirm the
>> SYN. Now, the sending side believes the minimum MTU is 2000, since
>> its initial SYN was successfully replied to with SYN ACK. => Problem.
>>
>> Makes sense?
>
>Hardly, the TCP header can contain a maximum of 40 bytes options :)
Well, then let it have [tcphdr] [stripopt] [lots of data] so that
the sum of it is 1504 if you want, and that by stripping one
option, it fits into the allotted 1500.
>Besides that: if the options are contained in every packet (lets
>say timestamp option) and is always stripped, the sender *should*
>assume the bigger MTU. And if it really overestimates it will
>receive a frag. needed message and learn the correct one.
It will not receive a frag on the SYN, but later on.
Does that work? I.e. subsequently change the tcp connection's base mtu?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 16:04 ` Jan Engelhardt
@ 2007-09-28 16:07 ` Patrick McHardy
0 siblings, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-09-28 16:07 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> On Sep 28 2007 17:44, Patrick McHardy wrote:
>
>>Besides that: if the options are contained in every packet (lets
>>say timestamp option) and is always stripped, the sender *should*
>>assume the bigger MTU. And if it really overestimates it will
>>receive a frag. needed message and learn the correct one.
>
>
> It will not receive a frag on the SYN, but later on.
> Does that work? I.e. subsequently change the tcp connection's base mtu?
Of course, there are lots of reasons why this could happen.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 15:02 ` Patrick McHardy
2007-09-28 15:33 ` Jan Engelhardt
@ 2007-09-29 9:04 ` Sven Schnelle
2007-09-29 9:16 ` Jan Engelhardt
` (4 more replies)
1 sibling, 5 replies; 44+ messages in thread
From: Sven Schnelle @ 2007-09-29 9:04 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, netfilter-devel
Patrick McHardy <kaber@trash.net> writes:
> Jan Engelhardt wrote:
>> Since I had nothing better to do, I did a cleanup :)
>
> Great :) My main question is what the use case of this is.
Main intention for writing this module was to strip of TCP Options from
the SYN packets sent by some Hosts - for example Hosts that are
announcing that they can do window scaling, but in fact some broken
implementation/routers inbetween are preventing this. Simply stripping
of these Option allows communicating with such device, without the need
to disable window scaling kernel-wide.
The first version was only stripping the Windows scaling option, but it
may be useful for other cases - so i decided to make the stripped option
configurable.
>
>> @@ -0,0 +1,155 @@
>> +/*
>> + * A module 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/x_tables.h>
>> +#include <linux/netfilter/xt_tcpudp.h>
>
> tcpudp.h? Shouldn't be needed.
>
>> +#include <linux/netfilter/xt_TCPOPTSTRIP.h>
>> +
>> +static void fast_csum(__sum16 *csum, const u_int8_t *optr,
>> + const u_int8_t *nptr, const int offset)
>> +{
>> + u_int8_t 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)));
>> +}
>
>
> Please use the generic checksumming helpers.
something like this?:
+ if (opt[i] == tinfo->tcpoption) {
+ for(j = 0; j < optl; j++) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ nf_proto_csum_replace2(&tcph->check, *pskb,
+ htons(o), htons(n), 0);
+ }
+ memset(opt+i, TCPOPT_NOP, optl);
+ }
As i'm currently travelling, i can't test the code above - will do the
end of next week, and resubmit.
>> +
>> +static unsigned int
>> +tcpoptstrip_mangle_packet(struct sk_buff **pskb,
>> + const struct xt_tcpoptstrip_info *info,
>> + unsigned int tcphoff, unsigned int minlen)
>> +{
>> + const u_int8_t newopt = TCPOPT_NOP;
>> + unsigned int optl, tcplen, i, j;
>> + struct tcphdr *tcph;
>> + u_int8_t *opt;
>> +
>> + if (!skb_make_writable(pskb, (*pskb)->len))
>> + return NF_DROP;
>> +
>> + tcplen = (*pskb)->len - tcphoff;
>> + tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
>> +
>> + if (tcplen != 4 * tcph->doff)
>> + return NF_DROP;
>
>
> Seems to be copied from TCPMSS - but I don't see why you shouldn't allow
> stripping options from packets with data.
Indeed, i've used xt_TCPMSS.c as some kind of template. Could be removed
of course.
>> +
>> + opt = (u_int8_t *)tcph;
>> +
>> + for (i = sizeof(struct tcphdr); i < 4 * tcph->doff; i += optl) {
>> + optl = optlen(opt, i);
>> +
>> + if (optl + i > tcph->doff*4)
>> + break;
>> +
>> + if (opt[i] == info->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);
>
>
> For TCPOPTSTRIP I would expect either real stripping or replacement
> by TCPOPT_NOP. In which cases does replacement by something else
> make sense?
It does replacement by TCPOPT_NOP - the newopt is a const
TCPOPT_NOP. But i've changed this with the checksum code above.
Of course we can choose another name which describes the task of this
target better - didn't care much about it the name in the first case.
I think replacing the TCP Option by nop is cheaper than moving all
remaining options.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 14:44 ` Jan Engelhardt
2007-09-28 14:57 ` Jan Engelhardt
2007-09-28 15:02 ` Patrick McHardy
@ 2007-09-29 9:05 ` Sven Schnelle
2 siblings, 0 replies; 44+ messages in thread
From: Sven Schnelle @ 2007-09-29 9:05 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
Jan Engelhardt <jengelh@computergmbh.de> writes:
> Since I had nothing better to do, I did a cleanup :)
Thanks :) will take a look next week when i'm back at home.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-29 9:04 ` Sven Schnelle
@ 2007-09-29 9:16 ` Jan Engelhardt
2007-09-29 14:33 ` Patrick McHardy
` (3 subsequent siblings)
4 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-09-29 9:16 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
On Sep 29 2007 11:04, Sven Schnelle wrote:
>> Jan Engelhardt wrote:
>>> Since I had nothing better to do, I did a cleanup :)
>>
>> Great :) My main question is what the use case of this is.
>
>Main intention for writing this module was to strip of TCP Options from
>the SYN packets sent by some Hosts - for example Hosts that are
>announcing that they can do window scaling, but in fact some broken
>implementation/routers inbetween are preventing this. Simply stripping
>of these Option allows communicating with such device, without the need
>to disable window scaling kernel-wide.
Come to speak of it, I would need this, as there is a broken
netgear router in this house :-/
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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
` (2 subsequent siblings)
4 siblings, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-09-29 14:33 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Jan Engelhardt, netfilter-devel
Sven Schnelle wrote:
> Patrick McHardy <kaber@trash.net> writes:
>
>
>>Jan Engelhardt wrote:
>>
>>>Since I had nothing better to do, I did a cleanup :)
>>
>>Great :) My main question is what the use case of this is.
>
>
> Main intention for writing this module was to strip of TCP Options from
> the SYN packets sent by some Hosts - for example Hosts that are
> announcing that they can do window scaling, but in fact some broken
> implementation/routers inbetween are preventing this. Simply stripping
> of these Option allows communicating with such device, without the need
> to disable window scaling kernel-wide.
>
> The first version was only stripping the Windows scaling option, but it
> may be useful for other cases - so i decided to make the stripped option
> configurable.
Sounds reasonable.
>>Please use the generic checksumming helpers.
>
>
> something like this?:
>
> + if (opt[i] == tinfo->tcpoption) {
> + for(j = 0; j < optl; j++) {
> + o = opt[i+j];
> + n = TCPOPT_NOP;
> + if ((i + j) % 2 == 0) {
> + o <<= 8;
> + n <<= 8;
> + }
> + nf_proto_csum_replace2(&tcph->check, *pskb,
> + htons(o), htons(n), 0);
> + }
> + memset(opt+i, TCPOPT_NOP, optl);
> + }
>
> As i'm currently travelling, i can't test the code above - will do the
> end of next week, and resubmit.
I'm not sure what the loop is doing exactly (still at my first
coffee :), but yes, I meant using nf_proto_csum*.
>>>+ memset(opt+i, newopt, optl);
>>
>>
>>For TCPOPTSTRIP I would expect either real stripping or replacement
>>by TCPOPT_NOP. In which cases does replacement by something else
>>make sense?
>
>
> It does replacement by TCPOPT_NOP - the newopt is a const
> TCPOPT_NOP. But i've changed this with the checksum code above.
> Of course we can choose another name which describes the task of this
> target better - didn't care much about it the name in the first case.
Actually I only misread the code, I thought newopt was configurable.
> I think replacing the TCP Option by nop is cheaper than moving all
> remaining options.
Agreed, that sounds fine.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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 14:09 ` [RFC] TCPOPTSTRIP target Sven Schnelle
4 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Oledzki @ 2007-09-29 17:23 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, Jan Engelhardt, netfilter-devel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2742 bytes --]
On Sat, 29 Sep 2007, Sven Schnelle wrote:
> Patrick McHardy <kaber@trash.net> writes:
>
>> Jan Engelhardt wrote:
>>> Since I had nothing better to do, I did a cleanup :)
>>
>> Great :) My main question is what the use case of this is.
>
> Main intention for writing this module was to strip of TCP Options from
> the SYN packets sent by some Hosts - for example Hosts that are
> announcing that they can do window scaling, but in fact some broken
> implementation/routers inbetween are preventing this. Simply stripping
> of these Option allows communicating with such device, without the need
> to disable window scaling kernel-wide.
Another example may be sack & broken fw/nats. BTW: it is possible to
disable window scaling by simply adding a route with a window attribute.
This unfortunately works only on a host that initiates a connection,
so this is not an option when you have some Windows workstations behind a
firewall.
> The first version was only stripping the Windows scaling option, but it
> may be useful for other cases - so i decided to make the stripped option
> configurable.
It is quite funny as I have also started working on similar target,
mainly to solve this sack problem.
>> Seems to be copied from TCPMSS - but I don't see why you shouldn't allow
>> stripping options from packets with data.
>
> Indeed, i've used xt_TCPMSS.c as some kind of template. Could be removed
> of course.
But the documentation should mention that it is often better to strip
for example sackok from a syn packet than sack from a packet with data.
>> For TCPOPTSTRIP I would expect either real stripping or replacement
>> by TCPOPT_NOP. In which cases does replacement by something else
>> make sense?
>
> It does replacement by TCPOPT_NOP - the newopt is a const
> TCPOPT_NOP. But i've changed this with the checksum code above.
> Of course we can choose another name which describes the task of this
> target better - didn't care much about it the name in the first case.
>
> I think replacing the TCP Option by nop is cheaper than moving all
> remaining options.
Indeed, especially that with moving, it would be nice to keep
alignments.
BTW: it is quite easy to pass more than one tcp option - all you need is
AFAIR something like "u8 options[32]" array accessed like:
to set:
options[optnr >> 3] |= (1<<(optnr&7))
to check:
if (options[optnr >> 3] & (1<<(optnr&7)) {
mask_it;
}
This may allow to specify a list of options to strip/mask:
--strip-tcp-options 3,4
I also suggest adding friendly names for tcp options. If you wish I have a
working code for that so I can post a incremental patch.
Best regards,
Krzysztof Olędzki
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-29 9:04 ` Sven Schnelle
` (2 preceding siblings ...)
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 14:09 ` [RFC] TCPOPTSTRIP target Sven Schnelle
4 siblings, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-02 14:09 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, netfilter-devel
Sven Schnelle <svens@bitebene.org> writes:
> As i'm currently travelling, i can't test the code above - will do the
> end of next week, and resubmit.
Ok, i've cleaned up the code and followed the suggestions here. I've
also added the possibility to strip more than one option from the Headers.
Signed-off-by: Sven Schnelle <svens@bitebene.org>
xtables part:
diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
new file mode 100644
index 0000000..384a33f
--- /dev/null
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,11 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define OPTION_IS_SET(p, bit) (p)[(bit) >> 3] & 1 << ((bit) & 0x07)
+#define SET_OPTION(p, bit) (p)[(bit) >> 3] |= 1 << ((bit) & 0x07)
+
+struct xt_tcpoptstrip_info {
+ unsigned char tcpoptions[32];
+};
+
+#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
+ tcp option(s) 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..ec86ac9
--- /dev/null
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,157 @@
+/*
+ * 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_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_TCPOPTSTRIP");
+
+static inline unsigned int xt_tcpoptstrip_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 int xt_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;
+ unsigned int optl, i,j;
+ u8 *opt;
+ u16 n, o;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return XT_CONTINUE;
+
+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+
+ opt = (u_int8_t *)tcph;
+
+ /* Walk through all TCP options - if we find some option to
+ remove, set all octets to TCPTOPT_NOP and adjust checksum */
+
+ for(i = sizeof(struct tcphdr); i < tcph->doff*4; i += optl) {
+ optl = xt_tcpoptstrip_optlen(opt, i);
+
+ if(optl + i > tcph->doff*4)
+ break;
+
+ if (OPTION_IS_SET(tinfo->tcpoptions, opt[i])) {
+ for(j = 0; j < optl; j++) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ nf_proto_csum_replace2(&tcph->check, *pskb, htons(o),
+ htons(n), 0);
+ }
+ memset(opt+i, TCPOPT_NOP, optl);
+ }
+ }
+ return XT_CONTINUE;
+}
+
+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);
+
+
+ return xt_tcpoptstrip_mangle_packet(pskb, targinfo, iph->ihl * 4,
+ sizeof(*iph) + sizeof(struct tcphdr));
+}
+
+#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;
+ }
+
+ return xt_tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+#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);
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-29 9:04 ` Sven Schnelle
` (3 preceding siblings ...)
2007-10-02 14:09 ` Sven Schnelle
@ 2007-10-02 14:09 ` Sven Schnelle
2007-10-02 14:20 ` Sven Schnelle
4 siblings, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-02 14:09 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, netfilter-devel
Sven Schnelle <svens@bitebene.org> writes:
> As i'm currently travelling, i can't test the code above - will do the
> end of next week, and resubmit.
Ok, i've cleaned up the code and followed the suggestions here. I've
also added the possibility to strip more than one option from the Headers.
Signed-off-by: Sven Schnelle <svens@bitebene.org>
iptables part:
Index: extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- extensions/libxt_TCPOPTSTRIP.c (revision 0)
+++ extensions/libxt_TCPOPTSTRIP.c (revision 0)
@@ -0,0 +1,182 @@
+/* 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>
+
+enum {
+ OPT_STRIP_OPTIONS=1,
+ OPT_STRIP_WSCALE,
+ OPT_STRIP_TIMESTAMP,
+ OPT_STRIP_MSS,
+ OPT_STRIP_SACK,
+ OPT_STRIP_SACK_PERMITTED,
+};
+
+static const struct option tcpoptstrip_opts[] = {
+ { "strip-tcp-options", 1, NULL, OPT_STRIP_OPTIONS },
+ { "strip-wscale", 0, NULL, OPT_STRIP_WSCALE },
+ { "strip-timestamp", 0, NULL, OPT_STRIP_TIMESTAMP },
+ { "strip-mss", 0, NULL, OPT_STRIP_MSS },
+ { "strip-sack", 0, NULL, OPT_STRIP_SACK },
+ { "strip-sack-permitted", 0, NULL, OPT_STRIP_SACK_PERMITTED },
+ { }
+};
+
+/* Function which prints out usage message. */
+static void tcpoptstrip_help(void)
+{
+ printf("TCPOPTSTRIP target options:\n"
+ " --strip-tcp-options option(s) strip specified tcp options from TCP Header\n"
+ " --strip-wscale strip windows scaling option\n"
+ " --strip-timestamp strip timestamp option\n"
+ " --strip-mss strip mss option\n"
+ " --strip-sack strip sack option\n"
+ " --strip-sack-permitted strip sack permitted option\n");
+}
+
+/* Initialize the target. */
+static void tcpoptstrip_init(struct xt_entry_target *target)
+{
+ struct xt_tcpoptstrip_info *optinfo
+ = (struct xt_tcpoptstrip_info *)target->data;
+ memset(optinfo->tcpoptions, 0, sizeof(optinfo->tcpoptions));
+}
+
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ char *p;
+ struct xt_tcpoptstrip_info *optinfo
+ = (struct xt_tcpoptstrip_info *)(*target)->data;
+
+ switch (c) {
+ unsigned int option;
+
+ case OPT_STRIP_OPTIONS:
+ for (p = strtok(optarg, ","); p; p = strtok(NULL, ",")) {
+ if (string_to_number(p, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM, "Bad TCPOPTSTRIP value `%s'",
+ optarg);
+
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM, "option has to be > 2");
+
+ SET_OPTION(optinfo->tcpoptions, option);
+ }
+ break;
+
+ case OPT_STRIP_WSCALE:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_WINDOW);
+ break;
+
+ case OPT_STRIP_MSS:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_MAXSEG);
+ break;
+
+ case OPT_STRIP_SACK:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_SACK);
+ break;
+
+ case OPT_STRIP_SACK_PERMITTED:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_SACK_PERMITTED);
+ break;
+
+ case OPT_STRIP_TIMESTAMP:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_TIMESTAMP);
+ break;
+
+ default:
+ return 0;
+ }
+ *flags = 1;
+ return 1;
+}
+
+static void tcpoptstrip_final_check(unsigned int flags)
+{
+ if (!flags)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP target: At least one parameter is required");
+}
+
+static void tcpoptstrip_print_options(const struct xt_tcpoptstrip_info *optinfo)
+{
+ int first = 1, option;
+ for(option = 0; option < 256; option++) {
+ if(OPTION_IS_SET(optinfo->tcpoptions, option)) {
+ printf("%c%d", first ? ' ' : ',', option);
+ first = 0;
+ }
+ }
+}
+
+/* Prints out the targinfo. */
+static void tcpoptstrip_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 options");
+ tcpoptstrip_print_options(optinfo);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void tcpoptstrip_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-options");
+ tcpoptstrip_print_options(optinfo);
+
+}
+
+static struct xtables_target tcpoptstrip_reg = {
+ .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 = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_final_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts
+};
+
+static struct xtables_target tcpoptstrip_reg6 = {
+ .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 = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_final_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_reg);
+ xtables_register_target(&tcpoptstrip_reg6);
+}
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:=
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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
0 siblings, 2 replies; 44+ messages in thread
From: Sven Schnelle @ 2007-10-02 14:20 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, netfilter-devel
Sven Schnelle <sschnelle@astaro.com> writes:
> Sven Schnelle <svens@bitebene.org> writes:
>
>> As i'm currently travelling, i can't test the code above - will do the
>> end of next week, and resubmit.
>
> Ok, i've cleaned up the code and followed the suggestions here. I've
> also added the possibility to strip more than one option from the Headers.
>
> Signed-off-by: Sven Schnelle <svens@bitebene.org>
Please ignore the last iptables patch, there was a typo in there. This
one should be fine.
Index: extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- extensions/libxt_TCPOPTSTRIP.c (revision 0)
+++ extensions/libxt_TCPOPTSTRIP.c (revision 0)
@@ -0,0 +1,182 @@
+/* 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>
+
+enum {
+ OPT_STRIP_OPTIONS=1,
+ OPT_STRIP_WSCALE,
+ OPT_STRIP_TIMESTAMP,
+ OPT_STRIP_MSS,
+ OPT_STRIP_SACK,
+ OPT_STRIP_SACK_PERMITTED,
+};
+
+static const struct option tcpoptstrip_opts[] = {
+ { "strip-tcp-options", 1, NULL, OPT_STRIP_OPTIONS },
+ { "strip-wscale", 0, NULL, OPT_STRIP_WSCALE },
+ { "strip-timestamp", 0, NULL, OPT_STRIP_TIMESTAMP },
+ { "strip-mss", 0, NULL, OPT_STRIP_MSS },
+ { "strip-sack", 0, NULL, OPT_STRIP_SACK },
+ { "strip-sack-permitted", 0, NULL, OPT_STRIP_SACK_PERMITTED },
+ { }
+};
+
+/* Function which prints out usage message. */
+static void tcpoptstrip_help(void)
+{
+ printf("TCPOPTSTRIP target options:\n"
+ " --strip-tcp-options option(s) strip specified tcp options from TCP Header\n"
+ " --strip-wscale strip windows scaling option\n"
+ " --strip-timestamp strip timestamp option\n"
+ " --strip-mss strip mss option\n"
+ " --strip-sack strip sack option\n"
+ " --strip-sack-permitted strip sack permitted option\n");
+}
+
+/* Initialize the target. */
+static void tcpoptstrip_init(struct xt_entry_target *target)
+{
+ struct xt_tcpoptstrip_info *optinfo
+ = (struct xt_tcpoptstrip_info *)target->data;
+ memset(optinfo->tcpoptions, 0, sizeof(optinfo->tcpoptions));
+}
+
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ char *p;
+ struct xt_tcpoptstrip_info *optinfo
+ = (struct xt_tcpoptstrip_info *)(*target)->data;
+
+ switch (c) {
+ unsigned int option;
+
+ case OPT_STRIP_OPTIONS:
+ for (p = strtok(optarg, ","); p; p = strtok(NULL, ",")) {
+ if (string_to_number(p, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM, "Bad TCPOPTSTRIP value `%s'",
+ p);
+
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM, "option has to be > 2");
+
+ SET_OPTION(optinfo->tcpoptions, option);
+ }
+ break;
+
+ case OPT_STRIP_WSCALE:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_WINDOW);
+ break;
+
+ case OPT_STRIP_MSS:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_MAXSEG);
+ break;
+
+ case OPT_STRIP_SACK:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_SACK);
+ break;
+
+ case OPT_STRIP_SACK_PERMITTED:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_SACK_PERMITTED);
+ break;
+
+ case OPT_STRIP_TIMESTAMP:
+ SET_OPTION(optinfo->tcpoptions, TCPOPT_TIMESTAMP);
+ break;
+
+ default:
+ return 0;
+ }
+ *flags = 1;
+ return 1;
+}
+
+static void tcpoptstrip_final_check(unsigned int flags)
+{
+ if (!flags)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP target: At least one parameter is required");
+}
+
+static void tcpoptstrip_print_options(const struct xt_tcpoptstrip_info *optinfo)
+{
+ int first = 1, option;
+ for(option = 0; option < 256; option++) {
+ if(OPTION_IS_SET(optinfo->tcpoptions, option)) {
+ printf("%c%d", first ? ' ' : ',', option);
+ first = 0;
+ }
+ }
+}
+
+/* Prints out the targinfo. */
+static void tcpoptstrip_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 options");
+ tcpoptstrip_print_options(optinfo);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void tcpoptstrip_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-options");
+ tcpoptstrip_print_options(optinfo);
+
+}
+
+static struct xtables_target tcpoptstrip_reg = {
+ .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 = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_final_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts
+};
+
+static struct xtables_target tcpoptstrip_reg6 = {
+ .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 = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_final_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_reg);
+ xtables_register_target(&tcpoptstrip_reg6);
+}
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:=
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-09-28 14:16 ` Jan Engelhardt
2007-09-28 14:44 ` Jan Engelhardt
@ 2007-10-02 17:22 ` Sven Schnelle
2007-10-02 17:31 ` Jan Engelhardt
1 sibling, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-02 17:22 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
Jan Engelhardt <jengelh@computergmbh.de> writes:
>>+ switch (c) {
>>+ unsigned int option;
>>+
Hmm, forgot to move that one. Still there :/
> Huh, what's that option doing there? It looks out of place.
> Try CodingStyle.
Damn, forgot once more to change my edit style in the editor - lets see
what else comes up. will submit the patch again with changed settings
if there are no other complains ;)
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
2007-10-02 17:22 ` Sven Schnelle
@ 2007-10-02 17:31 ` Jan Engelhardt
0 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-02 17:31 UTC (permalink / raw)
To: Sven Schnelle; +Cc: netfilter-devel
On Oct 2 2007 19:22, Sven Schnelle wrote:
>Jan Engelhardt <jengelh@computergmbh.de> writes:
>
>>>+ switch (c) {
>>>+ unsigned int option;
>>>+
>
>Hmm, forgot to move that one. Still there :/
>
>> Huh, what's that option doing there? It looks out of place.
>
>> Try CodingStyle.
>
>Damn, forgot once more to change my edit style in the editor - lets see
>what else comes up. will submit the patch again with changed settings
>if there are no other complains ;)
I've already taken care of all that - patches a-coming.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (netfilter)
2007-10-02 14:09 ` Sven Schnelle
@ 2007-10-02 17:32 ` Jan Engelhardt
2007-10-02 17:56 ` Krzysztof Oledzki
2007-10-04 5:04 ` Patrick McHardy
0 siblings, 2 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-02 17:32 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, Netfilter Developer Mailing List
On Oct 2 2007 16:09, Sven Schnelle wrote:
>Sven Schnelle <svens@bitebene.org> writes:
>
>> As i'm currently travelling, i can't test the code above - will do the
>> end of next week, and resubmit.
>
>Ok, i've cleaned up the code and followed the suggestions here. I've
>also added the possibility to strip more than one option from the Headers.
Would be great if we could work on one patch :) [see below]
>+#ifndef _XT_TCPOPTSTRIP_H
>+#define _XT_TCPOPTSTRIP_H
>+
>+#define OPTION_IS_SET(p, bit) (p)[(bit) >> 3] & 1 << ((bit) & 0x07)
>+#define SET_OPTION(p, bit) (p)[(bit) >> 3] |= 1 << ((bit) & 0x07)
You should probably use <linux/bitmap.h>.
>+struct xt_tcpoptstrip_info {
>+ unsigned char tcpoptions[32];
>+};
And u_int8_t. Better is uint32_t[8], because that is what the linux
bitops work with. (And, unfortunately, it's buggy so we end up
continuing to use own macros.)
>+static inline unsigned int xt_tcpoptstrip_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 int xt_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;
Redundant wrong cast. Just pass in const struct xt_TCPOPTSTRIP_info
and you are done.
>+ if (!skb_make_writable(pskb, (*pskb)->len))
>+ return XT_CONTINUE;
This was NF_DROP previously. Is this really ok to let it pass?
>+
>+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
>+
>+ opt = (u_int8_t *)tcph;
>+
>+ /* Walk through all TCP options - if we find some option to
>+ remove, set all octets to TCPTOPT_NOP and adjust checksum */
>+
>+ for(i = sizeof(struct tcphdr); i < tcph->doff*4; i += optl) {
>+ optl = xt_tcpoptstrip_optlen(opt, i);
>+
>+ if(optl + i > tcph->doff*4)
>+ break;
This check looks redundant (given that the break conditions is already
given in the for() line) -- though it is not as far as my math skills
can see. But can't it be done a bit nicer?
>+ for(j = 0; j < optl; j++) {
>+ o = opt[i+j];
>+ n = TCPOPT_NOP;
>+ if ((i + j) % 2 == 0) {
>+ o <<= 8;
>+ n <<= 8;
>+ }
>+ nf_proto_csum_replace2(&tcph->check, *pskb, htons(o),
>+ htons(n), 0);
>+ }
>+ memset(opt+i, TCPOPT_NOP, optl);
Can we modify the option field while moving through it, and update the
checksum after the loop?
>+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);
>+
>+
>+ return xt_tcpoptstrip_mangle_packet(pskb, targinfo, iph->ihl * 4,
>+ sizeof(*iph) + sizeof(struct tcphdr));
>+}
iph is redundant.
>+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
This does not seem necessary.
>+ nexthdr = ipv6h->nexthdr;
>+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
>+ if (tcphoff < 0) {
>+ WARN_ON(1);
Should not spew useless warning when someone sends a forged packet.
Find updated xt_TCPOPTSTRIP below, and libxt_TCPOPTSTRIP in its thread.
=== Patch begins here ===
Adds xt_TCPOPTSTRIP.
---
include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 ++
net/netfilter/Kconfig | 7 +
net/netfilter/Makefile | 1
net/netfilter/xt_TCPOPTSTRIP.c | 140 +++++++++++++++++++++++++++++++
4 files changed, 161 insertions(+)
Index: linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
Index: linux-2.6.23/net/netfilter/Kconfig
===================================================================
--- linux-2.6.23.orig/net/netfilter/Kconfig
+++ linux-2.6.23/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
+ ---help---
+ This option adds a "TCPOPTSTRIP" target, which allows you to strip
+ TCP options from TCP packets.
+
config NETFILTER_XT_MATCH_COMMENT
tristate '"comment" match support'
depends on NETFILTER_XTABLES
Index: linux-2.6.23/net/netfilter/Makefile
===================================================================
--- linux-2.6.23.orig/net/netfilter/Makefile
+++ linux-2.6.23/net/netfilter/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE)
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
Index: linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,140 @@
+/*
+ * A module 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/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+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 unsigned int
+tcpoptstrip_mangle_packet(struct sk_buff **pskb,
+ const struct xt_tcpoptstrip_info *info,
+ unsigned int tcphoff, unsigned int minlen)
+{
+ unsigned int optl, i, j;
+ struct tcphdr *tcph;
+ u_int16_t n, o;
+ u_int8_t *opt;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ /* hmm... NF_DROP? */
+ return XT_CONTINUE;
+
+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+ opt = (u_int8_t *)tcph;
+
+ /*
+ * Walk through all TCP options - if we find some option to remove,
+ * set all octets to %TCPOPT_NOP and adjust checksum.
+ */
+ for (i = sizeof(struct tcphdr); i < 4 * tcph->doff; i += optl) {
+ optl = optlen(opt, i);
+
+ if (i + optl > 4 * tcph->doff)
+ break;
+
+ if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
+ continue;
+
+ for (j = 0; j < optl; ++j) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ nf_proto_csum_replace2(&tcph->check, *pskb, htons(o),
+ htons(n), 0);
+ }
+ memset(opt + i, TCPOPT_NOP, optl);
+ }
+
+ return XT_CONTINUE;
+}
+
+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)
+{
+ return tcpoptstrip_mangle_packet(pskb, targinfo, ip_hdrlen(*pskb),
+ sizeof(struct iphdr) + sizeof(struct tcphdr));
+}
+
+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);
+ unsigned int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+ if (tcphoff < 0)
+ return NF_DROP;
+
+ return tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+
+static struct xt_target tcpoptstrip_reg[] __read_mostly = {
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target4,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target6,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_tcpoptstrip_init(void)
+{
+ return xt_register_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+static void __exit xt_tcpoptstrip_exit(void)
+{
+ xt_unregister_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+module_init(xt_tcpoptstrip_init);
+module_exit(xt_tcpoptstrip_exit);
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>");
+MODULE_DESCRIPTION("x_tables TCPOPTSTRIP module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSTRIP");
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target
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
1 sibling, 0 replies; 44+ messages in thread
From: Krzysztof Oledzki @ 2007-10-02 17:49 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, Jan Engelhardt, netfilter-devel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1219 bytes --]
On Tue, 2 Oct 2007, Sven Schnelle wrote:
> +static const struct option tcpoptstrip_opts[] = {
> + { "strip-tcp-options", 1, NULL, OPT_STRIP_OPTIONS },
> + { "strip-wscale", 0, NULL, OPT_STRIP_WSCALE },
> + { "strip-timestamp", 0, NULL, OPT_STRIP_TIMESTAMP },
> + { "strip-mss", 0, NULL, OPT_STRIP_MSS },
> + { "strip-sack", 0, NULL, OPT_STRIP_SACK },
> + { "strip-sack-permitted", 0, NULL, OPT_STRIP_SACK_PERMITTED },
> + { }
> +};
> +
> +/* Function which prints out usage message. */
> +static void tcpoptstrip_help(void)
> +{
> + printf("TCPOPTSTRIP target options:\n"
> + " --strip-tcp-options option(s) strip specified tcp options from TCP Header\n"
> + " --strip-wscale strip windows scaling option\n"
> + " --strip-timestamp strip timestamp option\n"
> + " --strip-mss strip mss option\n"
> + " --strip-sack strip sack option\n"
> + " --strip-sack-permitted strip sack permitted option\n");
> +
How about something similar to:
--strip-tcp-options wscale,timestamp,mss
? :)
Like in --dport for example:
--dport ftp,ssh,telnet,http
Best regards,
Krzysztof Olędzki
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (iptables)
2007-10-02 14:20 ` Sven Schnelle
2007-10-02 17:49 ` Krzysztof Oledzki
@ 2007-10-02 17:51 ` Jan Engelhardt
2007-10-06 14:10 ` Sven Schnelle
1 sibling, 1 reply; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-02 17:51 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
On Oct 2 2007 16:20, Sven Schnelle wrote:
>+static void tcpoptstrip_help(void)
>+{
>+ printf("TCPOPTSTRIP target options:\n"
>+ " --strip-tcp-options option(s) strip specified tcp options from TCP Header\n"
>+ " --strip-wscale strip windows scaling option\n"
>+ " --strip-timestamp strip timestamp option\n"
>+ " --strip-mss strip mss option\n"
>+ " --strip-sack strip sack option\n"
>+ " --strip-sack-permitted strip sack permitted option\n");
>+}
I have added a strip-md5.
>+ case OPT_STRIP_OPTIONS:
>+ for (p = strtok(optarg, ","); p; p = strtok(NULL, ",")) {
I have added option processing validation.
>+/* Saves the union ipt_targinfo in parsable form to stdout. */
>+static void tcpoptstrip_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-options");
>+ tcpoptstrip_print_options(optinfo);
>+
>+}
Bogus. The parser code does not know how to handle a comma-separated
list, so save() should not produce one.
This here is untested.
=== Patch begins here ===
---
extensions/Makefile | 2
extensions/libxt_TCPOPTSTRIP.c | 218 +++++++++++++++++++++++++++++++
include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 +
3 files changed, 232 insertions(+), 1 deletion(-)
Index: iptables/extensions/Makefile
===================================================================
--- iptables.orig/extensions/Makefile
+++ iptables/extensions/Makefile
@@ -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 TCPOPTSTRIP TRACE
PF_EXT_SELINUX_SLIB:=
PF6_EXT_SELINUX_SLIB:=
Index: iptables/extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ iptables/extensions/libxt_TCPOPTSTRIP.c
@@ -0,0 +1,218 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+#ifndef TCPOPT_MD5SIG
+# define TCPOPT_MD5SIG 19
+#endif
+
+enum {
+ F_STRIP = 1 << 0,
+ F_MSS = 1 << 1,
+ F_WSCALE = 1 << 2,
+ F_SACK_PERMITTED = 1 << 3,
+ F_SACK = 1 << 4,
+ F_TIMESTAMP = 1 << 5,
+ F_MD5 = 1 << 6,
+};
+
+static const struct option tcpoptstrip_opts[] = {
+ {"strip-options", true, NULL, '0'},
+ {"strip-mss", false, NULL, 'm'},
+ {"strip-wscale", false, NULL, 'w'},
+ {"strip-sack-permitted", false, NULL, 'S'},
+ {"strip-sack", false, NULL, 's'},
+ {"strip-timestamp", false, NULL, 't'},
+ {"strip-md5", false, NULL, '5'},
+ {NULL},
+};
+
+static void tcpoptstrip_help(void)
+{
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-options value strip specified TCP options denoted by value\n"
+" (separated by comma) from TCP header\n"
+" --strip-mss strip MSS option\n"
+" --strip-wscale strip window scaling option\n"
+" --strip-sack-permitted strip \"SACK permitted\" option\n"
+" --strip-sack strip SACK option\n"
+" --strip-timestamp strip timestamp option\n"
+" --strip-md5 strip MD5 signature (RFC2385) option\n"
+ );
+}
+
+static void tcpoptstrip_init(struct xt_entry_target *t)
+{
+ struct xt_tcpoptstrip_info *info = (void *)t->data;
+
+ /* strictly necessary? play safe for now. */
+ memset(info->strip_bmap, 0, sizeof(info->strip_bmap));
+}
+
+static void parse_list(struct xt_tcpoptstrip_info *info, char *arg)
+{
+ unsigned int option;
+ char *p;
+
+ while (true) {
+ p = strchr(arg, ',');
+ if (p != NULL)
+ *p = '\0';
+
+ if (string_to_number(arg, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM,
+ "Bad TCP option value \"%s\"", arg);
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM,
+ "Option value may not be 0 or 1");
+
+ tcpoptstrip_set_bit(info->strip_bmap, option);
+ if (p == NULL)
+ break;
+ arg = p + 1;
+ }
+}
+
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_info *info = (void *)(*target)->data;
+
+ switch (c) {
+ case '0':
+ if (*flags & F_STRIP)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-options only once");
+ parse_list(info, optarg);
+ *flags |= F_STRIP;
+ return 1;
+ case 'm':
+ if (*flags & F_MSS)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-mss only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_MAXSEG);
+ *flags |= F_MSS;
+ return 1;
+ case 'w':
+ if (*flags & F_WSCALE)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-wscale only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_WINDOW);
+ *flags |= F_WSCALE;
+ return 1;
+ case 'S':
+ if (*flags & F_SACK_PERMITTED)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-sack-permitted only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_SACK_PERMITTED);
+ *flags |= F_SACK_PERMITTED;
+ return 1;
+ case 's':
+ if (*flags & F_SACK)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-sack only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_SACK);
+ *flags |= F_SACK;
+ return 1;
+ case 't':
+ if (*flags & F_TIMESTAMP)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-timestamp only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_TIMESTAMP);
+ *flags |= F_TIMESTAMP;
+ return 1;
+ case '5':
+ if (*flags & F_MD5)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-md5 only once");
+ tcpoptstrip_set_bit(info->strip_bmap, TCPOPT_MD5SIG);
+ *flags |= F_MD5;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void tcpoptstrip_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: At least one of the strip options must be specified");
+}
+
+static void tcpoptstrip_print_list(const struct xt_tcpoptstrip_info *info)
+{
+ bool first = true;
+ unsigned int i;
+
+ for (i = 0; i < 256; ++i) {
+ if (!tcpoptstrip_test_bit(info->strip_bmap, i))
+ continue;
+ printf("%s%u", first ? "" : ",", i);
+ first = false;
+ }
+}
+
+static void tcpoptstrip_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+
+ printf("TCPOPTSTRIP options ");
+ tcpoptstrip_print_list(info);
+}
+
+static void tcpoptstrip_save(const void *ip,
+ const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+
+ printf("--strip-options ");
+ tcpoptstrip_print_list(info);
+}
+
+static struct xtables_target tcpoptstrip_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+static struct xtables_target tcpoptstrip6_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_reg);
+ xtables_register_target(&tcpoptstrip6_reg);
+}
Index: iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (netfilter)
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-04 5:04 ` Patrick McHardy
1 sibling, 1 reply; 44+ messages in thread
From: Krzysztof Oledzki @ 2007-10-02 17:56 UTC (permalink / raw)
To: Jan Engelhardt
Cc: Sven Schnelle, Patrick McHardy, Netfilter Developer Mailing List
[-- Attachment #1: Type: TEXT/PLAIN, Size: 759 bytes --]
On Tue, 2 Oct 2007, Jan Engelhardt wrote:
>> +#ifndef _XT_TCPOPTSTRIP_H
>> +#define _XT_TCPOPTSTRIP_H
>> +
>> +#define OPTION_IS_SET(p, bit) (p)[(bit) >> 3] & 1 << ((bit) & 0x07)
>> +#define SET_OPTION(p, bit) (p)[(bit) >> 3] |= 1 << ((bit) & 0x07)
>
> You should probably use <linux/bitmap.h>.
>
>> +struct xt_tcpoptstrip_info {
>> + unsigned char tcpoptions[32];
>> +};
>
> And u_int8_t. Better is uint32_t[8], because that is what the linux
> bitops work with. (And, unfortunately, it's buggy so we end up
> continuing to use own macros.)
But with uint32_t you have to remember about big/low-endianism &
network/host byte order conversion and stuff. Not sure if that's really
better.
Best regards,
Krzysztof Olędzki
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (netfilter)
2007-10-02 17:56 ` Krzysztof Oledzki
@ 2007-10-02 17:57 ` Jan Engelhardt
2007-10-02 18:01 ` Jan Engelhardt
0 siblings, 1 reply; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-02 17:57 UTC (permalink / raw)
To: Krzysztof Oledzki
Cc: Sven Schnelle, Patrick McHardy, Netfilter Developer Mailing List
On Oct 2 2007 19:56, Krzysztof Oledzki wrote:
>>
>> And u_int8_t. Better is uint32_t[8], because that is what the linux
>> bitops work with. (And, unfortunately, it's buggy so we end up
>> continuing to use own macros.)
>
> But with uint32_t you have to remember about big/low-endianism & network/host
> byte order conversion and stuff. Not sure if that's really better.
Should not matter. The endianess does not change between user- and
kernelspace, unless type widths do.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (netfilter)
2007-10-02 17:57 ` Jan Engelhardt
@ 2007-10-02 18:01 ` Jan Engelhardt
0 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-02 18:01 UTC (permalink / raw)
To: Krzysztof Oledzki
Cc: Sven Schnelle, Patrick McHardy, Netfilter Developer Mailing List
On Oct 2 2007 19:57, Jan Engelhardt wrote:
>>> And u_int8_t. Better is uint32_t[8], because that is what the linux
>>> bitops work with. (And, unfortunately, it's buggy so we end up
>>> continuing to use own macros.)
>>
>> But with uint32_t you have to remember about big/low-endianism & network/host
>> byte order conversion and stuff. Not sure if that's really better.
>
>Should not matter. The endianess does not change between user- and
>kernelspace, unless type widths do.
Should have read:
[...]kernelspace, unlike type widths, which do.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (netfilter)
2007-10-02 17:32 ` [RFC] TCPOPTSTRIP target (netfilter) Jan Engelhardt
2007-10-02 17:56 ` Krzysztof Oledzki
@ 2007-10-04 5:04 ` Patrick McHardy
1 sibling, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-10-04 5:04 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, Netfilter Developer Mailing List
Jan Engelhardt wrote:
> On Oct 2 2007 16:09, Sven Schnelle wrote:
>
>>Sven Schnelle <svens@bitebene.org> writes:
>>
>>
>>Ok, i've cleaned up the code and followed the suggestions here. I've
>>also added the possibility to strip more than one option from the Headers.
>
>
> Would be great if we could work on one patch :) [see below]
Indeed, that would be less confusing :) Please send the final
patch under new cover so I don't mix it up (its too late for
2.6.24 anyway, so no need to hurry).
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (iptables)
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
0 siblings, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-06 14:10 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Patrick McHardy, netfilter-devel
Jan Engelhardt <jengelh@computergmbh.de> writes:
> On Oct 2 2007 16:20, Sven Schnelle wrote:
>>+static void tcpoptstrip_help(void)
>>+{
>>+ printf("TCPOPTSTRIP target options:\n"
>>+ " --strip-tcp-options option(s) strip specified tcp options from TCP Header\n"
>>+ " --strip-wscale strip windows scaling option\n"
>>+ " --strip-timestamp strip timestamp option\n"
>>+ " --strip-mss strip mss option\n"
>>+ " --strip-sack strip sack option\n"
>>+ " --strip-sack-permitted strip sack permitted option\n");
>>+}
>
> I have added a strip-md5.
Thanks. I've added only a few options, so this list may still be
extensible ;-)
> This here is untested.
> [iptables patch]
I've changed the code in the meantime so that names could be specified
inside the --strip-options argument list, instead of having extra
options for every tcp option, this makes code smaller, and it is even
simpler to add new names.
For example:
--strip-options 3 is the same as --strip-options wscale. iptables-save
and iptables -L would give the names of the options, instead of the
numbers.
Output looks like this now:
root@deprecated(1058):~0# iptables -nvL -t mangle
Chain PREROUTING (policy ACCEPT 161 packets, 123K bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 161 packets, 123K bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 TCPOPTSTRIP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x17/0x02 TCPOPTSTRIP options wscale,77
Chain OUTPUT (policy ACCEPT 124 packets, 13460 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 124 packets, 13460 bytes)
pkts bytes target prot opt in out source destination
My version of the patch right now:
Index: libxt_TCPOPTSTRIP.c
===================================================================
--- libxt_TCPOPTSTRIP.c (revision 0)
+++ libxt_TCPOPTSTRIP.c (revision 0)
@@ -0,0 +1,205 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+#ifndef TCPOPT_MD5SIG
+# define TCPOPT_MD5SIG 19
+#endif
+
+enum {
+ F_STRIP = 1 << 0,
+};
+
+static const struct option tcpoptstrip_opts[] = {
+ {"strip-options", true, NULL, '0'},
+ {NULL},
+};
+
+struct tcp_optionmap_struct {
+ const char *name;
+ const int option;
+};
+
+static const struct tcp_optionmap_struct tcp_optionmap[] = {
+ {"wscale", TCPOPT_WINDOW},
+ {"mss", TCPOPT_MAXSEG},
+ {"sack-permitted", TCPOPT_SACK_PERMITTED},
+ {"sack", TCPOPT_SACK},
+ {"timestamp", TCPOPT_TIMESTAMP},
+ {"md5", TCPOPT_MD5SIG},
+ {NULL},
+};
+
+static void tcpoptstrip_help(void)
+{
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-options value strip specified TCP options denoted by value\n"
+" (separated by comma) from TCP header\n"
+" instead of the numeric value, you can also use the following names: \n"
+" mss strip MSS option\n"
+" wscale strip window scaling option\n"
+" sack-permitted strip \"SACK permitted\" option\n"
+" sack strip SACK option\n"
+" timestamp strip timestamp option\n"
+" md5 strip MD5 signature (RFC2385) option\n"
+ );
+}
+
+static void tcpoptstrip_init(struct xt_entry_target *t)
+{
+ struct xt_tcpoptstrip_info *info = (void *)t->data;
+
+ /* strictly necessary? play safe for now. */
+ memset(info->strip_bmap, 0, sizeof(info->strip_bmap));
+}
+
+static void parse_list(struct xt_tcpoptstrip_info *info, char *arg)
+{
+ unsigned int option;
+ char *p;
+ int i;
+
+ while (true) {
+ p = strchr(arg, ',');
+ if (p != NULL)
+ *p = '\0';
+
+ option = 0;
+ for (i = 0; tcp_optionmap[i].name != NULL; i++) {
+ if (!strcmp(tcp_optionmap[i].name, arg)) {
+ option = tcp_optionmap[i].option;
+ break;
+ }
+ }
+
+ if (option != 0 && string_to_number(arg, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM,
+ "Bad TCP option value \"%s\"", arg);
+
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM,
+ "Option value may not be 0 or 1");
+
+ if(tcpoptstrip_test_bit(info->strip_bmap, option))
+ exit_error(PARAMETER_PROBLEM,
+ "Option \"%s\" already specified", arg);
+
+ tcpoptstrip_set_bit(info->strip_bmap, option);
+ if (p == NULL)
+ break;
+ arg = p + 1;
+ }
+}
+
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_info *info = (void *)(*target)->data;
+
+ switch (c) {
+ case '0':
+ if (*flags & F_STRIP)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-options only once");
+ parse_list(info, optarg);
+ *flags |= F_STRIP;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void tcpoptstrip_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: At least one of the strip options must be specified");
+}
+
+static void tcpoptstrip_print_list(bool parse, const struct xt_tcpoptstrip_info *info)
+{
+ bool first = true;
+ unsigned int i,j;
+ const char *name;
+
+ for (i = 0; i < 256; ++i) {
+ if (!tcpoptstrip_test_bit(info->strip_bmap, i))
+ continue;
+
+ putchar(first ? ' ' : ',');
+ first = false;
+
+ name = NULL;
+ for (j = 0; tcp_optionmap[j].name != NULL; j++) {
+ if (tcp_optionmap[j].option == i)
+ name = tcp_optionmap[j].name;
+ }
+
+ if(name)
+ fputs(name, stdout);
+ else
+ printf("%u", i);
+ }
+}
+
+static void tcpoptstrip_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+ printf("TCPOPTSTRIP options");
+ tcpoptstrip_print_list(false, info);
+}
+
+static void tcpoptstrip_save(const void *ip,
+ const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+ printf("--strip-options");
+ tcpoptstrip_print_list(true, info);
+}
+
+static struct xtables_target tcpoptstrip_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+static struct xtables_target tcpoptstrip6_reg = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_reg);
+ xtables_register_target(&tcpoptstrip6_reg);
+}
Index: Makefile
===================================================================
--- Makefile (revision 7065)
+++ 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 TCPOPTSTRIP TRACE
PF_EXT_SELINUX_SLIB:=
PF6_EXT_SELINUX_SLIB:=
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (iptables)
2007-10-06 14:10 ` Sven Schnelle
@ 2007-10-06 14:33 ` Jan Engelhardt
2007-10-06 14:53 ` Sven Schnelle
` (2 more replies)
0 siblings, 3 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-06 14:33 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
On Oct 6 2007 16:10, Sven Schnelle wrote:
>
>Thanks. I've added only a few options, so this list may still be
>extensible ;-)
Well, with md5, it is complete for now. I have gone through net/tcp.h, which is
how I even found TCPOPT_MD5 (though, I knew of the existence of MD5 signatures
for network streams beforehand).
>I've changed the code in the meantime so that names could be specified
>inside the --strip-options argument list, instead of having extra
>options for every tcp option, this makes code smaller, and it is even
>simpler to add new names.
Very good.
> pkts bytes target prot opt in out source destination
> 0 0 TCPOPTSTRIP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x17/0x02 TCPOPTSTRIP options wscale,77
I added support for numeric printing (e.g. iptables -nvL),
so that it shows 3,77 (as requested by -n) instead of wscale,77,
making it behave like the other iptables modules like xt_tcpudp.
I have chosen to always use numeric output for tcpoptstrip_save,
_unlike_ xt_tcpudp, which always uses symbolic names.
Patches following.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [RFC] TCPOPTSTRIP target (iptables)
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:01 ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Jan Engelhardt
2 siblings, 0 replies; 44+ messages in thread
From: Sven Schnelle @ 2007-10-06 14:53 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Patrick McHardy, netfilter-devel
Jan Engelhardt <jengelh@computergmbh.de> writes:
> On Oct 6 2007 16:10, Sven Schnelle wrote:
>> pkts bytes target prot opt in out source destination
>> 0 0 TCPOPTSTRIP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x17/0x02 TCPOPTSTRIP options wscale,77
>
> I added support for numeric printing (e.g. iptables -nvL),
> so that it shows 3,77 (as requested by -n) instead of wscale,77,
> making it behave like the other iptables modules like xt_tcpudp.
Hehe, even though i'm almost always using iptables -nvL, i've missed
that one. Thanks again. :)
> I have chosen to always use numeric output for tcpoptstrip_save,
> _unlike_ xt_tcpudp, which always uses symbolic names.
That's fine with me.
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-06 14:33 ` Jan Engelhardt
2007-10-06 14:53 ` Sven Schnelle
@ 2007-10-06 15:00 ` Jan Engelhardt
2007-10-06 15:19 ` Sven Schnelle
2007-10-08 5:00 ` Patrick McHardy
2007-10-06 15:01 ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Jan Engelhardt
2 siblings, 2 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-06 15:00 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
Add xt_TCPOPTSTRIP, a module to replace TCP options by NOPs.
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 ++
net/netfilter/Kconfig | 7 +
net/netfilter/Makefile | 1
net/netfilter/xt_TCPOPTSTRIP.c | 139 +++++++++++++++++++++++++++++++
4 files changed, 160 insertions(+)
Index: linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ linux-2.6.23/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
Index: linux-2.6.23/net/netfilter/Kconfig
===================================================================
--- linux-2.6.23.orig/net/netfilter/Kconfig
+++ linux-2.6.23/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
+ ---help---
+ This option adds a "TCPOPTSTRIP" target, which allows you to strip
+ TCP options from TCP packets.
+
config NETFILTER_XT_MATCH_COMMENT
tristate '"comment" match support'
depends on NETFILTER_XTABLES
Index: linux-2.6.23/net/netfilter/Makefile
===================================================================
--- linux-2.6.23.orig/net/netfilter/Makefile
+++ linux-2.6.23/net/netfilter/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE)
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
Index: linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ linux-2.6.23/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,140 @@
+/*
+ * A module for stripping a specific TCP option from TCP packets.
+ *
+ * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright © Jan Engelhardt <jengelh@computergmbh.de>, 2007
+ *
+ * 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/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+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 unsigned int
+tcpoptstrip_mangle_packet(struct sk_buff **pskb,
+ const struct xt_tcpoptstrip_info *info,
+ unsigned int tcphoff, unsigned int minlen)
+{
+ unsigned int optl, i, j;
+ struct tcphdr *tcph;
+ u_int16_t n, o;
+ u_int8_t *opt;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+ opt = (u_int8_t *)tcph;
+
+ /*
+ * Walk through all TCP options - if we find some option to remove,
+ * set all octets to %TCPOPT_NOP and adjust checksum.
+ */
+ for (i = sizeof(struct tcphdr); i < tcp_hdrlen(*pskb); i += optl) {
+ optl = optlen(opt, i);
+
+ if (i + optl > tcp_hdrlen(*pskb))
+ break;
+
+ if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
+ continue;
+
+ for (j = 0; j < optl; ++j) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ nf_proto_csum_replace2(&tcph->check, *pskb, htons(o),
+ htons(n), 0);
+ }
+ memset(opt + i, TCPOPT_NOP, optl);
+ }
+
+ return XT_CONTINUE;
+}
+
+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)
+{
+ return tcpoptstrip_mangle_packet(pskb, targinfo, ip_hdrlen(*pskb),
+ sizeof(struct iphdr) + sizeof(struct tcphdr));
+}
+
+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);
+ unsigned int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+ if (tcphoff < 0)
+ return NF_DROP;
+
+ return tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+
+static struct xt_target tcpoptstrip_reg[] __read_mostly = {
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target4,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target6,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_tcpoptstrip_init(void)
+{
+ return xt_register_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+static void __exit xt_tcpoptstrip_exit(void)
+{
+ xt_unregister_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+module_init(xt_tcpoptstrip_init);
+module_exit(xt_tcpoptstrip_exit);
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>");
+MODULE_DESCRIPTION("netfilter TCPOPTSTRIP target module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSTRIP");
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH] TCPOPTSTRIP 20071006 (iptables)
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:01 ` Jan Engelhardt
2007-10-06 15:37 ` Krzysztof Oledzki
2007-10-08 8:22 ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Patrick McHardy
2 siblings, 2 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-06 15:01 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
Adds libxt_TCPOPTSTRIP.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
---
extensions/Makefile | 2
extensions/libxt_TCPOPTSTRIP.c | 206 +++++++++++++++++++++++++++++++
include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 +
3 files changed, 220 insertions(+), 1 deletion(-)
Index: iptables/extensions/Makefile
===================================================================
--- iptables.orig/extensions/Makefile
+++ iptables/extensions/Makefile
@@ -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 TCPOPTSTRIP TRACE
PF_EXT_SELINUX_SLIB:=
PF6_EXT_SELINUX_SLIB:=
Index: iptables/extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- /dev/null
+++ iptables/extensions/libxt_TCPOPTSTRIP.c
@@ -0,0 +1,206 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright © Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+#ifndef TCPOPT_MD5SIG
+# define TCPOPT_MD5SIG 19
+#endif
+
+enum {
+ F_STRIP = 1 << 0,
+};
+
+struct tcp_optionmap_struct {
+ const char *name;
+ const int option;
+};
+
+static const struct option tcpoptstrip_opts[] = {
+ {"strip-options", true, NULL, '0'},
+ {NULL},
+};
+
+static const struct tcp_optionmap_struct tcp_optionmap[] = {
+ {"wscale", TCPOPT_WINDOW},
+ {"mss", TCPOPT_MAXSEG},
+ {"sack-permitted", TCPOPT_SACK_PERMITTED},
+ {"sack", TCPOPT_SACK},
+ {"timestamp", TCPOPT_TIMESTAMP},
+ {"md5", TCPOPT_MD5SIG},
+ {NULL},
+};
+
+static void tcpoptstrip_help(void)
+{
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-options value strip specified TCP options denoted by value\n"
+" (separated by comma) from TCP header\n"
+" Instead of the numeric value, you can also use the following names:\n"
+" mss strip MSS option\n"
+" wscale strip window scaling option\n"
+" sack-permitted strip \"SACK permitted\" option\n"
+" sack strip SACK option\n"
+" timestamp strip timestamp option\n"
+" md5 strip MD5 signature option (RFC2385)\n"
+ );
+}
+
+static void tcpoptstrip_init(struct xt_entry_target *t)
+{
+ struct xt_tcpoptstrip_info *info = (void *)t->data;
+
+ /* strictly necessary? play safe for now. */
+ memset(info->strip_bmap, 0, sizeof(info->strip_bmap));
+}
+
+static void parse_list(struct xt_tcpoptstrip_info *info, char *arg)
+{
+ unsigned int option;
+ char *p;
+ int i;
+
+ while (true) {
+ p = strchr(arg, ',');
+ if (p != NULL)
+ *p = '\0';
+
+ option = 0;
+ for (i = 0; tcp_optionmap[i].name != NULL; ++i)
+ if (strcmp(tcp_optionmap[i].name, arg) == 0) {
+ option = tcp_optionmap[i].option;
+ break;
+ }
+
+ if (option == 0 && string_to_number(arg, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM,
+ "Bad TCP option value \"%s\"", arg);
+
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM,
+ "Option value may not be 0 or 1");
+
+ if (tcpoptstrip_test_bit(info->strip_bmap, option))
+ exit_error(PARAMETER_PROBLEM,
+ "Option \"%s\" already specified", arg);
+
+ tcpoptstrip_set_bit(info->strip_bmap, option);
+ if (p == NULL)
+ break;
+ arg = p + 1;
+ }
+}
+
+static int tcpoptstrip_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_info *info = (void *)(*target)->data;
+
+ switch (c) {
+ case '0':
+ if (*flags & F_STRIP)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-options only once");
+ parse_list(info, optarg);
+ *flags |= F_STRIP;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void tcpoptstrip_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: At least one of the strip options must be specified");
+}
+
+static void tcpoptstrip_print_list(const struct xt_tcpoptstrip_info *info,
+ bool numeric)
+{
+ unsigned int i, j;
+ const char *name;
+ bool first = true;
+
+ for (i = 0; i < 256; ++i) {
+ if (!tcpoptstrip_test_bit(info->strip_bmap, i))
+ continue;
+ if (!first)
+ printf(",");
+
+ first = false;
+ name = NULL;
+ if (!numeric)
+ for (j = 0; tcp_optionmap[j].name != NULL; ++j)
+ if (tcp_optionmap[j].option == i)
+ name = tcp_optionmap[j].name;
+
+ if (name != NULL)
+ printf("%s", name);
+ else
+ printf("%u", i);
+ }
+}
+
+static void tcpoptstrip_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+ printf("TCPOPTSTRIP options ");
+ tcpoptstrip_print_list(info, numeric);
+}
+
+static void tcpoptstrip_save(const void *ip,
+ const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_info *info = (const void *)target->data;
+ printf("--strip-options ");
+ tcpoptstrip_print_list(info, true);
+}
+
+static struct xtables_target tcpoptstrip_target = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+static struct xtables_target tcpoptstrip_target6 = {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_info)),
+ .help = tcpoptstrip_help,
+ .init = tcpoptstrip_init,
+ .parse = tcpoptstrip_parse,
+ .final_check = tcpoptstrip_check,
+ .print = tcpoptstrip_print,
+ .save = tcpoptstrip_save,
+ .extra_opts = tcpoptstrip_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_target);
+ xtables_register_target(&tcpoptstrip_target6);
+}
Index: iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
===================================================================
--- /dev/null
+++ iptables/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
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:00 ` Patrick McHardy
1 sibling, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-06 15:19 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Patrick McHardy, netfilter-devel
Jan Engelhardt <jengelh@computergmbh.de> writes:
> Add xt_TCPOPTSTRIP, a module to replace TCP options by NOPs.
>
> Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
> [..]
Thanks Jan, especially for all the help with a netfilter beginner like
me :). If nobody complains about serious bugs/problems, i'll submit these
patches as the final candidates.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-06 15:19 ` Sven Schnelle
@ 2007-10-06 15:21 ` Jan Engelhardt
2007-10-08 5:05 ` Patrick McHardy
0 siblings, 1 reply; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-06 15:21 UTC (permalink / raw)
To: Sven Schnelle; +Cc: Patrick McHardy, netfilter-devel
On Oct 6 2007 17:19, Sven Schnelle wrote:
>Jan Engelhardt <jengelh@computergmbh.de> writes:
>
>> Add xt_TCPOPTSTRIP, a module to replace TCP options by NOPs.
>>
>> Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
>> [..]
>
>Thanks Jan, especially for all the help with a netfilter beginner like
>me :). If nobody complains about serious bugs/problems, i'll submit these
>patches as the final candidates.
>
Sven, This is already submitted. With every mail you post, you have to fear
that your code is taken into the depths of the kernel source forest ;-)
Patrick, please apply.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] TCPOPTSTRIP 20071006 (iptables)
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
1 sibling, 1 reply; 44+ messages in thread
From: Krzysztof Oledzki @ 2007-10-06 15:37 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, Patrick McHardy, netfilter-devel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1760 bytes --]
On Sat, 6 Oct 2007, Jan Engelhardt wrote:
> +struct tcp_optionmap_struct {
> + const char *name;
> + const int option;
+ const char *desc;
> +};
> +static const struct tcp_optionmap_struct tcp_optionmap[] = {
> + {"wscale", TCPOPT_WINDOW},
> + {"mss", TCPOPT_MAXSEG},
> + {"sack-permitted", TCPOPT_SACK_PERMITTED},
> + {"sack", TCPOPT_SACK},
> + {"timestamp", TCPOPT_TIMESTAMP},
> + {"md5", TCPOPT_MD5SIG},
> + {NULL},
> +};
We could convert spaces into tabs here, plus:
> + {"mss", TCPOPT_MAXSEG, "Maximum Segment Size"},
> + {"wscale", TCPOPT_WINDOW, "Window Scale"},
> + {"sack-permitted", TCPOPT_SACK_PERMITTED, "SACK Permitted"},
> + {"sack", TCPOPT_SACK, "SACK"},
> + {"timestamp", TCPOPT_TIMESTAMP, "Time Stamp"},
> + {"md5", TCPOPT_MD5SIG, "MD5 Signature"},
> + {NULL},
...
> +static void tcpoptstrip_help(void)
> +{
+ int i;
> + printf(
> +"TCPOPTSTRIP target options:\n"
> +" --strip-options value strip specified TCP options denoted by value\n"
> +" (separated by comma) from TCP header\n"
> +" Instead of the numeric value, you can also use the following names:\n"
> + );
+ for (i = 0; tcp_optionmap[i].name != NULL; ++i) {
+ printf("\t%s\t%s\n", tcp_optionmap[i].name, tcp_optionmap[i].desc);
+ };
And remove this:
> +" mss strip MSS option\n"
> +" wscale strip window scaling option\n"
> +" sack-permitted strip \"SACK permitted\" option\n"
> +" sack strip SACK option\n"
> +" timestamp strip timestamp option\n"
> +" md5 strip MD5 signature option (RFC2385)\n"
> + );
Best regsrds,
Krzysztof Olędzki
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/1] TCPOPTSTRIP 20071006 descriptions (iptables)
2007-10-06 15:37 ` Krzysztof Oledzki
@ 2007-10-06 15:52 ` Jan Engelhardt
0 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-06 15:52 UTC (permalink / raw)
To: Krzysztof Oledzki; +Cc: Sven Schnelle, Patrick McHardy, netfilter-devel
On Oct 6 2007 17:37, Krzysztof Oledzki wrote:
>
>> +struct tcp_optionmap_struct {
>> + const char *name;
>> + const int option;
> + const char *desc;
>> +};
>
>> +static const struct tcp_optionmap_struct tcp_optionmap[] = {
>> + {"wscale", TCPOPT_WINDOW},
>> + {"mss", TCPOPT_MAXSEG},
>> + {"sack-permitted", TCPOPT_SACK_PERMITTED},
>> + {"sack", TCPOPT_SACK},
>> + {"timestamp", TCPOPT_TIMESTAMP},
>> + {"md5", TCPOPT_MD5SIG},
>> + {NULL},
>> +};
>
> We could convert spaces into tabs here, plus:
We should not, because that would break alignment.
When adhering to the indent-is-not-alignment distinction (see the one or
other CodingStyle debate on lkml), people can set their tab width to
their preferred value, while code does not look bad with other tab widths.
Only remaining requirement then is that it fits into 80 when \t width is 8,
which is easy; so the overall situation is a plus.
>> + {"mss", TCPOPT_MAXSEG, "Maximum Segment
>> Size"},
>> + {"wscale", TCPOPT_WINDOW, "Window Scale"},
>> + {"sack-permitted", TCPOPT_SACK_PERMITTED, "SACK Permitted"},
>> + {"sack", TCPOPT_SACK, "SACK"},
>> + {"timestamp", TCPOPT_TIMESTAMP, "Time Stamp"},
>> + {"md5", TCPOPT_MD5SIG, "MD5 Signature"},
>> + {NULL},
==
The following patch implements option descriptions after a
suggestion by Krzysztof Olędzki. It goes _on top_ of the
afore-posted libxt_TCPOPTSTRIP patch.
== patch begins here ==
Replace the manually typed help by option description fields.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
---
extensions/libxt_TCPOPTSTRIP.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
Index: iptables/extensions/libxt_TCPOPTSTRIP.c
===================================================================
--- iptables.orig/extensions/libxt_TCPOPTSTRIP.c
+++ iptables/extensions/libxt_TCPOPTSTRIP.c
@@ -19,8 +19,8 @@ enum {
F_STRIP = 1 << 0,
};
-struct tcp_optionmap_struct {
- const char *name;
+struct tcp_optionmap {
+ const char *name, *desc;
const int option;
};
@@ -29,30 +29,29 @@ static const struct option tcpoptstrip_o
{NULL},
};
-static const struct tcp_optionmap_struct tcp_optionmap[] = {
- {"wscale", TCPOPT_WINDOW},
- {"mss", TCPOPT_MAXSEG},
- {"sack-permitted", TCPOPT_SACK_PERMITTED},
- {"sack", TCPOPT_SACK},
- {"timestamp", TCPOPT_TIMESTAMP},
- {"md5", TCPOPT_MD5SIG},
+static const struct tcp_optionmap tcp_optionmap[] = {
+ {"wscale", "Window scale", TCPOPT_WINDOW},
+ {"mss", "Maximum Segment Size", TCPOPT_MAXSEG},
+ {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED},
+ {"sack", "Selective ACK", TCPOPT_SACK},
+ {"timestamp", "Timestamp", TCPOPT_TIMESTAMP},
+ {"md5", "MD5 signature", TCPOPT_MD5SIG},
{NULL},
};
static void tcpoptstrip_help(void)
{
+ const struct tcp_optionmap *w;
+
printf(
"TCPOPTSTRIP target options:\n"
" --strip-options value strip specified TCP options denoted by value\n"
" (separated by comma) from TCP header\n"
" Instead of the numeric value, you can also use the following names:\n"
-" mss strip MSS option\n"
-" wscale strip window scaling option\n"
-" sack-permitted strip \"SACK permitted\" option\n"
-" sack strip SACK option\n"
-" timestamp strip timestamp option\n"
-" md5 strip MD5 signature option (RFC2385)\n"
);
+
+ for (w = tcp_optionmap; w->name != NULL; ++w)
+ printf(" %-14s strip \"%s\" option\n", w->name, w->desc);
}
static void tcpoptstrip_init(struct xt_entry_target *t)
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-06 15:00 ` [PATCH] xt_TCPOPTSTRIP 20071006 (kernel) Jan Engelhardt
2007-10-06 15:19 ` Sven Schnelle
@ 2007-10-08 5:00 ` Patrick McHardy
2007-10-08 7:58 ` Sven Schnelle
2007-10-08 15:55 ` Jan Engelhardt
1 sibling, 2 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-10-08 5:00 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> Add xt_TCPOPTSTRIP, a module to replace TCP options by NOPs.
A few minor comments:
> +#define tcpoptstrip_set_bit(bmap, idx) \
> + (bmap[(idx) >> 5] |= 1UL << (idx & 31))
> +#define tcpoptstrip_test_bit(bmap, idx) \
> + (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
Why UL? You're using 32 bit variables for the bitmap ..
> +struct xt_tcpoptstrip_info {
> + u_int32_t strip_bmap[8];
> +};
> +
> +config NETFILTER_XT_TARGET_TCPOPTSTRIP
> + tristate '"TCPOPTSTRIP" target support'
> + depends on NETFILTER_XTABLES
EXPERIMENTAL please
> + ---help---
> + This option adds a "TCPOPTSTRIP" target, which allows you to strip
> + TCP options from TCP packets.
> +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);
> + unsigned int tcphoff;
> + u_int8_t nexthdr;
> +
> + nexthdr = ipv6h->nexthdr;
> + tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
This needs #ifdef CONFIG_IPV6
A Signed-off-by: line by Sven would also be appreciated - I guess
you can just include the original one since you modified his
patch.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-06 15:21 ` Jan Engelhardt
@ 2007-10-08 5:05 ` Patrick McHardy
0 siblings, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-10-08 5:05 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> On Oct 6 2007 17:19, Sven Schnelle wrote:
>
>>Thanks Jan, especially for all the help with a netfilter beginner like
>>me :). If nobody complains about serious bugs/problems, i'll submit these
>>patches as the final candidates.
>>
>
>
> Sven, This is already submitted. With every mail you post, you have to fear
> that your code is taken into the depths of the kernel source forest ;-)
Not really, I only apply patches when I'm addressed or am
certain otherwise that the submitter wants me to apply it.
> Patrick, please apply.
There were some discussions that new stuff shouldn't appear
so shortly before the merge window opens, so I'll queue it
for 2.6.25 when the last minor issues are addressed.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
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
1 sibling, 1 reply; 44+ messages in thread
From: Sven Schnelle @ 2007-10-08 7:58 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, Jan Engelhardt
[-- Attachment #1: Type: text/plain, Size: 7043 bytes --]
Patrick McHardy <kaber@trash.net> writes:
> Jan Engelhardt wrote:
>> Add xt_TCPOPTSTRIP, a module to replace TCP options by NOPs.
>
> A few minor comments:
> [..]
Added the updated version. This should now be considered as the final
Version. ;-)
Signed-off-by: Sven Schnelle <svens@bitebene.org>
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 +++
net/netfilter/Kconfig | 7 ++
net/netfilter/Makefile | 1 +
net/netfilter/xt_TCPOPTSTRIP.c | 144 ++++++++++++++++++++++++++++++
4 files changed, 165 insertions(+), 0 deletions(-)
create mode 100644 include/linux/netfilter/xt_TCPOPTSTRIP.h
create mode 100644 net/netfilter/xt_TCPOPTSTRIP.c
diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
new file mode 100644
index 0000000..a7edfeb
--- /dev/null
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1 << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1 << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3599770..9830c34 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 EXPERIMENTAL && NETFILTER_XTABLES
+ ---help---
+ This option adds a "TCPOPTSTRIP" target, which allows you to strip
+ TCP options 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..57005bc
--- /dev/null
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,144 @@
+/*
+ * A module for stripping a specific TCP option from TCP packets.
+ *
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright (c) 2007 Jan Engelhardt <jengelh@computergmbh.de>
+ *
+ * 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/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+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 unsigned int
+tcpoptstrip_mangle_packet(struct sk_buff **pskb,
+ const struct xt_tcpoptstrip_info *info,
+ unsigned int tcphoff, unsigned int minlen)
+{
+ unsigned int optl, i, j;
+ struct tcphdr *tcph;
+ u_int16_t n, o;
+ u_int8_t *opt;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+ opt = (u_int8_t *)tcph;
+
+ /*
+ * Walk through all TCP options - if we find some option to remove,
+ * set all octets to %TCPOPT_NOP and adjust checksum.
+ */
+ for (i = sizeof(struct tcphdr); i < tcp_hdrlen(*pskb); i += optl) {
+ optl = optlen(opt, i);
+
+ if (i + optl > tcp_hdrlen(*pskb))
+ return NF_DROP;
+
+ if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
+ continue;
+
+ for (j = 0; j < optl; ++j) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ nf_proto_csum_replace2(&tcph->check, *pskb, htons(o),
+ htons(n), 0);
+ }
+ memset(opt + i, TCPOPT_NOP, optl);
+ }
+
+ return XT_CONTINUE;
+}
+
+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)
+{
+ return tcpoptstrip_mangle_packet(pskb, targinfo, ip_hdrlen(*pskb),
+ sizeof(struct iphdr) + sizeof(struct tcphdr));
+}
+
+#ifdef CONFIG_IPV6
+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);
+ unsigned int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+ if (tcphoff < 0)
+ return NF_DROP;
+
+ return tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+#endif
+
+static struct xt_target tcpoptstrip_reg[] __read_mostly = {
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target4,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+#ifdef CONFIG_IPV6
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = xt_tcpoptstrip_target6,
+ .targetsize = sizeof(struct xt_tcpoptstrip_info),
+ .me = THIS_MODULE,
+ },
+#endif
+};
+
+static int __init xt_tcpoptstrip_init(void)
+{
+ return xt_register_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+static void __exit xt_tcpoptstrip_exit(void)
+{
+ xt_unregister_targets(tcpoptstrip_reg, ARRAY_SIZE(tcpoptstrip_reg));
+}
+
+module_init(xt_tcpoptstrip_init);
+module_exit(xt_tcpoptstrip_exit);
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>");
+MODULE_DESCRIPTION("netfilter TCPOPTSTRIP target module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSTRIP");
--
1.5.3.4
[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-08 7:58 ` Sven Schnelle
@ 2007-10-08 8:20 ` Patrick McHardy
0 siblings, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-10-08 8:20 UTC (permalink / raw)
To: Sven Schnelle; +Cc: netfilter-devel, Jan Engelhardt
Sven Schnelle wrote:
> Added the updated version. This should now be considered as the final
> Version. ;-)
Applied, thanks Sven and Jan.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] TCPOPTSTRIP 20071006 (iptables)
2007-10-06 15:01 ` [PATCH] TCPOPTSTRIP 20071006 (iptables) Jan Engelhardt
2007-10-06 15:37 ` Krzysztof Oledzki
@ 2007-10-08 8:22 ` Patrick McHardy
1 sibling, 0 replies; 44+ messages in thread
From: Patrick McHardy @ 2007-10-08 8:22 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> Adds libxt_TCPOPTSTRIP.
I'll wait with applying this until we've released the next
iptables version, I don't want to get back into releasing
extensions for unreleased targets.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-08 5:00 ` Patrick McHardy
2007-10-08 7:58 ` Sven Schnelle
@ 2007-10-08 15:55 ` Jan Engelhardt
2007-10-08 16:27 ` Patrick McHardy
1 sibling, 1 reply; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-08 15:55 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Sven Schnelle, netfilter-devel
On Oct 8 2007 07:00, Patrick McHardy wrote:
>
>A few minor comments:
>
>> +#define tcpoptstrip_set_bit(bmap, idx) \
>> + (bmap[(idx) >> 5] |= 1UL << (idx & 31))
>> +#define tcpoptstrip_test_bit(bmap, idx) \
>> + (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
>
>Why UL? You're using 32 bit variables for the bitmap ..
Blame linux/bitmap.h. It uses 1UL, but at the same time, limits itself
to uint32_t-based operations.
>> + nexthdr = ipv6h->nexthdr;
>> + tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
>
>This needs #ifdef CONFIG_IPV6
xt_TCPMSS also uses ipv6_skip_exthdr, but has no such protection.
xt_hashlimit uses ipv6_find_hdr, would not that need CONFIG_IPV6 protection
too?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-08 15:55 ` Jan Engelhardt
@ 2007-10-08 16:27 ` Patrick McHardy
2007-10-08 16:42 ` Jan Engelhardt
0 siblings, 1 reply; 44+ messages in thread
From: Patrick McHardy @ 2007-10-08 16:27 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sven Schnelle, netfilter-devel
Jan Engelhardt wrote:
> On Oct 8 2007 07:00, Patrick McHardy wrote:
>
>>A few minor comments:
>>
>>
>>>+#define tcpoptstrip_set_bit(bmap, idx) \
>>>+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
>>>+#define tcpoptstrip_test_bit(bmap, idx) \
>>>+ (((1UL << (idx & 31)) & bmap[(idx) >> 5]) != 0)
>>
>>Why UL? You're using 32 bit variables for the bitmap ..
>
>
> Blame linux/bitmap.h. It uses 1UL, but at the same time, limits itself
> to uint32_t-based operations.
It uses purely unsigned long, just as the bitops do.
>>>+ nexthdr = ipv6h->nexthdr;
>>>+ tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
>>
>>This needs #ifdef CONFIG_IPV6
>
>
> xt_TCPMSS also uses ipv6_skip_exthdr, but has no such protection.
> xt_hashlimit uses ipv6_find_hdr, would not that need CONFIG_IPV6 protection
> too?
Both use CONFIG_IP6_NF_IPTABLES, which is a superset of CONFIG_IPV6.
Will try if TCPOPTSTRIP actually needs that too.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] xt_TCPOPTSTRIP 20071006 (kernel)
2007-10-08 16:27 ` Patrick McHardy
@ 2007-10-08 16:42 ` Jan Engelhardt
0 siblings, 0 replies; 44+ messages in thread
From: Jan Engelhardt @ 2007-10-08 16:42 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Sven Schnelle, netfilter-devel
On Oct 8 2007 18:27, Patrick McHardy wrote:
>>>>+#define tcpoptstrip_set_bit(bmap, idx) \
>>>>+ (bmap[(idx) >> 5] |= 1UL << (idx & 31))
>>
>> Blame linux/bitmap.h. It uses 1UL, but at the same time, limits itself
>> to uint32_t-based operations.
>
>It uses purely unsigned long, just as the bitops do.
Hm, you are right.
Blame asm-i386/bitops.h instead - 1UL in there. :)
^ permalink raw reply [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).