1/* $NetBSD: os-ip.c,v 1.4 2010/12/12 15:46:33 adam Exp $ */ 2 3/* os-ip.c -- platform-specific TCP & UDP related code */ 4/* OpenLDAP: pkg/ldap/libraries/libldap/os-ip.c,v 1.118.2.20 2010/04/13 20:22:58 kurt Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 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 49int ldap_int_inet4or6 = AF_UNSPEC; 50# else 51int ldap_int_inet4or6 = AF_INET; 52# endif 53#endif 54 55#ifdef LDAP_DEBUG 56 57#define osip_debug(ld,fmt,arg1,arg2,arg3) \ 58do { \ 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 68static void 69ldap_pvt_set_errno(int err) 70{ 71 sock_errset(err); 72} 73 74int 75ldap_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 99static int 100ldap_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 106static int 107ldap_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 113static ber_socket_t 114ldap_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 124static int 125ldap_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 131static int 132ldap_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 */ 228static int 229ldap_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 */ 277int 278ldap_int_poll( 279 LDAP *ld, 280 ber_socket_t s, 281 struct timeval *tvp ) 282{ 283 int rc; 284 285 286 osip_debug(ld, "ldap_int_poll: fd: %d tm: %jd\n", 287 s, tvp ? (intmax_t)tvp->tv_sec : -1, 0); 288 289#ifdef HAVE_POLL 290 { 291 struct pollfd fd; 292 int timeout = INFTIM; 293 294 fd.fd = s; 295 fd.events = POLL_WRITE; 296 297 if ( tvp != NULL ) { 298 timeout = TV2MILLISEC( tvp ); 299 } 300 do { 301 fd.revents = 0; 302 rc = poll( &fd, 1, timeout ); 303 304 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 305 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 306 307 if ( rc == AC_SOCKET_ERROR ) { 308 return rc; 309 } 310 311 if ( timeout == 0 && rc == 0 ) { 312 return -2; 313 } 314 315 if ( fd.revents & POLL_WRITE ) { 316 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 317 return -1; 318 } 319 320 if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) { 321 return -1; 322 } 323 return 0; 324 } 325 } 326#else 327 { 328 fd_set wfds, *z = NULL; 329#ifdef HAVE_WINSOCK 330 fd_set efds; 331#endif 332 struct timeval tv = { 0 }; 333 334#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK ) 335 if ( s >= FD_SETSIZE ) { 336 rc = AC_SOCKET_ERROR; 337 tcp_close( s ); 338 ldap_pvt_set_errno( EMFILE ); 339 return rc; 340 } 341#endif 342 343 if ( tvp != NULL ) { 344 tv = *tvp; 345 } 346 347 do { 348 FD_ZERO(&wfds); 349 FD_SET(s, &wfds ); 350 351#ifdef HAVE_WINSOCK 352 FD_ZERO(&efds); 353 FD_SET(s, &efds ); 354#endif 355 356 rc = select( ldap_int_tblsize, z, &wfds, 357#ifdef HAVE_WINSOCK 358 &efds, 359#else 360 z, 361#endif 362 tvp ? &tv : NULL ); 363 } while ( rc == AC_SOCKET_ERROR && errno == EINTR && 364 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); 365 366 if ( rc == AC_SOCKET_ERROR ) { 367 return rc; 368 } 369 370 if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) { 371 return -2; 372 } 373 374#ifdef HAVE_WINSOCK 375 /* This means the connection failed */ 376 if ( FD_ISSET(s, &efds) ) { 377 int so_errno; 378 ber_socklen_t dummy = sizeof(so_errno); 379 if ( getsockopt( s, SOL_SOCKET, SO_ERROR, 380 (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno ) 381 { 382 /* impossible */ 383 so_errno = WSAGetLastError(); 384 } 385 ldap_pvt_set_errno( so_errno ); 386 osip_debug(ld, "ldap_int_poll: error on socket %d: " 387 "errno: %d (%s)\n", s, errno, sock_errstr( errno )); 388 return -1; 389 } 390#endif 391 if ( FD_ISSET(s, &wfds) ) { 392#ifndef HAVE_WINSOCK 393 if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { 394 return -1; 395 } 396#endif 397 if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { 398 return -1; 399 } 400 return 0; 401 } 402 } 403#endif 404 405 osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0); 406 ldap_pvt_set_errno( ETIMEDOUT ); 407 return -1; 408} 409 410static int 411ldap_pvt_connect(LDAP *ld, ber_socket_t s, 412 struct sockaddr *sin, ber_socklen_t addrlen, 413 int async) 414{ 415 int rc, err; 416 struct timeval tv, *opt_tv = NULL; 417 418#ifdef LDAP_CONNECTIONLESS 419 /* We could do a connect() but that would interfere with 420 * attempts to poll a broadcast address 421 */ 422 if (LDAP_IS_UDP(ld)) { 423 if (ld->ld_options.ldo_peer) 424 ldap_memfree(ld->ld_options.ldo_peer); 425 ld->ld_options.ldo_peer=ldap_memalloc(sizeof(struct sockaddr)); 426 AC_MEMCPY(ld->ld_options.ldo_peer,sin,sizeof(struct sockaddr)); 427 return ( 0 ); 428 } 429#endif 430 if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { 431 tv = ld->ld_options.ldo_tm_net; 432 opt_tv = &tv; 433 } 434 435 osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %jd async: %d\n", 436 s, opt_tv ? (intmax_t)tv.tv_sec : -1, async); 437 438 if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 ) 439 return ( -1 ); 440 441 if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { 442 if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) 443 return ( -1 ); 444 return ( 0 ); 445 } 446 447 err = sock_errno(); 448 if ( err != EINPROGRESS && err != EWOULDBLOCK ) { 449 return ( -1 ); 450 } 451 452 if ( async ) { 453 /* caller will call ldap_int_poll() as appropriate? */ 454 return ( -2 ); 455 } 456 457 rc = ldap_int_poll( ld, s, opt_tv ); 458 459 osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0); 460 461 return rc; 462} 463 464#ifndef HAVE_INET_ATON 465int 466ldap_pvt_inet_aton( const char *host, struct in_addr *in) 467{ 468 unsigned long u = inet_addr( host ); 469 470#ifdef INADDR_NONE 471 if ( u == INADDR_NONE ) return 0; 472#endif 473 if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0; 474 475 in->s_addr = u; 476 return 1; 477} 478#endif 479 480int 481ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr) 482{ 483 struct ldapoptions *lo; 484 ldaplist *ll; 485 ldap_conncb *cb; 486 int rc; 487 488 ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); 489 490 /* Invoke all handle-specific callbacks first */ 491 lo = &ld->ld_options; 492 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 493 cb = ll->ll_data; 494 rc = cb->lc_add( ld, sb, srv, addr, cb ); 495 /* on any failure, call the teardown functions for anything 496 * that previously succeeded 497 */ 498 if ( rc ) { 499 ldaplist *l2; 500 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 501 cb = l2->ll_data; 502 cb->lc_del( ld, sb, cb ); 503 } 504 /* a failure might have implicitly closed the fd */ 505 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 506 return rc; 507 } 508 } 509 lo = LDAP_INT_GLOBAL_OPT(); 510 for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { 511 cb = ll->ll_data; 512 rc = cb->lc_add( ld, sb, srv, addr, cb ); 513 if ( rc ) { 514 ldaplist *l2; 515 for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { 516 cb = l2->ll_data; 517 cb->lc_del( ld, sb, cb ); 518 } 519 lo = &ld->ld_options; 520 for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { 521 cb = l2->ll_data; 522 cb->lc_del( ld, sb, cb ); 523 } 524 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); 525 return rc; 526 } 527 } 528 return 0; 529} 530 531int 532ldap_connect_to_host(LDAP *ld, Sockbuf *sb, 533 int proto, LDAPURLDesc *srv, 534 int async ) 535{ 536 int rc; 537 int socktype, port; 538 ber_socket_t s = AC_SOCKET_INVALID; 539 char *host; 540 541#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 542 char serv[7]; 543 int err; 544 struct addrinfo hints, *res, *sai; 545#else 546 int i; 547 int use_hp = 0; 548 struct hostent *hp = NULL; 549 struct hostent he_buf; 550 struct in_addr in; 551 char *ha_buf=NULL; 552#endif 553 554 if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { 555 host = "localhost"; 556 } else { 557 host = srv->lud_host; 558 } 559 560 port = srv->lud_port; 561 562 if( !port ) { 563 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { 564 port = LDAPS_PORT; 565 } else { 566 port = LDAP_PORT; 567 } 568 } 569 570 switch(proto) { 571 case LDAP_PROTO_TCP: socktype = SOCK_STREAM; 572 osip_debug( ld, 573 "ldap_connect_to_host: TCP %s:%d\n", 574 host, port, 0); 575 break; 576 case LDAP_PROTO_UDP: socktype = SOCK_DGRAM; 577 osip_debug( ld, 578 "ldap_connect_to_host: UDP %s:%d\n", 579 host, port, 0); 580 break; 581 default: 582 osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n", 583 proto, 0, 0 ); 584 return -1; 585 } 586 587#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 588 memset( &hints, '\0', sizeof(hints) ); 589#ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */ 590 /* Use AI_ADDRCONFIG only on systems where its known to be needed. */ 591 hints.ai_flags = AI_ADDRCONFIG; 592#endif 593 hints.ai_family = ldap_int_inet4or6; 594 hints.ai_socktype = socktype; 595 snprintf(serv, sizeof serv, "%d", port ); 596 597#ifdef LDAP_R_COMPILE 598 /* most getaddrinfo(3) use non-threadsafe resolver libraries */ 599 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex); 600#endif 601 602 err = getaddrinfo( host, serv, &hints, &res ); 603 604#ifdef LDAP_R_COMPILE 605 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex); 606#endif 607 608 if ( err != 0 ) { 609 osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n", 610 AC_GAI_STRERROR(err), 0, 0); 611 return -1; 612 } 613 rc = -1; 614 615 for( sai=res; sai != NULL; sai=sai->ai_next) { 616 if( sai->ai_addr == NULL ) { 617 osip_debug(ld, "ldap_connect_to_host: getaddrinfo " 618 "ai_addr is NULL?\n", 0, 0, 0); 619 continue; 620 } 621 622 /* we assume AF_x and PF_x are equal for all x */ 623 s = ldap_int_socket( ld, sai->ai_family, socktype ); 624 if ( s == AC_SOCKET_INVALID ) { 625 continue; 626 } 627 628 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { 629 ldap_pvt_close_socket(ld, s); 630 break; 631 } 632 633 switch (sai->ai_family) { 634#ifdef LDAP_PF_INET6 635 case AF_INET6: { 636 char addr[INET6_ADDRSTRLEN]; 637 inet_ntop( AF_INET6, 638 &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, 639 addr, sizeof addr); 640 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 641 addr, serv, 0); 642 } break; 643#endif 644 case AF_INET: { 645 char addr[INET_ADDRSTRLEN]; 646 inet_ntop( AF_INET, 647 &((struct sockaddr_in *)sai->ai_addr)->sin_addr, 648 addr, sizeof addr); 649 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 650 addr, serv, 0); 651 } break; 652 } 653 654 rc = ldap_pvt_connect( ld, s, 655 sai->ai_addr, sai->ai_addrlen, async ); 656 if ( rc == 0 || rc == -2 ) { 657 err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); 658 if ( err ) 659 rc = err; 660 else 661 break; 662 } 663 ldap_pvt_close_socket(ld, s); 664 } 665 freeaddrinfo(res); 666 667#else 668 if (! inet_aton( host, &in ) ) { 669 int local_h_errno; 670 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, 671 &hp, &local_h_errno ); 672 673 if ( (rc < 0) || (hp == NULL) ) { 674#ifdef HAVE_WINSOCK 675 ldap_pvt_set_errno( WSAGetLastError() ); 676#else 677 /* not exactly right, but... */ 678 ldap_pvt_set_errno( EHOSTUNREACH ); 679#endif 680 if (ha_buf) LDAP_FREE(ha_buf); 681 return -1; 682 } 683 684 use_hp = 1; 685 } 686 687 rc = s = -1; 688 for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { 689 struct sockaddr_in sin; 690 691 s = ldap_int_socket( ld, PF_INET, socktype ); 692 if ( s == AC_SOCKET_INVALID ) { 693 /* use_hp ? continue : break; */ 694 break; 695 } 696 697 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { 698 ldap_pvt_close_socket(ld, s); 699 break; 700 } 701 702 (void)memset((char *)&sin, '\0', sizeof sin); 703 sin.sin_family = AF_INET; 704 sin.sin_port = htons((unsigned short) port); 705 706 if( use_hp ) { 707 AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], 708 sizeof(sin.sin_addr) ); 709 } else { 710 AC_MEMCPY( &sin.sin_addr, &in.s_addr, 711 sizeof(sin.sin_addr) ); 712 } 713 714#ifdef HAVE_INET_NTOA_B 715 { 716 /* for VxWorks */ 717 char address[INET_ADDR_LEN]; 718 inet_ntoa_b(sin.sin_address, address); 719 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 720 address, port, 0); 721 } 722#else 723 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 724 inet_ntoa(sin.sin_addr), port, 0); 725#endif 726 727 rc = ldap_pvt_connect(ld, s, 728 (struct sockaddr *)&sin, sizeof(sin), 729 async); 730 731 if ( (rc == 0) || (rc == -2) ) { 732 i = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); 733 if ( i ) 734 rc = i; 735 else 736 break; 737 } 738 739 ldap_pvt_close_socket(ld, s); 740 741 if (!use_hp) break; 742 } 743 if (ha_buf) LDAP_FREE(ha_buf); 744#endif 745 746 return rc; 747} 748 749#if defined( HAVE_CYRUS_SASL ) 750char * 751ldap_host_connected_to( Sockbuf *sb, const char *host ) 752{ 753 ber_socklen_t len; 754#ifdef LDAP_PF_INET6 755 struct sockaddr_storage sabuf; 756#else 757 struct sockaddr sabuf; 758#endif 759 struct sockaddr *sa = (struct sockaddr *) &sabuf; 760 ber_socket_t sd; 761 762 (void)memset( (char *)sa, '\0', sizeof sabuf ); 763 len = sizeof sabuf; 764 765 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 766 if ( getpeername( sd, sa, &len ) == -1 ) { 767 return( NULL ); 768 } 769 770 /* 771 * do a reverse lookup on the addr to get the official hostname. 772 * this is necessary for kerberos to work right, since the official 773 * hostname is used as the kerberos instance. 774 */ 775 776 switch (sa->sa_family) { 777#ifdef LDAP_PF_LOCAL 778 case AF_LOCAL: 779 return LDAP_STRDUP( ldap_int_hostname ); 780#endif 781#ifdef LDAP_PF_INET6 782 case AF_INET6: 783 { 784 struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; 785 if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, 786 &localhost, sizeof(localhost)) == 0 ) 787 { 788 return LDAP_STRDUP( ldap_int_hostname ); 789 } 790 } 791 break; 792#endif 793 case AF_INET: 794 { 795 struct in_addr localhost; 796 localhost.s_addr = htonl( INADDR_ANY ); 797 798 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 799 &localhost, sizeof(localhost) ) == 0 ) 800 { 801 return LDAP_STRDUP( ldap_int_hostname ); 802 } 803 804#ifdef INADDR_LOOPBACK 805 localhost.s_addr = htonl( INADDR_LOOPBACK ); 806 807 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 808 &localhost, sizeof(localhost) ) == 0 ) 809 { 810 return LDAP_STRDUP( ldap_int_hostname ); 811 } 812#endif 813 } 814 break; 815 816 default: 817 return( NULL ); 818 break; 819 } 820 821 { 822 char *herr; 823#ifdef NI_MAXHOST 824 char hbuf[NI_MAXHOST]; 825#elif defined( MAXHOSTNAMELEN ) 826 char hbuf[MAXHOSTNAMELEN]; 827#else 828 char hbuf[256]; 829#endif 830 hbuf[0] = 0; 831 832 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 833 && hbuf[0] ) 834 { 835 return LDAP_STRDUP( hbuf ); 836 } 837 } 838 839 return host ? LDAP_STRDUP( host ) : NULL; 840} 841#endif 842 843 844struct selectinfo { 845#ifdef HAVE_POLL 846 /* for UNIX poll(2) */ 847 int si_maxfd; 848 struct pollfd si_fds[FD_SETSIZE]; 849#else 850 /* for UNIX select(2) */ 851 fd_set si_readfds; 852 fd_set si_writefds; 853 fd_set si_use_readfds; 854 fd_set si_use_writefds; 855#endif 856}; 857 858void 859ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) 860{ 861 struct selectinfo *sip; 862 ber_socket_t sd; 863 864 sip = (struct selectinfo *)ld->ld_selectinfo; 865 866 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 867 868#ifdef HAVE_POLL 869 /* for UNIX poll(2) */ 870 { 871 int empty=-1; 872 int i; 873 for(i=0; i < sip->si_maxfd; i++) { 874 if( sip->si_fds[i].fd == sd ) { 875 sip->si_fds[i].events |= POLL_WRITE; 876 return; 877 } 878 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 879 empty=i; 880 } 881 } 882 883 if( empty == -1 ) { 884 if( sip->si_maxfd >= FD_SETSIZE ) { 885 /* FIXME */ 886 return; 887 } 888 empty = sip->si_maxfd++; 889 } 890 891 sip->si_fds[empty].fd = sd; 892 sip->si_fds[empty].events = POLL_WRITE; 893 } 894#else 895 /* for UNIX select(2) */ 896 if ( !FD_ISSET( sd, &sip->si_writefds )) { 897 FD_SET( sd, &sip->si_writefds ); 898 } 899#endif 900} 901 902 903void 904ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) 905{ 906 struct selectinfo *sip; 907 ber_socket_t sd; 908 909 sip = (struct selectinfo *)ld->ld_selectinfo; 910 911 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 912 913#ifdef HAVE_POLL 914 /* for UNIX poll(2) */ 915 { 916 int empty=-1; 917 int i; 918 for(i=0; i < sip->si_maxfd; i++) { 919 if( sip->si_fds[i].fd == sd ) { 920 sip->si_fds[i].events |= POLL_READ; 921 return; 922 } 923 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 924 empty=i; 925 } 926 } 927 928 if( empty == -1 ) { 929 if( sip->si_maxfd >= FD_SETSIZE ) { 930 /* FIXME */ 931 return; 932 } 933 empty = sip->si_maxfd++; 934 } 935 936 sip->si_fds[empty].fd = sd; 937 sip->si_fds[empty].events = POLL_READ; 938 } 939#else 940 /* for UNIX select(2) */ 941 if ( !FD_ISSET( sd, &sip->si_readfds )) { 942 FD_SET( sd, &sip->si_readfds ); 943 } 944#endif 945} 946 947 948void 949ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) 950{ 951 struct selectinfo *sip; 952 ber_socket_t sd; 953 954 sip = (struct selectinfo *)ld->ld_selectinfo; 955 956 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 957 958#ifdef HAVE_POLL 959 /* for UNIX poll(2) */ 960 { 961 int i; 962 for(i=0; i < sip->si_maxfd; i++) { 963 if( sip->si_fds[i].fd == sd ) { 964 sip->si_fds[i].fd = -1; 965 } 966 } 967 } 968#else 969 /* for UNIX select(2) */ 970 FD_CLR( sd, &sip->si_writefds ); 971 FD_CLR( sd, &sip->si_readfds ); 972#endif 973} 974 975 976int 977ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) 978{ 979 struct selectinfo *sip; 980 ber_socket_t sd; 981 982 sip = (struct selectinfo *)ld->ld_selectinfo; 983 984 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 985 986#ifdef HAVE_POLL 987 /* for UNIX poll(2) */ 988 { 989 int i; 990 for(i=0; i < sip->si_maxfd; i++) { 991 if( sip->si_fds[i].fd == sd ) { 992 return sip->si_fds[i].revents & POLL_WRITE; 993 } 994 } 995 996 return 0; 997 } 998#else 999 /* for UNIX select(2) */ 1000 return( FD_ISSET( sd, &sip->si_use_writefds )); 1001#endif 1002} 1003 1004 1005int 1006ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) 1007{ 1008 struct selectinfo *sip; 1009 ber_socket_t sd; 1010 1011 sip = (struct selectinfo *)ld->ld_selectinfo; 1012 1013 if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) 1014 return 1; 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_READ; 1025 } 1026 } 1027 1028 return 0; 1029 } 1030#else 1031 /* for UNIX select(2) */ 1032 return( FD_ISSET( sd, &sip->si_use_readfds )); 1033#endif 1034} 1035 1036 1037void * 1038ldap_new_select_info( void ) 1039{ 1040 struct selectinfo *sip; 1041 1042 sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); 1043 1044 if ( sip == NULL ) return NULL; 1045 1046#ifdef HAVE_POLL 1047 /* for UNIX poll(2) */ 1048 /* sip->si_maxfd=0 */ 1049#else 1050 /* for UNIX select(2) */ 1051 FD_ZERO( &sip->si_readfds ); 1052 FD_ZERO( &sip->si_writefds ); 1053#endif 1054 1055 return( (void *)sip ); 1056} 1057 1058 1059void 1060ldap_free_select_info( void *sip ) 1061{ 1062 LDAP_FREE( sip ); 1063} 1064 1065 1066#ifndef HAVE_POLL 1067int ldap_int_tblsize = 0; 1068 1069void 1070ldap_int_ip_init( void ) 1071{ 1072#if defined( HAVE_SYSCONF ) 1073 long tblsize = sysconf( _SC_OPEN_MAX ); 1074 if( tblsize > INT_MAX ) tblsize = INT_MAX; 1075 1076#elif defined( HAVE_GETDTABLESIZE ) 1077 int tblsize = getdtablesize(); 1078#else 1079 int tblsize = FD_SETSIZE; 1080#endif /* !USE_SYSCONF */ 1081 1082#ifdef FD_SETSIZE 1083 if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; 1084#endif /* FD_SETSIZE */ 1085 1086 ldap_int_tblsize = tblsize; 1087} 1088#endif 1089 1090 1091int 1092ldap_int_select( LDAP *ld, struct timeval *timeout ) 1093{ 1094 int rc; 1095 struct selectinfo *sip; 1096 1097 Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 ); 1098 1099#ifndef HAVE_POLL 1100 if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); 1101#endif 1102 1103 sip = (struct selectinfo *)ld->ld_selectinfo; 1104 assert( sip != NULL ); 1105 1106#ifdef HAVE_POLL 1107 { 1108 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; 1109 rc = poll( sip->si_fds, sip->si_maxfd, to ); 1110 } 1111#else 1112 sip->si_use_readfds = sip->si_readfds; 1113 sip->si_use_writefds = sip->si_writefds; 1114 1115 rc = select( ldap_int_tblsize, 1116 &sip->si_use_readfds, &sip->si_use_writefds, 1117 NULL, timeout ); 1118#endif 1119 1120 return rc; 1121} 1122