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