home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / src / util-int.c < prev   
C/C++ Source or Header  |  2001-11-13  |  10KB  |  460 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap/util-int.c,v 1.17.8.7 2000/10/30 17:05:57 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6. /*
  7.  * util-int.c    Various functions to replace missing threadsafe ones.
  8.  *                  Without the real *_r funcs, things will
  9.  *                  work, but might not be threadsafe. 
  10.  * 
  11.  * Written by Bart Hartgers.
  12.  *
  13.  * Copyright 1998, A. Hartgers, All rights reserved.
  14.  * This software is not subject to any license of Eindhoven University of
  15.  * Technology, since it was written in my spare time.
  16.  *            
  17.  * Redistribution and use in source and binary forms are permitted only
  18.  * as authorized by the OpenLDAP Public License.  A copy of this
  19.  * license is available at http://www.OpenLDAP.org/license.html or
  20.  * in file LICENSE in the top-level directory of the distribution.
  21.  */ 
  22.  
  23.  
  24. #include "portable.h"
  25.  
  26. #include <ac/stdlib.h>
  27.  
  28. #include <ac/errno.h>
  29. #include <ac/socket.h>
  30. #include <ac/string.h>
  31. #include <ac/time.h>
  32. #include <ac/unistd.h>
  33.  
  34. #include "ldap-int.h"
  35.  
  36. #if defined( LDAP_R_COMPILE )
  37. # include <ldap_pvt_thread.h>
  38. #else
  39. # undef HAVE_REENTRANT_FUNCTIONS
  40. #endif
  41.  
  42. #if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \
  43.     && defined( CTIME_R_NARGS )
  44. #    define USE_CTIME_R
  45. #endif
  46.  
  47. #if defined(HAVE_GETHOSTBYNAME_R) && \
  48.     (GETHOSTBYNAME_R_NARGS > 6 || GETHOSTBYNAME_R_NARGS < 5)
  49.     /* Don't know how to handle this version, pretend it's not there */
  50. #    undef HAVE_GETHOSTBYNAME_R
  51. #endif
  52. #if defined(HAVE_GETHOSTBYADDR_R) && \
  53.     (GETHOSTBYADDR_R_NARGS > 8 || GETHOSTBYADDR_R_NARGS < 7)
  54.     /* Don't know how to handle this version, pretend it's not there */
  55. #    undef HAVE_GETHOSTBYADDR_R
  56. #endif
  57.  
  58. #ifdef LDAP_R_COMPILE
  59. # ifndef USE_CTIME_R
  60.     static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex;
  61. # endif
  62. # if !defined( HAVE_GETHOSTBYNAME_R ) || !defined( HAVE_GETHOSTBYADDR_R )
  63.     static ldap_pvt_thread_mutex_t ldap_int_gethostby_mutex;
  64. # endif
  65. # ifdef HAVE_RES_QUERY
  66.     ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
  67. # endif
  68. #endif /* LDAP_R_COMPILE */
  69.  
  70. char *ldap_pvt_ctime( const time_t *tp, char *buf )
  71. {
  72. #ifdef USE_CTIME_R
  73. # if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2)
  74. #    error "CTIME_R_NARGS should be 2 or 3"
  75. # elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT)
  76.     return( ctime_r(tp,buf,26) < 0 ? 0 : buf );
  77. # elif CTIME_R_NARGS > 2
  78.     return ctime_r(tp,buf,26);
  79. # else
  80.     return ctime_r(tp,buf);
  81. # endif      
  82.  
  83. #else
  84. # ifdef LDAP_R_COMPILE
  85.     ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
  86. # endif
  87.     AC_MEMCPY( buf, ctime(tp), 26 );
  88. # ifdef LDAP_R_COMPILE
  89.     ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
  90. # endif
  91.     return buf;
  92. #endif    
  93. }
  94.  
  95. #define BUFSTART 1024
  96. #define BUFMAX (32*1024)
  97.  
  98. static char *safe_realloc( char **buf, int len );
  99.  
  100. #if !defined(HAVE_GETHOSTBYNAME_R) && defined(LDAP_R_COMPILE)
  101. static int copy_hostent( struct hostent *res, char **buf, struct hostent * src );
  102. #endif
  103.  
  104. int ldap_pvt_gethostbyname_a(
  105.     const char *name, 
  106.     struct hostent *resbuf,
  107.     char **buf,
  108.     struct hostent **result,
  109.     int *herrno_ptr )
  110. {
  111. #if defined( HAVE_GETHOSTBYNAME_R )
  112.  
  113. # define NEED_SAFE_REALLOC 1   
  114.     int r=-1;
  115.     int buflen=BUFSTART;
  116.     *buf = NULL;
  117.     for(;buflen<BUFMAX;) {
  118.         if (safe_realloc( buf, buflen )==NULL)
  119.             return r;
  120.  
  121. #if (GETHOSTBYNAME_R_NARGS < 6)
  122.         r = ((*result=gethostbyname_r( name, resbuf, *buf,
  123.                            buflen, herrno_ptr ))== NULL) ?
  124.             -1 : 0;
  125. #else
  126.         r = gethostbyname_r( name, resbuf, *buf,
  127.             buflen, result, herrno_ptr );
  128. #endif
  129.  
  130.         Debug( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n",
  131.                name, r, 0 );
  132.  
  133. #ifdef NETDB_INTERNAL
  134.         if ((r<0) &&
  135.             (*herrno_ptr==NETDB_INTERNAL) &&
  136.             (errno==ERANGE))
  137.         {
  138.             buflen*=2;
  139.             continue;
  140.          }
  141. #endif
  142.         return r;
  143.     }
  144.     return -1;
  145. #elif defined( LDAP_R_COMPILE )
  146. # define NEED_COPY_HOSTENT   
  147.     struct hostent *he;
  148.     int    retval;
  149.     *buf = NULL;
  150.     
  151.     ldap_pvt_thread_mutex_lock( &ldap_int_gethostby_mutex );
  152.     
  153.     he = gethostbyname( name );
  154.     
  155.     if (he==NULL) {
  156.         *herrno_ptr = h_errno;
  157.         retval = -1;
  158.     } else if (copy_hostent( resbuf, buf, he )<0) {
  159.         *herrno_ptr = -1;
  160.         retval = -1;
  161.     } else {
  162.         *result = resbuf;
  163.         retval = 0;
  164.     }
  165.     
  166.     ldap_pvt_thread_mutex_unlock( &ldap_int_gethostby_mutex );
  167.     
  168.     return retval;
  169. #else    
  170.     *buf = NULL;
  171. #if defined(__OS2__) && defined(TCPV40HDRS)    
  172.     *result = gethostbyname( (unsigned char *)name );
  173. #else    
  174.     *result = gethostbyname( name );
  175. #endif    
  176.  
  177.     if (*result!=NULL) {
  178.         return 0;
  179.     }
  180.  
  181.     *herrno_ptr = h_errno;
  182.     
  183.     return -1;
  184. #endif    
  185. }
  186.      
  187. int ldap_pvt_gethostbyaddr_a(
  188.     const char *addr,
  189.     int len,
  190.     int type,
  191.     struct hostent *resbuf,
  192.     char **buf,
  193.     struct hostent **result,
  194.     int *herrno_ptr )
  195. {
  196. #if defined( HAVE_GETHOSTBYADDR_R )
  197.  
  198. # undef NEED_SAFE_REALLOC
  199. # define NEED_SAFE_REALLOC   
  200.     int r=-1;
  201.     int buflen=BUFSTART;
  202.     *buf = NULL;   
  203.     for(;buflen<BUFMAX;) {
  204.         if (safe_realloc( buf, buflen )==NULL)
  205.             return r;
  206. #if (GETHOSTBYADDR_R_NARGS < 8)
  207.         r = ((*result=gethostbyaddr_r( addr, len, type,
  208.                            resbuf, *buf, buflen, 
  209.                            herrno_ptr )) == NULL) ?
  210.             -1 : 0;
  211. #else
  212.         r = gethostbyaddr_r( addr, len, type,
  213.             resbuf, *buf, buflen, 
  214.             result, herrno_ptr );
  215. #endif
  216.  
  217. #ifdef NETDB_INTERNAL
  218.         if ((r<0) &&
  219.             (*herrno_ptr==NETDB_INTERNAL) &&
  220.             (errno==ERANGE))
  221.         {
  222.             buflen*=2;
  223.             continue;
  224.         }
  225. #endif
  226.         return r;
  227.     }
  228.     return -1;
  229. #elif defined( LDAP_R_COMPILE )
  230. # undef NEED_COPY_HOSTENT
  231. # define NEED_COPY_HOSTENT   
  232.     struct hostent *he;
  233.     int    retval;
  234.     *buf = NULL;   
  235.     
  236.     ldap_pvt_thread_mutex_lock( &ldap_int_gethostby_mutex );
  237.     
  238.     he = gethostbyaddr( addr, len, type );
  239.     
  240.     if (he==NULL) {
  241.         *herrno_ptr = h_errno;
  242.         retval = -1;
  243.     } else if (copy_hostent( resbuf, buf, he )<0) {
  244.         *herrno_ptr = -1;
  245.         retval = -1;
  246.     } else {
  247.         *result = resbuf;
  248.         retval = 0;
  249.     }
  250.     
  251.     ldap_pvt_thread_mutex_unlock( &ldap_int_gethostby_mutex );
  252.     
  253.     return retval;   
  254. #else /* gethostbyaddr() */
  255.     *buf = NULL;   
  256. #if defined(__OS2__) && defined(TCPV40HDRS)    
  257.     *result = gethostbyaddr( (unsigned char *)addr, len, type );
  258. #else    
  259.     *result = gethostbyaddr( addr, len, type );
  260. #endif    
  261.  
  262.     if (*result!=NULL) {
  263.         return 0;
  264.     }
  265.     return -1;
  266. #endif    
  267. }
  268. /* 
  269.  * ldap_int_utils_init() should be called before any other function.
  270.  */
  271.  
  272. void ldap_int_utils_init( void )
  273. {
  274.     static int done=0;
  275.     if (done)
  276.       return;
  277.     done=1;
  278.  
  279. #ifdef LDAP_R_COMPILE
  280.  
  281. #if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS )
  282.     ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex );
  283. #endif
  284.  
  285. #if !defined( HAVE_GETHOSTBYNAME_R ) || !defined( HAVE_GETHOSTBYADDR_R )
  286.     ldap_pvt_thread_mutex_init( &ldap_int_gethostby_mutex );
  287. #endif
  288.  
  289. #ifdef HAVE_RES_QUERY
  290.     ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex );
  291. #endif
  292.  
  293.     /* call other module init functions here... */
  294. #endif
  295. }
  296.  
  297. #if defined( NEED_COPY_HOSTENT )
  298. # undef NEED_SAFE_REALLOC
  299. #define NEED_SAFE_REALLOC
  300.  
  301. static char *cpy_aliases( char ***tgtio, char *buf, char **src )
  302. {
  303.     int len;
  304.     char **tgt=*tgtio;
  305.     for( ; (*src) ; src++ ) {
  306.         len = strlen( *src ) + 1;
  307.         AC_MEMCPY( buf, *src, len );
  308.         *tgt++=buf;
  309.         buf+=len;
  310.     }
  311.     *tgtio=tgt;   
  312.     return buf;
  313. }
  314.  
  315. static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
  316. {
  317.        char **tgt=*tgtio;
  318.     for( ; (*src) ; src++ ) {
  319.         AC_MEMCPY( buf, *src, len );
  320.         *tgt++=buf;
  321.         buf+=len;
  322.     }
  323.     *tgtio=tgt;      
  324.     return buf;
  325. }
  326.  
  327. static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
  328. {
  329.     char    **p;
  330.     char    **tp;
  331.     char    *tbuf;
  332.     int    name_len;
  333.     int    n_alias=0;
  334.     int    total_alias_len=0;
  335.     int    n_addr=0;
  336.     int    total_addr_len;
  337.     int    total_len;
  338.       
  339.     /* calculate the size needed for the buffer */
  340.     name_len = strlen( src->h_name ) + 1;
  341.     
  342.     if( src->h_aliases != NULL ) {
  343.         for( p = src->h_aliases; (*p) != NULL; p++ ) {
  344.             total_alias_len += strlen( *p ) + 1;
  345.             n_alias++; 
  346.         }
  347.     }
  348.  
  349.     if( src->h_addr_list != NULL ) {
  350.         for( p = src->h_addr_list; (*p) != NULL; p++ ) {
  351.             n_addr++;
  352.         }
  353.         total_addr_len = n_addr * src->h_length;
  354.     }
  355.     
  356.     total_len = (n_alias + n_addr + 2) * sizeof( char * ) +
  357.         total_addr_len + total_alias_len + name_len;
  358.     
  359.     if (safe_realloc( buf, total_len )) {             
  360.         tp = (char **) *buf;
  361.         tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
  362.         AC_MEMCPY( res, src, sizeof( struct hostent ) );
  363.         /* first the name... */
  364.         AC_MEMCPY( tbuf, src->h_name, name_len );
  365.         res->h_name = tbuf; tbuf+=name_len;
  366.         /* now the aliases */
  367.         res->h_aliases = tp;
  368.         if ( src->h_aliases != NULL ) {
  369.             tbuf = cpy_aliases( &tp, tbuf, src->h_aliases );
  370.         }
  371.         *tp++=NULL;
  372.         /* finally the addresses */
  373.         res->h_addr_list = tp;
  374.         if ( src->h_addr_list != NULL ) {
  375.             tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length );
  376.         }
  377.         *tp++=NULL;
  378.         return 0;
  379.     }
  380.     return -1;
  381. }
  382. #endif
  383.  
  384. #if defined( NEED_SAFE_REALLOC )
  385. static char *safe_realloc( char **buf, int len )
  386. {
  387.     char *tmpbuf;
  388.     tmpbuf = LDAP_REALLOC( *buf, len );
  389.     if (tmpbuf) {
  390.         *buf=tmpbuf;
  391.     } 
  392.     return tmpbuf;
  393. }
  394. #endif
  395.  
  396. char * ldap_pvt_get_fqdn( char *name )
  397. {
  398.     char *fqdn, *ha_buf;
  399.     char hostbuf[MAXHOSTNAMELEN+1];
  400.     struct hostent *hp, he_buf;
  401.     int rc, local_h_errno;
  402.  
  403.     if( name == NULL ) {
  404.         if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) {
  405.             hostbuf[MAXHOSTNAMELEN] = '\0';
  406.             name = hostbuf;
  407.         } else {
  408.             name = "localhost";
  409.         }
  410.     }
  411.  
  412.     rc = ldap_pvt_gethostbyname_a( name,
  413.         &he_buf, &ha_buf, &hp, &local_h_errno );
  414.  
  415.     if( rc < 0 || hp == NULL || hp->h_name == NULL ) {
  416.         fqdn = LDAP_STRDUP( name );
  417.     } else {
  418.         fqdn = LDAP_STRDUP( hp->h_name );
  419.     }
  420.  
  421.     LDAP_FREE( ha_buf );
  422.     return fqdn;
  423. }
  424.  
  425. #if defined( HAVE_GETADDRINFO ) && !defined( HAVE_GAI_STRERROR )
  426. char *ldap_pvt_gai_strerror (int code) {
  427.     static struct {
  428.         int code;
  429.         const char *msg;
  430.     } values[] = {
  431. #ifdef EAI_ADDRFAMILY
  432.         { EAI_ADDRFAMILY, "Address family for hostname not supported" },
  433. #endif
  434.         { EAI_AGAIN, "Temporary failure in name resolution" },
  435.         { EAI_BADFLAGS, "Bad value for ai_flags" },
  436.         { EAI_FAIL, "Non-recoverable failure in name resolution" },
  437.         { EAI_FAMILY, "ai_family not supported" },
  438.         { EAI_MEMORY, "Memory allocation failure" },
  439. #ifdef EAI_NODATA
  440.         { EAI_NODATA, "No address associated with hostname" },
  441. #endif    
  442.         { EAI_NONAME, "Name or service not known" },
  443.         { EAI_SERVICE, "Servname not supported for ai_socktype" },
  444.         { EAI_SOCKTYPE, "ai_socktype not supported" },
  445.         { EAI_SYSTEM, "System error" },
  446.         { 0, NULL }
  447.     };
  448.  
  449.     int i;
  450.  
  451.     for ( i = 0; values[i].msg != NULL; i++ ) {
  452.         if ( values[i].code == code ) {
  453.             return (char *) values[i].msg;
  454.         }
  455.     }
  456.     
  457.     return "Unknown error";
  458. }
  459. #endif
  460.