1 /* $NetBSD: util-int.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2021 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.3 2021/08/14 16:14:56 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 #if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) 79 /* we use the same mutex for gmtime(3) and localtime(3) 80 * because implementations may use the same buffer 81 * for both functions */ 82 static ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; 83 #endif 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 97 char *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 LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex ); 113 AC_MEMCPY( buf, ctime(tp), 26 ); 114 LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex ); 115 116 return buf; 117 #endif 118 } 119 120 #if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) 121 int 122 ldap_pvt_gmtime_lock( void ) 123 { 124 # ifndef LDAP_R_COMPILE 125 return 0; 126 # else /* LDAP_R_COMPILE */ 127 return ldap_pvt_thread_mutex_lock( &ldap_int_gmtime_mutex ); 128 # endif /* LDAP_R_COMPILE */ 129 } 130 131 int 132 ldap_pvt_gmtime_unlock( void ) 133 { 134 # ifndef LDAP_R_COMPILE 135 return 0; 136 # else /* LDAP_R_COMPILE */ 137 return ldap_pvt_thread_mutex_unlock( &ldap_int_gmtime_mutex ); 138 # endif /* LDAP_R_COMPILE */ 139 } 140 #endif /* !USE_GMTIME_R || !USE_LOCALTIME_R */ 141 142 #ifndef USE_GMTIME_R 143 struct tm * 144 ldap_pvt_gmtime( const time_t *timep, struct tm *result ) 145 { 146 struct tm *tm_ptr; 147 148 LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); 149 tm_ptr = gmtime( timep ); 150 if ( tm_ptr == NULL ) { 151 result = NULL; 152 153 } else { 154 *result = *tm_ptr; 155 } 156 LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); 157 158 return result; 159 } 160 #endif /* !USE_GMTIME_R */ 161 162 #ifndef USE_LOCALTIME_R 163 struct tm * 164 ldap_pvt_localtime( const time_t *timep, struct tm *result ) 165 { 166 struct tm *tm_ptr; 167 168 LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); 169 tm_ptr = localtime( timep ); 170 if ( tm_ptr == NULL ) { 171 result = NULL; 172 173 } else { 174 *result = *tm_ptr; 175 } 176 LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); 177 178 return result; 179 } 180 #endif /* !USE_LOCALTIME_R */ 181 182 static int _ldap_pvt_gt_subs; 183 184 #ifdef _WIN32 185 /* Windows SYSTEMTIME only has 10 millisecond resolution, so we 186 * also need to use a high resolution timer to get nanoseconds. 187 * This is pretty clunky. 188 */ 189 static LARGE_INTEGER _ldap_pvt_gt_freq; 190 static LARGE_INTEGER _ldap_pvt_gt_prev; 191 static int _ldap_pvt_gt_offset; 192 193 #define SEC_TO_UNIX_EPOCH 11644473600LL 194 #define TICKS_PER_SECOND 10000000 195 #define BILLION 1000000000L 196 197 static int 198 ldap_pvt_gettimensec(int *sec) 199 { 200 LARGE_INTEGER count; 201 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 /* We assume Windows has at least a vague idea of 209 * when a second begins. So we align our nanosecond count 210 * with the Windows millisecond count using this offset. 211 * We retain the submillisecond portion of our own count. 212 * 213 * Note - this also assumes that the relationship between 214 * the PerformanceCounter and SystemTime stays constant; 215 * that assumption breaks if the SystemTime is adjusted by 216 * an external action. 217 */ 218 if ( !_ldap_pvt_gt_freq.QuadPart ) { 219 LARGE_INTEGER c2; 220 ULARGE_INTEGER ut; 221 FILETIME ft0, ft1; 222 long long t; 223 int nsec; 224 225 /* Initialize our offset */ 226 QueryPerformanceFrequency( &_ldap_pvt_gt_freq ); 227 228 /* Wait for a tick of the system time: 10-15ms */ 229 GetSystemTimeAsFileTime( &ft0 ); 230 do { 231 GetSystemTimeAsFileTime( &ft1 ); 232 } while ( ft1.dwLowDateTime == ft0.dwLowDateTime ); 233 234 ut.LowPart = ft1.dwLowDateTime; 235 ut.HighPart = ft1.dwHighDateTime; 236 QueryPerformanceCounter( &c2 ); 237 238 /* get second and fraction portion of counter */ 239 t = c2.QuadPart % (_ldap_pvt_gt_freq.QuadPart*10); 240 241 /* convert to nanoseconds */ 242 t *= BILLION; 243 nsec = t / _ldap_pvt_gt_freq.QuadPart; 244 245 ut.QuadPart /= 10; 246 ut.QuadPart %= (10 * BILLION); 247 _ldap_pvt_gt_offset = nsec - ut.QuadPart; 248 count = c2; 249 } 250 if ( count.QuadPart <= _ldap_pvt_gt_prev.QuadPart ) { 251 _ldap_pvt_gt_subs++; 252 } else { 253 _ldap_pvt_gt_subs = 0; 254 _ldap_pvt_gt_prev = count; 255 } 256 LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); 257 258 /* convert to nanoseconds */ 259 count.QuadPart %= _ldap_pvt_gt_freq.QuadPart*10; 260 count.QuadPart *= BILLION; 261 count.QuadPart /= _ldap_pvt_gt_freq.QuadPart; 262 count.QuadPart -= _ldap_pvt_gt_offset; 263 264 /* We've extracted the 1s and nanoseconds. 265 * The 1sec digit is used to detect wraparound in nanosecnds. 266 */ 267 if (count.QuadPart < 0) 268 count.QuadPart += (10 * BILLION); 269 else if (count.QuadPart >= (10 * BILLION)) 270 count.QuadPart -= (10 * BILLION); 271 272 *sec = count.QuadPart / BILLION; 273 return count.QuadPart % BILLION; 274 } 275 276 277 /* emulate POSIX clock_gettime */ 278 int 279 ldap_pvt_clock_gettime( int clk_id, struct timespec *tv ) 280 { 281 FILETIME ft; 282 ULARGE_INTEGER ut; 283 int sec, sec0; 284 285 GetSystemTimeAsFileTime( &ft ); 286 ut.LowPart = ft.dwLowDateTime; 287 ut.HighPart = ft.dwHighDateTime; 288 289 /* convert to sec */ 290 ut.QuadPart /= TICKS_PER_SECOND; 291 292 tv->tv_nsec = ldap_pvt_gettimensec(&sec); 293 tv->tv_sec = ut.QuadPart - SEC_TO_UNIX_EPOCH; 294 295 /* check for carry from microseconds */ 296 sec0 = tv->tv_sec % 10; 297 if (sec0 < sec || (sec0 == 9 && !sec)) 298 tv->tv_sec++; 299 300 return 0; 301 } 302 303 /* emulate POSIX gettimeofday */ 304 int 305 ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) 306 { 307 struct timespec ts; 308 ldap_pvt_clock_gettime( 0, &ts ); 309 tv->tv_sec = ts.tv_sec; 310 tv->tv_usec = ts.tv_nsec / 1000; 311 return 0; 312 } 313 314 315 /* return a broken out time, with nanoseconds 316 */ 317 void 318 ldap_pvt_gettime( struct lutil_tm *tm ) 319 { 320 SYSTEMTIME st; 321 int sec, sec0; 322 static const char daysPerMonth[] = { 323 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 324 325 GetSystemTime( &st ); 326 tm->tm_nsec = ldap_pvt_gettimensec(&sec); 327 tm->tm_usub = _ldap_pvt_gt_subs; 328 329 /* any difference larger than nanoseconds is 330 * already reflected in st 331 */ 332 tm->tm_sec = st.wSecond; 333 tm->tm_min = st.wMinute; 334 tm->tm_hour = st.wHour; 335 tm->tm_mday = st.wDay; 336 tm->tm_mon = st.wMonth - 1; 337 tm->tm_year = st.wYear - 1900; 338 339 /* check for carry from nanoseconds */ 340 sec0 = tm->tm_sec % 10; 341 if (sec0 < sec || (sec0 == 9 && !sec)) { 342 tm->tm_sec++; 343 /* FIXME: we don't handle leap seconds */ 344 if (tm->tm_sec > 59) { 345 tm->tm_sec = 0; 346 tm->tm_min++; 347 if (tm->tm_min > 59) { 348 tm->tm_min = 0; 349 tm->tm_hour++; 350 if (tm->tm_hour > 23) { 351 int days = daysPerMonth[tm->tm_mon]; 352 tm->tm_hour = 0; 353 tm->tm_mday++; 354 355 /* if it's February of a leap year, 356 * add 1 day to this month 357 */ 358 if (tm->tm_mon == 1 && 359 ((!(st.wYear % 4) && (st.wYear % 100)) || 360 !(st.wYear % 400))) 361 days++; 362 363 if (tm->tm_mday > days) { 364 tm->tm_mday = 1; 365 tm->tm_mon++; 366 if (tm->tm_mon > 11) { 367 tm->tm_mon = 0; 368 tm->tm_year++; 369 } 370 } 371 } 372 } 373 } 374 } 375 } 376 #else 377 378 #ifdef HAVE_CLOCK_GETTIME 379 static struct timespec _ldap_pvt_gt_prevTv; 380 #else 381 static struct timeval _ldap_pvt_gt_prevTv; 382 #endif 383 384 void 385 ldap_pvt_gettime( struct lutil_tm *ltm ) 386 { 387 struct tm tm; 388 time_t t; 389 #ifdef HAVE_CLOCK_GETTIME 390 #define FRAC tv_nsec 391 #define NSECS(x) x 392 struct timespec tv; 393 394 clock_gettime( CLOCK_REALTIME, &tv ); 395 #else 396 #define FRAC tv_usec 397 #define NSECS(x) x * 1000 398 struct timeval tv; 399 400 gettimeofday( &tv, NULL ); 401 #endif 402 t = tv.tv_sec; 403 404 LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); 405 if ( tv.tv_sec < _ldap_pvt_gt_prevTv.tv_sec 406 || ( tv.tv_sec == _ldap_pvt_gt_prevTv.tv_sec 407 && tv.FRAC <= _ldap_pvt_gt_prevTv.FRAC )) { 408 _ldap_pvt_gt_subs++; 409 } else { 410 _ldap_pvt_gt_subs = 0; 411 _ldap_pvt_gt_prevTv = tv; 412 } 413 LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); 414 415 ltm->tm_usub = _ldap_pvt_gt_subs; 416 417 ldap_pvt_gmtime( &t, &tm ); 418 419 ltm->tm_sec = tm.tm_sec; 420 ltm->tm_min = tm.tm_min; 421 ltm->tm_hour = tm.tm_hour; 422 ltm->tm_mday = tm.tm_mday; 423 ltm->tm_mon = tm.tm_mon; 424 ltm->tm_year = tm.tm_year; 425 ltm->tm_nsec = NSECS(tv.FRAC); 426 } 427 #endif 428 429 size_t 430 ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod) 431 { 432 struct lutil_tm tm; 433 int n; 434 435 ldap_pvt_gettime( &tm ); 436 437 n = snprintf( buf, len, 438 "%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x", 439 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, 440 tm.tm_min, tm.tm_sec, tm.tm_nsec / 1000, tm.tm_usub, replica, mod ); 441 442 if( n < 0 ) return 0; 443 return ( (size_t) n < len ) ? n : 0; 444 } 445 446 #define BUFSTART (1024-32) 447 #define BUFMAX (32*1024-32) 448 449 #if defined(LDAP_R_COMPILE) 450 static char *safe_realloc( char **buf, int len ); 451 452 #if !(defined(HAVE_GETHOSTBYNAME_R) && defined(HAVE_GETHOSTBYADDR_R)) 453 static int copy_hostent( struct hostent *res, 454 char **buf, struct hostent * src ); 455 #endif 456 #endif 457 458 int ldap_pvt_gethostbyname_a( 459 const char *name, 460 struct hostent *resbuf, 461 char **buf, 462 struct hostent **result, 463 int *herrno_ptr ) 464 { 465 #if defined( HAVE_GETHOSTBYNAME_R ) 466 467 # define NEED_SAFE_REALLOC 1 468 int r=-1; 469 int buflen=BUFSTART; 470 *buf = NULL; 471 for(;buflen<BUFMAX;) { 472 if (safe_realloc( buf, buflen )==NULL) 473 return r; 474 475 #if (GETHOSTBYNAME_R_NARGS < 6) 476 *result=gethostbyname_r( name, resbuf, *buf, buflen, herrno_ptr ); 477 r = (*result == NULL) ? -1 : 0; 478 #else 479 while((r = gethostbyname_r( name, resbuf, *buf, buflen, result, herrno_ptr )) == ERANGE) { 480 /* Increase the buffer */ 481 buflen*=2; 482 if (safe_realloc(buf, buflen) == NULL) 483 return -1; 484 } 485 #endif 486 487 Debug2( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n", 488 name, r ); 489 490 #ifdef NETDB_INTERNAL 491 if ((r<0) && 492 (*herrno_ptr==NETDB_INTERNAL) && 493 (errno==ERANGE)) 494 { 495 buflen*=2; 496 continue; 497 } 498 #endif 499 return r; 500 } 501 return -1; 502 #elif defined( LDAP_R_COMPILE ) 503 # define NEED_COPY_HOSTENT 504 struct hostent *he; 505 int retval; 506 *buf = NULL; 507 508 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 509 510 he = gethostbyname( name ); 511 512 if (he==NULL) { 513 *herrno_ptr = h_errno; 514 retval = -1; 515 } else if (copy_hostent( resbuf, buf, he )<0) { 516 *herrno_ptr = -1; 517 retval = -1; 518 } else { 519 *result = resbuf; 520 retval = 0; 521 } 522 523 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 524 525 return retval; 526 #else 527 *buf = NULL; 528 *result = gethostbyname( name ); 529 530 if (*result!=NULL) { 531 return 0; 532 } 533 534 *herrno_ptr = h_errno; 535 536 return -1; 537 #endif 538 } 539 540 #if !defined( HAVE_GETNAMEINFO ) && !defined( HAVE_HSTRERROR ) 541 static const char * 542 hp_strerror( int err ) 543 { 544 switch (err) { 545 case HOST_NOT_FOUND: return _("Host not found (authoritative)"); 546 case TRY_AGAIN: return _("Host not found (server fail?)"); 547 case NO_RECOVERY: return _("Non-recoverable failure"); 548 case NO_DATA: return _("No data of requested type"); 549 #ifdef NETDB_INTERNAL 550 case NETDB_INTERNAL: return STRERROR( errno ); 551 #endif 552 } 553 return _("Unknown resolver error"); 554 } 555 #endif 556 557 int ldap_pvt_get_hname( 558 const struct sockaddr *sa, 559 int len, 560 char *name, 561 int namelen, 562 char **err ) 563 { 564 int rc; 565 #if defined( HAVE_GETNAMEINFO ) 566 567 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 568 rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 ); 569 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 570 if ( rc ) *err = (char *)AC_GAI_STRERROR( rc ); 571 return rc; 572 573 #else /* !HAVE_GETNAMEINFO */ 574 char *addr; 575 int alen; 576 struct hostent *hp = NULL; 577 #ifdef HAVE_GETHOSTBYADDR_R 578 struct hostent hb; 579 int buflen=BUFSTART, h_errno; 580 char *buf=NULL; 581 #endif 582 583 #ifdef LDAP_PF_INET6 584 if (sa->sa_family == AF_INET6) { 585 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; 586 addr = (char *)&sin->sin6_addr; 587 alen = sizeof(sin->sin6_addr); 588 } else 589 #endif 590 if (sa->sa_family == AF_INET) { 591 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 592 addr = (char *)&sin->sin_addr; 593 alen = sizeof(sin->sin_addr); 594 } else { 595 rc = NO_RECOVERY; 596 *err = (char *)HSTRERROR( rc ); 597 return rc; 598 } 599 #if defined( HAVE_GETHOSTBYADDR_R ) 600 for(;buflen<BUFMAX;) { 601 if (safe_realloc( &buf, buflen )==NULL) { 602 *err = (char *)STRERROR( ENOMEM ); 603 return ENOMEM; 604 } 605 #if (GETHOSTBYADDR_R_NARGS < 8) 606 hp=gethostbyaddr_r( addr, alen, sa->sa_family, 607 &hb, buf, buflen, &h_errno ); 608 rc = (hp == NULL) ? -1 : 0; 609 #else 610 rc = gethostbyaddr_r( addr, alen, sa->sa_family, 611 &hb, buf, buflen, 612 &hp, &h_errno ); 613 #endif 614 #ifdef NETDB_INTERNAL 615 if ((rc<0) && 616 (h_errno==NETDB_INTERNAL) && 617 (errno==ERANGE)) 618 { 619 buflen*=2; 620 continue; 621 } 622 #endif 623 break; 624 } 625 if (hp) { 626 strncpy( name, hp->h_name, namelen ); 627 } else { 628 *err = (char *)HSTRERROR( h_errno ); 629 } 630 LDAP_FREE(buf); 631 #else /* HAVE_GETHOSTBYADDR_R */ 632 633 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 634 hp = gethostbyaddr( addr, alen, sa->sa_family ); 635 if (hp) { 636 strncpy( name, hp->h_name, namelen ); 637 rc = 0; 638 } else { 639 rc = h_errno; 640 *err = (char *)HSTRERROR( h_errno ); 641 } 642 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 643 644 #endif /* !HAVE_GETHOSTBYADDR_R */ 645 return rc; 646 #endif /* !HAVE_GETNAMEINFO */ 647 } 648 649 int ldap_pvt_gethostbyaddr_a( 650 const char *addr, 651 int len, 652 int type, 653 struct hostent *resbuf, 654 char **buf, 655 struct hostent **result, 656 int *herrno_ptr ) 657 { 658 #if defined( HAVE_GETHOSTBYADDR_R ) 659 660 # undef NEED_SAFE_REALLOC 661 # define NEED_SAFE_REALLOC 662 int r=-1; 663 int buflen=BUFSTART; 664 *buf = NULL; 665 for(;buflen<BUFMAX;) { 666 if (safe_realloc( buf, buflen )==NULL) 667 return r; 668 #if (GETHOSTBYADDR_R_NARGS < 8) 669 *result=gethostbyaddr_r( addr, len, type, 670 resbuf, *buf, buflen, herrno_ptr ); 671 r = (*result == NULL) ? -1 : 0; 672 #else 673 r = gethostbyaddr_r( addr, len, type, 674 resbuf, *buf, buflen, 675 result, herrno_ptr ); 676 #endif 677 678 #ifdef NETDB_INTERNAL 679 if ((r<0) && 680 (*herrno_ptr==NETDB_INTERNAL) && 681 (errno==ERANGE)) 682 { 683 buflen*=2; 684 continue; 685 } 686 #endif 687 return r; 688 } 689 return -1; 690 #elif defined( LDAP_R_COMPILE ) 691 # undef NEED_COPY_HOSTENT 692 # define NEED_COPY_HOSTENT 693 struct hostent *he; 694 int retval; 695 *buf = NULL; 696 697 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 698 he = gethostbyaddr( addr, len, type ); 699 700 if (he==NULL) { 701 *herrno_ptr = h_errno; 702 retval = -1; 703 } else if (copy_hostent( resbuf, buf, he )<0) { 704 *herrno_ptr = -1; 705 retval = -1; 706 } else { 707 *result = resbuf; 708 retval = 0; 709 } 710 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 711 712 return retval; 713 714 #else /* gethostbyaddr() */ 715 *buf = NULL; 716 *result = gethostbyaddr( addr, len, type ); 717 718 if (*result!=NULL) { 719 return 0; 720 } 721 return -1; 722 #endif 723 } 724 /* 725 * ldap_int_utils_init() should be called before any other function. 726 */ 727 728 void ldap_int_utils_init( void ) 729 { 730 static int done=0; 731 if (done) 732 return; 733 done=1; 734 735 #ifdef LDAP_R_COMPILE 736 #if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS ) 737 ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex ); 738 #endif 739 #if !defined( USE_GMTIME_R ) && !defined( USE_LOCALTIME_R ) 740 ldap_pvt_thread_mutex_init( &ldap_int_gmtime_mutex ); 741 #endif 742 ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex ); 743 744 ldap_pvt_thread_mutex_init( &ldap_int_hostname_mutex ); 745 746 ldap_pvt_thread_mutex_init( &ldap_int_gettime_mutex ); 747 748 #ifdef HAVE_GSSAPI 749 ldap_pvt_thread_mutex_init( &ldap_int_gssapi_mutex ); 750 #endif 751 #endif 752 753 /* call other module init functions here... */ 754 } 755 756 #if defined( NEED_COPY_HOSTENT ) 757 # undef NEED_SAFE_REALLOC 758 #define NEED_SAFE_REALLOC 759 760 static char *cpy_aliases( 761 char ***tgtio, 762 char *buf, 763 char **src ) 764 { 765 int len; 766 char **tgt=*tgtio; 767 for( ; (*src) ; src++ ) { 768 len = strlen( *src ) + 1; 769 AC_MEMCPY( buf, *src, len ); 770 *tgt++=buf; 771 buf+=len; 772 } 773 *tgtio=tgt; 774 return buf; 775 } 776 777 static char *cpy_addresses( 778 char ***tgtio, 779 char *buf, 780 char **src, 781 int len ) 782 { 783 char **tgt=*tgtio; 784 for( ; (*src) ; src++ ) { 785 AC_MEMCPY( buf, *src, len ); 786 *tgt++=buf; 787 buf+=len; 788 } 789 *tgtio=tgt; 790 return buf; 791 } 792 793 static int copy_hostent( 794 struct hostent *res, 795 char **buf, 796 struct hostent * src ) 797 { 798 char **p; 799 char **tp; 800 char *tbuf; 801 int name_len; 802 int n_alias=0; 803 int total_alias_len=0; 804 int n_addr=0; 805 int total_addr_len=0; 806 int total_len; 807 808 /* calculate the size needed for the buffer */ 809 name_len = strlen( src->h_name ) + 1; 810 811 if( src->h_aliases != NULL ) { 812 for( p = src->h_aliases; (*p) != NULL; p++ ) { 813 total_alias_len += strlen( *p ) + 1; 814 n_alias++; 815 } 816 } 817 818 if( src->h_addr_list != NULL ) { 819 for( p = src->h_addr_list; (*p) != NULL; p++ ) { 820 n_addr++; 821 } 822 total_addr_len = n_addr * src->h_length; 823 } 824 825 total_len = (n_alias + n_addr + 2) * sizeof( char * ) + 826 total_addr_len + total_alias_len + name_len; 827 828 if (safe_realloc( buf, total_len )) { 829 tp = (char **) *buf; 830 tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * ); 831 AC_MEMCPY( res, src, sizeof( struct hostent ) ); 832 /* first the name... */ 833 AC_MEMCPY( tbuf, src->h_name, name_len ); 834 res->h_name = tbuf; tbuf+=name_len; 835 /* now the aliases */ 836 res->h_aliases = tp; 837 if ( src->h_aliases != NULL ) { 838 tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); 839 } 840 *tp++=NULL; 841 /* finally the addresses */ 842 res->h_addr_list = tp; 843 if ( src->h_addr_list != NULL ) { 844 tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); 845 } 846 *tp++=NULL; 847 return 0; 848 } 849 return -1; 850 } 851 #endif 852 853 #if defined( NEED_SAFE_REALLOC ) 854 static char *safe_realloc( char **buf, int len ) 855 { 856 char *tmpbuf; 857 tmpbuf = LDAP_REALLOC( *buf, len ); 858 if (tmpbuf) { 859 *buf=tmpbuf; 860 } 861 return tmpbuf; 862 } 863 #endif 864 865 char * ldap_pvt_get_fqdn( char *name ) 866 { 867 #ifdef HAVE_GETADDRINFO 868 struct addrinfo hints, *res; 869 #else 870 char *ha_buf; 871 struct hostent *hp, he_buf; 872 int local_h_errno; 873 #endif 874 int rc; 875 char *fqdn, hostbuf[MAXHOSTNAMELEN+1]; 876 877 if( name == NULL ) { 878 if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { 879 hostbuf[MAXHOSTNAMELEN] = '\0'; 880 name = hostbuf; 881 } else { 882 name = "localhost"; 883 } 884 } 885 886 #ifdef HAVE_GETADDRINFO 887 memset( &hints, 0, sizeof( hints )); 888 hints.ai_family = AF_UNSPEC; 889 hints.ai_flags = AI_CANONNAME; 890 891 LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); 892 rc = getaddrinfo( name, NULL, &hints, &res ); 893 LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); 894 if ( rc == 0 && res->ai_canonname ) { 895 fqdn = LDAP_STRDUP( res->ai_canonname ); 896 } else { 897 fqdn = LDAP_STRDUP( name ); 898 } 899 if ( rc == 0 ) 900 freeaddrinfo( res ); 901 #else 902 rc = ldap_pvt_gethostbyname_a( name, 903 &he_buf, &ha_buf, &hp, &local_h_errno ); 904 905 if( rc < 0 || hp == NULL || hp->h_name == NULL ) { 906 fqdn = LDAP_STRDUP( name ); 907 } else { 908 fqdn = LDAP_STRDUP( hp->h_name ); 909 } 910 911 LDAP_FREE( ha_buf ); 912 #endif 913 return fqdn; 914 } 915 916 #if ( defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) ) \ 917 && !defined( HAVE_GAI_STRERROR ) 918 char *ldap_pvt_gai_strerror (int code) { 919 static struct { 920 int code; 921 const char *msg; 922 } values[] = { 923 #ifdef EAI_ADDRFAMILY 924 { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, 925 #endif 926 { EAI_AGAIN, N_("Temporary failure in name resolution") }, 927 { EAI_BADFLAGS, N_("Bad value for ai_flags") }, 928 { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, 929 { EAI_FAMILY, N_("ai_family not supported") }, 930 { EAI_MEMORY, N_("Memory allocation failure") }, 931 #ifdef EAI_NODATA 932 { EAI_NODATA, N_("No address associated with hostname") }, 933 #endif 934 { EAI_NONAME, N_("Name or service not known") }, 935 { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, 936 { EAI_SOCKTYPE, N_("ai_socktype not supported") }, 937 #ifdef EAI_SYSTEM 938 { EAI_SYSTEM, N_("System error") }, 939 #endif 940 { 0, NULL } 941 }; 942 943 int i; 944 945 for ( i = 0; values[i].msg != NULL; i++ ) { 946 if ( values[i].code == code ) { 947 return (char *) _(values[i].msg); 948 } 949 } 950 951 return _("Unknown error"); 952 } 953 #endif 954 955 /* format a socket address as a string */ 956 957 #ifdef HAVE_TCPD 958 # include <tcpd.h> 959 # define SOCKADDR_STRING_UNKNOWN STRING_UNKNOWN 960 #else /* ! TCP Wrappers */ 961 # define SOCKADDR_STRING_UNKNOWN "unknown" 962 #endif /* ! TCP Wrappers */ 963 964 void 965 ldap_pvt_sockaddrstr( Sockaddr *sa, struct berval *addrbuf ) 966 { 967 char *addr; 968 switch( sa->sa_addr.sa_family ) { 969 #ifdef LDAP_PF_LOCAL 970 case AF_LOCAL: 971 addrbuf->bv_len = snprintf( addrbuf->bv_val, addrbuf->bv_len, 972 "PATH=%s", sa->sa_un_addr.sun_path ); 973 break; 974 #endif 975 #ifdef LDAP_PF_INET6 976 case AF_INET6: 977 strcpy(addrbuf->bv_val, "IP="); 978 if ( IN6_IS_ADDR_V4MAPPED(&sa->sa_in6_addr.sin6_addr) ) { 979 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 980 addr = (char *)inet_ntop( AF_INET, 981 ((struct in_addr *)&sa->sa_in6_addr.sin6_addr.s6_addr[12]), 982 addrbuf->bv_val+3, addrbuf->bv_len-3 ); 983 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 984 addr = inet_ntoa( *((struct in_addr *) 985 &sa->sa_in6_addr.sin6_addr.s6_addr[12]) ); 986 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 987 if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; 988 if ( addr != addrbuf->bv_val+3 ) { 989 addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "%s:%d", addr, 990 (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + 3; 991 } else { 992 int len = strlen( addr ); 993 addrbuf->bv_len = sprintf( addr+len, ":%d", 994 (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + len + 3; 995 } 996 } else { 997 addr = (char *)inet_ntop( AF_INET6, 998 &sa->sa_in6_addr.sin6_addr, 999 addrbuf->bv_val+4, addrbuf->bv_len-4 ); 1000 if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; 1001 if ( addr != addrbuf->bv_val+4 ) { 1002 addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "[%s]:%d", addr, 1003 (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + 3; 1004 } else { 1005 int len = strlen( addr ); 1006 addrbuf->bv_val[3] = '['; 1007 addrbuf->bv_len = sprintf( addr+len, "]:%d", 1008 (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + len + 4; 1009 } 1010 } 1011 break; 1012 #endif /* LDAP_PF_INET6 */ 1013 case AF_INET: 1014 strcpy(addrbuf->bv_val, "IP="); 1015 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) 1016 addr = (char *)inet_ntop( AF_INET, &sa->sa_in_addr.sin_addr, 1017 addrbuf->bv_val+3, addrbuf->bv_len-3 ); 1018 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 1019 addr = inet_ntoa( sa->sa_in_addr.sin_addr ); 1020 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 1021 if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; 1022 if ( addr != addrbuf->bv_val+3 ) { 1023 addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "%s:%d", addr, 1024 (unsigned) ntohs( sa->sa_in_addr.sin_port ) ) + 3; 1025 } else { 1026 int len = strlen( addr ); 1027 addrbuf->bv_len = sprintf( addr+len, ":%d", 1028 (unsigned) ntohs( sa->sa_in_addr.sin_port ) ) + len + 3; 1029 } 1030 break; 1031 default: 1032 addrbuf->bv_val[0] = '\0'; 1033 } 1034 } 1035