home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap / util-int.c < prev    next >
C/C++ Source or Header  |  2000-10-31  |  10KB  |  452 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.     *result = gethostbyname( name );
  172.  
  173.     if (*result!=NULL) {
  174.         return 0;
  175.     }
  176.  
  177.     *herrno_ptr = h_errno;
  178.     
  179.     return -1;
  180. #endif    
  181. }
  182.      
  183. int ldap_pvt_gethostbyaddr_a(
  184.     const char *addr,
  185.     int len,
  186.     int type,
  187.     struct hostent *resbuf,
  188.     char **buf,
  189.     struct hostent **result,
  190.     int *herrno_ptr )
  191. {
  192. #if defined( HAVE_GETHOSTBYADDR_R )
  193.  
  194. # undef NEED_SAFE_REALLOC
  195. # define NEED_SAFE_REALLOC   
  196.     int r=-1;
  197.     int buflen=BUFSTART;
  198.     *buf = NULL;   
  199.     for(;buflen<BUFMAX;) {
  200.         if (safe_realloc( buf, buflen )==NULL)
  201.             return r;
  202. #if (GETHOSTBYADDR_R_NARGS < 8)
  203.         r = ((*result=gethostbyaddr_r( addr, len, type,
  204.                            resbuf, *buf, buflen, 
  205.                            herrno_ptr )) == NULL) ?
  206.             -1 : 0;
  207. #else
  208.         r = gethostbyaddr_r( addr, len, type,
  209.             resbuf, *buf, buflen, 
  210.             result, herrno_ptr );
  211. #endif
  212.  
  213. #ifdef NETDB_INTERNAL
  214.         if ((r<0) &&
  215.             (*herrno_ptr==NETDB_INTERNAL) &&
  216.             (errno==ERANGE))
  217.         {
  218.             buflen*=2;
  219.             continue;
  220.         }
  221. #endif
  222.         return r;
  223.     }
  224.     return -1;
  225. #elif defined( LDAP_R_COMPILE )
  226. # undef NEED_COPY_HOSTENT
  227. # define NEED_COPY_HOSTENT   
  228.     struct hostent *he;
  229.     int    retval;
  230.     *buf = NULL;   
  231.     
  232.     ldap_pvt_thread_mutex_lock( &ldap_int_gethostby_mutex );
  233.     
  234.     he = gethostbyaddr( addr, len, type );
  235.     
  236.     if (he==NULL) {
  237.         *herrno_ptr = h_errno;
  238.         retval = -1;
  239.     } else if (copy_hostent( resbuf, buf, he )<0) {
  240.         *herrno_ptr = -1;
  241.         retval = -1;
  242.     } else {
  243.         *result = resbuf;
  244.         retval = 0;
  245.     }
  246.     
  247.     ldap_pvt_thread_mutex_unlock( &ldap_int_gethostby_mutex );
  248.     
  249.     return retval;   
  250. #else /* gethostbyaddr() */
  251.     *buf = NULL;   
  252.     *result = gethostbyaddr( addr, len, type );
  253.  
  254.     if (*result!=NULL) {
  255.         return 0;
  256.     }
  257.     return -1;
  258. #endif    
  259. }
  260. /* 
  261.  * ldap_int_utils_init() should be called before any other function.
  262.  */
  263.  
  264. void ldap_int_utils_init( void )
  265. {
  266.     static int done=0;
  267.     if (done)
  268.       return;
  269.     done=1;
  270.  
  271. #ifdef LDAP_R_COMPILE
  272.  
  273. #if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS )
  274.     ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex );
  275. #endif
  276.  
  277. #if !defined( HAVE_GETHOSTBYNAME_R ) || !defined( HAVE_GETHOSTBYADDR_R )
  278.     ldap_pvt_thread_mutex_init( &ldap_int_gethostby_mutex );
  279. #endif
  280.  
  281. #ifdef HAVE_RES_QUERY
  282.     ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex );
  283. #endif
  284.  
  285.     /* call other module init functions here... */
  286. #endif
  287. }
  288.  
  289. #if defined( NEED_COPY_HOSTENT )
  290. # undef NEED_SAFE_REALLOC
  291. #define NEED_SAFE_REALLOC
  292.  
  293. static char *cpy_aliases( char ***tgtio, char *buf, char **src )
  294. {
  295.     int len;
  296.     char **tgt=*tgtio;
  297.     for( ; (*src) ; src++ ) {
  298.         len = strlen( *src ) + 1;
  299.         AC_MEMCPY( buf, *src, len );
  300.         *tgt++=buf;
  301.         buf+=len;
  302.     }
  303.     *tgtio=tgt;   
  304.     return buf;
  305. }
  306.  
  307. static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
  308. {
  309.        char **tgt=*tgtio;
  310.     for( ; (*src) ; src++ ) {
  311.         AC_MEMCPY( buf, *src, len );
  312.         *tgt++=buf;
  313.         buf+=len;
  314.     }
  315.     *tgtio=tgt;      
  316.     return buf;
  317. }
  318.  
  319. static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
  320. {
  321.     char    **p;
  322.     char    **tp;
  323.     char    *tbuf;
  324.     int    name_len;
  325.     int    n_alias=0;
  326.     int    total_alias_len=0;
  327.     int    n_addr=0;
  328.     int    total_addr_len;
  329.     int    total_len;
  330.       
  331.     /* calculate the size needed for the buffer */
  332.     name_len = strlen( src->h_name ) + 1;
  333.     
  334.     if( src->h_aliases != NULL ) {
  335.         for( p = src->h_aliases; (*p) != NULL; p++ ) {
  336.             total_alias_len += strlen( *p ) + 1;
  337.             n_alias++; 
  338.         }
  339.     }
  340.  
  341.     if( src->h_addr_list != NULL ) {
  342.         for( p = src->h_addr_list; (*p) != NULL; p++ ) {
  343.             n_addr++;
  344.         }
  345.         total_addr_len = n_addr * src->h_length;
  346.     }
  347.     
  348.     total_len = (n_alias + n_addr + 2) * sizeof( char * ) +
  349.         total_addr_len + total_alias_len + name_len;
  350.     
  351.     if (safe_realloc( buf, total_len )) {             
  352.         tp = (char **) *buf;
  353.         tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
  354.         AC_MEMCPY( res, src, sizeof( struct hostent ) );
  355.         /* first the name... */
  356.         AC_MEMCPY( tbuf, src->h_name, name_len );
  357.         res->h_name = tbuf; tbuf+=name_len;
  358.         /* now the aliases */
  359.         res->h_aliases = tp;
  360.         if ( src->h_aliases != NULL ) {
  361.             tbuf = cpy_aliases( &tp, tbuf, src->h_aliases );
  362.         }
  363.         *tp++=NULL;
  364.         /* finally the addresses */
  365.         res->h_addr_list = tp;
  366.         if ( src->h_addr_list != NULL ) {
  367.             tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length );
  368.         }
  369.         *tp++=NULL;
  370.         return 0;
  371.     }
  372.     return -1;
  373. }
  374. #endif
  375.  
  376. #if defined( NEED_SAFE_REALLOC )
  377. static char *safe_realloc( char **buf, int len )
  378. {
  379.     char *tmpbuf;
  380.     tmpbuf = LDAP_REALLOC( *buf, len );
  381.     if (tmpbuf) {
  382.         *buf=tmpbuf;
  383.     } 
  384.     return tmpbuf;
  385. }
  386. #endif
  387.  
  388. char * ldap_pvt_get_fqdn( char *name )
  389. {
  390.     char *fqdn, *ha_buf;
  391.     char hostbuf[MAXHOSTNAMELEN+1];
  392.     struct hostent *hp, he_buf;
  393.     int rc, local_h_errno;
  394.  
  395.     if( name == NULL ) {
  396.         if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) {
  397.             hostbuf[MAXHOSTNAMELEN] = '\0';
  398.             name = hostbuf;
  399.         } else {
  400.             name = "localhost";
  401.         }
  402.     }
  403.  
  404.     rc = ldap_pvt_gethostbyname_a( name,
  405.         &he_buf, &ha_buf, &hp, &local_h_errno );
  406.  
  407.     if( rc < 0 || hp == NULL || hp->h_name == NULL ) {
  408.         fqdn = LDAP_STRDUP( name );
  409.     } else {
  410.         fqdn = LDAP_STRDUP( hp->h_name );
  411.     }
  412.  
  413.     LDAP_FREE( ha_buf );
  414.     return fqdn;
  415. }
  416.  
  417. #if defined( HAVE_GETADDRINFO ) && !defined( HAVE_GAI_STRERROR )
  418. char *ldap_pvt_gai_strerror (int code) {
  419.     static struct {
  420.         int code;
  421.         const char *msg;
  422.     } values[] = {
  423. #ifdef EAI_ADDRFAMILY
  424.         { EAI_ADDRFAMILY, "Address family for hostname not supported" },
  425. #endif
  426.         { EAI_AGAIN, "Temporary failure in name resolution" },
  427.         { EAI_BADFLAGS, "Bad value for ai_flags" },
  428.         { EAI_FAIL, "Non-recoverable failure in name resolution" },
  429.         { EAI_FAMILY, "ai_family not supported" },
  430.         { EAI_MEMORY, "Memory allocation failure" },
  431. #ifdef EAI_NODATA
  432.         { EAI_NODATA, "No address associated with hostname" },
  433. #endif    
  434.         { EAI_NONAME, "Name or service not known" },
  435.         { EAI_SERVICE, "Servname not supported for ai_socktype" },
  436.         { EAI_SOCKTYPE, "ai_socktype not supported" },
  437.         { EAI_SYSTEM, "System error" },
  438.         { 0, NULL }
  439.     };
  440.  
  441.     int i;
  442.  
  443.     for ( i = 0; values[i].msg != NULL; i++ ) {
  444.         if ( values[i].code == code ) {
  445.             return (char *) values[i].msg;
  446.         }
  447.     }
  448.     
  449.     return "Unknown error";
  450. }
  451. #endif
  452.