pMTU discovery
David Woodhouse
dwmw2 at infradead.org
Fri Jun 8 08:02:19 EDT 2012
On Thu, 2012-05-31 at 11:44 +0200, Bernhard Schmidt wrote:
> we're currently testing OpenConnect 3.20 against our new shiny ASA Beta
> which finally does IPv6 transport. However, when we do use that, we have
> MTU problems on the link. The official AnyConnect client works fine.
It'd be very interesting to know where the Cisco client gets its numbers
from. How does this compare?
diff --git a/cstp.c b/cstp.c
index dbc24b9..5910940 100644
--- a/cstp.c
+++ b/cstp.c
@@ -32,6 +32,9 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
+#include <netinet/tcp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -86,6 +89,48 @@ static int __attribute__ ((format (printf, 3, 4)))
return ret;
}
+static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *mtu)
+{
+#ifdef TCP_MAXSEG
+ int mss;
+ socklen_t mss_size = sizeof(mss);
+#endif
+#ifdef TCP_INFO
+ struct tcp_info ti;
+ socklen_t ti_size = sizeof(ti);
+#endif
+ if (vpninfo->mtu) {
+ /* User override */
+ *base_mtu = 0;
+ *mtu = vpninfo->mtu;
+ }
+#ifdef TCP_INFO
+ else if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_INFO, &ti, &ti_size)) {
+ vpn_progress(vpninfo, PRG_TRACE,
+ _("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);
+ *base_mtu = ti.tcpi_pmtu;
+ if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
+ *mtu = ti.tcpi_rcv_mss;
+ else
+ *mtu = ti.tcpi_snd_mss;
+ }
+#endif
+#ifdef TCP_MAXSEG
+ else if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_MAXSEG, &mss, &mss_size)) {
+ vpn_progress(vpninfo, PRG_TRACE, _("TCP_MAXSEG %d\n"), mss);
+ *mtu = mss;
+ /* Erm, how do we sanely find the base MTU? */
+ *base_mtu = 1500;
+ }
+#endif
+ else {
+ /* Default */
+ *base_mtu = 0;
+ *mtu = 1406;
+ }
+}
+
static int start_cstp_connection(struct openconnect_info *vpninfo)
{
char buf[65536];
@@ -100,6 +145,7 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
const char *old_addr6 = vpninfo->vpn_addr6;
const char *old_netmask6 = vpninfo->vpn_netmask6;
struct split_include *inc;
+ int base_mtu, mtu;
/* Clear old options which will be overwritten */
vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
@@ -132,6 +178,8 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
}
retry:
+ calculate_mtu(vpninfo, &base_mtu, &mtu);
+
buf[0] = 0;
buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
@@ -141,7 +189,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
if (vpninfo->deflate && i < sizeof(buf))
buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
- buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
+ if (base_mtu)
+ buf_append(buf, sizeof(buf), "X-CSTP-Base-MTU: %d\r\n", base_mtu);
+ buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", mtu);
buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
diff --git a/main.c b/main.c
index 6f7f86c..9f52ed1 100644
--- a/main.c
+++ b/main.c
@@ -412,7 +412,7 @@ int main(int argc, char **argv)
/* Set up some defaults */
vpninfo->tun_fd = vpninfo->ssl_fd = vpninfo->dtls_fd = vpninfo->new_dtls_fd = -1;
vpninfo->useragent = openconnect_create_useragent("Open AnyConnect VPN Agent");
- vpninfo->mtu = 1406;
+ vpninfo->mtu = 0;
vpninfo->deflate = 1;
vpninfo->dtls_attempt_period = 60;
vpninfo->max_qlen = 10;
--
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 6171 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20120608/00ab415f/attachment.bin>
More information about the openconnect-devel
mailing list