mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
ITS#6625 concurrency patch from Doug Leavitt @ Oracle .com
This commit is contained in:
parent
026713f497
commit
0f30db1c46
19 changed files with 2499 additions and 249 deletions
714
doc/drafts/draft-zeilenga-ldap-c-api-concurrency-xx.txt
Normal file
714
doc/drafts/draft-zeilenga-ldap-c-api-concurrency-xx.txt
Normal file
|
|
@ -0,0 +1,714 @@
|
||||||
|
INTERNET-DRAFT Kurt D. Zeilenga
|
||||||
|
Intended Category: Standards Track OpenLDAP Foundation
|
||||||
|
Extends: draft-ietf-ldapext-ldap-c-api-03.txt
|
||||||
|
Expires: 28 March 2000
|
||||||
|
28 September 1999
|
||||||
|
|
||||||
|
LDAP C API Concurrency Extensions
|
||||||
|
<draft-zeilenga-ldap-c-api-concurrency-00.txt>
|
||||||
|
|
||||||
|
1. Status of this Memo
|
||||||
|
|
||||||
|
This document is an Internet-Draft and is in full conformance with all
|
||||||
|
provisions of Section 10 of RFC2026.
|
||||||
|
|
||||||
|
This draft document will be submitted to the RFC Editor as a Standards
|
||||||
|
Track document. Distribution of this memo is unlimited. Technical
|
||||||
|
discussion of this document will take place on the IETF LDAP Extension
|
||||||
|
Working Group mailing list <ietf-ldapext@netscape.com>. Please send
|
||||||
|
editorial comments directly to the author <Kurt@OpenLDAP.org>.
|
||||||
|
|
||||||
|
Internet-Drafts are working documents of the Internet Engineering Task
|
||||||
|
Force (IETF), its areas, and its working groups. Note that other
|
||||||
|
groups may also distribute working documents as Internet-Drafts.
|
||||||
|
|
||||||
|
Internet-Drafts are draft documents valid for a maximum of six months
|
||||||
|
and may be updated, replaced, or obsoleted by other documents at any
|
||||||
|
time. It is inappropriate to use Internet-Drafts as reference
|
||||||
|
material or to cite them other than as "work in progress."
|
||||||
|
|
||||||
|
The list of current Internet-Drafts can be accessed at
|
||||||
|
http://www.ietf.org/ietf/1id-abstracts.txt
|
||||||
|
|
||||||
|
The list of Internet-Draft Shadow Directories can be accessed at
|
||||||
|
http://www.ietf.org/shadow.html.
|
||||||
|
|
||||||
|
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||||
|
|
||||||
|
Please see the Copyright section near the end of this document for
|
||||||
|
more information.
|
||||||
|
|
||||||
|
2. Abstract
|
||||||
|
|
||||||
|
This document defines extensions to the LDAP C API to support use in
|
||||||
|
concurrent execution environments. The document describes and defines
|
||||||
|
|
||||||
|
Zeilenga [Page 1]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
requirements for multiple concurrency levels: thread safe, session
|
||||||
|
thread safe, and operation thread safe.
|
||||||
|
|
||||||
|
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||||
|
"SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are
|
||||||
|
to be interpreted as described in RFC 2119 [KEYW].
|
||||||
|
|
||||||
|
3. Introduction
|
||||||
|
|
||||||
|
This document extends the LDAP C API [CAPI] specification to support
|
||||||
|
use in concurrent execution environments. The extensions add powerful
|
||||||
|
concurrent processing capabilities to the simple to use CAPI. This
|
||||||
|
document provides an overview of different levels of concurrent
|
||||||
|
execution support and offers a number of CAPI "features" to provide
|
||||||
|
capabilities at these levels.
|
||||||
|
|
||||||
|
The remainder of this section describes three levels of concurrent
|
||||||
|
execution: thread safe, session thread safe, operation thread safe
|
||||||
|
APIs.
|
||||||
|
|
||||||
|
3.1. Thread Safe
|
||||||
|
|
||||||
|
An implementation which allows applications to safely execute in
|
||||||
|
concurrent execution environments where the application provides
|
||||||
|
necessary synchronization to ensure serialization of CAPI usage is
|
||||||
|
considered to be "thread safe." Applications may execute non-CAPI
|
||||||
|
calls in concurrent execution contexts when using thread safe
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
3.2. Session Thread Safe
|
||||||
|
|
||||||
|
A "thread safe" implementation which allows CAPI calls associated with
|
||||||
|
different LDAP sessions to proceed asychronously is considered to be
|
||||||
|
"session thread safe."
|
||||||
|
|
||||||
|
3.3. Operation Thread Safe
|
||||||
|
|
||||||
|
A "session thread safe" implementation which allows CAPI calls
|
||||||
|
associated with different LDAP operations to proceed asychronously is
|
||||||
|
considered to be "operation thread safe".
|
||||||
|
|
||||||
|
4. Basic Thread Safe Feature
|
||||||
|
|
||||||
|
Zeilenga [Page 2]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
This section details requirements for the thread safe CAPI feature.
|
||||||
|
Implementations fulfilling these requirements are said to support the
|
||||||
|
LDAP_API_FEATURE_THREAD_SAFE feature and SHOULD advertise this support
|
||||||
|
as detailed below. This feature SHOULD be provided by
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
Implementations of this feature MUST implement the LDAP error handling
|
||||||
|
extension [ERRNO].
|
||||||
|
|
||||||
|
Implementations of this feature MUST allow non-CAPI calls to proceed
|
||||||
|
asynchronously.
|
||||||
|
|
||||||
|
Implementations of this feature MUST NOT use any non-thread safe call
|
||||||
|
or mechanism provided by C environment or operating system. An
|
||||||
|
example of non-reentrant calls is the UNIX strtok() function. Example
|
||||||
|
of a non-reentrant mechanism is global (i.e.: non-thread specific)
|
||||||
|
errno.
|
||||||
|
|
||||||
|
5. Session Thread Safe Feature
|
||||||
|
|
||||||
|
This section details requirements for the session thread safe CAPI
|
||||||
|
feature. Implementations fulfilling these requirements are said to
|
||||||
|
support the LDAP_API_FEATURE_SESSION_THREAD_SAFE feature and SHOULD
|
||||||
|
advertise this support as detailed below. This feature is
|
||||||
|
RECOMMENDED.
|
||||||
|
|
||||||
|
5.1. Prerequisite Features
|
||||||
|
|
||||||
|
Implementations providing this feature MUST provide and advertise both
|
||||||
|
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO [ERRNO] and
|
||||||
|
LDAP_API_FEATURE_THREAD_SAFE.
|
||||||
|
|
||||||
|
5.2. Atomic Session Handles
|
||||||
|
|
||||||
|
Implementations providing this feature SHOULD ensure that operations
|
||||||
|
upon a given session handle are atomic. Implementations which provide
|
||||||
|
atomic session handles SHOULD advertise the feature
|
||||||
|
LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES.
|
||||||
|
|
||||||
|
5.3. Concurrency Requirements
|
||||||
|
|
||||||
|
Implementations providing this feature MUST not restrict CAPI calls
|
||||||
|
acting upon a given LDAP session to a particular execution context.
|
||||||
|
Applications MAY use a session handle on any thread. Applications
|
||||||
|
|
||||||
|
Zeilenga [Page 3]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
MUST NOT assume that operations upon a session are atomic.
|
||||||
|
|
||||||
|
Implementations providing this feature MUST allow CAPI calls acting
|
||||||
|
upon different LDAP sessions to safely proceed asynchronously.
|
||||||
|
|
||||||
|
Implementations providing this feature MUST allow CAPI calls not
|
||||||
|
acting upon an LDAP session to safely proceed asynchronously.
|
||||||
|
|
||||||
|
6. Operation Thread Safe Feature
|
||||||
|
|
||||||
|
This section details requirements for the operation thread safe CAPI
|
||||||
|
feature based upon a duplicate session handles mechanism.
|
||||||
|
|
||||||
|
Implementations fulfilling these requirements are said to support the
|
||||||
|
LDAP_API_FEATURE_DUPLICATE_SESSION_HANDLES feature and SHOULD
|
||||||
|
advertise this support as detailed below. This feature is OPTIONAL.
|
||||||
|
|
||||||
|
6.1. Prerequisite Features
|
||||||
|
|
||||||
|
Implementations of this feature MUST provide and advertise
|
||||||
|
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO [ERRNO],
|
||||||
|
LDAP_API_FEATURE_THREAD_SAFE, LDAP_API_FEATURE_SESSION_THREAD_SAFE,
|
||||||
|
and LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES.
|
||||||
|
|
||||||
|
6.2. Duplicated Session Handles
|
||||||
|
|
||||||
|
Implementations of this feature MUST support duplicated session
|
||||||
|
handles.
|
||||||
|
|
||||||
|
As defined in CAPI, a session handle refers to an LDAP session
|
||||||
|
encompassing connections with one or more servers, associated message
|
||||||
|
results, a set of properties (options), and state information. This
|
||||||
|
feature provides a mechanism for a handle to be duplicated. A session
|
||||||
|
handle and its duplicates are considered siblings. Each sibling
|
||||||
|
session handle refers to the same LDAP session and message results.
|
||||||
|
Some properties and state are specific to a handle and others shared
|
||||||
|
between siblings as detailed below.
|
||||||
|
|
||||||
|
CAPI calls made on a handle are atomic. Calls made on sibling (or
|
||||||
|
other) handles MAY proceed asynchronously.
|
||||||
|
|
||||||
|
Session handles are duplicated using ldap_dup() and destroyed using
|
||||||
|
ldap_destroy(). Use of duplicated session handles with CAPI calls
|
||||||
|
have the following semantics detailed in the sections below.
|
||||||
|
|
||||||
|
Zeilenga [Page 4]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
6.2.1. Creating and Destroying duplicated sessions
|
||||||
|
|
||||||
|
Implementations of this feature are required to provide two new
|
||||||
|
routines: LDAP *ldap_dup( ld ); int ldap_destroy( ld );
|
||||||
|
|
||||||
|
Parameters are: ld The session handle
|
||||||
|
|
||||||
|
The ldap_dup() function returns a duplicate of a session handle. The
|
||||||
|
returned session handle may be used concurrently with the original
|
||||||
|
session handle as described below. ldap_dup returns NULL if it is not
|
||||||
|
able to duplicate the session handle and sets LDAP_OPT_ERROR_NUMBER
|
||||||
|
and ldap_errno indicating the nature of the failure.
|
||||||
|
|
||||||
|
The ldap_destroy() function destroys the session handle. If the
|
||||||
|
session handle has no siblings, ldap_destroy behaves exactly like
|
||||||
|
ldap_unbind. If the session handle has siblings, the resources
|
||||||
|
assocated with the handle are released and the siblings remain valid.
|
||||||
|
ldap_destroy() returns LDAP_SUCCESS or an error number indicating the
|
||||||
|
nature of failure. Regardless of returned value, the handle SHOULD be
|
||||||
|
considered invalid and MUST not be used in subsequent calls. Attempts
|
||||||
|
to use a destroyed session handle MUST NOT result in
|
||||||
|
LDAP_INVALID_SESSION error being reported. Implementations SHOULD
|
||||||
|
report LDAP_PARAM_ERROR in such cases.
|
||||||
|
|
||||||
|
6.2.2. ldap_unbind and siblings
|
||||||
|
|
||||||
|
When ldap_unbind() is called on a session handle with siblings, the
|
||||||
|
siblings become invalid. The siblings must be destroyed using
|
||||||
|
ldap_destroy(). All attempts to obtain the siblings'
|
||||||
|
LDAP_OPT_ERROR_NUMBER will return LDAP_INVALID_SESSION. Any use other
|
||||||
|
than ldap_destroy() or reading LDAP_OPT_ERROR_NUMBER will fail with an
|
||||||
|
LDAP_INVALID_SESSION error being reported.
|
||||||
|
|
||||||
|
6.2.3. ldap_result()
|
||||||
|
|
||||||
|
Message queues are shared between siblings. Results of operations on
|
||||||
|
a duplicated session handles are accessible to all sibling session
|
||||||
|
handles.
|
||||||
|
|
||||||
|
Applications desiring results associated with a specific operation
|
||||||
|
SHOULD provide the appropriate msgid to ldap_result(). Applications
|
||||||
|
SHOULD avoid calling ldap_result() with LDAP_RES_ANY as such may
|
||||||
|
"steal" and return results which an operation on a sibling requires to
|
||||||
|
complete.
|
||||||
|
|
||||||
|
Zeilenga [Page 5]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
6.2.4. Session Options
|
||||||
|
|
||||||
|
The following CAPI options access values shared between siblings:
|
||||||
|
|
||||||
|
LDAP_OPT_API_INFO LDAP_OPT_DESC LDAP_OPT_REFERRALS
|
||||||
|
LDAP_OPT_PROTOCOL_VERSION LDAP_OPT_API_FEATURE_INFO
|
||||||
|
LDAP_OPT_HOST_NAME
|
||||||
|
|
||||||
|
The following CAPI options access values specific to a sibling:
|
||||||
|
|
||||||
|
LDAP_OPT_DEREF LDAP_OPT_SIZELIMIT LDAP_OPT_TIMELIMIT
|
||||||
|
LDAP_OPT_RESTART LDAP_OPT_CLIENT_CONTROLS
|
||||||
|
LDAP_OPT_SERVER_CONTROLS LDAP_OPT_ERROR_NUMBER
|
||||||
|
LDAP_OPT_ERROR_STRING LDAP_OPT_MATCHED_DN
|
||||||
|
|
||||||
|
6.2.4.1. LDAP_OPT_SESSION_REFCNT
|
||||||
|
|
||||||
|
In addition, implementations MUST provide the READ-ONLY, shared
|
||||||
|
LDAP_OPT_SESSION_REFCNT option. LDAP_OPT_SESSION_REFCNT returns the
|
||||||
|
reference count associated with the supplied session handle argument.
|
||||||
|
The session handle argument is required. The outvalue argument should
|
||||||
|
be a pointer to an integer. Example use:
|
||||||
|
|
||||||
|
int refcount(LDAP *ld) {
|
||||||
|
|
||||||
|
#ifdef LDAP_OPT_SESSION_REFCNT
|
||||||
|
|
||||||
|
if(ld != NULL) {
|
||||||
|
int refcnt, rc;
|
||||||
|
rc = ldap_get_option(ld,
|
||||||
|
LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||||
|
|
||||||
|
if(rc == LDAP_OPT_SUCCESS) {
|
||||||
|
return refcnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
7. Advertising Features
|
||||||
|
|
||||||
|
This document REQUIRES that supported features with the name in the
|
||||||
|
form LDAP_API_FEATURE_x be advertised to consumers of the CAPI as
|
||||||
|
|
||||||
|
Zeilenga [Page 6]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
follows:
|
||||||
|
|
||||||
|
SHOULD provide the macro LDAP_API_FEATURE_x with the value
|
||||||
|
of 1000 + revision number of this draft (i.e.: 1000+0 for
|
||||||
|
this 0 revision of the draft).
|
||||||
|
|
||||||
|
MUST provide the CAPI extension "x" when returning API
|
||||||
|
information upon LDAP_OPT_API_INFO option access, and
|
||||||
|
|
||||||
|
MUST provide feature info for "x" via LDAP_OPT_FEATURE_INFO
|
||||||
|
option mechanism. The feature version provided MUST match
|
||||||
|
the value LDAP_API_FEATURE_x macro
|
||||||
|
|
||||||
|
where x is replaced appropriately.
|
||||||
|
|
||||||
|
As implementations may not provide macros for all features,
|
||||||
|
applications SHOULD use LDAP_OPT_API_INFO to determine which features
|
||||||
|
are provided by a given implementation.
|
||||||
|
|
||||||
|
8. Changes to the C API specification
|
||||||
|
|
||||||
|
8.1. New Symbols
|
||||||
|
|
||||||
|
This extension introduces the following macros:
|
||||||
|
|
||||||
|
LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES
|
||||||
|
LDAP_API_FEATURE_DUPLICATE_SESSION_HANDLES
|
||||||
|
LDAP_API_FEATURE_SESSION_THREAD_SAFE
|
||||||
|
LDAP_API_FEATURE_THREAD_SAFE
|
||||||
|
LDAP_API_FEATURE_OPERATION_THREAD_SAFE LDAP_INVALID_SESSION
|
||||||
|
LDAP_OPT_SESSION_REFCNT
|
||||||
|
|
||||||
|
This extension introduces these new functions:
|
||||||
|
|
||||||
|
ldap_destroy() ldap_dup()
|
||||||
|
|
||||||
|
This extension introduces no new typedefs nor structure names.
|
||||||
|
|
||||||
|
8.2. Duplicated Session Handles
|
||||||
|
|
||||||
|
This extension introduces duplicated session handles and requirements
|
||||||
|
for handling duplicated session handles. Semantics of non-duplicated
|
||||||
|
session handles are not affected by this introduction. However, the
|
||||||
|
semantics of calls upon duplicate session handles differs as described
|
||||||
|
in the extension.
|
||||||
|
|
||||||
|
Zeilenga [Page 7]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
9. Security Considerations
|
||||||
|
|
||||||
|
None taken, none given.
|
||||||
|
|
||||||
|
10. Copyright
|
||||||
|
|
||||||
|
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||||
|
|
||||||
|
This document and translations of it may be copied and furnished to
|
||||||
|
others, and derivative works that comment on or otherwise explain it
|
||||||
|
or assist in its implementation may be prepared, copied, published and
|
||||||
|
distributed, in whole or in part, without restriction of any kind,
|
||||||
|
provided that the above copyright notice and this paragraph are
|
||||||
|
included on all such copies and derivative works. However, this
|
||||||
|
document itself may not be modified in any way, such as by removing
|
||||||
|
the copyright notice or references to the Internet Society or other
|
||||||
|
Internet organizations, except as needed for the purpose of
|
||||||
|
developing Internet standards in which case the procedures for
|
||||||
|
copyrights defined in the Internet Standards process must be followed,
|
||||||
|
or as required to translate it into languages other than English.
|
||||||
|
|
||||||
|
The limited permissions granted above are perpetual and will not be
|
||||||
|
revoked by the Internet Society or its successors or assigns.
|
||||||
|
|
||||||
|
This document and the information contained herein is provided on an
|
||||||
|
"AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
|
||||||
|
ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||||
|
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
11. Bibliography
|
||||||
|
|
||||||
|
[CAPI] M. Smith, T. Howes, A. Herron, M. Wahl, A. Anantha, "The
|
||||||
|
C LDAP Application Program Interface", INTERNET-DRAFT, <draft-
|
||||||
|
ietf-ldapext-ldap-c-api-03.txt> + LDAPext discussions, June 1999.
|
||||||
|
|
||||||
|
[ERRNO] K. Zeilenga, "LDAP C API Error Reporting Extension",
|
||||||
|
INTERNET-DRAFT, <draft-zeilenga-ldap-c-api-errno-00.txt>,
|
||||||
|
June 1999.
|
||||||
|
|
||||||
|
[KEYW] S. Bradner, "Key words for use in RFCs to Indicate
|
||||||
|
Requirement Levels", RFC 2119, March 1997.
|
||||||
|
|
||||||
|
Zeilenga [Page 8]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||||
|
|
||||||
|
[LDAP] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
|
||||||
|
Access Protocol (v3)", RFC 2251, December 1997.
|
||||||
|
|
||||||
|
13. Author's Address
|
||||||
|
|
||||||
|
Kurt D. Zeilenga
|
||||||
|
OpenLDAP Foundation
|
||||||
|
<Kurt@OpenLDAP.org>
|
||||||
|
|
||||||
|
This document expires on 28 March 2000.
|
||||||
|
|
||||||
|
Zeilenga [Page 9]
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
INTERNET-DRAFT Kurt D. Zeilenga
|
||||||
|
Intended Category: Standards Track OpenLDAP Foundation
|
||||||
|
Extends: draft-ietf-ldapext-ldap-c-api-03.txt
|
||||||
|
Expires: 28 March 2000
|
||||||
|
28 September 1999
|
||||||
|
|
||||||
|
LDAP C API Error Reporting Extension
|
||||||
|
<draft-zeilenga-ldap-c-api-errno-00.txt>
|
||||||
|
|
||||||
|
1. Status of this Memo
|
||||||
|
|
||||||
|
This document is an Internet-Draft and is in full conformance with all
|
||||||
|
provisions of Section 10 of RFC2026.
|
||||||
|
|
||||||
|
This draft document will be submitted to the RFC Editor as a Standards
|
||||||
|
Track document. Distribution of this memo is unlimited. Technical
|
||||||
|
discussion of this document will take place on the IETF LDAP Extension
|
||||||
|
Working Group mailing list <ietf-ldapext@netscape.com>. Please send
|
||||||
|
editorial comments directly to the author <Kurt@OpenLDAP.org>.
|
||||||
|
|
||||||
|
Internet-Drafts are working documents of the Internet Engineering Task
|
||||||
|
Force (IETF), its areas, and its working groups. Note that other
|
||||||
|
groups may also distribute working documents as Internet-Drafts.
|
||||||
|
|
||||||
|
Internet-Drafts are draft documents valid for a maximum of six months
|
||||||
|
and may be updated, replaced, or obsoleted by other documents at any
|
||||||
|
time. It is inappropriate to use Internet-Drafts as reference
|
||||||
|
material or to cite them other than as ``work in progress.''
|
||||||
|
|
||||||
|
The list of current Internet-Drafts can be accessed at
|
||||||
|
http://www.ietf.org/ietf/1id-abstracts.txt
|
||||||
|
|
||||||
|
The list of Internet-Draft Shadow Directories can be accessed at
|
||||||
|
http://www.ietf.org/shadow.html.
|
||||||
|
|
||||||
|
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||||
|
|
||||||
|
Please see the Copyright section near the end of this document for
|
||||||
|
more information.
|
||||||
|
|
||||||
|
2. Abstract
|
||||||
|
|
||||||
|
This document defines a manatory extension to the LDAP C API to
|
||||||
|
provide error reporting for all API calls. The mechanism is
|
||||||
|
nonintrusive and can, optionally, support concurrent execution
|
||||||
|
environments.
|
||||||
|
|
||||||
|
Zeilenga [Page 1]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
The key words ``MUST'', ``MUST NOT'', ``REQUIRED'', ``SHALL'', ``SHALL
|
||||||
|
NOT'', ``SHOULD'', ``SHOULD NOT'', ``RECOMMENDED'', and ``MAY'' in
|
||||||
|
this document are to be interpreted as described in RFC 2119 [KEYW].
|
||||||
|
|
||||||
|
3. Background and Intent of Use
|
||||||
|
|
||||||
|
The LDAP [LDAP] C API [CAPI] provides an interface which (due to
|
||||||
|
legacy compatibiity issues) does not provide a consistent mechanism
|
||||||
|
for reporting errors. A large number of the calls within the
|
||||||
|
specification have no mechanism to indicate the nature of a failure.
|
||||||
|
The usefulness of a CAPI without a consistent, easy to use, error
|
||||||
|
reporting mechanism is limited.
|
||||||
|
|
||||||
|
This document defines an mandatory extension to the CAPI. All
|
||||||
|
implementations of the CAPI MUST provide this extension.
|
||||||
|
|
||||||
|
The extension details additional requirements for error reporting.
|
||||||
|
Implementations MUST fulfill all other CAPI error reporting
|
||||||
|
requirements.
|
||||||
|
|
||||||
|
4. Error Handling Extension
|
||||||
|
|
||||||
|
This extension provides a mechanism that applications MAY use to
|
||||||
|
obtain an LDAP error number indicating the nature of the failure
|
||||||
|
associated with the last failed CAPI call.
|
||||||
|
|
||||||
|
Implementations MUST provide access to an LDAP error number (CAPI,
|
||||||
|
Section 9) resulting from the last failed CAPI call via the symbol
|
||||||
|
ldap_errno. The last failed CAPI call may be within the global
|
||||||
|
context or within the current execution context.
|
||||||
|
|
||||||
|
The ldap_errno MUST evaluate to a modifiable lvalue that has type
|
||||||
|
'int', the value of which is set to a LDAP error number. It is
|
||||||
|
unspecified whether ldap_errno is a macro or an identifier declared
|
||||||
|
with external linkage. If a macro definition is suppressed in order
|
||||||
|
to access an actual object, or a program defines an identifier with
|
||||||
|
the name ldap_errno, the behavior is undefined.
|
||||||
|
|
||||||
|
Applications MUST access ldap_errno within the same concurrent
|
||||||
|
execution context, commonly a thread, in which the failure occurred.
|
||||||
|
The value of ldap_errno is LDAP_SUCCESS (0) if no API failure has
|
||||||
|
occurred within the supported context and the user has not assigned a
|
||||||
|
value within the supported context.
|
||||||
|
|
||||||
|
Zeilenga [Page 2]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
Implementations SHALL NOT update the ldap_errno value upon successful
|
||||||
|
CAPI call completion.
|
||||||
|
|
||||||
|
Implementations providing a current execution context specific
|
||||||
|
ldap_errno MUST advertise the feature LDAP_API_CONTEXT_SPECIFIC_ERRNO
|
||||||
|
as described in Section 6. Implementation of
|
||||||
|
LDAP_API_CONTEXT_SPECIFIC_ERRNO is RECOMMENDED.
|
||||||
|
|
||||||
|
4.1. Reporting Server Errors
|
||||||
|
|
||||||
|
It is not a CAPI failure for a server to return an error number.
|
||||||
|
Implementations SHALL NOT assign error results returned by servers to
|
||||||
|
ldap_errno.
|
||||||
|
|
||||||
|
4.2. Implementation Specific Reporting
|
||||||
|
|
||||||
|
The CAPI specification stated that the caller may obtain an indication
|
||||||
|
of failure of certain calls (see listed below) using implementation
|
||||||
|
specific and/or operating system specific requirements.
|
||||||
|
Implementations are NOT REQUIRED to support any implementation
|
||||||
|
specific and/or operating system mechanism for ANY call detailed by
|
||||||
|
the CAPI specification or its extensions.
|
||||||
|
|
||||||
|
Affected calls include ldap_init(), ldap_open(), and ber_*().
|
||||||
|
|
||||||
|
4.3. Example
|
||||||
|
|
||||||
|
The following is an example showing how an application may obtain the
|
||||||
|
error information resulting from a failed CAPI calls:
|
||||||
|
|
||||||
|
int msgid;
|
||||||
|
LDAP *ld = ldap_init("localhost", 389);
|
||||||
|
|
||||||
|
if(ld == NULL) {
|
||||||
|
printf("ldap_init failed, ldap_errno=%d (%s)\n",
|
||||||
|
ldap_errno, ldap_err2string(ldap_errno));
|
||||||
|
|
||||||
|
printf("unable to initialize LDAP session\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgid = ldap_simple_bind(ld, NULL, NULL);
|
||||||
|
|
||||||
|
if(msgid == -1) {
|
||||||
|
int err = ldap_errno;
|
||||||
|
|
||||||
|
if (err != LDAP_SUCCESS ) {
|
||||||
|
|
||||||
|
Zeilenga [Page 3]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
/* API failure */
|
||||||
|
printf("ldap_simple_bind failure: ldap_errno=%d (%s)\n",
|
||||||
|
err, ldap_err2string(err));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int lderr, rc;
|
||||||
|
|
||||||
|
printf("ldap_simple_bind failed\n");
|
||||||
|
|
||||||
|
rc = ldap_get_option(ld,
|
||||||
|
LDAP_OPT_ERROR_NUMBER, &lderr);
|
||||||
|
|
||||||
|
if(rc == LDAP_OPT_SUCCESS) {
|
||||||
|
printf(" reason=%d (%s)\n",
|
||||||
|
lderr, ldap_err2string(lderr));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("ldap_get_option failed, ldap_errno=%d (%s)\n",
|
||||||
|
ldap_errno, ldap_err2string(ldap_errno)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
goto unbind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... */
|
||||||
|
|
||||||
|
unbind: if(ldap_unbind(ld) != 0) {
|
||||||
|
printf("ldap_unbind failed, ldap_errno=%d (%s)\n",
|
||||||
|
ldap_errno, ldap_error2str(ldap_errno));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
5. Advertising Features
|
||||||
|
|
||||||
|
This document REQUIRES that supported features with the name in the
|
||||||
|
form LDAP_API_FEATURE_x be advertised to consumers of the CAPI as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
SHOULD provide the macro LDAP_API_FEATURE_x with the value
|
||||||
|
of 1000 + revision number of this draft (i.e.: 1000+0 for
|
||||||
|
this 0 revision of the draft).
|
||||||
|
|
||||||
|
MUST provide the CAPI extension "x" when returning API
|
||||||
|
information upon LDAP_OPT_API_INFO option access, and
|
||||||
|
|
||||||
|
Zeilenga [Page 4]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
MUST provide feature info for "x" via LDAP_OPT_FEATURE_INFO
|
||||||
|
option mechanism. The feature version provided MUST match
|
||||||
|
the value LDAP_API_FEATURE_x macro
|
||||||
|
|
||||||
|
where x is replaced appropriately.
|
||||||
|
|
||||||
|
As implementations may not provide macros for all features,
|
||||||
|
applications SHOULD use LDAP_OPT_API_INFO to determine which features
|
||||||
|
are provided by a given implementation.
|
||||||
|
|
||||||
|
6. Changes to the LDAP C API
|
||||||
|
|
||||||
|
This section provides a summary of changes to the CAPI specification.
|
||||||
|
|
||||||
|
6.1. LDAP_API_VERSION
|
||||||
|
|
||||||
|
LDAP_API_VERSION should be set to the RFC number of this extension if
|
||||||
|
and when it is published as a Standards Track RFC. (see purpose of
|
||||||
|
this draft above).
|
||||||
|
|
||||||
|
Until such time as this document is published as an RFC,
|
||||||
|
implementations should use the value specified by CAPI plus 100 + 10 *
|
||||||
|
the number of this draft.
|
||||||
|
|
||||||
|
For the third draft of CAPI and this 0 revision of draft, the value of
|
||||||
|
2103 ((2000+3) + (100+10*0)) should be used.
|
||||||
|
|
||||||
|
6.2. New Symbols
|
||||||
|
|
||||||
|
This extension introduces two new symbols:
|
||||||
|
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO ldap_errno
|
||||||
|
|
||||||
|
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO is a macro. ldap_errno MAY be
|
||||||
|
a MACRO.
|
||||||
|
|
||||||
|
This extension indroductes no new functions, typedefs, or structure
|
||||||
|
names.
|
||||||
|
|
||||||
|
6.3. Implementation/System Specific Error Handling
|
||||||
|
|
||||||
|
This extensions removes any requirements that implementations to use
|
||||||
|
implementation and/or operating system specific error reporting
|
||||||
|
mechanisms.
|
||||||
|
|
||||||
|
Zeilenga [Page 5]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
7. Security Considerations
|
||||||
|
|
||||||
|
None taken, none given.
|
||||||
|
|
||||||
|
8. Copyright
|
||||||
|
|
||||||
|
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||||
|
|
||||||
|
This document and translations of it may be copied and furnished to
|
||||||
|
others, and derivative works that comment on or otherwise explain it
|
||||||
|
or assist in its implementation may be prepared, copied, published and
|
||||||
|
distributed, in whole or in part, without restriction of any kind,
|
||||||
|
provided that the above copyright notice and this paragraph are
|
||||||
|
included on all such copies and derivative works. However, this
|
||||||
|
document itself may not be modified in any way, such as by removing
|
||||||
|
the copyright notice or references to the Internet Society or other
|
||||||
|
Internet organizations, except as needed for the purpose of
|
||||||
|
developing Internet standards in which case the procedures for
|
||||||
|
copyrights defined in the Internet Standards process must be followed,
|
||||||
|
or as required to translate it into languages other than English.
|
||||||
|
|
||||||
|
The limited permissions granted above are perpetual and will not be
|
||||||
|
revoked by the Internet Society or its successors or assigns.
|
||||||
|
|
||||||
|
This document and the information contained herein is provided on an
|
||||||
|
"AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
|
||||||
|
ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||||
|
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
9. Bibliography
|
||||||
|
|
||||||
|
[CAPI] M. Smith, T. Howes, A. Herron, M. Wahl, A. Anantha,
|
||||||
|
"The C LDAP Application Program Interface", INTERNET-DRAFT,
|
||||||
|
<draft-ietf-ldapext-ldap-c-api-03.txt> + LDAPext discussions,
|
||||||
|
June 1999.
|
||||||
|
|
||||||
|
[KEYW] S. Bradner, "Key words for use in RFCs to Indicate
|
||||||
|
Requirement Levels", RFC 2119, March 1997.
|
||||||
|
|
||||||
|
[LDAP] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
|
||||||
|
Access Protocol (v3)", RFC 2251, December 1997.
|
||||||
|
|
||||||
|
Zeilenga [Page 6]
|
||||||
|
|
||||||
|
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||||
|
|
||||||
|
10. Author's Address
|
||||||
|
|
||||||
|
Kurt D. Zeilenga
|
||||||
|
OpenLDAP Foundation
|
||||||
|
<Kurt@OpenLDAP.org>
|
||||||
|
|
||||||
|
This document expires on 28 March 2000.
|
||||||
|
|
||||||
|
Zeilenga [Page 7]
|
||||||
126
doc/man/man3/ldap_dup.3
Normal file
126
doc/man/man3/ldap_dup.3
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
.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
|
||||||
1
doc/man/man3/ldap_dup.3.links
Normal file
1
doc/man/man3/ldap_dup.3.links
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ldap_destroy.3
|
||||||
|
|
@ -322,6 +322,15 @@ must be
|
||||||
the library duplicates the controls passed via
|
the library duplicates the controls passed via
|
||||||
.BR invalue .
|
.BR invalue .
|
||||||
.TP
|
.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
|
.B LDAP_OPT_SIZELIMIT
|
||||||
Sets/gets the value that defines the maximum number of entries
|
Sets/gets the value that defines the maximum number of entries
|
||||||
to be returned by a search operation.
|
to be returned by a search operation.
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,9 @@ LDAP_BEGIN_DECL
|
||||||
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
|
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
|
||||||
/* -lldap may or may not be thread safe */
|
/* -lldap may or may not be thread safe */
|
||||||
/* -lldap_r, if available, is always 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
|
#endif
|
||||||
#if defined( LDAP_THREAD_SAFE ) && \
|
#if defined( LDAP_THREAD_SAFE ) && \
|
||||||
defined( LDAP_API_FEATURE_X_OPENLDAP_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_DEFBASE 0x5009 /* searchbase */
|
||||||
#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */
|
#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */
|
||||||
#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */
|
#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */
|
||||||
|
#define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */
|
||||||
|
|
||||||
/* OpenLDAP TLS options */
|
/* OpenLDAP TLS options */
|
||||||
#define LDAP_OPT_X_TLS 0x6000
|
#define LDAP_OPT_X_TLS 0x6000
|
||||||
|
|
@ -1519,6 +1522,10 @@ ldap_initialize LDAP_P((
|
||||||
LDAP **ldp,
|
LDAP **ldp,
|
||||||
LDAP_CONST char *url ));
|
LDAP_CONST char *url ));
|
||||||
|
|
||||||
|
LDAP_F( LDAP * )
|
||||||
|
ldap_dup LDAP_P((
|
||||||
|
LDAP *old ));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in tls.c
|
* in tls.c
|
||||||
*/
|
*/
|
||||||
|
|
@ -1931,6 +1938,10 @@ ldap_unbind_ext_s LDAP_P((
|
||||||
LDAPControl **serverctrls,
|
LDAPControl **serverctrls,
|
||||||
LDAPControl **clientctrls));
|
LDAPControl **clientctrls));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_destroy LDAP_P((
|
||||||
|
LDAP *ld));
|
||||||
|
|
||||||
#if LDAP_DEPRECATED
|
#if LDAP_DEPRECATED
|
||||||
LDAP_F( int )
|
LDAP_F( int )
|
||||||
ldap_unbind LDAP_P(( /* deprecated, use ldap_unbind_ext */
|
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;
|
typedef pthread_rwlock_t ldap_int_thread_rdwr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LDO_MUTEX_NULL
|
||||||
|
#define LDO_MUTEX_NULL ,PTHREAD_MUTEX_INITIALIZER
|
||||||
|
#define MUTEX_FIRSTCREATE(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
LDAP_END_DECL
|
LDAP_END_DECL
|
||||||
|
|
||||||
#elif defined ( HAVE_MACH_CTHREADS )
|
#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 struct condition ldap_int_thread_cond_t;
|
||||||
typedef cthread_key_t ldap_int_thread_key_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
|
LDAP_END_DECL
|
||||||
|
|
||||||
#elif defined( HAVE_GNU_PTH )
|
#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;
|
typedef pth_rwlock_t ldap_int_thread_rdwr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LDO_MUTEX_NULL
|
||||||
|
#define LDO_MUTEX_NULL ,PTH_MUTEX_INIT
|
||||||
|
#define MUTEX_FIRSTCREATE(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
LDAP_END_DECL
|
LDAP_END_DECL
|
||||||
|
|
||||||
#elif defined( HAVE_THR )
|
#elif defined( HAVE_THR )
|
||||||
|
|
@ -143,7 +158,10 @@ typedef thread_key_t ldap_int_thread_key_t;
|
||||||
#define LDAP_THREAD_HAVE_SETCONCURRENCY 1
|
#define LDAP_THREAD_HAVE_SETCONCURRENCY 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LDAP_END_DECL
|
#ifndef LDO_MUTEX_NULL
|
||||||
|
#define LDO_MUTEX_NULL ,DEFAULTMUTEX
|
||||||
|
#define MUTEX_FIRSTCREATE(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(HAVE_NT_THREADS)
|
#elif defined(HAVE_NT_THREADS)
|
||||||
/*************************************
|
/*************************************
|
||||||
|
|
@ -162,6 +180,11 @@ typedef HANDLE ldap_int_thread_mutex_t;
|
||||||
typedef HANDLE ldap_int_thread_cond_t;
|
typedef HANDLE ldap_int_thread_cond_t;
|
||||||
typedef DWORD ldap_int_thread_key_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
|
LDAP_END_DECL
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
@ -186,6 +209,11 @@ typedef int ldap_int_thread_key_t;
|
||||||
#define LDAP_THREAD_HAVE_TPOOL 1
|
#define LDAP_THREAD_HAVE_TPOOL 1
|
||||||
typedef int ldap_int_thread_pool_t;
|
typedef int ldap_int_thread_pool_t;
|
||||||
|
|
||||||
|
#ifndef LDO_MUTEX_NULL
|
||||||
|
#define LDO_MUTEX_NULL
|
||||||
|
#define MUTEX_FIRSTCREATE(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
LDAP_END_DECL
|
LDAP_END_DECL
|
||||||
|
|
||||||
#endif /* no threads support */
|
#endif /* no threads support */
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ start_again:;
|
||||||
* LDAP_NEXT_MSGID(ld, i);
|
* LDAP_NEXT_MSGID(ld, i);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
i = ++(ld)->ld_msgid;
|
LDAP_NEXT_MSGID(ld, i);
|
||||||
#ifdef LDAP_CONNECTIONLESS
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
if ( LDAP_IS_UDP(ld) ) {
|
if ( LDAP_IS_UDP(ld) ) {
|
||||||
struct sockaddr sa = {0};
|
struct sockaddr sa = {0};
|
||||||
|
|
@ -216,11 +216,14 @@ start_again:;
|
||||||
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
|
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
|
||||||
LDAP_VERSION2 )
|
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 = "";
|
if (!dn) dn = "";
|
||||||
err = ber_printf( ber, "{isti", /* '}' */
|
err = ber_printf( ber, "{isti", /* '}' */
|
||||||
i, dn,
|
i, dn,
|
||||||
LDAP_REQ_ABANDON, msgid );
|
LDAP_REQ_ABANDON, msgid );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
@ -287,10 +290,7 @@ start_again:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ld_abandoned is actually protected by the ld_res_mutex;
|
LDAP_MUTEX_LOCK( &ld->ld_abandon_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 );
|
|
||||||
|
|
||||||
/* use bisection */
|
/* use bisection */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
@ -304,8 +304,7 @@ start_again:;
|
||||||
ld->ld_errno = LDAP_SUCCESS;
|
ld->ld_errno = LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
return( ld->ld_errno );
|
return( ld->ld_errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,7 @@ ldap_int_sasl_bind(
|
||||||
void *ssl;
|
void *ssl;
|
||||||
|
|
||||||
rc = 0;
|
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 );
|
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
|
||||||
|
|
||||||
if ( sd == AC_SOCKET_INVALID ) {
|
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;
|
if( rc != 0 ) return ld->ld_errno;
|
||||||
|
|
||||||
oldctx = ld->ld_defconn->lconn_sasl_authctx;
|
oldctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#include "lutil.h"
|
#include "lutil.h"
|
||||||
|
|
||||||
struct ldapoptions ldap_int_global_options =
|
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_NONE 0
|
||||||
#define ATTR_BOOL 1
|
#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 )
|
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)
|
if (dbglvl)
|
||||||
gopts->ldo_debug = *dbglvl;
|
gopts->ldo_debug = *dbglvl;
|
||||||
else
|
else
|
||||||
|
|
@ -573,6 +580,7 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl
|
||||||
gopts->ldo_keepalive_idle = 0;
|
gopts->ldo_keepalive_idle = 0;
|
||||||
|
|
||||||
gopts->ldo_valid = LDAP_INITIALIZED;
|
gopts->ldo_valid = LDAP_INITIALIZED;
|
||||||
|
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@ typedef struct ldaplist {
|
||||||
/*
|
/*
|
||||||
* structure representing get/set'able options
|
* structure representing get/set'able options
|
||||||
* which have global defaults.
|
* which have global defaults.
|
||||||
|
* Protect access to this struct with ldo_mutex
|
||||||
*/
|
*/
|
||||||
struct ldapoptions {
|
struct ldapoptions {
|
||||||
short ldo_valid;
|
short ldo_valid;
|
||||||
|
|
@ -182,6 +183,12 @@ struct ldapoptions {
|
||||||
#define LDAP_VALID_SESSION 0x2
|
#define LDAP_VALID_SESSION 0x2
|
||||||
#define LDAP_TRASHED_SESSION 0xFF
|
#define LDAP_TRASHED_SESSION 0xFF
|
||||||
int ldo_debug;
|
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
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
#define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp)
|
#define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp)
|
||||||
void* ldo_peer; /* struct sockaddr* */
|
void* ldo_peer; /* struct sockaddr* */
|
||||||
|
|
@ -361,24 +368,27 @@ typedef struct ldapreqinfo {
|
||||||
* structure representing an ldap connection
|
* structure representing an ldap connection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ldap {
|
struct ldap_common {
|
||||||
Sockbuf *ld_sb; /* socket descriptor & buffer */
|
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_valid ld_options.ldo_valid
|
||||||
#define ld_debug ld_options.ldo_debug
|
#define ld_debug ld_options.ldo_debug
|
||||||
|
|
||||||
#define ld_deref ld_options.ldo_deref
|
#define ld_deref ld_options.ldo_deref
|
||||||
#define ld_timelimit ld_options.ldo_timelimit
|
#define ld_timelimit ld_options.ldo_timelimit
|
||||||
#define ld_sizelimit ld_options.ldo_sizelimit
|
#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_defbase ld_options.ldo_defbase
|
||||||
#define ld_defhost ld_options.ldo_defhost
|
#define ld_defhost ld_options.ldo_defhost
|
||||||
#define ld_defport ld_options.ldo_defport
|
#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_sctrls ld_options.ldo_sctrls
|
||||||
#define ld_cctrls ld_options.ldo_cctrls
|
#define ld_cctrls ld_options.ldo_cctrls
|
||||||
|
|
@ -390,36 +400,79 @@ struct ldap {
|
||||||
#define ld_urllist_params ld_options.ldo_urllist_params
|
#define ld_urllist_params ld_options.ldo_urllist_params
|
||||||
|
|
||||||
#define ld_version ld_options.ldo_version
|
#define ld_version ld_options.ldo_version
|
||||||
|
|
||||||
unsigned short ld_lberoptions;
|
|
||||||
|
|
||||||
ber_int_t ld_errno;
|
|
||||||
char *ld_error;
|
|
||||||
char *ld_matched;
|
|
||||||
char **ld_referrals;
|
|
||||||
ber_len_t ld_msgid;
|
|
||||||
|
|
||||||
/* do not mess with these */
|
|
||||||
LDAPRequest *ld_requests; /* list of outstanding requests */
|
|
||||||
LDAPMessage *ld_responses; /* list of outstanding responses */
|
|
||||||
|
|
||||||
#ifdef LDAP_R_COMPILE
|
#ifdef LDAP_R_COMPILE
|
||||||
ldap_pvt_thread_mutex_t ld_conn_mutex;
|
#define ld_ldopts_mutex ld_options.ldo_mutex
|
||||||
ldap_pvt_thread_mutex_t ld_req_mutex;
|
|
||||||
ldap_pvt_thread_mutex_t ld_res_mutex;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ber_len_t ld_nabandoned;
|
unsigned short ldc_lberoptions;
|
||||||
ber_int_t *ld_abandoned; /* array of abandoned requests */
|
#define ld_lberoptions ldc->ldc_lberoptions
|
||||||
|
|
||||||
LDAPCache *ld_cache; /* non-null if cache is initialized */
|
/* protected by msgid_mutex */
|
||||||
|
ber_len_t ldc_msgid;
|
||||||
|
#define ld_msgid ldc->ldc_msgid
|
||||||
|
|
||||||
|
/* do not mess with these */
|
||||||
|
/* 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 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
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* 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 */
|
/* do not mess with the rest though */
|
||||||
|
|
||||||
LDAPConn *ld_defconn; /* default connection */
|
/* protected by conn_mutex */
|
||||||
LDAPConn *ld_conns; /* list of server connections */
|
LDAPConn *ldc_defconn; /* default connection */
|
||||||
void *ld_selectinfo; /* platform specifics for select */
|
#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_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
|
||||||
#define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION )
|
#define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION )
|
||||||
#define LDAP_TRASH(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
|
#ifdef LDAP_R_COMPILE
|
||||||
#define LDAP_NEXT_MSGID(ld, id) \
|
#define LDAP_NEXT_MSGID(ld, id) \
|
||||||
LDAP_MUTEX_LOCK( &(ld)->ld_req_mutex ); \
|
LDAP_MUTEX_LOCK( &(ld)->ld_msgid_mutex ); \
|
||||||
id = ++(ld)->ld_msgid; \
|
id = ++(ld)->ld_msgid; \
|
||||||
LDAP_MUTEX_UNLOCK( &(ld)->ld_req_mutex )
|
LDAP_MUTEX_UNLOCK( &(ld)->ld_msgid_mutex )
|
||||||
#else
|
#else
|
||||||
#define LDAP_NEXT_MSGID(ld, id) id = ++(ld)->ld_msgid
|
#define LDAP_NEXT_MSGID(ld, id) id = ++(ld)->ld_msgid
|
||||||
#endif
|
#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 (BerElement *) ldap_alloc_ber_with_options( LDAP *ld );
|
||||||
LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
|
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 (int) ldap_send_server_request( LDAP *ld, BerElement *ber,
|
||||||
LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
|
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 (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_return_request( LDAP *ld, LDAPRequest *lr, int freeit );
|
||||||
LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
|
LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@
|
||||||
#include "ldap-int.h"
|
#include "ldap-int.h"
|
||||||
#include "ldap_log.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 )
|
int ldap_open_defconn( LDAP *ld )
|
||||||
{
|
{
|
||||||
ld->ld_defconn = ldap_new_connection( 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 ) {
|
if( ld->ld_defconn == NULL ) {
|
||||||
ld->ld_errno = LDAP_SERVER_DOWN;
|
ld->ld_errno = LDAP_SERVER_DOWN;
|
||||||
|
|
@ -74,7 +74,9 @@ ldap_open( LDAP_CONST char *host, int port )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
rc = ldap_open_defconn( ld );
|
rc = ldap_open_defconn( ld );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
|
||||||
if( rc < 0 ) {
|
if( rc < 0 ) {
|
||||||
ldap_ld_free( ld, 0, NULL, NULL );
|
ldap_ld_free( ld, 0, NULL, NULL );
|
||||||
|
|
@ -114,8 +116,19 @@ ldap_create( LDAP **ldp )
|
||||||
return( LDAP_NO_MEMORY );
|
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 */
|
/* copy the global options */
|
||||||
|
LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
|
||||||
AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
|
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;
|
ld->ld_valid = LDAP_VALID_SESSION;
|
||||||
|
|
||||||
|
|
@ -159,10 +172,14 @@ ldap_create( LDAP **ldp )
|
||||||
if ( ld->ld_sb == NULL ) goto nomem;
|
if ( ld->ld_sb == NULL ) goto nomem;
|
||||||
|
|
||||||
#ifdef LDAP_R_COMPILE
|
#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_req_mutex );
|
||||||
ldap_pvt_thread_mutex_init( &ld->ld_res_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
|
#endif
|
||||||
|
ld->ld_ldcrefcnt = 1;
|
||||||
*ldp = ld;
|
*ldp = ld;
|
||||||
return LDAP_SUCCESS;
|
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 */
|
/* 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 ) {
|
if( conn == NULL ) {
|
||||||
ldap_unbind_ext( ld, NULL, NULL );
|
ldap_unbind_ext( ld, NULL, NULL );
|
||||||
return( LDAP_NO_MEMORY );
|
return( LDAP_NO_MEMORY );
|
||||||
|
|
@ -276,6 +294,7 @@ ldap_init_fd(
|
||||||
ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
|
ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
|
||||||
ld->ld_defconn = conn;
|
ld->ld_defconn = conn;
|
||||||
++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
|
++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
|
||||||
switch( proto ) {
|
switch( proto ) {
|
||||||
case LDAP_PROTO_TCP:
|
case LDAP_PROTO_TCP:
|
||||||
|
|
@ -331,6 +350,7 @@ ldap_init_fd(
|
||||||
return LDAP_SUCCESS;
|
return LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Protected by ld_conn_mutex */
|
||||||
int
|
int
|
||||||
ldap_int_open_connection(
|
ldap_int_open_connection(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -434,8 +454,9 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||||
int rc;
|
int rc;
|
||||||
LDAPConn *c;
|
LDAPConn *c;
|
||||||
LDAPRequest *lr;
|
LDAPRequest *lr;
|
||||||
|
LDAP *ld;
|
||||||
|
|
||||||
rc = ldap_create( ldp );
|
rc = ldap_create( &ld );
|
||||||
if( rc != LDAP_SUCCESS ) {
|
if( rc != LDAP_SUCCESS ) {
|
||||||
*ldp = NULL;
|
*ldp = NULL;
|
||||||
return( rc );
|
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 */
|
/* Make it appear that a search request, msgid 0, was sent */
|
||||||
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
|
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
|
||||||
if( lr == NULL ) {
|
if( lr == NULL ) {
|
||||||
ldap_unbind_ext( *ldp, NULL, NULL );
|
ldap_unbind_ext( ld, NULL, NULL );
|
||||||
*ldp = NULL;
|
*ldp = NULL;
|
||||||
return( LDAP_NO_MEMORY );
|
return( LDAP_NO_MEMORY );
|
||||||
}
|
}
|
||||||
|
|
@ -453,13 +474,15 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||||
lr->lr_status = LDAP_REQST_INPROGRESS;
|
lr->lr_status = LDAP_REQST_INPROGRESS;
|
||||||
lr->lr_res_errno = LDAP_SUCCESS;
|
lr->lr_res_errno = LDAP_SUCCESS;
|
||||||
/* no mutex lock needed, we just created this ld here */
|
/* no mutex lock needed, we just created this ld here */
|
||||||
(*ldp)->ld_requests = lr;
|
ld->ld_requests = lr;
|
||||||
|
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
/* Attach the passed socket as the *LDAP's connection */
|
/* Attach the passed socket as the *LDAP's connection */
|
||||||
c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
|
c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
|
||||||
if( c == NULL ) {
|
if( c == NULL ) {
|
||||||
ldap_unbind_ext( *ldp, NULL, NULL );
|
ldap_unbind_ext( ld, NULL, NULL );
|
||||||
*ldp = NULL;
|
*ldp = NULL;
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return( LDAP_NO_MEMORY );
|
return( LDAP_NO_MEMORY );
|
||||||
}
|
}
|
||||||
ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
|
ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
|
||||||
|
|
@ -469,15 +492,39 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||||
#endif
|
#endif
|
||||||
ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
|
ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
|
||||||
LBER_SBIOD_LEVEL_PROVIDER, NULL );
|
LBER_SBIOD_LEVEL_PROVIDER, NULL );
|
||||||
(*ldp)->ld_defconn = c;
|
ld->ld_defconn = c;
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
|
||||||
/* Add the connection to the *LDAP's select pool */
|
/* Add the connection to the *LDAP's select pool */
|
||||||
ldap_mark_select_read( *ldp, c->lconn_sb );
|
ldap_mark_select_read( ld, c->lconn_sb );
|
||||||
ldap_mark_select_write( *ldp, c->lconn_sb );
|
ldap_mark_select_write( ld, c->lconn_sb );
|
||||||
|
|
||||||
/* Make this connection an LDAP V3 protocol connection */
|
/* Make this connection an LDAP V3 protocol connection */
|
||||||
rc = LDAP_VERSION3;
|
rc = LDAP_VERSION3;
|
||||||
ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
|
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc );
|
||||||
|
*ldp = ld;
|
||||||
|
|
||||||
return( LDAP_SUCCESS );
|
return( LDAP_SUCCESS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LDAP *
|
||||||
|
ldap_dup( LDAP *old )
|
||||||
|
{
|
||||||
|
LDAP *ld;
|
||||||
|
|
||||||
|
if ( old == NULL ) {
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "ldap_dup\n", 0, 0, 0 );
|
||||||
|
|
||||||
|
if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
LDAP_MUTEX_LOCK( &old->ld_ldcmutex );
|
||||||
|
ld->ldc = old->ldc;
|
||||||
|
old->ld_ldcrefcnt++;
|
||||||
|
LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex );
|
||||||
|
return ( ld );
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ ldap_get_option(
|
||||||
void *outvalue)
|
void *outvalue)
|
||||||
{
|
{
|
||||||
struct ldapoptions *lo;
|
struct ldapoptions *lo;
|
||||||
|
int rc = LDAP_OPT_ERROR;
|
||||||
|
|
||||||
/* Get pointer to global option structure */
|
/* Get pointer to global option structure */
|
||||||
lo = LDAP_INT_GLOBAL_OPT();
|
lo = LDAP_INT_GLOBAL_OPT();
|
||||||
|
|
@ -122,19 +123,21 @@ ldap_get_option(
|
||||||
return LDAP_OPT_ERROR;
|
return LDAP_OPT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||||
|
|
||||||
switch(option) {
|
switch(option) {
|
||||||
case LDAP_OPT_API_INFO: {
|
case LDAP_OPT_API_INFO: {
|
||||||
struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
|
struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
|
||||||
|
|
||||||
if(info == NULL) {
|
if(info == NULL) {
|
||||||
/* outvalue must point to an apiinfo structure */
|
/* outvalue must point to an apiinfo structure */
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
|
if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
|
||||||
/* api info version mismatch */
|
/* api info version mismatch */
|
||||||
info->ldapai_info_version = LDAP_API_INFO_VERSION;
|
info->ldapai_info_version = LDAP_API_INFO_VERSION;
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
info->ldapai_api_version = LDAP_API_VERSION;
|
info->ldapai_api_version = LDAP_API_VERSION;
|
||||||
|
|
@ -158,7 +161,8 @@ ldap_get_option(
|
||||||
info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
|
info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
|
||||||
info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
|
info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
|
||||||
|
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case LDAP_OPT_DESC:
|
case LDAP_OPT_DESC:
|
||||||
|
|
@ -168,74 +172,86 @@ ldap_get_option(
|
||||||
}
|
}
|
||||||
|
|
||||||
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
|
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_SOCKBUF:
|
case LDAP_OPT_SOCKBUF:
|
||||||
if( ld == NULL ) break;
|
if( ld == NULL ) break;
|
||||||
*(Sockbuf **)outvalue = ld->ld_sb;
|
*(Sockbuf **)outvalue = ld->ld_sb;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_TIMEOUT:
|
case LDAP_OPT_TIMEOUT:
|
||||||
/* the caller has to free outvalue ! */
|
/* the caller has to free outvalue ! */
|
||||||
if ( lo->ldo_tm_api.tv_sec < 0 ) {
|
if ( lo->ldo_tm_api.tv_sec < 0 ) {
|
||||||
*(void **)outvalue = NULL;
|
*(void **)outvalue = NULL;
|
||||||
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
|
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_NETWORK_TIMEOUT:
|
case LDAP_OPT_NETWORK_TIMEOUT:
|
||||||
/* the caller has to free outvalue ! */
|
/* the caller has to free outvalue ! */
|
||||||
if ( lo->ldo_tm_net.tv_sec < 0 ) {
|
if ( lo->ldo_tm_net.tv_sec < 0 ) {
|
||||||
*(void **)outvalue = NULL;
|
*(void **)outvalue = NULL;
|
||||||
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
|
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_DEREF:
|
case LDAP_OPT_DEREF:
|
||||||
* (int *) outvalue = lo->ldo_deref;
|
* (int *) outvalue = lo->ldo_deref;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_SIZELIMIT:
|
case LDAP_OPT_SIZELIMIT:
|
||||||
* (int *) outvalue = lo->ldo_sizelimit;
|
* (int *) outvalue = lo->ldo_sizelimit;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_TIMELIMIT:
|
case LDAP_OPT_TIMELIMIT:
|
||||||
* (int *) outvalue = lo->ldo_timelimit;
|
* (int *) outvalue = lo->ldo_timelimit;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_REFERRALS:
|
case LDAP_OPT_REFERRALS:
|
||||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
|
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_RESTART:
|
case LDAP_OPT_RESTART:
|
||||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
|
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_PROTOCOL_VERSION:
|
case LDAP_OPT_PROTOCOL_VERSION:
|
||||||
* (int *) outvalue = lo->ldo_version;
|
* (int *) outvalue = lo->ldo_version;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_SERVER_CONTROLS:
|
case LDAP_OPT_SERVER_CONTROLS:
|
||||||
* (LDAPControl ***) outvalue =
|
* (LDAPControl ***) outvalue =
|
||||||
ldap_controls_dup( lo->ldo_sctrls );
|
ldap_controls_dup( lo->ldo_sctrls );
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CLIENT_CONTROLS:
|
case LDAP_OPT_CLIENT_CONTROLS:
|
||||||
* (LDAPControl ***) outvalue =
|
* (LDAPControl ***) outvalue =
|
||||||
ldap_controls_dup( lo->ldo_cctrls );
|
ldap_controls_dup( lo->ldo_cctrls );
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_HOST_NAME:
|
case LDAP_OPT_HOST_NAME:
|
||||||
* (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
|
* (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_URI:
|
case LDAP_OPT_URI:
|
||||||
* (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
|
* (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_DEFBASE:
|
case LDAP_OPT_DEFBASE:
|
||||||
if( lo->ldo_defbase == NULL ) {
|
if( lo->ldo_defbase == NULL ) {
|
||||||
|
|
@ -243,12 +259,13 @@ ldap_get_option(
|
||||||
} else {
|
} else {
|
||||||
* (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
|
* (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
|
||||||
}
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CONNECT_ASYNC:
|
case LDAP_OPT_CONNECT_ASYNC:
|
||||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CONNECT_CB:
|
case LDAP_OPT_CONNECT_CB:
|
||||||
{
|
{
|
||||||
|
|
@ -263,7 +280,8 @@ ldap_get_option(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_RESULT_CODE:
|
case LDAP_OPT_RESULT_CODE:
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
|
|
@ -271,7 +289,8 @@ ldap_get_option(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
* (int *) outvalue = ld->ld_errno;
|
* (int *) outvalue = ld->ld_errno;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_DIAGNOSTIC_MESSAGE:
|
case LDAP_OPT_DIAGNOSTIC_MESSAGE:
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
|
|
@ -284,8 +303,8 @@ ldap_get_option(
|
||||||
} else {
|
} else {
|
||||||
* (char **) outvalue = LDAP_STRDUP(ld->ld_error);
|
* (char **) outvalue = LDAP_STRDUP(ld->ld_error);
|
||||||
}
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_MATCHED_DN:
|
case LDAP_OPT_MATCHED_DN:
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
|
|
@ -298,8 +317,8 @@ ldap_get_option(
|
||||||
} else {
|
} else {
|
||||||
* (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
|
* (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
|
||||||
}
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_REFERRAL_URLS:
|
case LDAP_OPT_REFERRAL_URLS:
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
|
|
@ -312,28 +331,31 @@ ldap_get_option(
|
||||||
} else {
|
} else {
|
||||||
* (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
|
* (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
|
||||||
}
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
return LDAP_OPT_SUCCESS;
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_API_FEATURE_INFO: {
|
case LDAP_OPT_API_FEATURE_INFO: {
|
||||||
LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
|
LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(info == NULL) return LDAP_OPT_ERROR;
|
if(info == NULL)
|
||||||
|
break; /* LDAP_OPT_ERROR */
|
||||||
|
|
||||||
if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
|
if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
|
||||||
/* api info version mismatch */
|
/* api info version mismatch */
|
||||||
info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
|
info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
|
if(info->ldapaif_name == NULL)
|
||||||
|
break; /* LDAP_OPT_ERROR */
|
||||||
|
|
||||||
for(i=0; features[i].ldapaif_name != NULL; i++) {
|
for(i=0; features[i].ldapaif_name != NULL; i++) {
|
||||||
if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
|
if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
|
||||||
info->ldapaif_version =
|
info->ldapaif_version =
|
||||||
features[i].ldapaif_version;
|
features[i].ldapaif_version;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,41 +363,54 @@ ldap_get_option(
|
||||||
|
|
||||||
case LDAP_OPT_DEBUG_LEVEL:
|
case LDAP_OPT_DEBUG_LEVEL:
|
||||||
* (int *) outvalue = lo->ldo_debug;
|
* (int *) outvalue = lo->ldo_debug;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LDAP_OPT_SESSION_REFCNT:
|
||||||
|
* (int *) outvalue = ld->ld_ldcrefcnt;
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
||||||
* (int *) outvalue = lo->ldo_keepalive_idle;
|
* (int *) outvalue = lo->ldo_keepalive_idle;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_X_KEEPALIVE_PROBES:
|
case LDAP_OPT_X_KEEPALIVE_PROBES:
|
||||||
* (int *) outvalue = lo->ldo_keepalive_probes;
|
* (int *) outvalue = lo->ldo_keepalive_probes;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
|
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
|
||||||
* (int *) outvalue = lo->ldo_keepalive_interval;
|
* (int *) outvalue = lo->ldo_keepalive_interval;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
|
if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
|
if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GSSAPI
|
#ifdef HAVE_GSSAPI
|
||||||
if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
|
if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* bad param */
|
/* bad param */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LDAP_OPT_ERROR;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( rc );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -386,6 +421,7 @@ ldap_set_option(
|
||||||
{
|
{
|
||||||
struct ldapoptions *lo;
|
struct ldapoptions *lo;
|
||||||
int *dbglvl = NULL;
|
int *dbglvl = NULL;
|
||||||
|
int rc = LDAP_OPT_ERROR;
|
||||||
|
|
||||||
/* Get pointer to global option structure */
|
/* Get pointer to global option structure */
|
||||||
lo = LDAP_INT_GLOBAL_OPT();
|
lo = LDAP_INT_GLOBAL_OPT();
|
||||||
|
|
@ -416,14 +452,19 @@ ldap_set_option(
|
||||||
lo = &ld->ld_options;
|
lo = &ld->ld_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(option) {
|
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||||
|
|
||||||
|
switch ( option ) {
|
||||||
|
|
||||||
|
/* options with boolean values */
|
||||||
case LDAP_OPT_REFERRALS:
|
case LDAP_OPT_REFERRALS:
|
||||||
if(invalue == LDAP_OPT_OFF) {
|
if(invalue == LDAP_OPT_OFF) {
|
||||||
LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
|
LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
|
||||||
} else {
|
} else {
|
||||||
LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
|
LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_RESTART:
|
case LDAP_OPT_RESTART:
|
||||||
if(invalue == LDAP_OPT_OFF) {
|
if(invalue == LDAP_OPT_OFF) {
|
||||||
|
|
@ -431,7 +472,8 @@ ldap_set_option(
|
||||||
} else {
|
} else {
|
||||||
LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
|
LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CONNECT_ASYNC:
|
case LDAP_OPT_CONNECT_ASYNC:
|
||||||
if(invalue == LDAP_OPT_OFF) {
|
if(invalue == LDAP_OPT_OFF) {
|
||||||
|
|
@ -439,11 +481,10 @@ ldap_set_option(
|
||||||
} else {
|
} else {
|
||||||
LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
}
|
break;
|
||||||
|
|
||||||
/* options which can withstand invalue == NULL */
|
/* options which can withstand invalue == NULL */
|
||||||
switch ( option ) {
|
|
||||||
case LDAP_OPT_SERVER_CONTROLS: {
|
case LDAP_OPT_SERVER_CONTROLS: {
|
||||||
LDAPControl *const *controls =
|
LDAPControl *const *controls =
|
||||||
(LDAPControl *const *) invalue;
|
(LDAPControl *const *) invalue;
|
||||||
|
|
@ -453,16 +494,19 @@ ldap_set_option(
|
||||||
|
|
||||||
if( controls == NULL || *controls == NULL ) {
|
if( controls == NULL || *controls == NULL ) {
|
||||||
lo->ldo_sctrls = NULL;
|
lo->ldo_sctrls = NULL;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lo->ldo_sctrls = ldap_controls_dup( controls );
|
lo->ldo_sctrls = ldap_controls_dup( controls );
|
||||||
|
|
||||||
if(lo->ldo_sctrls == NULL) {
|
if(lo->ldo_sctrls == NULL) {
|
||||||
/* memory allocation error ? */
|
/* memory allocation error ? */
|
||||||
break;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CLIENT_CONTROLS: {
|
case LDAP_OPT_CLIENT_CONTROLS: {
|
||||||
LDAPControl *const *controls =
|
LDAPControl *const *controls =
|
||||||
|
|
@ -473,22 +517,25 @@ ldap_set_option(
|
||||||
|
|
||||||
if( controls == NULL || *controls == NULL ) {
|
if( controls == NULL || *controls == NULL ) {
|
||||||
lo->ldo_cctrls = NULL;
|
lo->ldo_cctrls = NULL;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lo->ldo_cctrls = ldap_controls_dup( controls );
|
lo->ldo_cctrls = ldap_controls_dup( controls );
|
||||||
|
|
||||||
if(lo->ldo_cctrls == NULL) {
|
if(lo->ldo_cctrls == NULL) {
|
||||||
/* memory allocation error ? */
|
/* memory allocation error ? */
|
||||||
break;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case LDAP_OPT_HOST_NAME: {
|
case LDAP_OPT_HOST_NAME: {
|
||||||
const char *host = (const char *) invalue;
|
const char *host = (const char *) invalue;
|
||||||
LDAPURLDesc *ludlist = NULL;
|
LDAPURLDesc *ludlist = NULL;
|
||||||
int rc = LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
|
||||||
if(host != NULL) {
|
if(host != NULL) {
|
||||||
rc = ldap_url_parsehosts( &ludlist, host,
|
rc = ldap_url_parsehosts( &ludlist, host,
|
||||||
|
|
@ -519,13 +566,13 @@ ldap_set_option(
|
||||||
ldap_free_urllist(lo->ldo_defludp);
|
ldap_free_urllist(lo->ldo_defludp);
|
||||||
lo->ldo_defludp = ludlist;
|
lo->ldo_defludp = ludlist;
|
||||||
}
|
}
|
||||||
return rc;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDAP_OPT_URI: {
|
case LDAP_OPT_URI: {
|
||||||
const char *urls = (const char *) invalue;
|
const char *urls = (const char *) invalue;
|
||||||
LDAPURLDesc *ludlist = NULL;
|
LDAPURLDesc *ludlist = NULL;
|
||||||
int rc = LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
|
||||||
if(urls != NULL) {
|
if(urls != NULL) {
|
||||||
rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
|
rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
|
||||||
|
|
@ -578,7 +625,7 @@ ldap_set_option(
|
||||||
ldap_free_urllist(lo->ldo_defludp);
|
ldap_free_urllist(lo->ldo_defludp);
|
||||||
lo->ldo_defludp = ludlist;
|
lo->ldo_defludp = ludlist;
|
||||||
}
|
}
|
||||||
return rc;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDAP_OPT_DEFBASE: {
|
case LDAP_OPT_DEFBASE: {
|
||||||
|
|
@ -587,24 +634,32 @@ ldap_set_option(
|
||||||
|
|
||||||
if ( newbase != NULL ) {
|
if ( newbase != NULL ) {
|
||||||
defbase = LDAP_STRDUP( newbase );
|
defbase = LDAP_STRDUP( newbase );
|
||||||
if ( defbase == NULL ) return LDAP_NO_MEMORY;
|
if ( defbase == NULL ) {
|
||||||
|
rc = LDAP_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
} else if ( ld != NULL ) {
|
} else if ( ld != NULL ) {
|
||||||
defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
|
defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
|
||||||
if ( defbase == NULL ) return LDAP_NO_MEMORY;
|
if ( defbase == NULL ) {
|
||||||
|
rc = LDAP_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lo->ldo_defbase != NULL )
|
if ( lo->ldo_defbase != NULL )
|
||||||
LDAP_FREE( lo->ldo_defbase );
|
LDAP_FREE( lo->ldo_defbase );
|
||||||
lo->ldo_defbase = defbase;
|
lo->ldo_defbase = defbase;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
|
case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
|
||||||
const char *err = (const char *) invalue;
|
const char *err = (const char *) invalue;
|
||||||
|
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
/* need a struct ldap */
|
/* need a struct ldap */
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ld->ld_error ) {
|
if( ld->ld_error ) {
|
||||||
|
|
@ -615,14 +670,16 @@ ldap_set_option(
|
||||||
if ( err ) {
|
if ( err ) {
|
||||||
ld->ld_error = LDAP_STRDUP(err);
|
ld->ld_error = LDAP_STRDUP(err);
|
||||||
}
|
}
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_MATCHED_DN: {
|
case LDAP_OPT_MATCHED_DN: {
|
||||||
const char *matched = (const char *) invalue;
|
const char *matched = (const char *) invalue;
|
||||||
|
|
||||||
if (ld == NULL) {
|
if (ld == NULL) {
|
||||||
/* need a struct ldap */
|
/* need a struct ldap */
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ld->ld_matched ) {
|
if( ld->ld_matched ) {
|
||||||
|
|
@ -633,14 +690,16 @@ ldap_set_option(
|
||||||
if ( matched ) {
|
if ( matched ) {
|
||||||
ld->ld_matched = LDAP_STRDUP( matched );
|
ld->ld_matched = LDAP_STRDUP( matched );
|
||||||
}
|
}
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_REFERRAL_URLS: {
|
case LDAP_OPT_REFERRAL_URLS: {
|
||||||
char *const *referrals = (char *const *) invalue;
|
char *const *referrals = (char *const *) invalue;
|
||||||
|
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
/* need a struct ldap */
|
/* need a struct ldap */
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ld->ld_referrals ) {
|
if( ld->ld_referrals ) {
|
||||||
|
|
@ -650,38 +709,52 @@ ldap_set_option(
|
||||||
if ( referrals ) {
|
if ( referrals ) {
|
||||||
ld->ld_referrals = ldap_value_dup(referrals);
|
ld->ld_referrals = ldap_value_dup(referrals);
|
||||||
}
|
}
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Only accessed from inside this function by ldap_set_rebind_proc() */
|
/* Only accessed from inside this function by ldap_set_rebind_proc() */
|
||||||
case LDAP_OPT_REBIND_PROC: {
|
case LDAP_OPT_REBIND_PROC: {
|
||||||
lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
|
lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_REBIND_PARAMS: {
|
case LDAP_OPT_REBIND_PARAMS: {
|
||||||
lo->ldo_rebind_params = (void *)invalue;
|
lo->ldo_rebind_params = (void *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Only accessed from inside this function by ldap_set_nextref_proc() */
|
/* Only accessed from inside this function by ldap_set_nextref_proc() */
|
||||||
case LDAP_OPT_NEXTREF_PROC: {
|
case LDAP_OPT_NEXTREF_PROC: {
|
||||||
lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
|
lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_NEXTREF_PARAMS: {
|
case LDAP_OPT_NEXTREF_PARAMS: {
|
||||||
lo->ldo_nextref_params = (void *)invalue;
|
lo->ldo_nextref_params = (void *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Only accessed from inside this function by ldap_set_urllist_proc() */
|
/* Only accessed from inside this function by ldap_set_urllist_proc() */
|
||||||
case LDAP_OPT_URLLIST_PROC: {
|
case LDAP_OPT_URLLIST_PROC: {
|
||||||
lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
|
lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_URLLIST_PARAMS: {
|
case LDAP_OPT_URLLIST_PARAMS: {
|
||||||
lo->ldo_urllist_params = (void *)invalue;
|
lo->ldo_urllist_params = (void *)invalue;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
/* read-only options */
|
/* read-only options */
|
||||||
case LDAP_OPT_API_INFO:
|
case LDAP_OPT_API_INFO:
|
||||||
case LDAP_OPT_DESC:
|
case LDAP_OPT_DESC:
|
||||||
case LDAP_OPT_SOCKBUF:
|
case LDAP_OPT_SOCKBUF:
|
||||||
case LDAP_OPT_API_FEATURE_INFO:
|
case LDAP_OPT_API_FEATURE_INFO:
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
|
|
||||||
/* options which cannot withstand invalue == NULL */
|
/* options which cannot withstand invalue == NULL */
|
||||||
case LDAP_OPT_DEREF:
|
case LDAP_OPT_DEREF:
|
||||||
|
|
@ -698,25 +771,29 @@ ldap_set_option(
|
||||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
||||||
if(invalue == NULL) {
|
if(invalue == NULL) {
|
||||||
/* no place to set from */
|
/* no place to set from */
|
||||||
return LDAP_OPT_ERROR;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( LDAP_OPT_ERROR );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
|
if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
|
||||||
return LDAP_OPT_SUCCESS;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( LDAP_OPT_SUCCESS );
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
|
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
|
||||||
return LDAP_OPT_SUCCESS;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( LDAP_OPT_SUCCESS );
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GSSAPI
|
#ifdef HAVE_GSSAPI
|
||||||
if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 )
|
if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 )
|
||||||
return LDAP_OPT_SUCCESS;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( LDAP_OPT_SUCCESS );
|
||||||
#endif
|
#endif
|
||||||
/* bad param */
|
/* bad param */
|
||||||
return LDAP_OPT_ERROR;
|
break; /* LDAP_OPT_ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* options which cannot withstand invalue == NULL */
|
/* options which cannot withstand invalue == NULL */
|
||||||
|
|
@ -725,31 +802,38 @@ ldap_set_option(
|
||||||
case LDAP_OPT_DEREF:
|
case LDAP_OPT_DEREF:
|
||||||
/* FIXME: check value for protocol compliance? */
|
/* FIXME: check value for protocol compliance? */
|
||||||
lo->ldo_deref = * (const int *) invalue;
|
lo->ldo_deref = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_SIZELIMIT:
|
case LDAP_OPT_SIZELIMIT:
|
||||||
/* FIXME: check value for protocol compliance? */
|
/* FIXME: check value for protocol compliance? */
|
||||||
lo->ldo_sizelimit = * (const int *) invalue;
|
lo->ldo_sizelimit = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_TIMELIMIT:
|
case LDAP_OPT_TIMELIMIT:
|
||||||
/* FIXME: check value for protocol compliance? */
|
/* FIXME: check value for protocol compliance? */
|
||||||
lo->ldo_timelimit = * (const int *) invalue;
|
lo->ldo_timelimit = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_TIMEOUT: {
|
case LDAP_OPT_TIMEOUT: {
|
||||||
const struct timeval *tv =
|
const struct timeval *tv =
|
||||||
(const struct timeval *) invalue;
|
(const struct timeval *) invalue;
|
||||||
|
|
||||||
lo->ldo_tm_api = *tv;
|
lo->ldo_tm_api = *tv;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_NETWORK_TIMEOUT: {
|
case LDAP_OPT_NETWORK_TIMEOUT: {
|
||||||
const struct timeval *tv =
|
const struct timeval *tv =
|
||||||
(const struct timeval *) invalue;
|
(const struct timeval *) invalue;
|
||||||
|
|
||||||
lo->ldo_tm_net = *tv;
|
lo->ldo_tm_net = *tv;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_PROTOCOL_VERSION: {
|
case LDAP_OPT_PROTOCOL_VERSION: {
|
||||||
int vers = * (const int *) invalue;
|
int vers = * (const int *) invalue;
|
||||||
|
|
@ -758,7 +842,9 @@ ldap_set_option(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lo->ldo_version = vers;
|
lo->ldo_version = vers;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_RESULT_CODE: {
|
case LDAP_OPT_RESULT_CODE: {
|
||||||
int err = * (const int *) invalue;
|
int err = * (const int *) invalue;
|
||||||
|
|
@ -769,11 +855,14 @@ ldap_set_option(
|
||||||
}
|
}
|
||||||
|
|
||||||
ld->ld_errno = err;
|
ld->ld_errno = err;
|
||||||
} return LDAP_OPT_SUCCESS;
|
}
|
||||||
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_DEBUG_LEVEL:
|
case LDAP_OPT_DEBUG_LEVEL:
|
||||||
lo->ldo_debug = * (const int *) invalue;
|
lo->ldo_debug = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_OPT_CONNECT_CB:
|
case LDAP_OPT_CONNECT_CB:
|
||||||
{
|
{
|
||||||
|
|
@ -784,19 +873,24 @@ ldap_set_option(
|
||||||
ll->ll_next = lo->ldo_conn_cbs;
|
ll->ll_next = lo->ldo_conn_cbs;
|
||||||
lo->ldo_conn_cbs = ll;
|
lo->ldo_conn_cbs = ll;
|
||||||
}
|
}
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
||||||
lo->ldo_keepalive_idle = * (const int *) invalue;
|
lo->ldo_keepalive_idle = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_X_KEEPALIVE_PROBES :
|
case LDAP_OPT_X_KEEPALIVE_PROBES :
|
||||||
lo->ldo_keepalive_probes = * (const int *) invalue;
|
lo->ldo_keepalive_probes = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
||||||
lo->ldo_keepalive_interval = * (const int *) invalue;
|
lo->ldo_keepalive_interval = * (const int *) invalue;
|
||||||
return LDAP_OPT_SUCCESS;
|
rc = LDAP_OPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return LDAP_OPT_ERROR;
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
|
return ( rc );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,29 @@
|
||||||
#include "ldap-int.h"
|
#include "ldap-int.h"
|
||||||
#include "lber.h"
|
#include "lber.h"
|
||||||
|
|
||||||
|
/* used by ldap_send_server_request and ldap_new_connection */
|
||||||
|
#ifdef LDAP_R_COMPILE
|
||||||
|
#define LDAP_CONN_LOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); }
|
||||||
|
#define LDAP_CONN_UNLOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); }
|
||||||
|
#define LDAP_REQ_LOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); }
|
||||||
|
#define LDAP_REQ_UNLOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); }
|
||||||
|
#define LDAP_RES_LOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); }
|
||||||
|
#define LDAP_RES_UNLOCK_IF(nolock) \
|
||||||
|
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); }
|
||||||
|
#else
|
||||||
|
#define LDAP_CONN_LOCK_IF(nolock)
|
||||||
|
#define LDAP_CONN_UNLOCK_IF(nolock)
|
||||||
|
#define LDAP_REQ_LOCK_IF(nolock)
|
||||||
|
#define LDAP_REQ_UNLOCK_IF(nolock)
|
||||||
|
#define LDAP_RES_LOCK_IF(nolock)
|
||||||
|
#define LDAP_RES_UNLOCK_IF(nolock)
|
||||||
|
#endif
|
||||||
|
|
||||||
static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
|
static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
|
||||||
static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
|
static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
|
||||||
static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
|
static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
|
||||||
|
|
@ -82,10 +105,12 @@ ldap_alloc_ber_with_options( LDAP *ld )
|
||||||
void
|
void
|
||||||
ldap_set_ber_options( LDAP *ld, BerElement *ber )
|
ldap_set_ber_options( LDAP *ld, BerElement *ber )
|
||||||
{
|
{
|
||||||
|
/* ld_lberoptions is constant, hence no lock */
|
||||||
ber->ber_options = ld->ld_lberoptions;
|
ber->ber_options = ld->ld_lberoptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* sets needed mutexes - no mutexes set to this point */
|
||||||
ber_int_t
|
ber_int_t
|
||||||
ldap_send_initial_request(
|
ldap_send_initial_request(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -98,15 +123,15 @@ ldap_send_initial_request(
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
|
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
|
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
|
||||||
/* not connected yet */
|
/* not connected yet */
|
||||||
rc = ldap_open_defconn( ld );
|
rc = ldap_open_defconn( ld );
|
||||||
|
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
if( rc < 0 ) {
|
if( rc < 0 ) {
|
||||||
ber_free( ber, 1 );
|
ber_free( ber, 1 );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
} else if ( rc == 0 ) {
|
} else if ( rc == 0 ) {
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
|
@ -117,27 +142,33 @@ ldap_send_initial_request(
|
||||||
#ifdef LDAP_CONNECTIONLESS
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
if (LDAP_IS_UDP(ld)) {
|
if (LDAP_IS_UDP(ld)) {
|
||||||
if (msgtype == LDAP_REQ_BIND) {
|
if (msgtype == LDAP_REQ_BIND) {
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||||
if (ld->ld_options.ldo_cldapdn)
|
if (ld->ld_options.ldo_cldapdn)
|
||||||
ldap_memfree(ld->ld_options.ldo_cldapdn);
|
ldap_memfree(ld->ld_options.ldo_cldapdn);
|
||||||
ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
|
ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
|
||||||
ber_free( ber, 1 );
|
ber_free( ber, 1 );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
|
if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
|
||||||
{
|
{
|
||||||
ber_free( ber, 1 );
|
ber_free( ber, 1 );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return LDAP_PARAM_ERROR;
|
return LDAP_PARAM_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||||
rc = ldap_send_server_request( ld, ber, msgid, NULL,
|
rc = ldap_send_server_request( ld, ber, msgid, NULL,
|
||||||
NULL, NULL, NULL );
|
NULL, NULL, NULL, 0, 0 );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return(rc);
|
return(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by conn_mutex */
|
||||||
int
|
int
|
||||||
ldap_int_flush_request(
|
ldap_int_flush_request(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -145,6 +176,7 @@ ldap_int_flush_request(
|
||||||
{
|
{
|
||||||
LDAPConn *lc = lr->lr_conn;
|
LDAPConn *lc = lr->lr_conn;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
|
if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
|
||||||
if ( sock_errno() == EAGAIN ) {
|
if ( sock_errno() == EAGAIN ) {
|
||||||
/* need to continue write later */
|
/* need to continue write later */
|
||||||
|
|
@ -171,6 +203,13 @@ ldap_int_flush_request(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protected by req_mutex
|
||||||
|
* if m_noconn then protect using conn_lock
|
||||||
|
* else already protected with conn_lock
|
||||||
|
* if m_res then also protected by res_mutex
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_send_server_request(
|
ldap_send_server_request(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -179,16 +218,20 @@ ldap_send_server_request(
|
||||||
LDAPRequest *parentreq,
|
LDAPRequest *parentreq,
|
||||||
LDAPURLDesc **srvlist,
|
LDAPURLDesc **srvlist,
|
||||||
LDAPConn *lc,
|
LDAPConn *lc,
|
||||||
LDAPreqinfo *bind )
|
LDAPreqinfo *bind,
|
||||||
|
int m_noconn,
|
||||||
|
int m_res )
|
||||||
{
|
{
|
||||||
LDAPRequest *lr;
|
LDAPRequest *lr;
|
||||||
int incparent, rc;
|
int incparent, rc;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
|
Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
|
||||||
|
|
||||||
incparent = 0;
|
incparent = 0;
|
||||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||||
|
|
||||||
|
LDAP_CONN_LOCK_IF(m_noconn);
|
||||||
if ( lc == NULL ) {
|
if ( lc == NULL ) {
|
||||||
if ( srvlist == NULL ) {
|
if ( srvlist == NULL ) {
|
||||||
lc = ld->ld_defconn;
|
lc = ld->ld_defconn;
|
||||||
|
|
@ -200,7 +243,8 @@ ldap_send_server_request(
|
||||||
incparent = 1;
|
incparent = 1;
|
||||||
++parentreq->lr_outrefcnt;
|
++parentreq->lr_outrefcnt;
|
||||||
}
|
}
|
||||||
lc = ldap_new_connection( ld, srvlist, 0, 1, bind );
|
lc = ldap_new_connection( ld, srvlist, 0,
|
||||||
|
1, bind, 1, m_res );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,11 +267,13 @@ ldap_send_server_request(
|
||||||
/* async only occurs if a network timeout is set */
|
/* async only occurs if a network timeout is set */
|
||||||
|
|
||||||
/* honor network timeout */
|
/* honor network timeout */
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||||
if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
|
if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
|
||||||
{
|
{
|
||||||
/* caller will have to call again */
|
/* caller will have to call again */
|
||||||
ld->ld_errno = LDAP_X_CONNECTING;
|
ld->ld_errno = LDAP_X_CONNECTING;
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||||
/* fallthru */
|
/* fallthru */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -246,6 +292,7 @@ ldap_send_server_request(
|
||||||
/* Forget about the bind */
|
/* Forget about the bind */
|
||||||
--parentreq->lr_outrefcnt;
|
--parentreq->lr_outrefcnt;
|
||||||
}
|
}
|
||||||
|
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,10 +302,13 @@ ldap_send_server_request(
|
||||||
if ( LDAP_IS_UDP( ld )) {
|
if ( LDAP_IS_UDP( ld )) {
|
||||||
BerElement tmpber = *ber;
|
BerElement tmpber = *ber;
|
||||||
ber_rewind( &tmpber );
|
ber_rewind( &tmpber );
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||||
rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
|
rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
|
||||||
sizeof( struct sockaddr ), 0 );
|
sizeof( struct sockaddr ), 0 );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||||
if ( rc == -1 ) {
|
if ( rc == -1 ) {
|
||||||
ld->ld_errno = LDAP_ENCODING_ERROR;
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +326,10 @@ ldap_send_server_request(
|
||||||
{
|
{
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
if ( rc ) return rc;
|
if ( rc ) {
|
||||||
|
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
|
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
|
||||||
if ( lr == NULL ) {
|
if ( lr == NULL ) {
|
||||||
|
|
@ -287,6 +340,7 @@ ldap_send_server_request(
|
||||||
/* Forget about the bind */
|
/* Forget about the bind */
|
||||||
--parentreq->lr_outrefcnt;
|
--parentreq->lr_outrefcnt;
|
||||||
}
|
}
|
||||||
|
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
lr->lr_msgid = msgid;
|
lr->lr_msgid = msgid;
|
||||||
|
|
@ -345,6 +399,7 @@ ldap_send_server_request(
|
||||||
msgid = -1;
|
msgid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||||
return( msgid );
|
return( msgid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -375,18 +430,17 @@ find_tls_ext( LDAPURLDesc *srv )
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* caller must hold ld_req_mutex or be exclusive user of ld
|
* always protected by conn_mutex
|
||||||
* if ( connect != 0 ) or ( bind != NULL ) caller must also hold
|
* optionally protected by req_mutex and res_mutex
|
||||||
* ld_req_mutex and ld_res_mutex
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LDAPConn *
|
LDAPConn *
|
||||||
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
int connect, LDAPreqinfo *bind )
|
int connect, LDAPreqinfo *bind, int m_req, int m_res )
|
||||||
{
|
{
|
||||||
LDAPConn *lc;
|
LDAPConn *lc;
|
||||||
int async = 0;
|
int async = 0;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
|
Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
|
||||||
use_ldsb, connect, (bind != NULL) );
|
use_ldsb, connect, (bind != NULL) );
|
||||||
/*
|
/*
|
||||||
|
|
@ -445,15 +499,10 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
}
|
}
|
||||||
|
|
||||||
lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
|
lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
|
||||||
lc->lconn_next = ld->ld_conns;
|
lc->lconn_next = ld->ld_conns;
|
||||||
ld->ld_conns = lc;
|
ld->ld_conns = lc;
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
|
|
||||||
if ( connect ) {
|
if ( connect ) {
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
|
||||||
|
|
||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
if ( lc->lconn_server->lud_exts ) {
|
if ( lc->lconn_server->lud_exts ) {
|
||||||
int rc, ext = find_tls_ext( lc->lconn_server );
|
int rc, ext = find_tls_ext( lc->lconn_server );
|
||||||
|
|
@ -464,11 +513,13 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
++lc->lconn_refcnt; /* avoid premature free */
|
++lc->lconn_refcnt; /* avoid premature free */
|
||||||
ld->ld_defconn = lc;
|
ld->ld_defconn = lc;
|
||||||
|
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_REQ_UNLOCK_IF(m_req);
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_RES_UNLOCK_IF(m_res);
|
||||||
rc = ldap_start_tls_s( ld, NULL, NULL );
|
rc = ldap_start_tls_s( ld, NULL, NULL );
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
LDAP_RES_LOCK_IF(m_res);
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_REQ_LOCK_IF(m_req);
|
||||||
ld->ld_defconn = savedefconn;
|
ld->ld_defconn = savedefconn;
|
||||||
--lc->lconn_refcnt;
|
--lc->lconn_refcnt;
|
||||||
|
|
||||||
|
|
@ -485,9 +536,6 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
int err = 0;
|
int err = 0;
|
||||||
LDAPConn *savedefconn;
|
LDAPConn *savedefconn;
|
||||||
|
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
|
||||||
|
|
||||||
/* Set flag to prevent additional referrals
|
/* Set flag to prevent additional referrals
|
||||||
* from being processed on this
|
* from being processed on this
|
||||||
* connection until the bind has completed
|
* connection until the bind has completed
|
||||||
|
|
@ -507,13 +555,15 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
ld->ld_defconn = lc;
|
ld->ld_defconn = lc;
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
|
Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_REQ_UNLOCK_IF(m_req);
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_RES_UNLOCK_IF(m_res);
|
||||||
err = (*ld->ld_rebind_proc)( ld,
|
err = (*ld->ld_rebind_proc)( ld,
|
||||||
bind->ri_url, bind->ri_request, bind->ri_msgid,
|
bind->ri_url, bind->ri_request, bind->ri_msgid,
|
||||||
ld->ld_rebind_params );
|
ld->ld_rebind_params );
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
LDAP_RES_LOCK_IF(m_res);
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_REQ_LOCK_IF(m_req);
|
||||||
|
|
||||||
ld->ld_defconn = savedefconn;
|
ld->ld_defconn = savedefconn;
|
||||||
--lc->lconn_refcnt;
|
--lc->lconn_refcnt;
|
||||||
|
|
@ -538,8 +588,9 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
"anonymous rebind via ldap_sasl_bind(\"\")\n",
|
"anonymous rebind via ldap_sasl_bind(\"\")\n",
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
|
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_REQ_UNLOCK_IF(m_req);
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_RES_UNLOCK_IF(m_res);
|
||||||
rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
|
rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
|
||||||
NULL, NULL, &msgid );
|
NULL, NULL, &msgid );
|
||||||
if ( rc != LDAP_SUCCESS ) {
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
|
@ -583,8 +634,9 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
LDAP_RES_LOCK_IF(m_res);
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
|
LDAP_REQ_LOCK_IF(m_req);
|
||||||
ld->ld_defconn = savedefconn;
|
ld->ld_defconn = savedefconn;
|
||||||
--lc->lconn_refcnt;
|
--lc->lconn_refcnt;
|
||||||
|
|
||||||
|
|
@ -596,11 +648,11 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||||
if ( lc != NULL )
|
if ( lc != NULL )
|
||||||
lc->lconn_rebind_inprogress = 0;
|
lc->lconn_rebind_inprogress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return( lc );
|
return( lc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by ld_conn_mutex */
|
||||||
static LDAPConn *
|
static LDAPConn *
|
||||||
find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||||
/*
|
/*
|
||||||
|
|
@ -613,7 +665,7 @@ find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||||
int lcu_port, lsu_port;
|
int lcu_port, lsu_port;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
|
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
|
||||||
lcu = lc->lconn_server;
|
lcu = lc->lconn_server;
|
||||||
lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
|
lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
|
||||||
|
|
@ -637,35 +689,34 @@ find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||||
if ( found )
|
if ( found )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: the caller holds ld_req_mutex
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/* protected by ld_conn_mutex */
|
||||||
static void
|
static void
|
||||||
use_connection( LDAP *ld, LDAPConn *lc )
|
use_connection( LDAP *ld, LDAPConn *lc )
|
||||||
{
|
{
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
++lc->lconn_refcnt;
|
++lc->lconn_refcnt;
|
||||||
lc->lconn_lastused = time( NULL );
|
lc->lconn_lastused = time( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by ld_conn_mutex */
|
||||||
void
|
void
|
||||||
ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||||
{
|
{
|
||||||
LDAPConn *tmplc, *prevlc;
|
LDAPConn *tmplc, *prevlc;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
"ldap_free_connection %d %d\n",
|
"ldap_free_connection %d %d\n",
|
||||||
force, unbind, 0 );
|
force, unbind, 0 );
|
||||||
|
|
||||||
if ( force || --lc->lconn_refcnt <= 0 ) {
|
if ( force || --lc->lconn_refcnt <= 0 ) {
|
||||||
/* remove from connections list first */
|
/* remove from connections list first */
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
|
||||||
|
|
||||||
for ( prevlc = NULL, tmplc = ld->ld_conns;
|
for ( prevlc = NULL, tmplc = ld->ld_conns;
|
||||||
tmplc != NULL;
|
tmplc != NULL;
|
||||||
|
|
@ -684,7 +735,6 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||||
}
|
}
|
||||||
prevlc = tmplc;
|
prevlc = tmplc;
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
|
|
||||||
/* process connection callbacks */
|
/* process connection callbacks */
|
||||||
{
|
{
|
||||||
|
|
@ -693,19 +743,23 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||||
ldap_conncb *cb;
|
ldap_conncb *cb;
|
||||||
|
|
||||||
lo = &ld->ld_options;
|
lo = &ld->ld_options;
|
||||||
|
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||||
if ( lo->ldo_conn_cbs ) {
|
if ( lo->ldo_conn_cbs ) {
|
||||||
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
||||||
cb = ll->ll_data;
|
cb = ll->ll_data;
|
||||||
cb->lc_del( ld, lc->lconn_sb, cb );
|
cb->lc_del( ld, lc->lconn_sb, cb );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
lo = LDAP_INT_GLOBAL_OPT();
|
lo = LDAP_INT_GLOBAL_OPT();
|
||||||
|
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||||
if ( lo->ldo_conn_cbs ) {
|
if ( lo->ldo_conn_cbs ) {
|
||||||
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
||||||
cb = ll->ll_data;
|
cb = ll->ll_data;
|
||||||
cb->lc_del( ld, lc->lconn_sb, cb );
|
cb->lc_del( ld, lc->lconn_sb, cb );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
|
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
|
||||||
|
|
@ -773,6 +827,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Protects self with ld_conn_mutex */
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
void
|
void
|
||||||
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||||
|
|
@ -781,6 +836,7 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||||
char timebuf[32];
|
char timebuf[32];
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 );
|
Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 );
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
|
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
|
||||||
if ( lc->lconn_server != NULL ) {
|
if ( lc->lconn_server != NULL ) {
|
||||||
Debug( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n",
|
Debug( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n",
|
||||||
|
|
@ -817,9 +873,11 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by req_mutex and res_mutex */
|
||||||
void
|
void
|
||||||
ldap_dump_requests_and_responses( LDAP *ld )
|
ldap_dump_requests_and_responses( LDAP *ld )
|
||||||
{
|
{
|
||||||
|
|
@ -868,9 +926,11 @@ ldap_dump_requests_and_responses( LDAP *ld )
|
||||||
}
|
}
|
||||||
#endif /* LDAP_DEBUG */
|
#endif /* LDAP_DEBUG */
|
||||||
|
|
||||||
|
/* protected by req_mutex */
|
||||||
static void
|
static void
|
||||||
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||||
{
|
{
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
/* if lr_refcnt > 0, the request has been looked up
|
/* if lr_refcnt > 0, the request has been looked up
|
||||||
* by ldap_find_request_by_msgid(); if in the meanwhile
|
* by ldap_find_request_by_msgid(); if in the meanwhile
|
||||||
* the request is free()'d by someone else, just decrease
|
* the request is free()'d by someone else, just decrease
|
||||||
|
|
@ -921,11 +981,11 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||||
LDAP_FREE( lr );
|
LDAP_FREE( lr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* protected by req_mutex */
|
||||||
void
|
void
|
||||||
ldap_free_request( LDAP *ld, LDAPRequest *lr )
|
ldap_free_request( LDAP *ld, LDAPRequest *lr )
|
||||||
{
|
{
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
|
Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
|
||||||
lr->lr_origid, lr->lr_msgid, 0 );
|
lr->lr_origid, lr->lr_msgid, 0 );
|
||||||
|
|
||||||
|
|
@ -993,6 +1053,8 @@ static int ldap_int_nextref(
|
||||||
* (OUT) hadrefp = 1 if sucessfully followed referral
|
* (OUT) hadrefp = 1 if sucessfully followed referral
|
||||||
*
|
*
|
||||||
* Return value - number of referrals followed
|
* Return value - number of referrals followed
|
||||||
|
*
|
||||||
|
* Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
|
ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
|
||||||
|
|
@ -1008,11 +1070,14 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||||
LDAPreqinfo rinfo;
|
LDAPreqinfo rinfo;
|
||||||
LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref;
|
LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
|
||||||
|
|
||||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||||
*hadrefp = 0;
|
*hadrefp = 0;
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
|
|
||||||
|
|
||||||
unfollowed = NULL;
|
unfollowed = NULL;
|
||||||
rc = count = 0;
|
rc = count = 0;
|
||||||
|
|
||||||
|
|
@ -1184,10 +1249,8 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||||
/* Send the new request to the server - may require a bind */
|
/* Send the new request to the server - may require a bind */
|
||||||
rinfo.ri_msgid = origreq->lr_origid;
|
rinfo.ri_msgid = origreq->lr_origid;
|
||||||
rinfo.ri_url = refarray[i];
|
rinfo.ri_url = refarray[i];
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
rc = ldap_send_server_request( ld, ber, id,
|
rc = ldap_send_server_request( ld, ber, id,
|
||||||
origreq, &srv, NULL, &rinfo );
|
origreq, &srv, NULL, &rinfo, 0, 1 );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
if ( rc < 0 ) {
|
if ( rc < 0 ) {
|
||||||
/* Failure, try next referral in the list */
|
/* Failure, try next referral in the list */
|
||||||
Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n",
|
Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n",
|
||||||
|
|
@ -1208,6 +1271,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||||
if ( lc == NULL ) {
|
if ( lc == NULL ) {
|
||||||
ld->ld_errno = LDAP_OPERATIONS_ERROR;
|
ld->ld_errno = LDAP_OPERATIONS_ERROR;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1253,6 +1317,7 @@ done:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX merging of errors in this routine needs to be improved
|
* XXX merging of errors in this routine needs to be improved
|
||||||
|
* Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ldap_chase_referrals( LDAP *ld,
|
ldap_chase_referrals( LDAP *ld,
|
||||||
|
|
@ -1270,6 +1335,9 @@ ldap_chase_referrals( LDAP *ld,
|
||||||
LDAPreqinfo rinfo;
|
LDAPreqinfo rinfo;
|
||||||
LDAPConn *lc;
|
LDAPConn *lc;
|
||||||
|
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
|
Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
|
||||||
|
|
||||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||||
|
|
@ -1367,11 +1435,8 @@ ldap_chase_referrals( LDAP *ld,
|
||||||
|
|
||||||
rinfo.ri_msgid = origreq->lr_origid;
|
rinfo.ri_msgid = origreq->lr_origid;
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
rc = ldap_send_server_request( ld, ber, id,
|
rc = ldap_send_server_request( ld, ber, id,
|
||||||
lr, &srv, NULL, &rinfo );
|
lr, &srv, NULL, &rinfo, 0, 1 );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
|
|
||||||
LDAP_FREE( rinfo.ri_url );
|
LDAP_FREE( rinfo.ri_url );
|
||||||
|
|
||||||
if( rc >= 0 ) {
|
if( rc >= 0 ) {
|
||||||
|
|
@ -1561,12 +1626,12 @@ re_encode_request( LDAP *ld,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by req_mutex */
|
||||||
LDAPRequest *
|
LDAPRequest *
|
||||||
ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
||||||
{
|
{
|
||||||
LDAPRequest *lr;
|
LDAPRequest *lr;
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||||
if ( lr->lr_status == LDAP_REQST_COMPLETED ) {
|
if ( lr->lr_status == LDAP_REQST_COMPLETED ) {
|
||||||
continue; /* Skip completed requests */
|
continue; /* Skip completed requests */
|
||||||
|
|
@ -1576,17 +1641,16 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
|
|
||||||
return( lr );
|
return( lr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* protected by req_mutex */
|
||||||
void
|
void
|
||||||
ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
||||||
{
|
{
|
||||||
LDAPRequest *lr;
|
LDAPRequest *lr;
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||||
if ( lr == lrx ) {
|
if ( lr == lrx ) {
|
||||||
if ( lr->lr_refcnt > 0 ) {
|
if ( lr->lr_refcnt > 0 ) {
|
||||||
|
|
@ -1607,5 +1671,4 @@ ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
||||||
} else if ( freeit ) {
|
} else if ( freeit ) {
|
||||||
ldap_free_request( ld, lrx );
|
ldap_free_request( ld, lrx );
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@
|
||||||
#include "ldap_log.h"
|
#include "ldap_log.h"
|
||||||
#include "lutil.h"
|
#include "lutil.h"
|
||||||
|
|
||||||
static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int *idx ));
|
static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
|
||||||
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int idx ));
|
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
|
||||||
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout,
|
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout,
|
||||||
LDAPMessage **result ));
|
LDAPMessage **result ));
|
||||||
static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid,
|
static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid,
|
||||||
|
|
@ -120,6 +120,7 @@ ldap_result(
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* protected by res_mutex */
|
||||||
static LDAPMessage *
|
static LDAPMessage *
|
||||||
chkResponseList(
|
chkResponseList(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -144,12 +145,10 @@ chkResponseList(
|
||||||
|
|
||||||
lastlm = &ld->ld_responses;
|
lastlm = &ld->ld_responses;
|
||||||
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
|
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
|
||||||
int idx;
|
|
||||||
|
|
||||||
nextlm = lm->lm_next;
|
nextlm = lm->lm_next;
|
||||||
++cnt;
|
++cnt;
|
||||||
|
|
||||||
if ( ldap_abandoned( ld, lm->lm_msgid, &idx ) ) {
|
if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
|
||||||
Debug( LDAP_DEBUG_ANY,
|
Debug( LDAP_DEBUG_ANY,
|
||||||
"response list msg abandoned, "
|
"response list msg abandoned, "
|
||||||
"msgid %d message type %s\n",
|
"msgid %d message type %s\n",
|
||||||
|
|
@ -164,7 +163,7 @@ chkResponseList(
|
||||||
default:
|
default:
|
||||||
/* there's no need to keep the id
|
/* there's no need to keep the id
|
||||||
* in the abandoned list any longer */
|
* in the abandoned list any longer */
|
||||||
ldap_mark_abandoned( ld, lm->lm_msgid, idx );
|
ldap_mark_abandoned( ld, lm->lm_msgid );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,6 +230,7 @@ chkResponseList(
|
||||||
return lm;
|
return lm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* protected by res_mutex */
|
||||||
static int
|
static int
|
||||||
wait4msg(
|
wait4msg(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -284,9 +284,7 @@ wait4msg(
|
||||||
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
|
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
|
||||||
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
|
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
|
||||||
(void *)ld, msgid, all );
|
(void *)ld, msgid, all );
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
|
||||||
ldap_dump_connection( ld, ld->ld_conns, 1 );
|
ldap_dump_connection( ld, ld->ld_conns, 1 );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||||
ldap_dump_requests_and_responses( ld );
|
ldap_dump_requests_and_responses( ld );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||||
|
|
@ -308,7 +306,6 @@ wait4msg(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
|
|
||||||
if ( !lc_ready ) {
|
if ( !lc_ready ) {
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -328,6 +325,7 @@ wait4msg(
|
||||||
{
|
{
|
||||||
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
|
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
|
||||||
LDAP_TIMEOUT);
|
LDAP_TIMEOUT);
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
return( rc );
|
return( rc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,8 +347,6 @@ wait4msg(
|
||||||
{
|
{
|
||||||
ldap_int_flush_request( ld, ld->ld_requests );
|
ldap_int_flush_request( ld, ld->ld_requests );
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
|
||||||
for ( lc = ld->ld_conns;
|
for ( lc = ld->ld_conns;
|
||||||
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
|
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
|
||||||
lc = lnext )
|
lc = lnext )
|
||||||
|
|
@ -360,25 +356,22 @@ wait4msg(
|
||||||
{
|
{
|
||||||
/* Don't let it get freed out from under us */
|
/* Don't let it get freed out from under us */
|
||||||
++lc->lconn_refcnt;
|
++lc->lconn_refcnt;
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
|
||||||
rc = try_read1msg( ld, msgid, all, lc, result );
|
rc = try_read1msg( ld, msgid, all, lc, result );
|
||||||
lnext = lc->lconn_next;
|
lnext = lc->lconn_next;
|
||||||
|
|
||||||
/* Only take locks if we're really freeing */
|
/* Only take locks if we're really freeing */
|
||||||
if ( lc->lconn_refcnt <= 1 ) {
|
if ( lc->lconn_refcnt <= 1 ) {
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
|
||||||
ldap_free_connection( ld, lc, 0, 1 );
|
ldap_free_connection( ld, lc, 0, 1 );
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
|
||||||
} else {
|
} else {
|
||||||
--lc->lconn_refcnt;
|
--lc->lconn_refcnt;
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
|
||||||
} else {
|
} else {
|
||||||
lnext = lc->lconn_next;
|
lnext = lc->lconn_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
|
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
|
||||||
|
|
@ -432,6 +425,7 @@ wait4msg(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* protected by res_mutex, conn_mutex and req_mutex */
|
||||||
static ber_tag_t
|
static ber_tag_t
|
||||||
try_read1msg(
|
try_read1msg(
|
||||||
LDAP *ld,
|
LDAP *ld,
|
||||||
|
|
@ -443,7 +437,6 @@ try_read1msg(
|
||||||
BerElement *ber;
|
BerElement *ber;
|
||||||
LDAPMessage *newmsg, *l, *prev;
|
LDAPMessage *newmsg, *l, *prev;
|
||||||
ber_int_t id;
|
ber_int_t id;
|
||||||
int idx;
|
|
||||||
ber_tag_t tag;
|
ber_tag_t tag;
|
||||||
ber_len_t len;
|
ber_len_t len;
|
||||||
int foundit = 0;
|
int foundit = 0;
|
||||||
|
|
@ -461,6 +454,8 @@ try_read1msg(
|
||||||
assert( lc != NULL );
|
assert( lc != NULL );
|
||||||
|
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||||
|
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
|
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
|
||||||
(void *)ld, msgid, all );
|
(void *)ld, msgid, all );
|
||||||
|
|
@ -535,7 +530,7 @@ nextresp3:
|
||||||
|
|
||||||
/* if it's been abandoned, toss it */
|
/* if it's been abandoned, toss it */
|
||||||
if ( id > 0 ) {
|
if ( id > 0 ) {
|
||||||
if ( ldap_abandoned( ld, id, &idx ) ) {
|
if ( ldap_abandoned( ld, id ) ) {
|
||||||
/* the message type */
|
/* the message type */
|
||||||
tag = ber_peek_tag( ber, &len );
|
tag = ber_peek_tag( ber, &len );
|
||||||
switch ( tag ) {
|
switch ( tag ) {
|
||||||
|
|
@ -548,7 +543,7 @@ nextresp3:
|
||||||
default:
|
default:
|
||||||
/* there's no need to keep the id
|
/* there's no need to keep the id
|
||||||
* in the abandoned list any longer */
|
* in the abandoned list any longer */
|
||||||
ldap_mark_abandoned( ld, id, idx );
|
ldap_mark_abandoned( ld, id );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1337,35 +1332,37 @@ ldap_msgdelete( LDAP *ld, int msgid )
|
||||||
*
|
*
|
||||||
* return the location of the message id in the array of abandoned
|
* return the location of the message id in the array of abandoned
|
||||||
* message ids, or -1
|
* message ids, or -1
|
||||||
*
|
|
||||||
* expects ld_res_mutex to be locked
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ldap_abandoned( LDAP *ld, ber_int_t msgid, int *idxp )
|
ldap_abandoned( LDAP *ld, ber_int_t msgid )
|
||||||
{
|
{
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
int ret, idx;
|
||||||
|
|
||||||
assert( idxp != NULL );
|
|
||||||
assert( msgid >= 0 );
|
assert( msgid >= 0 );
|
||||||
|
|
||||||
return ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, idxp );
|
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
|
||||||
|
ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ldap_mark_abandoned
|
* ldap_mark_abandoned
|
||||||
*
|
|
||||||
* expects ld_res_mutex to be locked
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid, int idx )
|
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid )
|
||||||
{
|
{
|
||||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
int ret, idx;
|
||||||
|
|
||||||
/* NOTE: those assertions are repeated in ldap_int_bisect_delete() */
|
assert( msgid >= 0 );
|
||||||
assert( idx >= 0 );
|
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
|
||||||
assert( (unsigned) idx < ld->ld_nabandoned );
|
ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
|
||||||
assert( ld->ld_abandoned[ idx ] == msgid );
|
if (ret <= 0) { /* error or already deleted by another thread */
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||||
return ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
|
return ret;
|
||||||
|
}
|
||||||
|
/* still in abandoned array, so delete */
|
||||||
|
ret = ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
|
||||||
msgid, idx );
|
msgid, idx );
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,18 +80,44 @@ ldap_ld_free(
|
||||||
LDAPMessage *lm, *next;
|
LDAPMessage *lm, *next;
|
||||||
int err = LDAP_SUCCESS;
|
int err = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
|
||||||
|
/* Someone else is still using this ld. */
|
||||||
|
if (ld->ld_ldcrefcnt > 1) { /* but not last thread */
|
||||||
|
/* clean up self only */
|
||||||
|
ld->ld_ldcrefcnt--;
|
||||||
|
if ( ld->ld_error != NULL ) {
|
||||||
|
LDAP_FREE( ld->ld_error );
|
||||||
|
ld->ld_error = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ld->ld_matched != NULL ) {
|
||||||
|
LDAP_FREE( ld->ld_matched );
|
||||||
|
ld->ld_matched = NULL;
|
||||||
|
}
|
||||||
|
if ( ld->ld_referrals != NULL) {
|
||||||
|
LDAP_VFREE(ld->ld_referrals);
|
||||||
|
ld->ld_referrals = NULL;
|
||||||
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
|
||||||
|
LDAP_FREE( (char *) ld );
|
||||||
|
return( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This ld is the last thread. */
|
||||||
|
|
||||||
/* free LDAP structure and outstanding requests/responses */
|
/* free LDAP structure and outstanding requests/responses */
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||||
while ( ld->ld_requests != NULL ) {
|
while ( ld->ld_requests != NULL ) {
|
||||||
ldap_free_request( ld, ld->ld_requests );
|
ldap_free_request( ld, ld->ld_requests );
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||||
|
|
||||||
/* free and unbind from all open connections */
|
/* free and unbind from all open connections */
|
||||||
while ( ld->ld_conns != NULL ) {
|
while ( ld->ld_conns != NULL ) {
|
||||||
ldap_free_connection( ld, ld->ld_conns, 1, close );
|
ldap_free_connection( ld, ld->ld_conns, 1, close );
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||||
|
|
||||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||||
for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
|
for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
|
||||||
next = lm->lm_next;
|
next = lm->lm_next;
|
||||||
|
|
@ -103,6 +129,7 @@ ldap_ld_free(
|
||||||
ld->ld_abandoned = NULL;
|
ld->ld_abandoned = NULL;
|
||||||
}
|
}
|
||||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||||
|
LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );
|
||||||
|
|
||||||
/* final close callbacks */
|
/* final close callbacks */
|
||||||
{
|
{
|
||||||
|
|
@ -126,7 +153,7 @@ ldap_ld_free(
|
||||||
ld->ld_matched = NULL;
|
ld->ld_matched = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ld->ld_referrals != NULL) {
|
if ( ld->ld_referrals != NULL) {
|
||||||
LDAP_VFREE(ld->ld_referrals);
|
LDAP_VFREE(ld->ld_referrals);
|
||||||
ld->ld_referrals = NULL;
|
ld->ld_referrals = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -188,22 +215,35 @@ ldap_ld_free(
|
||||||
ldap_controls_free( ld->ld_options.ldo_cctrls );
|
ldap_controls_free( ld->ld_options.ldo_cctrls );
|
||||||
ld->ld_options.ldo_cctrls = NULL;
|
ld->ld_options.ldo_cctrls = NULL;
|
||||||
}
|
}
|
||||||
|
LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );
|
||||||
|
|
||||||
ber_sockbuf_free( ld->ld_sb );
|
ber_sockbuf_free( ld->ld_sb );
|
||||||
|
|
||||||
#ifdef LDAP_R_COMPILE
|
#ifdef LDAP_R_COMPILE
|
||||||
|
ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
|
||||||
|
ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
|
||||||
ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
|
ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
|
||||||
ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
|
ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
|
||||||
ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
|
ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
|
||||||
|
ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
|
||||||
|
ldap_pvt_thread_mutex_unlock( &ld->ld_ldcmutex );
|
||||||
|
ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
|
||||||
#endif
|
#endif
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
LDAP_TRASH(ld);
|
LDAP_TRASH(ld);
|
||||||
#endif
|
#endif
|
||||||
|
LDAP_FREE( (char *) ld->ldc );
|
||||||
LDAP_FREE( (char *) ld );
|
LDAP_FREE( (char *) ld );
|
||||||
|
|
||||||
return( err );
|
return( err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_destroy( LDAP *ld )
|
||||||
|
{
|
||||||
|
return ( ldap_ld_free( ld, 1, NULL, NULL ) );
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_unbind_s( LDAP *ld )
|
ldap_unbind_s( LDAP *ld )
|
||||||
{
|
{
|
||||||
|
|
@ -233,7 +273,7 @@ ldap_send_unbind(
|
||||||
return( ld->ld_errno );
|
return( ld->ld_errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
id = ++(ld)->ld_msgid;
|
LDAP_NEXT_MSGID(ld, id);
|
||||||
|
|
||||||
/* fill it in */
|
/* fill it in */
|
||||||
if ( ber_printf( ber, "{itn" /*}*/, id,
|
if ( ber_printf( ber, "{itn" /*}*/, id,
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,21 @@
|
||||||
## <http://www.OpenLDAP.org/license.html>.
|
## <http://www.OpenLDAP.org/license.html>.
|
||||||
|
|
||||||
PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel slapd-modrdn \
|
PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel slapd-modrdn \
|
||||||
slapd-modify slapd-bind ldif-filter
|
slapd-modify slapd-bind slapd-mtread ldif-filter
|
||||||
|
|
||||||
SRCS = slapd-common.c \
|
SRCS = slapd-common.c \
|
||||||
slapd-tester.c slapd-search.c slapd-read.c slapd-addel.c \
|
slapd-tester.c slapd-search.c slapd-read.c slapd-addel.c \
|
||||||
slapd-modrdn.c slapd-modify.c slapd-bind.c ldif-filter.c
|
slapd-modrdn.c slapd-modify.c slapd-bind.c slapd-mtread.c \
|
||||||
|
ldif-filter.c
|
||||||
|
|
||||||
LDAP_INCDIR= ../../include
|
LDAP_INCDIR= ../../include
|
||||||
LDAP_LIBDIR= ../../libraries
|
LDAP_LIBDIR= ../../libraries
|
||||||
|
|
||||||
XLIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA)
|
XLIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA)
|
||||||
|
XRLIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA)
|
||||||
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
|
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
|
||||||
|
RLIBS = $(XRLIBS) $(XXLIBS) $(AC_LIBS) $(XXXLIBS)
|
||||||
|
|
||||||
|
|
||||||
OBJS = slapd-common.o
|
OBJS = slapd-common.o
|
||||||
|
|
||||||
|
|
@ -57,3 +61,6 @@ slapd-bind: slapd-bind.o $(OBJS) $(XLIBS)
|
||||||
ldif-filter: ldif-filter.o $(XLIBS)
|
ldif-filter: ldif-filter.o $(XLIBS)
|
||||||
$(LTLINK) -o $@ ldif-filter.o $(LIBS)
|
$(LTLINK) -o $@ ldif-filter.o $(LIBS)
|
||||||
|
|
||||||
|
slapd-mtread: slapd-mtread.o $(OBJS) $(XRLIBS)
|
||||||
|
$(LTLINK) -o $@ slapd-mtread.o $(OBJS) $(RLIBS)
|
||||||
|
|
||||||
|
|
|
||||||
758
tests/progs/slapd-mtread.c
Normal file
758
tests/progs/slapd-mtread.c
Normal file
|
|
@ -0,0 +1,758 @@
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 1999-2009 The OpenLDAP Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted only as authorized by the OpenLDAP
|
||||||
|
* Public License.
|
||||||
|
*
|
||||||
|
* A copy of this license is available in file LICENSE in the
|
||||||
|
* top-level directory of the distribution or, alternatively, at
|
||||||
|
* <http://www.OpenLDAP.org/license.html>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Kurt Spanier for inclusion
|
||||||
|
* in OpenLDAP Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This tool is a MT reader. It behaves like slapd-read however
|
||||||
|
* with one or more threads simultaneously using the same connection.
|
||||||
|
* If -M is enabled, then M threads will also perfrom write operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ldap_pvt_thread.h"
|
||||||
|
|
||||||
|
#include "ac/stdlib.h"
|
||||||
|
|
||||||
|
#include "ac/ctype.h"
|
||||||
|
#include "ac/param.h"
|
||||||
|
#include "ac/socket.h"
|
||||||
|
#include "ac/string.h"
|
||||||
|
#include "ac/unistd.h"
|
||||||
|
#include "ac/wait.h"
|
||||||
|
|
||||||
|
#include "ldap.h"
|
||||||
|
#include "lutil.h"
|
||||||
|
|
||||||
|
#include "ldap_pvt.h"
|
||||||
|
|
||||||
|
#include "slapd-common.h"
|
||||||
|
|
||||||
|
#define MAXCONN 512
|
||||||
|
#define LOOPS 100
|
||||||
|
#define RETRIES 0
|
||||||
|
#define DEFAULT_BASE "ou=people,dc=example,dc=com"
|
||||||
|
|
||||||
|
static int
|
||||||
|
whoami()
|
||||||
|
{
|
||||||
|
int me = ldap_pvt_thread_self();
|
||||||
|
return (me);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_conn( char *uri, char *manager, struct berval *passwd,
|
||||||
|
LDAP **ld, int nobind, int maxretries, int conn_num );
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_read( LDAP *ld, char *entry,
|
||||||
|
char **attrs, int noattrs, int nobind, int maxloop,
|
||||||
|
int maxretries, int delay, int force, int chaserefs, int idx );
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_random( LDAP *ld,
|
||||||
|
char *sbase, char *filter, char **attrs, int noattrs, int nobind,
|
||||||
|
int innerloop, int maxretries, int delay, int force, int chaserefs,
|
||||||
|
int idx );
|
||||||
|
|
||||||
|
static void *
|
||||||
|
do_onethread( void *arg );
|
||||||
|
|
||||||
|
static void *
|
||||||
|
do_onerwthread( void *arg );
|
||||||
|
|
||||||
|
#define MAX_THREAD 1024
|
||||||
|
int rt_pass[MAX_THREAD];
|
||||||
|
int rt_fail[MAX_THREAD];
|
||||||
|
int rwt_pass[MAX_THREAD];
|
||||||
|
int rwt_fail[MAX_THREAD];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared globals (command line args)
|
||||||
|
*/
|
||||||
|
LDAP *ld = NULL;
|
||||||
|
char *entry = NULL;
|
||||||
|
char *filter = NULL;
|
||||||
|
int loops = LOOPS;
|
||||||
|
int outerloops = 1;
|
||||||
|
int retries = RETRIES;
|
||||||
|
int delay = 0;
|
||||||
|
int force = 0;
|
||||||
|
int chaserefs = 0;
|
||||||
|
char *srchattrs[] = { "1.1", NULL };
|
||||||
|
char **attrs = srchattrs;
|
||||||
|
int noattrs = 0;
|
||||||
|
int nobind = 0;
|
||||||
|
int threads = 1;
|
||||||
|
int rwthreads = 0;
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
int noconns = 1;
|
||||||
|
LDAP **lds = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_error(char *string)
|
||||||
|
{
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
snprintf(thrstr, BUFSIZ, "error on tid: %d: %s", whoami(), string);
|
||||||
|
tester_error( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_output(char *string)
|
||||||
|
{
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
snprintf(thrstr, BUFSIZ, "tid: %d says: %s", whoami(), string);
|
||||||
|
tester_error( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_verbose(char *string)
|
||||||
|
{
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
if (!verbose)
|
||||||
|
return;
|
||||||
|
snprintf(thrstr, BUFSIZ, "tid: %d says: %s", whoami(), string);
|
||||||
|
tester_error( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage( char *name )
|
||||||
|
{
|
||||||
|
fprintf( stderr,
|
||||||
|
"usage: %s "
|
||||||
|
"-H <uri> | ([-h <host>] -p <port>) "
|
||||||
|
"-D <manager> "
|
||||||
|
"-w <passwd> "
|
||||||
|
"-e <entry> "
|
||||||
|
"[-A] "
|
||||||
|
"[-C] "
|
||||||
|
"[-F] "
|
||||||
|
"[-N] "
|
||||||
|
"[-v] "
|
||||||
|
"[-c connections] "
|
||||||
|
"[-f filter] "
|
||||||
|
"[-i <ignore>] "
|
||||||
|
"[-l <loops>] "
|
||||||
|
"[-L <outerloops>] "
|
||||||
|
"[-m threads] "
|
||||||
|
"[-M threads] "
|
||||||
|
"[-r <maxretries>] "
|
||||||
|
"[-t <delay>] "
|
||||||
|
"[-T <attrs>] "
|
||||||
|
"[<attrs>] "
|
||||||
|
"\n",
|
||||||
|
name );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main( int argc, char **argv )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *uri = NULL;
|
||||||
|
char *host = "localhost";
|
||||||
|
int port = -1;
|
||||||
|
char *manager = NULL;
|
||||||
|
struct berval passwd = { 0, NULL };
|
||||||
|
ldap_pvt_thread_t rtid[MAX_THREAD], rwtid[MAX_THREAD];
|
||||||
|
char outstr[BUFSIZ];
|
||||||
|
int ptpass;
|
||||||
|
int testfail = 0;
|
||||||
|
|
||||||
|
|
||||||
|
tester_init( "slapd-mtread", TESTER_READ );
|
||||||
|
|
||||||
|
/* by default, tolerate referrals and no such object */
|
||||||
|
tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
|
||||||
|
|
||||||
|
while ( (i = getopt( argc, argv, "ACc:D:e:Ff:H:h:i:L:l:M:m:p:r:t:T:w:v" )) != EOF ) {
|
||||||
|
switch ( i ) {
|
||||||
|
case 'A':
|
||||||
|
noattrs++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
chaserefs++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H': /* the server uri */
|
||||||
|
uri = strdup( optarg );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h': /* the servers host */
|
||||||
|
host = strdup( optarg );
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
tester_ignore_str2errlist( optarg );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
nobind++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p': /* the servers port */
|
||||||
|
if ( lutil_atoi( &port, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D': /* the servers manager */
|
||||||
|
manager = strdup( optarg );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w': /* the server managers password */
|
||||||
|
passwd.bv_val = strdup( optarg );
|
||||||
|
passwd.bv_len = strlen( optarg );
|
||||||
|
memset( optarg, '*', passwd.bv_len );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c': /* the number of connections */
|
||||||
|
if ( lutil_atoi( &noconns, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e': /* DN to search for */
|
||||||
|
entry = strdup( optarg );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f': /* the search request */
|
||||||
|
filter = strdup( optarg );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
force++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l': /* the number of loops */
|
||||||
|
if ( lutil_atoi( &loops, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'L': /* the number of outerloops */
|
||||||
|
if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M': /* the number of R/W threads */
|
||||||
|
if ( lutil_atoi( &rwthreads, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
if (rwthreads > MAX_THREAD)
|
||||||
|
rwthreads = MAX_THREAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm': /* the number of threads */
|
||||||
|
if ( lutil_atoi( &threads, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
if (threads > MAX_THREAD)
|
||||||
|
threads = MAX_THREAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': /* the number of retries */
|
||||||
|
if ( lutil_atoi( &retries, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't': /* delay in seconds */
|
||||||
|
if ( lutil_atoi( &delay, optarg ) != 0 ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
attrs = ldap_str2charray( optarg, "," );
|
||||||
|
if ( attrs == NULL ) {
|
||||||
|
usage( argv[0] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
usage( argv[0] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( entry == NULL ) || ( port == -1 && uri == NULL ))
|
||||||
|
usage( argv[0] );
|
||||||
|
|
||||||
|
if ( *entry == '\0' ) {
|
||||||
|
fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
|
||||||
|
argv[0] );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( argv[optind] != NULL ) {
|
||||||
|
attrs = &argv[optind];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noconns < 1)
|
||||||
|
noconns = 1;
|
||||||
|
if (noconns > MAXCONN)
|
||||||
|
noconns = MAXCONN;
|
||||||
|
lds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||||
|
if (lds == NULL) {
|
||||||
|
fprintf( stderr, "%s: Memory error: calloc noconns.\n",
|
||||||
|
argv[0] );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = tester_uri( uri, host, port );
|
||||||
|
/* One connection and one connection only */
|
||||||
|
do_conn( uri, manager, &passwd, &ld, nobind, retries, 0 );
|
||||||
|
lds[0] = ld;
|
||||||
|
for(i = 1; i < noconns; i++) {
|
||||||
|
do_conn( uri, manager, &passwd, &lds[i], nobind, retries, i );
|
||||||
|
}
|
||||||
|
|
||||||
|
ldap_pvt_thread_initialize();
|
||||||
|
|
||||||
|
snprintf(outstr, BUFSIZ, "MT Test Start: conns: %d (%s)", noconns, uri);
|
||||||
|
tester_error(outstr);
|
||||||
|
snprintf(outstr, BUFSIZ, "Threads: RO: %d RW: %d", threads, rwthreads);
|
||||||
|
tester_error(outstr);
|
||||||
|
|
||||||
|
/* Set up read only threads */
|
||||||
|
for ( i = 0; i < threads; i++ ) {
|
||||||
|
ldap_pvt_thread_create( &rtid[i], 0, do_onethread, (void*)i);
|
||||||
|
snprintf(outstr, BUFSIZ, "Created RO thread %d [%d]", i, rtid[i]);
|
||||||
|
thread_verbose(outstr);
|
||||||
|
}
|
||||||
|
/* Set up read/write threads */
|
||||||
|
for ( i = 0; i < rwthreads; i++ ) {
|
||||||
|
ldap_pvt_thread_create( &rwtid[i], 0, do_onerwthread, (void*)i);
|
||||||
|
snprintf(outstr, BUFSIZ, "Created RW thread %d [%d]", i, rwtid[i]);
|
||||||
|
thread_verbose(outstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptpass = outerloops * loops;
|
||||||
|
|
||||||
|
/* wait for read only threads to complete */
|
||||||
|
for ( i = 0; i < threads; i++ )
|
||||||
|
ldap_pvt_thread_join(rtid[i], NULL);
|
||||||
|
/* wait for read/write threads to complete */
|
||||||
|
for ( i = 0; i < rwthreads; i++ )
|
||||||
|
ldap_pvt_thread_join(rwtid[i], NULL);
|
||||||
|
|
||||||
|
for(i = 0; i < noconns; i++) {
|
||||||
|
if ( lds[i] != NULL ) {
|
||||||
|
ldap_unbind_ext( lds[i], NULL, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( lds );
|
||||||
|
|
||||||
|
for ( i = 0; i < threads; i++ ) {
|
||||||
|
snprintf(outstr, BUFSIZ, "RO thread %d pass=%d fail=%d", i,
|
||||||
|
rt_pass[i], rt_fail[i]);
|
||||||
|
tester_error(outstr);
|
||||||
|
if (rt_fail[i] != 0 || rt_pass[i] != ptpass) {
|
||||||
|
snprintf(outstr, BUFSIZ, "FAIL RO thread %d", i);
|
||||||
|
tester_error(outstr);
|
||||||
|
testfail++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( i = 0; i < rwthreads; i++ ) {
|
||||||
|
snprintf(outstr, BUFSIZ, "RW thread %d pass=%d fail=%d", i,
|
||||||
|
rwt_pass[i], rwt_fail[i]);
|
||||||
|
tester_error(outstr);
|
||||||
|
if (rwt_fail[i] != 0 || rwt_pass[i] != ptpass) {
|
||||||
|
snprintf(outstr, BUFSIZ, "FAIL RW thread %d", i);
|
||||||
|
tester_error(outstr);
|
||||||
|
testfail++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(outstr, BUFSIZ, "MT Test complete" );
|
||||||
|
tester_error(outstr);
|
||||||
|
|
||||||
|
if (testfail)
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
exit( EXIT_SUCCESS );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
do_onethread( void *arg )
|
||||||
|
{
|
||||||
|
int i, j, thisconn;
|
||||||
|
LDAP **mlds;
|
||||||
|
int me = whoami();
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
int rc, refcnt = 0;
|
||||||
|
int myidx = (int)arg;
|
||||||
|
|
||||||
|
mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||||
|
if (mlds == NULL) {
|
||||||
|
thread_error( "Memory error: thread calloc for noconns" );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( j = 0; j < outerloops; j++ ) {
|
||||||
|
for(i = 0; i < noconns; i++) {
|
||||||
|
mlds[i] = ldap_dup(lds[i]);
|
||||||
|
if (mlds[i] == NULL) {
|
||||||
|
thread_error( "ldap_dup error" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||||
|
snprintf(thrstr, BUFSIZ,
|
||||||
|
"RO Thread: %d conns: %d refcnt: %d (rc = %d)",
|
||||||
|
me, noconns, refcnt, rc);
|
||||||
|
thread_verbose(thrstr);
|
||||||
|
|
||||||
|
thisconn = (me + j) % noconns;
|
||||||
|
if (thisconn < 0 || thisconn >= noconns)
|
||||||
|
thisconn = 0;
|
||||||
|
if (mlds[thisconn] == NULL) {
|
||||||
|
thread_error("(failed to dup)");
|
||||||
|
tester_perror( "ldap_dup", "(failed to dup)" );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
snprintf(thrstr, BUFSIZ, "Thread %d using conn %d", me, thisconn);
|
||||||
|
thread_verbose(thrstr);
|
||||||
|
if ( filter != NULL ) {
|
||||||
|
do_random( mlds[thisconn], entry, filter, attrs,
|
||||||
|
noattrs, nobind, loops, retries, delay, force,
|
||||||
|
chaserefs, myidx );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
do_read( mlds[thisconn], entry, attrs,
|
||||||
|
noattrs, nobind, loops, retries, delay, force,
|
||||||
|
chaserefs, myidx );
|
||||||
|
}
|
||||||
|
for(i = 0; i < noconns; i++) {
|
||||||
|
(void) ldap_destroy(mlds[i]);
|
||||||
|
mlds[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( mlds );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
do_onerwthread( void *arg )
|
||||||
|
{
|
||||||
|
int i, j, thisconn;
|
||||||
|
LDAP **mlds, *ld;
|
||||||
|
int me = whoami();
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
char dn[256], uids[32], cns[32], *base;
|
||||||
|
LDAPMod *attrp[5], attrs[4];
|
||||||
|
char *oc_vals[] = { "top", "OpenLDAPperson", NULL };
|
||||||
|
char *cn_vals[] = { NULL, NULL };
|
||||||
|
char *sn_vals[] = { NULL, NULL };
|
||||||
|
char *uid_vals[] = { NULL, NULL };
|
||||||
|
int ret;
|
||||||
|
int adds = 0;
|
||||||
|
int dels = 0;
|
||||||
|
int rc, refcnt = 0;
|
||||||
|
int myidx = (int)arg;
|
||||||
|
|
||||||
|
mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||||
|
if (mlds == NULL) {
|
||||||
|
thread_error( "Memory error: thread calloc for noconns" );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(uids, 32, "rwtest%04.4d", me);
|
||||||
|
snprintf(cns, 32, "rwtest%04.4d", me);
|
||||||
|
/* add setup */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
attrp[i] = &attrs[i];
|
||||||
|
attrs[i].mod_op = 0;
|
||||||
|
}
|
||||||
|
attrp[4] = NULL;
|
||||||
|
attrs[0].mod_type = "objectClass";
|
||||||
|
attrs[0].mod_values = oc_vals;
|
||||||
|
attrs[1].mod_type = "cn";
|
||||||
|
attrs[1].mod_values = cn_vals;
|
||||||
|
cn_vals[0] = &cns[0];
|
||||||
|
attrs[2].mod_type = "sn";
|
||||||
|
attrs[2].mod_values = sn_vals;
|
||||||
|
sn_vals[0] = &cns[0];
|
||||||
|
attrs[3].mod_type = "uid";
|
||||||
|
attrs[3].mod_values = uid_vals;
|
||||||
|
uid_vals[0] = &uids[0];
|
||||||
|
|
||||||
|
for ( j = 0; j < outerloops; j++ ) {
|
||||||
|
for(i = 0; i < noconns; i++) {
|
||||||
|
mlds[i] = ldap_dup(lds[i]);
|
||||||
|
if (mlds[i] == NULL) {
|
||||||
|
thread_error( "ldap_dup error" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||||
|
snprintf(thrstr, BUFSIZ,
|
||||||
|
"RW Thread: %d conns: %d refcnt: %d (rc = %d)",
|
||||||
|
me, noconns, refcnt, rc);
|
||||||
|
thread_verbose(thrstr);
|
||||||
|
|
||||||
|
thisconn = (me + j) % noconns;
|
||||||
|
if (thisconn < 0 || thisconn >= noconns)
|
||||||
|
thisconn = 0;
|
||||||
|
if (mlds[thisconn] == NULL) {
|
||||||
|
thread_error("(failed to dup)");
|
||||||
|
tester_perror( "ldap_dup", "(failed to dup)" );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
snprintf(thrstr, BUFSIZ, "START RW Thread %d using conn %d",
|
||||||
|
me, thisconn);
|
||||||
|
thread_verbose(thrstr);
|
||||||
|
|
||||||
|
ld = mlds[thisconn];
|
||||||
|
if (entry != NULL)
|
||||||
|
base = entry;
|
||||||
|
else
|
||||||
|
base = DEFAULT_BASE;
|
||||||
|
snprintf(dn, 256, "cn=%s,%s", cns, base);
|
||||||
|
|
||||||
|
adds = 0;
|
||||||
|
dels = 0;
|
||||||
|
for (i = 0; i < loops; i++) {
|
||||||
|
ret = ldap_add_ext_s(ld, dn, &attrp[0], NULL, NULL);
|
||||||
|
if (ret == LDAP_SUCCESS) {
|
||||||
|
adds++;
|
||||||
|
ret = ldap_delete_ext_s(ld, dn, NULL, NULL);
|
||||||
|
if (ret == LDAP_SUCCESS) {
|
||||||
|
dels++;
|
||||||
|
rwt_pass[myidx]++;
|
||||||
|
} else {
|
||||||
|
thread_output(ldap_err2string(ret));
|
||||||
|
rwt_fail[myidx]++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
thread_output(ldap_err2string(ret));
|
||||||
|
rwt_fail[myidx]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(thrstr, BUFSIZ,
|
||||||
|
"INNER STOP RW Thread %d using conn %d (%d/%d)",
|
||||||
|
me, thisconn, adds, dels);
|
||||||
|
thread_verbose(thrstr);
|
||||||
|
|
||||||
|
for(i = 0; i < noconns; i++) {
|
||||||
|
(void) ldap_destroy(mlds[i]);
|
||||||
|
mlds[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free( mlds );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_conn( char *uri, char *manager, struct berval *passwd,
|
||||||
|
LDAP **ldp, int nobind, int maxretries, int conn_num )
|
||||||
|
{
|
||||||
|
LDAP *ld = NULL;
|
||||||
|
int version = LDAP_VERSION3;
|
||||||
|
int i = 0, do_retry = maxretries;
|
||||||
|
int rc = LDAP_SUCCESS;
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
retry:;
|
||||||
|
ldap_initialize( &ld, uri );
|
||||||
|
if ( ld == NULL ) {
|
||||||
|
snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
|
||||||
|
tester_error( thrstr );
|
||||||
|
tester_perror( "ldap_initialize", NULL );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
|
||||||
|
(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
|
||||||
|
chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
|
||||||
|
|
||||||
|
if ( do_retry == maxretries ) {
|
||||||
|
snprintf( thrstr, BUFSIZ, "do_conn #%d\n", conn_num );
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nobind == 0 ) {
|
||||||
|
rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
|
||||||
|
tester_error( thrstr );
|
||||||
|
tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
|
||||||
|
switch ( rc ) {
|
||||||
|
case LDAP_BUSY:
|
||||||
|
case LDAP_UNAVAILABLE:
|
||||||
|
if ( do_retry > 0 ) {
|
||||||
|
ldap_unbind_ext( ld, NULL, NULL );
|
||||||
|
ld = NULL;
|
||||||
|
do_retry--;
|
||||||
|
if ( delay != 0 ) {
|
||||||
|
sleep( delay );
|
||||||
|
}
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
/* fallthru */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ldp = ld;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_random( LDAP *ld,
|
||||||
|
char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
|
||||||
|
int innerloop, int maxretries, int delay, int force, int chaserefs,
|
||||||
|
int idx )
|
||||||
|
{
|
||||||
|
int i = 0, do_retry = maxretries;
|
||||||
|
char *attrs[ 2 ];
|
||||||
|
int rc = LDAP_SUCCESS;
|
||||||
|
int nvalues = 0;
|
||||||
|
char **values = NULL;
|
||||||
|
LDAPMessage *res = NULL, *e = NULL;
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
attrs[ 0 ] = LDAP_NO_ATTRS;
|
||||||
|
attrs[ 1 ] = NULL;
|
||||||
|
|
||||||
|
snprintf( thrstr, BUFSIZ,
|
||||||
|
"Read(%d): base=\"%s\", filter=\"%s\".\n",
|
||||||
|
innerloop, sbase, filter );
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
|
||||||
|
rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
|
||||||
|
filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
|
||||||
|
switch ( rc ) {
|
||||||
|
case LDAP_SIZELIMIT_EXCEEDED:
|
||||||
|
case LDAP_TIMELIMIT_EXCEEDED:
|
||||||
|
case LDAP_SUCCESS:
|
||||||
|
nvalues = ldap_count_entries( ld, res );
|
||||||
|
if ( nvalues == 0 ) {
|
||||||
|
if ( rc ) {
|
||||||
|
tester_ldap_error( ld, "ldap_search_ext_s", NULL );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
values = malloc( ( nvalues + 1 ) * sizeof( char * ) );
|
||||||
|
for ( i = 0, e = ldap_first_entry( ld, res ); e != NULL; i++, e = ldap_next_entry( ld, e ) )
|
||||||
|
{
|
||||||
|
values[ i ] = ldap_get_dn( ld, e );
|
||||||
|
}
|
||||||
|
values[ i ] = NULL;
|
||||||
|
|
||||||
|
ldap_msgfree( res );
|
||||||
|
|
||||||
|
if ( do_retry == maxretries ) {
|
||||||
|
snprintf( thrstr, BUFSIZ,
|
||||||
|
"Read base=\"%s\" filter=\"%s\" got %d values.\n",
|
||||||
|
sbase, filter, nvalues );
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < innerloop; i++ ) {
|
||||||
|
int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
|
||||||
|
|
||||||
|
do_read( ld, values[ r ],
|
||||||
|
srchattrs, noattrs, nobind, 1, maxretries,
|
||||||
|
delay, force, chaserefs, idx );
|
||||||
|
}
|
||||||
|
for( i = 0; i < nvalues; i++) {
|
||||||
|
if (values[i] != NULL)
|
||||||
|
free( values[i] );
|
||||||
|
}
|
||||||
|
free( values );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
tester_ldap_error( ld, "ldap_search_ext_s", NULL );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( thrstr, BUFSIZ, "Search done (%d).\n", rc );
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_read( LDAP *ld, char *entry,
|
||||||
|
char **attrs, int noattrs, int nobind, int maxloop,
|
||||||
|
int maxretries, int delay, int force, int chaserefs, int idx )
|
||||||
|
{
|
||||||
|
int i = 0, do_retry = maxretries;
|
||||||
|
int rc = LDAP_SUCCESS;
|
||||||
|
char thrstr[BUFSIZ];
|
||||||
|
|
||||||
|
retry:;
|
||||||
|
if ( do_retry == maxretries ) {
|
||||||
|
snprintf( thrstr, BUFSIZ, "Read(%d): entry=\"%s\".\n",
|
||||||
|
maxloop, entry );
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(thrstr, BUFSIZ, "tid: %d LD %x cnt: %d (retried %d) (%s)", \
|
||||||
|
whoami(), ld, maxloop, (do_retry - maxretries), entry);
|
||||||
|
thread_verbose( thrstr );
|
||||||
|
|
||||||
|
for ( ; i < maxloop; i++ ) {
|
||||||
|
LDAPMessage *res = NULL;
|
||||||
|
|
||||||
|
rc = ldap_search_ext_s( ld, entry, LDAP_SCOPE_BASE,
|
||||||
|
NULL, attrs, noattrs, NULL, NULL, NULL,
|
||||||
|
LDAP_NO_LIMIT, &res );
|
||||||
|
if ( res != NULL ) {
|
||||||
|
ldap_msgfree( res );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rc == 0 ) {
|
||||||
|
rt_pass[idx]++;
|
||||||
|
} else {
|
||||||
|
int first = tester_ignore_err( rc );
|
||||||
|
char buf[ BUFSIZ ];
|
||||||
|
|
||||||
|
rt_fail[idx]++;
|
||||||
|
snprintf( buf, sizeof( buf ), "ldap_search_ext_s(%s)", entry );
|
||||||
|
|
||||||
|
/* if ignore.. */
|
||||||
|
if ( first ) {
|
||||||
|
/* only log if first occurrence */
|
||||||
|
if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
|
||||||
|
tester_ldap_error( ld, buf, NULL );
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* busy needs special handling */
|
||||||
|
tester_ldap_error( ld, buf, NULL );
|
||||||
|
if ( rc == LDAP_BUSY && do_retry > 0 ) {
|
||||||
|
do_retry--;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -192,6 +192,7 @@ LDAPCOMPARE="$CLIENTDIR/ldapcompare $TOOLARGS"
|
||||||
LDAPEXOP="$CLIENTDIR/ldapexop $TOOLARGS"
|
LDAPEXOP="$CLIENTDIR/ldapexop $TOOLARGS"
|
||||||
SLAPDTESTER=$PROGDIR/slapd-tester
|
SLAPDTESTER=$PROGDIR/slapd-tester
|
||||||
LDIFFILTER=$PROGDIR/ldif-filter
|
LDIFFILTER=$PROGDIR/ldif-filter
|
||||||
|
SLAPDMTREAD=$PROGDIR/slapd-mtread
|
||||||
LVL=${SLAPD_DEBUG-0x4105}
|
LVL=${SLAPD_DEBUG-0x4105}
|
||||||
LOCALHOST=localhost
|
LOCALHOST=localhost
|
||||||
BASEPORT=${SLAPD_BASEPORT-9010}
|
BASEPORT=${SLAPD_BASEPORT-9010}
|
||||||
|
|
@ -311,6 +312,8 @@ SLAVE2OUT=$SERVER3OUT
|
||||||
SLAVEFLT=$SERVER2FLT
|
SLAVEFLT=$SERVER2FLT
|
||||||
SLAVE2FLT=$SERVER3FLT
|
SLAVE2FLT=$SERVER3FLT
|
||||||
|
|
||||||
|
MTREADOUT=$TESTDIR/mtread.out
|
||||||
|
|
||||||
# original outputs for cmp
|
# original outputs for cmp
|
||||||
PROXYCACHEOUT=$DATADIR/proxycache.out
|
PROXYCACHEOUT=$DATADIR/proxycache.out
|
||||||
REFERRALOUT=$DATADIR/referrals.out
|
REFERRALOUT=$DATADIR/referrals.out
|
||||||
|
|
|
||||||
289
tests/scripts/test060-mt-hot
Executable file
289
tests/scripts/test060-mt-hot
Executable file
|
|
@ -0,0 +1,289 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# $OpenLDAP$
|
||||||
|
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
##
|
||||||
|
## Copyright 1998-2009 The OpenLDAP Foundation.
|
||||||
|
## All rights reserved.
|
||||||
|
##
|
||||||
|
## Redistribution and use in source and binary forms, with or without
|
||||||
|
## modification, are permitted only as authorized by the OpenLDAP
|
||||||
|
## Public License.
|
||||||
|
##
|
||||||
|
## A copy of this license is available in the file LICENSE in the
|
||||||
|
## top-level directory of the distribution or, alternatively, at
|
||||||
|
## <http://www.OpenLDAP.org/license.html>.
|
||||||
|
|
||||||
|
echo "running defines.sh"
|
||||||
|
. $SRCDIR/scripts/defines.sh
|
||||||
|
|
||||||
|
mkdir -p $TESTDIR $DBDIR1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Populate and start up slapd server with some random data
|
||||||
|
#
|
||||||
|
|
||||||
|
echo "Running slapadd to build slapd database..."
|
||||||
|
. $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
|
||||||
|
$SLAPADD -f $ADDCONF -l $LDIFORDERED
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapadd failed ($RC)!"
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running slapindex to index slapd database..."
|
||||||
|
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
||||||
|
$SLAPINDEX -f $CONF1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "warning: slapindex failed ($RC)"
|
||||||
|
echo " assuming no indexing support"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||||
|
echo $SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING
|
||||||
|
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||||
|
PID=$!
|
||||||
|
if test $WAIT != 0 ; then
|
||||||
|
echo PID $PID
|
||||||
|
read foo
|
||||||
|
fi
|
||||||
|
KILLPIDS="$PID"
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Perform a basic search, make sure of a functional setup
|
||||||
|
echo "Testing basic monitor search..."
|
||||||
|
for i in 0 1 2 3 4 5; do
|
||||||
|
$LDAPSEARCH -s base -b "$MONITORDN" -h $LOCALHOST -p $PORT1 \
|
||||||
|
'(objectclass=*)' > /dev/null 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC = 0 ; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo "Waiting 5 seconds for slapd to start..."
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "mt-hot read failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat /dev/null > $MTREADOUT
|
||||||
|
|
||||||
|
echo "Monitor searches"
|
||||||
|
# Perform a basic single threaded search on a single connection
|
||||||
|
THR=1
|
||||||
|
OUTER=1
|
||||||
|
INNER=50000
|
||||||
|
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a basic multi-threaded search on a single connection
|
||||||
|
THR=5
|
||||||
|
OUTER=1
|
||||||
|
INNER=10000
|
||||||
|
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a basic multi-threaded search on a single connection
|
||||||
|
THR=100
|
||||||
|
OUTER=5
|
||||||
|
INNER=100
|
||||||
|
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a single threaded random DB search on a single connection
|
||||||
|
echo "Random searches"
|
||||||
|
THR=1
|
||||||
|
OUTER=1
|
||||||
|
INNER=50000
|
||||||
|
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a multi-threaded random DB search on a single connection
|
||||||
|
THR=5
|
||||||
|
OUTER=1
|
||||||
|
INNER=10000
|
||||||
|
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a multi-threaded random DB search on a single connection
|
||||||
|
THR=100
|
||||||
|
OUTER=5
|
||||||
|
INNER=100
|
||||||
|
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a basic multi-threaded search using multiple connections
|
||||||
|
echo "Multiple threads and connection searches"
|
||||||
|
CONN=5
|
||||||
|
THR=5
|
||||||
|
OUTER=1
|
||||||
|
INNER=10000
|
||||||
|
echo "Testing basic mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a basic multi-threaded search using multiple connections
|
||||||
|
CONN=5
|
||||||
|
THR=50
|
||||||
|
OUTER=5
|
||||||
|
INNER=1000
|
||||||
|
echo "Testing basic mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a multi-threaded random DB search using multiple connections
|
||||||
|
CONN=5
|
||||||
|
THR=100
|
||||||
|
OUTER=5
|
||||||
|
INNER=100
|
||||||
|
echo "Testing random mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(objectclass=*)" \
|
||||||
|
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a multi-threaded random reads and writes using single connection
|
||||||
|
CONN=1
|
||||||
|
THR=10
|
||||||
|
WTHR=10
|
||||||
|
OUTER=5
|
||||||
|
INNER=100
|
||||||
|
echo "Testing random mt-hot r/w search: $THR read threads $WTHR write threads $CONN conns ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||||
|
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||||
|
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform a multi-threaded random reads and writes using multiple connections
|
||||||
|
CONN=5
|
||||||
|
THR=10
|
||||||
|
WTHR=10
|
||||||
|
OUTER=5
|
||||||
|
INNER=100
|
||||||
|
echo "Testing random mt-hot r/w search: $THR read threads $WTHR write threads $CONN conns ($OUTER x $INNER) loops..."
|
||||||
|
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||||
|
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER
|
||||||
|
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||||
|
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||||
|
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||||
|
RC=$?
|
||||||
|
if test $RC != 0 ; then
|
||||||
|
echo "slapd-mtread failed ($RC)!"
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
exit $RC
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
|
||||||
|
echo ">>>>> Test succeeded"
|
||||||
|
|
||||||
|
exit 0
|
||||||
Loading…
Reference in a new issue