diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/xt_TCPMSS.c | 25 | ||||
-rw-r--r-- | net/netfilter/xt_TCPOPTSTRIP.c | 6 |
2 files changed, 22 insertions, 9 deletions
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index afaebc766933..7011c71646f0 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -45,17 +45,22 @@ optlen(const u_int8_t *opt, unsigned int offset) | |||
45 | 45 | ||
46 | static int | 46 | static int |
47 | tcpmss_mangle_packet(struct sk_buff *skb, | 47 | tcpmss_mangle_packet(struct sk_buff *skb, |
48 | const struct xt_tcpmss_info *info, | 48 | const struct xt_action_param *par, |
49 | unsigned int in_mtu, | 49 | unsigned int in_mtu, |
50 | unsigned int tcphoff, | 50 | unsigned int tcphoff, |
51 | unsigned int minlen) | 51 | unsigned int minlen) |
52 | { | 52 | { |
53 | const struct xt_tcpmss_info *info = par->targinfo; | ||
53 | struct tcphdr *tcph; | 54 | struct tcphdr *tcph; |
54 | unsigned int tcplen, i; | 55 | unsigned int tcplen, i; |
55 | __be16 oldval; | 56 | __be16 oldval; |
56 | u16 newmss; | 57 | u16 newmss; |
57 | u8 *opt; | 58 | u8 *opt; |
58 | 59 | ||
60 | /* This is a fragment, no TCP header is available */ | ||
61 | if (par->fragoff != 0) | ||
62 | return XT_CONTINUE; | ||
63 | |||
59 | if (!skb_make_writable(skb, skb->len)) | 64 | if (!skb_make_writable(skb, skb->len)) |
60 | return -1; | 65 | return -1; |
61 | 66 | ||
@@ -125,11 +130,17 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
125 | 130 | ||
126 | skb_put(skb, TCPOLEN_MSS); | 131 | skb_put(skb, TCPOLEN_MSS); |
127 | 132 | ||
128 | /* RFC 879 states that the default MSS is 536 without specific | 133 | /* |
129 | * knowledge that the destination host is prepared to accept larger. | 134 | * IPv4: RFC 1122 states "If an MSS option is not received at |
130 | * Since no MSS was provided, we MUST NOT set a value > 536. | 135 | * connection setup, TCP MUST assume a default send MSS of 536". |
136 | * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum | ||
137 | * length IPv6 header of 60, ergo the default MSS value is 1220 | ||
138 | * Since no MSS was provided, we must use the default values | ||
131 | */ | 139 | */ |
132 | newmss = min(newmss, (u16)536); | 140 | if (par->family == NFPROTO_IPV4) |
141 | newmss = min(newmss, (u16)536); | ||
142 | else | ||
143 | newmss = min(newmss, (u16)1220); | ||
133 | 144 | ||
134 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | 145 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); |
135 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | 146 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); |
@@ -188,7 +199,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) | |||
188 | __be16 newlen; | 199 | __be16 newlen; |
189 | int ret; | 200 | int ret; |
190 | 201 | ||
191 | ret = tcpmss_mangle_packet(skb, par->targinfo, | 202 | ret = tcpmss_mangle_packet(skb, par, |
192 | tcpmss_reverse_mtu(skb, PF_INET), | 203 | tcpmss_reverse_mtu(skb, PF_INET), |
193 | iph->ihl * 4, | 204 | iph->ihl * 4, |
194 | sizeof(*iph) + sizeof(struct tcphdr)); | 205 | sizeof(*iph) + sizeof(struct tcphdr)); |
@@ -217,7 +228,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
217 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); | 228 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); |
218 | if (tcphoff < 0) | 229 | if (tcphoff < 0) |
219 | return NF_DROP; | 230 | return NF_DROP; |
220 | ret = tcpmss_mangle_packet(skb, par->targinfo, | 231 | ret = tcpmss_mangle_packet(skb, par, |
221 | tcpmss_reverse_mtu(skb, PF_INET6), | 232 | tcpmss_reverse_mtu(skb, PF_INET6), |
222 | tcphoff, | 233 | tcphoff, |
223 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 234 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 1eb1a44bfd3d..b68fa191710f 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c | |||
@@ -48,11 +48,13 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
48 | return NF_DROP; | 48 | return NF_DROP; |
49 | 49 | ||
50 | len = skb->len - tcphoff; | 50 | len = skb->len - tcphoff; |
51 | if (len < (int)sizeof(struct tcphdr) || | 51 | if (len < (int)sizeof(struct tcphdr)) |
52 | tcp_hdr(skb)->doff * 4 > len) | ||
53 | return NF_DROP; | 52 | return NF_DROP; |
54 | 53 | ||
55 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 54 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
55 | if (tcph->doff * 4 > len) | ||
56 | return NF_DROP; | ||
57 | |||
56 | opt = (u_int8_t *)tcph; | 58 | opt = (u_int8_t *)tcph; |
57 | 59 | ||
58 | /* | 60 | /* |