2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
5 * Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
7 * Author: David Woodhouse <dwmw2@infradead.org>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * version 2.1, as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to:
21 * Free Software Foundation, Inc.
22 * 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301 USA
36 #include <openssl/ssl.h>
37 #include <openssl/err.h>
39 #include "openconnect-internal.h"
42 * Data packets are encapsulated in the SSL stream as follows:
44 * 0000: Magic "STF\x1"
45 * 0004: Big-endian 16-bit length (not including 8-byte header)
46 * 0006: Byte packet type (see openconnect-internal.h)
50 static char data_hdr[8] = {
53 AC_PKT_DATA, /* Type */
57 static struct pkt keepalive_pkt = {
58 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
61 static struct pkt dpd_pkt = {
62 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
65 static struct pkt dpd_resp_pkt = {
66 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
69 static int __attribute__ ((format (printf, 3, 4)))
70 buf_append(char *buf, int len, const char *fmt, ...)
72 int start = strlen(buf);
80 ret = vsnprintf(buf + start, len - start, fmt, args);
89 static int start_cstp_connection(struct openconnect_info *vpninfo)
93 int retried = 0, sessid_found = 0;
94 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
95 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
96 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
97 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
98 const char *old_addr = vpninfo->vpn_addr;
99 const char *old_netmask = vpninfo->vpn_netmask;
100 const char *old_addr6 = vpninfo->vpn_addr6;
101 const char *old_netmask6 = vpninfo->vpn_netmask6;
102 struct split_include *inc;
104 /* Clear old options which will be overwritten */
105 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
106 vpninfo->vpn_addr6 = vpninfo->vpn_netmask6 = NULL;
107 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
108 vpninfo->vpn_domain = vpninfo->vpn_proxy_pac = NULL;
109 vpninfo->banner = NULL;
112 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
114 for (inc = vpninfo->split_includes; inc; ) {
115 struct split_include *next = inc->next;
119 for (inc = vpninfo->split_excludes; inc; ) {
120 struct split_include *next = inc->next;
124 vpninfo->split_includes = vpninfo->split_excludes = NULL;
126 /* Create (new) random master key for DTLS connection, if needed */
127 if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
129 openconnect_random(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret))) {
130 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
136 buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
137 buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
138 buf_append(buf, sizeof(buf), "User-Agent: %s\r\n", vpninfo->useragent);
139 buf_append(buf, sizeof(buf), "Cookie: webvpn=%s\r\n", vpninfo->cookie);
140 buf_append(buf, sizeof(buf), "X-CSTP-Version: 1\r\n");
141 buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
142 if (vpninfo->deflate && i < sizeof(buf))
143 buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
144 buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
145 buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
146 vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
147 buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
148 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
149 buf_append(buf, sizeof(buf), "%02X", vpninfo->dtls_secret[i]);
150 buf_append(buf, sizeof(buf), "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
151 vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
153 openconnect_SSL_write(vpninfo, buf, strlen(buf));
155 if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) {
158 vpn_progress(vpninfo, PRG_ERR,
159 _("Error fetching HTTPS response\n"));
162 openconnect_close_https(vpninfo);
164 if (openconnect_open_https(vpninfo)) {
165 vpn_progress(vpninfo, PRG_ERR,
166 _("Failed to open HTTPS connection to %s\n"),
175 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
176 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
177 /* "Service Unavailable. Why? */
178 const char *reason = "<unknown>";
179 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
180 if (!strncmp(buf, "X-Reason: ", 10)) {
185 vpn_progress(vpninfo, PRG_ERR,
186 _("VPN service unavailable; reason: %s\n"),
190 vpn_progress(vpninfo, PRG_ERR,
191 _("Got inappropriate HTTP CONNECT response: %s\n"),
193 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
198 vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
200 /* We may have advertised it, but we only do it if the server agrees */
201 vpninfo->deflate = 0;
203 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
204 struct vpn_option *new_option;
210 colon = strchr(buf, ':');
219 if (strncmp(buf, "X-DTLS-", 7) &&
220 strncmp(buf, "X-CSTP-", 7))
223 new_option = malloc(sizeof(*new_option));
225 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
228 new_option->option = strdup(buf);
229 new_option->value = strdup(colon);
230 new_option->next = NULL;
232 if (!new_option->option || !new_option->value) {
233 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
237 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
239 if (!strncmp(buf, "X-DTLS-", 7)) {
240 *next_dtls_option = new_option;
241 next_dtls_option = &new_option->next;
243 if (!strcmp(buf + 7, "Session-ID")) {
244 if (strlen(colon) != 64) {
245 vpn_progress(vpninfo, PRG_ERR,
246 _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
248 vpninfo->dtls_attempt_period = 0;
251 for (i = 0; i < 64; i += 2)
252 vpninfo->dtls_session_id[i/2] = unhex(colon + i);
254 time(&vpninfo->dtls_times.last_rekey);
258 /* CSTP options... */
259 *next_cstp_option = new_option;
260 next_cstp_option = &new_option->next;
263 if (!strcmp(buf + 7, "Keepalive")) {
264 vpninfo->ssl_times.keepalive = atol(colon);
265 } else if (!strcmp(buf + 7, "DPD")) {
267 if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
268 vpninfo->ssl_times.dpd = j;
269 } else if (!strcmp(buf + 7, "Rekey-Time")) {
270 vpninfo->ssl_times.rekey = atol(colon);
271 } else if (!strcmp(buf + 7, "Content-Encoding")) {
272 if (!strcmp(colon, "deflate"))
273 vpninfo->deflate = 1;
275 vpn_progress(vpninfo, PRG_ERR,
276 _("Unknown CSTP-Content-Encoding %s\n"),
280 } else if (!strcmp(buf + 7, "MTU")) {
281 vpninfo->mtu = atol(colon);
282 } else if (!strcmp(buf + 7, "Address")) {
283 if (strchr(new_option->value, ':'))
284 vpninfo->vpn_addr6 = new_option->value;
286 vpninfo->vpn_addr = new_option->value;
287 } else if (!strcmp(buf + 7, "Netmask")) {
288 if (strchr(new_option->value, ':'))
289 vpninfo->vpn_netmask6 = new_option->value;
291 vpninfo->vpn_netmask = new_option->value;
292 } else if (!strcmp(buf + 7, "DNS")) {
294 for (j = 0; j < 3; j++) {
295 if (!vpninfo->vpn_dns[j]) {
296 vpninfo->vpn_dns[j] = new_option->value;
300 } else if (!strcmp(buf + 7, "NBNS")) {
302 for (j = 0; j < 3; j++) {
303 if (!vpninfo->vpn_nbns[j]) {
304 vpninfo->vpn_nbns[j] = new_option->value;
308 } else if (!strcmp(buf + 7, "Default-Domain")) {
309 vpninfo->vpn_domain = new_option->value;
310 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
311 vpninfo->vpn_proxy_pac = new_option->value;
312 } else if (!strcmp(buf + 7, "Banner")) {
313 vpninfo->banner = new_option->value;
314 } else if (!strcmp(buf + 7, "Split-Include")) {
315 struct split_include *inc = malloc(sizeof(*inc));
318 inc->route = new_option->value;
319 inc->next = vpninfo->split_includes;
320 vpninfo->split_includes = inc;
321 } else if (!strcmp(buf + 7, "Split-Exclude")) {
322 struct split_include *exc = malloc(sizeof(*exc));
325 exc->route = new_option->value;
326 exc->next = vpninfo->split_excludes;
327 vpninfo->split_excludes = exc;
331 if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
332 vpn_progress(vpninfo, PRG_ERR,
333 _("No IP address received. Aborting\n"));
337 if (strcmp(old_addr, vpninfo->vpn_addr)) {
338 vpn_progress(vpninfo, PRG_ERR,
339 _("Reconnect gave different Legacy IP address (%s != %s)\n"),
340 vpninfo->vpn_addr, old_addr);
345 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
346 vpn_progress(vpninfo, PRG_ERR,
347 _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
348 vpninfo->vpn_netmask, old_netmask);
353 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
354 vpn_progress(vpninfo, PRG_ERR,
355 _("Reconnect gave different IPv6 address (%s != %s)\n"),
356 vpninfo->vpn_addr6, old_addr6);
361 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
362 vpn_progress(vpninfo, PRG_ERR,
363 _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
364 vpninfo->vpn_netmask6, old_netmask6);
369 while (old_dtls_opts) {
370 struct vpn_option *tmp = old_dtls_opts;
371 old_dtls_opts = old_dtls_opts->next;
376 while (old_cstp_opts) {
377 struct vpn_option *tmp = old_cstp_opts;
378 old_cstp_opts = old_cstp_opts->next;
383 vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
384 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
386 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
387 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
389 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
390 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
393 vpninfo->dtls_attempt_period = 0;
395 vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
396 vpninfo->ssl_times.last_tx = time(NULL);
401 int make_cstp_connection(struct openconnect_info *vpninfo)
405 ret = openconnect_open_https(vpninfo);
409 if (vpninfo->deflate) {
410 vpninfo->deflate_adler32 = 1;
411 vpninfo->inflate_adler32 = 1;
413 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
414 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
415 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
416 vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
417 vpninfo->deflate = 0;
420 if (!vpninfo->deflate_pkt) {
421 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
422 if (!vpninfo->deflate_pkt) {
423 vpn_progress(vpninfo, PRG_ERR,
424 _("Allocation of deflate buffer failed\n"));
425 inflateEnd(&vpninfo->inflate_strm);
426 deflateEnd(&vpninfo->deflate_strm);
427 vpninfo->deflate = 0;
429 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
430 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
431 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
436 return start_cstp_connection(vpninfo);
439 int cstp_reconnect(struct openconnect_info *vpninfo)
445 openconnect_close_https(vpninfo);
447 /* Requeue the original packet that was deflated */
448 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
449 vpninfo->current_ssl_pkt = NULL;
450 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
451 vpninfo->pending_deflated_pkt = NULL;
453 if (vpninfo->deflate) {
454 inflateEnd(&vpninfo->inflate_strm);
455 deflateEnd(&vpninfo->deflate_strm);
457 timeout = vpninfo->reconnect_timeout;
458 interval = vpninfo->reconnect_interval;
460 while ((ret = make_cstp_connection(vpninfo))) {
463 vpn_progress(vpninfo, PRG_INFO,
464 _("sleep %ds, remaining timeout %ds\n"),
470 interval += vpninfo->reconnect_interval;
471 if (interval > RECONNECT_INTERVAL_MAX)
472 interval = RECONNECT_INTERVAL_MAX;
474 script_config_tun(vpninfo, "reconnect");
478 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
479 unsigned char *buf, int len)
481 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
489 vpninfo->inflate_strm.next_in = buf;
490 vpninfo->inflate_strm.avail_in = len - 4;
492 vpninfo->inflate_strm.next_out = new->data;
493 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
494 vpninfo->inflate_strm.total_out = 0;
496 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
497 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
502 new->len = vpninfo->inflate_strm.total_out;
504 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
505 new->data, new->len);
507 pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
508 (buf[len - 3] << 16) | (buf[len - 4] << 24);
510 if (vpninfo->inflate_adler32 != pkt_sum) {
511 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
514 vpn_progress(vpninfo, PRG_TRACE,
515 _("Received compressed data packet of %ld bytes\n"),
516 (long)vpninfo->inflate_strm.total_out);
518 queue_packet(&vpninfo->incoming_queue, new);
522 #if defined (OPENCONNECT_OPENSSL)
523 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
527 len = SSL_read(vpninfo->https_ssl, buf, maxlen);
531 ret = SSL_get_error(vpninfo->https_ssl, len);
532 if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
533 vpn_progress(vpninfo, PRG_ERR,
534 _("SSL read error %d (server probably closed connection); reconnecting.\n"),
541 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
545 ret = SSL_write(vpninfo->https_ssl, buf, buflen);
549 ret = SSL_get_error(vpninfo->https_ssl, ret);
551 case SSL_ERROR_WANT_WRITE:
552 /* Waiting for the socket to become writable -- it's
553 probably stalled, and/or the buffers are full */
554 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
555 case SSL_ERROR_WANT_READ:
559 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
560 openconnect_report_ssl_errors(vpninfo);
564 #elif defined (OPENCONNECT_GNUTLS)
565 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
569 ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
573 if (ret != GNUTLS_E_AGAIN) {
574 vpn_progress(vpninfo, PRG_ERR,
575 _("SSL read error: %s; reconnecting.\n"),
576 gnutls_strerror(ret));
582 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
586 ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
590 if (ret == GNUTLS_E_AGAIN) {
591 if (gnutls_record_get_direction(vpninfo->https_sess)) {
592 /* Waiting for the socket to become writable -- it's
593 probably stalled, and/or the buffers are full */
594 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
598 vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
599 gnutls_strerror(ret));
604 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
606 unsigned char buf[16384];
610 /* FIXME: The poll() handling here is fairly simplistic. Actually,
611 if the SSL connection stalls it could return a WANT_WRITE error
612 on _either_ of the SSL_read() or SSL_write() calls. In that case,
613 we should probably remove POLLIN from the events we're looking for,
614 and add POLLOUT. As it is, though, it'll just chew CPU time in that
615 fairly unlikely situation, until the write backlog clears. */
616 while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
619 if (buf[0] != 'S' || buf[1] != 'T' ||
620 buf[2] != 'F' || buf[3] != 1 || buf[7])
623 payload_len = (buf[4] << 8) + buf[5];
624 if (len != 8 + payload_len) {
625 vpn_progress(vpninfo, PRG_ERR,
626 _("Unexpected packet length. SSL_read returned %d but packet is\n"),
628 vpn_progress(vpninfo, PRG_ERR,
629 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
630 buf[0], buf[1], buf[2], buf[3],
631 buf[4], buf[5], buf[6], buf[7]);
634 vpninfo->ssl_times.last_rx = time(NULL);
637 vpn_progress(vpninfo, PRG_TRACE,
638 _("Got CSTP DPD request\n"));
639 vpninfo->owe_ssl_dpd_response = 1;
642 case AC_PKT_DPD_RESP:
643 vpn_progress(vpninfo, PRG_TRACE,
644 _("Got CSTP DPD response\n"));
647 case AC_PKT_KEEPALIVE:
648 vpn_progress(vpninfo, PRG_TRACE,
649 _("Got CSTP Keepalive\n"));
653 vpn_progress(vpninfo, PRG_TRACE,
654 _("Received uncompressed data packet of %d bytes\n"),
656 queue_new_packet(&vpninfo->incoming_queue, buf + 8,
661 case AC_PKT_DISCONN: {
663 for (i = 0; i < payload_len; i++) {
664 if (!isprint(buf[payload_len + 8 + i]))
665 buf[payload_len + 8 + i] = '.';
667 buf[payload_len + 8] = 0;
668 vpn_progress(vpninfo, PRG_ERR,
669 _("Received server disconnect: %02x '%s'\n"),
671 vpninfo->quit_reason = "Server request";
674 case AC_PKT_COMPRESSED:
675 if (!vpninfo->deflate) {
676 vpn_progress(vpninfo, PRG_ERR,
677 _("Compressed packet received in !deflate mode\n"));
680 inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
684 case AC_PKT_TERM_SERVER:
685 vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
686 vpninfo->quit_reason = "Server request";
691 vpn_progress(vpninfo, PRG_ERR,
692 _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
693 buf[0], buf[1], buf[2], buf[3],
694 buf[4], buf[5], buf[6], buf[7]);
695 vpninfo->quit_reason = "Unknown packet received";
702 /* If SSL_write() fails we are expected to try again. With exactly
703 the same data, at exactly the same location. So we keep the
704 packet we had before.... */
705 if (vpninfo->current_ssl_pkt) {
707 vpninfo->ssl_times.last_tx = time(NULL);
708 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
710 ret = cstp_write(vpninfo,
711 vpninfo->current_ssl_pkt->hdr,
712 vpninfo->current_ssl_pkt->len + 8);
716 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
719 if (ret != vpninfo->current_ssl_pkt->len + 8) {
720 vpn_progress(vpninfo, PRG_ERR,
721 _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
722 vpninfo->current_ssl_pkt->len + 8, ret);
723 vpninfo->quit_reason = "Internal error";
726 /* Don't free the 'special' packets */
727 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
728 free(vpninfo->pending_deflated_pkt);
729 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
730 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
731 vpninfo->current_ssl_pkt != &keepalive_pkt)
732 free(vpninfo->current_ssl_pkt);
734 vpninfo->current_ssl_pkt = NULL;
737 if (vpninfo->owe_ssl_dpd_response) {
738 vpninfo->owe_ssl_dpd_response = 0;
739 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
740 goto handle_outgoing;
743 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
745 /* Not that this will ever happen; we don't even process
746 the setting when we're asked for it. */
747 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
753 vpn_progress(vpninfo, PRG_ERR,
754 _("CSTP Dead Peer Detection detected dead peer!\n"));
756 if (cstp_reconnect(vpninfo)) {
757 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
758 vpninfo->quit_reason = "CSTP reconnect failed";
761 /* I think we can leave DTLS to its own devices; when we reconnect
762 with the same master secret, we do seem to get the same sessid */
766 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
768 vpninfo->current_ssl_pkt = &dpd_pkt;
769 goto handle_outgoing;
772 /* No need to send an explicit keepalive
773 if we have real data to send */
774 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
777 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
779 vpninfo->current_ssl_pkt = &keepalive_pkt;
780 goto handle_outgoing;
786 /* Service outgoing packet queue, if no DTLS */
787 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
788 struct pkt *this = vpninfo->outgoing_queue;
789 vpninfo->outgoing_queue = this->next;
790 vpninfo->outgoing_qlen--;
792 if (vpninfo->deflate) {
793 unsigned char *adler;
796 vpninfo->deflate_strm.next_in = this->data;
797 vpninfo->deflate_strm.avail_in = this->len;
798 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
799 vpninfo->deflate_strm.avail_out = 2040;
800 vpninfo->deflate_strm.total_out = 0;
802 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
804 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
808 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
809 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
811 /* Add ongoing adler32 to tail of compressed packet */
812 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
813 this->data, this->len);
815 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
816 *(adler++) = vpninfo->deflate_adler32 >> 24;
817 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
818 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
819 *(adler) = vpninfo->deflate_adler32 & 0xff;
821 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
823 vpn_progress(vpninfo, PRG_TRACE,
824 _("Sending compressed data packet of %d bytes\n"),
827 vpninfo->pending_deflated_pkt = this;
828 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
831 memcpy(this->hdr, data_hdr, 8);
832 this->hdr[4] = this->len >> 8;
833 this->hdr[5] = this->len & 0xff;
835 vpn_progress(vpninfo, PRG_TRACE,
836 _("Sending uncompressed data packet of %d bytes\n"),
839 vpninfo->current_ssl_pkt = this;
841 goto handle_outgoing;
844 /* Work is not done if we just got rid of packets off the queue */
848 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
850 unsigned char *bye_pkt;
853 /* already lost connection? */
854 #if defined (OPENCONNECT_OPENSSL)
855 if (!vpninfo->https_ssl)
857 #elif defined (OPENCONNECT_GNUTLS)
858 if (!vpninfo->https_sess)
862 reason_len = strlen(reason);
863 bye_pkt = malloc(reason_len + 9);
867 memcpy(bye_pkt, data_hdr, 8);
868 memcpy(bye_pkt + 9, reason, reason_len);
870 bye_pkt[4] = (reason_len + 1) >> 8;
871 bye_pkt[5] = (reason_len + 1) & 0xff;
872 bye_pkt[6] = AC_PKT_DISCONN;
875 vpn_progress(vpninfo, PRG_INFO,
876 _("Send BYE packet: %s\n"), reason);
878 cstp_write(vpninfo, bye_pkt, reason_len + 9);