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 ver->security_level = 128; 405 #endif 406 407 } 408 return (int)(VI_PRODUCTVERSION * 100); 409 } 410 411 /* 412 * ldap_open - initialize and connect to an ldap server. A magic cookie to 413 * be used for future communication is returned on success, NULL on failure. 414 * "host" may be a space-separated list of hosts or IP addresses 415 * 416 * Example: 417 * LDAP *ld; 418 * ld = ldap_open( hostname, port ); 419 */ 420 421 LDAP * 422 LDAP_CALL 423 ldap_open( const char *host, int port ) 424 { 425 LDAP *ld; 426 427 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 ); 428 429 if (( ld = ldap_init( host, port )) == NULL ) { 430 return( NULL ); 431 } 432 433 LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); 434 if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { 435 LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 436 ldap_ld_free( ld, NULL, NULL, 0 ); 437 return( NULL ); 438 } 439 440 LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 441 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n", 442 ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); 443 444 return( ld ); 445 } 446 447 448 /* 449 * ldap_init - initialize the LDAP library. A magic cookie to be used for 450 * future communication is returned on success, NULL on failure. 451 * "defhost" may be a space-separated list of hosts or IP addresses 452 * 453 * Example: 454 * LDAP *ld; 455 * ld = ldap_init( default_hostname, default_port ); 456 */ 457 LDAP * 458 LDAP_CALL 459 ldap_init( const char *defhost, int defport ) 460 { 461 LDAP *ld; 462 463 if ( !nsldapi_initialized ) { 464 nsldapi_initialize_defaults(); 465 } 466 467 if ( defport < 0 || defport > LDAP_PORT_MAX ) { 468 LDAPDebug( LDAP_DEBUG_ANY, 469 "ldap_init: port %d is invalid (port numbers must range from 1 to %d)\n", 470 defport, LDAP_PORT_MAX, 0 ); 471 #if !defined( macintosh ) && !defined( DOS ) 472 errno = EINVAL; 473 #endif 474 return( NULL ); 475 } 476 477 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); 478 479 if ( (ld = (LDAP*)NSLDAPI_MALLOC( sizeof(struct ldap) )) == NULL ) { 480 return( NULL ); 481 } 482 483 /* copy defaults */ 484 SAFEMEMCPY( ld, &nsldapi_ld_defaults, sizeof( struct ldap )); 485 if ( nsldapi_ld_defaults.ld_io_fns_ptr != NULL ) { 486 if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_MALLOC( 487 sizeof( struct ldap_io_fns ))) == NULL ) { 488 NSLDAPI_FREE( (char *)ld ); 489 return( NULL ); 490 } 491 /* struct copy */ 492 *(ld->ld_io_fns_ptr) = *(nsldapi_ld_defaults.ld_io_fns_ptr); 493 } 494 495 /* call the new handle I/O callback if one is defined */ 496 if ( ld->ld_extnewhandle_fn != NULL ) { 497 /* 498 * We always pass the session extended I/O argument to 499 * the new handle callback. 500 */ 501 if ( ld->ld_extnewhandle_fn( ld, ld->ld_ext_session_arg ) 502 != LDAP_SUCCESS ) { 503 NSLDAPI_FREE( (char*)ld ); 504 return( NULL ); 505 } 506 } 507 508 /* allocate session-specific resources */ 509 if (( ld->ld_sbp = ber_sockbuf_alloc()) == NULL || 510 ( defhost != NULL && 511 ( ld->ld_defhost = nsldapi_strdup( defhost )) == NULL ) || 512 ((ld->ld_mutex = (void **) NSLDAPI_CALLOC( LDAP_MAX_LOCK, sizeof(void *))) == NULL )) { 513 if ( ld->ld_sbp != NULL ) { 514 ber_sockbuf_free( ld->ld_sbp ); 515 } 516 if( ld->ld_mutex != NULL ) { 517 NSLDAPI_FREE( ld->ld_mutex ); 518 } 519 NSLDAPI_FREE( (char*)ld ); 520 return( NULL ); 521 } 522 523 /* install Sockbuf I/O functions if set in LDAP * */ 524 if ( ld->ld_extread_fn != NULL || ld->ld_extwrite_fn != NULL ) { 525 struct lber_x_ext_io_fns lberiofns; 526 527 memset( &lberiofns, 0, sizeof( lberiofns )); 528 529 lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; 530 lberiofns.lbextiofn_read = ld->ld_extread_fn; 531 lberiofns.lbextiofn_write = ld->ld_extwrite_fn; 532 lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; 533 lberiofns.lbextiofn_socket_arg = NULL; 534 ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, 535 (void *)&lberiofns ); 536 } 537 538 #ifdef _SOLARIS_SDK 539 /* Install the functions for IPv6 support */ 540 /* code sequencing is critical from here to nsldapi_mutex_alloc_all */ 541 if ( prldap_install_thread_functions( ld, 1 ) != 0 || 542 prldap_install_io_functions( ld, 1 ) != 0 || 543 prldap_install_dns_functions( ld ) != 0 ) { 544 /* go through ld and free resources */ 545 ldap_unbind( ld ); 546 ld = NULL; 547 return( NULL ); 548 } 549 #else 550 551 /* allocate mutexes */ 552 nsldapi_mutex_alloc_all( ld ); 553 #endif 554 555 /* set default port */ 556 ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport; 557 558 return( ld ); 559 } 560 561 void 562 nsldapi_mutex_alloc_all( LDAP *ld ) 563 { 564 int i; 565 566 if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { 567 for ( i = 0; i<LDAP_MAX_LOCK; i++ ) { 568 ld->ld_mutex[i] = LDAP_MUTEX_ALLOC( ld ); 569 ld->ld_mutex_threadid[i] = (void *) -1; 570 ld->ld_mutex_refcnt[i] = 0; 571 } 572 } 573 } 574 575 576 void 577 nsldapi_mutex_free_all( LDAP *ld ) 578 { 579 int i; 580 581 if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { 582 for ( i = 0; i<LDAP_MAX_LOCK; i++ ) { 583 LDAP_MUTEX_FREE( ld, ld->ld_mutex[i] ); 584 } 585 } 586 } 587 588 /* returns 0 if connection opened and -1 if an error occurs */ 589 int 590 nsldapi_open_ldap_defconn( LDAP *ld ) 591 { 592 LDAPServer *srv; 593 594 if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == 595 NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = 596 nsldapi_strdup( ld->ld_defhost )) == NULL )) { 597 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); 598 return( -1 ); 599 } 600 srv->lsrv_port = ld->ld_defport; 601 602 #ifdef LDAP_SSLIO_HOOKS 603 if (( ld->ld_options & LDAP_BITOPT_SSL ) != 0 ) { 604 srv->lsrv_options |= LDAP_SRV_OPT_SECURE; 605 } 606 #endif 607 608 if (( ld->ld_defconn = nsldapi_new_connection( ld, &srv, 1, 1, 0 )) 609 == NULL ) { 610 if ( ld->ld_defhost != NULL ) { 611 NSLDAPI_FREE( srv->lsrv_host ); 612 } 613 NSLDAPI_FREE( (char *)srv ); 614 return( -1 ); 615 } 616 ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ 617 618 return( 0 ); 619 } 620 621 622 struct ldap_x_hostlist_status { 623 char *lhs_hostlist; 624 char *lhs_nexthost; 625 int lhs_defport; 626 }; 627 628 /* 629 * Return the first host and port in hostlist (setting *hostp and *portp). 630 * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). 631 * Note that a NULL or zero-length hostlist causes the host "127.0.0.1" to 632 * be returned. 633 */ 634 int LDAP_CALL 635 ldap_x_hostlist_first( const char *hostlist, int defport, char **hostp, 636 int *portp, struct ldap_x_hostlist_status **statusp ) 637 { 638 639 if ( NULL == hostp || NULL == portp || NULL == statusp ) { 640 return( LDAP_PARAM_ERROR ); 641 } 642 643 if ( NULL == hostlist || *hostlist == '\0' ) { 644 *hostp = nsldapi_strdup( "127.0.0.1" ); 645 if ( NULL == *hostp ) { 646 return( LDAP_NO_MEMORY ); 647 } 648 *portp = defport; 649 *statusp = NULL; 650 return( LDAP_SUCCESS ); 651 } 652 653 *statusp = NSLDAPI_CALLOC( 1, sizeof( struct ldap_x_hostlist_status )); 654 if ( NULL == *statusp ) { 655 return( LDAP_NO_MEMORY ); 656 } 657 (*statusp)->lhs_hostlist = nsldapi_strdup( hostlist ); 658 if ( NULL == (*statusp)->lhs_hostlist ) { 659 return( LDAP_NO_MEMORY ); 660 } 661 (*statusp)->lhs_nexthost = (*statusp)->lhs_hostlist; 662 (*statusp)->lhs_defport = defport; 663 return( ldap_x_hostlist_next( hostp, portp, *statusp )); 664 } 665 666 /* 667 * Return the next host and port in hostlist (setting *hostp and *portp). 668 * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). 669 * If no more hosts are available, LDAP_SUCCESS is returned but *hostp is set 670 * to NULL. 671 */ 672 int LDAP_CALL 673 ldap_x_hostlist_next( char **hostp, int *portp, 674 struct ldap_x_hostlist_status *status ) 675 { 676 char *q; 677 int squarebrackets = 0; 678 679 if ( NULL == hostp || NULL == portp ) { 680 return( LDAP_PARAM_ERROR ); 681 } 682 683 if ( NULL == status || NULL == status->lhs_nexthost ) { 684 *hostp = NULL; 685 return( LDAP_SUCCESS ); 686 } 687 688 /* 689 * skip past leading '[' if present (IPv6 addresses may be surrounded 690 * with square brackets, e.g., [fe80::a00:20ff:fee5:c0b4]:389 691 */ 692 if ( status->lhs_nexthost[0] == '[' ) { 693 ++status->lhs_nexthost; 694 squarebrackets = 1; 695 } 696 697 /* copy host into *hostp */ 698 if ( NULL != ( q = strchr( status->lhs_nexthost, ' ' ))) { 699 size_t len = q - status->lhs_nexthost; 700 *hostp = NSLDAPI_MALLOC( len + 1 ); 701 if ( NULL == *hostp ) { 702 return( LDAP_NO_MEMORY ); 703 } 704 strncpy( *hostp, status->lhs_nexthost, len ); 705 (*hostp)[len] = '\0'; 706 status->lhs_nexthost += ( len + 1 ); 707 } else { /* last host */ 708 *hostp = nsldapi_strdup( status->lhs_nexthost ); 709 if ( NULL == *hostp ) { 710 return( LDAP_NO_MEMORY ); 711 } 712 status->lhs_nexthost = NULL; 713 } 714 715 /* 716 * Look for closing ']' and skip past it before looking for port. 717 */ 718 if ( squarebrackets && NULL != ( q = strchr( *hostp, ']' ))) { 719 *q++ = '\0'; 720 } else { 721 q = *hostp; 722 } 723 724 /* determine and set port */ 725 if ( NULL != ( q = strchr( q, ':' ))) { 726 *q++ = '\0'; 727 *portp = atoi( q ); 728 } else { 729 *portp = status->lhs_defport; 730 } 731 732 return( LDAP_SUCCESS ); 733 } 734 735 736 void LDAP_CALL 737 ldap_x_hostlist_statusfree( struct ldap_x_hostlist_status *status ) 738 { 739 if ( NULL != status ) { 740 if ( NULL != status->lhs_hostlist ) { 741 NSLDAPI_FREE( status->lhs_hostlist ); 742 } 743 NSLDAPI_FREE( status ); 744 } 745 } 746 747 748 749 /* 750 * memory allocation functions. we include these in open.c since every 751 * LDAP application is likely to pull the rest of the code in this file 752 * in anyways. 753 */ 754 void * 755 ldap_x_malloc( size_t size ) 756 { 757 return( nsldapi_memalloc_fns.ldapmem_malloc == NULL ? 758 malloc( size ) : 759 nsldapi_memalloc_fns.ldapmem_malloc( size )); 760 } 761 762 763 void * 764 ldap_x_calloc( size_t nelem, size_t elsize ) 765 { 766 return( nsldapi_memalloc_fns.ldapmem_calloc == NULL ? 767 calloc( nelem, elsize ) : 768 nsldapi_memalloc_fns.ldapmem_calloc( nelem, elsize )); 769 } 770 771 772 void * 773 ldap_x_realloc( void *ptr, size_t size ) 774 { 775 return( nsldapi_memalloc_fns.ldapmem_realloc == NULL ? 776 realloc( ptr, size ) : 777 nsldapi_memalloc_fns.ldapmem_realloc( ptr, size )); 778 } 779 780 781 void 782 ldap_x_free( void *ptr ) 783 { 784 if ( nsldapi_memalloc_fns.ldapmem_free == NULL ) { 785 free( ptr ); 786 } else { 787 nsldapi_memalloc_fns.ldapmem_free( ptr ); 788 } 789 } 790 791 792 /* if s is NULL, returns NULL */ 793 char * 794 nsldapi_strdup( const char *s ) 795 { 796 char *p; 797 798 if ( s == NULL || 799 (p = (char *)NSLDAPI_MALLOC( strlen( s ) + 1 )) == NULL ) 800 return( NULL ); 801 802 strcpy( p, s ); 803 804 return( p ); 805 }