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