Also clamp MSS on IPv6
Some routers erratically drop "Packet too big" icmp messages, and PMTU discovery then doesn't work. We can however easily clamp MSS on IPv6 too.
This commit is contained in:
parent
7514eecf68
commit
3667bdfe80
3 changed files with 42 additions and 10 deletions
38
l2tpns.c
38
l2tpns.c
|
|
@ -90,6 +90,7 @@ int guest_accounts_num = 0; // Number of guest users
|
|||
// calculated from config->l2tp_mtu
|
||||
uint16_t MRU = 0; // PPP MRU
|
||||
uint16_t MSS = 0; // TCP MSS
|
||||
uint16_t MSS6 = 0; // TCPv6 MSS
|
||||
|
||||
struct cli_session_actions *cli_session_actions = NULL; // Pending session changes requested by CLI
|
||||
struct cli_tunnel_actions *cli_tunnel_actions = NULL; // Pending tunnel changes required by CLI
|
||||
|
|
@ -1322,7 +1323,7 @@ int tun_write(uint8_t * data, int size)
|
|||
}
|
||||
|
||||
// adjust tcp mss to avoid fragmentation (called only for tcp packets with syn set)
|
||||
void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp)
|
||||
static void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp, in_addr_t src, in_addr_t dst, uint16_t mss_clamp)
|
||||
{
|
||||
int d = (tcp[12] >> 4) * 4;
|
||||
uint8_t *mss = 0;
|
||||
|
|
@ -1359,23 +1360,34 @@ void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *t
|
|||
if (!mss) return; // not found
|
||||
orig = ntohs(*(uint16_t *) mss);
|
||||
|
||||
if (orig <= MSS) return; // mss OK
|
||||
if (orig <= mss_clamp) return; // mss OK
|
||||
|
||||
LOG(5, s, t, "TCP: %s:%u -> %s:%u SYN%s: adjusted mss from %u to %u\n",
|
||||
fmtaddr(*(in_addr_t *) (buf + 12), 0), ntohs(*(uint16_t *) tcp),
|
||||
fmtaddr(*(in_addr_t *) (buf + 16), 1), ntohs(*(uint16_t *) (tcp + 2)),
|
||||
(tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, MSS);
|
||||
fmtaddr(src, 0), ntohs(*(uint16_t *) tcp),
|
||||
fmtaddr(dst, 1), ntohs(*(uint16_t *) (tcp + 2)),
|
||||
(tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, mss_clamp);
|
||||
|
||||
// set mss
|
||||
*(int16_t *) mss = htons(MSS);
|
||||
*(int16_t *) mss = htons(mss_clamp);
|
||||
|
||||
// adjust checksum (see rfc1141)
|
||||
sum = orig + (~MSS & 0xffff);
|
||||
sum = orig + (~mss_clamp & 0xffff);
|
||||
sum += ntohs(*(uint16_t *) (tcp + 16));
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
*(uint16_t *) (tcp + 16) = htons(sum + (sum >> 16));
|
||||
}
|
||||
|
||||
void adjust_tcp4_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp)
|
||||
{
|
||||
adjust_tcp_mss(s, t, buf, len, tcp, *(in_addr_t *) (buf + 12), *(in_addr_t *) (buf + 16), MSS);
|
||||
}
|
||||
|
||||
void adjust_tcp6_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp)
|
||||
{
|
||||
/* Showing the lower part of IPv6 addresses */
|
||||
adjust_tcp_mss(s, t, buf, len, tcp, *(in_addr_t *) (buf + 20), *(in_addr_t *) (buf + 36), MSS6);
|
||||
}
|
||||
|
||||
void processmpframe(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint8_t extra)
|
||||
{
|
||||
uint16_t proto;
|
||||
|
|
@ -1565,7 +1577,7 @@ void processipout(uint8_t *buf, int len)
|
|||
{
|
||||
int ihl = (buf[0] & 0xf) * 4; // length of IP header
|
||||
if (len >= ihl + 20 && (buf[ihl + 13] & TCP_FLAG_SYN) && ((buf[ihl + 12] >> 4) > 5))
|
||||
adjust_tcp_mss(s, t, buf, len, buf + ihl);
|
||||
adjust_tcp4_mss(s, t, buf, len, buf + ihl);
|
||||
}
|
||||
|
||||
if (sp->tbf_out)
|
||||
|
|
@ -1792,6 +1804,14 @@ static void processipv6out(uint8_t * buf, int len)
|
|||
|
||||
// FIXME: add DoS prevention/filters?
|
||||
|
||||
// adjust MSS on SYN and SYN,ACK packets with options
|
||||
if (buf[6] == IPPROTO_TCP)
|
||||
{
|
||||
int ihl = 40; // length of IPv6 header
|
||||
if (len >= ihl + 20 && (buf[ihl + 13] & TCP_FLAG_SYN) && ((buf[ihl + 12] >> 4) > 5))
|
||||
adjust_tcp6_mss(s, t, buf, len, buf + ihl);
|
||||
}
|
||||
|
||||
if (sp->tbf_out)
|
||||
{
|
||||
// Are we throttling this session?
|
||||
|
|
@ -5391,6 +5411,7 @@ static void update_config()
|
|||
|
||||
#define L2TP_HDRS (20+8+6+4) // L2TP data encaptulation: ip + udp + l2tp (data) + ppp (inc hdlc)
|
||||
#define TCP_HDRS (20+20) // TCP encapsulation: ip + tcp
|
||||
#define TCP6_HDRS (40+20) // TCP encapsulation: ipv6 + tcp
|
||||
|
||||
if (config->l2tp_mtu <= 0) config->l2tp_mtu = 1500; // ethernet default
|
||||
else if (config->l2tp_mtu < MINMTU) config->l2tp_mtu = MINMTU;
|
||||
|
|
@ -5404,6 +5425,7 @@ static void update_config()
|
|||
MRU = PPPoE_MRU;
|
||||
|
||||
MSS = MRU - TCP_HDRS;
|
||||
MSS6 = MRU - TCP6_HDRS;
|
||||
|
||||
// Update radius
|
||||
config->numradiusservers = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue