All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch */3] some xtables changes
@ 2007-01-25 21:12 Jan Engelhardt
  2007-01-25 21:14 ` [patch 1/3] Fix return values for LOG and ULOG Jan Engelhardt
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Jan Engelhardt @ 2007-01-25 21:12 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Developer Mailing List

Hi,


the following three patches are a rebase to 2.6.20-rc6 for the archived 
patches/messages
https://lists.netfilter.org/pipermail/netfilter-devel/2007-January/026669.html
026670.html and 026671.html.

	-`J'
-- 

^ permalink raw reply	[flat|nested] 10+ messages in thread
* [patch] netfilter: implement TCPMSS target for IPv6
@ 2007-01-14 19:20 David Madore
  2007-01-14 20:10 ` Jan Engelhardt
  0 siblings, 1 reply; 10+ messages in thread
From: David Madore @ 2007-01-14 19:20 UTC (permalink / raw)
  To: netfilter-devel, kaber; +Cc: linux-kernel

Implement TCPMSS target for IPv6 by shamelessly copying from
Marc Boucher's IPv4 implementation.

Signed-off-by: David A. Madore <david.madore@ens.fr>

---

 Note: The patch for ip6tables to make use of this module can be
 obtained from <URL:
 ftp://quatramaran.ens.fr/pub/madore/misc/ip6t-TCPMSS/
 > (also contains a version of this same patch for 2.6.19.2).

 include/linux/netfilter_ipv6/ip6t_TCPMSS.h |   10 ++
 net/ipv6/netfilter/Kconfig                 |   26 ++++
 net/ipv6/netfilter/Makefile                |    1 +
 net/ipv6/netfilter/ip6t_TCPMSS.c           |  225 ++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+), 0 deletions(-)

diff --git a/include/linux/netfilter_ipv6/ip6t_TCPMSS.h b/include/linux/netfilter_ipv6/ip6t_TCPMSS.h
new file mode 100644
index 0000000..412d1cb
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_TCPMSS.h
@@ -0,0 +1,10 @@
+#ifndef _IP6T_TCPMSS_H
+#define _IP6T_TCPMSS_H
+
+struct ip6t_tcpmss_info {
+	u_int16_t mss;
+};
+
+#define IP6T_TCPMSS_CLAMP_PMTU 0xffff
+
+#endif /*_IP6T_TCPMSS_H*/
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index adcd613..3890a59 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -154,6 +154,32 @@ config IP6_NF_TARGET_REJECT
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_TARGET_TCPMSS
+	tristate "TCPMSS target support"
+	depends on IP6_NF_IPTABLES
+	---help---
+	  This option adds a `TCPMSS' target, which allows you to alter the
+	  MSS value of TCP SYN packets, to control the maximum size for that
+	  connection (usually limiting it to your outgoing interface's MTU
+	  minus 60).
+
+	  This is used to overcome criminally braindead ISPs or servers which
+	  block ICMPv6 Packet Too Big packets.  The symptoms of this
+	  problem are that everything works fine from your Linux
+	  firewall/router, but machines behind it can never exchange large
+	  packets:
+	  	1) Web browsers connect, then hang with no data received.
+	  	2) Small mail works fine, but large emails hang.
+	  	3) ssh works fine, but scp hangs after initial handshaking.
+
+	  Workaround: activate this option and add a rule to your firewall
+	  configuration like:
+
+	  ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
+	  		 -j TCPMSS --clamp-mss-to-pmtu
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP6_NF_MANGLE
 	tristate "Packet mangling"
 	depends on IP6_NF_IPTABLES
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index ac1dfeb..616a006 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
+obj-$(CONFIG_IP6_NF_TARGET_TCPMSS) += ip6t_TCPMSS.o
 
 # objects for l3 independent conntrack
 nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
diff --git a/net/ipv6/netfilter/ip6t_TCPMSS.c b/net/ipv6/netfilter/ip6t_TCPMSS.c
new file mode 100644
index 0000000..ab492c3
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_TCPMSS.c
@@ -0,0 +1,225 @@
+/*
+ * This is a module which is used for setting the MSS option in TCP packets.
+ *
+ * Copyright (C) 2007 David Madore <david.madore@ens.fr>
+ *
+ * Shamelessly based on net/ipv4/netfilter/ipt_TCPMSS.c
+ *
+ * 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 <net/ipv6.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_TCPMSS.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Madore <david.madore@ens.fr>");
+MODULE_DESCRIPTION("ip6tables TCP MSS modification module");
+
+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
+ip6t_tcpmss_target(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)
+{
+	const struct ip6t_tcpmss_info *tcpmssinfo = targinfo;
+	struct tcphdr *tcph;
+	struct ipv6hdr *ipv6h;
+	u_int8_t nexthdr;
+	int tcphoff;
+	u_int16_t tcplen, newmss;
+	__be16 newiplen, oldval;
+	unsigned int i;
+	u_int8_t *opt;
+
+	if (!skb_make_writable(pskb, (*pskb)->len))
+		return NF_DROP;
+
+	ipv6h = (*pskb)->nh.ipv6h;
+	nexthdr = ipv6h->nexthdr;
+	tcphoff = ipv6_skip_exthdr(*pskb, sizeof(struct ipv6hdr), &nexthdr);
+	if ((tcphoff < 0) || (tcphoff > (*pskb)->len)) {
+		if (net_ratelimit())
+			printk(KERN_ERR
+			       "ip6t_tcpmss_target: can't find TCP header\n");
+		return NF_DROP;
+	}
+	tcplen = (*pskb)->len - tcphoff;
+	if ((nexthdr != IPPROTO_TCP) || (tcplen < sizeof(struct tcphdr))) {
+		/* Can't happen (see other comment below)? */
+		if (net_ratelimit())
+			printk(KERN_ERR
+			       "ip6t_tcpmss_target: bad TCP header\n");
+		return NF_DROP;
+	}
+	tcph = (void *)ipv6h + tcphoff;
+
+	/* Since it passed flags test in tcp match, we know it is is
+	   not a fragment, and has data >= tcp header length.  SYN
+	   packets should not contain data: if they did, then we risk
+	   running over MTU, sending Frag Needed and breaking things
+	   badly. --RR */
+	if (tcplen != tcph->doff*4) {
+		if (net_ratelimit())
+			printk(KERN_ERR
+			       "ip6t_tcpmss_target: bad length (%d bytes)\n",
+			       (*pskb)->len);
+		return NF_DROP;
+	}
+
+	if (tcpmssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU) {
+		if (dst_mtu((*pskb)->dst) <= sizeof(struct ipv6hdr) +
+					     sizeof(struct tcphdr)) {
+			if (net_ratelimit())
+				printk(KERN_ERR "ip6t_tcpmss_target: "
+				       "unknown or invalid path-MTU (%d)\n",
+				       dst_mtu((*pskb)->dst));
+			return NF_DROP; /* or IP6T_CONTINUE ?? */
+		}
+
+		newmss = dst_mtu((*pskb)->dst) - sizeof(struct ipv6hdr) -
+						 sizeof(struct tcphdr);
+	} else
+		newmss = tcpmssinfo->mss;
+
+ 	opt = (u_int8_t *)tcph;
+	for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
+		if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
+		    opt[i+1] == TCPOLEN_MSS) {
+			u_int16_t oldmss;
+
+			oldmss = (opt[i+2] << 8) | opt[i+3];
+
+			if (tcpmssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU &&
+			    oldmss <= newmss)
+				return IP6T_CONTINUE;
+
+			opt[i+2] = (newmss & 0xff00) >> 8;
+			opt[i+3] = (newmss & 0x00ff);
+
+			nf_proto_csum_replace2(&tcph->check, *pskb,
+					       htons(oldmss), htons(newmss), 0);
+			return IP6T_CONTINUE;
+		}
+	}
+
+	/*
+	 * MSS Option not found ?! add it..
+	 */
+	if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
+		struct sk_buff *newskb;
+
+		newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
+					 TCPOLEN_MSS, GFP_ATOMIC);
+		if (!newskb)
+			return NF_DROP;
+		kfree_skb(*pskb);
+		*pskb = newskb;
+		ipv6h = (*pskb)->nh.ipv6h;
+		tcph = (void *)ipv6h + tcphoff;
+	}
+
+	skb_put((*pskb), TCPOLEN_MSS);
+
+ 	opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
+	memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
+
+ 	nf_proto_csum_replace2(&tcph->check, *pskb,
+ 				htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
+	opt[0] = TCPOPT_MSS;
+	opt[1] = TCPOLEN_MSS;
+	opt[2] = (newmss & 0xff00) >> 8;
+	opt[3] = (newmss & 0x00ff);
+
+ 	nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
+
+	oldval = ((__be16 *)tcph)[6];
+	tcph->doff += TCPOLEN_MSS/4;
+ 	nf_proto_csum_replace2(&tcph->check, *pskb,
+ 				oldval, ((__be16 *)tcph)[6], 0);
+
+	newiplen = htons(ntohs(ipv6h->payload_len) + TCPOLEN_MSS);
+	ipv6h->payload_len = newiplen;
+	return IP6T_CONTINUE;
+}
+
+#define TH_SYN 0x02
+
+static inline int find_syn_match(const struct ip6t_entry_match *m)
+{
+	const struct ip6t_tcp *tcpinfo = (const struct ip6t_tcp *)m->data;
+
+	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
+	    tcpinfo->flg_cmp & TH_SYN &&
+	    !(tcpinfo->invflags & IP6T_TCP_INV_FLAGS))
+		return 1;
+
+	return 0;
+}
+
+/* Must specify -p tcp --syn/--tcp-flags SYN */
+static int
+ip6t_tcpmss_checkentry(const char *tablename,
+		       const void *e_void,
+		       const struct xt_target *target,
+		       void *targinfo,
+		       unsigned int hook_mask)
+{
+	const struct ip6t_tcpmss_info *tcpmssinfo = targinfo;
+	const struct ip6t_entry *e = e_void;
+
+	if (tcpmssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU &&
+	    (hook_mask & ~((1 << NF_IP6_FORWARD) |
+			   (1 << NF_IP6_LOCAL_OUT) |
+			   (1 << NF_IP6_POST_ROUTING))) != 0) {
+		printk("TCPMSS: path-MTU clamping only supported in "
+		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
+		return 0;
+	}
+
+	if (IP6T_MATCH_ITERATE(e, find_syn_match))
+		return 1;
+	printk("TCPMSS: Only works on TCP SYN packets\n");
+	return 0;
+}
+
+static struct ip6t_target ip6t_tcpmss_reg = {
+	.name		= "TCPMSS",
+	.target		= ip6t_tcpmss_target,
+	.targetsize	= sizeof(struct ip6t_tcpmss_info),
+	.proto		= IPPROTO_TCP,
+	.checkentry	= ip6t_tcpmss_checkentry,
+	.me		= THIS_MODULE,
+};
+
+static int __init ip6t_tcpmss_init(void)
+{
+	return ip6t_register_target(&ip6t_tcpmss_reg);
+}
+
+static void __exit ip6t_tcpmss_fini(void)
+{
+	ip6t_unregister_target(&ip6t_tcpmss_reg);
+}
+
+module_init(ip6t_tcpmss_init);
+module_exit(ip6t_tcpmss_fini);

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

end of thread, other threads:[~2007-01-26 16:18 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-25 21:12 [patch */3] some xtables changes Jan Engelhardt
2007-01-25 21:14 ` [patch 1/3] Fix return values for LOG and ULOG Jan Engelhardt
2007-01-26 14:03   ` Patrick McHardy
2007-01-25 21:45 ` [patch 2/3] some xtables changes (xt_match,xt_target) Jan Engelhardt
2007-01-26 14:17   ` Patrick McHardy
2007-01-25 22:15 ` [patch 3/3] some xtables changes (xt_table) Jan Engelhardt
2007-01-26 14:21   ` Patrick McHardy
2007-01-26 16:05     ` [PATCH */3] several messages Jan Engelhardt
2007-01-26 16:18       ` Patrick McHardy
  -- strict thread matches above, loose matches on Subject: below --
2007-01-14 19:20 [patch] netfilter: implement TCPMSS target for IPv6 David Madore
2007-01-14 20:10 ` Jan Engelhardt
2007-01-15  8:39   ` Patrick McHardy
2007-01-15 10:12     ` Jan Engelhardt
2007-01-15 10:18       ` Patrick McHardy
2007-01-15 14:40         ` [PATCH] Re: ipt->xt (was: implement TCPMSS target for IPv6) Jan Engelhardt
2007-01-15 14:51           ` [PATCH] Re: ipt->xt Patrick McHardy
2007-01-15 16:34             ` ipt->xt Jan Engelhardt
2007-01-15 16:36               ` ipt->xt Patrick McHardy
2007-01-15 16:39                 ` ipt->xt [p2] Jan Engelhardt
2007-01-17 11:31                   ` Patrick McHardy
2007-01-17 12:38                     ` Jan Engelhardt
2007-01-17 12:40                       ` Patrick McHardy
2007-01-17 13:13                         ` ipt->xt [p3] Jan Engelhardt
2007-01-17 13:17                           ` Jan Engelhardt
2007-01-17 14:14                             ` [PATCH 1/3] Fix return values for LOG and ULOG Jan Engelhardt

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