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