bss_dgram.c revision 21c841450af61d0a9119cdc863e93d019127bfe1
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 union { 112 struct sockaddr sa; 113 struct sockaddr_in sa_in; 114#if OPENSSL_USE_IPV6 115 struct sockaddr_in6 sa_in6; 116#endif 117 } peer; 118 unsigned int connected; 119 unsigned int _errno; 120 unsigned int mtu; 121 struct timeval next_timeout; 122 struct timeval socket_timeout; 123 } bio_dgram_data; 124 125BIO_METHOD *BIO_s_datagram(void) 126 { 127 return(&methods_dgramp); 128 } 129 130BIO *BIO_new_dgram(int fd, int close_flag) 131 { 132 BIO *ret; 133 134 ret=BIO_new(BIO_s_datagram()); 135 if (ret == NULL) return(NULL); 136 BIO_set_fd(ret,fd,close_flag); 137 return(ret); 138 } 139 140static int dgram_new(BIO *bi) 141 { 142 bio_dgram_data *data = NULL; 143 144 bi->init=0; 145 bi->num=0; 146 data = OPENSSL_malloc(sizeof(bio_dgram_data)); 147 if (data == NULL) 148 return 0; 149 memset(data, 0x00, sizeof(bio_dgram_data)); 150 bi->ptr = data; 151 152 bi->flags=0; 153 return(1); 154 } 155 156static int dgram_free(BIO *a) 157 { 158 bio_dgram_data *data; 159 160 if (a == NULL) return(0); 161 if ( ! dgram_clear(a)) 162 return 0; 163 164 data = (bio_dgram_data *)a->ptr; 165 if(data != NULL) OPENSSL_free(data); 166 167 return(1); 168 } 169 170static int dgram_clear(BIO *a) 171 { 172 if (a == NULL) return(0); 173 if (a->shutdown) 174 { 175 if (a->init) 176 { 177 SHUTDOWN2(a->num); 178 } 179 a->init=0; 180 a->flags=0; 181 } 182 return(1); 183 } 184 185static void dgram_adjust_rcv_timeout(BIO *b) 186 { 187#if defined(SO_RCVTIMEO) 188 bio_dgram_data *data = (bio_dgram_data *)b->ptr; 189 int sz = sizeof(int); 190 191 /* Is a timer active? */ 192 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) 193 { 194 struct timeval timenow, timeleft; 195 196 /* Read current socket timeout */ 197#ifdef OPENSSL_SYS_WINDOWS 198 int timeout; 199 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 200 (void*)&timeout, &sz) < 0) 201 { perror("getsockopt"); } 202 else 203 { 204 data->socket_timeout.tv_sec = timeout / 1000; 205 data->socket_timeout.tv_usec = (timeout % 1000) * 1000; 206 } 207#else 208 if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 209 &(data->socket_timeout), (void *)&sz) < 0) 210 { perror("getsockopt"); } 211#endif 212 213 /* Get current time */ 214 get_current_time(&timenow); 215 216 /* Calculate time left until timer expires */ 217 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); 218 timeleft.tv_sec -= timenow.tv_sec; 219 timeleft.tv_usec -= timenow.tv_usec; 220 if (timeleft.tv_usec < 0) 221 { 222 timeleft.tv_sec--; 223 timeleft.tv_usec += 1000000; 224 } 225 226 if (timeleft.tv_sec < 0) 227 { 228 timeleft.tv_sec = 0; 229 timeleft.tv_usec = 1; 230 } 231 232 /* Adjust socket timeout if next handhake message timer 233 * will expire earlier. 234 */ 235 if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) || 236 (data->socket_timeout.tv_sec > timeleft.tv_sec) || 237 (data->socket_timeout.tv_sec == timeleft.tv_sec && 238 data->socket_timeout.tv_usec >= timeleft.tv_usec)) 239 { 240#ifdef OPENSSL_SYS_WINDOWS 241 timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; 242 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 243 (void*)&timeout, sizeof(timeout)) < 0) 244 { perror("setsockopt"); } 245#else 246 if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft, 247 sizeof(struct timeval)) < 0) 248 { perror("setsockopt"); } 249#endif 250 } 251 } 252#endif 253 } 254 255static void dgram_reset_rcv_timeout(BIO *b) 256 { 257#if defined(SO_RCVTIMEO) 258 bio_dgram_data *data = (bio_dgram_data *)b->ptr; 259 260 /* Is a timer active? */ 261 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) 262 { 263#ifdef OPENSSL_SYS_WINDOWS 264 int timeout = data->socket_timeout.tv_sec * 1000 + 265 data->socket_timeout.tv_usec / 1000; 266 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 267 (void*)&timeout, sizeof(timeout)) < 0) 268 { perror("setsockopt"); } 269#else 270 if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), 271 sizeof(struct timeval)) < 0) 272 { perror("setsockopt"); } 273#endif 274 } 275#endif 276 } 277 278static int dgram_read(BIO *b, char *out, int outl) 279 { 280 int ret=0; 281 bio_dgram_data *data = (bio_dgram_data *)b->ptr; 282 283 struct { 284 /* 285 * See commentary in b_sock.c. <appro> 286 */ 287 union { size_t s; int i; } len; 288 union { 289 struct sockaddr sa; 290 struct sockaddr_in sa_in; 291#if OPENSSL_USE_IPV6 292 struct sockaddr_in6 sa_in6; 293#endif 294 } peer; 295 } sa; 296 297 sa.len.s=0; 298 sa.len.i=sizeof(sa.peer); 299 300 if (out != NULL) 301 { 302 clear_socket_error(); 303 memset(&sa.peer, 0x00, sizeof(sa.peer)); 304 dgram_adjust_rcv_timeout(b); 305 ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len); 306 if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) 307 { 308 OPENSSL_assert(sa.len.s<=sizeof(sa.peer)); 309 sa.len.i = (int)sa.len.s; 310 } 311 312 if ( ! data->connected && ret >= 0) 313 BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer); 314 315 BIO_clear_retry_flags(b); 316 if (ret < 0) 317 { 318 if (BIO_dgram_should_retry(ret)) 319 { 320 BIO_set_retry_read(b); 321 data->_errno = get_last_socket_error(); 322 } 323 } 324 325 dgram_reset_rcv_timeout(b); 326 } 327 return(ret); 328 } 329 330static int dgram_write(BIO *b, const char *in, int inl) 331 { 332 int ret; 333 bio_dgram_data *data = (bio_dgram_data *)b->ptr; 334 clear_socket_error(); 335 336 if ( data->connected ) 337 ret=writesocket(b->num,in,inl); 338 else 339 { 340 int peerlen = sizeof(data->peer); 341 342 if (data->peer.sa.sa_family == AF_INET) 343 peerlen = sizeof(data->peer.sa_in); 344#if OPENSSL_USE_IPV6 345 else if (data->peer.sa.sa_family == AF_INET6) 346 peerlen = sizeof(data->peer.sa_in6); 347#endif 348#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) 349 ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen); 350#else 351 ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen); 352#endif 353 } 354 355 BIO_clear_retry_flags(b); 356 if (ret <= 0) 357 { 358 if (BIO_dgram_should_retry(ret)) 359 { 360 BIO_set_retry_write(b); 361 data->_errno = get_last_socket_error(); 362 363#if 0 /* higher layers are responsible for querying MTU, if necessary */ 364 if ( data->_errno == EMSGSIZE) 365 /* retrieve the new MTU */ 366 BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); 367#endif 368 } 369 } 370 return(ret); 371 } 372 373static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) 374 { 375 long ret=1; 376 int *ip; 377 struct sockaddr *to = NULL; 378 bio_dgram_data *data = NULL; 379#if defined(IP_MTU_DISCOVER) || defined(IP_MTU) 380 long sockopt_val = 0; 381 unsigned int sockopt_len = 0; 382#endif 383#ifdef OPENSSL_SYS_LINUX 384 socklen_t addr_len; 385 union { 386 struct sockaddr sa; 387 struct sockaddr_in s4; 388#if OPENSSL_USE_IPV6 389 struct sockaddr_in6 s6; 390#endif 391 } addr; 392#endif 393 394 data = (bio_dgram_data *)b->ptr; 395 396 switch (cmd) 397 { 398 case BIO_CTRL_RESET: 399 num=0; 400 case BIO_C_FILE_SEEK: 401 ret=0; 402 break; 403 case BIO_C_FILE_TELL: 404 case BIO_CTRL_INFO: 405 ret=0; 406 break; 407 case BIO_C_SET_FD: 408 dgram_clear(b); 409 b->num= *((int *)ptr); 410 b->shutdown=(int)num; 411 b->init=1; 412 break; 413 case BIO_C_GET_FD: 414 if (b->init) 415 { 416 ip=(int *)ptr; 417 if (ip != NULL) *ip=b->num; 418 ret=b->num; 419 } 420 else 421 ret= -1; 422 break; 423 case BIO_CTRL_GET_CLOSE: 424 ret=b->shutdown; 425 break; 426 case BIO_CTRL_SET_CLOSE: 427 b->shutdown=(int)num; 428 break; 429 case BIO_CTRL_PENDING: 430 case BIO_CTRL_WPENDING: 431 ret=0; 432 break; 433 case BIO_CTRL_DUP: 434 case BIO_CTRL_FLUSH: 435 ret=1; 436 break; 437 case BIO_CTRL_DGRAM_CONNECT: 438 to = (struct sockaddr *)ptr; 439#if 0 440 if (connect(b->num, to, sizeof(struct sockaddr)) < 0) 441 { perror("connect"); ret = 0; } 442 else 443 { 444#endif 445 switch (to->sa_family) 446 { 447 case AF_INET: 448 memcpy(&data->peer,to,sizeof(data->peer.sa_in)); 449 break; 450#if OPENSSL_USE_IPV6 451 case AF_INET6: 452 memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); 453 break; 454#endif 455 default: 456 memcpy(&data->peer,to,sizeof(data->peer.sa)); 457 break; 458 } 459#if 0 460 } 461#endif 462 break; 463 /* (Linux)kernel sets DF bit on outgoing IP packets */ 464 case BIO_CTRL_DGRAM_MTU_DISCOVER: 465#ifdef OPENSSL_SYS_LINUX 466 addr_len = (socklen_t)sizeof(addr); 467 memset((void *)&addr, 0, sizeof(addr)); 468 if (getsockname(b->num, &addr.sa, &addr_len) < 0) 469 { 470 ret = 0; 471 break; 472 } 473 sockopt_len = sizeof(sockopt_val); 474 switch (addr.sa.sa_family) 475 { 476 case AF_INET: 477 sockopt_val = IP_PMTUDISC_DO; 478 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, 479 &sockopt_val, sizeof(sockopt_val))) < 0) 480 perror("setsockopt"); 481 break; 482#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) 483 case AF_INET6: 484 sockopt_val = IPV6_PMTUDISC_DO; 485 if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, 486 &sockopt_val, sizeof(sockopt_val))) < 0) 487 perror("setsockopt"); 488 break; 489#endif 490 default: 491 ret = -1; 492 break; 493 } 494 ret = -1; 495#else 496 break; 497#endif 498 case BIO_CTRL_DGRAM_QUERY_MTU: 499#ifdef OPENSSL_SYS_LINUX 500 addr_len = (socklen_t)sizeof(addr); 501 memset((void *)&addr, 0, sizeof(addr)); 502 if (getsockname(b->num, &addr.sa, &addr_len) < 0) 503 { 504 ret = 0; 505 break; 506 } 507 sockopt_len = sizeof(sockopt_val); 508 switch (addr.sa.sa_family) 509 { 510 case AF_INET: 511 if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, 512 &sockopt_len)) < 0 || sockopt_val < 0) 513 { 514 ret = 0; 515 } 516 else 517 { 518 /* we assume that the transport protocol is UDP and no 519 * IP options are used. 520 */ 521 data->mtu = sockopt_val - 8 - 20; 522 ret = data->mtu; 523 } 524 break; 525#if OPENSSL_USE_IPV6 && defined(IPV6_MTU) 526 case AF_INET6: 527 if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val, 528 &sockopt_len)) < 0 || sockopt_val < 0) 529 { 530 ret = 0; 531 } 532 else 533 { 534 /* we assume that the transport protocol is UDP and no 535 * IPV6 options are used. 536 */ 537 data->mtu = sockopt_val - 8 - 40; 538 ret = data->mtu; 539 } 540 break; 541#endif 542 default: 543 ret = 0; 544 break; 545 } 546#else 547 ret = 0; 548#endif 549 break; 550 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: 551 switch (data->peer.sa.sa_family) 552 { 553 case AF_INET: 554 ret = 576 - 20 - 8; 555 break; 556#if OPENSSL_USE_IPV6 557 case AF_INET6: 558#ifdef IN6_IS_ADDR_V4MAPPED 559 if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr)) 560 ret = 576 - 20 - 8; 561 else 562#endif 563 ret = 1280 - 40 - 8; 564 break; 565#endif 566 default: 567 ret = 576 - 20 - 8; 568 break; 569 } 570 break; 571 case BIO_CTRL_DGRAM_GET_MTU: 572 return data->mtu; 573 break; 574 case BIO_CTRL_DGRAM_SET_MTU: 575 data->mtu = num; 576 ret = num; 577 break; 578 case BIO_CTRL_DGRAM_SET_CONNECTED: 579 to = (struct sockaddr *)ptr; 580 581 if ( to != NULL) 582 { 583 data->connected = 1; 584 switch (to->sa_family) 585 { 586 case AF_INET: 587 memcpy(&data->peer,to,sizeof(data->peer.sa_in)); 588 break; 589#if OPENSSL_USE_IPV6 590 case AF_INET6: 591 memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); 592 break; 593#endif 594 default: 595 memcpy(&data->peer,to,sizeof(data->peer.sa)); 596 break; 597 } 598 } 599 else 600 { 601 data->connected = 0; 602 memset(&(data->peer), 0x00, sizeof(data->peer)); 603 } 604 break; 605 case BIO_CTRL_DGRAM_GET_PEER: 606 switch (data->peer.sa.sa_family) 607 { 608 case AF_INET: 609 ret=sizeof(data->peer.sa_in); 610 break; 611#if OPENSSL_USE_IPV6 612 case AF_INET6: 613 ret=sizeof(data->peer.sa_in6); 614 break; 615#endif 616 default: 617 ret=sizeof(data->peer.sa); 618 break; 619 } 620 if (num==0 || num>ret) 621 num=ret; 622 memcpy(ptr,&data->peer,(ret=num)); 623 break; 624 case BIO_CTRL_DGRAM_SET_PEER: 625 to = (struct sockaddr *) ptr; 626 switch (to->sa_family) 627 { 628 case AF_INET: 629 memcpy(&data->peer,to,sizeof(data->peer.sa_in)); 630 break; 631#if OPENSSL_USE_IPV6 632 case AF_INET6: 633 memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); 634 break; 635#endif 636 default: 637 memcpy(&data->peer,to,sizeof(data->peer.sa)); 638 break; 639 } 640 break; 641 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: 642 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); 643 break; 644#if defined(SO_RCVTIMEO) 645 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: 646#ifdef OPENSSL_SYS_WINDOWS 647 { 648 struct timeval *tv = (struct timeval *)ptr; 649 int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; 650 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 651 (void*)&timeout, sizeof(timeout)) < 0) 652 { perror("setsockopt"); ret = -1; } 653 } 654#else 655 if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, 656 sizeof(struct timeval)) < 0) 657 { perror("setsockopt"); ret = -1; } 658#endif 659 break; 660 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: 661#ifdef OPENSSL_SYS_WINDOWS 662 { 663 int timeout, sz = sizeof(timeout); 664 struct timeval *tv = (struct timeval *)ptr; 665 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 666 (void*)&timeout, &sz) < 0) 667 { perror("getsockopt"); ret = -1; } 668 else 669 { 670 tv->tv_sec = timeout / 1000; 671 tv->tv_usec = (timeout % 1000) * 1000; 672 ret = sizeof(*tv); 673 } 674 } 675#else 676 if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 677 ptr, (void *)&ret) < 0) 678 { perror("getsockopt"); ret = -1; } 679#endif 680 break; 681#endif 682#if defined(SO_SNDTIMEO) 683 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: 684#ifdef OPENSSL_SYS_WINDOWS 685 { 686 struct timeval *tv = (struct timeval *)ptr; 687 int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; 688 if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 689 (void*)&timeout, sizeof(timeout)) < 0) 690 { perror("setsockopt"); ret = -1; } 691 } 692#else 693 if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, 694 sizeof(struct timeval)) < 0) 695 { perror("setsockopt"); ret = -1; } 696#endif 697 break; 698 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: 699#ifdef OPENSSL_SYS_WINDOWS 700 { 701 int timeout, sz = sizeof(timeout); 702 struct timeval *tv = (struct timeval *)ptr; 703 if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 704 (void*)&timeout, &sz) < 0) 705 { perror("getsockopt"); ret = -1; } 706 else 707 { 708 tv->tv_sec = timeout / 1000; 709 tv->tv_usec = (timeout % 1000) * 1000; 710 ret = sizeof(*tv); 711 } 712 } 713#else 714 if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 715 ptr, (void *)&ret) < 0) 716 { perror("getsockopt"); ret = -1; } 717#endif 718 break; 719#endif 720 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: 721 /* fall-through */ 722 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: 723#ifdef OPENSSL_SYS_WINDOWS 724 if ( data->_errno == WSAETIMEDOUT) 725#else 726 if ( data->_errno == EAGAIN) 727#endif 728 { 729 ret = 1; 730 data->_errno = 0; 731 } 732 else 733 ret = 0; 734 break; 735#ifdef EMSGSIZE 736 case BIO_CTRL_DGRAM_MTU_EXCEEDED: 737 if ( data->_errno == EMSGSIZE) 738 { 739 ret = 1; 740 data->_errno = 0; 741 } 742 else 743 ret = 0; 744 break; 745#endif 746 default: 747 ret=0; 748 break; 749 } 750 return(ret); 751 } 752 753static int dgram_puts(BIO *bp, const char *str) 754 { 755 int n,ret; 756 757 n=strlen(str); 758 ret=dgram_write(bp,str,n); 759 return(ret); 760 } 761 762static int BIO_dgram_should_retry(int i) 763 { 764 int err; 765 766 if ((i == 0) || (i == -1)) 767 { 768 err=get_last_socket_error(); 769 770#if defined(OPENSSL_SYS_WINDOWS) 771 /* If the socket return value (i) is -1 772 * and err is unexpectedly 0 at this point, 773 * the error code was overwritten by 774 * another system call before this error 775 * handling is called. 776 */ 777#endif 778 779 return(BIO_dgram_non_fatal_error(err)); 780 } 781 return(0); 782 } 783 784int BIO_dgram_non_fatal_error(int err) 785 { 786 switch (err) 787 { 788#if defined(OPENSSL_SYS_WINDOWS) 789# if defined(WSAEWOULDBLOCK) 790 case WSAEWOULDBLOCK: 791# endif 792 793# if 0 /* This appears to always be an error */ 794# if defined(WSAENOTCONN) 795 case WSAENOTCONN: 796# endif 797# endif 798#endif 799 800#ifdef EWOULDBLOCK 801# ifdef WSAEWOULDBLOCK 802# if WSAEWOULDBLOCK != EWOULDBLOCK 803 case EWOULDBLOCK: 804# endif 805# else 806 case EWOULDBLOCK: 807# endif 808#endif 809 810#ifdef EINTR 811 case EINTR: 812#endif 813 814#ifdef EAGAIN 815#if EWOULDBLOCK != EAGAIN 816 case EAGAIN: 817# endif 818#endif 819 820#ifdef EPROTO 821 case EPROTO: 822#endif 823 824#ifdef EINPROGRESS 825 case EINPROGRESS: 826#endif 827 828#ifdef EALREADY 829 case EALREADY: 830#endif 831 832 return(1); 833 /* break; */ 834 default: 835 break; 836 } 837 return(0); 838 } 839 840static void get_current_time(struct timeval *t) 841 { 842#ifdef OPENSSL_SYS_WIN32 843 struct _timeb tb; 844 _ftime(&tb); 845 t->tv_sec = (long)tb.time; 846 t->tv_usec = (long)tb.millitm * 1000; 847#elif defined(OPENSSL_SYS_VMS) 848 struct timeb tb; 849 ftime(&tb); 850 t->tv_sec = (long)tb.time; 851 t->tv_usec = (long)tb.millitm * 1000; 852#else 853 gettimeofday(t, NULL); 854#endif 855 } 856 857#endif 858