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