diff options
author | Jan Engelhardt <jengelh@computergmbh.de> | 2008-01-31 07:06:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:27:42 -0500 |
commit | 37c08387fc31a0fe7a570664c93be4f1c1bc0c94 (patch) | |
tree | 30dc561200b0ada3fe92da4b4cdd39d18565b093 /net/netfilter | |
parent | df200969b1627e8f1cda7ce8c0707863f91bb81b (diff) |
[NETFILTER]: xt_TCPMSS: consider reverse route's MTU in clamp-to-pmtu
The TCPMSS target in Xtables should consider the MTU of the reverse
route on forwarded packets as part of the path MTU.
Point in case: IN=ppp0, OUT=eth0. MSS set to 1460 in spite of MTU of
ppp0 being 1392.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/xt_TCPMSS.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 60e3767cc71d..217e2b686322 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -13,7 +13,10 @@ | |||
13 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
14 | #include <linux/ipv6.h> | 14 | #include <linux/ipv6.h> |
15 | #include <linux/tcp.h> | 15 | #include <linux/tcp.h> |
16 | #include <net/dst.h> | ||
17 | #include <net/flow.h> | ||
16 | #include <net/ipv6.h> | 18 | #include <net/ipv6.h> |
19 | #include <net/route.h> | ||
17 | #include <net/tcp.h> | 20 | #include <net/tcp.h> |
18 | 21 | ||
19 | #include <linux/netfilter_ipv4/ip_tables.h> | 22 | #include <linux/netfilter_ipv4/ip_tables.h> |
@@ -41,6 +44,7 @@ optlen(const u_int8_t *opt, unsigned int offset) | |||
41 | static int | 44 | static int |
42 | tcpmss_mangle_packet(struct sk_buff *skb, | 45 | tcpmss_mangle_packet(struct sk_buff *skb, |
43 | const struct xt_tcpmss_info *info, | 46 | const struct xt_tcpmss_info *info, |
47 | unsigned int in_mtu, | ||
44 | unsigned int tcphoff, | 48 | unsigned int tcphoff, |
45 | unsigned int minlen) | 49 | unsigned int minlen) |
46 | { | 50 | { |
@@ -76,7 +80,13 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
76 | dst_mtu(skb->dst)); | 80 | dst_mtu(skb->dst)); |
77 | return -1; | 81 | return -1; |
78 | } | 82 | } |
79 | newmss = dst_mtu(skb->dst) - minlen; | 83 | if (in_mtu <= minlen) { |
84 | if (net_ratelimit()) | ||
85 | printk(KERN_ERR "xt_TCPMSS: unknown or " | ||
86 | "invalid path-MTU (%u)\n", in_mtu); | ||
87 | return -1; | ||
88 | } | ||
89 | newmss = min(dst_mtu(skb->dst), in_mtu) - minlen; | ||
80 | } else | 90 | } else |
81 | newmss = info->mss; | 91 | newmss = info->mss; |
82 | 92 | ||
@@ -137,6 +147,28 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
137 | return TCPOLEN_MSS; | 147 | return TCPOLEN_MSS; |
138 | } | 148 | } |
139 | 149 | ||
150 | static u_int32_t tcpmss_reverse_mtu4(const struct iphdr *iph) | ||
151 | { | ||
152 | struct flowi fl = { | ||
153 | .fl4_dst = iph->saddr, | ||
154 | }; | ||
155 | const struct nf_afinfo *ai; | ||
156 | struct rtable *rt = NULL; | ||
157 | u_int32_t mtu = ~0U; | ||
158 | |||
159 | rcu_read_lock(); | ||
160 | ai = nf_get_afinfo(AF_INET); | ||
161 | if (ai != NULL) | ||
162 | ai->route((struct dst_entry **)&rt, &fl); | ||
163 | rcu_read_unlock(); | ||
164 | |||
165 | if (rt != NULL) { | ||
166 | mtu = dst_mtu(&rt->u.dst); | ||
167 | dst_release(&rt->u.dst); | ||
168 | } | ||
169 | return mtu; | ||
170 | } | ||
171 | |||
140 | static unsigned int | 172 | static unsigned int |
141 | tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, | 173 | tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, |
142 | const struct net_device *out, unsigned int hooknum, | 174 | const struct net_device *out, unsigned int hooknum, |
@@ -146,7 +178,8 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, | |||
146 | __be16 newlen; | 178 | __be16 newlen; |
147 | int ret; | 179 | int ret; |
148 | 180 | ||
149 | ret = tcpmss_mangle_packet(skb, targinfo, iph->ihl * 4, | 181 | ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu4(iph), |
182 | iph->ihl * 4, | ||
150 | sizeof(*iph) + sizeof(struct tcphdr)); | 183 | sizeof(*iph) + sizeof(struct tcphdr)); |
151 | if (ret < 0) | 184 | if (ret < 0) |
152 | return NF_DROP; | 185 | return NF_DROP; |
@@ -160,6 +193,28 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, | |||
160 | } | 193 | } |
161 | 194 | ||
162 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 195 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
196 | static u_int32_t tcpmss_reverse_mtu6(const struct ipv6hdr *iph) | ||
197 | { | ||
198 | struct flowi fl = { | ||
199 | .fl6_dst = iph->saddr, | ||
200 | }; | ||
201 | const struct nf_afinfo *ai; | ||
202 | struct rtable *rt = NULL; | ||
203 | u_int32_t mtu = ~0U; | ||
204 | |||
205 | rcu_read_lock(); | ||
206 | ai = nf_get_afinfo(AF_INET6); | ||
207 | if (ai != NULL) | ||
208 | ai->route((struct dst_entry **)&rt, &fl); | ||
209 | rcu_read_unlock(); | ||
210 | |||
211 | if (rt != NULL) { | ||
212 | mtu = dst_mtu(&rt->u.dst); | ||
213 | dst_release(&rt->u.dst); | ||
214 | } | ||
215 | return mtu; | ||
216 | } | ||
217 | |||
163 | static unsigned int | 218 | static unsigned int |
164 | tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, | 219 | tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, |
165 | const struct net_device *out, unsigned int hooknum, | 220 | const struct net_device *out, unsigned int hooknum, |
@@ -174,7 +229,8 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, | |||
174 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); | 229 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); |
175 | if (tcphoff < 0) | 230 | if (tcphoff < 0) |
176 | return NF_DROP; | 231 | return NF_DROP; |
177 | ret = tcpmss_mangle_packet(skb, targinfo, tcphoff, | 232 | ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu6(ipv6h), |
233 | tcphoff, | ||
178 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 234 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
179 | if (ret < 0) | 235 | if (ret < 0) |
180 | return NF_DROP; | 236 | return NF_DROP; |