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