*/
static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *mtu)
{
- *mtu = vpninfo->mtu;
+ *mtu = vpninfo->reqmtu;
*base_mtu = vpninfo->basemtu;
#if defined(__linux__) && defined(TCP_INFO)
/* We may have advertised it, but we only do it if the server agrees */
vpninfo->deflate = 0;
+ mtu = 0;
while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
struct vpn_option *new_option;
next_dtls_option = &new_option->next;
if (!strcmp(buf + 7, "MTU")) {
- int mtu = atol(colon);
- if (mtu > vpninfo->mtu)
- vpninfo->mtu = mtu;
+ int dtlsmtu = atol(colon);
+ if (dtlsmtu > mtu)
+ mtu = dtlsmtu;
} else if (!strcmp(buf + 7, "Session-ID")) {
if (strlen(colon) != 64) {
vpn_progress(vpninfo, PRG_ERR,
return -EINVAL;
}
} else if (!strcmp(buf + 7, "MTU")) {
- int mtu = atol(colon);
- if (mtu > vpninfo->mtu)
- vpninfo->mtu = mtu;
+ int cstpmtu = atol(colon);
+ if (cstpmtu > mtu)
+ mtu = cstpmtu;
} else if (!strcmp(buf + 7, "Address")) {
if (strchr(new_option->value, ':')) {
if (!vpninfo->disable_ipv6)
}
}
+ if (!mtu) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("No MTU received. Aborting\n"));
+ return -EINVAL;
+ }
+ vpninfo->actual_mtu = mtu;
+
if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
vpn_progress(vpninfo, PRG_ERR,
_("No IP address received. Aborting\n"));
static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
unsigned char *buf, int len)
{
- struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
+ struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->actual_mtu);
uint32_t pkt_sum;
if (!new)
vpninfo->inflate_strm.avail_in = len - 4;
vpninfo->inflate_strm.next_out = new->data;
- vpninfo->inflate_strm.avail_out = vpninfo->mtu;
+ vpninfo->inflate_strm.avail_out = vpninfo->actual_mtu;
vpninfo->inflate_strm.total_out = 0;
if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
#ifdef HAVE_GNUTLS_DTLS_SET_DATA_MTU
/* Make sure GnuTLS's idea of the MTU is sufficient to take
a full VPN MTU (with 1-byte header) in a data record. */
- err = gnutls_dtls_set_data_mtu(vpninfo->new_dtls_ssl, vpninfo->mtu + 1);
+ err = gnutls_dtls_set_data_mtu(vpninfo->new_dtls_ssl, vpninfo->actual_mtu + 1);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to set DTLS MTU: %s\n"),
We only support AES128-CBC and DES-CBC3-SHA anyway, so
working out the worst case isn't hard. */
gnutls_dtls_set_mtu(vpninfo->new_dtls_ssl,
- vpninfo->mtu + 1 /* packet + header */
+ vpninfo->actual_mtu + 1 /* packet + header */
+ 13 /* DTLS header */
+ 20 /* biggest supported MAC (SHA1) */
+ 16 /* biggest supported IV (AES-128) */
char magic_pkt;
while (1) {
- int len = vpninfo->mtu;
+ int len = vpninfo->actual_mtu;
unsigned char *buf;
if (!dtls_pkt) {
{
struct openconnect_info *vpninfo = calloc (sizeof(*vpninfo), 1);
- vpninfo->mtu = 1406;
vpninfo->ssl_fd = -1;
vpninfo->cert_expire_warning = 60 * 86400;
vpninfo->useragent = openconnect_create_useragent (useragent);
/* 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 = 0;
+ vpninfo->reqmtu = 0;
vpninfo->deflate = 1;
vpninfo->dtls_attempt_period = 60;
vpninfo->max_qlen = 10;
use_syslog = 1;
break;
case 'm':
- vpninfo->mtu = atol(config_arg);
- if (vpninfo->mtu < 576) {
- fprintf(stderr, _("MTU %d too small\n"), vpninfo->mtu);
- vpninfo->mtu = 576;
+ vpninfo->reqmtu = atol(config_arg);
+ if (vpninfo->reqmtu < 576) {
+ fprintf(stderr, _("MTU %d too small\n"), vpninfo->reqmtu);
+ vpninfo->reqmtu = 576;
}
break;
case OPT_BASEMTU:
int script_tun;
char *ifname;
- int mtu, basemtu;
+ int actual_mtu;
+ int reqmtu, basemtu;
const char *banner;
const char *vpn_addr;
const char *vpn_netmask;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, vpninfo->ifname, sizeof(ifr.ifr_name) - 1);
- ifr.ifr_mtu = vpninfo->mtu;
+ ifr.ifr_mtu = vpninfo->actual_mtu;
if (ioctl(net_fd, SIOCSIFMTU, &ifr) < 0)
perror(_("SIOCSIFMTU"));
unsetenv("CISCO_SPLIT_INC");
unsetenv("CISCO_SPLIT_EXC");
- setenv_int("INTERNAL_IP4_MTU", vpninfo->mtu);
+ setenv_int("INTERNAL_IP4_MTU", vpninfo->actual_mtu);
if (vpninfo->vpn_addr) {
setenv("INTERNAL_IP4_ADDRESS", vpninfo->vpn_addr, 1);
if (FD_ISSET(vpninfo->tun_fd, &vpninfo->select_rfds)) {
while (1) {
- int len = vpninfo->mtu;
+ int len = vpninfo->actual_mtu;
if (!out_pkt) {
out_pkt = malloc(sizeof(struct pkt) + len);
<ul>
<li><b>OpenConnect HEAD</b>
<ul>
+ <li>Fix handling of requested vs. received MTU settings.</li>
<li>Fix DTLS MTU for GnuTLS 3.0.21 and newer.</li>
<li>Support more ciphers for OpenSSL encrypted PEM keys, with GnuTLS.</li>
<li>Fix GnuTLS compatibilty issue with servers that insist on TLSv1.0 <a href="https://bugzilla.redhat.com/show_bug.cgi?id=836558"><i>(RH#836558)</i></a>.</li>