Commit 0f30db1c authored by Howard Chu's avatar Howard Chu
Browse files

ITS#6625 concurrency patch from Doug Leavitt @ Oracle .com

parent 026713f4
This diff is collapsed.
.TH LDAP_OPEN 3 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.\" Copyright 1998-2010 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
ldap_dup, ldap_destroy, \- Duplicate and destroy LDAP session handles
.SH LIBRARY
OpenLDAP LDAP (libldap, \-lldap)
.SH SYNOPSIS
.nf
.ft B
#include <ldap.h>
.LP
.ft B
LDAP *ldap_dup(
.RS
.ft B
LDAP *\fIold\fB );
.RE
.LP
.ft B
int ldap_destroy(
.RS
.ft B
LDAP *\fIold\fB );
.RE
.SH DESCRIPTION
.LP
.B ldap_dup()
duplicates an existing LDAP
.RB ( "LDAP *" )
session handle.
The new session handle may be used concurrently with the
original session handle.
In a threaded environment, different threads may execute concurrent
requests on the same connection/session without fear of contamination.
Each session handle manages its own private error results.
.LP
.B ldap_destroy()
destroys an existing session handle.
.LP
The
.B ldap_dup()
and
.B ldap_destroy()
functions are used in conjunction with a "thread safe" version
of
.B libldap
.RB ( libldap_r )
to enable operation thread safe API calls, so that a single session
may be simultaneously used across multiple threads with consistent
error handling.
.LP
When a session is created through the use of one of the session creation
functions including
.BR ldap_open (3),
.BR ldap_init (3),
.BR ldap_initialize (3)
or
.BR ldap_init_fd (3)
an
.B "LDAP *"
session handle is returned to the application.
The session handle may be shared amongst threads, however the
error codes are unique to a session handle.
Multiple threads performing different operations using the same
session handle will result in inconsistent error codes and
return values.
.LP
To prevent this confusion,
.B ldap_dup()
is used duplicate an existing session handle so that multiple threads
can share the session, and maintain consistent error information
and results.
.LP
The message queues for a session are shared between sibling session handles.
Results of operations on a sibling session handles are accessible
to all the sibling session handles.
Applications desiring results associated with a specific operation
should provide the appropriate msgid to
.BR ldap_result() .
Applications should avoid calling
.B ldap_result()
with
.B LDAP_RES_ANY
as that may "steal" and return results in the calling thread
that another operation in a different thread, using a
different session handle, may require to complete.
.LP
When
.B ldap_unbind()
is called on a session handle with siblings, all the
siblings become invalid.
.LP
Siblings must be destroyed using
.BR ldap_destroy() .
Session handle resources associated with the original
.RB ( "LDAP *" )
will be freed when the last session handle is destroyed or when
.B ldap_unbind()
is called, if no other session handles currently exist.
.SH ERRORS
If an error occurs,
.B ldap_dup()
will return NULL and
.I errno
should be set appropriately.
.B ldap_destroy()
will directly return the LDAP code associated to the error (or
.I LDAP_SUCCESS
in case of success);
.I errno
should be set as well whenever appropriate.
.SH SEE ALSO
.BR ldap_open (3),
.BR ldap_init (3),
.BR ldap_initialize (3),
.BR ldap_init_fd (3),
.BR errno (3)
.SH ACKNOWLEDGEMENTS
This work is based on the previously proposed
.B LDAP C API Concurrency Extensions
draft
.BR ( draft-zeilenga-ldap-c-api-concurrency-00.txt )
effort.
.so ../Project
......@@ -322,6 +322,15 @@ must be
the library duplicates the controls passed via
.BR invalue .
.TP
.B LDAP_OPT_SESSION_REFCNT
Returns the reference count associated with the LDAP handle passed in as
.BR ld ;
.BR outvalue
must be a
.BR "int *" .
This is a read-only, handle-specific option.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_SIZELIMIT
Sets/gets the value that defines the maximum number of entries
to be returned by a search operation.
......
......@@ -59,7 +59,9 @@ LDAP_BEGIN_DECL
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
/* -lldap may or may not be thread safe */
/* -lldap_r, if available, is always thread safe */
# define LDAP_API_FEATURE_THREAD_SAFE 1
# define LDAP_API_FEATURE_THREAD_SAFE 1
# define LDAP_API_FEATURE_SESSION_THREAD_SAFE 1
# define LDAP_API_FEATURE_OPERATION_THREAD_SAFE 1
#endif
#if defined( LDAP_THREAD_SAFE ) && \
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE )
......@@ -135,6 +137,7 @@ LDAP_BEGIN_DECL
#define LDAP_OPT_DEFBASE 0x5009 /* searchbase */
#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */
#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */
#define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */
/* OpenLDAP TLS options */
#define LDAP_OPT_X_TLS 0x6000
......@@ -1519,6 +1522,10 @@ ldap_initialize LDAP_P((
LDAP **ldp,
LDAP_CONST char *url ));
LDAP_F( LDAP * )
ldap_dup LDAP_P((
LDAP *old ));
/*
* in tls.c
*/
......@@ -1931,6 +1938,10 @@ ldap_unbind_ext_s LDAP_P((
LDAPControl **serverctrls,
LDAPControl **clientctrls));
LDAP_F( int )
ldap_destroy LDAP_P((
LDAP *ld));
#if LDAP_DEPRECATED
LDAP_F( int )
ldap_unbind LDAP_P(( /* deprecated, use ldap_unbind_ext */
......
......@@ -69,6 +69,11 @@ typedef pthread_key_t ldap_int_thread_key_t;
typedef pthread_rwlock_t ldap_int_thread_rdwr_t;
#endif
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL ,PTHREAD_MUTEX_INITIALIZER
#define MUTEX_FIRSTCREATE(m)
#endif
LDAP_END_DECL
#elif defined ( HAVE_MACH_CTHREADS )
......@@ -91,6 +96,11 @@ typedef struct mutex ldap_int_thread_mutex_t;
typedef struct condition ldap_int_thread_cond_t;
typedef cthread_key_t ldap_int_thread_key_t;
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL ,MUTEX_INITIALIZER
#define MUTEX_FIRSTCREATE(m)
#endif
LDAP_END_DECL
#elif defined( HAVE_GNU_PTH )
......@@ -115,6 +125,11 @@ typedef pth_key_t ldap_int_thread_key_t;
typedef pth_rwlock_t ldap_int_thread_rdwr_t;
#endif
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL ,PTH_MUTEX_INIT
#define MUTEX_FIRSTCREATE(m)
#endif
LDAP_END_DECL
#elif defined( HAVE_THR )
......@@ -143,7 +158,10 @@ typedef thread_key_t ldap_int_thread_key_t;
#define LDAP_THREAD_HAVE_SETCONCURRENCY 1
#endif
LDAP_END_DECL
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL ,DEFAULTMUTEX
#define MUTEX_FIRSTCREATE(m)
#endif
#elif defined(HAVE_NT_THREADS)
/*************************************
......@@ -162,6 +180,11 @@ typedef HANDLE ldap_int_thread_mutex_t;
typedef HANDLE ldap_int_thread_cond_t;
typedef DWORD ldap_int_thread_key_t;
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL ,(HANDLE)0
#define MUTEX_FIRSTCREATE(m) (!m ? 0 : ldap_pvt_thread_mutex_init(&m) )
#endif
LDAP_END_DECL
#else
......@@ -186,6 +209,11 @@ typedef int ldap_int_thread_key_t;
#define LDAP_THREAD_HAVE_TPOOL 1
typedef int ldap_int_thread_pool_t;
#ifndef LDO_MUTEX_NULL
#define LDO_MUTEX_NULL
#define MUTEX_FIRSTCREATE(m)
#endif
LDAP_END_DECL
#endif /* no threads support */
......
......@@ -206,7 +206,7 @@ start_again:;
* LDAP_NEXT_MSGID(ld, i);
*/
i = ++(ld)->ld_msgid;
LDAP_NEXT_MSGID(ld, i);
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
struct sockaddr sa = {0};
......@@ -216,11 +216,14 @@ start_again:;
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
LDAP_VERSION2 )
{
char *dn = ld->ld_options.ldo_cldapdn;
char *dn;
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
dn = ld->ld_options.ldo_cldapdn;
if (!dn) dn = "";
err = ber_printf( ber, "{isti", /* '}' */
i, dn,
LDAP_REQ_ABANDON, msgid );
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
} else
#endif
{
......@@ -287,10 +290,7 @@ start_again:;
}
}
/* ld_abandoned is actually protected by the ld_res_mutex;
* give up the ld_req_mutex and get the other */
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
/* use bisection */
i = 0;
......@@ -304,8 +304,7 @@ start_again:;
ld->ld_errno = LDAP_SUCCESS;
}
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
return( ld->ld_errno );
}
......
......@@ -416,7 +416,7 @@ ldap_int_sasl_bind(
void *ssl;
rc = 0;
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
if ( sd == AC_SOCKET_INVALID ) {
......@@ -434,7 +434,7 @@ ldap_int_sasl_bind(
}
}
}
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
if( rc != 0 ) return ld->ld_errno;
oldctx = ld->ld_defconn->lconn_sasl_authctx;
......
......@@ -36,7 +36,7 @@
#include "lutil.h"
struct ldapoptions ldap_int_global_options =
{ LDAP_UNINITIALIZED, LDAP_DEBUG_NONE };
{ LDAP_UNINITIALIZED, LDAP_DEBUG_NONE LDO_MUTEX_NULL };
#define ATTR_NONE 0
#define ATTR_BOOL 1
......@@ -510,6 +510,13 @@ ldap_int_destroy_global_options(void)
*/
void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl )
{
MUTEX_FIRSTCREATE(gopts->ldo_mutex);
LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
if (gopts->ldo_valid == LDAP_INITIALIZED) {
/* someone else got here first */
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
return;
}
if (dbglvl)
gopts->ldo_debug = *dbglvl;
else
......@@ -573,6 +580,7 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl
gopts->ldo_keepalive_idle = 0;
gopts->ldo_valid = LDAP_INITIALIZED;
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
return;
}
......
......@@ -174,6 +174,7 @@ typedef struct ldaplist {
/*
* structure representing get/set'able options
* which have global defaults.
* Protect access to this struct with ldo_mutex
*/
struct ldapoptions {
short ldo_valid;
......@@ -182,6 +183,12 @@ struct ldapoptions {
#define LDAP_VALID_SESSION 0x2
#define LDAP_TRASHED_SESSION 0xFF
int ldo_debug;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t ldo_mutex;
#else
#define LDO_MUTEX_NULL
#define MUTEX_FIRSTCREATE(m)
#endif
#ifdef LDAP_CONNECTIONLESS
#define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp)
void* ldo_peer; /* struct sockaddr* */
......@@ -361,24 +368,27 @@ typedef struct ldapreqinfo {
* structure representing an ldap connection
*/
struct ldap {
Sockbuf *ld_sb; /* socket descriptor & buffer */
struct ldap_common {
Sockbuf *ldc_sb; /* socket descriptor & buffer */
#define ld_sb ldc->ldc_sb
struct ldapoptions ld_options;
/* protected by ldo_mutex */
struct ldapoptions ldc_options;
#define ld_options ldc->ldc_options
#define ld_valid ld_options.ldo_valid
#define ld_debug ld_options.ldo_debug
#define ld_deref ld_options.ldo_deref
#define ld_timelimit ld_options.ldo_timelimit
#define ld_sizelimit ld_options.ldo_sizelimit
#define ld_timelimit ld_options.ldo_timelimit
#define ld_sizelimit ld_options.ldo_sizelimit
#define ld_defbinddn ld_options.ldo_defbinddn
#define ld_defbinddn ld_options.ldo_defbinddn
#define ld_defbase ld_options.ldo_defbase
#define ld_defhost ld_options.ldo_defhost
#define ld_defport ld_options.ldo_defport
#define ld_refhoplimit ld_options.ldo_refhoplimit
#define ld_refhoplimit ld_options.ldo_refhoplimit
#define ld_sctrls ld_options.ldo_sctrls
#define ld_cctrls ld_options.ldo_cctrls
......@@ -390,36 +400,79 @@ struct ldap {
#define ld_urllist_params ld_options.ldo_urllist_params
#define ld_version ld_options.ldo_version
#ifdef LDAP_R_COMPILE
#define ld_ldopts_mutex ld_options.ldo_mutex
#endif
unsigned short ld_lberoptions;
unsigned short ldc_lberoptions;
#define ld_lberoptions ldc->ldc_lberoptions
ber_int_t ld_errno;
char *ld_error;
char *ld_matched;
char **ld_referrals;
ber_len_t ld_msgid;
/* protected by msgid_mutex */
ber_len_t ldc_msgid;
#define ld_msgid ldc->ldc_msgid
/* do not mess with these */
LDAPRequest *ld_requests; /* list of outstanding requests */
LDAPMessage *ld_responses; /* list of outstanding responses */
/* protected by req_mutex */
LDAPRequest *ldc_requests; /* list of outstanding requests */
/* protected by res_mutex */
LDAPMessage *ldc_responses; /* list of outstanding responses */
#define ld_requests ldc->ldc_requests
#define ld_responses ldc->ldc_responses
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t ld_conn_mutex;
ldap_pvt_thread_mutex_t ld_req_mutex;
ldap_pvt_thread_mutex_t ld_res_mutex;
ldap_pvt_thread_mutex_t ldc_msgid_mutex;
ldap_pvt_thread_mutex_t ldc_conn_mutex;
ldap_pvt_thread_mutex_t ldc_req_mutex;
ldap_pvt_thread_mutex_t ldc_res_mutex;
ldap_pvt_thread_mutex_t ldc_abandon_mutex;
#define ld_msgid_mutex ldc->ldc_msgid_mutex
#define ld_conn_mutex ldc->ldc_conn_mutex
#define ld_req_mutex ldc->ldc_req_mutex
#define ld_res_mutex ldc->ldc_res_mutex
#define ld_abandon_mutex ldc->ldc_abandon_mutex
#endif
ber_len_t ld_nabandoned;
ber_int_t *ld_abandoned; /* array of abandoned requests */
/* protected by abandon_mutex */
ber_len_t ldc_nabandoned;
ber_int_t *ldc_abandoned; /* array of abandoned requests */
#define ld_nabandoned ldc->ldc_nabandoned
#define ld_abandoned ldc->ldc_abandoned
LDAPCache *ld_cache; /* non-null if cache is initialized */
/* unused by libldap */
LDAPCache *ldc_cache; /* non-null if cache is initialized */
#define ld_cache ldc->ldc_cache
/* do not mess with the rest though */
LDAPConn *ld_defconn; /* default connection */
LDAPConn *ld_conns; /* list of server connections */
void *ld_selectinfo; /* platform specifics for select */
/* protected by conn_mutex */
LDAPConn *ldc_defconn; /* default connection */
#define ld_defconn ldc->ldc_defconn
LDAPConn *ldc_conns; /* list of server connections */
#define ld_conns ldc->ldc_conns
void *ldc_selectinfo;/* platform specifics for select */
#define ld_selectinfo ldc->ldc_selectinfo
/* ldap_common refcnt - free only if 0 */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t ldc_mutex;
#define ld_ldcmutex ldc->ldc_mutex
#endif
/* protected by ldc_mutex */
unsigned int ldc_refcnt;
#define ld_ldcrefcnt ldc->ldc_refcnt
};
struct ldap {
/* thread shared */
struct ldap_common *ldc;
/* thread specific */
ber_int_t ld_errno;
char *ld_error;
char *ld_matched;
char **ld_referrals;
};
#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
#define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION )
#define LDAP_TRASH(ld) ( (ld)->ld_valid = LDAP_TRASHED_SESSION )
......@@ -448,9 +501,9 @@ LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_gssapi_mutex;
#ifdef LDAP_R_COMPILE
#define LDAP_NEXT_MSGID(ld, id) \
LDAP_MUTEX_LOCK( &(ld)->ld_req_mutex ); \
LDAP_MUTEX_LOCK( &(ld)->ld_msgid_mutex ); \
id = ++(ld)->ld_msgid; \
LDAP_MUTEX_UNLOCK( &(ld)->ld_req_mutex )
LDAP_MUTEX_UNLOCK( &(ld)->ld_msgid_mutex )
#else
#define LDAP_NEXT_MSGID(ld, id) id = ++(ld)->ld_msgid
#endif
......@@ -584,8 +637,11 @@ LDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype,
LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld );
LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind );
LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber,
ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist,
LDAPConn *lc, LDAPreqinfo *bind, int noconn, int m_res );
LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist,
int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res );
LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
LDAP_F (void) ldap_return_request( LDAP *ld, LDAPRequest *lr, int freeit );
LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
......
......@@ -35,11 +35,11 @@
#include "ldap-int.h"
#include "ldap_log.h"
/* Caller should hold the req_mutex if simultaneous accesses are possible */
/* Caller must hold the conn_mutex since simultaneous accesses are possible */
int ldap_open_defconn( LDAP *ld )
{
ld->ld_defconn = ldap_new_connection( ld,
&ld->ld_options.ldo_defludp, 1, 1, NULL );
&ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 );
if( ld->ld_defconn == NULL ) {
ld->ld_errno = LDAP_SERVER_DOWN;
......@@ -74,7 +74,9 @@ ldap_open( LDAP_CONST char *host, int port )
return( NULL );
}
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
rc = ldap_open_defconn( ld );
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
if( rc < 0 ) {
ldap_ld_free( ld, 0, NULL, NULL );
......@@ -114,8 +116,19 @@ ldap_create( LDAP **ldp )
return( LDAP_NO_MEMORY );
}
if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1,
sizeof(struct ldap_common) )) == NULL ) {
LDAP_FREE( (char *)ld );
return( LDAP_NO_MEMORY );
}
/* copy the global options */
LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
#ifdef LDAP_R_COMPILE
/* Properly initialize the structs mutex */
ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) );
#endif
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
ld->ld_valid = LDAP_VALID_SESSION;
......@@ -159,10 +172,14 @@ ldap_create( LDAP **ldp )
if ( ld->ld_sb == NULL ) goto nomem;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex );
#endif
ld->ld_ldcrefcnt = 1;
*ldp = ld;
return LDAP_SUCCESS;
......@@ -265,8 +282,9 @@ ldap_init_fd(
}
}
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
/* Attach the passed socket as the LDAP's connection */
conn = ldap_new_connection( ld, NULL, 1, 0, NULL);
conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
if( conn == NULL ) {
ldap_unbind_ext( ld, NULL, NULL );
return( LDAP_NO_MEMORY );
......@@ -276,6 +294,7 @@ ldap_init_fd(
ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
ld->ld_defconn = conn;
++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
switch( proto ) {
case LDAP_PROTO_TCP:
......@@ -331,6 +350,7 @@ ldap_init_fd(
return LDAP_SUCCESS;
}
/* Protected by ld_conn_mutex */
int
ldap_int_open_connection(
LDAP *ld,
......@@ -434,8 +454,9 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
int rc;
LDAPConn *c;
LDAPRequest *lr;
LDAP *ld;
rc = ldap_create( ldp );
rc = ldap_create( &ld );
if( rc != LDAP_SUCCESS ) {
*ldp = NULL;
return( rc );
......@@ -444,7 +465,7 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
/* Make it appear that a search request, msgid 0, was sent */
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
if( lr == NULL ) {
ldap_unbind_ext( *ldp, NULL, NULL );
ldap_unbind_ext( ld, NULL, NULL );
*ldp = NULL;
return( LDAP_NO_MEMORY );
}
......@@ -453,13 +474,15 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )