Remove all _xxx_SOURCE macros from source, do it in configure.
[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,
160                                      _("Initialise DTLSv1 CTX failed\n"));
161                         vpninfo->dtls_attempt_period = 0;
162                         return -EINVAL;
163                 }
164
165                 /* If we don't readahead, then we do short reads and throw
166                    away the tail of data packets. */
167                 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
168
169                 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
170                         vpn_progress(vpninfo, PRG_ERR,
171                                      _("Set DTLS cipher list failed\n"));
172                         SSL_CTX_free(vpninfo->dtls_ctx);
173                         vpninfo->dtls_ctx = NULL;
174                         vpninfo->dtls_attempt_period = 0;
175                         return -EINVAL;
176                 }
177         }
178
179         if (!vpninfo->dtls_session) {
180                 /* We're going to "resume" a session which never existed. Fake it... */
181                 vpninfo->dtls_session = SSL_SESSION_new();
182                 if (!vpninfo->dtls_session) {
183                         vpn_progress(vpninfo, PRG_ERR,
184                                      _("Initialise DTLSv1 session failed\n"));
185                         vpninfo->dtls_attempt_period = 0;
186                         return -EINVAL;
187                 }
188                 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
189         }
190
191         /* Do this every time; it may have changed due to a rekey */
192         vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
193         memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
194                sizeof(vpninfo->dtls_secret));
195
196         vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
197         memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
198                sizeof(vpninfo->dtls_session_id));
199
200         dtls_ssl = SSL_new(vpninfo->dtls_ctx);
201         SSL_set_connect_state(dtls_ssl);
202
203         ciphers = SSL_get_ciphers(dtls_ssl);
204         if (sk_SSL_CIPHER_num(ciphers) != 1) {
205                 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
206                 SSL_CTX_free(vpninfo->dtls_ctx);
207                 SSL_free(dtls_ssl);
208                 SSL_SESSION_free(vpninfo->dtls_session);
209                 vpninfo->dtls_ctx = NULL;
210                 vpninfo->dtls_session = NULL;
211                 vpninfo->dtls_attempt_period = 0;
212                 return -EINVAL;
213         }
214         dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
215
216         /* Set the appropriate cipher on our session to be resumed */
217         vpninfo->dtls_session->cipher = dtls_cipher;
218         vpninfo->dtls_session->cipher_id = dtls_cipher->id;
219
220         /* Add the generated session to the SSL */
221         if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
222                 vpn_progress(vpninfo, PRG_ERR,
223                              _("SSL_set_session() failed with old protocol version 0x%x\n"
224                                "Are you using a version of OpenSSL older than 0.9.8m?\n"
225                                "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
226                                "Use the --no-dtls command line option to avoid this message\n"),
227                              vpninfo->dtls_session->ssl_version);
228                 vpninfo->dtls_attempt_period = 0;
229                 return -EINVAL;
230         }
231
232         /* Go Go Go! */
233         dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
234         SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
235
236         SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
237
238         /* Set non-blocking */
239         BIO_set_nbio(SSL_get_rbio(dtls_ssl), 1);
240         BIO_set_nbio(SSL_get_wbio(dtls_ssl), 1);
241
242         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
243
244         vpninfo->new_dtls_fd = dtls_fd;
245         vpninfo->new_dtls_ssl = dtls_ssl;
246
247         if (vpninfo->select_nfds <= dtls_fd)
248                 vpninfo->select_nfds = dtls_fd + 1;
249
250         FD_SET(dtls_fd, &vpninfo->select_rfds);
251         FD_SET(dtls_fd, &vpninfo->select_efds);
252
253         time(&vpninfo->new_dtls_started);
254         return dtls_try_handshake(vpninfo);
255 }
256
257 int dtls_try_handshake(struct openconnect_info *vpninfo)
258 {
259         int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
260
261         if (ret == 1) {
262                 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection\n"));
263
264                 if (vpninfo->dtls_ssl) {
265                         /* We are replacing an old connection */
266                         SSL_free(vpninfo->dtls_ssl);
267                         close(vpninfo->dtls_fd);
268                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
269                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
270                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
271                 }
272                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
273                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
274
275                 vpninfo->new_dtls_ssl = NULL;
276                 vpninfo->new_dtls_fd = -1;
277
278                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
279
280                 /* From about 8.4.1(11) onwards, the ASA seems to get
281                    very unhappy if we resend ChangeCipherSpec messages
282                    after the initial setup. This was "fixed" in OpenSSL
283                    1.0.0e for RT#2505, but it's not clear if that was
284                    the right fix. What happens if the original packet
285                    *does* get lost? Surely we *wanted* the retransmits,
286                    because without them the server will never be able
287                    to decrypt anything we send?
288                    Oh well, our retransmitted packets upset the server
289                    because we don't get the Cisco-compatibility right
290                    (this is one of the areas in which Cisco's DTLS differs
291                    from the RFC4347 spec), and DPD should help us notice
292                    if *nothing* is getting through. */
293 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
294                 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
295                    However, if we were *built* against 1.0.0e or newer, but at
296                    runtime we find that we are being run against an older 
297                    version, warn about it. */
298                 if (SSLeay() < 0x1000005fL) {
299                         vpn_progress(vpninfo, PRG_ERR,
300                                      _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
301                 }
302 #elif defined (HAVE_DTLS1_STOP_TIMER)
303                 dtls1_stop_timer(vpninfo->dtls_ssl);
304 #else
305                 /* Debian restricts visibility of dtls1_stop_timer()
306                    so do it manually. Thankfully this *should* work,
307                    from 0.9.8m to 1.0.0d inclusive, and we don't have
308                    to worry about future changes because we don't do
309                    this for 1.0.0e and above anyway */
310                 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
311                         sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
312                 vpninfo->dtls_ssl->d1->timeout_duration = 1;
313                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
314                          BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
315                          &(vpninfo->dtls_ssl->d1->next_timeout));
316 #endif
317                 return 0;
318         }
319
320         ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
321         if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
322                 if (time(NULL) < vpninfo->new_dtls_started + 5)
323                         return 0;
324                 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
325         }
326
327         vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
328         report_ssl_errors(vpninfo);
329
330         /* Kill the new (failed) connection... */
331         SSL_free(vpninfo->new_dtls_ssl);
332         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
333         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
334         close(vpninfo->new_dtls_fd);
335         vpninfo->new_dtls_ssl = NULL;
336         vpninfo->new_dtls_fd = -1;
337
338         /* ... and kill the old one too. The only time there'll be a valid
339            existing session is when it was a rekey, and in that case it's
340            time for the old one to die. */
341         if (vpninfo->dtls_ssl) {
342                 SSL_free(vpninfo->dtls_ssl);
343                 close(vpninfo->dtls_fd);
344                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
345                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
346                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
347                 vpninfo->dtls_ssl = NULL;
348                 vpninfo->dtls_fd = -1;
349         }
350
351         time(&vpninfo->new_dtls_started);
352         return -EINVAL;
353 }
354
355 static int dtls_restart(struct openconnect_info *vpninfo)
356 {
357         if (vpninfo->dtls_ssl) {
358                 SSL_free(vpninfo->dtls_ssl);
359                 close(vpninfo->dtls_fd);
360                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
361                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
362                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
363                 vpninfo->dtls_ssl = NULL;
364                 vpninfo->dtls_fd = -1;
365         }
366
367         return connect_dtls_socket(vpninfo);
368 }
369
370
371 int setup_dtls(struct openconnect_info *vpninfo)
372 {
373         struct vpn_option *dtls_opt = vpninfo->dtls_options;
374         int dtls_port = 0;
375
376         while (dtls_opt) {
377                 vpn_progress(vpninfo, PRG_TRACE,
378                              _("DTLS option %s : %s\n"),
379                              dtls_opt->option, dtls_opt->value);
380
381                 if (!strcmp(dtls_opt->option + 7, "Port")) {
382                         dtls_port = atol(dtls_opt->value);
383                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
384                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
385                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
386                         int j = atol(dtls_opt->value);
387                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
388                                 vpninfo->dtls_times.dpd = j;
389                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
390                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
391                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
392                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
393                 }
394
395                 dtls_opt = dtls_opt->next;
396         }
397         if (!dtls_port) {
398                 vpninfo->dtls_attempt_period = 0;
399                 return -EINVAL;
400         }
401
402         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
403         if (!vpninfo->dtls_addr) {
404                 vpninfo->dtls_attempt_period = 0;
405                 return -ENOMEM;
406         }
407         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
408
409         if (vpninfo->peer_addr->sa_family == AF_INET) {
410                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
411                 sin->sin_port = htons(dtls_port);
412         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
413                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
414                 sin->sin6_port = htons(dtls_port);
415         } else {
416                 vpn_progress(vpninfo, PRG_ERR,
417                              _("Unknown protocol family %d. Cannot do DTLS\n"),
418                              vpninfo->peer_addr->sa_family);
419                 vpninfo->dtls_attempt_period = 0;
420                 return -EINVAL;
421         }
422
423         if (connect_dtls_socket(vpninfo))
424                 return -EINVAL;
425
426         vpn_progress(vpninfo, PRG_TRACE,
427                      _("DTLS connected. DPD %d, Keepalive %d\n"),
428                      vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
429
430         return 0;
431 }
432
433 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
434 {
435         unsigned char buf[2000];
436         int len;
437         int work_done = 0;
438         char magic_pkt;
439
440         while ( (len = SSL_read(vpninfo->dtls_ssl, buf, sizeof(buf))) > 0 ) {
441
442                 vpn_progress(vpninfo, PRG_TRACE,
443                              _("Received DTLS packet 0x%02x of %d bytes\n"),
444                              buf[0], len);
445
446                 vpninfo->dtls_times.last_rx = time(NULL);
447
448                 switch(buf[0]) {
449                 case AC_PKT_DATA:
450                         queue_new_packet(&vpninfo->incoming_queue, buf+1, len-1);
451                         work_done = 1;
452                         break;
453
454                 case AC_PKT_DPD_OUT:
455                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
456
457                         /* FIXME: What if the packet doesn't get through? */
458                         magic_pkt = AC_PKT_DPD_RESP;
459                         if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
460                                 vpn_progress(vpninfo, PRG_ERR,
461                                              _("Failed to send DPD response. Expect disconnect\n"));
462                         continue;
463
464                 case AC_PKT_DPD_RESP:
465                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
466                         break;
467
468                 case AC_PKT_KEEPALIVE:
469                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
470                         break;
471
472                 default:
473                         vpn_progress(vpninfo, PRG_ERR,
474                                      _("Unknown DTLS packet type %02x, len %d\n"),
475                                      buf[0], len);
476                         if (1) {
477                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
478                                  * packets. Not only do they wrongly decide to drop packets if
479                                  * two packets get swapped in transit, but they also _fail_ to
480                                  * drop the packet in non-blocking mode; instead they return
481                                  * the appropriate length of garbage. So don't abort... for now. */
482                                 break;
483                         } else {
484                                 vpninfo->quit_reason = "Unknown packet received";
485                                 return 1;
486                         }
487
488                 }
489         }
490
491         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
492         case KA_REKEY:
493                 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
494
495                 /* There ought to be a method of rekeying DTLS without tearing down
496                    the CSTP session and restarting, but we don't (yet) know it */
497                 if (cstp_reconnect(vpninfo)) {
498                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
499                         vpninfo->quit_reason = "CSTP reconnect failed";
500                         return 1;
501                 }
502
503                 if (dtls_restart(vpninfo)) {
504                         vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
505                         return 1;
506                 }
507                 work_done = 1;
508                 break;
509
510
511         case KA_DPD_DEAD:
512                 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
513                 /* Fall back to SSL, and start a new DTLS connection */
514                 dtls_restart(vpninfo);
515                 return 1;
516
517         case KA_DPD:
518                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
519
520                 magic_pkt = AC_PKT_DPD_OUT;
521                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
522                 /* last_dpd will just have been set */
523                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
524                 work_done = 1;
525                 break;
526
527         case KA_KEEPALIVE:
528                 /* No need to send an explicit keepalive
529                    if we have real data to send */
530                 if (vpninfo->outgoing_queue)
531                         break;
532
533                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
534
535                 magic_pkt = AC_PKT_KEEPALIVE;
536                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
537                 time(&vpninfo->dtls_times.last_tx);
538                 work_done = 1;
539                 break;
540
541         case KA_NONE:
542                 ;
543         }
544
545         /* Service outgoing packet queue */
546         while (vpninfo->outgoing_queue) {
547                 struct pkt *this = vpninfo->outgoing_queue;
548                 int ret;
549
550                 vpninfo->outgoing_queue = this->next;
551                 vpninfo->outgoing_qlen--;
552
553                 /* One byte of header */
554                 this->hdr[7] = AC_PKT_DATA;
555
556                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
557                 if (ret <= 0) {
558                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
559
560                         /* If it's a real error, kill the DTLS connection and
561                            requeue the packet to be sent over SSL */
562                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
563                                 vpn_progress(vpninfo, PRG_ERR,
564                                              _("DTLS got write error %d. Falling back to SSL\n"),
565                                              ret);
566                                 report_ssl_errors(vpninfo);
567                                 dtls_restart(vpninfo);
568                                 vpninfo->outgoing_queue = this;
569                                 vpninfo->outgoing_qlen++;
570                         }
571                         return 1;
572                 }
573                 time(&vpninfo->dtls_times.last_tx);
574                 vpn_progress(vpninfo, PRG_TRACE,
575                              _("Sent DTLS packet of %d bytes; SSL_write() returned %d\n"),
576                              this->len, ret);
577                 free(this);
578         }
579
580         return work_done;
581 }
582 #else /* No DTLS support in OpenSSL */
583 #warning Your version of OpenSSL does not seem to support Cisco DTLS compatibility
584  int setup_dtls(struct openconnect_info *vpninfo)
585 {
586         vpn_progress(vpninfo, PRG_ERR,
587                      _("Built against OpenSSL with no Cisco DTLS support\n"));
588         return -EINVAL;
589 }
590 #endif
591