]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/bio/bss_dgram.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / bio / bss_dgram.c
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
82 static int dgram_write(BIO *h, const char *buf, int num);
83 static int dgram_read(BIO *h, char *buf, int size);
84 static int dgram_puts(BIO *h, const char *str);
85 static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
86 static int dgram_new(BIO *h);
87 static int dgram_free(BIO *data);
88 static int dgram_clear(BIO *bio);
89
90 static int BIO_dgram_should_retry(int s);
91
92 static void get_current_time(struct timeval *t);
93
94 static 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
107 typedef 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
116 BIO_METHOD *BIO_s_datagram(void)
117 {
118     return (&methods_dgramp);
119 }
120
121 BIO *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
132 static 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
148 static 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
164 static 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
178 static 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
248 static 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
273 static 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
308 static 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
342 static 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
642 static 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
651 static 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
671 int 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
726 static 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