aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/xt_TCPMSS.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index cd24290f3b2f..62776de8293c 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -43,10 +43,41 @@ optlen(const u_int8_t *opt, unsigned int offset)
43 return opt[offset+1]; 43 return opt[offset+1];
44} 44}
45 45
46static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
47 unsigned int family)
48{
49 struct flowi fl;
50 const struct nf_afinfo *ai;
51 struct rtable *rt = NULL;
52 u_int32_t mtu = ~0U;
53
54 if (family == PF_INET) {
55 struct flowi4 *fl4 = &fl.u.ip4;
56 memset(fl4, 0, sizeof(*fl4));
57 fl4->daddr = ip_hdr(skb)->saddr;
58 } else {
59 struct flowi6 *fl6 = &fl.u.ip6;
60
61 memset(fl6, 0, sizeof(*fl6));
62 fl6->daddr = ipv6_hdr(skb)->saddr;
63 }
64 rcu_read_lock();
65 ai = nf_get_afinfo(family);
66 if (ai != NULL)
67 ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
68 rcu_read_unlock();
69
70 if (rt != NULL) {
71 mtu = dst_mtu(&rt->dst);
72 dst_release(&rt->dst);
73 }
74 return mtu;
75}
76
46static int 77static int
47tcpmss_mangle_packet(struct sk_buff *skb, 78tcpmss_mangle_packet(struct sk_buff *skb,
48 const struct xt_action_param *par, 79 const struct xt_action_param *par,
49 unsigned int in_mtu, 80 unsigned int family,
50 unsigned int tcphoff, 81 unsigned int tcphoff,
51 unsigned int minlen) 82 unsigned int minlen)
52{ 83{
@@ -76,6 +107,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
76 return -1; 107 return -1;
77 108
78 if (info->mss == XT_TCPMSS_CLAMP_PMTU) { 109 if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
110 unsigned int in_mtu = tcpmss_reverse_mtu(skb, family);
111
79 if (dst_mtu(skb_dst(skb)) <= minlen) { 112 if (dst_mtu(skb_dst(skb)) <= minlen) {
80 net_err_ratelimited("unknown or invalid path-MTU (%u)\n", 113 net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
81 dst_mtu(skb_dst(skb))); 114 dst_mtu(skb_dst(skb)));
@@ -165,37 +198,6 @@ tcpmss_mangle_packet(struct sk_buff *skb,
165 return TCPOLEN_MSS; 198 return TCPOLEN_MSS;
166} 199}
167 200
168static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
169 unsigned int family)
170{
171 struct flowi fl;
172 const struct nf_afinfo *ai;
173 struct rtable *rt = NULL;
174 u_int32_t mtu = ~0U;
175
176 if (family == PF_INET) {
177 struct flowi4 *fl4 = &fl.u.ip4;
178 memset(fl4, 0, sizeof(*fl4));
179 fl4->daddr = ip_hdr(skb)->saddr;
180 } else {
181 struct flowi6 *fl6 = &fl.u.ip6;
182
183 memset(fl6, 0, sizeof(*fl6));
184 fl6->daddr = ipv6_hdr(skb)->saddr;
185 }
186 rcu_read_lock();
187 ai = nf_get_afinfo(family);
188 if (ai != NULL)
189 ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
190 rcu_read_unlock();
191
192 if (rt != NULL) {
193 mtu = dst_mtu(&rt->dst);
194 dst_release(&rt->dst);
195 }
196 return mtu;
197}
198
199static unsigned int 201static unsigned int
200tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) 202tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
201{ 203{
@@ -204,7 +206,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
204 int ret; 206 int ret;
205 207
206 ret = tcpmss_mangle_packet(skb, par, 208 ret = tcpmss_mangle_packet(skb, par,
207 tcpmss_reverse_mtu(skb, PF_INET), 209 PF_INET,
208 iph->ihl * 4, 210 iph->ihl * 4,
209 sizeof(*iph) + sizeof(struct tcphdr)); 211 sizeof(*iph) + sizeof(struct tcphdr));
210 if (ret < 0) 212 if (ret < 0)
@@ -233,7 +235,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
233 if (tcphoff < 0) 235 if (tcphoff < 0)
234 return NF_DROP; 236 return NF_DROP;
235 ret = tcpmss_mangle_packet(skb, par, 237 ret = tcpmss_mangle_packet(skb, par,
236 tcpmss_reverse_mtu(skb, PF_INET6), 238 PF_INET6,
237 tcphoff, 239 tcphoff,
238 sizeof(*ipv6h) + sizeof(struct tcphdr)); 240 sizeof(*ipv6h) + sizeof(struct tcphdr));
239 if (ret < 0) 241 if (ret < 0)