Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Always calculate the base_mtu value
This patch fixes issues in base_mtu value calcuation (previously it was
never calculated), and ensures that this value is always present. This
value provides the server of an estimation of the link (or path) MTU between
the server and the client, is much simpler to calculate than the tunnel MTU
(does not rely on an estimation of the negotiated DTLS ciphers). As such
it can provide the server with more reliable information than the X-CSTP-MTU
value.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
Nikos Mavrogiannopoulos authored and David Woodhouse committed Aug 25, 2016
1 parent 20ef570 commit d029f8d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
52 changes: 37 additions & 15 deletions cstp.c
Expand Up @@ -32,6 +32,11 @@
#include <lz4.h>
#endif

#if defined(__linux__)
/* For TCP_INFO */
# include <linux/tcp.h>
#endif

#include "openconnect-internal.h"

/*
Expand Down Expand Up @@ -68,9 +73,13 @@ static const struct pkt dpd_resp_pkt = {
{ .cstp.hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 } }
};

#define UDP_HEADER_SIZE 8
#define IPV4_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40

/* Calculate MTU to request. Old servers simply use the X-CSTP-MTU: header,
* which represents the tunnel MTU, while new servers do calculations on the
* X-CSTP-Base-MTU: header which represents the cleartext MTU between client
* X-CSTP-Base-MTU: header which represents the link MTU between client
* and server.
*
* If possible, the legacy MTU value should be the TCP MSS less 5 bytes of
Expand Down Expand Up @@ -99,34 +108,47 @@ static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *
vpn_progress(vpninfo, PRG_DEBUG,
_("TCP_INFO rcv mss %d, snd mss %d, adv mss %d, pmtu %d\n"),
ti.tcpi_rcv_mss, ti.tcpi_snd_mss, ti.tcpi_advmss, ti.tcpi_pmtu);
if (!*base_mtu)

if (!*base_mtu) {
*base_mtu = ti.tcpi_pmtu;
if (!*mtu) {
}

if (!*base_mtu) {
if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
*mtu = ti.tcpi_rcv_mss - 13;
*base_mtu = ti.tcpi_rcv_mss - 13;
else
*mtu = ti.tcpi_snd_mss - 13;
*base_mtu = ti.tcpi_snd_mss - 13;
}
}
}
#endif
#ifdef TCP_MAXSEG
if (!*mtu) {
if (!*base_mtu) {
int mss;
socklen_t mss_size = sizeof(mss);
if (!getsockopt(vpninfo->ssl_fd, IPPROTO_TCP, TCP_MAXSEG,
&mss, &mss_size)) {
vpn_progress(vpninfo, PRG_DEBUG, _("TCP_MAXSEG %d\n"), mss);
*mtu = mss - 13;
*base_mtu = mss - 13;
}
}
#endif
if (!*mtu) {
if (!*base_mtu) {
/* Default */
*mtu = 1406;
*base_mtu = 1406;
}

if (*base_mtu < 1280)
*base_mtu = 1280;

if (!*mtu) {
/* remove IP/UDP and DTLS overhead from base MTU to calculate tunnel MTU */
*mtu = *base_mtu - DTLS_OVERHEAD - UDP_HEADER_SIZE;
if (vpninfo->peer_addr->sa_family == AF_INET6)
*mtu -= IPV6_HEADER_SIZE;
else
*mtu -= IPV4_HEADER_SIZE;
}
if (*mtu < 1280)
*mtu = 1280;
}

static void append_compr_types(struct oc_text_buf *buf, const char *proto, int avail)
Expand Down Expand Up @@ -181,7 +203,7 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
const char *old_netmask = vpninfo->ip_info.netmask;
const char *old_addr6 = vpninfo->ip_info.addr6;
const char *old_netmask6 = vpninfo->ip_info.netmask6;
int base_mtu, mtu;
int base_mtu = 0, mtu = 0;

/* Clear old options which will be overwritten */
vpninfo->ip_info.addr = vpninfo->ip_info.netmask = NULL;
Expand Down Expand Up @@ -211,9 +233,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
append_mobile_headers(vpninfo, reqbuf);
append_compr_types(reqbuf, "CSTP", vpninfo->req_compr);

if (base_mtu)
buf_append(reqbuf, "X-CSTP-Base-MTU: %d\r\n", base_mtu);
buf_append(reqbuf, "X-CSTP-MTU: %d\r\n", mtu);
buf_append(reqbuf, "X-CSTP-Base-MTU: %d\r\n", base_mtu);
if (mtu)
buf_append(reqbuf, "X-CSTP-MTU: %d\r\n", mtu);
buf_append(reqbuf, "X-CSTP-Address-Type: %s\r\n",
vpninfo->disable_ipv6 ? "IPv4" : "IPv6,IPv4");
if (!vpninfo->disable_ipv6)
Expand Down
6 changes: 1 addition & 5 deletions dtls.c
Expand Up @@ -654,11 +654,7 @@ static int dtls_try_handshake(struct openconnect_info *vpninfo)
We only support AES128-CBC and DES-CBC3-SHA anyway, so
working out the worst case isn't hard. */
gnutls_dtls_set_mtu(vpninfo->dtls_ssl,
vpninfo->ip_info.mtu + 1 /* packet + header */
+ 13 /* DTLS header */
+ 20 /* biggest supported MAC (SHA1) */
+ 16 /* biggest supported IV (AES-128) */
+ 16 /* max padding */);
vpninfo->ip_info.mtu + DTLS_OVERHEAD);
#endif

vpninfo->dtls_state = DTLS_CONNECTED;
Expand Down
7 changes: 7 additions & 0 deletions openconnect-internal.h
Expand Up @@ -312,6 +312,13 @@ static inline void init_pkt_queue(struct pkt_q *q)
{
q->tail = &q->head;
}

#define DTLS_OVERHEAD (1 /* packet + header */ + 13 /* DTLS header */ + \
20 /* biggest supported MAC (SHA1) */ + 16 /* biggest supported IV (AES-128) */ + \
16 /* max padding */)

#define LINK_TO_TUNNEL_MTU(linkmtu) \
(linkmtu - DTLS_OVERHEAD)

struct esp {
#if defined(ESP_GNUTLS)
Expand Down

0 comments on commit d029f8d

Please sign in to comment.