1 /* $NetBSD: os-ip.c,v 1.6 2014/05/28 10:12:43 tron Exp $ */ 2 3 /* os-ip.c -- platform-specific TCP & UDP related code */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2014 The OpenLDAP Foundation. 8 * Portions Copyright 1999 Lars Uffmann. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 20 * All rights reserved. 21 */ 22 /* Significant additional contributors include: 23 * Lars Uffman 24 */ 25 26 #include "portable.h" 27 28 #include <stdio.h> 29 30 #include <ac/stdlib.h> 31 32 #include <ac/errno.h> 33 #include <ac/socket.h> 34 #include <ac/string.h> 35 #include <ac/time.h> 36 #include <ac/unistd.h> 37 38 #ifdef HAVE_IO_H 39 #include <io.h> 40 #endif /* HAVE_IO_H */ 41 #ifdef HAVE_FCNTL_H 42 #include <fcntl.h> 43 #endif 44 45 #include "ldap-int.h" 46 47 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 48 # ifdef LDAP_PF_INET6 49 int ldap_int_inet4or6 = AF_UNSPEC; 50 # else 51 int ldap_int_inet4or6 = AF_INET; 52 # endif 53 #endif 54 55 #ifdef LDAP_DEBUG 56 57 #define osip_debug(ld,fmt,arg1,arg2,arg3) \ 58 do { \ 59 ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ 60 } while(0) 61 62 #else 63 64 #define osip_debug(ld,fmt,arg1,arg2,arg3) ((void)0) 65 66 #endif /* LDAP_DEBUG */ 67 68 static void 69 ldap_pvt_set_errno(int err) 70 { 71 sock_errset(err); 72 } 73 74 int 75 ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src ) 76 { 77 struct timeval *new; 78 79 assert( dest != NULL ); 80 81 if (src == NULL) { 82 *dest = NULL; 83 return 0; 84 } 85 86 new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval)); 87 88 if( new == NULL ) { 89 *dest = NULL; 90 return 1; 91 } 92 93 AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval)); 94 95 *dest = new; 96 return 0; 97 } 98 99 static int 100 ldap_pvt_ndelay_on(LDAP *ld, int fd) 101 { 102 osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0); 103 return ber_pvt_socket_set_nonblock( fd, 1 ); 104 } 105 106 static int 107 ldap_pvt_ndelay_off(LDAP *ld, int fd) 108 { 109 osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0); 110 return ber_pvt_socket_set_nonblock( fd, 0 ); 111 } 112 113 static ber_socket_t 114 ldap_int_socket(LDAP *ld, int family, int type ) 115 { 116 ber_socket_t s = socket(family, type, 0); 117 osip_debug(ld, "ldap_new_socket: %d\n",s,0,0); 118 #ifdef FD_CLOEXEC 119 fcntl(s, F_SETFD, FD_CLOEXEC); 120 #endif 121 return ( s ); 122 } 123 124 static int 125 ldap_pvt_close_socket(LDAP *ld, int s) 126 { 127 osip_debug(ld, "ldap_close_socket: %d\n",s,0,0); 128 return tcp_close(s); 129 } 130 131 static int 132 ldap_int_prepare_socket(LDAP *ld, int s, int proto ) 133 { 134 osip_debug( ld, "ldap_prepare_socket: %d\n", s, 0, 0 ); 135 136 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) 137 if ( proto == LDAP_PROTO_TCP ) { 138 int dummy = 1; 139 #ifdef SO_KEEPALIVE 140 if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, 141 (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) 142 { 143 osip_debug( ld, "ldap_prepare_socket: " 144 "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n", 145 s, 0, 0 ); 146 } 147 if ( ld->ld_options.ldo_keepalive_idle > 0 ) 148 { 149 #ifdef TCP_KEEPIDLE 150 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE, 151 (void*) &ld->ld_options.ldo_keepalive_idle, 152 sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR ) 153 { 154 osip_debug( ld, "ldap_prepare_socket: " 155 "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n", 156 s, 0, 0 ); 157 } 158 #else 159 osip_debug( ld, "ldap_prepare_socket: " 160 "sockopt TCP_KEEPIDLE not supported on this system.\n", 161 0, 0, 0 ); 162 #endif /* TCP_KEEPIDLE */ 163 } 164 if ( ld->ld_options.ldo_keepalive_probes > 0 ) 165 { 166 #ifdef TCP_KEEPCNT 167 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT, 168 (void*) &ld->ld_options.ldo_keepalive_probes, 169 sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR ) 170 { 171 osip_debug( ld, "ldap_prepare_socket: " 172 "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n", 173 s, 0, 0 ); 174 } 175 #else 176 osip_debug( ld, "ldap_prepare_socket: " 177 "sockopt TCP_KEEPCNT not supported on this system.\n", 178 0, 0, 0 ); 179 #endif /* TCP_KEEPCNT */ 180 } 181 if ( ld->ld_options.ldo_keepalive_interval > 0 ) 182 { 183 #ifdef TCP_KEEPINTVL 184 if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL, 185 (void*) &ld->ld_options.ldo_keepalive_interval, 186 sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR ) 187 { 188 osip_debug( ld, "ldap_prepare_socket: " 189 "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n", 190 s, 0, 0 ); 191 } 192 #else 193 osip_debug( ld, "ldap_prepare_socket: " 194 "sockopt TCP_KEEPINTVL not supported on this system.\n", 195 0, 0, 0 ); 196 #endif /* TCP_KEEPINTVL */ 197 } 198 #endif /* SO_KEEPALIVE */ 199 #ifdef TCP_NODELAY 200 if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, 201 (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) 202 { 203 osip_debug( ld, "ldap_prepare_socket: " 204 "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", 205 s, 0, 0 ); 206 } 207 #endif /* TCP_NODELAY */ 208 } 209 #endif /* SO_KEEPALIVE || TCP_NODELAY */ 210 211 return 0; 212 } 213 214 #ifndef HAVE_WINSOCK 215 216 #undef TRACE 217 #define TRACE do { \ 218 osip_debug(ld, \ 219 "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \ 220 s, \ 221 errno, \ 222 sock_errstr(errno) ); \ 223 } while( 0 ) 224 225 /* 226 * check the socket for errors after select returned. 227 */ 228 static int 229 ldap_pvt_is_socket_ready(LDAP *ld, int s) 230 { 231 osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0); 232 233 #if defined( notyet ) /* && defined( SO_ERROR ) */ 234 { 235 int so_errno; 236 ber_socklen_t dummy = sizeof(so_errno); 237 if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) 238 == AC_SOCKET_ERROR ) 239 { 240 return -1; 241 } 242 if ( so_errno ) { 243 ldap_pvt_set_errno(so_errno); 244 TRACE; 245 return -1; 246 } 247 return 0; 248 } 249 #else 250 { 251 /* error slippery */ 252 #ifdef LDAP_PF_INET6 253 struct sockaddr_storage sin; 254 #else 255 struct sockaddr_in sin; 256 #endif 257 char ch; 258 ber_socklen_t dummy = sizeof(sin); 259 if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) 260 == AC_SOCKET_ERROR ) 261 { 262 /* XXX: needs to be replace with ber_stream_read() */ 263 (void)read(s, &ch, 1); 264 TRACE; 265 return -1; 266 } 267 return 0; 268 } 269 #endif 270 return -1; 271 } 272 #undef TRACE 273 274 #endif /* HAVE_WINSOCK */ 275 276 /* NOTE: this is identical to analogous code in os-local.c */ 277 int 278 ldap_int_poll( 279 LDAP *ld, 280 ber_socket_t s, 281 struct timeval *tvp, 282 int wr ) 283 { 284 int rc; 285 286 287 osip_debug(ld, "ldap_int_poll: fd: %d tm: %jd\n", 288 s, tvp ? (intmax_t)tvp->tv_sec : -1, 0); 289 290 #ifdef HAVE_POLL 291 { 292 struct pollfd fd; 293 int timeout = INFTIM; 294 short event = wr ? POLL_WRITE : POLL_READ; 295 296 fd.fd = s; 297 fd.events = event; 298 299 if ( tvp != NULL ) { 300 timeout = TV2MILLISEC( tvp ); 301 } 302 do { 303 fd.revents = 0; 304 rc = poll( &fd, 1, timeout ); 305 306 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 307 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 308 309 if ( rc == AC_SOCKET_ERROR ) { 310 return rc; 311 } 312 313 if ( timeout == 0 && rc == 0 ) { 314 return -2; 315 } 316 317 if ( fd.revents & event ) { 318 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 319 return -1; 320 } 321 322 if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) { 323 return -1; 324 } 325 return 0; 326 } 327 } 328 #else 329 { 330 fd_set wfds, *z = NULL; 331 #ifdef HAVE_WINSOCK 332 fd_set efds; 333 #endif 334 struct timeval tv = { 0 }; 335 336 #if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK ) 337 if ( s >= FD_SETSIZE ) { 338 rc = AC_SOCKET_ERROR; 339 tcp_close( s ); 340 ldap_pvt_set_errno( EMFILE ); 341 return rc; 342 } 343 #endif 344 345 if ( tvp != NULL ) { 346 tv = *tvp; 347 } 348 349 do { 350 FD_ZERO(&wfds); 351 FD_SET(s, &wfds ); 352 353 #ifdef HAVE_WINSOCK 354 FD_ZERO(&efds); 355 FD_SET(s, &efds ); 356 #endif 357 358 rc = select( ldap_int_tblsize, z, &wfds, 359 #ifdef HAVE_WINSOCK 360 &efds, 361 #else 362 z, 363 #endif 364 tvp ? &tv : NULL ); 365 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 366 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 367 368 if ( rc == AC_SOCKET_ERROR ) { 369 return rc; 370 } 371 372 if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) { 373 return -2; 374 } 375 376 #ifdef HAVE_WINSOCK 377 /* This means the connection failed */ 378 if ( FD_ISSET(s, &efds) ) { 379 int so_errno; 380 ber_socklen_t dummy = sizeof(so_errno); 381 if ( getsockopt( s, SOL_SOCKET, SO_ERROR, 382 (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno ) 383 { 384 /* impossible */ 385 so_errno = WSAGetLastError(); 386 } 387 ldap_pvt_set_errno( so_errno ); 388 osip_debug(ld, "ldap_int_poll: error on socket %d: " 389 "errno: %d (%s)\n", s, errno, sock_errstr( errno )); 390 return -1; 391 } 392 #endif 393 if ( FD_ISSET(s, &wfds) ) { 394 #ifndef HAVE_WINSOCK 395 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 396 return -1; 397 } 398 #endif 399 if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { 400 return -1; 401 } 402 return 0; 403 } 404 } 405 #endif 406 407 osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0); 408 ldap_pvt_set_errno( ETIMEDOUT ); 409 return -1; 410 } 411 412 static int 413 ldap_pvt_connect(LDAP *ld, ber_socket_t s, 414 struct sockaddr *sin, ber_socklen_t addrlen, 415 int async) 416 { 417 int rc, err; 418 struct timeval tv, *opt_tv = NULL; 419 420 #ifdef LDAP_CONNECTIONLESS 421 /* We could do a connect() but that would interfere with 422 * attempts to poll a broadcast address 423 */ 424 if (LDAP_IS_UDP(ld)) { 425 if (ld->ld_options.ldo_peer) 426 ldap_memfree(ld->ld_options.ldo_peer); 427 ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage)); 428 AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen); 429 return ( 0 ); 430 } 431 #endif 432 if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { 433 tv = ld->ld_options.ldo_tm_net; 434 opt_tv = &tv; 435 } 436 437 osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %jd async: %d\n", 438 s, opt_tv ? (intmax_t)tv.tv_sec : -1, async); 439 440 if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 ) 441 return ( -1 ); 442 443 do{ 444 osip_debug(ld, "attempting to connect: \n", 0, 0, 0); 445 if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { 446 osip_debug(ld, "connect success\n", 0, 0, 0); 447 448 if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) 449 return ( -1 ); 450 return ( 0 ); 451 } 452 err = sock_errno(); 453 osip_debug(ld, "connect errno: %d\n", err, 0, 0); 454 455 } while(err == EINTR && 456 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART )); 457 458 if ( err != EINPROGRESS && err != EWOULDBLOCK ) { 459 return ( -1 ); 460 } 461 462 if ( async ) { 463 /* caller will call ldap_int_poll() as appropriate? */ 464 return ( -2 ); 465 } 466 467 rc = ldap_int_poll( ld, s, opt_tv, 1 ); 468 469 osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0); 470 471 return rc; 472 } 473 474 #ifndef HAVE_INET_ATON 475 int 476 ldap_pvt_inet_aton( const char *host, struct in_addr *in) 477 { 478 unsigned long u = inet_addr( host ); 479 480 #ifdef INADDR_NONE 481 if ( u == INADDR_NONE ) return 0; 482 #endif 483 if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0; 484 485 in->s_addr = u; 486 return 1; 487 } 488 #endif 489 490 int 491 ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr) 492 { 493 struct ldapoptions *lo; 494 ldaplist *ll; 495 ldap_conncb *cb; 496 int rc; 497 498 ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); 499 500 /* Invoke all handle-specific callbacks first */ 501 lo = &ld->ld_options; 502 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 503 cb = ll->ll_data; 504 rc = cb->lc_add( ld, sb, srv, addr, cb ); 505 /* on any failure, call the teardown functions for anything 506 * that previously succeeded 507 */ 508 if ( rc ) { 509 ldaplist *l2; 510 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 511 cb = l2->ll_data; 512 cb->lc_del( ld, sb, cb ); 513 } 514 /* a failure might have implicitly closed the fd */ 515 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 516 return rc; 517 } 518 } 519 lo = LDAP_INT_GLOBAL_OPT(); 520 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 521 cb = ll->ll_data; 522 rc = cb->lc_add( ld, sb, srv, addr, cb ); 523 if ( rc ) { 524 ldaplist *l2; 525 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 526 cb = l2->ll_data; 527 cb->lc_del( ld, sb, cb ); 528 } 529 lo = &ld->ld_options; 530 for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { 531 cb = l2->ll_data; 532 cb->lc_del( ld, sb, cb ); 533 } 534 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 535 return rc; 536 } 537 } 538 return 0; 539 } 540 541 int 542 ldap_connect_to_host(LDAP *ld, Sockbuf *sb, 543 int proto, LDAPURLDesc *srv, 544 int async ) 545 { 546 int rc; 547 int socktype, port; 548 ber_socket_t s = AC_SOCKET_INVALID; 549 char *host; 550 551 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 552 char serv[7]; 553 int err; 554 struct addrinfo hints, *res, *sai; 555 #else 556 int i; 557 int use_hp = 0; 558 struct hostent *hp = NULL; 559 struct hostent he_buf; 560 struct in_addr in; 561 char *ha_buf=NULL; 562 #endif 563 564 if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { 565 host = "localhost"; 566 } else { 567 host = srv->lud_host; 568 } 569 570 port = srv->lud_port; 571 572 if( !port ) { 573 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { 574 port = LDAPS_PORT; 575 } else { 576 port = LDAP_PORT; 577 } 578 } 579 580 switch(proto) { 581 case LDAP_PROTO_TCP: socktype = SOCK_STREAM; 582 osip_debug( ld, 583 "ldap_connect_to_host: TCP %s:%d\n", 584 host, port, 0); 585 break; 586 case LDAP_PROTO_UDP: socktype = SOCK_DGRAM; 587 osip_debug( ld, 588 "ldap_connect_to_host: UDP %s:%d\n", 589 host, port, 0); 590 break; 591 default: 592 osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n", 593 proto, 0, 0 ); 594 return -1; 595 } 596 597 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 598 memset( &hints, '\0', sizeof(hints) ); 599 #ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */ 600 /* Use AI_ADDRCONFIG only on systems where its known to be needed. */ 601 hints.ai_flags = AI_ADDRCONFIG; 602 #endif 603 hints.ai_family = ldap_int_inet4or6; 604 hints.ai_socktype = socktype; 605 snprintf(serv, sizeof serv, "%d", port ); 606 607 /* most getaddrinfo(3) use non-threadsafe resolver libraries */ 608 LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex); 609 610 err = getaddrinfo( host, serv, &hints, &res ); 611 612 LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex); 613 614 if ( err != 0 ) { 615 osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n", 616 AC_GAI_STRERROR(err), 0, 0); 617 return -1; 618 } 619 rc = -1; 620 621 for( sai=res; sai != NULL; sai=sai->ai_next) { 622 if( sai->ai_addr == NULL ) { 623 osip_debug(ld, "ldap_connect_to_host: getaddrinfo " 624 "ai_addr is NULL?\n", 0, 0, 0); 625 continue; 626 } 627 628 /* we assume AF_x and PF_x are equal for all x */ 629 s = ldap_int_socket( ld, sai->ai_family, socktype ); 630 if ( s == AC_SOCKET_INVALID ) { 631 continue; 632 } 633 634 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { 635 ldap_pvt_close_socket(ld, s); 636 break; 637 } 638 639 switch (sai->ai_family) { 640 #ifdef LDAP_PF_INET6 641 case AF_INET6: { 642 char addr[INET6_ADDRSTRLEN]; 643 inet_ntop( AF_INET6, 644 &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, 645 addr, sizeof addr); 646 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 647 addr, serv, 0); 648 } break; 649 #endif 650 case AF_INET: { 651 char addr[INET_ADDRSTRLEN]; 652 inet_ntop( AF_INET, 653 &((struct sockaddr_in *)sai->ai_addr)->sin_addr, 654 addr, sizeof addr); 655 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 656 addr, serv, 0); 657 } break; 658 } 659 660 rc = ldap_pvt_connect( ld, s, 661 sai->ai_addr, sai->ai_addrlen, async ); 662 if ( rc == 0 || rc == -2 ) { 663 err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); 664 if ( err ) 665 rc = err; 666 else 667 break; 668 } 669 ldap_pvt_close_socket(ld, s); 670 } 671 freeaddrinfo(res); 672 673 #else 674 if (! inet_aton( host, &in ) ) { 675 int local_h_errno; 676 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, 677 &hp, &local_h_errno ); 678 679 if ( (rc < 0) || (hp == NULL) ) { 680 #ifdef HAVE_WINSOCK 681 ldap_pvt_set_errno( WSAGetLastError() ); 682 #else 683 /* not exactly right, but... */ 684 ldap_pvt_set_errno( EHOSTUNREACH ); 685 #endif 686 if (ha_buf) LDAP_FREE(ha_buf); 687 return -1; 688 } 689 690 use_hp = 1; 691 } 692 693 rc = s = -1; 694 for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { 695 struct sockaddr_in sin; 696 697 s = ldap_int_socket( ld, PF_INET, socktype ); 698 if ( s == AC_SOCKET_INVALID ) { 699 /* use_hp ? continue : break; */ 700 break; 701 } 702 703 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { 704 ldap_pvt_close_socket(ld, s); 705 break; 706 } 707 708 (void)memset((char *)&sin, '\0', sizeof sin); 709 sin.sin_family = AF_INET; 710 sin.sin_port = htons((unsigned short) port); 711 712 if( use_hp ) { 713 AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], 714 sizeof(sin.sin_addr) ); 715 } else { 716 AC_MEMCPY( &sin.sin_addr, &in.s_addr, 717 sizeof(sin.sin_addr) ); 718 } 719 720 #ifdef HAVE_INET_NTOA_B 721 { 722 /* for VxWorks */ 723 char address[INET_ADDR_LEN]; 724 inet_ntoa_b(sin.sin_address, address); 725 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 726 address, port, 0); 727 } 728 #else 729 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 730 inet_ntoa(sin.sin_addr), port, 0); 731 #endif 732 733 rc = ldap_pvt_connect(ld, s, 734 (struct sockaddr *)&sin, sizeof(sin), 735 async); 736 737 if ( (rc == 0) || (rc == -2) ) { 738 int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); 739 if ( err ) 740 rc = err; 741 else 742 break; 743 } 744 745 ldap_pvt_close_socket(ld, s); 746 747 if (!use_hp) break; 748 } 749 if (ha_buf) LDAP_FREE(ha_buf); 750 #endif 751 752 return rc; 753 } 754 755 #if defined( HAVE_CYRUS_SASL ) 756 char * 757 ldap_host_connected_to( Sockbuf *sb, const char *host ) 758 { 759 ber_socklen_t len; 760 #ifdef LDAP_PF_INET6 761 struct sockaddr_storage sabuf; 762 #else 763 struct sockaddr sabuf; 764 #endif 765 struct sockaddr *sa = (struct sockaddr *) &sabuf; 766 ber_socket_t sd; 767 768 (void)memset( (char *)sa, '\0', sizeof sabuf ); 769 len = sizeof sabuf; 770 771 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 772 if ( getpeername( sd, sa, &len ) == -1 ) { 773 return( NULL ); 774 } 775 776 /* 777 * do a reverse lookup on the addr to get the official hostname. 778 * this is necessary for kerberos to work right, since the official 779 * hostname is used as the kerberos instance. 780 */ 781 782 switch (sa->sa_family) { 783 #ifdef LDAP_PF_LOCAL 784 case AF_LOCAL: 785 return LDAP_STRDUP( ldap_int_hostname ); 786 #endif 787 #ifdef LDAP_PF_INET6 788 case AF_INET6: 789 { 790 struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; 791 if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, 792 &localhost, sizeof(localhost)) == 0 ) 793 { 794 return LDAP_STRDUP( ldap_int_hostname ); 795 } 796 } 797 break; 798 #endif 799 case AF_INET: 800 { 801 struct in_addr localhost; 802 localhost.s_addr = htonl( INADDR_ANY ); 803 804 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 805 &localhost, sizeof(localhost) ) == 0 ) 806 { 807 return LDAP_STRDUP( ldap_int_hostname ); 808 } 809 810 #ifdef INADDR_LOOPBACK 811 localhost.s_addr = htonl( INADDR_LOOPBACK ); 812 813 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 814 &localhost, sizeof(localhost) ) == 0 ) 815 { 816 return LDAP_STRDUP( ldap_int_hostname ); 817 } 818 #endif 819 } 820 break; 821 822 default: 823 return( NULL ); 824 break; 825 } 826 827 { 828 char *herr; 829 #ifdef NI_MAXHOST 830 char hbuf[NI_MAXHOST]; 831 #elif defined( MAXHOSTNAMELEN ) 832 char hbuf[MAXHOSTNAMELEN]; 833 #else 834 char hbuf[256]; 835 #endif 836 hbuf[0] = 0; 837 838 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 839 && hbuf[0] ) 840 { 841 return LDAP_STRDUP( hbuf ); 842 } 843 } 844 845 return host ? LDAP_STRDUP( host ) : NULL; 846 } 847 #endif 848 849 850 struct selectinfo { 851 #ifdef HAVE_POLL 852 /* for UNIX poll(2) */ 853 int si_maxfd; 854 struct pollfd si_fds[FD_SETSIZE]; 855 #else 856 /* for UNIX select(2) */ 857 fd_set si_readfds; 858 fd_set si_writefds; 859 fd_set si_use_readfds; 860 fd_set si_use_writefds; 861 #endif 862 }; 863 864 void 865 ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) 866 { 867 struct selectinfo *sip; 868 ber_socket_t sd; 869 870 sip = (struct selectinfo *)ld->ld_selectinfo; 871 872 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 873 874 #ifdef HAVE_POLL 875 /* for UNIX poll(2) */ 876 { 877 int empty=-1; 878 int i; 879 for(i=0; i < sip->si_maxfd; i++) { 880 if( sip->si_fds[i].fd == sd ) { 881 sip->si_fds[i].events |= POLL_WRITE; 882 return; 883 } 884 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 885 empty=i; 886 } 887 } 888 889 if( empty == -1 ) { 890 if( sip->si_maxfd >= FD_SETSIZE ) { 891 /* FIXME */ 892 return; 893 } 894 empty = sip->si_maxfd++; 895 } 896 897 sip->si_fds[empty].fd = sd; 898 sip->si_fds[empty].events = POLL_WRITE; 899 } 900 #else 901 /* for UNIX select(2) */ 902 if ( !FD_ISSET( sd, &sip->si_writefds )) { 903 FD_SET( sd, &sip->si_writefds ); 904 } 905 #endif 906 } 907 908 909 void 910 ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) 911 { 912 struct selectinfo *sip; 913 ber_socket_t sd; 914 915 sip = (struct selectinfo *)ld->ld_selectinfo; 916 917 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 918 919 #ifdef HAVE_POLL 920 /* for UNIX poll(2) */ 921 { 922 int empty=-1; 923 int i; 924 for(i=0; i < sip->si_maxfd; i++) { 925 if( sip->si_fds[i].fd == sd ) { 926 sip->si_fds[i].events |= POLL_READ; 927 return; 928 } 929 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 930 empty=i; 931 } 932 } 933 934 if( empty == -1 ) { 935 if( sip->si_maxfd >= FD_SETSIZE ) { 936 /* FIXME */ 937 return; 938 } 939 empty = sip->si_maxfd++; 940 } 941 942 sip->si_fds[empty].fd = sd; 943 sip->si_fds[empty].events = POLL_READ; 944 } 945 #else 946 /* for UNIX select(2) */ 947 if ( !FD_ISSET( sd, &sip->si_readfds )) { 948 FD_SET( sd, &sip->si_readfds ); 949 } 950 #endif 951 } 952 953 954 void 955 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) 956 { 957 struct selectinfo *sip; 958 ber_socket_t sd; 959 960 sip = (struct selectinfo *)ld->ld_selectinfo; 961 962 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 963 964 #ifdef HAVE_POLL 965 /* for UNIX poll(2) */ 966 { 967 int i; 968 for(i=0; i < sip->si_maxfd; i++) { 969 if( sip->si_fds[i].fd == sd ) { 970 sip->si_fds[i].fd = -1; 971 } 972 } 973 } 974 #else 975 /* for UNIX select(2) */ 976 FD_CLR( sd, &sip->si_writefds ); 977 FD_CLR( sd, &sip->si_readfds ); 978 #endif 979 } 980 981 void 982 ldap_clear_select_write( LDAP *ld, Sockbuf *sb ) 983 { 984 struct selectinfo *sip; 985 ber_socket_t sd; 986 987 sip = (struct selectinfo *)ld->ld_selectinfo; 988 989 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 990 991 #ifdef HAVE_POLL 992 /* for UNIX poll(2) */ 993 { 994 int i; 995 for(i=0; i < sip->si_maxfd; i++) { 996 if( sip->si_fds[i].fd == sd ) { 997 sip->si_fds[i].events &= ~POLL_WRITE; 998 } 999 } 1000 } 1001 #else 1002 /* for UNIX select(2) */ 1003 FD_CLR( sd, &sip->si_writefds ); 1004 #endif 1005 } 1006 1007 1008 int 1009 ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) 1010 { 1011 struct selectinfo *sip; 1012 ber_socket_t sd; 1013 1014 sip = (struct selectinfo *)ld->ld_selectinfo; 1015 1016 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1017 1018 #ifdef HAVE_POLL 1019 /* for UNIX poll(2) */ 1020 { 1021 int i; 1022 for(i=0; i < sip->si_maxfd; i++) { 1023 if( sip->si_fds[i].fd == sd ) { 1024 return sip->si_fds[i].revents & POLL_WRITE; 1025 } 1026 } 1027 1028 return 0; 1029 } 1030 #else 1031 /* for UNIX select(2) */ 1032 return( FD_ISSET( sd, &sip->si_use_writefds )); 1033 #endif 1034 } 1035 1036 1037 int 1038 ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) 1039 { 1040 struct selectinfo *sip; 1041 ber_socket_t sd; 1042 1043 sip = (struct selectinfo *)ld->ld_selectinfo; 1044 1045 if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) 1046 return 1; 1047 1048 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1049 1050 #ifdef HAVE_POLL 1051 /* for UNIX poll(2) */ 1052 { 1053 int i; 1054 for(i=0; i < sip->si_maxfd; i++) { 1055 if( sip->si_fds[i].fd == sd ) { 1056 return sip->si_fds[i].revents & POLL_READ; 1057 } 1058 } 1059 1060 return 0; 1061 } 1062 #else 1063 /* for UNIX select(2) */ 1064 return( FD_ISSET( sd, &sip->si_use_readfds )); 1065 #endif 1066 } 1067 1068 1069 void * 1070 ldap_new_select_info( void ) 1071 { 1072 struct selectinfo *sip; 1073 1074 sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); 1075 1076 if ( sip == NULL ) return NULL; 1077 1078 #ifdef HAVE_POLL 1079 /* for UNIX poll(2) */ 1080 /* sip->si_maxfd=0 */ 1081 #else 1082 /* for UNIX select(2) */ 1083 FD_ZERO( &sip->si_readfds ); 1084 FD_ZERO( &sip->si_writefds ); 1085 #endif 1086 1087 return( (void *)sip ); 1088 } 1089 1090 1091 void 1092 ldap_free_select_info( void *sip ) 1093 { 1094 LDAP_FREE( sip ); 1095 } 1096 1097 1098 #ifndef HAVE_POLL 1099 int ldap_int_tblsize = 0; 1100 1101 void 1102 ldap_int_ip_init( void ) 1103 { 1104 #if defined( HAVE_SYSCONF ) 1105 long tblsize = sysconf( _SC_OPEN_MAX ); 1106 if( tblsize > INT_MAX ) tblsize = INT_MAX; 1107 1108 #elif defined( HAVE_GETDTABLESIZE ) 1109 int tblsize = getdtablesize(); 1110 #else 1111 int tblsize = FD_SETSIZE; 1112 #endif /* !USE_SYSCONF */ 1113 1114 #ifdef FD_SETSIZE 1115 if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; 1116 #endif /* FD_SETSIZE */ 1117 1118 ldap_int_tblsize = tblsize; 1119 } 1120 #endif 1121 1122 1123 int 1124 ldap_int_select( LDAP *ld, struct timeval *timeout ) 1125 { 1126 int rc; 1127 struct selectinfo *sip; 1128 1129 Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 ); 1130 1131 #ifndef HAVE_POLL 1132 if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); 1133 #endif 1134 1135 sip = (struct selectinfo *)ld->ld_selectinfo; 1136 assert( sip != NULL ); 1137 1138 #ifdef HAVE_POLL 1139 { 1140 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; 1141 rc = poll( sip->si_fds, sip->si_maxfd, to ); 1142 } 1143 #else 1144 sip->si_use_readfds = sip->si_readfds; 1145 sip->si_use_writefds = sip->si_writefds; 1146 1147 rc = select( ldap_int_tblsize, 1148 &sip->si_use_readfds, &sip->si_use_writefds, 1149 NULL, timeout ); 1150 #endif 1151 1152 return rc; 1153 } 1154