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