天天看點

linux 核心參數mss,linux 核心對于TCPMSS的處理

iptables -A FORWARD -p tcp-

-tcp-flags SYN,RST SYN -j TCPMSS

--clamp-mss-to-pmtu

這條規則的目的就是改變TCP MSS以适應PMTU(Path

MTU)

iptables -A FORWARD -p tcp

--tcp-flags SYN,RST SYN- j TCPMSS --set-mss

1400

設定MSS為1400

6 核心對于TCP MSS的處理

那麼核心對于TCP

MSS的處理到底在哪邊呢? 主要是在net/netfilter/xt_TCPMSS.c裡面:

static

int

tcpmss_mangle_packet(struct

sk_buff **pskb,

const struct xt_tcpmss_info *info,

unsigned int tcphoff,

unsigned int minlen)

{

struct

tcphdr *tcph;

unsigned

int tcplen, i;

__be16

oldval;

u16

newmss;

u8

*opt;

if

(!skb_make_writable(pskb, (*pskb)->len))

return -1;

tcplen =

(*pskb)->len - tcphoff;

tcph =

(struct tcphdr *)(skb_network_header(*pskb) + tcphoff);

if (tcplen

!= tcph->doff*4) {

if (net_ratelimit())

printk(KERN_ERR "xt_TCPMSS:

bad length (%u bytes)\n",

(*pskb)->len);

return -1;

}

if

(info->mss == XT_TCPMSS_CLAMP_PMTU) {

if (dst_mtu((*pskb)->dst)

<= minlen) {

if (net_ratelimit())

printk(KERN_ERR "xt_TCPMSS: "

"unknown or invalid path-MTU (%u)\n",

dst_mtu((*pskb)->dst));

return -1;

}

根據目的網卡的MTU進行newMSS的設定

newmss =

dst_mtu((*pskb)->dst) - minlen;

} else

newmss = info->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 (info->mss

== XT_TCPMSS_CLAMP_PMTU &&

oldmss <= newmss)

return

0;

opt[i+2] = (newmss

& 0xff00) >> 8;

opt[i+3] = (newmss

& 0x00ff);

nf_proto_csum_replace2(&tcph->check,

*pskb,

htons(oldmss), htons(newmss),

0);

return 0;

}

}

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 -1;

kfree_skb(*pskb);

*pskb = newskb;

tcph = (struct tcphdr

*)(skb_network_header(*pskb) + 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;

設定新的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);

return

TCPOLEN_MSS;

}