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