1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 9 /* 10 * The contents of this file are subject to the Netscape Public 11 * License Version 1.1 (the "License"); you may not use this file 12 * except in compliance with the License. You may obtain a copy of 13 * the License at http://www.mozilla.org/NPL/ 14 * 15 * Software distributed under the License is distributed on an "AS 16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 17 * implied. See the License for the specific language governing 18 * rights and limitations under the License. 19 * 20 * The Original Code is Mozilla Communicator client code, released 21 * March 31, 1998. 22 * 23 * The Initial Developer of the Original Code is Netscape 24 * Communications Corporation. Portions created by Netscape are 25 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 26 * Rights Reserved. 27 * 28 * Contributor(s): 29 */ 30 /* 31 * Copyright (c) 1995 Regents of the University of Michigan. 32 * All rights reserved. 33 */ 34 /* 35 * open.c 36 */ 37 38 #if 0 39 #ifndef lint 40 static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; 41 #endif 42 #endif 43 44 #include "ldap-int.h" 45 #ifdef LDAP_SASLIO_HOOKS 46 /* Valid for any ANSI C compiler */ 47 #include <limits.h> 48 #endif 49 50 #define VI_PRODUCTVERSION 3 51 52 #ifndef INADDR_LOOPBACK 53 #define INADDR_LOOPBACK ((unsigned long) 0x7f000001) 54 #endif 55 56 #ifndef MAXHOSTNAMELEN 57 #define MAXHOSTNAMELEN 64 58 #endif 59 60 #ifdef LDAP_DEBUG 61 int ldap_debug; 62 #endif 63 64 65 /* 66 * global defaults for callbacks are stored here. callers of the API set 67 * these by passing a NULL "ld" to ldap_set_option(). Everything in 68 * nsldapi_ld_defaults can be overridden on a per-ld basis as well (the 69 * memory allocation functions are global to all ld's). 70 */ 71 struct ldap nsldapi_ld_defaults; 72 struct ldap_memalloc_fns nsldapi_memalloc_fns = { 0, 0, 0, 0 }; 73 int nsldapi_initialized = 0; 74 75 #ifndef _WINDOWS 76 #include <pthread.h> 77 static pthread_key_t nsldapi_key; 78 79 struct nsldapi_ldap_error { 80 int le_errno; 81 char *le_matched; 82 char *le_errmsg; 83 }; 84 #else 85 __declspec ( thread ) int nsldapi_gldaperrno; 86 __declspec ( thread ) char *nsldapi_gmatched = NULL; 87 __declspec ( thread ) char *nsldapi_gldaperror = NULL; 88 #endif /* _WINDOWS */ 89 90 #ifdef _WINDOWS 91 #define LDAP_MUTEX_T HANDLE 92 93 int 94 pthread_mutex_init( LDAP_MUTEX_T *mp, void *attr) 95 { 96 if ( (*mp = CreateMutex(NULL, FALSE, NULL)) == NULL ) 97 return( 1 ); 98 else 99 return( 0 ); 100 } 101 102 static void * 103 pthread_mutex_alloc( void ) 104 { 105 LDAP_MUTEX_T *mutexp; 106 107 if ( (mutexp = malloc( sizeof(LDAP_MUTEX_T) )) != NULL ) { 108 pthread_mutex_init( mutexp, NULL ); 109 } 110 return( mutexp ); 111 } 112 113 int 114 pthread_mutex_destroy( LDAP_MUTEX_T *mp ) 115 { 116 if ( !(CloseHandle(*mp)) ) 117 return( 1 ); 118 else 119 return( 0 ); 120 } 121 122 static void 123 pthread_mutex_free( void *mutexp ) 124 { 125 pthread_mutex_destroy( (LDAP_MUTEX_T *) mutexp ); 126 free( mutexp ); 127 } 128 129 int 130 pthread_mutex_lock( LDAP_MUTEX_T *mp ) 131 { 132 if ( (WaitForSingleObject(*mp, INFINITE) != WAIT_OBJECT_0) ) 133 return( 1 ); 134 else 135 return( 0 ); 136 } 137 138 int 139 pthread_mutex_unlock( LDAP_MUTEX_T *mp ) 140 { 141 if ( !(ReleaseMutex(*mp)) ) 142 return( 1 ); 143 else 144 return( 0 ); 145 } 146 147 static int 148 get_errno( void ) 149 { 150 return errno; 151 } 152 153 static void 154 set_errno( int Errno ) 155 { 156 errno = Errno; 157 } 158 159 static int 160 get_ld_error( char **LDMatched, char **LDError, void * Args ) 161 { 162 if ( LDMatched != NULL ) 163 { 164 *LDMatched = nsldapi_gmatched; 165 } 166 if ( LDError != NULL ) 167 { 168 *LDError = nsldapi_gldaperror; 169 } 170 return nsldapi_gldaperrno; 171 } 172 173 static void 174 set_ld_error( int LDErrno, char * LDMatched, char * LDError, 175 void * Args ) 176 { 177 /* Clean up any previous string storage. */ 178 if ( nsldapi_gmatched != NULL ) 179 { 180 ldap_memfree( nsldapi_gmatched ); 181 } 182 if ( nsldapi_gldaperror != NULL ) 183 { 184 ldap_memfree( nsldapi_gldaperror ); 185 } 186 187 nsldapi_gldaperrno = LDErrno; 188 nsldapi_gmatched = LDMatched; 189 nsldapi_gldaperror = LDError; 190 } 191 #else 192 static void * 193 pthread_mutex_alloc( void ) 194 { 195 pthread_mutex_t *mutexp; 196 197 if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { 198 pthread_mutex_init( mutexp, NULL ); 199 } 200 return( mutexp ); 201 } 202 203 static void 204 pthread_mutex_free( void *mutexp ) 205 { 206 pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); 207 free( mutexp ); 208 } 209 210 static void 211 set_ld_error( int err, char *matched, char *errmsg, void *dummy ) 212 { 213 struct nsldapi_ldap_error *le; 214 void *tsd; 215 216 le = pthread_getspecific( nsldapi_key ); 217 218 if (le == NULL) { 219 tsd = (void *)calloc(1, sizeof(struct nsldapi_ldap_error)); 220 pthread_setspecific( nsldapi_key, tsd ); 221 } 222 223 le = pthread_getspecific( nsldapi_key ); 224 225 if (le == NULL) { 226 free(tsd); 227 return; 228 } 229 230 le->le_errno = err; 231 232 if ( le->le_matched != NULL ) { 233 ldap_memfree( le->le_matched ); 234 } 235 le->le_matched = matched; 236 237 if ( le->le_errmsg != NULL ) { 238 ldap_memfree( le->le_errmsg ); 239 } 240 le->le_errmsg = errmsg; 241 } 242 243 static int 244 get_ld_error( char **matched, char **errmsg, void *dummy ) 245 { 246 struct nsldapi_ldap_error *le; 247 248 le = pthread_getspecific( nsldapi_key ); 249 if (le != NULL) { 250 if ( matched != NULL ) { 251 *matched = le->le_matched; 252 } 253 if ( errmsg != NULL ) { 254 *errmsg = le->le_errmsg; 255 } 256 return( le->le_errno ); 257 } else { 258 if ( matched != NULL ) 259 *matched = NULL; 260 if ( errmsg != NULL ) 261 *errmsg = NULL; 262 } 263 return (LDAP_SUCCESS); 264 } 265 266 static void 267 set_errno( int err ) 268 { 269 errno = err; 270 } 271 272 static int 273 get_errno( void ) 274 { 275 return( errno ); 276 } 277 #endif /* _WINDOWS */ 278 279 static struct ldap_thread_fns 280 nsldapi_default_thread_fns = { 281 (void *(*)(void))pthread_mutex_alloc, 282 (void (*)(void *))pthread_mutex_free, 283 (int (*)(void *))pthread_mutex_lock, 284 (int (*)(void *))pthread_mutex_unlock, 285 (int (*)(void))get_errno, 286 (void (*)(int))set_errno, 287 (int (*)(char **, char **, void *))get_ld_error, 288 (void (*)(int, char *, char *, void *))set_ld_error, 289 0 }; 290 291 static struct ldap_extra_thread_fns 292 nsldapi_default_extra_thread_fns = { 293 0, 0, 0, 0, 0, 294 #ifdef _WINDOWS 295 0 296 #else 297 (void *(*)(void))pthread_self 298 #endif /* _WINDOWS */ 299 }; 300 301 void 302 nsldapi_initialize_defaults( void ) 303 { 304 305 if ( nsldapi_initialized ) { 306 return; 307 } 308 #ifdef _SOLARIS_SDK 309 /* 310 * This has to be called before nsldapi_initialized is set to 1 311 * because nsldapi_initialized does not have mutex protection 312 */ 313 prldap_nspr_init(); 314 #endif 315 316 #ifndef _WINDOWS 317 if ( pthread_key_create(&nsldapi_key, free ) != 0) { 318 perror("pthread_key_create"); 319 } 320 #endif /* _WINDOWS */ 321 322 nsldapi_initialized = 1; 323 memset( &nsldapi_memalloc_fns, 0, sizeof( nsldapi_memalloc_fns )); 324 memset( &nsldapi_ld_defaults, 0, sizeof( nsldapi_ld_defaults )); 325 nsldapi_ld_defaults.ld_options = LDAP_BITOPT_REFERRALS; 326 nsldapi_ld_defaults.ld_version = LDAP_VERSION2; 327 nsldapi_ld_defaults.ld_lberoptions = LBER_OPT_USE_DER; 328 nsldapi_ld_defaults.ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; 329 330 #ifdef LDAP_SASLIO_HOOKS 331 /* SASL default option settings */ 332 nsldapi_ld_defaults.ld_def_sasl_mech = NULL; 333 nsldapi_ld_defaults.ld_def_sasl_realm = NULL; 334 nsldapi_ld_defaults.ld_def_sasl_authcid = NULL; 335 nsldapi_ld_defaults.ld_def_sasl_authzid = NULL; 336 /* SASL Security properties */ 337 nsldapi_ld_defaults.ld_sasl_secprops.max_ssf = UINT_MAX; 338 nsldapi_ld_defaults.ld_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE; 339 nsldapi_ld_defaults.ld_sasl_secprops.security_flags = 340 SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; 341 #endif 342 343 #if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET ) 344 nsldapi_ld_defaults.ld_lberoptions |= LBER_OPT_TRANSLATE_STRINGS; 345 #if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET 346 ldap_set_string_translators( &nsldapi_ld_defaults, ldap_8859_to_t61, 347 ldap_t61_to_8859 ); 348 #endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */ 349 #endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */ 350 351 /* set default connect timeout (in milliseconds) */ 352 /* this was picked as it is the standard tcp timeout as well */ 353 nsldapi_ld_defaults.ld_connect_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; 354 355 /* load up default platform specific locking routines */ 356 if (ldap_set_option( NULL, LDAP_OPT_THREAD_FN_PTRS, 357 (void *)&nsldapi_default_thread_fns) != LDAP_SUCCESS) { 358 return; 359 } 360 361 #ifndef _WINDOWS 362 /* load up default threadid function */ 363 if (ldap_set_option( NULL, LDAP_OPT_EXTRA_THREAD_FN_PTRS, 364 (void *)&nsldapi_default_extra_thread_fns) != LDAP_SUCCESS) { 365 return; 366 } 367 #endif /* _WINDOWS */ 368 } 369 370 371 /* 372 * ldap_version - report version levels for important properties 373 * This function is deprecated. Use ldap_get_option( ..., LDAP_OPT_API_INFO, 374 * ... ) instead. 375 * 376 * Example: 377 * LDAPVersion ver; 378 * ldap_version( &ver ); 379 * if ( (ver.sdk_version < 100) || (ver.SSL_version < 300) ) 380 * fprintf( stderr, "LDAP SDK level insufficient\n" ); 381 * 382 * or: 383 * if ( ldap_version(NULL) < 100 ) 384 * fprintf( stderr, "LDAP SDK level insufficient\n" ); 385 * 386 */ 387 388 int 389 LDAP_CALL 390 ldap_version( LDAPVersion *ver ) 391 { 392 if ( NULL != ver ) 393 { 394 memset( ver, 0, sizeof(*ver) ); 395 ver->sdk_version = (int)(VI_PRODUCTVERSION * 100); 396 ver->protocol_version = LDAP_VERSION_MAX * 100; 397 ver->SSL_version = SSL_VERSION * 100; 398 /* 399 * set security to none by default 400 */ 401 402 ver->security_level = LDAP_SECURITY_NONE; 403 #if defined(LINK_SSL) 404 #if defined(NS_DOMESTIC) 405 ver->security_level = 128; 406 #elif defined(NSS_EXPORT) 407 ver->security_level = 40; 408 #endif 409 #endif 410 411 } 412 return (int)(VI_PRODUCTVERSION * 100); 413 } 414 415 /* 416 * ldap_open - initialize and connect to an ldap server. A magic cookie to 417 * be used for future communication is returned on success, NULL on failure. 418 * "host" may be a space-separated list of hosts or IP addresses 419 * 420 * Example: 421 * LDAP *ld; 422 * ld = ldap_open( hostname, port ); 423 */ 424 425 LDAP * 426 LDAP_CALL 427 ldap_open( const char *host, int port ) 428 { 429 LDAP *ld; 430 431 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 ); 432 433 if (( ld = ldap_init( host, port )) == NULL ) { 434 return( NULL ); 435 } 436 437 LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); 438 if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { 439 LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 440 ldap_ld_free( ld, NULL, NULL, 0 ); 441 return( NULL ); 442 } 443 444 LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 445 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n", 446 ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); 447 448 return( ld ); 449 } 450 451 452 /* 453 * ldap_init - initialize the LDAP library. A magic cookie to be used for 454 * future communication is returned on success, NULL on failure. 455 * "defhost" may be a space-separated list of hosts or IP addresses 456 * 457 * Example: 458 * LDAP *ld; 459 * ld = ldap_init( default_hostname, default_port ); 460 */ 461 LDAP * 462 LDAP_CALL 463 ldap_init( const char *defhost, int defport ) 464 { 465 LDAP *ld; 466 467 if ( !nsldapi_initialized ) { 468 nsldapi_initialize_defaults(); 469 } 470 471 if ( defport < 0 || defport > LDAP_PORT_MAX ) { 472 LDAPDebug( LDAP_DEBUG_ANY, 473 "ldap_init: port %d is invalid (port numbers must range from 1 to %d)\n", 474 defport, LDAP_PORT_MAX, 0 ); 475 #if !defined( macintosh ) && !defined( DOS ) 476 errno = EINVAL; 477 #endif 478 return( NULL ); 479 } 480 481 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); 482 483 if ( (ld = (LDAP*)NSLDAPI_MALLOC( sizeof(struct ldap) )) == NULL ) { 484 return( NULL ); 485 } 486 487 /* copy defaults */ 488 SAFEMEMCPY( ld, &nsldapi_ld_defaults, sizeof( struct ldap )); 489 if ( nsldapi_ld_defaults.ld_io_fns_ptr != NULL ) { 490 if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_MALLOC( 491 sizeof( struct ldap_io_fns ))) == NULL ) { 492 NSLDAPI_FREE( (char *)ld ); 493 return( NULL ); 494 } 495 /* struct copy */ 496 *(ld->ld_io_fns_ptr) = *(nsldapi_ld_defaults.ld_io_fns_ptr); 497 } 498 499 /* call the new handle I/O callback if one is defined */ 500 if ( ld->ld_extnewhandle_fn != NULL ) { 501 /* 502 * We always pass the session extended I/O argument to 503 * the new handle callback. 504 */ 505 if ( ld->ld_extnewhandle_fn( ld, ld->ld_ext_session_arg ) 506 != LDAP_SUCCESS ) { 507 NSLDAPI_FREE( (char*)ld ); 508 return( NULL ); 509 } 510 } 511 512 /* allocate session-specific resources */ 513 if (( ld->ld_sbp = ber_sockbuf_alloc()) == NULL || 514 ( defhost != NULL && 515 ( ld->ld_defhost = nsldapi_strdup( defhost )) == NULL ) || 516 ((ld->ld_mutex = (void **) NSLDAPI_CALLOC( LDAP_MAX_LOCK, sizeof(void *))) == NULL )) { 517 if ( ld->ld_sbp != NULL ) { 518 ber_sockbuf_free( ld->ld_sbp ); 519 } 520 if( ld->ld_mutex != NULL ) { 521 NSLDAPI_FREE( ld->ld_mutex ); 522 } 523 NSLDAPI_FREE( (char*)ld ); 524 return( NULL ); 525 } 526 527 /* install Sockbuf I/O functions if set in LDAP * */ 528 if ( ld->ld_extread_fn != NULL || ld->ld_extwrite_fn != NULL ) { 529 struct lber_x_ext_io_fns lberiofns; 530 531 memset( &lberiofns, 0, sizeof( lberiofns )); 532 533 lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; 534 lberiofns.lbextiofn_read = ld->ld_extread_fn; 535 lberiofns.lbextiofn_write = ld->ld_extwrite_fn; 536 lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; 537 lberiofns.lbextiofn_socket_arg = NULL; 538 ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, 539 (void *)&lberiofns ); 540 } 541 542 #ifdef _SOLARIS_SDK 543 /* Install the functions for IPv6 support */ 544 /* code sequencing is critical from here to nsldapi_mutex_alloc_all */ 545 if ( prldap_install_thread_functions( ld, 1 ) != 0 || 546 prldap_install_io_functions( ld, 1 ) != 0 || 547 prldap_install_dns_functions( ld ) != 0 ) { 548 /* go through ld and free resources */ 549 ldap_unbind( ld ); 550 ld = NULL; 551 return( NULL ); 552 } 553 #else 554 555 /* allocate mutexes */ 556 nsldapi_mutex_alloc_all( ld ); 557 #endif 558 559 /* set default port */ 560 ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport; 561 562 return( ld ); 563 } 564 565 void 566 nsldapi_mutex_alloc_all( LDAP *ld ) 567 { 568 int i; 569 570 if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { 571 for ( i = 0; i<LDAP_MAX_LOCK; i++ ) { 572 ld->ld_mutex[i] = LDAP_MUTEX_ALLOC( ld ); 573 ld->ld_mutex_threadid[i] = (void *) -1; 574 ld->ld_mutex_refcnt[i] = 0; 575 } 576 } 577 } 578 579 580 void 581 nsldapi_mutex_free_all( LDAP *ld ) 582 { 583 int i; 584 585 if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { 586 for ( i = 0; i<LDAP_MAX_LOCK; i++ ) { 587 LDAP_MUTEX_FREE( ld, ld->ld_mutex[i] ); 588 } 589 } 590 } 591 592 /* returns 0 if connection opened and -1 if an error occurs */ 593 int 594 nsldapi_open_ldap_defconn( LDAP *ld ) 595 { 596 LDAPServer *srv; 597 598 if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == 599 NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = 600 nsldapi_strdup( ld->ld_defhost )) == NULL )) { 601 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); 602 return( -1 ); 603 } 604 srv->lsrv_port = ld->ld_defport; 605 606 #ifdef LDAP_SSLIO_HOOKS 607 if (( ld->ld_options & LDAP_BITOPT_SSL ) != 0 ) { 608 srv->lsrv_options |= LDAP_SRV_OPT_SECURE; 609 } 610 #endif 611 612 if (( ld->ld_defconn = nsldapi_new_connection( ld, &srv, 1, 1, 0 )) 613 == NULL ) { 614 if ( ld->ld_defhost != NULL ) { 615 NSLDAPI_FREE( srv->lsrv_host ); 616 } 617 NSLDAPI_FREE( (char *)srv ); 618 return( -1 ); 619 } 620 ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ 621 622 return( 0 ); 623 } 624 625 626 struct ldap_x_hostlist_status { 627 char *lhs_hostlist; 628 char *lhs_nexthost; 629 int lhs_defport; 630 }; 631 632 /* 633 * Return the first host and port in hostlist (setting *hostp and *portp). 634 * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). 635 * Note that a NULL or zero-length hostlist causes the host "127.0.0.1" to 636 * be returned. 637 */ 638 int LDAP_CALL 639 ldap_x_hostlist_first( const char *hostlist, int defport, char **hostp, 640 int *portp, struct ldap_x_hostlist_status **statusp ) 641 { 642 643 if ( NULL == hostp || NULL == portp || NULL == statusp ) { 644 return( LDAP_PARAM_ERROR ); 645 } 646 647 if ( NULL == hostlist || *hostlist == '\0' ) { 648 *hostp = nsldapi_strdup( "127.0.0.1" ); 649 if ( NULL == *hostp ) { 650 return( LDAP_NO_MEMORY ); 651 } 652 *portp = defport; 653 *statusp = NULL; 654 return( LDAP_SUCCESS ); 655 } 656 657 *statusp = NSLDAPI_CALLOC( 1, sizeof( struct ldap_x_hostlist_status )); 658 if ( NULL == *statusp ) { 659 return( LDAP_NO_MEMORY ); 660 } 661 (*statusp)->lhs_hostlist = nsldapi_strdup( hostlist ); 662 if ( NULL == (*statusp)->lhs_hostlist ) { 663 return( LDAP_NO_MEMORY ); 664 } 665 (*statusp)->lhs_nexthost = (*statusp)->lhs_hostlist; 666 (*statusp)->lhs_defport = defport; 667 return( ldap_x_hostlist_next( hostp, portp, *statusp )); 668 } 669 670 /* 671 * Return the next host and port in hostlist (setting *hostp and *portp). 672 * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). 673 * If no more hosts are available, LDAP_SUCCESS is returned but *hostp is set 674 * to NULL. 675 */ 676 int LDAP_CALL 677 ldap_x_hostlist_next( char **hostp, int *portp, 678 struct ldap_x_hostlist_status *status ) 679 { 680 char *q; 681 int squarebrackets = 0; 682 683 if ( NULL == hostp || NULL == portp ) { 684 return( LDAP_PARAM_ERROR ); 685 } 686 687 if ( NULL == status || NULL == status->lhs_nexthost ) { 688 *hostp = NULL; 689 return( LDAP_SUCCESS ); 690 } 691 692 /* 693 * skip past leading '[' if present (IPv6 addresses may be surrounded 694 * with square brackets, e.g., [fe80::a00:20ff:fee5:c0b4]:389 695 */ 696 if ( status->lhs_nexthost[0] == '[' ) { 697 ++status->lhs_nexthost; 698 squarebrackets = 1; 699 } 700 701 /* copy host into *hostp */ 702 if ( NULL != ( q = strchr( status->lhs_nexthost, ' ' ))) { 703 size_t len = q - status->lhs_nexthost; 704 *hostp = NSLDAPI_MALLOC( len + 1 ); 705 if ( NULL == *hostp ) { 706 return( LDAP_NO_MEMORY ); 707 } 708 strncpy( *hostp, status->lhs_nexthost, len ); 709 (*hostp)[len] = '\0'; 710 status->lhs_nexthost += ( len + 1 ); 711 } else { /* last host */ 712 *hostp = nsldapi_strdup( status->lhs_nexthost ); 713 if ( NULL == *hostp ) { 714 return( LDAP_NO_MEMORY ); 715 } 716 status->lhs_nexthost = NULL; 717 } 718 719 /* 720 * Look for closing ']' and skip past it before looking for port. 721 */ 722 if ( squarebrackets && NULL != ( q = strchr( *hostp, ']' ))) { 723 *q++ = '\0'; 724 } else { 725 q = *hostp; 726 } 727 728 /* determine and set port */ 729 if ( NULL != ( q = strchr( q, ':' ))) { 730 *q++ = '\0'; 731 *portp = atoi( q ); 732 } else { 733 *portp = status->lhs_defport; 734 } 735 736 return( LDAP_SUCCESS ); 737 } 738 739 740 void LDAP_CALL 741 ldap_x_hostlist_statusfree( struct ldap_x_hostlist_status *status ) 742 { 743 if ( NULL != status ) { 744 if ( NULL != status->lhs_hostlist ) { 745 NSLDAPI_FREE( status->lhs_hostlist ); 746 } 747 NSLDAPI_FREE( status ); 748 } 749 } 750 751 752 753 /* 754 * memory allocation functions. we include these in open.c since every 755 * LDAP application is likely to pull the rest of the code in this file 756 * in anyways. 757 */ 758 void * 759 ldap_x_malloc( size_t size ) 760 { 761 return( nsldapi_memalloc_fns.ldapmem_malloc == NULL ? 762 malloc( size ) : 763 nsldapi_memalloc_fns.ldapmem_malloc( size )); 764 } 765 766 767 void * 768 ldap_x_calloc( size_t nelem, size_t elsize ) 769 { 770 return( nsldapi_memalloc_fns.ldapmem_calloc == NULL ? 771 calloc( nelem, elsize ) : 772 nsldapi_memalloc_fns.ldapmem_calloc( nelem, elsize )); 773 } 774 775 776 void * 777 ldap_x_realloc( void *ptr, size_t size ) 778 { 779 return( nsldapi_memalloc_fns.ldapmem_realloc == NULL ? 780 realloc( ptr, size ) : 781 nsldapi_memalloc_fns.ldapmem_realloc( ptr, size )); 782 } 783 784 785 void 786 ldap_x_free( void *ptr ) 787 { 788 if ( nsldapi_memalloc_fns.ldapmem_free == NULL ) { 789 free( ptr ); 790 } else { 791 nsldapi_memalloc_fns.ldapmem_free( ptr ); 792 } 793 } 794 795 796 /* if s is NULL, returns NULL */ 797 char * 798 nsldapi_strdup( const char *s ) 799 { 800 char *p; 801 802 if ( s == NULL || 803 (p = (char *)NSLDAPI_MALLOC( strlen( s ) + 1 )) == NULL ) 804 return( NULL ); 805 806 strcpy( p, s ); 807 808 return( p ); 809 } 810