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