1/* os-ip.c -- platform-specific TCP & UDP related code */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * Portions Copyright 1999 Lars Uffmann. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17/* Portions Copyright (c) 1995 Regents of the University of Michigan. 18 * All rights reserved. 19 */ 20/* Significant additional contributors include: 21 * Lars Uffman 22 */ 23 24#include "portable.h" 25 26#include <stdio.h> 27 28#include <ac/stdlib.h> 29 30#include <ac/errno.h> 31#include <ac/socket.h> 32#include <ac/string.h> 33#include <ac/time.h> 34#include <ac/unistd.h> 35 36#ifdef HAVE_IO_H 37#include <io.h> 38#endif /* HAVE_IO_H */ 39#ifdef HAVE_FCNTL_H 40#include <fcntl.h> 41#endif 42 43#include "ldap-int.h" 44 45#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 46# ifdef LDAP_PF_INET6 47int ldap_int_inet4or6 = AF_UNSPEC; 48# else 49int ldap_int_inet4or6 = AF_INET; 50# endif 51#endif 52 53#ifdef LDAP_DEBUG 54 55#define osip_debug(ld,fmt,arg1,arg2,arg3) \ 56do { \ 57 ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ 58} while(0) 59 60#else 61 62#define osip_debug(ld,fmt,arg1,arg2,arg3) ((void)0) 63 64#endif /* LDAP_DEBUG */ 65 66static void 67ldap_pvt_set_errno(int err) 68{ 69 sock_errset(err); 70} 71 72int 73ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src ) 74{ 75 struct timeval *new; 76 77 assert( dest != NULL ); 78 79 if (src == NULL) { 80 *dest = NULL; 81 return 0; 82 } 83 84 new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval)); 85 86 if( new == NULL ) { 87 *dest = NULL; 88 return 1; 89 } 90 91 AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval)); 92 93 *dest = new; 94 return 0; 95} 96 97static int 98ldap_pvt_ndelay_on(LDAP *ld, int fd) 99{ 100 osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0); 101 return ber_pvt_socket_set_nonblock( fd, 1 ); 102} 103 104static int 105ldap_pvt_ndelay_off(LDAP *ld, int fd) 106{ 107 osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0); 108 return ber_pvt_socket_set_nonblock( fd, 0 ); 109} 110 111static ber_socket_t 112ldap_int_socket(LDAP *ld, int family, int type ) 113{ 114 ber_socket_t s = socket(family, type, 0); 115 osip_debug(ld, "ldap_new_socket: %d\n",s,0,0); 116#ifdef FD_CLOEXEC 117 fcntl(s, F_SETFD, FD_CLOEXEC); 118#endif 119 return ( s ); 120} 121 122static int 123ldap_pvt_close_socket(LDAP *ld, int s) 124{ 125 osip_debug(ld, "ldap_close_socket: %d\n",s,0,0); 126 return tcp_close(s); 127} 128 129static int 130ldap_int_prepare_socket(LDAP *ld, int s, int proto ) 131{ 132 osip_debug( ld, "ldap_prepare_socket: %d\n", s, 0, 0 ); 133 134#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) 135 if ( proto == LDAP_PROTO_TCP ) { 136 int dummy = 1; 137#ifdef SO_KEEPALIVE 138 if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, 139 (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) 140 { 141 osip_debug( ld, "ldap_prepare_socket: " 142 "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n", 143 s, 0, 0 ); 144 } 145 if ( ld->ld_options.ldo_keepalive_idle > 0 ) 146 { 147#ifdef TCP_KEEPIDLE 148 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE, 149 (void*) &ld->ld_options.ldo_keepalive_idle, 150 sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR ) 151 { 152 osip_debug( ld, "ldap_prepare_socket: " 153 "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n", 154 s, 0, 0 ); 155 } 156#else 157 osip_debug( ld, "ldap_prepare_socket: " 158 "sockopt TCP_KEEPIDLE not supported on this system.\n", 159 0, 0, 0 ); 160#endif /* TCP_KEEPIDLE */ 161 } 162 if ( ld->ld_options.ldo_keepalive_probes > 0 ) 163 { 164#ifdef TCP_KEEPCNT 165 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT, 166 (void*) &ld->ld_options.ldo_keepalive_probes, 167 sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR ) 168 { 169 osip_debug( ld, "ldap_prepare_socket: " 170 "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n", 171 s, 0, 0 ); 172 } 173#else 174 osip_debug( ld, "ldap_prepare_socket: " 175 "sockopt TCP_KEEPCNT not supported on this system.\n", 176 0, 0, 0 ); 177#endif /* TCP_KEEPCNT */ 178 } 179 if ( ld->ld_options.ldo_keepalive_interval > 0 ) 180 { 181#ifdef TCP_KEEPINTVL 182 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL, 183 (void*) &ld->ld_options.ldo_keepalive_interval, 184 sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR ) 185 { 186 osip_debug( ld, "ldap_prepare_socket: " 187 "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n", 188 s, 0, 0 ); 189 } 190#else 191 osip_debug( ld, "ldap_prepare_socket: " 192 "sockopt TCP_KEEPINTVL not supported on this system.\n", 193 0, 0, 0 ); 194#endif /* TCP_KEEPINTVL */ 195 } 196#endif /* SO_KEEPALIVE */ 197#ifdef TCP_NODELAY 198 if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, 199 (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) 200 { 201 osip_debug( ld, "ldap_prepare_socket: " 202 "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", 203 s, 0, 0 ); 204 } 205#endif /* TCP_NODELAY */ 206 } 207#endif /* SO_KEEPALIVE || TCP_NODELAY */ 208 209 int flag = 1; 210 if(ld->ld_options.ldo_noaddr_option == 1) { 211 if ( setsockopt( s, SOL_SOCKET, SO_NOADDRERR, 212 (char*) &flag, sizeof(flag) ) == AC_SOCKET_ERROR ) 213 { 214 osip_debug(ld, "ldap_set_noaddrerr: " 215 "setsockopt(%d, SO_NOADDRERR) failed (ignored).\n", 216 s, 0, 0); 217 } 218 } 219 220 return 0; 221} 222 223#ifndef HAVE_WINSOCK 224 225#undef TRACE 226#define TRACE do { \ 227 osip_debug(ld, \ 228 "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \ 229 s, \ 230 errno, \ 231 sock_errstr(errno) ); \ 232} while( 0 ) 233 234/* 235 * check the socket for errors after select returned. 236 */ 237static int 238ldap_pvt_is_socket_ready(LDAP *ld, int s) 239{ 240 osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0); 241 242#if defined( notyet ) /* && defined( SO_ERROR ) */ 243{ 244 int so_errno; 245 ber_socklen_t dummy = sizeof(so_errno); 246 if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) 247 == AC_SOCKET_ERROR ) 248 { 249 return -1; 250 } 251 if ( so_errno ) { 252 ldap_pvt_set_errno(so_errno); 253 TRACE; 254 return -1; 255 } 256 return 0; 257} 258#else 259{ 260 /* error slippery */ 261#ifdef LDAP_PF_INET6 262 struct sockaddr_storage sin; 263#else 264 struct sockaddr_in sin; 265#endif 266 char ch; 267 ber_socklen_t dummy = sizeof(sin); 268 if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) 269 == AC_SOCKET_ERROR ) 270 { 271 /* XXX: needs to be replace with ber_stream_read() */ 272 (void)read(s, &ch, 1); 273 TRACE; 274 return -1; 275 } 276 return 0; 277} 278#endif 279 return -1; 280} 281#undef TRACE 282 283#endif /* HAVE_WINSOCK */ 284 285/* NOTE: this is identical to analogous code in os-local.c */ 286int 287ldap_int_poll( 288 LDAP *ld, 289 ber_socket_t s, 290 struct timeval *tvp ) 291{ 292 int rc; 293 294 295 osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n", 296 s, tvp ? tvp->tv_sec : -1L, 0); 297 298#ifdef HAVE_POLL 299 { 300 struct pollfd fd; 301 int timeout = INFTIM; 302 303 fd.fd = s; 304 fd.events = POLL_WRITE; 305 306 if ( tvp != NULL ) { 307 timeout = TV2MILLISEC( tvp ); 308 } 309 do { 310 fd.revents = 0; 311 rc = poll( &fd, 1, timeout ); 312 313 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 314 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 315 316 if ( rc == AC_SOCKET_ERROR ) { 317 return rc; 318 } 319 320 if ( timeout == 0 && rc == 0 ) { 321 return -2; 322 } 323 324 if ( fd.revents & POLL_WRITE ) { 325 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 326 return -1; 327 } 328 329 if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) { 330 return -1; 331 } 332 return 0; 333 } 334 } 335#else 336 { 337 fd_set wfds, *z = NULL; 338#ifdef HAVE_WINSOCK 339 fd_set efds; 340#endif 341 struct timeval tv = { 0 }; 342 343#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK ) 344 if ( s >= FD_SETSIZE ) { 345 rc = AC_SOCKET_ERROR; 346 tcp_close( s ); 347 ldap_pvt_set_errno( EMFILE ); 348 return rc; 349 } 350#endif 351 352 if ( tvp != NULL ) { 353 tv = *tvp; 354 } 355 356 do { 357 FD_ZERO(&wfds); 358 FD_SET(s, &wfds ); 359 360#ifdef HAVE_WINSOCK 361 FD_ZERO(&efds); 362 FD_SET(s, &efds ); 363#endif 364 365 rc = select( ldap_int_tblsize, z, &wfds, 366#ifdef HAVE_WINSOCK 367 &efds, 368#else 369 z, 370#endif 371 tvp ? &tv : NULL ); 372 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 373 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 374 375 if ( rc == AC_SOCKET_ERROR ) { 376 return rc; 377 } 378 379 if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) { 380 return -2; 381 } 382 383#ifdef HAVE_WINSOCK 384 /* This means the connection failed */ 385 if ( FD_ISSET(s, &efds) ) { 386 int so_errno; 387 ber_socklen_t dummy = sizeof(so_errno); 388 if ( getsockopt( s, SOL_SOCKET, SO_ERROR, 389 (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno ) 390 { 391 /* impossible */ 392 so_errno = WSAGetLastError(); 393 } 394 ldap_pvt_set_errno( so_errno ); 395 osip_debug(ld, "ldap_int_poll: error on socket %d: " 396 "errno: %d (%s)\n", s, errno, sock_errstr( errno )); 397 return -1; 398 } 399#endif 400 if ( FD_ISSET(s, &wfds) ) { 401#ifndef HAVE_WINSOCK 402 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 403 return -1; 404 } 405#endif 406 if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { 407 return -1; 408 } 409 return 0; 410 } 411 } 412#endif 413 414 osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0); 415 ldap_pvt_set_errno( ETIMEDOUT ); 416 return -1; 417} 418 419static int 420ldap_pvt_connect(LDAP *ld, ber_socket_t s, 421 struct sockaddr *sin, ber_socklen_t addrlen, 422 int async) 423{ 424 int rc, err; 425 struct timeval tv, *opt_tv = NULL; 426 427#ifdef LDAP_CONNECTIONLESS 428 /* We could do a connect() but that would interfere with 429 * attempts to poll a broadcast address 430 */ 431 if (LDAP_IS_UDP(ld)) { 432 if (ld->ld_options.ldo_peer) 433 ldap_memfree(ld->ld_options.ldo_peer); 434 ld->ld_options.ldo_peer=ldap_memalloc(sizeof(struct sockaddr)); 435 AC_MEMCPY(ld->ld_options.ldo_peer,sin,sizeof(struct sockaddr)); 436 return ( 0 ); 437 } 438#endif 439 if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { 440 tv = ld->ld_options.ldo_tm_net; 441 opt_tv = &tv; 442 } 443 444 osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n", 445 s, opt_tv ? tv.tv_sec : -1L, async); 446 447 if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 ) 448 return ( -1 ); 449 450 if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { 451 if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) 452 return ( -1 ); 453 return ( 0 ); 454 } 455 456 err = sock_errno(); 457 if ( err != EINPROGRESS && err != EWOULDBLOCK ) { 458 return ( -1 ); 459 } 460 461 if ( async ) { 462 /* caller will call ldap_int_poll() as appropriate? */ 463 return ( -2 ); 464 } 465 466 rc = ldap_int_poll( ld, s, opt_tv ); 467 468 osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0); 469 470 return rc; 471} 472 473#ifndef HAVE_INET_ATON 474int 475ldap_pvt_inet_aton( const char *host, struct in_addr *in) 476{ 477 unsigned long u = inet_addr( host ); 478 479#ifdef INADDR_NONE 480 if ( u == INADDR_NONE ) return 0; 481#endif 482 if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0; 483 484 in->s_addr = u; 485 return 1; 486} 487#endif 488 489int 490ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr) 491{ 492 struct ldapoptions *lo; 493 ldaplist *ll; 494 ldap_conncb *cb; 495 int rc; 496 497 ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); 498 499 /* Invoke all handle-specific callbacks first */ 500 lo = &ld->ld_options; 501 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 502 cb = ll->ll_data; 503 rc = cb->lc_add( ld, sb, srv, addr, cb ); 504 /* on any failure, call the teardown functions for anything 505 * that previously succeeded 506 */ 507 if ( rc ) { 508 ldaplist *l2; 509 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 510 cb = l2->ll_data; 511 cb->lc_del( ld, sb, cb ); 512 } 513 /* a failure might have implicitly closed the fd */ 514 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 515 return rc; 516 } 517 } 518 lo = LDAP_INT_GLOBAL_OPT(); 519 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 520 cb = ll->ll_data; 521 rc = cb->lc_add( ld, sb, srv, addr, cb ); 522 if ( rc ) { 523 ldaplist *l2; 524 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 525 cb = l2->ll_data; 526 cb->lc_del( ld, sb, cb ); 527 } 528 lo = &ld->ld_options; 529 for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { 530 cb = l2->ll_data; 531 cb->lc_del( ld, sb, cb ); 532 } 533 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 534 return rc; 535 } 536 } 537 return 0; 538} 539 540int 541ldap_connect_to_host(LDAP *ld, Sockbuf *sb, 542 int proto, LDAPURLDesc *srv, 543 int async ) 544{ 545 int rc; 546 int socktype, port; 547 ber_socket_t s = AC_SOCKET_INVALID; 548 char *host; 549 550#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 551 char serv[7]; 552 int err; 553 struct addrinfo hints, *res, *sai; 554#else 555 int i; 556 int use_hp = 0; 557 struct hostent *hp = NULL; 558 struct hostent he_buf; 559 struct in_addr in; 560 char *ha_buf=NULL; 561#endif 562 563 if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { 564 host = "localhost"; 565 } else { 566 host = srv->lud_host; 567 } 568 569 port = srv->lud_port; 570 571 if( !port ) { 572 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { 573 port = LDAPS_PORT; 574 } else { 575 port = LDAP_PORT; 576 } 577 } 578 579 switch(proto) { 580 case LDAP_PROTO_TCP: socktype = SOCK_STREAM; 581 osip_debug( ld, 582 "ldap_connect_to_host: TCP %s:%d\n", 583 host, port, 0); 584 break; 585 case LDAP_PROTO_UDP: socktype = SOCK_DGRAM; 586 osip_debug( ld, 587 "ldap_connect_to_host: UDP %s:%d\n", 588 host, port, 0); 589 break; 590 default: 591 osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n", 592 proto, 0, 0 ); 593 return -1; 594 } 595 596#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 597 memset( &hints, '\0', sizeof(hints) ); 598#ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */ 599 /* Use AI_ADDRCONFIG only on systems where its known to be needed. */ 600 hints.ai_flags = AI_ADDRCONFIG; 601#endif 602 hints.ai_family = ldap_int_inet4or6; 603 hints.ai_socktype = socktype; 604 snprintf(serv, sizeof serv, "%d", port ); 605 606 /* most getaddrinfo(3) use non-threadsafe resolver libraries */ 607 LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex); 608 609 err = getaddrinfo( host, serv, &hints, &res ); 610 611 LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex); 612 613 if ( err != 0 ) { 614 osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n", 615 AC_GAI_STRERROR(err), 0, 0); 616 return -1; 617 } 618 rc = -1; 619 620 for( sai=res; sai != NULL; sai=sai->ai_next) { 621 if( sai->ai_addr == NULL ) { 622 osip_debug(ld, "ldap_connect_to_host: getaddrinfo " 623 "ai_addr is NULL?\n", 0, 0, 0); 624 continue; 625 } 626 627 /* we assume AF_x and PF_x are equal for all x */ 628 s = ldap_int_socket( ld, sai->ai_family, socktype ); 629 if ( s == AC_SOCKET_INVALID ) { 630 continue; 631 } 632 633 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { 634 ldap_pvt_close_socket(ld, s); 635 break; 636 } 637 638 switch (sai->ai_family) { 639#ifdef LDAP_PF_INET6 640 case AF_INET6: { 641 char addr[INET6_ADDRSTRLEN]; 642 inet_ntop( AF_INET6, 643 &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, 644 addr, sizeof addr); 645 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 646 addr, serv, 0); 647 } break; 648#endif 649 case AF_INET: { 650 char addr[INET_ADDRSTRLEN]; 651 inet_ntop( AF_INET, 652 &((struct sockaddr_in *)sai->ai_addr)->sin_addr, 653 addr, sizeof addr); 654 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 655 addr, serv, 0); 656 } break; 657 } 658 659 rc = ldap_pvt_connect( ld, s, 660 sai->ai_addr, sai->ai_addrlen, async ); 661 if ( rc == 0 || rc == -2 ) { 662 err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); 663 if ( err ) 664 rc = err; 665 else 666 break; 667 } 668 ldap_pvt_close_socket(ld, s); 669 } 670 freeaddrinfo(res); 671 672#else 673 if (! inet_aton( host, &in ) ) { 674 int local_h_errno; 675 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, 676 &hp, &local_h_errno ); 677 678 if ( (rc < 0) || (hp == NULL) ) { 679#ifdef HAVE_WINSOCK 680 ldap_pvt_set_errno( WSAGetLastError() ); 681#else 682 /* not exactly right, but... */ 683 ldap_pvt_set_errno( EHOSTUNREACH ); 684#endif 685 if (ha_buf) LDAP_FREE(ha_buf); 686 return -1; 687 } 688 689 use_hp = 1; 690 } 691 692 rc = s = -1; 693 for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { 694 struct sockaddr_in sin; 695 696 s = ldap_int_socket( ld, PF_INET, socktype ); 697 if ( s == AC_SOCKET_INVALID ) { 698 /* use_hp ? continue : break; */ 699 break; 700 } 701 702 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { 703 ldap_pvt_close_socket(ld, s); 704 break; 705 } 706 707 (void)memset((char *)&sin, '\0', sizeof sin); 708 sin.sin_family = AF_INET; 709 sin.sin_port = htons((unsigned short) port); 710 711 if( use_hp ) { 712 AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], 713 sizeof(sin.sin_addr) ); 714 } else { 715 AC_MEMCPY( &sin.sin_addr, &in.s_addr, 716 sizeof(sin.sin_addr) ); 717 } 718 719#ifdef HAVE_INET_NTOA_B 720 { 721 /* for VxWorks */ 722 char address[INET_ADDR_LEN]; 723 inet_ntoa_b(sin.sin_address, address); 724 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 725 address, port, 0); 726 } 727#else 728 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 729 inet_ntoa(sin.sin_addr), port, 0); 730#endif 731 732 rc = ldap_pvt_connect(ld, s, 733 (struct sockaddr *)&sin, sizeof(sin), 734 async); 735 736 if ( (rc == 0) || (rc == -2) ) { 737 int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); 738 if ( err ) 739 rc = err; 740 else 741 break; 742 } 743 744 ldap_pvt_close_socket(ld, s); 745 746 if (!use_hp) break; 747 } 748 if (ha_buf) LDAP_FREE(ha_buf); 749#endif 750 751 return rc; 752} 753 754#if defined( HAVE_CYRUS_SASL ) 755char * 756ldap_host_connected_to( Sockbuf *sb, const char *host ) 757{ 758 ber_socklen_t len; 759#ifdef LDAP_PF_INET6 760 struct sockaddr_storage sabuf; 761#else 762 struct sockaddr sabuf; 763#endif 764 struct sockaddr *sa = (struct sockaddr *) &sabuf; 765 ber_socket_t sd; 766 767 (void)memset( (char *)sa, '\0', sizeof sabuf ); 768 len = sizeof sabuf; 769 770 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 771 if ( getpeername( sd, sa, &len ) == -1 ) { 772 return( NULL ); 773 } 774 775 /* 776 * do a reverse lookup on the addr to get the official hostname. 777 * this is necessary for kerberos to work right, since the official 778 * hostname is used as the kerberos instance. 779 */ 780 781 switch (sa->sa_family) { 782#ifdef LDAP_PF_LOCAL 783 case AF_LOCAL: 784 return LDAP_STRDUP( ldap_int_hostname ); 785#endif 786#ifdef LDAP_PF_INET6 787 case AF_INET6: 788 { 789 struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; 790 if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, 791 &localhost, sizeof(localhost)) == 0 ) 792 { 793 return LDAP_STRDUP( ldap_int_hostname ); 794 } 795 } 796 break; 797#endif 798 case AF_INET: 799 { 800 struct in_addr localhost; 801 localhost.s_addr = htonl( INADDR_ANY ); 802 803 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 804 &localhost, sizeof(localhost) ) == 0 ) 805 { 806 return LDAP_STRDUP( ldap_int_hostname ); 807 } 808 809#ifdef INADDR_LOOPBACK 810 localhost.s_addr = htonl( INADDR_LOOPBACK ); 811 812 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 813 &localhost, sizeof(localhost) ) == 0 ) 814 { 815 return LDAP_STRDUP( ldap_int_hostname ); 816 } 817#endif 818 } 819 break; 820 821 default: 822 return( NULL ); 823 break; 824 } 825 826 { 827 char *herr; 828#ifdef NI_MAXHOST 829 char hbuf[NI_MAXHOST]; 830#elif defined( MAXHOSTNAMELEN ) 831 char hbuf[MAXHOSTNAMELEN]; 832#else 833 char hbuf[256]; 834#endif 835 hbuf[0] = 0; 836 837 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 838 && hbuf[0] ) 839 { 840 return LDAP_STRDUP( hbuf ); 841 } 842 } 843 844 return host ? LDAP_STRDUP( host ) : NULL; 845} 846#endif 847 848 849struct selectinfo { 850#ifdef HAVE_POLL 851 /* for UNIX poll(2) */ 852 int si_maxfd; 853#ifdef __APPLE__ 854 int si_nfds; /* current # fds */ 855 int si_update_done; /* cond var predicate */ 856 int si_pipe_fds[2]; 857 int si_pipe_fd_idx_in_poll; 858#endif 859 struct pollfd si_fds[FD_SETSIZE]; 860#else 861 /* for UNIX select(2) */ 862 fd_set si_readfds; 863 fd_set si_writefds; 864 fd_set si_use_readfds; 865 fd_set si_use_writefds; 866#endif 867}; 868 869#ifdef __APPLE__ 870struct updatecmd { 871 int type; 872#define LDAP_SEL_UPDATE_READ 1 873#define LDAP_SEL_UPDATE_WRITE 2 874#define LDAP_SEL_UPDATE_CLEAR 3 875 876 ber_socket_t sd; 877}; 878 879static int ldap_int_mark_select_read( struct selectinfo *sip, ber_socket_t sd ); 880static int ldap_int_mark_select_write( struct selectinfo *sip, ber_socket_t sd ); 881static void ldap_int_mark_select_clear( struct selectinfo *sip, ber_socket_t sd ); 882 883static void 884ldap_int_queue_select_update( struct selectinfo *sip, ber_socket_t sd, int cmdtype ) 885{ 886 Debug( LDAP_DEBUG_ASYNC, "ldap_queue_select_update: sip = %p, sd = %d, cmdtype = %d\n", sip, (int)sd, cmdtype ); 887 888 /* Send the command to the select/poll thread. */ 889 struct updatecmd cmd = {cmdtype, sd}; 890 write( sip->si_pipe_fds[1], &cmd, sizeof(cmd) ); 891} 892 893static void 894ldap_int_handle_select_updates( struct selectinfo *sip ) 895{ 896 struct updatecmd cmd; 897 898 Debug( LDAP_DEBUG_ASYNC, "ldap_int_handle_select_updates: sip = %p\n", sip, 0, 0 ); 899 900 while ( read( sip->si_pipe_fds[0], &cmd, sizeof(cmd) ) == sizeof(cmd) ) { 901 902 Debug( LDAP_DEBUG_ASYNC, "ldap_int_handle_select_updates: sip = %p, cmd.sd = %d, cmd.type = %d\n", 903 sip, cmd.sd, cmd.type ); 904 905 switch ( cmd.type ) { 906 case LDAP_SEL_UPDATE_READ: 907 ldap_int_mark_select_read( sip, cmd.sd ); 908 break; 909 case LDAP_SEL_UPDATE_WRITE: 910 ldap_int_mark_select_write( sip, cmd.sd ); 911 break; 912 case LDAP_SEL_UPDATE_CLEAR: 913 ldap_int_mark_select_clear( sip, cmd.sd ); 914 break; 915 default: 916 break; 917 } 918 } 919} 920 921static int 922ldap_int_mark_select_write( struct selectinfo *sip, ber_socket_t sd ) 923{ 924#ifdef HAVE_POLL 925 /* for UNIX poll(2) */ 926 { 927 Debug( LDAP_DEBUG_ASYNC, "ldap_int_mark_select_write: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 928 929 int empty=-1; 930 int i; 931 for(i=0; i < sip->si_maxfd; i++) { 932 if( sip->si_fds[i].fd == sd ) { 933 sip->si_fds[i].events |= POLL_WRITE; 934 return i; 935 } 936 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 937 empty=i; 938 } 939 } 940 941 if( empty == -1 ) { 942 if( sip->si_maxfd >= FD_SETSIZE ) { 943 /* FIXME */ 944 return -1; 945 } 946 empty = sip->si_maxfd++; 947 } 948 949 sip->si_fds[empty].fd = sd; 950 sip->si_fds[empty].events = POLL_WRITE; 951 sip->si_nfds++; 952 return empty; 953 } 954#else 955 /* for UNIX select(2) */ 956 if ( !FD_ISSET( sd, &sip->si_writefds )) { 957 FD_SET( sd, &sip->si_writefds ); 958 } 959#endif 960} 961 962static int 963ldap_int_mark_select_read( struct selectinfo *sip, ber_socket_t sd ) 964{ 965#ifdef HAVE_POLL 966 /* for UNIX poll(2) */ 967 { 968 Debug( LDAP_DEBUG_ASYNC, "ldap_int_mark_select_read: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 969 970 int empty=-1; 971 int i; 972 for(i=0; i < sip->si_maxfd; i++) { 973 if( sip->si_fds[i].fd == sd ) { 974 sip->si_fds[i].events |= POLL_READ; 975 return i; 976 } 977 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 978 empty=i; 979 } 980 } 981 982 if( empty == -1 ) { 983 if( sip->si_maxfd >= FD_SETSIZE ) { 984 /* FIXME */ 985 return -1; 986 } 987 empty = sip->si_maxfd++; 988 } 989 990 sip->si_fds[empty].fd = sd; 991 sip->si_fds[empty].events = POLL_READ; 992 sip->si_nfds++; 993 return empty; 994 995 } 996#else 997 /* for UNIX select(2) */ 998 if ( !FD_ISSET( sd, &sip->si_readfds )) { 999 FD_SET( sd, &sip->si_readfds ); 1000 } 1001#endif 1002} 1003 1004static void 1005ldap_int_mark_select_clear( struct selectinfo *sip, ber_socket_t sd ) 1006{ 1007#ifdef HAVE_POLL 1008 /* for UNIX poll(2) */ 1009 { 1010 Debug( LDAP_DEBUG_ASYNC, "ldap_int_mark_select_clear: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 1011 1012 int i; 1013 for(i=0; i < sip->si_maxfd; i++) { 1014 if( sip->si_fds[i].fd == sd ) { 1015 sip->si_fds[i].fd = -1; 1016 sip->si_nfds--; 1017 } 1018 } 1019 } 1020#else 1021 /* for UNIX select(2) */ 1022 FD_CLR( sd, &sip->si_writefds ); 1023 FD_CLR( sd, &sip->si_readfds ); 1024#endif 1025} 1026 1027#endif /*__APPLE__*/ 1028void 1029ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) 1030{ 1031 struct selectinfo *sip; 1032 ber_socket_t sd; 1033 1034 sip = (struct selectinfo *)ld->ld_selectinfo; 1035 1036 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1037 1038#ifdef __APPLE__ 1039 Debug( LDAP_DEBUG_ASYNC, "ldap_mark_select_write: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 1040 1041 if ( LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_ASYNC_RESULTS ) ) { 1042 ldap_int_queue_select_update( sip, sd, LDAP_SEL_UPDATE_WRITE ); 1043 } 1044 else { 1045 ldap_int_mark_select_write( sip, sd ); 1046 } 1047#else 1048#ifdef HAVE_POLL 1049 /* for UNIX poll(2) */ 1050 { 1051 int empty=-1; 1052 int i; 1053 for(i=0; i < sip->si_maxfd; i++) { 1054 if( sip->si_fds[i].fd == sd ) { 1055 sip->si_fds[i].events |= POLL_WRITE; 1056 return; 1057 } 1058 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 1059 empty=i; 1060 } 1061 } 1062 1063 if( empty == -1 ) { 1064 if( sip->si_maxfd >= FD_SETSIZE ) { 1065 /* FIXME */ 1066 return; 1067 } 1068 empty = sip->si_maxfd++; 1069 } 1070 1071 sip->si_fds[empty].fd = sd; 1072 sip->si_fds[empty].events = POLL_WRITE; 1073 } 1074#else 1075 /* for UNIX select(2) */ 1076 if ( !FD_ISSET( sd, &sip->si_writefds )) { 1077 FD_SET( sd, &sip->si_writefds ); 1078 } 1079#endif 1080#endif /*__APPLE__*/ 1081} 1082 1083 1084void 1085ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) 1086{ 1087 struct selectinfo *sip; 1088 ber_socket_t sd; 1089 1090 sip = (struct selectinfo *)ld->ld_selectinfo; 1091 1092 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1093#ifdef __APPLE__ 1094 Debug( LDAP_DEBUG_ASYNC, "ldap_mark_select_read: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 1095 1096 if ( LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_ASYNC_RESULTS ) ) { 1097 ldap_int_queue_select_update( sip, sd, LDAP_SEL_UPDATE_READ ); 1098 } 1099 else { 1100 ldap_int_mark_select_read( sip, sd ); 1101 } 1102#else 1103#ifdef HAVE_POLL 1104 /* for UNIX poll(2) */ 1105 { 1106 int empty=-1; 1107 int i; 1108 for(i=0; i < sip->si_maxfd; i++) { 1109 if( sip->si_fds[i].fd == sd ) { 1110 sip->si_fds[i].events |= POLL_READ; 1111 return; 1112 } 1113 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 1114 empty=i; 1115 } 1116 } 1117 1118 if( empty == -1 ) { 1119 if( sip->si_maxfd >= FD_SETSIZE ) { 1120 /* FIXME */ 1121 return; 1122 } 1123 empty = sip->si_maxfd++; 1124 } 1125 1126 sip->si_fds[empty].fd = sd; 1127 sip->si_fds[empty].events = POLL_READ; 1128 } 1129#else 1130 /* for UNIX select(2) */ 1131 if ( !FD_ISSET( sd, &sip->si_readfds )) { 1132 FD_SET( sd, &sip->si_readfds ); 1133 } 1134#endif 1135#endif /*__APPLE__*/ 1136} 1137 1138 1139void 1140ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) 1141{ 1142 struct selectinfo *sip; 1143 ber_socket_t sd; 1144 1145 sip = (struct selectinfo *)ld->ld_selectinfo; 1146 1147 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1148#ifdef __APPLE__ 1149 Debug( LDAP_DEBUG_ASYNC, "ldap_mark_select_clear: sip = %p, sd = %d\n", sip, (int)sd, 0 ); 1150 1151 if ( LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_ASYNC_RESULTS ) ) { 1152 ldap_int_queue_select_update( sip, sd, LDAP_SEL_UPDATE_CLEAR ); 1153 } 1154 else { 1155 ldap_int_mark_select_clear( sip, sd ); 1156 } 1157#else 1158#ifdef HAVE_POLL 1159 /* for UNIX poll(2) */ 1160 { 1161 int i; 1162 for(i=0; i < sip->si_maxfd; i++) { 1163 if( sip->si_fds[i].fd == sd ) { 1164 sip->si_fds[i].fd = -1; 1165 } 1166 } 1167 } 1168#else 1169 /* for UNIX select(2) */ 1170 FD_CLR( sd, &sip->si_writefds ); 1171 FD_CLR( sd, &sip->si_readfds ); 1172#endif 1173#endif /*__APPLE__*/ 1174} 1175 1176 1177int 1178ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) 1179{ 1180 struct selectinfo *sip; 1181 ber_socket_t sd; 1182 1183 sip = (struct selectinfo *)ld->ld_selectinfo; 1184 1185 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1186 1187#ifdef HAVE_POLL 1188 /* for UNIX poll(2) */ 1189 { 1190 int i; 1191 for(i=0; i < sip->si_maxfd; i++) { 1192 if( sip->si_fds[i].fd == sd ) { 1193 return sip->si_fds[i].revents & POLL_WRITE; 1194 } 1195 } 1196 1197 return 0; 1198 } 1199#else 1200 /* for UNIX select(2) */ 1201 return( FD_ISSET( sd, &sip->si_use_writefds )); 1202#endif 1203} 1204 1205 1206int 1207ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) 1208{ 1209 struct selectinfo *sip; 1210 ber_socket_t sd; 1211 1212 sip = (struct selectinfo *)ld->ld_selectinfo; 1213 1214 if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) 1215 return 1; 1216 1217 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1218 1219#ifdef HAVE_POLL 1220 /* for UNIX poll(2) */ 1221 { 1222 int i; 1223 for(i=0; i < sip->si_maxfd; i++) { 1224 if( sip->si_fds[i].fd == sd ) { 1225 return sip->si_fds[i].revents & POLL_READ; 1226 } 1227 } 1228 1229 return 0; 1230 } 1231#else 1232 /* for UNIX select(2) */ 1233 return( FD_ISSET( sd, &sip->si_use_readfds )); 1234#endif 1235} 1236 1237 1238#ifdef __APPLE__ 1239void 1240ldap_pvt_open_select_pipe( LDAP* ld ) 1241{ 1242 struct selectinfo *sip; 1243 1244 assert( ld != NULL ); 1245 1246 sip = (struct selectinfo *)ld->ld_selectinfo; 1247 assert( sip != NULL ); 1248 1249 Debug( LDAP_DEBUG_ASYNC, "ldap_pvt_open_select_pipe: sip = %p\n", sip, 0, 0 ); 1250 1251 int rc = pipe( sip->si_pipe_fds ); 1252 assert( rc == 0 ); 1253 1254 /* Put the read end of the pipe in non-blocking mode so we can handle 1255 * mutliple updates by reading until we get EWOULDBLOCK. 1256 */ 1257 int flags = fcntl( sip->si_pipe_fds[0], F_GETFL, 0 ); 1258 if (flags == -1 ) flags = 0; 1259 rc = fcntl( sip->si_pipe_fds[0], F_SETFL, flags | O_NONBLOCK ); 1260 assert ( rc == 0 ); 1261 1262 /* Add the read end of the pipe to the pollfds */ 1263 sip->si_pipe_fd_idx_in_poll = ldap_int_mark_select_read(sip, sip->si_pipe_fds[0]); 1264 assert( sip->si_pipe_fd_idx_in_poll != -1 ); 1265 1266 Debug( LDAP_DEBUG_ASYNC, "ldap_pvt_open_select_pipe: write pipe = %d read pipe = %d, idx in poll = %d\n", 1267 sip->si_pipe_fds[1], sip->si_pipe_fds[0], sip->si_pipe_fd_idx_in_poll ); 1268} 1269 1270void 1271ldap_pvt_close_select_pipe( LDAP* ld ) 1272{ 1273 struct selectinfo *sip; 1274 1275 assert( ld != NULL ); 1276 1277 sip = (struct selectinfo *)ld->ld_selectinfo; 1278 assert( sip != NULL ); 1279 1280 Debug( LDAP_DEBUG_ASYNC, "ldap_pvt_close_select_pipe: sip = %p\n", sip, 0, 0 ); 1281 1282 if ( sip->si_pipe_fds[0] != -1 ) { 1283 /* Need to queue the update so it's handled by the thread that's 1284 * running ldap_int_select(). 1285 */ 1286 ldap_int_queue_select_update( sip, sip->si_pipe_fds[0], LDAP_SEL_UPDATE_CLEAR ); 1287 } 1288} 1289 1290void 1291ldap_int_close_select_pipe( struct selectinfo* sip ) 1292{ 1293 assert( sip != NULL ); 1294 1295 Debug( LDAP_DEBUG_ASYNC, "ldap_int_close_select_pipe: sip = %p, write pipe = %d, read pipe = %d\n", 1296 sip, sip->si_pipe_fds[1], sip->si_pipe_fds[0] ); 1297 1298 if ( sip->si_pipe_fds[0] != -1 ) { 1299 close( sip->si_pipe_fds[0] ); 1300 sip->si_pipe_fds[0] = -1; 1301 } 1302 1303 if ( sip->si_pipe_fds[1] != -1 ) { 1304 close( sip->si_pipe_fds[1] ); 1305 sip->si_pipe_fds[1] = -1; 1306 } 1307} 1308 1309#endif /* __APPLE__ */ 1310 1311void * 1312ldap_new_select_info( void ) 1313{ 1314 struct selectinfo *sip; 1315 1316 sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); 1317 1318 if ( sip == NULL ) return NULL; 1319 1320#ifdef HAVE_POLL 1321 /* for UNIX poll(2) */ 1322 /* sip->si_maxfd=0 */ 1323#ifdef __APPLE__ 1324 sip->si_pipe_fds[0] = -1; 1325 sip->si_pipe_fds[1] = -1; 1326 sip->si_pipe_fd_idx_in_poll = -1; 1327#endif 1328#else 1329 /* for UNIX select(2) */ 1330 FD_ZERO( &sip->si_readfds ); 1331 FD_ZERO( &sip->si_writefds ); 1332#endif 1333 1334 return( (void *)sip ); 1335} 1336 1337 1338void 1339ldap_free_select_info( void *sip ) 1340{ 1341 LDAP_FREE( sip ); 1342} 1343 1344 1345#ifndef HAVE_POLL 1346int ldap_int_tblsize = 0; 1347 1348void 1349ldap_int_ip_init( void ) 1350{ 1351#if defined( HAVE_SYSCONF ) 1352 long tblsize = sysconf( _SC_OPEN_MAX ); 1353 if( tblsize > INT_MAX ) tblsize = INT_MAX; 1354 1355#elif defined( HAVE_GETDTABLESIZE ) 1356 int tblsize = getdtablesize(); 1357#else 1358 int tblsize = FD_SETSIZE; 1359#endif /* !USE_SYSCONF */ 1360 1361#ifdef FD_SETSIZE 1362 if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; 1363#endif /* FD_SETSIZE */ 1364 1365 ldap_int_tblsize = tblsize; 1366} 1367#endif 1368 1369 1370int 1371ldap_int_select( LDAP *ld, struct timeval *timeout ) 1372{ 1373 int rc; 1374 struct selectinfo *sip; 1375 1376 Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 ); 1377 1378#ifndef HAVE_POLL 1379 if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); 1380#endif 1381 1382 sip = (struct selectinfo *)ld->ld_selectinfo; 1383 assert( sip != NULL ); 1384 1385#ifdef HAVE_POLL 1386 { 1387#ifdef __APPLE__ 1388 1389 tryagain: 1390 1391 if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_ASYNC_RESULTS)) { 1392 1393 /* Clear any fd's that got an error last time. If we 1394 * don't we'll just spin. 1395 */ 1396 int i; 1397 for ( i = 0; i < sip->si_maxfd; i++ ) { 1398 if ( sip->si_fds[i].revents & (POLLERR|POLLHUP|POLLNVAL) ) { 1399 ldap_int_mark_select_clear( sip, sip->si_fds[i].fd ); 1400 } 1401 } 1402 1403 /* If there are no fds left don't call poll(2). No fds and an 1404 * infinite timeout will result in a hang. 1405 * If there are still fds, but we're no longer watching the 1406 * pipe, that's another good reason to bail. 1407 */ 1408 if ( sip->si_nfds == 0 || sip->si_fds[sip->si_pipe_fd_idx_in_poll].fd == -1 ) { 1409 Debug( LDAP_DEBUG_ASYNC, "ldap_int_select: %s\n", 1410 sip->si_nfds == 0 ? "no fds being watched" : "pipe not being watched", 1411 0, 0 ); 1412 1413 /* If we're not even watching the select pipe, then 1414 * close it. We're going to return an errno that will 1415 * cause the async thread to exit anyway. 1416 */ 1417 ldap_int_close_select_pipe( sip ); 1418 1419 errno = EPIPE; 1420 return -1; 1421 } 1422 } 1423 1424 /* There are still fds being watched... */ 1425#endif 1426 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; 1427 rc = poll( sip->si_fds, sip->si_maxfd, to ); 1428 1429#ifdef __APPLE__ 1430 if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_ASYNC_RESULTS) ) { 1431 if ( rc > 0 ) 1432 { 1433 /* Handle updates on the pipe. If it's the only 1434 * activity, then go back to the top. 1435 */ 1436 if ( sip->si_fds[sip->si_pipe_fd_idx_in_poll].revents & POLLIN ) { 1437 ldap_int_handle_select_updates( sip ); 1438 if ( rc == 1 ) { 1439 goto tryagain; 1440 } 1441 } 1442 } 1443 } 1444#endif /* __APPLE__ */ 1445 } 1446#else 1447 sip->si_use_readfds = sip->si_readfds; 1448 sip->si_use_writefds = sip->si_writefds; 1449 1450 rc = select( ldap_int_tblsize, 1451 &sip->si_use_readfds, &sip->si_use_writefds, 1452 NULL, timeout ); 1453#endif 1454 1455 return rc; 1456} 1457