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