mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
Use the Base-MTU for MTU calculations.
This commit is contained in:
+40
-32
@@ -295,8 +295,8 @@ static void value_check(struct worker_st *ws, struct http_req_st *req)
|
||||
|
||||
break;
|
||||
|
||||
case HEADER_CSTP_MTU:
|
||||
req->cstp_mtu = atoi((char *)value);
|
||||
case HEADER_CSTP_BASE_MTU:
|
||||
req->base_mtu = atoi((char *)value);
|
||||
break;
|
||||
case HEADER_CSTP_ATYPE:
|
||||
if (memmem(value, value_length, "IPv4", 4) ==
|
||||
@@ -311,9 +311,6 @@ static void value_check(struct worker_st *ws, struct http_req_st *req)
|
||||
NULL)
|
||||
ws->full_ipv6 = 1;
|
||||
break;
|
||||
case HEADER_DTLS_MTU:
|
||||
req->dtls_mtu = atoi((char *)value);
|
||||
break;
|
||||
case HEADER_COOKIE:
|
||||
|
||||
str = (char *)value;
|
||||
@@ -400,14 +397,10 @@ static void header_check(struct http_req_st *req)
|
||||
strncmp((char *)req->header.data, STR_HDR_MS,
|
||||
req->header.length) == 0) {
|
||||
req->next_header = HEADER_MASTER_SECRET;
|
||||
} else if (req->header.length == sizeof(STR_HDR_DMTU) - 1 &&
|
||||
strncmp((char *)req->header.data, STR_HDR_DMTU,
|
||||
req->header.length) == 0) {
|
||||
req->next_header = HEADER_DTLS_MTU;
|
||||
} else if (req->header.length == sizeof(STR_HDR_CMTU) - 1 &&
|
||||
strncmp((char *)req->header.data, STR_HDR_CMTU,
|
||||
req->header.length) == 0) {
|
||||
req->next_header = HEADER_CSTP_MTU;
|
||||
req->next_header = HEADER_CSTP_BASE_MTU;
|
||||
} else if (req->header.length == sizeof(STR_HDR_HOST) - 1 &&
|
||||
strncmp((char *)req->header.data, STR_HDR_HOST,
|
||||
req->header.length) == 0) {
|
||||
@@ -785,7 +778,7 @@ void mtu_send(worker_st * ws, unsigned mtu)
|
||||
{
|
||||
TunMtuMsg msg = TUN_MTU_MSG__INIT;
|
||||
|
||||
msg.mtu = mtu - 1; /* account DTLS CSTP header */
|
||||
msg.mtu = mtu;
|
||||
send_msg_to_main(ws, CMD_TUN_MTU, &msg,
|
||||
(pack_size_func) tun_mtu_msg__get_packed_size,
|
||||
(pack_func) tun_mtu_msg__pack);
|
||||
@@ -817,6 +810,11 @@ void session_info_send(worker_st * ws)
|
||||
gnutls_free(msg.tls_ciphersuite);
|
||||
}
|
||||
|
||||
/* mtu_set: Sets the MTU for the session
|
||||
*
|
||||
* @ws: a worker structure
|
||||
* @mtu: the "plaintext" data MTU
|
||||
*/
|
||||
static
|
||||
void mtu_set(worker_st * ws, unsigned mtu)
|
||||
{
|
||||
@@ -858,6 +856,11 @@ unsigned min = MIN_MTU(ws);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mtu_set: initiates MTU discovery
|
||||
*
|
||||
* @ws: a worker structure
|
||||
* @mtu: the current "plaintext" data MTU
|
||||
*/
|
||||
static void mtu_discovery_init(worker_st * ws, unsigned mtu)
|
||||
{
|
||||
ws->last_good_mtu = mtu;
|
||||
@@ -1308,13 +1311,16 @@ static int connect_handler(worker_st * ws)
|
||||
ws->vinfo.mtu = ws->config->default_mtu;
|
||||
}
|
||||
|
||||
proto_overhead = CSTP_OVERHEAD;
|
||||
ws->conn_mtu = ws->vinfo.mtu - proto_overhead;
|
||||
|
||||
if (req->cstp_mtu > 0) {
|
||||
oclog(ws, LOG_DEBUG, "peer's CSTP MTU is %u (ignored)", req->cstp_mtu);
|
||||
if (req->base_mtu > 0) {
|
||||
oclog(ws, LOG_DEBUG, "peer's base MTU is %u", req->base_mtu);
|
||||
ws->vinfo.mtu = MIN(ws->vinfo.mtu, req->base_mtu);
|
||||
}
|
||||
|
||||
proto_overhead = CSTP_OVERHEAD;
|
||||
/* plaintext MTU is the device MTU minus the overhead
|
||||
* of the CSTP protocol. */
|
||||
ws->conn_mtu = ws->vinfo.mtu - proto_overhead;
|
||||
|
||||
sl = sizeof(max);
|
||||
ret = getsockopt(ws->conn_fd, IPPROTO_TCP, TCP_MAXSEG, &max, &sl);
|
||||
if (ret == -1) {
|
||||
@@ -1399,20 +1405,20 @@ static int connect_handler(worker_st * ws)
|
||||
else
|
||||
proto_overhead = 40 + CSTP_DTLS_OVERHEAD; /* ipv6 */
|
||||
proto_overhead += 8; /* udp */
|
||||
ws->conn_mtu = MIN(ws->conn_mtu, ws->vinfo.mtu - proto_overhead);
|
||||
proto_overhead += CSTP_DTLS_OVERHEAD;
|
||||
|
||||
/* crypto overhead for DTLS */
|
||||
crypto_overhead =
|
||||
CSTP_DTLS_OVERHEAD +
|
||||
tls_get_overhead(ws->req.selected_ciphersuite->gnutls_version,
|
||||
ws->req.selected_ciphersuite->gnutls_cipher, ws->req.selected_ciphersuite->gnutls_mac);
|
||||
|
||||
if (req->dtls_mtu <= 0)
|
||||
req->dtls_mtu = req->cstp_mtu;
|
||||
if (req->dtls_mtu > 0) {
|
||||
ws->conn_mtu = MIN(req->dtls_mtu+crypto_overhead+proto_overhead, ws->conn_mtu);
|
||||
oclog(ws, LOG_DEBUG,
|
||||
"peer's DTLS MTU is %u (overhead: %u)", req->dtls_mtu, proto_overhead+crypto_overhead);
|
||||
}
|
||||
oclog(ws, LOG_DEBUG,
|
||||
"DTLS overhead is %u", proto_overhead+crypto_overhead);
|
||||
|
||||
/* plaintext MTU is the device MTU minus the overhead
|
||||
* of the DTLS (+AnyConnect header) protocol.
|
||||
*/
|
||||
ws->conn_mtu = MIN(ws->conn_mtu, ws->vinfo.mtu - proto_overhead);
|
||||
|
||||
dtls_mtu = ws->conn_mtu - crypto_overhead;
|
||||
|
||||
@@ -1442,8 +1448,8 @@ static int connect_handler(worker_st * ws)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* crypto overhead for TLS */
|
||||
crypto_overhead =
|
||||
CSTP_OVERHEAD +
|
||||
tls_get_overhead(gnutls_protocol_get_version(ws->session),
|
||||
gnutls_cipher_get(ws->session),
|
||||
gnutls_mac_get(ws->session));
|
||||
@@ -1453,9 +1459,11 @@ static int connect_handler(worker_st * ws)
|
||||
|
||||
ret = tls_printf(ws->session, "X-CSTP-MTU: %u\r\n", cstp_mtu);
|
||||
SEND_ERR(ret);
|
||||
oclog(ws, LOG_DEBUG, "suggesting CSTP MTU %u", cstp_mtu);
|
||||
|
||||
oclog(ws, LOG_DEBUG, "plaintext MTU is %u", ws->conn_mtu - 1);
|
||||
ret = tls_printf(ws->session, "X-CSTP-Base-MTU: %u\r\n", ws->conn_mtu);
|
||||
SEND_ERR(ret);
|
||||
|
||||
oclog(ws, LOG_DEBUG, "CSTP Base MTU is %u bytes", ws->conn_mtu);
|
||||
|
||||
mtu_send(ws, ws->conn_mtu);
|
||||
|
||||
@@ -1767,19 +1775,19 @@ static int connect_handler(worker_st * ws)
|
||||
if (ret == 0) {
|
||||
unsigned mtu =
|
||||
gnutls_dtls_get_data_mtu(ws->
|
||||
dtls_session);
|
||||
dtls_session) - proto_overhead;
|
||||
|
||||
/* openconnect doesn't like if we send more bytes
|
||||
* than the initially agreed MTU */
|
||||
if (mtu > dtls_mtu)
|
||||
mtu = dtls_mtu;
|
||||
if (mtu > ws->conn_mtu)
|
||||
mtu = ws->conn_mtu;
|
||||
|
||||
ws->udp_state = UP_ACTIVE;
|
||||
mtu_discovery_init(ws, mtu);
|
||||
mtu_set(ws, mtu);
|
||||
oclog(ws, LOG_INFO,
|
||||
"DTLS handshake completed (plaintext MTU: %u)\n",
|
||||
ws->conn_mtu - 1);
|
||||
ws->conn_mtu);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
+8
-6
@@ -47,8 +47,7 @@ typedef enum {
|
||||
#define STR_HDR_CONNECTION "Connection"
|
||||
#define STR_HDR_MS "X-DTLS-Master-Secret"
|
||||
#define STR_HDR_CS "X-DTLS-CipherSuite"
|
||||
#define STR_HDR_DMTU "X-DTLS-MTU"
|
||||
#define STR_HDR_CMTU "X-CSTP-MTU"
|
||||
#define STR_HDR_CMTU "X-CSTP-Base-MTU"
|
||||
#define STR_HDR_ATYPE "X-CSTP-Address-Type"
|
||||
#define STR_HDR_HOST "X-CSTP-Hostname"
|
||||
#define STR_HDR_FULL_IPV6 "X-CSTP-Full-IPv6-Capability"
|
||||
@@ -58,9 +57,8 @@ enum {
|
||||
HEADER_COOKIE = 1,
|
||||
HEADER_MASTER_SECRET,
|
||||
HEADER_HOSTNAME,
|
||||
HEADER_CSTP_MTU,
|
||||
HEADER_CSTP_BASE_MTU,
|
||||
HEADER_CSTP_ATYPE,
|
||||
HEADER_DTLS_MTU,
|
||||
HEADER_DEVICE_TYPE,
|
||||
HEADER_DTLS_CIPHERSUITE,
|
||||
HEADER_CONNECTION,
|
||||
@@ -125,8 +123,7 @@ struct http_req_st {
|
||||
|
||||
unsigned int headers_complete;
|
||||
unsigned int message_complete;
|
||||
unsigned dtls_mtu;
|
||||
unsigned cstp_mtu;
|
||||
unsigned base_mtu;
|
||||
|
||||
unsigned no_ipv4;
|
||||
unsigned no_ipv6;
|
||||
@@ -172,6 +169,11 @@ typedef struct worker_st {
|
||||
/* for mtu trials */
|
||||
unsigned last_good_mtu;
|
||||
unsigned last_bad_mtu;
|
||||
|
||||
|
||||
/* ws->conn_mtu: The MTU of the plaintext data we can send to the client.
|
||||
* It also matches the MTU of the TUN device. Note that this is
|
||||
* the same as the 'real' MTU of the connection, minus the IP+UDP+CSTP headers. */
|
||||
unsigned conn_mtu;
|
||||
|
||||
/* Indicates whether the new IPv6 headers will
|
||||
|
||||
Reference in New Issue
Block a user