1 /* $NetBSD: os-ip.c,v 1.8 2018/02/06 01:57:23 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-2017 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.8 2018/02/06 01:57:23 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 ( 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 /* we assume AF_x and PF_x are equal for all x */ 632 s = ldap_int_socket( ld, sai->ai_family, socktype ); 633 if ( s == AC_SOCKET_INVALID ) { 634 continue; 635 } 636 637 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { 638 ldap_pvt_close_socket(ld, s); 639 break; 640 } 641 642 switch (sai->ai_family) { 643 #ifdef LDAP_PF_INET6 644 case AF_INET6: { 645 char addr[INET6_ADDRSTRLEN]; 646 inet_ntop( AF_INET6, 647 &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, 648 addr, sizeof addr); 649 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 650 addr, serv, 0); 651 } break; 652 #endif 653 case AF_INET: { 654 char addr[INET_ADDRSTRLEN]; 655 inet_ntop( AF_INET, 656 &((struct sockaddr_in *)sai->ai_addr)->sin_addr, 657 addr, sizeof addr); 658 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 659 addr, serv, 0); 660 } break; 661 } 662 663 rc = ldap_pvt_connect( ld, s, 664 sai->ai_addr, sai->ai_addrlen, async ); 665 if ( rc == 0 || rc == -2 ) { 666 err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); 667 if ( err ) 668 rc = err; 669 else 670 break; 671 } 672 ldap_pvt_close_socket(ld, s); 673 } 674 freeaddrinfo(res); 675 676 #else 677 if (! inet_aton( host, &in ) ) { 678 int local_h_errno; 679 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, 680 &hp, &local_h_errno ); 681 682 if ( (rc < 0) || (hp == NULL) ) { 683 #ifdef HAVE_WINSOCK 684 ldap_pvt_set_errno( WSAGetLastError() ); 685 #else 686 /* not exactly right, but... */ 687 ldap_pvt_set_errno( EHOSTUNREACH ); 688 #endif 689 if (ha_buf) LDAP_FREE(ha_buf); 690 return -1; 691 } 692 693 use_hp = 1; 694 } 695 696 rc = s = -1; 697 for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { 698 struct sockaddr_in sin; 699 700 s = ldap_int_socket( ld, PF_INET, socktype ); 701 if ( s == AC_SOCKET_INVALID ) { 702 /* use_hp ? continue : break; */ 703 break; 704 } 705 706 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { 707 ldap_pvt_close_socket(ld, s); 708 break; 709 } 710 711 (void)memset((char *)&sin, '\0', sizeof sin); 712 sin.sin_family = AF_INET; 713 sin.sin_port = htons((unsigned short) port); 714 715 if( use_hp ) { 716 AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], 717 sizeof(sin.sin_addr) ); 718 } else { 719 AC_MEMCPY( &sin.sin_addr, &in.s_addr, 720 sizeof(sin.sin_addr) ); 721 } 722 723 #ifdef HAVE_INET_NTOA_B 724 { 725 /* for VxWorks */ 726 char address[INET_ADDR_LEN]; 727 inet_ntoa_b(sin.sin_address, address); 728 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 729 address, port, 0); 730 } 731 #else 732 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 733 inet_ntoa(sin.sin_addr), port, 0); 734 #endif 735 736 rc = ldap_pvt_connect(ld, s, 737 (struct sockaddr *)&sin, sizeof(sin), 738 async); 739 740 if ( (rc == 0) || (rc == -2) ) { 741 int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); 742 if ( err ) 743 rc = err; 744 else 745 break; 746 } 747 748 ldap_pvt_close_socket(ld, s); 749 750 if (!use_hp) break; 751 } 752 if (ha_buf) LDAP_FREE(ha_buf); 753 #endif 754 755 return rc; 756 } 757 758 #if defined( HAVE_CYRUS_SASL ) 759 char * 760 ldap_host_connected_to( Sockbuf *sb, const char *host ) 761 { 762 ber_socklen_t len; 763 #ifdef LDAP_PF_INET6 764 struct sockaddr_storage sabuf; 765 #else 766 struct sockaddr sabuf; 767 #endif 768 struct sockaddr *sa = (struct sockaddr *) &sabuf; 769 ber_socket_t sd; 770 771 (void)memset( (char *)sa, '\0', sizeof sabuf ); 772 len = sizeof sabuf; 773 774 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 775 if ( getpeername( sd, sa, &len ) == -1 ) { 776 return( NULL ); 777 } 778 779 /* 780 * do a reverse lookup on the addr to get the official hostname. 781 * this is necessary for kerberos to work right, since the official 782 * hostname is used as the kerberos instance. 783 */ 784 785 switch (sa->sa_family) { 786 #ifdef LDAP_PF_LOCAL 787 case AF_LOCAL: 788 return LDAP_STRDUP( ldap_int_hostname ); 789 #endif 790 #ifdef LDAP_PF_INET6 791 case AF_INET6: 792 { 793 struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; 794 if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, 795 &localhost, sizeof(localhost)) == 0 ) 796 { 797 return LDAP_STRDUP( ldap_int_hostname ); 798 } 799 } 800 break; 801 #endif 802 case AF_INET: 803 { 804 struct in_addr localhost; 805 localhost.s_addr = htonl( INADDR_ANY ); 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 813 #ifdef INADDR_LOOPBACK 814 localhost.s_addr = htonl( INADDR_LOOPBACK ); 815 816 if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, 817 &localhost, sizeof(localhost) ) == 0 ) 818 { 819 return LDAP_STRDUP( ldap_int_hostname ); 820 } 821 #endif 822 } 823 break; 824 825 default: 826 return( NULL ); 827 break; 828 } 829 830 { 831 char *herr; 832 #ifdef NI_MAXHOST 833 char hbuf[NI_MAXHOST]; 834 #elif defined( MAXHOSTNAMELEN ) 835 char hbuf[MAXHOSTNAMELEN]; 836 #else 837 char hbuf[256]; 838 #endif 839 hbuf[0] = 0; 840 841 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 842 && hbuf[0] ) 843 { 844 return LDAP_STRDUP( hbuf ); 845 } 846 } 847 848 return host ? LDAP_STRDUP( host ) : NULL; 849 } 850 #endif 851 852 853 struct selectinfo { 854 #ifdef HAVE_POLL 855 /* for UNIX poll(2) */ 856 int si_maxfd; 857 struct pollfd si_fds[FD_SETSIZE]; 858 #else 859 /* for UNIX select(2) */ 860 fd_set si_readfds; 861 fd_set si_writefds; 862 fd_set si_use_readfds; 863 fd_set si_use_writefds; 864 #endif 865 }; 866 867 void 868 ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) 869 { 870 struct selectinfo *sip; 871 ber_socket_t sd; 872 873 sip = (struct selectinfo *)ld->ld_selectinfo; 874 875 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 876 877 #ifdef HAVE_POLL 878 /* for UNIX poll(2) */ 879 { 880 int empty=-1; 881 int i; 882 for(i=0; i < sip->si_maxfd; i++) { 883 if( sip->si_fds[i].fd == sd ) { 884 sip->si_fds[i].events |= POLL_WRITE; 885 return; 886 } 887 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 888 empty=i; 889 } 890 } 891 892 if( empty == -1 ) { 893 if( sip->si_maxfd >= FD_SETSIZE ) { 894 /* FIXME */ 895 return; 896 } 897 empty = sip->si_maxfd++; 898 } 899 900 sip->si_fds[empty].fd = sd; 901 sip->si_fds[empty].events = POLL_WRITE; 902 } 903 #else 904 /* for UNIX select(2) */ 905 if ( !FD_ISSET( sd, &sip->si_writefds )) { 906 FD_SET( sd, &sip->si_writefds ); 907 } 908 #endif 909 } 910 911 912 void 913 ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) 914 { 915 struct selectinfo *sip; 916 ber_socket_t sd; 917 918 sip = (struct selectinfo *)ld->ld_selectinfo; 919 920 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 921 922 #ifdef HAVE_POLL 923 /* for UNIX poll(2) */ 924 { 925 int empty=-1; 926 int i; 927 for(i=0; i < sip->si_maxfd; i++) { 928 if( sip->si_fds[i].fd == sd ) { 929 sip->si_fds[i].events |= POLL_READ; 930 return; 931 } 932 if( empty==-1 && sip->si_fds[i].fd == -1 ) { 933 empty=i; 934 } 935 } 936 937 if( empty == -1 ) { 938 if( sip->si_maxfd >= FD_SETSIZE ) { 939 /* FIXME */ 940 return; 941 } 942 empty = sip->si_maxfd++; 943 } 944 945 sip->si_fds[empty].fd = sd; 946 sip->si_fds[empty].events = POLL_READ; 947 } 948 #else 949 /* for UNIX select(2) */ 950 if ( !FD_ISSET( sd, &sip->si_readfds )) { 951 FD_SET( sd, &sip->si_readfds ); 952 } 953 #endif 954 } 955 956 957 void 958 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) 959 { 960 struct selectinfo *sip; 961 ber_socket_t sd; 962 963 sip = (struct selectinfo *)ld->ld_selectinfo; 964 965 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 966 967 #ifdef HAVE_POLL 968 /* for UNIX poll(2) */ 969 { 970 int i; 971 for(i=0; i < sip->si_maxfd; i++) { 972 if( sip->si_fds[i].fd == sd ) { 973 sip->si_fds[i].fd = -1; 974 } 975 } 976 } 977 #else 978 /* for UNIX select(2) */ 979 FD_CLR( sd, &sip->si_writefds ); 980 FD_CLR( sd, &sip->si_readfds ); 981 #endif 982 } 983 984 void 985 ldap_clear_select_write( LDAP *ld, Sockbuf *sb ) 986 { 987 struct selectinfo *sip; 988 ber_socket_t sd; 989 990 sip = (struct selectinfo *)ld->ld_selectinfo; 991 992 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 993 994 #ifdef HAVE_POLL 995 /* for UNIX poll(2) */ 996 { 997 int i; 998 for(i=0; i < sip->si_maxfd; i++) { 999 if( sip->si_fds[i].fd == sd ) { 1000 sip->si_fds[i].events &= ~POLL_WRITE; 1001 } 1002 } 1003 } 1004 #else 1005 /* for UNIX select(2) */ 1006 FD_CLR( sd, &sip->si_writefds ); 1007 #endif 1008 } 1009 1010 1011 int 1012 ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) 1013 { 1014 struct selectinfo *sip; 1015 ber_socket_t sd; 1016 1017 sip = (struct selectinfo *)ld->ld_selectinfo; 1018 1019 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1020 1021 #ifdef HAVE_POLL 1022 /* for UNIX poll(2) */ 1023 { 1024 int i; 1025 for(i=0; i < sip->si_maxfd; i++) { 1026 if( sip->si_fds[i].fd == sd ) { 1027 return sip->si_fds[i].revents & POLL_WRITE; 1028 } 1029 } 1030 1031 return 0; 1032 } 1033 #else 1034 /* for UNIX select(2) */ 1035 return( FD_ISSET( sd, &sip->si_use_writefds )); 1036 #endif 1037 } 1038 1039 1040 int 1041 ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) 1042 { 1043 struct selectinfo *sip; 1044 ber_socket_t sd; 1045 1046 sip = (struct selectinfo *)ld->ld_selectinfo; 1047 1048 if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) 1049 return 1; 1050 1051 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); 1052 1053 #ifdef HAVE_POLL 1054 /* for UNIX poll(2) */ 1055 { 1056 int i; 1057 for(i=0; i < sip->si_maxfd; i++) { 1058 if( sip->si_fds[i].fd == sd ) { 1059 return sip->si_fds[i].revents & POLL_READ; 1060 } 1061 } 1062 1063 return 0; 1064 } 1065 #else 1066 /* for UNIX select(2) */ 1067 return( FD_ISSET( sd, &sip->si_use_readfds )); 1068 #endif 1069 } 1070 1071 1072 void * 1073 ldap_new_select_info( void ) 1074 { 1075 struct selectinfo *sip; 1076 1077 sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); 1078 1079 if ( sip == NULL ) return NULL; 1080 1081 #ifdef HAVE_POLL 1082 /* for UNIX poll(2) */ 1083 /* sip->si_maxfd=0 */ 1084 #else 1085 /* for UNIX select(2) */ 1086 FD_ZERO( &sip->si_readfds ); 1087 FD_ZERO( &sip->si_writefds ); 1088 #endif 1089 1090 return( (void *)sip ); 1091 } 1092 1093 1094 void 1095 ldap_free_select_info( void *sip ) 1096 { 1097 LDAP_FREE( sip ); 1098 } 1099 1100 1101 #ifndef HAVE_POLL 1102 int ldap_int_tblsize = 0; 1103 1104 void 1105 ldap_int_ip_init( void ) 1106 { 1107 #if defined( HAVE_SYSCONF ) 1108 long tblsize = sysconf( _SC_OPEN_MAX ); 1109 if( tblsize > INT_MAX ) tblsize = INT_MAX; 1110 1111 #elif defined( HAVE_GETDTABLESIZE ) 1112 int tblsize = getdtablesize(); 1113 #else 1114 int tblsize = FD_SETSIZE; 1115 #endif /* !USE_SYSCONF */ 1116 1117 #ifdef FD_SETSIZE 1118 if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; 1119 #endif /* FD_SETSIZE */ 1120 1121 ldap_int_tblsize = tblsize; 1122 } 1123 #endif 1124 1125 1126 int 1127 ldap_int_select( LDAP *ld, struct timeval *timeout ) 1128 { 1129 int rc; 1130 struct selectinfo *sip; 1131 1132 Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 ); 1133 1134 #ifndef HAVE_POLL 1135 if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); 1136 #endif 1137 1138 sip = (struct selectinfo *)ld->ld_selectinfo; 1139 assert( sip != NULL ); 1140 1141 #ifdef HAVE_POLL 1142 { 1143 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; 1144 rc = poll( sip->si_fds, sip->si_maxfd, to ); 1145 } 1146 #else 1147 sip->si_use_readfds = sip->si_readfds; 1148 sip->si_use_writefds = sip->si_writefds; 1149 1150 rc = select( ldap_int_tblsize, 1151 &sip->si_use_readfds, &sip->si_use_writefds, 1152 NULL, timeout ); 1153 #endif 1154 1155 return rc; 1156 } 1157