b_sock.c revision 296465
1/* crypto/bio/b_sock.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60#include <stdlib.h> 61#include <errno.h> 62#define USE_SOCKETS 63#include "cryptlib.h" 64#include <openssl/bio.h> 65#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) 66# include <netdb.h> 67# if defined(NETWARE_CLIB) 68# include <sys/ioctl.h> 69NETDB_DEFINE_CONTEXT 70# endif 71#endif 72#ifndef OPENSSL_NO_SOCK 73# ifdef OPENSSL_SYS_WIN16 74# define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 75# else 76# define SOCKET_PROTOCOL IPPROTO_TCP 77# endif 78# ifdef SO_MAXCONN 79# define MAX_LISTEN SO_MAXCONN 80# elif defined(SOMAXCONN) 81# define MAX_LISTEN SOMAXCONN 82# else 83# define MAX_LISTEN 32 84# endif 85# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 86static int wsa_init_done = 0; 87# endif 88 89# if 0 90static unsigned long BIO_ghbn_hits = 0L; 91static unsigned long BIO_ghbn_miss = 0L; 92 93# define GHBN_NUM 4 94static struct ghbn_cache_st { 95 char name[129]; 96 struct hostent *ent; 97 unsigned long order; 98} ghbn_cache[GHBN_NUM]; 99# endif 100 101static int get_ip(const char *str, unsigned char *ip); 102# if 0 103static void ghbn_free(struct hostent *a); 104static struct hostent *ghbn_dup(struct hostent *a); 105# endif 106int BIO_get_host_ip(const char *str, unsigned char *ip) 107{ 108 int i; 109 int err = 1; 110 int locked = 0; 111 struct hostent *he; 112 113 i = get_ip(str, ip); 114 if (i < 0) { 115 BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_INVALID_IP_ADDRESS); 116 goto err; 117 } 118 119 /* 120 * At this point, we have something that is most probably correct in some 121 * way, so let's init the socket. 122 */ 123 if (BIO_sock_init() != 1) 124 return 0; /* don't generate another error code here */ 125 126 /* 127 * If the string actually contained an IP address, we need not do 128 * anything more 129 */ 130 if (i > 0) 131 return (1); 132 133 /* do a gethostbyname */ 134 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 135 locked = 1; 136 he = BIO_gethostbyname(str); 137 if (he == NULL) { 138 BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP); 139 goto err; 140 } 141 142 /* cast to short because of win16 winsock definition */ 143 if ((short)he->h_addrtype != AF_INET) { 144 BIOerr(BIO_F_BIO_GET_HOST_IP, 145 BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 146 goto err; 147 } 148 for (i = 0; i < 4; i++) 149 ip[i] = he->h_addr_list[0][i]; 150 err = 0; 151 152 err: 153 if (locked) 154 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 155 if (err) { 156 ERR_add_error_data(2, "host=", str); 157 return 0; 158 } else 159 return 1; 160} 161 162int BIO_get_port(const char *str, unsigned short *port_ptr) 163{ 164 int i; 165 struct servent *s; 166 167 if (str == NULL) { 168 BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); 169 return (0); 170 } 171 i = atoi(str); 172 if (i != 0) 173 *port_ptr = (unsigned short)i; 174 else { 175 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); 176 /* 177 * Note: under VMS with SOCKETSHR, it seems like the first parameter 178 * is 'char *', instead of 'const char *' 179 */ 180# ifndef CONST_STRICT 181 s = getservbyname((char *)str, "tcp"); 182# else 183 s = getservbyname(str, "tcp"); 184# endif 185 if (s != NULL) 186 *port_ptr = ntohs((unsigned short)s->s_port); 187 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); 188 if (s == NULL) { 189 if (strcmp(str, "http") == 0) 190 *port_ptr = 80; 191 else if (strcmp(str, "telnet") == 0) 192 *port_ptr = 23; 193 else if (strcmp(str, "socks") == 0) 194 *port_ptr = 1080; 195 else if (strcmp(str, "https") == 0) 196 *port_ptr = 443; 197 else if (strcmp(str, "ssl") == 0) 198 *port_ptr = 443; 199 else if (strcmp(str, "ftp") == 0) 200 *port_ptr = 21; 201 else if (strcmp(str, "gopher") == 0) 202 *port_ptr = 70; 203# if 0 204 else if (strcmp(str, "wais") == 0) 205 *port_ptr = 21; 206# endif 207 else { 208 SYSerr(SYS_F_GETSERVBYNAME, get_last_socket_error()); 209 ERR_add_error_data(3, "service='", str, "'"); 210 return (0); 211 } 212 } 213 } 214 return (1); 215} 216 217int BIO_sock_error(int sock) 218{ 219 int j, i; 220 int size; 221 222 size = sizeof(int); 223 /* 224 * Note: under Windows the third parameter is of type (char *) whereas 225 * under other systems it is (void *) if you don't have a cast it will 226 * choke the compiler: if you do have a cast then you can either go for 227 * (char *) or (void *). 228 */ 229 i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, (void *)&size); 230 if (i < 0) 231 return (1); 232 else 233 return (j); 234} 235 236# if 0 237long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) 238{ 239 int i; 240 char **p; 241 242 switch (cmd) { 243 case BIO_GHBN_CTRL_HITS: 244 return (BIO_ghbn_hits); 245 /* break; */ 246 case BIO_GHBN_CTRL_MISSES: 247 return (BIO_ghbn_miss); 248 /* break; */ 249 case BIO_GHBN_CTRL_CACHE_SIZE: 250 return (GHBN_NUM); 251 /* break; */ 252 case BIO_GHBN_CTRL_GET_ENTRY: 253 if ((iarg >= 0) && (iarg < GHBN_NUM) && (ghbn_cache[iarg].order > 0)) { 254 p = (char **)parg; 255 if (p == NULL) 256 return (0); 257 *p = ghbn_cache[iarg].name; 258 ghbn_cache[iarg].name[128] = '\0'; 259 return (1); 260 } 261 return (0); 262 /* break; */ 263 case BIO_GHBN_CTRL_FLUSH: 264 for (i = 0; i < GHBN_NUM; i++) 265 ghbn_cache[i].order = 0; 266 break; 267 default: 268 return (0); 269 } 270 return (1); 271} 272# endif 273 274# if 0 275static struct hostent *ghbn_dup(struct hostent *a) 276{ 277 struct hostent *ret; 278 int i, j; 279 280 MemCheck_off(); 281 ret = (struct hostent *)OPENSSL_malloc(sizeof(struct hostent)); 282 if (ret == NULL) 283 return (NULL); 284 memset(ret, 0, sizeof(struct hostent)); 285 286 for (i = 0; a->h_aliases[i] != NULL; i++) ; 287 i++; 288 ret->h_aliases = (char **)OPENSSL_malloc(i * sizeof(char *)); 289 if (ret->h_aliases == NULL) 290 goto err; 291 memset(ret->h_aliases, 0, i * sizeof(char *)); 292 293 for (i = 0; a->h_addr_list[i] != NULL; i++) ; 294 i++; 295 ret->h_addr_list = (char **)OPENSSL_malloc(i * sizeof(char *)); 296 if (ret->h_addr_list == NULL) 297 goto err; 298 memset(ret->h_addr_list, 0, i * sizeof(char *)); 299 300 j = strlen(a->h_name) + 1; 301 if ((ret->h_name = OPENSSL_malloc(j)) == NULL) 302 goto err; 303 memcpy((char *)ret->h_name, a->h_name, j); 304 for (i = 0; a->h_aliases[i] != NULL; i++) { 305 j = strlen(a->h_aliases[i]) + 1; 306 if ((ret->h_aliases[i] = OPENSSL_malloc(j)) == NULL) 307 goto err; 308 memcpy(ret->h_aliases[i], a->h_aliases[i], j); 309 } 310 ret->h_length = a->h_length; 311 ret->h_addrtype = a->h_addrtype; 312 for (i = 0; a->h_addr_list[i] != NULL; i++) { 313 if ((ret->h_addr_list[i] = OPENSSL_malloc(a->h_length)) == NULL) 314 goto err; 315 memcpy(ret->h_addr_list[i], a->h_addr_list[i], a->h_length); 316 } 317 if (0) { 318 err: 319 if (ret != NULL) 320 ghbn_free(ret); 321 ret = NULL; 322 } 323 MemCheck_on(); 324 return (ret); 325} 326 327static void ghbn_free(struct hostent *a) 328{ 329 int i; 330 331 if (a == NULL) 332 return; 333 334 if (a->h_aliases != NULL) { 335 for (i = 0; a->h_aliases[i] != NULL; i++) 336 OPENSSL_free(a->h_aliases[i]); 337 OPENSSL_free(a->h_aliases); 338 } 339 if (a->h_addr_list != NULL) { 340 for (i = 0; a->h_addr_list[i] != NULL; i++) 341 OPENSSL_free(a->h_addr_list[i]); 342 OPENSSL_free(a->h_addr_list); 343 } 344 if (a->h_name != NULL) 345 OPENSSL_free(a->h_name); 346 OPENSSL_free(a); 347} 348 349# endif 350 351struct hostent *BIO_gethostbyname(const char *name) 352{ 353# if 1 354 /* 355 * Caching gethostbyname() results forever is wrong, so we have to let 356 * the true gethostbyname() worry about this 357 */ 358# if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__)) 359 return gethostbyname((char *)name); 360# else 361 return gethostbyname(name); 362# endif 363# else 364 struct hostent *ret; 365 int i, lowi = 0, j; 366 unsigned long low = (unsigned long)-1; 367 368# if 0 369 /* 370 * It doesn't make sense to use locking here: The function interface is 371 * not thread-safe, because threads can never be sure when some other 372 * thread destroys the data they were given a pointer to. 373 */ 374 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 375# endif 376 j = strlen(name); 377 if (j < 128) { 378 for (i = 0; i < GHBN_NUM; i++) { 379 if (low > ghbn_cache[i].order) { 380 low = ghbn_cache[i].order; 381 lowi = i; 382 } 383 if (ghbn_cache[i].order > 0) { 384 if (strncmp(name, ghbn_cache[i].name, 128) == 0) 385 break; 386 } 387 } 388 } else 389 i = GHBN_NUM; 390 391 if (i == GHBN_NUM) { /* no hit */ 392 BIO_ghbn_miss++; 393 /* 394 * Note: under VMS with SOCKETSHR, it seems like the first parameter 395 * is 'char *', instead of 'const char *' 396 */ 397# ifndef CONST_STRICT 398 ret = gethostbyname((char *)name); 399# else 400 ret = gethostbyname(name); 401# endif 402 403 if (ret == NULL) 404 goto end; 405 if (j > 128) { /* too big to cache */ 406# if 0 407 /* 408 * If we were trying to make this function thread-safe (which is 409 * bound to fail), we'd have to give up in this case (or allocate 410 * more memory). 411 */ 412 ret = NULL; 413# endif 414 goto end; 415 } 416 417 /* else add to cache */ 418 if (ghbn_cache[lowi].ent != NULL) 419 ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ 420 ghbn_cache[lowi].name[0] = '\0'; 421 422 if ((ret = ghbn_cache[lowi].ent = ghbn_dup(ret)) == NULL) { 423 BIOerr(BIO_F_BIO_GETHOSTBYNAME, ERR_R_MALLOC_FAILURE); 424 goto end; 425 } 426 strncpy(ghbn_cache[lowi].name, name, 128); 427 ghbn_cache[lowi].order = BIO_ghbn_miss + BIO_ghbn_hits; 428 } else { 429 BIO_ghbn_hits++; 430 ret = ghbn_cache[i].ent; 431 ghbn_cache[i].order = BIO_ghbn_miss + BIO_ghbn_hits; 432 } 433 end: 434# if 0 435 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 436# endif 437 return (ret); 438# endif 439} 440 441int BIO_sock_init(void) 442{ 443# ifdef OPENSSL_SYS_WINDOWS 444 static struct WSAData wsa_state; 445 446 if (!wsa_init_done) { 447 int err; 448 449 wsa_init_done = 1; 450 memset(&wsa_state, 0, sizeof(wsa_state)); 451 if (WSAStartup(0x0101, &wsa_state) != 0) { 452 err = WSAGetLastError(); 453 SYSerr(SYS_F_WSASTARTUP, err); 454 BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); 455 return (-1); 456 } 457 } 458# endif /* OPENSSL_SYS_WINDOWS */ 459# ifdef WATT32 460 extern int _watt_do_exit; 461 _watt_do_exit = 0; /* don't make sock_init() call exit() */ 462 if (sock_init()) 463 return (-1); 464# endif 465 466# if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 467 WORD wVerReq; 468 WSADATA wsaData; 469 int err; 470 471 if (!wsa_init_done) { 472 wsa_init_done = 1; 473 wVerReq = MAKEWORD(2, 0); 474 err = WSAStartup(wVerReq, &wsaData); 475 if (err != 0) { 476 SYSerr(SYS_F_WSASTARTUP, err); 477 BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); 478 return (-1); 479 } 480 } 481# endif 482 483 return (1); 484} 485 486void BIO_sock_cleanup(void) 487{ 488# ifdef OPENSSL_SYS_WINDOWS 489 if (wsa_init_done) { 490 wsa_init_done = 0; 491# ifndef OPENSSL_SYS_WINCE 492 WSACancelBlockingCall(); /* Winsock 1.1 specific */ 493# endif 494 WSACleanup(); 495 } 496# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 497 if (wsa_init_done) { 498 wsa_init_done = 0; 499 WSACleanup(); 500 } 501# endif 502} 503 504# if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 505 506int BIO_socket_ioctl(int fd, long type, void *arg) 507{ 508 int i; 509 510# ifdef __DJGPP__ 511 i = ioctlsocket(fd, type, (char *)arg); 512# else 513 i = ioctlsocket(fd, type, arg); 514# endif /* __DJGPP__ */ 515 if (i < 0) 516 SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); 517 return (i); 518} 519# endif /* __VMS_VER */ 520 521/* 522 * The reason I have implemented this instead of using sscanf is because 523 * Visual C 1.52c gives an unresolved external when linking a DLL :-( 524 */ 525static int get_ip(const char *str, unsigned char ip[4]) 526{ 527 unsigned int tmp[4]; 528 int num = 0, c, ok = 0; 529 530 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; 531 532 for (;;) { 533 c = *(str++); 534 if ((c >= '0') && (c <= '9')) { 535 ok = 1; 536 tmp[num] = tmp[num] * 10 + c - '0'; 537 if (tmp[num] > 255) 538 return (0); 539 } else if (c == '.') { 540 if (!ok) 541 return (-1); 542 if (num == 3) 543 return (0); 544 num++; 545 ok = 0; 546 } else if (c == '\0' && (num == 3) && ok) 547 break; 548 else 549 return (0); 550 } 551 ip[0] = tmp[0]; 552 ip[1] = tmp[1]; 553 ip[2] = tmp[2]; 554 ip[3] = tmp[3]; 555 return (1); 556} 557 558int BIO_get_accept_socket(char *host, int bind_mode) 559{ 560 int ret = 0; 561 struct sockaddr_in server, client; 562 int s = INVALID_SOCKET, cs; 563 unsigned char ip[4]; 564 unsigned short port; 565 char *str = NULL, *e; 566 const char *h, *p; 567 unsigned long l; 568 int err_num; 569 570 if (BIO_sock_init() != 1) 571 return (INVALID_SOCKET); 572 573 if ((str = BUF_strdup(host)) == NULL) 574 return (INVALID_SOCKET); 575 576 h = p = NULL; 577 h = str; 578 for (e = str; *e; e++) { 579 if (*e == ':') { 580 p = &(e[1]); 581 *e = '\0'; 582 } else if (*e == '/') { 583 *e = '\0'; 584 break; 585 } 586 } 587 588 if (p == NULL) { 589 p = h; 590 h = "*"; 591 } 592 593 if (!BIO_get_port(p, &port)) 594 goto err; 595 596 memset((char *)&server, 0, sizeof(server)); 597 server.sin_family = AF_INET; 598 server.sin_port = htons(port); 599 600 if (strcmp(h, "*") == 0) 601 server.sin_addr.s_addr = INADDR_ANY; 602 else { 603 if (!BIO_get_host_ip(h, &(ip[0]))) 604 goto err; 605 l = (unsigned long) 606 ((unsigned long)ip[0] << 24L) | 607 ((unsigned long)ip[1] << 16L) | 608 ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]); 609 server.sin_addr.s_addr = htonl(l); 610 } 611 612 again: 613 s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL); 614 if (s == INVALID_SOCKET) { 615 SYSerr(SYS_F_SOCKET, get_last_socket_error()); 616 ERR_add_error_data(3, "port='", host, "'"); 617 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); 618 goto err; 619 } 620# ifdef SO_REUSEADDR 621 if (bind_mode == BIO_BIND_REUSEADDR) { 622 int i = 1; 623 624 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)); 625 bind_mode = BIO_BIND_NORMAL; 626 } 627# endif 628 if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) { 629# ifdef SO_REUSEADDR 630 err_num = get_last_socket_error(); 631 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && 632# ifdef OPENSSL_SYS_WINDOWS 633 /* 634 * Some versions of Windows define EADDRINUSE to a dummy value. 635 */ 636 (err_num == WSAEADDRINUSE)) 637# else 638 (err_num == EADDRINUSE)) 639# endif 640 { 641 memcpy((char *)&client, (char *)&server, sizeof(server)); 642 if (strcmp(h, "*") == 0) 643 client.sin_addr.s_addr = htonl(0x7F000001); 644 cs = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL); 645 if (cs != INVALID_SOCKET) { 646 int ii; 647 ii = connect(cs, (struct sockaddr *)&client, sizeof(client)); 648 closesocket(cs); 649 if (ii == INVALID_SOCKET) { 650 bind_mode = BIO_BIND_REUSEADDR; 651 closesocket(s); 652 goto again; 653 } 654 /* else error */ 655 } 656 /* else error */ 657 } 658# endif 659 SYSerr(SYS_F_BIND, err_num); 660 ERR_add_error_data(3, "port='", host, "'"); 661 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_BIND_SOCKET); 662 goto err; 663 } 664 if (listen(s, MAX_LISTEN) == -1) { 665 SYSerr(SYS_F_BIND, get_last_socket_error()); 666 ERR_add_error_data(3, "port='", host, "'"); 667 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_LISTEN_SOCKET); 668 goto err; 669 } 670 ret = 1; 671 err: 672 if (str != NULL) 673 OPENSSL_free(str); 674 if ((ret == 0) && (s != INVALID_SOCKET)) { 675 closesocket(s); 676 s = INVALID_SOCKET; 677 } 678 return (s); 679} 680 681int BIO_accept(int sock, char **addr) 682{ 683 int ret = INVALID_SOCKET; 684 static struct sockaddr_in from; 685 unsigned long l; 686 unsigned short port; 687 int len; 688 char *p; 689 690 memset((char *)&from, 0, sizeof(from)); 691 len = sizeof(from); 692 /* 693 * Note: under VMS with SOCKETSHR the fourth parameter is currently of 694 * type (int *) whereas under other systems it is (void *) if you don't 695 * have a cast it will choke the compiler: if you do have a cast then you 696 * can either go for (int *) or (void *). 697 */ 698 ret = accept(sock, (struct sockaddr *)&from, (void *)&len); 699 if (ret == INVALID_SOCKET) { 700 if (BIO_sock_should_retry(ret)) 701 return -2; 702 SYSerr(SYS_F_ACCEPT, get_last_socket_error()); 703 BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); 704 goto end; 705 } 706 707 if (addr == NULL) 708 goto end; 709 710 l = ntohl(from.sin_addr.s_addr); 711 port = ntohs(from.sin_port); 712 if (*addr == NULL) { 713 if ((p = OPENSSL_malloc(24)) == NULL) { 714 BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); 715 goto end; 716 } 717 *addr = p; 718 } 719 BIO_snprintf(*addr, 24, "%d.%d.%d.%d:%d", 720 (unsigned char)(l >> 24L) & 0xff, 721 (unsigned char)(l >> 16L) & 0xff, 722 (unsigned char)(l >> 8L) & 0xff, 723 (unsigned char)(l) & 0xff, port); 724 end: 725 return (ret); 726} 727 728int BIO_set_tcp_ndelay(int s, int on) 729{ 730 int ret = 0; 731# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 732 int opt; 733 734# ifdef SOL_TCP 735 opt = SOL_TCP; 736# else 737# ifdef IPPROTO_TCP 738 opt = IPPROTO_TCP; 739# endif 740# endif 741 742 ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); 743# endif 744 return (ret == 0); 745} 746#endif 747 748int BIO_socket_nbio(int s, int mode) 749{ 750 int ret = -1; 751 int l; 752 753 l = mode; 754#ifdef FIONBIO 755 ret = BIO_socket_ioctl(s, FIONBIO, &l); 756#endif 757 return (ret == 0); 758} 759