Clean up DTLS timer workaround to make it work with Debian OpenSSL, hopefully
[platform/upstream/openconnect.git] / dtls.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2010 Intel Corporation.
5  *
6  * Author: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to:
19  *
20  *   Free Software Foundation, Inc.
21  *   51 Franklin Street, Fifth Floor,
22  *   Boston, MA 02110-1301 USA
23  */
24
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <netinet/in.h>
31 #include <openssl/err.h>
32 #include <openssl/ssl.h>
33 #include <fcntl.h>
34 #include <string.h>
35
36 #include "openconnect-internal.h"
37
38 #ifdef HAVE_DTLS1_STOP_TIMER
39 /* OpenSSL doesn't deliberately export this, but we need it to
40    workaround a DTLS bug in versions < 1.0.0e */
41 extern void dtls1_stop_timer (SSL *);
42 #endif
43
44 static unsigned char nybble(unsigned char n)
45 {
46         if      (n >= '0' && n <= '9') return n - '0';
47         else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
48         else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
49         return 0;
50 }
51
52 unsigned char unhex(const char *data)
53 {
54         return (nybble(data[0]) << 4) | nybble(data[1]);
55 }
56
57 #ifdef SSL_OP_CISCO_ANYCONNECT
58 #if 0
59 /*
60  * Useful for catching test cases, where we want everything to be
61  * reproducible.  *NEVER* do this in the wild.
62  */
63 time_t time(time_t *t)
64 {
65         time_t x = 0x3ab2d948;
66         if (t) *t = x;
67         return x;
68 }
69
70 int RAND_pseudo_bytes(char *buf, int len)
71 {
72         memset(buf, 0x5a, len);
73         printf("FAKE PSEUDO RANDOM!\n");
74         return 1;
75
76 }
77 int RAND_bytes(char *buf, int len)
78 {
79         static int foo = 0x5b;
80         printf("FAKE RANDOM!\n");
81         memset(buf, foo, len);
82         return 1;
83 }
84 #endif
85
86 /*
87  * The master-secret is generated randomly by the client. The server
88  * responds with a DTLS Session-ID. These, done over the HTTPS
89  * connection, are enough to 'resume' a DTLS session, bypassing all
90  * the normal setup of a normal DTLS connection.
91  *
92  * Cisco use a version of the protocol which predates RFC4347, but
93  * isn't quite the same as the pre-RFC version of the protocol which
94  * was in OpenSSL 0.9.8e -- it includes backports of some later
95  * OpenSSL patches.
96  *
97  * The openssl/ directory of this source tree should contain both a
98  * small patch against OpenSSL 0.9.8e to make it support Cisco's
99  * snapshot of the protocol, and a larger patch against newer OpenSSL
100  * which gives us an option to use the old protocol again.
101  *
102  * Cisco's server also seems to respond to the official version of the
103  * protocol, with a change in the ChangeCipherSpec packet which implies
104  * that it does know the difference and isn't just repeating the version
105  * number seen in the ClientHello. But although I can make the handshake
106  * complete by hacking tls1_mac() to use the _old_ protocol version
107  * number when calculating the MAC, the server still seems to be ignoring
108  * my subsequent data packets. So we use the old protocol, which is what
109  * their clients use anyway.
110  */
111
112 int connect_dtls_socket(struct openconnect_info *vpninfo)
113 {
114         STACK_OF(SSL_CIPHER) *ciphers;
115         method_const SSL_METHOD *dtls_method;
116         SSL_CIPHER *dtls_cipher;
117         SSL *dtls_ssl;
118         BIO *dtls_bio;
119         int dtls_fd;
120
121         if (!vpninfo->dtls_addr) {
122                 vpn_progress(vpninfo, PRG_ERR, "No DTLS address\n");
123                 vpninfo->dtls_attempt_period = 0;
124                 return -EINVAL;
125         }
126
127         if (!vpninfo->dtls_cipher) {
128                 /* We probably didn't offer it any ciphers it liked */
129                 vpn_progress(vpninfo, PRG_ERR, "Server offered no DTLS cipher option\n");
130                 vpninfo->dtls_attempt_period = 0;
131                 return -EINVAL;
132         }
133
134         if (vpninfo->proxy) {
135                 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
136                 vpn_progress(vpninfo, PRG_ERR, "No DTLS when connected via proxy\n");
137                 vpninfo->dtls_attempt_period = 0;
138                 return -EINVAL;
139         }
140
141         dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
142         if (dtls_fd < 0) {
143                 perror("Open UDP socket for DTLS:");
144                 return -EINVAL;
145         }
146
147         if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
148                 perror("UDP (DTLS) connect:\n");
149                 close(dtls_fd);
150                 return -EINVAL;
151         }
152
153         fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
154
155         if (!vpninfo->dtls_ctx) {
156                 dtls_method = DTLSv1_client_method();
157                 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
158                 if (!vpninfo->dtls_ctx) {
159                         vpn_progress(vpninfo, PRG_ERR, "Initialise DTLSv1 CTX failed\n");
160                         vpninfo->dtls_attempt_period = 0;
161                         return -EINVAL;
162                 }
163
164                 /* If we don't readahead, then we do short reads and throw
165                    away the tail of data packets. */
166                 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
167
168                 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
169                         vpn_progress(vpninfo, PRG_ERR, "Set DTLS cipher list failed\n");
170                         SSL_CTX_free(vpninfo->dtls_ctx);
171                         vpninfo->dtls_ctx = NULL;
172                         vpninfo->dtls_attempt_period = 0;
173                         return -EINVAL;
174                 }
175         }
176
177         if (!vpninfo->dtls_session) {
178                 /* We're going to "resume" a session which never existed. Fake it... */
179                 vpninfo->dtls_session = SSL_SESSION_new();
180                 if (!vpninfo->dtls_session) {
181                         vpn_progress(vpninfo, PRG_ERR, "Initialise DTLSv1 session failed\n");
182                         vpninfo->dtls_attempt_period = 0;
183                         return -EINVAL;
184                 }
185                 vpninfo->dtls_session->ssl_version = 0x0100; // DTLS1_BAD_VER
186         }
187
188         /* Do this every time; it may have changed due to a rekey */
189         vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
190         memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
191                sizeof(vpninfo->dtls_secret));
192
193         vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
194         memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
195                sizeof(vpninfo->dtls_session_id));
196
197         dtls_ssl = SSL_new(vpninfo->dtls_ctx);
198         SSL_set_connect_state(dtls_ssl);
199
200         ciphers = SSL_get_ciphers(dtls_ssl);
201         if (sk_SSL_CIPHER_num(ciphers) != 1) {
202                 vpn_progress(vpninfo, PRG_ERR, "Not precisely one DTLS cipher\n");
203                 SSL_CTX_free(vpninfo->dtls_ctx);
204                 SSL_free(dtls_ssl);
205                 SSL_SESSION_free(vpninfo->dtls_session);
206                 vpninfo->dtls_ctx = NULL;
207                 vpninfo->dtls_session = NULL;
208                 vpninfo->dtls_attempt_period = 0;
209                 return -EINVAL;
210         }
211         dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
212
213         /* Set the appropriate cipher on our session to be resumed */
214         vpninfo->dtls_session->cipher = dtls_cipher;
215         vpninfo->dtls_session->cipher_id = dtls_cipher->id;
216
217         /* Add the generated session to the SSL */
218         if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
219                 vpn_progress(vpninfo, PRG_ERR,
220                                   "SSL_set_session() failed with old protocol version 0x%x\n"
221                                   "Are you using a version of OpenSSL older than 0.9.8m?\n"
222                                   "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
223                                   "Use the --no-dtls command line option to avoid this message\n",
224                                   vpninfo->dtls_session->ssl_version);
225                 vpninfo->dtls_attempt_period = 0;
226                 return -EINVAL;
227         }
228
229         /* Go Go Go! */
230         dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
231         SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
232
233         SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
234
235         /* Set non-blocking */
236         BIO_set_nbio(SSL_get_rbio(dtls_ssl), 1);
237         BIO_set_nbio(SSL_get_wbio(dtls_ssl), 1);
238
239         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
240
241         vpninfo->new_dtls_fd = dtls_fd;
242         vpninfo->new_dtls_ssl = dtls_ssl;
243
244         if (vpninfo->select_nfds <= dtls_fd)
245                 vpninfo->select_nfds = dtls_fd + 1;
246
247         FD_SET(dtls_fd, &vpninfo->select_rfds);
248         FD_SET(dtls_fd, &vpninfo->select_efds);
249
250         time(&vpninfo->new_dtls_started);
251         return dtls_try_handshake(vpninfo);
252 }
253
254 int dtls_try_handshake(struct openconnect_info *vpninfo)
255 {
256         int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
257
258         if (ret == 1) {
259                 vpn_progress(vpninfo, PRG_INFO, "Established DTLS connection\n");
260
261                 if (vpninfo->dtls_ssl) {
262                         /* We are replacing an old connection */
263                         SSL_free(vpninfo->dtls_ssl);
264                         close(vpninfo->dtls_fd);
265                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
266                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
267                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
268                 }
269                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
270                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
271
272                 vpninfo->new_dtls_ssl = NULL;
273                 vpninfo->new_dtls_fd = -1;
274
275                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
276
277                 /* From about 8.4.1(11) onwards, the ASA seems to get
278                    very unhappy if we resend ChangeCipherSpec messages
279                    after the initial setup. This was "fixed" in OpenSSL
280                    1.0.0e for RT#2505, but it's not clear if that was
281                    the right fix. What happens if the original packet
282                    *does* get lost? Surely we *wanted* the retransmits,
283                    because without them the server will never be able
284                    to decrypt anything we send?
285                    Oh well, our retransmitted packets upset the server
286                    because we don't get the Cisco-compatibility right
287                    (this is one of the areas in which Cisco's DTLS differs
288                    from the RFC4347 spec), and DPD should help us notice
289                    if *nothing* is getting through. */
290 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
291                 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
292                    However, if we were *built* against 1.0.0e or newer, but at
293                    runtime we find that we are being run against an older 
294                    version, warn about it. */
295                 if (SSLeay() < 0x1000005fL) {
296                         vpn_progress(vpninfo, PRG_WARNING,
297                                      "Your OpenSSL is older than the one you built against, so DTLS may fail!");
298                 }
299 #elif defined (HAVE_DTLS1_STOP_TIMER)
300                 dtls1_stop_timer(vpninfo->dtls_ssl);
301 #else
302                 /* Debian restricts visibility of dtls1_stop_timer()
303                    so do it manually. Thankfully this *should* work,
304                    from 0.9.8m to 1.0.0d inclusive, and we don't have
305                    to worry about future changes because we don't do
306                    this for 1.0.0e and above anyway */
307                 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
308                         sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
309                 vpninfo->dtls_ssl->d1->timeout_duration = 1;
310                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
311                          BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
312                          &(vpninfo->dtls_ssl->d1->next_timeout));
313 #endif
314                 return 0;
315         }
316
317         ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
318         if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
319                 if (time(NULL) < vpninfo->new_dtls_started + 5)
320                         return 0;
321                 vpn_progress(vpninfo, PRG_TRACE, "DTLS handshake timed out\n");
322         }
323
324         vpn_progress(vpninfo, PRG_ERR, "DTLS handshake failed: %d\n", ret);
325         report_ssl_errors(vpninfo);
326
327         /* Kill the new (failed) connection... */
328         SSL_free(vpninfo->new_dtls_ssl);
329         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
330         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
331         close(vpninfo->new_dtls_fd);
332         vpninfo->new_dtls_ssl = NULL;
333         vpninfo->new_dtls_fd = -1;
334
335         /* ... and kill the old one too. The only time there'll be a valid
336            existing session is when it was a rekey, and in that case it's
337            time for the old one to die. */
338         if (vpninfo->dtls_ssl) {
339                 SSL_free(vpninfo->dtls_ssl);
340                 close(vpninfo->dtls_fd);
341                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
342                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
343                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
344                 vpninfo->dtls_ssl = NULL;
345                 vpninfo->dtls_fd = -1;
346         }
347
348         time(&vpninfo->new_dtls_started);
349         return -EINVAL;
350 }
351
352 static int dtls_restart(struct openconnect_info *vpninfo)
353 {
354         if (vpninfo->dtls_ssl) {
355                 SSL_free(vpninfo->dtls_ssl);
356                 close(vpninfo->dtls_fd);
357                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
358                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
359                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
360                 vpninfo->dtls_ssl = NULL;
361                 vpninfo->dtls_fd = -1;
362         }
363
364         return connect_dtls_socket(vpninfo);
365 }
366
367
368 int setup_dtls(struct openconnect_info *vpninfo)
369 {
370         struct vpn_option *dtls_opt = vpninfo->dtls_options;
371         int dtls_port = 0;
372
373         while (dtls_opt) {
374                 vpn_progress(vpninfo, PRG_TRACE,
375                                   "DTLS option %s : %s\n",
376                                   dtls_opt->option, dtls_opt->value);
377
378                 if (!strcmp(dtls_opt->option + 7, "Port")) {
379                         dtls_port = atol(dtls_opt->value);
380                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
381                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
382                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
383                         int j = atol(dtls_opt->value);
384                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
385                                 vpninfo->dtls_times.dpd = j;
386                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
387                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
388                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
389                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
390                 }
391
392                 dtls_opt = dtls_opt->next;
393         }
394         if (!dtls_port) {
395                 vpninfo->dtls_attempt_period = 0;
396                 return -EINVAL;
397         }
398
399         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
400         if (!vpninfo->dtls_addr) {
401                 vpninfo->dtls_attempt_period = 0;
402                 return -ENOMEM;
403         }
404         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
405
406         if (vpninfo->peer_addr->sa_family == AF_INET) {
407                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
408                 sin->sin_port = htons(dtls_port);
409         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
410                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
411                 sin->sin6_port = htons(dtls_port);
412         } else {
413                 vpn_progress(vpninfo, PRG_ERR, "Unknown protocol family %d. Cannot do DTLS\n",
414                                   vpninfo->peer_addr->sa_family);
415                 vpninfo->dtls_attempt_period = 0;
416                 return -EINVAL;
417         }
418
419         if (connect_dtls_socket(vpninfo))
420                 return -EINVAL;
421
422         vpn_progress(vpninfo, PRG_TRACE,
423                           "DTLS connected. DPD %d, Keepalive %d\n",
424                           vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
425
426         return 0;
427 }
428
429 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
430 {
431         unsigned char buf[2000];
432         int len;
433         int work_done = 0;
434         char magic_pkt;
435
436         while ( (len = SSL_read(vpninfo->dtls_ssl, buf, sizeof(buf))) > 0 ) {
437
438                 vpn_progress(vpninfo, PRG_TRACE,
439                                   "Received DTLS packet 0x%02x of %d bytes\n",
440                                   buf[0], len);
441
442                 vpninfo->dtls_times.last_rx = time(NULL);
443
444                 switch(buf[0]) {
445                 case AC_PKT_DATA:
446                         queue_new_packet(&vpninfo->incoming_queue, buf+1, len-1);
447                         work_done = 1;
448                         break;
449
450                 case AC_PKT_DPD_OUT:
451                         vpn_progress(vpninfo, PRG_TRACE, "Got DTLS DPD request\n");
452
453                         /* FIXME: What if the packet doesn't get through? */
454                         magic_pkt = AC_PKT_DPD_RESP;
455                         if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
456                                 vpn_progress(vpninfo, PRG_ERR, "Failed to send DPD response. Expect disconnect\n");
457                         continue;
458
459                 case AC_PKT_DPD_RESP:
460                         vpn_progress(vpninfo, PRG_TRACE, "Got DTLS DPD response\n");
461                         break;
462
463                 case AC_PKT_KEEPALIVE:
464                         vpn_progress(vpninfo, PRG_TRACE, "Got DTLS Keepalive\n");
465                         break;
466
467                 default:
468                         vpn_progress(vpninfo, PRG_ERR,
469                                           "Unknown DTLS packet type %02x, len %d\n", buf[0], len);
470                         if (1) {
471                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
472                                  * packets. Not only do they wrongly decide to drop packets if
473                                  * two packets get swapped in transit, but they also _fail_ to
474                                  * drop the packet in non-blocking mode; instead they return
475                                  * the appropriate length of garbage. So don't abort... for now. */
476                                 break;
477                         } else {
478                                 vpninfo->quit_reason = "Unknown packet received";
479                                 return 1;
480                         }
481
482                 }
483         }
484
485         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
486         case KA_REKEY:
487                 vpn_progress(vpninfo, PRG_INFO, "DTLS rekey due\n");
488
489                 /* There ought to be a method of rekeying DTLS without tearing down
490                    the CSTP session and restarting, but we don't (yet) know it */
491                 if (cstp_reconnect(vpninfo)) {
492                         vpn_progress(vpninfo, PRG_ERR, "Reconnect failed\n");
493                         vpninfo->quit_reason = "CSTP reconnect failed";
494                         return 1;
495                 }
496
497                 if (dtls_restart(vpninfo)) {
498                         vpn_progress(vpninfo, PRG_ERR, "DTLS rekey failed\n");
499                         return 1;
500                 }
501                 work_done = 1;
502                 break;
503
504
505         case KA_DPD_DEAD:
506                 vpn_progress(vpninfo, PRG_ERR, "DTLS Dead Peer Detection detected dead peer!\n");
507                 /* Fall back to SSL, and start a new DTLS connection */
508                 dtls_restart(vpninfo);
509                 return 1;
510
511         case KA_DPD:
512                 vpn_progress(vpninfo, PRG_TRACE, "Send DTLS DPD\n");
513
514                 magic_pkt = AC_PKT_DPD_OUT;
515                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
516                 /* last_dpd will just have been set */
517                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
518                 work_done = 1;
519                 break;
520
521         case KA_KEEPALIVE:
522                 /* No need to send an explicit keepalive
523                    if we have real data to send */
524                 if (vpninfo->outgoing_queue)
525                         break;
526
527                 vpn_progress(vpninfo, PRG_TRACE, "Send DTLS Keepalive\n");
528
529                 magic_pkt = AC_PKT_KEEPALIVE;
530                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
531                 time(&vpninfo->dtls_times.last_tx);
532                 work_done = 1;
533                 break;
534
535         case KA_NONE:
536                 ;
537         }
538
539         /* Service outgoing packet queue */
540         while (vpninfo->outgoing_queue) {
541                 struct pkt *this = vpninfo->outgoing_queue;
542                 int ret;
543
544                 vpninfo->outgoing_queue = this->next;
545                 vpninfo->outgoing_qlen--;
546
547                 /* One byte of header */
548                 this->hdr[7] = AC_PKT_DATA;
549
550                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
551                 if (ret <= 0) {
552                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
553
554                         /* If it's a real error, kill the DTLS connection and
555                            requeue the packet to be sent over SSL */
556                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
557                                 vpn_progress(vpninfo, PRG_ERR,
558                                                   "DTLS got write error %d. Falling back to SSL\n", ret);
559                                 report_ssl_errors(vpninfo);
560                                 dtls_restart(vpninfo);
561                                 vpninfo->outgoing_queue = this;
562                                 vpninfo->outgoing_qlen++;
563                         }
564                         return 1;
565                 }
566                 time(&vpninfo->dtls_times.last_tx);
567                 vpn_progress(vpninfo, PRG_TRACE,
568                                   "Sent DTLS packet of %d bytes; SSL_write() returned %d\n",
569                                   this->len, ret);
570                 free(this);
571         }
572
573         return work_done;
574 }
575 #else /* No DTLS support in OpenSSL */
576 #warning Your version of OpenSSL does not seem to support Cisco DTLS compatibility
577  int setup_dtls(struct openconnect_info *vpninfo)
578 {
579         vpn_progress(vpninfo, PRG_ERR, "Built against OpenSSL with no Cisco DTLS support\n");
580         return -EINVAL;
581 }
582 #endif
583