1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2011 The OpenLDAP Foundation. 5 * Portions Copyright 1998 A. Hartgers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* ACKNOWLEDGEMENTS: 17 * This work was initially developed by Bart Hartgers for inclusion in 18 * OpenLDAP Software. 19 */ 20 21/* 22 * util-int.c Various functions to replace missing threadsafe ones. 23 * Without the real *_r funcs, things will 24 * work, but might not be threadsafe. 25 */ 26 27#include "portable.h" 28 29#include <ac/stdlib.h> 30 31#include <ac/errno.h> 32#include <ac/socket.h> 33#include <ac/string.h> 34#include <ac/time.h> 35#include <ac/unistd.h> 36 37#include "ldap-int.h" 38 39#ifdef __APPLE__ 40#define __COREFOUNDATION_CFFILESECURITY__ 41#include <CoreFoundation/CoreFoundation.h> 42#include <SystemConfiguration/SystemConfiguration.h> 43#endif 44 45#ifndef h_errno 46/* newer systems declare this in <netdb.h> for you, older ones don't. 47 * harmless to declare it again (unless defined by a macro). 48 */ 49extern int h_errno; 50#endif 51 52#ifdef HAVE_HSTRERROR 53# define HSTRERROR(e) hstrerror(e) 54#else 55# define HSTRERROR(e) hp_strerror(e) 56#endif 57 58#ifndef LDAP_R_COMPILE 59# undef HAVE_REENTRANT_FUNCTIONS 60# undef HAVE_CTIME_R 61# undef HAVE_GETHOSTBYNAME_R 62# undef HAVE_GETHOSTBYADDR_R 63 64#else 65# include <ldap_pvt_thread.h> 66 ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; 67 68# if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \ 69 && defined( CTIME_R_NARGS ) 70# define USE_CTIME_R 71# else 72 static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex; 73# endif 74 75/* USE_GMTIME_R and USE_LOCALTIME_R defined in ldap_pvt.h */ 76 77#ifdef LDAP_DEVEL 78 /* to be released with 2.5 */ 79#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) 80 /* we use the same mutex for gmtime(3) and localtime(3) 81 * because implementations may use the same buffer 82 * for both functions */ 83 static ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; 84#endif 85#else /* ! LDAP_DEVEL */ 86 ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; 87#endif /* ! LDAP_DEVEL */ 88 89# if defined(HAVE_GETHOSTBYNAME_R) && \ 90 (GETHOSTBYNAME_R_NARGS < 5) || (6 < GETHOSTBYNAME_R_NARGS) 91 /* Don't know how to handle this version, pretend it's not there */ 92# undef HAVE_GETHOSTBYNAME_R 93# endif 94# if defined(HAVE_GETHOSTBYADDR_R) && \ 95 (GETHOSTBYADDR_R_NARGS < 7) || (8 < GETHOSTBYADDR_R_NARGS) 96 /* Don't know how to handle this version, pretend it's not there */ 97# undef HAVE_GETHOSTBYADDR_R 98# endif 99#endif /* LDAP_R_COMPILE */ 100 101char *ldap_pvt_ctime( const time_t *tp, char *buf ) 102{ 103#ifdef USE_CTIME_R 104# if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2) 105# error "CTIME_R_NARGS should be 2 or 3" 106# elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT) 107 return( ctime_r(tp,buf,26) < 0 ? 0 : buf ); 108# elif CTIME_R_NARGS > 2 109 return ctime_r(tp,buf,26); 110# else 111 return ctime_r(tp,buf); 112# endif 113 114#else 115 116 LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex ); 117 AC_MEMCPY( buf, ctime(tp), 26 ); 118 LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex ); 119 120 return buf; 121#endif 122} 123 124#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) 125int 126ldap_pvt_gmtime_lock( void ) 127{ 128# ifndef LDAP_R_COMPILE 129 return 0; 130# else /* LDAP_R_COMPILE */ 131 return ldap_pvt_thread_mutex_lock( &ldap_int_gmtime_mutex ); 132# endif /* LDAP_R_COMPILE */ 133} 134 135int 136ldap_pvt_gmtime_unlock( void ) 137{ 138# ifndef LDAP_R_COMPILE 139 return 0; 140# else /* LDAP_R_COMPILE */ 141 return ldap_pvt_thread_mutex_unlock( &ldap_int_gmtime_mutex ); 142# endif /* LDAP_R_COMPILE */ 143} 144#endif /* !USE_GMTIME_R || !USE_LOCALTIME_R */ 145 146#ifndef USE_GMTIME_R 147struct tm * 148ldap_pvt_gmtime( const time_t *timep, struct tm *result ) 149{ 150 struct tm *tm_ptr; 151 152 LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); 153 tm_ptr = gmtime( timep ); 154 if ( tm_ptr == NULL ) { 155 result = NULL; 156 157 } else { 158 *result = *tm_ptr; 159 } 160 LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); 161 162 return result; 163} 164#endif /* !USE_GMTIME_R */ 165 166#ifndef USE_LOCALTIME_R 167struct tm * 168ldap_pvt_localtime( const time_t *timep, struct tm *result ) 169{ 170 struct tm *tm_ptr; 171 172 LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); 173 tm_ptr = localtime( timep ); 174 if ( tm_ptr == NULL ) { 175 result = NULL; 176 177 } else { 178 *result = *tm_ptr; 179 } 180 LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); 181 182 return result; 183} 184#endif /* !USE_LOCALTIME_R */ 185 186/* return a broken out time, with microseconds 187 * Must be mutex-protected. 188 */ 189#ifdef _WIN32 190/* Windows SYSTEMTIME only has 10 millisecond resolution, so we 191 * also need to use a high resolution timer to get microseconds. 192 * This is pretty clunky. 193 */ 194void 195ldap_pvt_gettime( struct lutil_tm *tm ) 196{ 197 static LARGE_INTEGER cFreq; 198 static LARGE_INTEGER prevCount; 199 static int subs; 200 static int offset; 201 LARGE_INTEGER count; 202 SYSTEMTIME st; 203 204 GetSystemTime( &st ); 205 QueryPerformanceCounter( &count ); 206 207 /* It shouldn't ever go backwards, but multiple CPUs might 208 * be able to hit in the same tick. 209 */ 210 if ( count.QuadPart <= prevCount.QuadPart ) { 211 subs++; 212 } else { 213 subs = 0; 214 prevCount = count; 215 } 216 217 /* We assume Windows has at least a vague idea of 218 * when a second begins. So we align our microsecond count 219 * with the Windows millisecond count using this offset. 220 * We retain the submillisecond portion of our own count. 221 * 222 * Note - this also assumes that the relationship between 223 * the PerformanceCouunter and SystemTime stays constant; 224 * that assumption breaks if the SystemTime is adjusted by 225 * an external action. 226 */ 227 if ( !cFreq.QuadPart ) { 228 long long t; 229 int usec; 230 QueryPerformanceFrequency( &cFreq ); 231 232 /* just get sub-second portion of counter */ 233 t = count.QuadPart % cFreq.QuadPart; 234 235 /* convert to microseconds */ 236 t *= 1000000; 237 usec = t / cFreq.QuadPart; 238 239 offset = usec - st.wMilliseconds * 1000; 240 } 241 242 tm->tm_usub = subs; 243 244 /* convert to microseconds */ 245 count.QuadPart %= cFreq.QuadPart; 246 count.QuadPart *= 1000000; 247 count.QuadPart /= cFreq.QuadPart; 248 count.QuadPart -= offset; 249 250 tm->tm_usec = count.QuadPart % 1000000; 251 if ( tm->tm_usec < 0 ) 252 tm->tm_usec += 1000000; 253 254 /* any difference larger than microseconds is 255 * already reflected in st 256 */ 257 258 tm->tm_sec = st.wSecond; 259 tm->tm_min = st.wMinute; 260 tm->tm_hour = st.wHour; 261 tm->tm_mday = st.wDay; 262 tm->tm_mon = st.wMonth - 1; 263 tm->tm_year = st.wYear - 1900; 264} 265#else 266void 267ldap_pvt_gettime( struct lutil_tm *ltm ) 268{ 269 struct timeval tv; 270 static struct timeval prevTv; 271 static int subs; 272 273 struct tm tm; 274 time_t t; 275 276 gettimeofday( &tv, NULL ); 277 t = tv.tv_sec; 278 279 if ( tv.tv_sec < prevTv.tv_sec 280 || ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec <= prevTv.tv_usec )) { 281 subs++; 282 } else { 283 subs = 0; 284 prevTv = tv; 285 } 286 287 ltm->tm_usub = subs; 288 289 ldap_pvt_gmtime( &t, &tm ); 290 291 ltm->tm_sec = tm.tm_sec; 292 ltm->tm_min = tm.tm_min; 293 ltm->tm_hour = tm.tm_hour; 294 ltm->tm_mday = tm.tm_mday; 295 ltm->tm_mon = tm.tm_mon; 296 ltm->tm_year = tm.tm_year; 297 ltm->tm_usec = tv.tv_usec; 298} 299#endif 300 301size_t 302ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod) 303{ 304 struct lutil_tm tm; 305 int n; 306 307 ldap_pvt_gettime( &tm ); 308 309 n = snprintf( buf, len, 310 "%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x", 311 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, 312 tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_usub, replica, mod ); 313 314 if( n < 0 ) return 0; 315 return ( (size_t) n < len ) ? n : 0; 316} 317 318#define BUFSTART (1024-32) 319#define BUFMAX (32*1024-32) 320 321#if defined(LDAP_R_COMPILE) 322static char *safe_realloc( char **buf, int len ); 323 324#if !(defined(HAVE_GETHOSTBYNAME_R) && defined(HAVE_GETHOSTBYADDR_R)) 325static int copy_hostent( struct hostent *res, 326 char **buf, struct hostent * src ); 327#endif 328#endif 329 330int ldap_pvt_gethostbyname_a( 331 const char *name, 332 struct hostent *resbuf, 333 char **buf, 334 struct hostent **result, 335 int *herrno_ptr ) 336{ 337#if defined( HAVE_GETHOSTBYNAME_R ) 338 339# define NEED_SAFE_REALLOC 1 340 int r=-1; 341 int buflen=BUFSTART; 342 *buf = NULL; 343 for(;buflen<BUFMAX;) { 344 if (safe_realloc( buf, buflen )==NULL) 345 return r; 346 347#if (GETHOSTBYNAME_R_NARGS < 6) 348 *result=gethostbyname_r( name, resbuf, *buf, buflen, herrno_ptr ); 349 r = (*result == NULL) ? -1 : 0; 350#else 351 r = gethostbyname_r( name, resbuf, *buf, 352 buflen, result, herrno_ptr ); 353#endif 354 355 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n", 356 name, r, 0 ); 357 358#ifdef NETDB_INTERNAL 359 if ((r<0) && 360 (*herrno_ptr==NETDB_INTERNAL) && 361 (errno==ERANGE)) 362 { 363 buflen*=2; 364 continue; 365 } 366#endif 367 return r; 368 } 369 return -1; 370#elif defined( LDAP_R_COMPILE ) 371# define NEED_COPY_HOSTENT 372 struct hostent *he; 373 int retval; 374 *buf = NULL; 375 376 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 377 378 he = gethostbyname( name ); 379 380 if (he==NULL) { 381 *herrno_ptr = h_errno; 382 retval = -1; 383 } else if (copy_hostent( resbuf, buf, he )<0) { 384 *herrno_ptr = -1; 385 retval = -1; 386 } else { 387 *result = resbuf; 388 retval = 0; 389 } 390 391 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 392 393 return retval; 394#else 395 *buf = NULL; 396 *result = gethostbyname( name ); 397 398 if (*result!=NULL) { 399 return 0; 400 } 401 402 *herrno_ptr = h_errno; 403 404 return -1; 405#endif 406} 407 408#if !defined( HAVE_GETNAMEINFO ) && !defined( HAVE_HSTRERROR ) 409static const char * 410hp_strerror( int err ) 411{ 412 switch (err) { 413 case HOST_NOT_FOUND: return _("Host not found (authoritative)"); 414 case TRY_AGAIN: return _("Host not found (server fail?)"); 415 case NO_RECOVERY: return _("Non-recoverable failure"); 416 case NO_DATA: return _("No data of requested type"); 417#ifdef NETDB_INTERNAL 418 case NETDB_INTERNAL: return STRERROR( errno ); 419#endif 420 } 421 return _("Unknown resolver error"); 422} 423#endif 424 425int ldap_pvt_get_hname( 426 const struct sockaddr *sa, 427 int len, 428 char *name, 429 int namelen, 430 char **err ) 431{ 432 int rc; 433#if defined( HAVE_GETNAMEINFO ) 434 435 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 436 rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 ); 437 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 438 if ( rc ) *err = (char *)AC_GAI_STRERROR( rc ); 439 return rc; 440 441#else /* !HAVE_GETNAMEINFO */ 442 char *addr; 443 int alen; 444 struct hostent *hp = NULL; 445#ifdef HAVE_GETHOSTBYADDR_R 446 struct hostent hb; 447 int buflen=BUFSTART, h_errno; 448 char *buf=NULL; 449#endif 450 451#ifdef LDAP_PF_INET6 452 if (sa->sa_family == AF_INET6) { 453 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; 454 addr = (char *)&sin->sin6_addr; 455 alen = sizeof(sin->sin6_addr); 456 } else 457#endif 458 if (sa->sa_family == AF_INET) { 459 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 460 addr = (char *)&sin->sin_addr; 461 alen = sizeof(sin->sin_addr); 462 } else { 463 rc = NO_RECOVERY; 464 *err = (char *)HSTRERROR( rc ); 465 return rc; 466 } 467#if defined( HAVE_GETHOSTBYADDR_R ) 468 for(;buflen<BUFMAX;) { 469 if (safe_realloc( &buf, buflen )==NULL) { 470 *err = (char *)STRERROR( ENOMEM ); 471 return ENOMEM; 472 } 473#if (GETHOSTBYADDR_R_NARGS < 8) 474 hp=gethostbyaddr_r( addr, alen, sa->sa_family, 475 &hb, buf, buflen, &h_errno ); 476 rc = (hp == NULL) ? -1 : 0; 477#else 478 rc = gethostbyaddr_r( addr, alen, sa->sa_family, 479 &hb, buf, buflen, 480 &hp, &h_errno ); 481#endif 482#ifdef NETDB_INTERNAL 483 if ((rc<0) && 484 (h_errno==NETDB_INTERNAL) && 485 (errno==ERANGE)) 486 { 487 buflen*=2; 488 continue; 489 } 490#endif 491 break; 492 } 493 if (hp) { 494 strncpy( name, hp->h_name, namelen ); 495 } else { 496 *err = (char *)HSTRERROR( h_errno ); 497 } 498 LDAP_FREE(buf); 499#else /* HAVE_GETHOSTBYADDR_R */ 500 501 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 502 hp = gethostbyaddr( addr, alen, sa->sa_family ); 503 if (hp) { 504 strncpy( name, hp->h_name, namelen ); 505 rc = 0; 506 } else { 507 rc = h_errno; 508 *err = (char *)HSTRERROR( h_errno ); 509 } 510 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 511 512#endif /* !HAVE_GETHOSTBYADDR_R */ 513 return rc; 514#endif /* !HAVE_GETNAMEINFO */ 515} 516 517int ldap_pvt_gethostbyaddr_a( 518 const char *addr, 519 int len, 520 int type, 521 struct hostent *resbuf, 522 char **buf, 523 struct hostent **result, 524 int *herrno_ptr ) 525{ 526#if defined( HAVE_GETHOSTBYADDR_R ) 527 528# undef NEED_SAFE_REALLOC 529# define NEED_SAFE_REALLOC 530 int r=-1; 531 int buflen=BUFSTART; 532 *buf = NULL; 533 for(;buflen<BUFMAX;) { 534 if (safe_realloc( buf, buflen )==NULL) 535 return r; 536#if (GETHOSTBYADDR_R_NARGS < 8) 537 *result=gethostbyaddr_r( addr, len, type, 538 resbuf, *buf, buflen, herrno_ptr ); 539 r = (*result == NULL) ? -1 : 0; 540#else 541 r = gethostbyaddr_r( addr, len, type, 542 resbuf, *buf, buflen, 543 result, herrno_ptr ); 544#endif 545 546#ifdef NETDB_INTERNAL 547 if ((r<0) && 548 (*herrno_ptr==NETDB_INTERNAL) && 549 (errno==ERANGE)) 550 { 551 buflen*=2; 552 continue; 553 } 554#endif 555 return r; 556 } 557 return -1; 558#elif defined( LDAP_R_COMPILE ) 559# undef NEED_COPY_HOSTENT 560# define NEED_COPY_HOSTENT 561 struct hostent *he; 562 int retval; 563 *buf = NULL; 564 565 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 566 he = gethostbyaddr( addr, len, type ); 567 568 if (he==NULL) { 569 *herrno_ptr = h_errno; 570 retval = -1; 571 } else if (copy_hostent( resbuf, buf, he )<0) { 572 *herrno_ptr = -1; 573 retval = -1; 574 } else { 575 *result = resbuf; 576 retval = 0; 577 } 578 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 579 580 return retval; 581 582#else /* gethostbyaddr() */ 583 *buf = NULL; 584 *result = gethostbyaddr( addr, len, type ); 585 586 if (*result!=NULL) { 587 return 0; 588 } 589 return -1; 590#endif 591} 592/* 593 * ldap_int_utils_init() should be called before any other function. 594 */ 595 596void ldap_int_utils_init( void ) 597{ 598 static int done=0; 599 if (done) 600 return; 601 done=1; 602 603#ifdef LDAP_R_COMPILE 604#if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS ) 605 ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex ); 606#endif 607#if !defined( USE_GMTIME_R ) && !defined( USE_LOCALTIME_R ) 608 ldap_pvt_thread_mutex_init( &ldap_int_gmtime_mutex ); 609#endif 610 ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex ); 611 612#ifdef HAVE_CYRUS_SASL 613 ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex ); 614#endif 615#ifdef HAVE_GSSAPI 616 ldap_pvt_thread_mutex_init( &ldap_int_gssapi_mutex ); 617#endif 618#endif 619 620 /* call other module init functions here... */ 621} 622 623#if defined( NEED_COPY_HOSTENT ) 624# undef NEED_SAFE_REALLOC 625#define NEED_SAFE_REALLOC 626 627static char *cpy_aliases( 628 char ***tgtio, 629 char *buf, 630 char **src ) 631{ 632 int len; 633 char **tgt=*tgtio; 634 for( ; (*src) ; src++ ) { 635 len = strlen( *src ) + 1; 636 AC_MEMCPY( buf, *src, len ); 637 *tgt++=buf; 638 buf+=len; 639 } 640 *tgtio=tgt; 641 return buf; 642} 643 644static char *cpy_addresses( 645 char ***tgtio, 646 char *buf, 647 char **src, 648 int len ) 649{ 650 char **tgt=*tgtio; 651 for( ; (*src) ; src++ ) { 652 AC_MEMCPY( buf, *src, len ); 653 *tgt++=buf; 654 buf+=len; 655 } 656 *tgtio=tgt; 657 return buf; 658} 659 660static int copy_hostent( 661 struct hostent *res, 662 char **buf, 663 struct hostent * src ) 664{ 665 char **p; 666 char **tp; 667 char *tbuf; 668 int name_len; 669 int n_alias=0; 670 int total_alias_len=0; 671 int n_addr=0; 672 int total_addr_len=0; 673 int total_len; 674 675 /* calculate the size needed for the buffer */ 676 name_len = strlen( src->h_name ) + 1; 677 678 if( src->h_aliases != NULL ) { 679 for( p = src->h_aliases; (*p) != NULL; p++ ) { 680 total_alias_len += strlen( *p ) + 1; 681 n_alias++; 682 } 683 } 684 685 if( src->h_addr_list != NULL ) { 686 for( p = src->h_addr_list; (*p) != NULL; p++ ) { 687 n_addr++; 688 } 689 total_addr_len = n_addr * src->h_length; 690 } 691 692 total_len = (n_alias + n_addr + 2) * sizeof( char * ) + 693 total_addr_len + total_alias_len + name_len; 694 695 if (safe_realloc( buf, total_len )) { 696 tp = (char **) *buf; 697 tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * ); 698 AC_MEMCPY( res, src, sizeof( struct hostent ) ); 699 /* first the name... */ 700 AC_MEMCPY( tbuf, src->h_name, name_len ); 701 res->h_name = tbuf; tbuf+=name_len; 702 /* now the aliases */ 703 res->h_aliases = tp; 704 if ( src->h_aliases != NULL ) { 705 tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); 706 } 707 *tp++=NULL; 708 /* finally the addresses */ 709 res->h_addr_list = tp; 710 if ( src->h_addr_list != NULL ) { 711 tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); 712 } 713 *tp++=NULL; 714 return 0; 715 } 716 return -1; 717} 718#endif 719 720#if defined( NEED_SAFE_REALLOC ) 721static char *safe_realloc( char **buf, int len ) 722{ 723 char *tmpbuf; 724 tmpbuf = LDAP_REALLOC( *buf, len ); 725 if (tmpbuf) { 726 *buf=tmpbuf; 727 } 728 return tmpbuf; 729} 730#endif 731 732#ifdef __APPLE__ 733char * ldap_pvt_get_fqdn_from_sys_conf ( void ) 734{ 735 char* fqdn = NULL; 736 SCPreferencesRef scpRef = NULL; 737 scpRef = SCPreferencesCreate( NULL, CFSTR("slapd"), 0 ); 738 if ( scpRef != NULL ) { 739 CFDictionaryRef sysDict = (CFDictionaryRef) SCPreferencesGetValue( scpRef, CFSTR("System") ); 740 if ( sysDict != NULL ) { 741 CFDictionaryRef sys2Dict = (CFDictionaryRef) CFDictionaryGetValue( sysDict, CFSTR("System") ); 742 if ( sys2Dict != NULL ) { 743 CFStringRef hostString = (CFStringRef) CFDictionaryGetValue( sys2Dict, CFSTR("HostName") ); 744 if ( hostString != NULL ) { 745 fqdn = LDAP_MALLOC(CFStringGetLength(hostString) + 1); 746 if ( fqdn != NULL) { 747 if ( !CFStringGetCString(hostString, fqdn, CFStringGetLength(hostString) + 1 , kCFStringEncodingUTF8)) { 748 LDAP_FREE(fqdn); 749 fqdn = NULL; 750 } 751 } 752 } 753 } 754 } 755 CFRelease( scpRef ); 756 } 757 return fqdn; 758} 759#endif 760 761char * ldap_pvt_get_fqdn( char *name ) 762{ 763 char *fqdn, *ha_buf; 764 char hostbuf[MAXHOSTNAMELEN+1]; 765 struct hostent *hp, he_buf; 766 int rc, local_h_errno; 767 768 if( name == NULL ) { 769 if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { 770 hostbuf[MAXHOSTNAMELEN] = '\0'; 771 name = hostbuf; 772 } else { 773 name = "localhost"; 774 } 775 } 776 777 rc = ldap_pvt_gethostbyname_a( name, 778 &he_buf, &ha_buf, &hp, &local_h_errno ); 779 780 if( rc < 0 || hp == NULL || hp->h_name == NULL ) { 781 fqdn = LDAP_STRDUP( name ); 782 } else { 783 fqdn = LDAP_STRDUP( hp->h_name ); 784 } 785 786 LDAP_FREE( ha_buf ); 787 return fqdn; 788} 789 790#if ( defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) ) \ 791 && !defined( HAVE_GAI_STRERROR ) 792char *ldap_pvt_gai_strerror (int code) { 793 static struct { 794 int code; 795 const char *msg; 796 } values[] = { 797#ifdef EAI_ADDRFAMILY 798 { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, 799#endif 800 { EAI_AGAIN, N_("Temporary failure in name resolution") }, 801 { EAI_BADFLAGS, N_("Bad value for ai_flags") }, 802 { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, 803 { EAI_FAMILY, N_("ai_family not supported") }, 804 { EAI_MEMORY, N_("Memory allocation failure") }, 805#ifdef EAI_NODATA 806 { EAI_NODATA, N_("No address associated with hostname") }, 807#endif 808 { EAI_NONAME, N_("Name or service not known") }, 809 { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, 810 { EAI_SOCKTYPE, N_("ai_socktype not supported") }, 811 { EAI_SYSTEM, N_("System error") }, 812 { 0, NULL } 813 }; 814 815 int i; 816 817 for ( i = 0; values[i].msg != NULL; i++ ) { 818 if ( values[i].code == code ) { 819 return (char *) _(values[i].msg); 820 } 821 } 822 823 return _("Unknown error"); 824} 825#endif 826