Commit 0024cf2f authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

-lldap reentrantancy improvements from Bart Hartgers <A.Hartgers@phys.tue.nl>

including use of ctime_r, gethostby*_r, etc..  Also reworked ldap_sort_entries
to be reentrant.
Need to add code to properly set LDAP_API_FEATURE_THREAD_SAFE.
parent b5e50eff
......@@ -22,7 +22,8 @@ lint5: lint5-local FORCE
$(5LINT) $(DEFS) $(DEFINES) $(SRCS)
clean-common: FORCE
$(RM) $(LIBRARY) ../$(LIBRARY) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) \
$(RM) $(LIBRARY) ../$(LIBRARY) $(XLIBRARY) \
$(PROGRAMS) $(XPROGRAMS) $(XSRCS) \
*.o *.lo a.out core version.c .libs/*
depend-common: FORCE
......
This diff is collapsed.
......@@ -803,24 +803,37 @@ int x = errno;
LTHREAD_LIBS=""
fi
dnl check for reentrant/threadsafe functions
dnl
dnl note: these should only be used when linking
dnl with $LTHREAD_LIBS
dnl
save_CPPFLAGS="$CPPFLAGS"
save_LIBS="$LIBS"
LIBS="$LTHREAD_LIBS $LIBS"
AC_CHECK_FUNCS( \
strtok_r \
gmtime_r \
gethostbyaddr_r gethostbyname_r \
feof_unlocked unlocked_feof \
putc_unlocked unlocked_putc \
flockfile ftrylockfile \
)
CPPFLAGS="$save_CPPFLAGS"
LIBS="$save_LIBS"
dnl When in thread environment, use
dnl #if defined( HAVE_REENTRANT_FUNCTIONS ) \
dnl || defined( HAVE_FUNC_R )
dnl func_r(...);
dnl #else
dnl func(...);
dnl #endif
dnl
dnl HAVE_REENTRANT_FUNCTIONS is derived from:
dnl _POSIX_REENTRANT_FUNCTIONS
dnl _POSIX_THREAD_SAFE_FUNCTIONS
dnl _POSIX_THREADSAFE_FUNCTIONS
dnl
dnl dnl check for reentrant/threadsafe functions
dnl dnl
dnl dnl note: these should only be used when linking
dnl dnl with $LTHREAD_LIBS
dnl dnl
dnl save_CPPFLAGS="$CPPFLAGS"
dnl save_LIBS="$LIBS"
dnl LIBS="$LTHREAD_LIBS $LIBS"
dnl AC_CHECK_FUNCS( \
dnl strtok_r \
dnl gmtime_r \
dnl gethostbyaddr_r gethostbyname_r \
dnl feof_unlocked unlocked_feof \
dnl putc_unlocked unlocked_putc \
dnl flockfile ftrylockfile \
dnl )
dnl CPPFLAGS="$save_CPPFLAGS"
dnl LIBS="$save_LIBS"
fi
dnl ----------------------------------------------------------------
......@@ -1103,9 +1116,11 @@ AC_FUNC_WAIT3
AC_CHECK_FUNCS( \
bcopy \
ctime_r \
flock \
getdtablesize \
gethostname \
gethostbyaddr_r gethostbyname_r \
getpwuid \
gettimeofday \
lockf \
......@@ -1126,6 +1141,7 @@ AC_CHECK_FUNCS( \
strsep \
strstr \
strtok \
strtok_r \
strtol \
strtoul \
sysconf \
......
......@@ -279,18 +279,12 @@ is provided ``as is'' without express or implied warranty.
/* Define if you have the bcopy function. */
#undef HAVE_BCOPY
/* Define if you have the feof_unlocked function. */
#undef HAVE_FEOF_UNLOCKED
/* Define if you have the ctime_r function. */
#undef HAVE_CTIME_R
/* Define if you have the flock function. */
#undef HAVE_FLOCK
/* Define if you have the flockfile function. */
#undef HAVE_FLOCKFILE
/* Define if you have the ftrylockfile function. */
#undef HAVE_FTRYLOCKFILE
/* Define if you have the getdtablesize function. */
#undef HAVE_GETDTABLESIZE
......@@ -312,9 +306,6 @@ is provided ``as is'' without express or implied warranty.
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the gmtime_r function. */
#undef HAVE_GMTIME_R
/* Define if you have the lockf function. */
#undef HAVE_LOCKF
......@@ -354,9 +345,6 @@ is provided ``as is'' without express or implied warranty.
/* Define if you have the pthread_yield function. */
#undef HAVE_PTHREAD_YIELD
/* Define if you have the putc_unlocked function. */
#undef HAVE_PUTC_UNLOCKED
/* Define if you have the res_search function. */
#undef HAVE_RES_SEARCH
......@@ -423,12 +411,6 @@ is provided ``as is'' without express or implied warranty.
/* Define if you have the thr_setconcurrency function. */
#undef HAVE_THR_SETCONCURRENCY
/* Define if you have the unlocked_feof function. */
#undef HAVE_UNLOCKED_FEOF
/* Define if you have the unlocked_putc function. */
#undef HAVE_UNLOCKED_PUTC
/* Define if you have the vsnprintf function. */
#undef HAVE_VSNPRINTF
......
......@@ -3,6 +3,7 @@
##
LIBRARY = liblber.la
XLIBRARY = ../liblber.a
SRCS= decode.c encode.c io.c bprint.c
OBJS= decode.lo encode.lo io.lo bprint.lo
......
......@@ -2,6 +2,8 @@
## Makefile.in for LDAP -lldap
##
LIBRARY = libldap.la
XLIBRARY = ../libldap.a
PROGRAMS = apitest ltest ttest
SRCS = bind.c open.c result.c error.c compare.c search.c \
......@@ -10,14 +12,14 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \
free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c getdxbyname.c os-ip.c url.c charset.c \
init.c options.c strdup.c
init.c options.c strdup.c util-int.c
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
getfilter.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \
init.lo options.lo strdup.lo
init.lo options.lo strdup.lo util-int.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
......
......@@ -64,6 +64,13 @@ cldap_open( char *host, int port )
char *p;
int i;
/* buffers for ldap_int_gethostbyname_a ... */
struct hostent he_buf;
int local_h_errno;
char *ha_buf=NULL;
#define DO_RETURN(x) if (ha_buf) free(ha_buf); return (x);
Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 );
if ( (s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
......@@ -110,9 +117,11 @@ cldap_open( char *host, int port )
/* This was just a test for -1 until OSF1 let inet_addr return
unsigned int, which is narrower than 'unsigned long address' */
if ( address == 0xffffffff || address == (unsigned long) -1 ) {
if ( (hp = gethostbyname( host )) == NULL ) {
errno = EHOSTUNREACH;
continue;
if ((ldap_int_gethostbyname_a( host, &he_buf, &ha_buf,
&hp,&local_h_errno)<0) ||
(hp==NULL)) {
errno = EHOSTUNREACH;
continue;
}
for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) {
......@@ -121,7 +130,7 @@ cldap_open( char *host, int port )
sizeof(sock.sin_addr.s_addr));
if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
ldap_ld_free( ld, 1 );
return( NULL );
DO_RETURN( NULL );
}
}
......@@ -129,7 +138,7 @@ cldap_open( char *host, int port )
sock.sin_addr.s_addr = address;
if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
ldap_ld_free( ld, 1 );
return( NULL );
DO_RETURN( NULL );
}
}
......@@ -137,13 +146,12 @@ cldap_open( char *host, int port )
ld->ld_host = ldap_strdup( host );
}
}
} else {
address = INADDR_LOOPBACK;
sock.sin_addr.s_addr = htonl( address );
if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
ldap_ld_free( ld, 1 );
return( NULL );
DO_RETURN( NULL );
}
}
......@@ -153,7 +161,7 @@ cldap_open( char *host, int port )
#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
) {
ldap_ld_free( ld, 0 );
return( NULL );
DO_RETURN( NULL );
}
ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ 0 ];
......@@ -168,10 +176,10 @@ cldap_open( char *host, int port )
}
#endif
return( ld );
DO_RETURN( ld );
}
#undef DO_RETURN
void
cldap_close( LDAP *ld )
......
......@@ -124,6 +124,7 @@ ldap_explode_dns( char *dn )
int ncomps, maxcomps;
char *s;
char **rdns;
char *tok_r;
if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) {
return( NULL );
......@@ -131,7 +132,8 @@ ldap_explode_dns( char *dn )
maxcomps = 8;
ncomps = 0;
for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) {
for ( s = ldap_int_strtok( dn, "@.", &tok_r ); s != NULL;
s = ldap_int_strtok( NULL, "@.", &tok_r ) ) {
if ( ncomps == maxcomps ) {
maxcomps *= 2;
if ( (rdns = (char **) realloc( rdns, maxcomps *
......
......@@ -405,14 +405,15 @@ break_into_words( char *str, char *delims, char ***wordsp )
{
char *word, **words;
int count;
char *tok_r;
if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
return( -1 );
}
count = 0;
words[ count ] = NULL;
word = strtok( str, delims );
word = ldap_int_strtok( str, delims, &tok_r );
while ( word != NULL ) {
if (( words = (char **)realloc( words,
( count + 2 ) * sizeof( char * ))) == NULL ) {
......@@ -421,7 +422,7 @@ break_into_words( char *str, char *delims, char ***wordsp )
words[ count ] = word;
words[ ++count ] = NULL;
word = strtok( NULL, delims );
word = ldap_int_strtok( NULL, delims, &tok_r );
}
*wordsp = words;
......
......@@ -11,6 +11,8 @@
#include "../liblber/lber-int.h"
#include "ldap_log.h"
#include "ldap.h"
#include <time.h>
#include <netdb.h>
LDAP_BEGIN_DECL
......@@ -273,6 +275,28 @@ int ldap_8859_to_t61( char **bufp, unsigned long *buflenp, int free_input );
#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
/*
* in util_r.c
*
*/
extern char *ldap_int_strtok( char *str, const char *delim, char **pos );
extern char *ldap_int_ctime( const time_t *tp, char *buf );
extern int ldap_int_gethostbyname_a(
const char *name,
struct hostent *resbuf,
char **buf,
struct hostent **result,
int *herrno_ptr );
extern int ldap_int_gethostbyaddr_a(
const char *addr,
int len,
int type,
struct hostent *resbuf,
char **buf,
struct hostent **result,
int *herrno_ptr );
LDAP_END_DECL
#endif /* _LDAP_INT_H */
......@@ -48,7 +48,13 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
int status; /* for ioctl call */
#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
#endif /* notyet */
/* buffers for ldap_int_gethostbyname_a */
struct hostent he_buf;
int local_h_errno;
char *ha_buf=NULL;
#define DO_RETURN(x) if (ha_buf) free(ha_buf); return (x);
Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
( host == NULL ) ? "(by address)" : host, (int) ntohs( (short) port ), 0 );
......@@ -59,13 +65,15 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
/* This was just a test for -1 until OSF1 let inet_addr return
unsigned int, which is narrower than 'unsigned long address' */
if ( address == 0xffffffff || address == (unsigned long) -1 ) {
if ( (hp = gethostbyname( host )) == NULL ) {
if ( ( ldap_int_gethostbyname_a( host, &he_buf, &ha_buf,
&hp, &local_h_errno) < 0) || (hp==NULL))
{
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#else
errno = EHOSTUNREACH; /* not exactly right, but... */
#endif
return( -1 );
DO_RETURN( -1 );
}
use_hp = 1;
}
......@@ -74,7 +82,7 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
rc = -1;
for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
return( -1 );
DO_RETURN( -1 );
}
#ifdef notyet
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
......@@ -99,7 +107,7 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
break;
} else {
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
errno = WSAGetLastError();
#endif
#ifdef notyet
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
......@@ -145,8 +153,12 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
s, (char *) inet_ntoa( sin.sin_addr ), 0 );
}
return( rc );
DO_RETURN( rc );
}
#undef DO_RETURN
void
......@@ -165,6 +177,12 @@ ldap_host_connected_to( Sockbuf *sb )
int len;
struct sockaddr_in sin;
/* buffers for gethostbyaddr_r */
struct hostent he_buf;
int local_h_errno;
char *ha_buf=NULL;
#define DO_RETURN(x) if (ha_buf) free(ha_buf); return (x);
(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
len = sizeof( sin );
if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
......@@ -176,15 +194,20 @@ ldap_host_connected_to( Sockbuf *sb )
* this is necessary for kerberos to work right, since the official
* hostname is used as the kerberos instance.
*/
if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
if ((ldap_int_gethostbyaddr_a( (char *) &sin.sin_addr,
sizeof( sin.sin_addr ),
AF_INET, &he_buf, &ha_buf,
&hp,&local_h_errno ) ==0 ) && (hp != NULL) )
{
if ( hp->h_name != NULL ) {
return( ldap_strdup( hp->h_name ));
DO_RETURN( ldap_strdup( hp->h_name ));
}
}
return( NULL );
DO_RETURN( NULL );
}
#undef DO_RETURN
#endif /* HAVE_KERBEROS */
......
......@@ -442,6 +442,7 @@ void
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
{
LDAPConn *lc;
char timebuf[32];
fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
......@@ -457,7 +458,7 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
"NeedSocket" : ( lc->lconn_status ==
LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
fprintf( stderr, " last used: %s\n",
ctime( &lc->lconn_lastused ));
ldap_int_ctime( &lc->lconn_lastused, timebuf ));
if ( !all ) {
break;
}
......
......@@ -27,9 +27,9 @@
struct entrything {
char **et_vals;
LDAPMessage *et_msg;
int (*et_cmp_fn) LDAP_P((const char *a, const char *b));
};
static int (*et_cmp_fn) LDAP_P(( const char *a, const char *b ));
static int et_cmp LDAP_P(( const void *aa, const void *bb));
......@@ -60,8 +60,7 @@ et_cmp(
return( 1 );
for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
!= 0 ) {
if ( (rc = a->et_cmp_fn( a->et_vals[i], b->et_vals[i] )) != 0 ) {
return( rc );
}
}
......@@ -96,6 +95,7 @@ ldap_sort_entries(
e = *chain;
for ( i = 0; i < count; i++ ) {
et[i].et_cmp_fn = cmp;
et[i].et_msg = e;
if ( attr == NULL ) {
char *dn;
......@@ -111,7 +111,6 @@ ldap_sort_entries(
}
last = e;
et_cmp_fn = cmp;
qsort( et, count, sizeof(struct entrything), et_cmp );
ep = chain;
......
......@@ -874,6 +874,7 @@ time2text( char *ldtimestr, int dateonly )
struct tm t;
char *p, *timestr, zone, *fmterr = "badly formatted time";
time_t gmttime;
char timebuf[32];
memset( (char *)&t, 0, sizeof( struct tm ));
if ( (int) strlen( ldtimestr ) < 13 ) {
......@@ -899,8 +900,9 @@ time2text( char *ldtimestr, int dateonly )
}
gmttime = gtime( &t );
timestr = ctime( &gmttime );
timestr = ldap_int_ctime( &gmttime, timebuf );
timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
if ( dateonly ) {
strcpy( timestr + 11, timestr + 20 );
......
/*
* util-int.c Various functions to replace missing threadsafe ones.
* Without the real *_r funcs, things will work, but won't be
* threadsafe.
*
* Written by Bart Hartgers.
*
* Copyright 1998, A. Hartgers, All rights reserved.
* This software is not subject to any license of Eindhoven University of
* Technology, since it was written in my spare time.
*
* Redistribution and use in source and binary forms are permitted only
* as authorized by the OpenLDAP Public License. A copy of this
* license is available at http://www.OpenLDAP.org/license.html or
* in file LICENSE in the top-level directory of the distribution.
*/
#include "portable.h"
#include <stdlib.h>
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include "ldap-int.h"
char *ldap_int_strtok( char *str, const char *delim, char **pos )
{
#ifdef HAVE_STRTOK_R
return strtok_r(str, delim, pos);
#else
return strtok(str, delim);
#endif
}
char *ldap_int_ctime( const time_t *tp, char *buf )
{
#ifdef HAVE_CTIME_R
return ctime_r(tp,buf);
#else
return ctime(tp);
#endif
}
#define BUFSTART 1024
#define BUFMAX (32*1024)
static char *safe_realloc( char **buf, int len )
{
char *tmpbuf;
tmpbuf = realloc( *buf, len );
if (tmpbuf) {
*buf=tmpbuf;
}
return tmpbuf;
}
int ldap_int_gethostbyname_a(
const char *name,
struct hostent *resbuf,
char **buf,
struct hostent **result,
int *herrno_ptr )
{
#ifdef HAVE_GETHOSTBYNAME_R
int r;
int buflen=BUFSTART;
if (safe_realloc( buf, buflen)) {
for(;buflen<BUFMAX;) {
r = gethostbyname_r( name, resbuf, *buf,
buflen, result, herrno_ptr );
#ifdef NETDB_INTERNAL
if ((r<0) &&
(*herrno_ptr==NETDB_INTERNAL) &&
(errno==ERANGE))
{
if (safe_realloc( buf, buflen*=2 )) {
continue;
}
}
#endif
return r;
}
}
#else /* gethostbyname() */
*result = gethostbyname( name );
if (*result!=NULL) {
return 0;
}
*herrno_ptr = h_errno;
#endif
return -1;
}
int ldap_int_gethostbyaddr_a(
const char *addr,
int len,
int type,
struct hostent *resbuf,
char **buf,
struct hostent **result,
int *herrno_ptr )
{
#ifdef HAVE_GETHOSTBYADDR_R
int r;
int buflen=BUFSTART;
if (safe_realloc( buf, buflen)) {
for(;buflen<BUFMAX;) {