|
@@ -43,10 +43,41 @@ optlen(const u_int8_t *opt, unsigned int offset)
|
|
|
return opt[offset+1];
|
|
|
}
|
|
|
|
|
|
+static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
|
|
|
+ unsigned int family)
|
|
|
+{
|
|
|
+ struct flowi fl;
|
|
|
+ const struct nf_afinfo *ai;
|
|
|
+ struct rtable *rt = NULL;
|
|
|
+ u_int32_t mtu = ~0U;
|
|
|
+
|
|
|
+ if (family == PF_INET) {
|
|
|
+ struct flowi4 *fl4 = &fl.u.ip4;
|
|
|
+ memset(fl4, 0, sizeof(*fl4));
|
|
|
+ fl4->daddr = ip_hdr(skb)->saddr;
|
|
|
+ } else {
|
|
|
+ struct flowi6 *fl6 = &fl.u.ip6;
|
|
|
+
|
|
|
+ memset(fl6, 0, sizeof(*fl6));
|
|
|
+ fl6->daddr = ipv6_hdr(skb)->saddr;
|
|
|
+ }
|
|
|
+ rcu_read_lock();
|
|
|
+ ai = nf_get_afinfo(family);
|
|
|
+ if (ai != NULL)
|
|
|
+ ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ if (rt != NULL) {
|
|
|
+ mtu = dst_mtu(&rt->dst);
|
|
|
+ dst_release(&rt->dst);
|
|
|
+ }
|
|
|
+ return mtu;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
tcpmss_mangle_packet(struct sk_buff *skb,
|
|
|
const struct xt_action_param *par,
|
|
|
- unsigned int in_mtu,
|
|
|
+ unsigned int family,
|
|
|
unsigned int tcphoff,
|
|
|
unsigned int minlen)
|
|
|
{
|
|
@@ -76,6 +107,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
|
|
return -1;
|
|
|
|
|
|
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
|
|
|
+ unsigned int in_mtu = tcpmss_reverse_mtu(skb, family);
|
|
|
+
|
|
|
if (dst_mtu(skb_dst(skb)) <= minlen) {
|
|
|
net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
|
|
|
dst_mtu(skb_dst(skb)));
|
|
@@ -165,37 +198,6 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
|
|
return TCPOLEN_MSS;
|
|
|
}
|
|
|
|
|
|
-static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
|
|
|
- unsigned int family)
|
|
|
-{
|
|
|
- struct flowi fl;
|
|
|
- const struct nf_afinfo *ai;
|
|
|
- struct rtable *rt = NULL;
|
|
|
- u_int32_t mtu = ~0U;
|
|
|
-
|
|
|
- if (family == PF_INET) {
|
|
|
- struct flowi4 *fl4 = &fl.u.ip4;
|
|
|
- memset(fl4, 0, sizeof(*fl4));
|
|
|
- fl4->daddr = ip_hdr(skb)->saddr;
|
|
|
- } else {
|
|
|
- struct flowi6 *fl6 = &fl.u.ip6;
|
|
|
-
|
|
|
- memset(fl6, 0, sizeof(*fl6));
|
|
|
- fl6->daddr = ipv6_hdr(skb)->saddr;
|
|
|
- }
|
|
|
- rcu_read_lock();
|
|
|
- ai = nf_get_afinfo(family);
|
|
|
- if (ai != NULL)
|
|
|
- ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
|
|
|
- rcu_read_unlock();
|
|
|
-
|
|
|
- if (rt != NULL) {
|
|
|
- mtu = dst_mtu(&rt->dst);
|
|
|
- dst_release(&rt->dst);
|
|
|
- }
|
|
|
- return mtu;
|
|
|
-}
|
|
|
-
|
|
|
static unsigned int
|
|
|
tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
|
|
{
|
|
@@ -204,7 +206,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
|
|
int ret;
|
|
|
|
|
|
ret = tcpmss_mangle_packet(skb, par,
|
|
|
- tcpmss_reverse_mtu(skb, PF_INET),
|
|
|
+ PF_INET,
|
|
|
iph->ihl * 4,
|
|
|
sizeof(*iph) + sizeof(struct tcphdr));
|
|
|
if (ret < 0)
|
|
@@ -233,7 +235,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
|
|
if (tcphoff < 0)
|
|
|
return NF_DROP;
|
|
|
ret = tcpmss_mangle_packet(skb, par,
|
|
|
- tcpmss_reverse_mtu(skb, PF_INET6),
|
|
|
+ PF_INET6,
|
|
|
tcphoff,
|
|
|
sizeof(*ipv6h) + sizeof(struct tcphdr));
|
|
|
if (ret < 0)
|