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
|
// calculated from config->l2tp_mtu
|
||||||
uint16_t MRU = 0; // PPP MRU
|
uint16_t MRU = 0; // PPP MRU
|
||||||
uint16_t MSS = 0; // TCP MSS
|
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_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
|
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)
|
// 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;
|
int d = (tcp[12] >> 4) * 4;
|
||||||
uint8_t *mss = 0;
|
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
|
if (!mss) return; // not found
|
||||||
orig = ntohs(*(uint16_t *) mss);
|
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",
|
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(src, 0), ntohs(*(uint16_t *) tcp),
|
||||||
fmtaddr(*(in_addr_t *) (buf + 16), 1), ntohs(*(uint16_t *) (tcp + 2)),
|
fmtaddr(dst, 1), ntohs(*(uint16_t *) (tcp + 2)),
|
||||||
(tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, MSS);
|
(tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, mss_clamp);
|
||||||
|
|
||||||
// set mss
|
// set mss
|
||||||
*(int16_t *) mss = htons(MSS);
|
*(int16_t *) mss = htons(mss_clamp);
|
||||||
|
|
||||||
// adjust checksum (see rfc1141)
|
// adjust checksum (see rfc1141)
|
||||||
sum = orig + (~MSS & 0xffff);
|
sum = orig + (~mss_clamp & 0xffff);
|
||||||
sum += ntohs(*(uint16_t *) (tcp + 16));
|
sum += ntohs(*(uint16_t *) (tcp + 16));
|
||||||
sum = (sum & 0xffff) + (sum >> 16);
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
*(uint16_t *) (tcp + 16) = htons(sum + (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)
|
void processmpframe(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint8_t extra)
|
||||||
{
|
{
|
||||||
uint16_t proto;
|
uint16_t proto;
|
||||||
|
|
@ -1565,7 +1577,7 @@ void processipout(uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int ihl = (buf[0] & 0xf) * 4; // length of IP header
|
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))
|
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)
|
if (sp->tbf_out)
|
||||||
|
|
@ -1792,6 +1804,14 @@ static void processipv6out(uint8_t * buf, int len)
|
||||||
|
|
||||||
// FIXME: add DoS prevention/filters?
|
// 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)
|
if (sp->tbf_out)
|
||||||
{
|
{
|
||||||
// Are we throttling this session?
|
// 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 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 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
|
if (config->l2tp_mtu <= 0) config->l2tp_mtu = 1500; // ethernet default
|
||||||
else if (config->l2tp_mtu < MINMTU) config->l2tp_mtu = MINMTU;
|
else if (config->l2tp_mtu < MINMTU) config->l2tp_mtu = MINMTU;
|
||||||
|
|
@ -5404,6 +5425,7 @@ static void update_config()
|
||||||
MRU = PPPoE_MRU;
|
MRU = PPPoE_MRU;
|
||||||
|
|
||||||
MSS = MRU - TCP_HDRS;
|
MSS = MRU - TCP_HDRS;
|
||||||
|
MSS6 = MRU - TCP6_HDRS;
|
||||||
|
|
||||||
// Update radius
|
// Update radius
|
||||||
config->numradiusservers = 0;
|
config->numradiusservers = 0;
|
||||||
|
|
|
||||||
4
l2tpns.h
4
l2tpns.h
|
|
@ -969,7 +969,8 @@ void filter_session(sessionidt s, int filter_in, int filter_out);
|
||||||
void send_garp(in_addr_t ip);
|
void send_garp(in_addr_t ip);
|
||||||
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
|
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
|
||||||
int tun_write(uint8_t *data, int size);
|
int tun_write(uint8_t *data, int size);
|
||||||
void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp);
|
void adjust_tcp4_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp);
|
||||||
|
void adjust_tcp6_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp);
|
||||||
void sendipcp(sessionidt s, tunnelidt t);
|
void sendipcp(sessionidt s, tunnelidt t);
|
||||||
void sendipv6cp(sessionidt s, tunnelidt t);
|
void sendipv6cp(sessionidt s, tunnelidt t);
|
||||||
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd);
|
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd);
|
||||||
|
|
@ -1054,6 +1055,7 @@ struct event_data {
|
||||||
|
|
||||||
extern uint16_t MRU;
|
extern uint16_t MRU;
|
||||||
extern uint16_t MSS;
|
extern uint16_t MSS;
|
||||||
|
extern uint16_t MSS6;
|
||||||
|
|
||||||
// macros for handling help in cli commands
|
// macros for handling help in cli commands
|
||||||
#define CLI_HELP_REQUESTED (argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?')
|
#define CLI_HELP_REQUESTED (argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?')
|
||||||
|
|
|
||||||
10
ppp.c
10
ppp.c
|
|
@ -1803,7 +1803,7 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
{
|
{
|
||||||
int ihl = (p[0] & 0xf) * 4; // length of IP header
|
int ihl = (p[0] & 0xf) * 4; // length of IP header
|
||||||
if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5))
|
if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5))
|
||||||
adjust_tcp_mss(s, t, p, l, p + ihl);
|
adjust_tcp4_mss(s, t, p, l, p + ihl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add on the tun header
|
// Add on the tun header
|
||||||
|
|
@ -2284,6 +2284,14 @@ void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adjust MSS on SYN and SYN,ACK packets with options
|
||||||
|
if (p[6] == IPPROTO_TCP)
|
||||||
|
{
|
||||||
|
int ihl = 40; // length of IPv6 header
|
||||||
|
if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5))
|
||||||
|
adjust_tcp6_mss(s, t, p, l, p + ihl);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if it's a Router Solicition message.
|
// Check if it's a Router Solicition message.
|
||||||
if (*(p + 6) == 58 && *(p + 7) == 255 && *(p + 24) == 0xFF && *(p + 25) == 2 &&
|
if (*(p + 6) == 58 && *(p + 7) == 255 && *(p + 24) == 0xFF && *(p + 25) == 2 &&
|
||||||
*(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 &&
|
*(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 &&
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue