bss_dgram.c revision 296465
1/* crypto/bio/bio_dgram.c */
2/*
3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5 */
6/* ====================================================================
7 * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    openssl-core@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com).  This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59
60#include <stdio.h>
61#include <errno.h>
62#define USE_SOCKETS
63#include "cryptlib.h"
64
65#include <openssl/bio.h>
66#ifndef OPENSSL_NO_DGRAM
67
68# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
69#  include <sys/timeb.h>
70# endif
71
72# ifdef OPENSSL_SYS_LINUX
73#  define IP_MTU      14        /* linux is lame */
74# endif
75
76# ifdef WATT32
77#  define sock_write SockWrite  /* Watt-32 uses same names */
78#  define sock_read  SockRead
79#  define sock_puts  SockPuts
80# endif
81
82static int dgram_write(BIO *h, const char *buf, int num);
83static int dgram_read(BIO *h, char *buf, int size);
84static int dgram_puts(BIO *h, const char *str);
85static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
86static int dgram_new(BIO *h);
87static int dgram_free(BIO *data);
88static int dgram_clear(BIO *bio);
89
90static int BIO_dgram_should_retry(int s);
91
92static void get_current_time(struct timeval *t);
93
94static BIO_METHOD methods_dgramp = {
95    BIO_TYPE_DGRAM,
96    "datagram socket",
97    dgram_write,
98    dgram_read,
99    dgram_puts,
100    NULL,                       /* dgram_gets, */
101    dgram_ctrl,
102    dgram_new,
103    dgram_free,
104    NULL,
105};
106
107typedef struct bio_dgram_data_st {
108    struct sockaddr peer;
109    unsigned int connected;
110    unsigned int _errno;
111    unsigned int mtu;
112    struct timeval next_timeout;
113    struct timeval socket_timeout;
114} bio_dgram_data;
115
116BIO_METHOD *BIO_s_datagram(void)
117{
118    return (&methods_dgramp);
119}
120
121BIO *BIO_new_dgram(int fd, int close_flag)
122{
123    BIO *ret;
124
125    ret = BIO_new(BIO_s_datagram());
126    if (ret == NULL)
127        return (NULL);
128    BIO_set_fd(ret, fd, close_flag);
129    return (ret);
130}
131
132static int dgram_new(BIO *bi)
133{
134    bio_dgram_data *data = NULL;
135
136    bi->init = 0;
137    bi->num = 0;
138    data = OPENSSL_malloc(sizeof(bio_dgram_data));
139    if (data == NULL)
140        return 0;
141    memset(data, 0x00, sizeof(bio_dgram_data));
142    bi->ptr = data;
143
144    bi->flags = 0;
145    return (1);
146}
147
148static int dgram_free(BIO *a)
149{
150    bio_dgram_data *data;
151
152    if (a == NULL)
153        return (0);
154    if (!dgram_clear(a))
155        return 0;
156
157    data = (bio_dgram_data *)a->ptr;
158    if (data != NULL)
159        OPENSSL_free(data);
160
161    return (1);
162}
163
164static int dgram_clear(BIO *a)
165{
166    if (a == NULL)
167        return (0);
168    if (a->shutdown) {
169        if (a->init) {
170            SHUTDOWN2(a->num);
171        }
172        a->init = 0;
173        a->flags = 0;
174    }
175    return (1);
176}
177
178static void dgram_adjust_rcv_timeout(BIO *b)
179{
180# if defined(SO_RCVTIMEO)
181    bio_dgram_data *data = (bio_dgram_data *)b->ptr;
182    int sz = sizeof(int);
183
184    /* Is a timer active? */
185    if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
186        struct timeval timenow, timeleft;
187
188        /* Read current socket timeout */
189#  ifdef OPENSSL_SYS_WINDOWS
190        int timeout;
191        if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
192                       (void *)&timeout, &sz) < 0) {
193            perror("getsockopt");
194        } else {
195            data->socket_timeout.tv_sec = timeout / 1000;
196            data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
197        }
198#  else
199        if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
200                       &(data->socket_timeout), (void *)&sz) < 0) {
201            perror("getsockopt");
202        }
203#  endif
204
205        /* Get current time */
206        get_current_time(&timenow);
207
208        /* Calculate time left until timer expires */
209        memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
210        timeleft.tv_sec -= timenow.tv_sec;
211        timeleft.tv_usec -= timenow.tv_usec;
212        if (timeleft.tv_usec < 0) {
213            timeleft.tv_sec--;
214            timeleft.tv_usec += 1000000;
215        }
216
217        if (timeleft.tv_sec < 0) {
218            timeleft.tv_sec = 0;
219            timeleft.tv_usec = 1;
220        }
221
222        /*
223         * Adjust socket timeout if next handhake message timer will expire
224         * earlier.
225         */
226        if ((data->socket_timeout.tv_sec == 0
227             && data->socket_timeout.tv_usec == 0)
228            || (data->socket_timeout.tv_sec > timeleft.tv_sec)
229            || (data->socket_timeout.tv_sec == timeleft.tv_sec
230                && data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
231#  ifdef OPENSSL_SYS_WINDOWS
232            timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
233            if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
234                           (void *)&timeout, sizeof(timeout)) < 0) {
235                perror("setsockopt");
236            }
237#  else
238            if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
239                           sizeof(struct timeval)) < 0) {
240                perror("setsockopt");
241            }
242#  endif
243        }
244    }
245# endif
246}
247
248static void dgram_reset_rcv_timeout(BIO *b)
249{
250# if defined(SO_RCVTIMEO)
251    bio_dgram_data *data = (bio_dgram_data *)b->ptr;
252
253    /* Is a timer active? */
254    if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
255#  ifdef OPENSSL_SYS_WINDOWS
256        int timeout = data->socket_timeout.tv_sec * 1000 +
257            data->socket_timeout.tv_usec / 1000;
258        if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
259                       (void *)&timeout, sizeof(timeout)) < 0) {
260            perror("setsockopt");
261        }
262#  else
263        if (setsockopt
264            (b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
265             sizeof(struct timeval)) < 0) {
266            perror("setsockopt");
267        }
268#  endif
269    }
270# endif
271}
272
273static int dgram_read(BIO *b, char *out, int outl)
274{
275    int ret = 0;
276    bio_dgram_data *data = (bio_dgram_data *)b->ptr;
277
278    struct sockaddr peer;
279    int peerlen = sizeof(peer);
280
281    if (out != NULL) {
282        clear_socket_error();
283        memset(&peer, 0x00, peerlen);
284        /*
285         * Last arg in recvfrom is signed on some platforms and unsigned on
286         * others. It is of type socklen_t on some but this is not universal.
287         * Cast to (void *) to avoid compiler warnings.
288         */
289        dgram_adjust_rcv_timeout(b);
290        ret = recvfrom(b->num, out, outl, 0, &peer, (void *)&peerlen);
291
292        if (!data->connected && ret >= 0)
293            BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer);
294
295        BIO_clear_retry_flags(b);
296        if (ret < 0) {
297            if (BIO_dgram_should_retry(ret)) {
298                BIO_set_retry_read(b);
299                data->_errno = get_last_socket_error();
300            }
301        }
302
303        dgram_reset_rcv_timeout(b);
304    }
305    return (ret);
306}
307
308static int dgram_write(BIO *b, const char *in, int inl)
309{
310    int ret;
311    bio_dgram_data *data = (bio_dgram_data *)b->ptr;
312    clear_socket_error();
313
314    if (data->connected)
315        ret = writesocket(b->num, in, inl);
316    else
317# if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
318        ret =
319            sendto(b->num, (char *)in, inl, 0, &data->peer,
320                   sizeof(data->peer));
321# else
322        ret = sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer));
323# endif
324
325    BIO_clear_retry_flags(b);
326    if (ret <= 0) {
327        if (BIO_dgram_should_retry(ret)) {
328            BIO_set_retry_write(b);
329            data->_errno = get_last_socket_error();
330
331# if 0                          /* higher layers are responsible for querying
332                                 * MTU, if necessary */
333            if (data->_errno == EMSGSIZE)
334                /* retrieve the new MTU */
335                BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
336# endif
337        }
338    }
339    return (ret);
340}
341
342static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
343{
344    long ret = 1;
345    int *ip;
346    struct sockaddr *to = NULL;
347    bio_dgram_data *data = NULL;
348# if defined(IP_MTU_DISCOVER) || defined(IP_MTU)
349    long sockopt_val = 0;
350    unsigned int sockopt_len = 0;
351# endif
352# ifdef OPENSSL_SYS_LINUX
353    socklen_t addr_len;
354    struct sockaddr_storage addr;
355# endif
356
357    data = (bio_dgram_data *)b->ptr;
358
359    switch (cmd) {
360    case BIO_CTRL_RESET:
361        num = 0;
362    case BIO_C_FILE_SEEK:
363        ret = 0;
364        break;
365    case BIO_C_FILE_TELL:
366    case BIO_CTRL_INFO:
367        ret = 0;
368        break;
369    case BIO_C_SET_FD:
370        dgram_clear(b);
371        b->num = *((int *)ptr);
372        b->shutdown = (int)num;
373        b->init = 1;
374        break;
375    case BIO_C_GET_FD:
376        if (b->init) {
377            ip = (int *)ptr;
378            if (ip != NULL)
379                *ip = b->num;
380            ret = b->num;
381        } else
382            ret = -1;
383        break;
384    case BIO_CTRL_GET_CLOSE:
385        ret = b->shutdown;
386        break;
387    case BIO_CTRL_SET_CLOSE:
388        b->shutdown = (int)num;
389        break;
390    case BIO_CTRL_PENDING:
391    case BIO_CTRL_WPENDING:
392        ret = 0;
393        break;
394    case BIO_CTRL_DUP:
395    case BIO_CTRL_FLUSH:
396        ret = 1;
397        break;
398    case BIO_CTRL_DGRAM_CONNECT:
399        to = (struct sockaddr *)ptr;
400# if 0
401        if (connect(b->num, to, sizeof(struct sockaddr)) < 0) {
402            perror("connect");
403            ret = 0;
404        } else {
405# endif
406            memcpy(&(data->peer), to, sizeof(struct sockaddr));
407# if 0
408        }
409# endif
410        break;
411        /* (Linux)kernel sets DF bit on outgoing IP packets */
412    case BIO_CTRL_DGRAM_MTU_DISCOVER:
413# ifdef OPENSSL_SYS_LINUX
414        addr_len = (socklen_t) sizeof(struct sockaddr_storage);
415        memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
416        if (getsockname(b->num, (void *)&addr, &addr_len) < 0) {
417            ret = 0;
418            break;
419        }
420        sockopt_len = sizeof(sockopt_val);
421        switch (addr.ss_family) {
422        case AF_INET:
423            sockopt_val = IP_PMTUDISC_DO;
424            if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
425                                  &sockopt_val, sizeof(sockopt_val))) < 0)
426                perror("setsockopt");
427            break;
428        case AF_INET6:
429            sockopt_val = IPV6_PMTUDISC_DO;
430            if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
431                                  &sockopt_val, sizeof(sockopt_val))) < 0)
432                perror("setsockopt");
433            break;
434        default:
435            ret = -1;
436            break;
437        }
438        ret = -1;
439# else
440        break;
441# endif
442    case BIO_CTRL_DGRAM_QUERY_MTU:
443# ifdef OPENSSL_SYS_LINUX
444        addr_len = (socklen_t) sizeof(struct sockaddr_storage);
445        memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
446        if (getsockname(b->num, (void *)&addr, &addr_len) < 0) {
447            ret = 0;
448            break;
449        }
450        sockopt_len = sizeof(sockopt_val);
451        switch (addr.ss_family) {
452        case AF_INET:
453            if ((ret =
454                 getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
455                            &sockopt_len)) < 0 || sockopt_val < 0) {
456                ret = 0;
457            } else {
458                /*
459                 * we assume that the transport protocol is UDP and no IP
460                 * options are used.
461                 */
462                data->mtu = sockopt_val - 8 - 20;
463                ret = data->mtu;
464            }
465            break;
466        case AF_INET6:
467            if ((ret =
468                 getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU,
469                            (void *)&sockopt_val, &sockopt_len)) < 0
470                || sockopt_val < 0) {
471                ret = 0;
472            } else {
473                /*
474                 * we assume that the transport protocol is UDP and no IPV6
475                 * options are used.
476                 */
477                data->mtu = sockopt_val - 8 - 40;
478                ret = data->mtu;
479            }
480            break;
481        default:
482            ret = 0;
483            break;
484        }
485# else
486        ret = 0;
487# endif
488        break;
489    case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
490        ret = 576 - 20 - 8;
491        break;
492    case BIO_CTRL_DGRAM_GET_MTU:
493        return data->mtu;
494        break;
495    case BIO_CTRL_DGRAM_SET_MTU:
496        data->mtu = num;
497        ret = num;
498        break;
499    case BIO_CTRL_DGRAM_SET_CONNECTED:
500        to = (struct sockaddr *)ptr;
501
502        if (to != NULL) {
503            data->connected = 1;
504            memcpy(&(data->peer), to, sizeof(struct sockaddr));
505        } else {
506            data->connected = 0;
507            memset(&(data->peer), 0x00, sizeof(struct sockaddr));
508        }
509        break;
510    case BIO_CTRL_DGRAM_GET_PEER:
511        to = (struct sockaddr *)ptr;
512
513        memcpy(to, &(data->peer), sizeof(struct sockaddr));
514        ret = sizeof(struct sockaddr);
515        break;
516    case BIO_CTRL_DGRAM_SET_PEER:
517        to = (struct sockaddr *)ptr;
518
519        memcpy(&(data->peer), to, sizeof(struct sockaddr));
520        break;
521    case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
522        memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
523        break;
524# if defined(SO_RCVTIMEO)
525    case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
526#  ifdef OPENSSL_SYS_WINDOWS
527        {
528            struct timeval *tv = (struct timeval *)ptr;
529            int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
530            if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
531                           (void *)&timeout, sizeof(timeout)) < 0) {
532                perror("setsockopt");
533                ret = -1;
534            }
535        }
536#  else
537        if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
538                       sizeof(struct timeval)) < 0) {
539            perror("setsockopt");
540            ret = -1;
541        }
542#  endif
543        break;
544    case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
545#  ifdef OPENSSL_SYS_WINDOWS
546        {
547            int timeout, sz = sizeof(timeout);
548            struct timeval *tv = (struct timeval *)ptr;
549            if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
550                           (void *)&timeout, &sz) < 0) {
551                perror("getsockopt");
552                ret = -1;
553            } else {
554                tv->tv_sec = timeout / 1000;
555                tv->tv_usec = (timeout % 1000) * 1000;
556                ret = sizeof(*tv);
557            }
558        }
559#  else
560        if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
561                       ptr, (void *)&ret) < 0) {
562            perror("getsockopt");
563            ret = -1;
564        }
565#  endif
566        break;
567# endif
568# if defined(SO_SNDTIMEO)
569    case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
570#  ifdef OPENSSL_SYS_WINDOWS
571        {
572            struct timeval *tv = (struct timeval *)ptr;
573            int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
574            if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
575                           (void *)&timeout, sizeof(timeout)) < 0) {
576                perror("setsockopt");
577                ret = -1;
578            }
579        }
580#  else
581        if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
582                       sizeof(struct timeval)) < 0) {
583            perror("setsockopt");
584            ret = -1;
585        }
586#  endif
587        break;
588    case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
589#  ifdef OPENSSL_SYS_WINDOWS
590        {
591            int timeout, sz = sizeof(timeout);
592            struct timeval *tv = (struct timeval *)ptr;
593            if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
594                           (void *)&timeout, &sz) < 0) {
595                perror("getsockopt");
596                ret = -1;
597            } else {
598                tv->tv_sec = timeout / 1000;
599                tv->tv_usec = (timeout % 1000) * 1000;
600                ret = sizeof(*tv);
601            }
602        }
603#  else
604        if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
605                       ptr, (void *)&ret) < 0) {
606            perror("getsockopt");
607            ret = -1;
608        }
609#  endif
610        break;
611# endif
612    case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
613        /* fall-through */
614    case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
615# ifdef OPENSSL_SYS_WINDOWS
616        if (data->_errno == WSAETIMEDOUT)
617# else
618        if (data->_errno == EAGAIN)
619# endif
620        {
621            ret = 1;
622            data->_errno = 0;
623        } else
624            ret = 0;
625        break;
626# ifdef EMSGSIZE
627    case BIO_CTRL_DGRAM_MTU_EXCEEDED:
628        if (data->_errno == EMSGSIZE) {
629            ret = 1;
630            data->_errno = 0;
631        } else
632            ret = 0;
633        break;
634# endif
635    default:
636        ret = 0;
637        break;
638    }
639    return (ret);
640}
641
642static int dgram_puts(BIO *bp, const char *str)
643{
644    int n, ret;
645
646    n = strlen(str);
647    ret = dgram_write(bp, str, n);
648    return (ret);
649}
650
651static int BIO_dgram_should_retry(int i)
652{
653    int err;
654
655    if ((i == 0) || (i == -1)) {
656        err = get_last_socket_error();
657
658# if defined(OPENSSL_SYS_WINDOWS)
659        /*
660         * If the socket return value (i) is -1 and err is unexpectedly 0 at
661         * this point, the error code was overwritten by another system call
662         * before this error handling is called.
663         */
664# endif
665
666        return (BIO_dgram_non_fatal_error(err));
667    }
668    return (0);
669}
670
671int BIO_dgram_non_fatal_error(int err)
672{
673    switch (err) {
674# if defined(OPENSSL_SYS_WINDOWS)
675#  if defined(WSAEWOULDBLOCK)
676    case WSAEWOULDBLOCK:
677#  endif
678
679#  if 0                         /* This appears to always be an error */
680#   if defined(WSAENOTCONN)
681    case WSAENOTCONN:
682#   endif
683#  endif
684# endif
685
686# ifdef EWOULDBLOCK
687#  ifdef WSAEWOULDBLOCK
688#   if WSAEWOULDBLOCK != EWOULDBLOCK
689    case EWOULDBLOCK:
690#   endif
691#  else
692    case EWOULDBLOCK:
693#  endif
694# endif
695
696# ifdef EINTR
697    case EINTR:
698# endif
699
700# ifdef EAGAIN
701#  if EWOULDBLOCK != EAGAIN
702    case EAGAIN:
703#  endif
704# endif
705
706# ifdef EPROTO
707    case EPROTO:
708# endif
709
710# ifdef EINPROGRESS
711    case EINPROGRESS:
712# endif
713
714# ifdef EALREADY
715    case EALREADY:
716# endif
717
718        return (1);
719        /* break; */
720    default:
721        break;
722    }
723    return (0);
724}
725
726static void get_current_time(struct timeval *t)
727{
728# ifdef OPENSSL_SYS_WIN32
729    struct _timeb tb;
730    _ftime(&tb);
731    t->tv_sec = (long)tb.time;
732    t->tv_usec = (long)tb.millitm * 1000;
733# elif defined(OPENSSL_SYS_VMS)
734    struct timeb tb;
735    ftime(&tb);
736    t->tv_sec = (long)tb.time;
737    t->tv_usec = (long)tb.millitm * 1000;
738# else
739    gettimeofday(t, NULL);
740# endif
741}
742
743#endif
744