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
BIO_s_datagram(void)116 BIO_METHOD *BIO_s_datagram(void)
117 {
118 return (&methods_dgramp);
119 }
120
BIO_new_dgram(int fd,int close_flag)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
dgram_new(BIO * bi)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
dgram_free(BIO * a)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
dgram_clear(BIO * a)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
dgram_adjust_rcv_timeout(BIO * b)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
dgram_reset_rcv_timeout(BIO * b)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
dgram_read(BIO * b,char * out,int outl)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
dgram_write(BIO * b,const char * in,int inl)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
dgram_ctrl(BIO * b,int cmd,long num,void * ptr)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
dgram_puts(BIO * bp,const char * str)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
BIO_dgram_should_retry(int i)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
BIO_dgram_non_fatal_error(int err)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
get_current_time(struct timeval * t)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
744