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 #ifndef OPENSSL_NO_SOCK 60 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <errno.h> 64 #define USE_SOCKETS 65 #include "cryptlib.h" 66 #include <openssl/bio.h> 67 68 #ifdef OPENSSL_SYS_WIN16 69 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 70 #else 71 #define SOCKET_PROTOCOL IPPROTO_TCP 72 #endif 73 74 #ifdef SO_MAXCONN 75 #define MAX_LISTEN SO_MAXCONN 76 #elif defined(SOMAXCONN) 77 #define MAX_LISTEN SOMAXCONN 78 #else 79 #define MAX_LISTEN 32 80 #endif 81 82 #ifdef OPENSSL_SYS_WINDOWS 83 static int wsa_init_done=0; 84 #endif 85 86 static unsigned long BIO_ghbn_hits=0L; 87 static unsigned long BIO_ghbn_miss=0L; 88 89 #define GHBN_NUM 4 90 static struct ghbn_cache_st 91 { 92 char name[129]; 93 struct hostent *ent; 94 unsigned long order; 95 } ghbn_cache[GHBN_NUM]; 96 97 static int get_ip(const char *str,unsigned char *ip); 98 #if 0 99 static void ghbn_free(struct hostent *a); 100 static struct hostent *ghbn_dup(struct hostent *a); 101 #endif 102 int BIO_get_host_ip(const char *str, unsigned char *ip) 103 { 104 int i; 105 int err = 1; 106 int locked = 0; 107 struct hostent *he; 108 109 i=get_ip(str,ip); 110 if (i < 0) 111 { 112 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); 113 goto err; 114 } 115 116 /* At this point, we have something that is most probably correct 117 in some way, so let's init the socket. */ 118 if (BIO_sock_init() != 1) 119 return 0; /* don't generate another error code here */ 120 121 /* If the string actually contained an IP address, we need not do 122 anything more */ 123 if (i > 0) return(1); 124 125 /* do a gethostbyname */ 126 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 127 locked = 1; 128 he=BIO_gethostbyname(str); 129 if (he == NULL) 130 { 131 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); 132 goto err; 133 } 134 135 /* cast to short because of win16 winsock definition */ 136 if ((short)he->h_addrtype != AF_INET) 137 { 138 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 139 goto err; 140 } 141 for (i=0; i<4; i++) 142 ip[i]=he->h_addr_list[0][i]; 143 err = 0; 144 145 err: 146 if (locked) 147 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 148 if (err) 149 { 150 ERR_add_error_data(2,"host=",str); 151 return 0; 152 } 153 else 154 return 1; 155 } 156 157 int BIO_get_port(const char *str, unsigned short *port_ptr) 158 { 159 int i; 160 struct servent *s; 161 162 if (str == NULL) 163 { 164 BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED); 165 return(0); 166 } 167 i=atoi(str); 168 if (i != 0) 169 *port_ptr=(unsigned short)i; 170 else 171 { 172 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); 173 /* Note: under VMS with SOCKETSHR, it seems like the first 174 * parameter is 'char *', instead of 'const char *' 175 */ 176 s=getservbyname( 177 #ifndef CONST_STRICT 178 (char *) 179 #endif 180 str,"tcp"); 181 if(s != NULL) 182 *port_ptr=ntohs((unsigned short)s->s_port); 183 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); 184 if(s == NULL) 185 { 186 if (strcmp(str,"http") == 0) 187 *port_ptr=80; 188 else if (strcmp(str,"telnet") == 0) 189 *port_ptr=23; 190 else if (strcmp(str,"socks") == 0) 191 *port_ptr=1080; 192 else if (strcmp(str,"https") == 0) 193 *port_ptr=443; 194 else if (strcmp(str,"ssl") == 0) 195 *port_ptr=443; 196 else if (strcmp(str,"ftp") == 0) 197 *port_ptr=21; 198 else if (strcmp(str,"gopher") == 0) 199 *port_ptr=70; 200 #if 0 201 else if (strcmp(str,"wais") == 0) 202 *port_ptr=21; 203 #endif 204 else 205 { 206 SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error()); 207 ERR_add_error_data(3,"service='",str,"'"); 208 return(0); 209 } 210 } 211 } 212 return(1); 213 } 214 215 int BIO_sock_error(int sock) 216 { 217 int j,i; 218 int size; 219 220 size=sizeof(int); 221 /* Note: under Windows the third parameter is of type (char *) 222 * whereas under other systems it is (void *) if you don't have 223 * a cast it will choke the compiler: if you do have a cast then 224 * you can either go for (char *) or (void *). 225 */ 226 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); 227 if (i < 0) 228 return(1); 229 else 230 return(j); 231 } 232 233 long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) 234 { 235 int i; 236 char **p; 237 238 switch (cmd) 239 { 240 case BIO_GHBN_CTRL_HITS: 241 return(BIO_ghbn_hits); 242 /* break; */ 243 case BIO_GHBN_CTRL_MISSES: 244 return(BIO_ghbn_miss); 245 /* break; */ 246 case BIO_GHBN_CTRL_CACHE_SIZE: 247 return(GHBN_NUM); 248 /* break; */ 249 case BIO_GHBN_CTRL_GET_ENTRY: 250 if ((iarg >= 0) && (iarg <GHBN_NUM) && 251 (ghbn_cache[iarg].order > 0)) 252 { 253 p=(char **)parg; 254 if (p == NULL) return(0); 255 *p=ghbn_cache[iarg].name; 256 ghbn_cache[iarg].name[128]='\0'; 257 return(1); 258 } 259 return(0); 260 /* break; */ 261 case BIO_GHBN_CTRL_FLUSH: 262 for (i=0; i<GHBN_NUM; i++) 263 ghbn_cache[i].order=0; 264 break; 265 default: 266 return(0); 267 } 268 return(1); 269 } 270 271 #if 0 272 static struct hostent *ghbn_dup(struct hostent *a) 273 { 274 struct hostent *ret; 275 int i,j; 276 277 MemCheck_off(); 278 ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent)); 279 if (ret == NULL) return(NULL); 280 memset(ret,0,sizeof(struct hostent)); 281 282 for (i=0; a->h_aliases[i] != NULL; i++) 283 ; 284 i++; 285 ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *)); 286 if (ret->h_aliases == NULL) 287 goto err; 288 memset(ret->h_aliases, 0, i*sizeof(char *)); 289 290 for (i=0; a->h_addr_list[i] != NULL; i++) 291 ; 292 i++; 293 ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *)); 294 if (ret->h_addr_list == NULL) 295 goto err; 296 memset(ret->h_addr_list, 0, i*sizeof(char *)); 297 298 j=strlen(a->h_name)+1; 299 if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err; 300 memcpy((char *)ret->h_name,a->h_name,j); 301 for (i=0; a->h_aliases[i] != NULL; i++) 302 { 303 j=strlen(a->h_aliases[i])+1; 304 if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err; 305 memcpy(ret->h_aliases[i],a->h_aliases[i],j); 306 } 307 ret->h_length=a->h_length; 308 ret->h_addrtype=a->h_addrtype; 309 for (i=0; a->h_addr_list[i] != NULL; i++) 310 { 311 if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL) 312 goto err; 313 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); 314 } 315 if (0) 316 { 317 err: 318 if (ret != NULL) 319 ghbn_free(ret); 320 ret=NULL; 321 } 322 MemCheck_on(); 323 return(ret); 324 } 325 326 static void ghbn_free(struct hostent *a) 327 { 328 int i; 329 330 if(a == NULL) 331 return; 332 333 if (a->h_aliases != NULL) 334 { 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 { 341 for (i=0; a->h_addr_list[i] != NULL; i++) 342 OPENSSL_free(a->h_addr_list[i]); 343 OPENSSL_free(a->h_addr_list); 344 } 345 if (a->h_name != NULL) OPENSSL_free(a->h_name); 346 OPENSSL_free(a); 347 } 348 349 #endif 350 351 struct hostent *BIO_gethostbyname(const char *name) 352 { 353 #if 1 354 /* Caching gethostbyname() results forever is wrong, 355 * so we have to let the true gethostbyname() worry about this */ 356 return gethostbyname(name); 357 #else 358 struct hostent *ret; 359 int i,lowi=0,j; 360 unsigned long low= (unsigned long)-1; 361 362 363 # if 0 364 /* It doesn't make sense to use locking here: The function interface 365 * is not thread-safe, because threads can never be sure when 366 * some other thread destroys the data they were given a pointer to. 367 */ 368 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 369 # endif 370 j=strlen(name); 371 if (j < 128) 372 { 373 for (i=0; i<GHBN_NUM; i++) 374 { 375 if (low > ghbn_cache[i].order) 376 { 377 low=ghbn_cache[i].order; 378 lowi=i; 379 } 380 if (ghbn_cache[i].order > 0) 381 { 382 if (strncmp(name,ghbn_cache[i].name,128) == 0) 383 break; 384 } 385 } 386 } 387 else 388 i=GHBN_NUM; 389 390 if (i == GHBN_NUM) /* no hit*/ 391 { 392 BIO_ghbn_miss++; 393 /* Note: under VMS with SOCKETSHR, it seems like the first 394 * parameter is 'char *', instead of 'const char *' 395 */ 396 ret=gethostbyname( 397 # ifndef CONST_STRICT 398 (char *) 399 # endif 400 name); 401 402 if (ret == NULL) 403 goto end; 404 if (j > 128) /* too big to cache */ 405 { 406 # if 0 407 /* If we were trying to make this function thread-safe (which 408 * is bound to fail), we'd have to give up in this case 409 * (or allocate more memory). */ 410 ret = NULL; 411 # endif 412 goto end; 413 } 414 415 /* else add to cache */ 416 if (ghbn_cache[lowi].ent != NULL) 417 ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ 418 ghbn_cache[lowi].name[0] = '\0'; 419 420 if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) 421 { 422 BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); 423 goto end; 424 } 425 strncpy(ghbn_cache[lowi].name,name,128); 426 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; 427 } 428 else 429 { 430 BIO_ghbn_hits++; 431 ret= ghbn_cache[i].ent; 432 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; 433 } 434 end: 435 # if 0 436 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 437 # endif 438 return(ret); 439 #endif 440 } 441 442 443 int BIO_sock_init(void) 444 { 445 #ifdef OPENSSL_SYS_WINDOWS 446 static struct WSAData wsa_state; 447 448 if (!wsa_init_done) 449 { 450 int err; 451 452 #ifdef SIGINT 453 signal(SIGINT,(void (*)(int))BIO_sock_cleanup); 454 #endif 455 wsa_init_done=1; 456 memset(&wsa_state,0,sizeof(wsa_state)); 457 if (WSAStartup(0x0101,&wsa_state)!=0) 458 { 459 err=WSAGetLastError(); 460 SYSerr(SYS_F_WSASTARTUP,err); 461 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP); 462 return(-1); 463 } 464 } 465 #endif /* OPENSSL_SYS_WINDOWS */ 466 return(1); 467 } 468 469 void BIO_sock_cleanup(void) 470 { 471 #ifdef OPENSSL_SYS_WINDOWS 472 if (wsa_init_done) 473 { 474 wsa_init_done=0; 475 WSACancelBlockingCall(); 476 WSACleanup(); 477 } 478 #endif 479 } 480 481 #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 482 483 int BIO_socket_ioctl(int fd, long type, unsigned long *arg) 484 { 485 int i; 486 487 i=ioctlsocket(fd,type,arg); 488 if (i < 0) 489 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); 490 return(i); 491 } 492 #endif /* __VMS_VER */ 493 494 /* The reason I have implemented this instead of using sscanf is because 495 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ 496 static int get_ip(const char *str, unsigned char ip[4]) 497 { 498 unsigned int tmp[4]; 499 int num=0,c,ok=0; 500 501 tmp[0]=tmp[1]=tmp[2]=tmp[3]=0; 502 503 for (;;) 504 { 505 c= *(str++); 506 if ((c >= '0') && (c <= '9')) 507 { 508 ok=1; 509 tmp[num]=tmp[num]*10+c-'0'; 510 if (tmp[num] > 255) return(0); 511 } 512 else if (c == '.') 513 { 514 if (!ok) return(-1); 515 if (num == 3) return(0); 516 num++; 517 ok=0; 518 } 519 else if (c == '\0' && (num == 3) && ok) 520 break; 521 else 522 return(0); 523 } 524 ip[0]=tmp[0]; 525 ip[1]=tmp[1]; 526 ip[2]=tmp[2]; 527 ip[3]=tmp[3]; 528 return(1); 529 } 530 531 int BIO_get_accept_socket(char *host, int bind_mode) 532 { 533 int ret=0; 534 struct sockaddr_in server,client; 535 int s=INVALID_SOCKET,cs; 536 unsigned char ip[4]; 537 unsigned short port; 538 char *str=NULL,*e; 539 const char *h,*p; 540 unsigned long l; 541 int err_num; 542 543 if (BIO_sock_init() != 1) return(INVALID_SOCKET); 544 545 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); 546 547 h=p=NULL; 548 h=str; 549 for (e=str; *e; e++) 550 { 551 if (*e == ':') 552 { 553 p= &(e[1]); 554 *e='\0'; 555 } 556 else if (*e == '/') 557 { 558 *e='\0'; 559 break; 560 } 561 } 562 563 if (p == NULL) 564 { 565 p=h; 566 h="*"; 567 } 568 569 if (!BIO_get_port(p,&port)) goto err; 570 571 memset((char *)&server,0,sizeof(server)); 572 server.sin_family=AF_INET; 573 server.sin_port=htons(port); 574 575 if (strcmp(h,"*") == 0) 576 server.sin_addr.s_addr=INADDR_ANY; 577 else 578 { 579 if (!BIO_get_host_ip(h,&(ip[0]))) goto err; 580 l=(unsigned long) 581 ((unsigned long)ip[0]<<24L)| 582 ((unsigned long)ip[1]<<16L)| 583 ((unsigned long)ip[2]<< 8L)| 584 ((unsigned long)ip[3]); 585 server.sin_addr.s_addr=htonl(l); 586 } 587 588 again: 589 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 590 if (s == INVALID_SOCKET) 591 { 592 SYSerr(SYS_F_SOCKET,get_last_socket_error()); 593 ERR_add_error_data(3,"port='",host,"'"); 594 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); 595 goto err; 596 } 597 598 #ifdef SO_REUSEADDR 599 if (bind_mode == BIO_BIND_REUSEADDR) 600 { 601 int i=1; 602 603 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); 604 bind_mode=BIO_BIND_NORMAL; 605 } 606 #endif 607 if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) 608 { 609 #ifdef SO_REUSEADDR 610 err_num=get_last_socket_error(); 611 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && 612 (err_num == EADDRINUSE)) 613 { 614 memcpy((char *)&client,(char *)&server,sizeof(server)); 615 if (strcmp(h,"*") == 0) 616 client.sin_addr.s_addr=htonl(0x7F000001); 617 cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 618 if (cs != INVALID_SOCKET) 619 { 620 int ii; 621 ii=connect(cs,(struct sockaddr *)&client, 622 sizeof(client)); 623 closesocket(cs); 624 if (ii == INVALID_SOCKET) 625 { 626 bind_mode=BIO_BIND_REUSEADDR; 627 closesocket(s); 628 goto again; 629 } 630 /* else error */ 631 } 632 /* else error */ 633 } 634 #endif 635 SYSerr(SYS_F_BIND,err_num); 636 ERR_add_error_data(3,"port='",host,"'"); 637 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); 638 goto err; 639 } 640 if (listen(s,MAX_LISTEN) == -1) 641 { 642 SYSerr(SYS_F_BIND,get_last_socket_error()); 643 ERR_add_error_data(3,"port='",host,"'"); 644 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET); 645 goto err; 646 } 647 ret=1; 648 err: 649 if (str != NULL) OPENSSL_free(str); 650 if ((ret == 0) && (s != INVALID_SOCKET)) 651 { 652 closesocket(s); 653 s= INVALID_SOCKET; 654 } 655 return(s); 656 } 657 658 int BIO_accept(int sock, char **addr) 659 { 660 int ret=INVALID_SOCKET; 661 static struct sockaddr_in from; 662 unsigned long l; 663 unsigned short port; 664 int len; 665 char *p; 666 667 memset((char *)&from,0,sizeof(from)); 668 len=sizeof(from); 669 /* Note: under VMS with SOCKETSHR the fourth parameter is currently 670 * of type (int *) whereas under other systems it is (void *) if 671 * you don't have a cast it will choke the compiler: if you do 672 * have a cast then you can either go for (int *) or (void *). 673 */ 674 ret=accept(sock,(struct sockaddr *)&from,(void *)&len); 675 if (ret == INVALID_SOCKET) 676 { 677 if(BIO_sock_should_retry(ret)) return -2; 678 SYSerr(SYS_F_ACCEPT,get_last_socket_error()); 679 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); 680 goto end; 681 } 682 683 if (addr == NULL) goto end; 684 685 l=ntohl(from.sin_addr.s_addr); 686 port=ntohs(from.sin_port); 687 if (*addr == NULL) 688 { 689 if ((p=OPENSSL_malloc(24)) == NULL) 690 { 691 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); 692 goto end; 693 } 694 *addr=p; 695 } 696 sprintf(*addr,"%d.%d.%d.%d:%d", 697 (unsigned char)(l>>24L)&0xff, 698 (unsigned char)(l>>16L)&0xff, 699 (unsigned char)(l>> 8L)&0xff, 700 (unsigned char)(l )&0xff, 701 port); 702 end: 703 return(ret); 704 } 705 706 int BIO_set_tcp_ndelay(int s, int on) 707 { 708 int ret=0; 709 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 710 int opt; 711 712 #ifdef SOL_TCP 713 opt=SOL_TCP; 714 #else 715 #ifdef IPPROTO_TCP 716 opt=IPPROTO_TCP; 717 #endif 718 #endif 719 720 ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on)); 721 #endif 722 return(ret == 0); 723 } 724 #endif 725 726 int BIO_socket_nbio(int s, int mode) 727 { 728 int ret= -1; 729 unsigned long l; 730 731 l=mode; 732 #ifdef FIONBIO 733 ret=BIO_socket_ioctl(s,FIONBIO,&l); 734 #endif 735 return(ret == 0); 736 } 737