]> git.sur5r.net Git - openldap/blob - libraries/libldap/util-int.c
Cast char* argument to hh_to_c() to Byte*
[openldap] / libraries / libldap / util-int.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * util-int.c   Various functions to replace missing threadsafe ones.
7  *                                Without the real *_r funcs, things will
8  *                                work, but might not be threadsafe. 
9  * 
10  * Written by Bart Hartgers.
11  *
12  * Copyright 1998, A. Hartgers, All rights reserved.
13  * This software is not subject to any license of Eindhoven University of
14  * Technology, since it was written in my spare time.
15  *                      
16  * Redistribution and use in source and binary forms are permitted only
17  * as authorized by the OpenLDAP Public License.  A copy of this
18  * license is available at http://www.OpenLDAP.org/license.html or
19  * in file LICENSE in the top-level directory of the distribution.
20  */ 
21
22
23 #include "portable.h"
24
25 #include <stdlib.h>
26
27 #include <ac/errno.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "ldap-int.h"
33
34 #if defined( LDAP_R_COMPILE )
35 # include <ldap_pvt_thread.h>
36 #else
37 # undef HAVE_REENTRANT_FUNCTIONS
38 #endif
39
40 #if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \
41         && defined( CTIME_R_NARGS )
42 #       define USE_CTIME_R
43 #endif
44
45 #if defined(HAVE_GETHOSTBYNAME_R) && \
46     (GETHOSTBYNAME_R_NARGS > 6 || GETHOSTBYNAME_R_NARGS < 5)
47         /* Don't know how to handle this version, pretend it's not there */
48 #       undef HAVE_GETHOSTBYNAME_R
49 #endif
50 #if defined(HAVE_GETHOSTBYADDR_R) && \
51     (GETHOSTBYADDR_R_NARGS > 8 || GETHOSTBYADDR_R_NARGS < 7)
52         /* Don't know how to handle this version, pretend it's not there */
53 #       undef HAVE_GETHOSTBYADDR_R
54 #endif
55
56 #ifdef LDAP_R_COMPILE
57 # ifndef USE_CTIME_R
58         static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex;
59 # endif
60 # ifndef HAVE_GETHOSTBYNAME_R
61         static ldap_pvt_thread_mutex_t ldap_int_gethostbyname_mutex;
62 # endif
63 # ifndef HAVE_GETHOSTBYADDR_R
64         static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex;
65 # endif
66 #endif /* LDAP_R_COMPILE */
67
68 char *ldap_pvt_ctime( const time_t *tp, char *buf )
69 {
70 #ifdef USE_CTIME_R
71 # if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2)
72         choke me!  nargs should have 2 or 3
73 # elif CTIME_R_NARGS > 2
74         return ctime_r(tp,buf,26);
75 # else
76         return ctime_r(tp,buf);
77 # endif   
78
79 #else
80 # ifdef LDAP_R_COMPILE
81         ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
82 # endif
83         memcpy( buf, ctime(tp), 26 );
84 # ifdef LDAP_R_COMPILE
85         ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
86 # endif
87         return buf;
88 #endif  
89 }
90
91 #define BUFSTART 1024
92 #define BUFMAX (32*1024)
93
94 static char *safe_realloc( char **buf, int len );
95 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src );
96
97 int ldap_pvt_gethostbyname_a(
98         const char *name, 
99         struct hostent *resbuf,
100         char **buf,
101         struct hostent **result,
102         int *herrno_ptr )
103 {
104 #if defined( HAVE_GETHOSTBYNAME_R )
105
106 # define NEED_SAFE_REALLOC 1   
107         int r=-1;
108         int buflen=BUFSTART;
109         *buf = NULL;
110         for(;buflen<BUFMAX;) {
111                 if (safe_realloc( buf, buflen )==NULL)
112                         return r;
113
114 #if (GETHOSTBYNAME_R_NARGS < 6)
115                 r = ((*result=gethostbyname_r( name, resbuf, *buf,\
116                                                buflen, herrno_ptr ))== NULL) ?\
117                     -1 : 0;
118 #else
119                 r = gethostbyname_r( name, resbuf, *buf,
120                         buflen, result, herrno_ptr );
121 #endif
122
123                 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n",\
124                        name, r, 0 );
125
126 #ifdef NETDB_INTERNAL
127                 if ((r<0) &&
128                         (*herrno_ptr==NETDB_INTERNAL) &&
129                         (errno==ERANGE))
130                 {
131                         buflen*=2;
132                         continue;
133                 }
134 #endif
135                 return r;
136         }
137         return -1;
138 #elif defined( LDAP_R_COMPILE )
139 # define NEED_COPY_HOSTENT   
140         struct hostent *he;
141         int     retval;
142         
143         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyname_mutex );
144         
145         he = gethostbyname( name );
146         
147         if (he==NULL) {
148                 *herrno_ptr = h_errno;
149                 retval = -1;
150         } else if (copy_hostent( resbuf, buf, he )<0) {
151                 *herrno_ptr = -1;
152                 retval = -1;
153         } else {
154                 *result = resbuf;
155                 retval = 0;
156         }
157         
158         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyname_mutex );
159         
160         return retval;
161 #else   
162         *result = gethostbyname( name );
163
164         if (*result!=NULL) {
165                 return 0;
166         }
167
168         *herrno_ptr = h_errno;
169         
170         return -1;
171 #endif  
172 }
173          
174 int ldap_pvt_gethostbyaddr_a(
175         const char *addr,
176         int len,
177         int type,
178         struct hostent *resbuf,
179         char **buf,
180         struct hostent **result,
181         int *herrno_ptr )
182 {
183 #if defined( HAVE_GETHOSTBYADDR_R )
184
185 # undef NEED_SAFE_REALLOC
186 # define NEED_SAFE_REALLOC   
187         int r=-1;
188         int buflen=BUFSTART;
189         *buf = NULL;   
190         for(;buflen<BUFMAX;) {
191                 if (safe_realloc( buf, buflen )==NULL)
192                         return r;
193 #if (GETHOSTBYADDR_R_NARGS < 8)
194                 r = ((*result=gethostbyaddr_r( addr, len, type,
195                                                resbuf, *buf, buflen, 
196                                                herrno_ptr )) == NULL) ?\
197                     -1 : 0;
198 #else
199                 r = gethostbyaddr_r( addr, len, type,
200                         resbuf, *buf, buflen, 
201                         result, herrno_ptr );
202 #endif
203
204 #ifdef NETDB_INTERNAL
205                 if ((r<0) &&
206                         (*herrno_ptr==NETDB_INTERNAL) &&
207                         (errno==ERANGE))
208                 {
209                         buflen*=2;
210                         continue;
211                 }
212 #endif
213                 return r;
214         }
215         return -1;
216 #elif defined( LDAP_R_COMPILE )
217 # undef NEED_COPY_HOSTENT
218 # define NEED_COPY_HOSTENT   
219         struct hostent *he;
220         int     retval;
221         
222         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyaddr_mutex );
223         
224         he = gethostbyaddr( addr, len, type );
225         
226         if (he==NULL) {
227                 *herrno_ptr = h_errno;
228                 retval = -1;
229         } else if (copy_hostent( resbuf, buf, he )<0) {
230                 *herrno_ptr = -1;
231                 retval = -1;
232         } else {
233                 *result = resbuf;
234                 retval = 0;
235         }
236         
237         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyaddr_mutex );
238         
239         return retval;   
240 #else /* gethostbyaddr() */
241         *result = gethostbyaddr( addr, len, type );
242
243         if (*result!=NULL) {
244                 return 0;
245         }
246         return -1;
247 #endif  
248 }
249 /* 
250  * ldap_pvt_init_utils() should be called before any other function.
251  */
252
253 void ldap_pvt_init_utils( void )
254 {
255         static int done=0;
256         if (done)
257           return;
258         done=1;
259
260 #ifdef LDAP_R_COMPILE
261
262 #if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS )
263         ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex );
264 #endif
265
266 #if !defined( HAVE_GETHOSTBYNAME_R )
267         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyname_mutex );
268 #endif
269
270 #if !defined( HAVE_GETHOSTBYADDR_R )
271         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex );
272 #endif
273
274         /* call other module init functions here... */
275 #endif
276 }
277
278 #if defined( NEED_COPY_HOSTENT )
279 # undef NEED_SAFE_REALLOC
280 #define NEED_SAFE_REALLOC
281
282 static char *cpy_aliases( char ***tgtio, char *buf, char **src )
283 {
284         int len;
285         char **tgt=*tgtio;
286         for( ; (*src) ; src++ ) {
287                 len = strlen( *src ) + 1;
288                 memcpy( buf, *src, len );
289                 *tgt++=buf;
290                 buf+=len;
291         }
292         *tgtio=tgt;   
293         return buf;
294 }
295
296 static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
297 {
298         char **tgt=*tgtio;
299         for( ; (*src) ; src++ ) {
300                 memcpy( buf, *src, len );
301                 *tgt++=buf;
302                 buf+=len;
303         }
304         *tgtio=tgt;      
305         return buf;
306 }
307
308 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
309 {
310         char    **p;
311         char    **tp;
312         char    *tbuf;
313         int     name_len;
314         int     n_alias;
315         int     total_alias_len;
316         int     n_addr;
317         int     total_addr_len;
318         int     total_len;
319           
320         /* calculate the size needed for the buffer */
321         name_len = strlen( src->h_name ) + 1;
322         
323         for( n_alias=total_alias_len=0, p=src->h_aliases; (*p) ; p++ ) {
324                 total_alias_len += strlen( *p ) + 1;
325                 n_alias++; 
326         }
327
328         for( n_addr=0, p=src->h_addr_list; (*p) ; p++ ) {
329                 n_addr++;
330         }
331         total_addr_len = n_addr * src->h_length;
332         
333         total_len = (n_alias + n_addr + 2) * sizeof( char * ) +
334                 total_addr_len + total_alias_len + name_len;
335         
336         if (safe_realloc( buf, total_len )) {                    
337                 tp = (char **) *buf;
338                 tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
339                 memcpy( res, src, sizeof( struct hostent ) );
340                 /* first the name... */
341                 memcpy( tbuf, src->h_name, name_len );
342                 res->h_name = tbuf; tbuf+=name_len;
343                 /* now the aliases */
344                 res->h_aliases = tp;
345                 tbuf = cpy_aliases( &tp, tbuf, src->h_aliases );
346                 *tp++=NULL;
347                 /* finally the addresses */
348                 res->h_addr_list = tp;
349                 tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length );
350                 *tp++=NULL;
351                 return 0;
352         }
353         return -1;
354 }
355 #endif
356
357 #if defined( NEED_SAFE_REALLOC )
358 static char *safe_realloc( char **buf, int len )
359 {
360         char *tmpbuf;
361         tmpbuf = realloc( *buf, len );
362         if (tmpbuf) {
363                 *buf=tmpbuf;
364         } 
365         return tmpbuf;
366 }
367 #endif
368
369