util-int.c 22 KB

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