]> git.sur5r.net Git - openldap/commitdiff
Add draft 3 of the C API spec.
authorKurt Zeilenga <kurt@openldap.org>
Sat, 12 Jun 1999 21:28:24 +0000 (21:28 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Sat, 12 Jun 1999 21:28:24 +0000 (21:28 +0000)
doc/drafts/draft-ietf-ldapext-ldap-c-api-03.txt [new file with mode: 0644]

diff --git a/doc/drafts/draft-ietf-ldapext-ldap-c-api-03.txt b/doc/drafts/draft-ietf-ldapext-ldap-c-api-03.txt
new file mode 100644 (file)
index 0000000..6fd89dd
--- /dev/null
@@ -0,0 +1,4443 @@
+Network Working Group                                   M. Smith, Editor
+INTERNET-DRAFT                             Netscape Communications Corp.
+Intended Category: Standards Track                              T. Howes
+Obsoletes: RFC 1823                        Netscape Communications Corp.
+Expires: 2 December 1999                                       A. Herron
+                                                         Microsoft Corp.
+                                                                 M. Wahl
+                                            Innosoft International, Inc.
+                                                              A. Anantha
+                                                         Microsoft Corp.
+
+
+                                                             2 June 1999
+
+                The C LDAP Application Program Interface
+                 <draft-ietf-ldapext-ldap-c-api-03.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.  Internet-Drafts are working docu-
+ments 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.
+
+This draft document will be submitted to the RFC Editor as a Standards
+Track document. Distribution of this memo is unlimited.  Technical dis-
+cussion 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 authors.
+
+Copyright (C) The Internet Society (1997-1999). All Rights Reserved.
+
+Please see the Copyright section near the end of this document for more
+information.
+
+
+
+
+Expires: 2 December 1999                                        [Page 1]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+2.  Introduction
+
+This document defines a C language application program interface (API)
+to the Lightweight Directory Access Protocol (LDAP). This document
+replaces the previous definition of this API, defined in RFC 1823,
+updating it to include support for features found in version 3 of the
+LDAP protocol.  New extended operation functions were added to support
+LDAPv3 features such as controls.  In addition, other LDAP API changes
+were made to support information hiding and thread safety.
+
+The C LDAP API is designed to be powerful, yet simple to use. It defines
+compatible synchronous and asynchronous interfaces to LDAP to suit a
+wide variety of applications. This document gives a brief overview of
+the LDAP model, then an overview of how the API is used by an applica-
+tion program to obtain LDAP information.  The API calls are described in
+detail, followed by appendices that provide example code demonstrating
+use of the API, the namespace consumed by the API, a summary of require-
+ments for API extensions, known incompatibilities with RFC 1823, and a
+list of changes made since the last revision of this document.
+
+
+3.  Table of Contents
+
+1.     Status of this Memo............................................1
+2.     Introduction...................................................2
+3.     Table of Contents..............................................2
+4.     Overview of the LDAP Model.....................................4
+5.     Overview of LDAP API Use.......................................4
+6.     Header File Requirements.......................................6
+7.     Common Data Structures.........................................7
+8.     Retrieving Information About the API Implementation............8
+8.1.      Retrieving Information at Compile Time......................9
+8.2.      Retrieving Information During Execution.....................10
+9.     LDAP Error Codes...............................................13
+10.    Performing LDAP Operations.....................................14
+10.1.     Initializing an LDAP Session................................14
+10.2.     LDAP Session Handle Options.................................15
+10.3.     Working With Controls.......................................20
+10.3.1.      A Client Control That Governs Referral Processing........22
+10.4.     Authenticating to the directory.............................22
+10.5.     Closing the session.........................................25
+10.6.     Searching...................................................26
+10.7.     Reading an Entry............................................29
+10.8.     Listing the Children of an Entry............................30
+10.9.     Comparing a Value Against an Entry..........................30
+10.10.    Modifying an entry..........................................32
+10.11.    Modifying the Name of an Entry..............................34
+10.12.    Adding an entry.............................................36
+
+
+
+Expires: 2 December 1999                                        [Page 2]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+10.13.    Deleting an entry...........................................38
+10.14.    Extended Operations.........................................39
+11.    Abandoning An Operation........................................41
+12.    Obtaining Results and Peeking Inside LDAP Messages.............42
+13.    Handling Errors and Parsing Results............................44
+14.    Stepping Through a List of Results.............................46
+15.    Parsing Search Results.........................................47
+15.1.     Stepping Through a List of Entries or References............48
+15.2.     Stepping Through the Attributes of an Entry.................49
+15.3.     Retrieving the Values of an Attribute.......................50
+15.4.     Retrieving the name of an entry.............................51
+15.5.     Retrieving controls from an entry...........................52
+15.6.     Parsing References..........................................53
+16.    Encoded ASN.1 Value Manipulation...............................54
+16.1.     General.....................................................54
+16.2.     Encoding....................................................55
+16.3.     Encoding Example............................................58
+16.4.     Decoding....................................................59
+16.5.     Decoding Example............................................61
+17.    Security Considerations........................................64
+18.    Acknowledgements...............................................64
+19.    Copyright......................................................64
+20.    Bibliography...................................................65
+21.    Authors' Addresses.............................................66
+22.    Appendix A - Sample C LDAP API Code............................66
+23.    Appendix B - Namespace Consumed By This Specification..........68
+24.    Appendix C - Summary of Requirements for API Extensions........68
+24.1.     Compatibility...............................................69
+24.2.     Style.......................................................69
+24.3.     Dependence on Externally Defined Types......................69
+24.4.     Compile Time Information....................................69
+24.5.     Runtime Information.........................................69
+24.6.     Values Used for Session Handle Options......................70
+25.    Appendix D - Known Incompatibilities with RFC 1823.............70
+25.1.     Opaque LDAP Structure.......................................70
+25.2.     Additional Error Codes......................................70
+25.3.     Freeing of String Data with ldap_memfree()..................71
+25.4.     Changes to ldap_result()....................................71
+25.5.     Changes to ldap_first_attribute() and ldap_next_attribute...71
+25.6.     Changes to ldap_modrdn() and ldap_modrdn_s() Functions......71
+25.7.     Changes to the berval structure.............................71
+25.8.     API Specification Clarified.................................72
+25.9.     Deprecated Functions........................................72
+26.    Appendix E - Data Types and Legacy Implementations.............72
+27.    Appendix F - Changes Made Since Last Document Revision.........73
+27.1.     API Changes.................................................73
+27.2.     Editorial Changes...........................................74
+28.    Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api-.74
+28.1.     API Changes.................................................74
+28.2.     Editorial changes...........................................75
+
+Expires: 2 December 1999                                        [Page 3]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+4.  Overview of the LDAP Model
+
+LDAP is the lightweight directory access protocol, described in [2] and
+[6]. It can provide a lightweight frontend to the X.500 directory [1],
+or a stand-alone service. In either mode, LDAP is based on a client-
+server model in which a client makes a TCP connection to an LDAP server,
+over which it sends requests and receives responses.
+
+The LDAP information model is based on the entry, which contains infor-
+mation about some object (e.g., a person).  Entries are composed of
+attributes, which have a type and one or more values. Each attribute has
+a syntax that determines what kinds of values are allowed in the attri-
+bute (e.g., ASCII characters, a jpeg photograph, etc.) and how those
+values behave during directory operations (e.g., is case significant
+during comparisons).
+
+Entries may be organized in a tree structure, usually based on politi-
+cal, geographical, and organizational boundaries. Each entry is uniquely
+named relative to its sibling entries by its relative distinguished name
+(RDN) consisting of one or more distinguished attribute values from the
+entry.  At most one value from each attribute may be used in the RDN.
+For example, the entry for the person Babs Jensen might be named with
+the "Barbara Jensen" value from the commonName attribute.
+
+A globally unique name for an entry, called a distinguished name or DN,
+is constructed by concatenating the sequence of RDNs from the entry up
+to the root of the tree. For example, if Babs worked for the University
+of Michigan, the DN of her U-M entry might be "cn=Barbara Jensen,
+o=University of Michigan, c=US". The DN format used by LDAP is defined
+in [4].
+
+Operations are provided to authenticate, search for and retrieve infor-
+mation, modify information, and add and delete entries from the tree.
+The next sections give an overview of how the API is used and detailed
+descriptions of the LDAP API calls that implement all of these func-
+tions.
+
+
+5.  Overview of LDAP API Use
+
+An application generally uses the C LDAP API in four simple steps.
+
+   1.   Initialize an LDAP session with a primary LDAP server. The
+        ldap_init() function returns a handle to the session, allowing
+        multiple connections to be open at once.
+
+   2.   Authenticate to the LDAP server. The ldap_sasl_bind() function
+        and friends support a variety of authentication methods.
+
+
+
+Expires: 2 December 1999                                        [Page 4]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   3.   Perform some LDAP operations and obtain some results.
+        ldap_search() and friends return results which can be parsed by
+        ldap_parse_result(), ldap_first_entry(), ldap_next_entry(), etc.
+
+   4.   Close the session. The ldap_unbind() function closes the connec-
+        tion.
+
+Operations can be performed either synchronously or asynchronously.  The
+names of the synchronous functions end in _s. For example, a synchronous
+search can be completed by calling ldap_search_s(). An asynchronous
+search can be initiated by calling ldap_search(). All synchronous rou-
+tines return an indication of the outcome of the operation (e.g, the
+constant LDAP_SUCCESS or some other error code).  The asynchronous rou-
+tines make available to the caller the message id of the operation ini-
+tiated. This id can be used in subsequent calls to ldap_result() to
+obtain the result(s) of the operation. An asynchronous operation can be
+abandoned by calling ldap_abandon() or ldap_abandon_ext().
+
+Results and errors are returned in an opaque structure called LDAPMes-
+sage.  Routines are provided to parse this structure, step through
+entries and attributes returned, etc. Routines are also provided to
+interpret errors. Later sections of this document describe these rou-
+tines in more detail.
+
+LDAP version 3 servers may return referrals and references to other
+servers.  By default, implementations of this API will attempt to follow
+referrals automatically for the application.  This behavior can be dis-
+abled globally (using the ldap_set_option() call) or on a per-request
+basis through the use of a client control.
+
+All DN and string attribute values passed into or produced by this C
+LDAP API are represented using the character set of the underlying LDAP
+protocol version in use.  When this API is used with LDAPv3, DN and
+string values are represented as UTF-8[10] characters.  When this API is
+used with LDAPv2, the US-ASCII[12] or T.61[12] character set are used.
+Future documents may specific additional APIs supporting other character
+sets.
+
+For compatibility with existing applications, implementations of this
+API will by default use version 2 of the LDAP protocol.  Applications
+that intend to take advantage of LDAP version 3 features will need to
+use the ldap_set_option() call with a LDAP_OPT_PROTOCOL_VERSION to
+switch to version 3.
+
+Note that this API is designed for use in environments where the 'int'
+type is at least 32 bits in size.
+
+
+
+
+
+Expires: 2 December 1999                                        [Page 5]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+6.  Header File Requirements
+
+To promote portability of applications, implementations of this C LDAP
+API must conform to the following requirements of the header files used
+by applications to access the services of this API:
+
+Name and Inclusion
+        Applications are only required to include a single header file
+        named ldap.h to access all of the API services described in this
+        document.  Therefore, the following C source program must com-
+        pile without errors:
+
+           #include <ldap.h>
+
+           int
+           main()
+           {
+               return 0;
+           }
+
+        Note that it is permissible for the ldap.h header file to
+        include other implementation-specific header files.
+
+Implementations SHOULD also provide a header file named lber.h to faci-
+late development of applications desiring compatibility with older LDAP
+implementations.  The lber.h header file may be empty.
+
+
+Idempotence
+        All header files should be idempotent; that is, if they are
+        included more than once the effect is as if they had only been
+        included once.
+
+Must Be Included Before API Is Used
+        An application must include the ldap.h header file before
+        referencing any of the function or type definitions described in
+        this API specification.
+
+Mutual Independence
+        If possible, header files should be mutually independent with
+        minimal dependence on system or any other header files.
+
+Use of the 'const' Keyword
+        This API specification is defined in terms of ISO C[13].  It
+        makes use of function prototypes and the 'const' keyword.  The
+        use of 'const' in this specification is limited to simple, non-
+        array function parameters to avoid forcing applications to
+        declare parameters and variables that accept return values from
+
+
+
+Expires: 2 December 1999                                        [Page 6]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+        LDAP API functions as 'const.'  Implementations specifically
+        designed to be used with non-ISO C translators may provide func-
+        tion declarations without prototypes or function prototypes
+        without specification of 'const' arguments.
+
+Definition of 'struct timeval'
+        This API specification uses the 'struct timeval' type.  Imple-
+        mentations of this API should ensure that the struct timeval
+        type is by default defined as a consequence of including the
+        ldap.h header file.  Because struct timeval is usually defined
+        in one or more system header files, it is possible for header
+        file conflicts to occur if ldap.h also defines it or arranges
+        for it to be defined by including another header file.  There-
+        fore, applications may want to arrange for struct timeval to be
+        defined before they include ldap.h.  To support this, the ldap.h
+        header file must not itself define struct timeval if the prepro-
+        cessor symbol LDAP_TYPE_TIMEVAL_DEFINED is defined before ldap.h
+        is included.
+
+
+7.  Common Data Structures
+
+Some data structures that are common to several LDAP API functions are
+defined here:
+
+       typedef struct ldap LDAP;
+
+       typedef struct ldapmsg LDAPMessage;
+
+       typedef struct berelement BerElement;
+
+       typedef ber_len_t;  /* actual definition is implementation-specific */
+
+       typedef ber_tag_t;  /* actual definition is implementation-specific */
+
+       struct berval {
+           ber_len_t       bv_len;
+           char            *bv_val;
+       };
+
+       struct timeval {
+               long        tv_sec;
+               long        tv_usec;
+       };
+
+The LDAP structure is an opaque data type that represents an LDAP ses-
+sion Typically this corresponds to a connection to a single server, but
+it may encompass several server connections in the face of LDAPv3
+
+
+
+Expires: 2 December 1999                                        [Page 7]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+referrals.
+
+The LDAPMessage structure is an opaque data type that is used to return
+entry, reference, result, and error information.  An LDAPMessage struc-
+ture may represent the beginning of a list, or chain of messages that
+consists of a series of entries, references, and result messages as
+returned by LDAP operations such as search.  LDAP API functions such as
+ldap_parse_result() that operate on message chains that may contain more
+than one result message always operate on the first result message in
+the chain.  See the "Obtaining Results and Peeking Inside LDAP Messages"
+section of this document for more information.
+
+The BerElement structure is an opaque data type that is used to hold
+data and state information about encoded data.  It is described in more
+detail in the section "Encoded ASN.1 Value Manipulation" later in this
+document.
+
+The ber_len_t type is an unsigned integral data type that is large
+enough to contain the length of the largest piece of data supported by
+the API implementation.  Similarly, the ber_tag_t type is an unsigned
+integral data type that is large enough to hold the largest BER tag sup-
+ported by the API implementation.  Both of these types should be at
+least 32 bits in size.  See the appendix "Data Types and Legacy Imple-
+mentations" for additional considerations.
+
+The berval structure is used to represent arbitrary binary data and its
+fields have the following meanings:
+
+bv_len   Length of data in bytes.
+
+bv_val   A pointer to the data itself.
+
+
+The timeval structure is used to represent an interval of time and its
+fields have the following meanings:
+
+tv_sec   Seconds component of time interval.
+
+tv_usec  Microseconds component of time interval.
+
+See the earlier section "Header File Requirements" for more information
+on struct timeval.
+
+
+8.  Retrieving Information About the API Implementation
+
+Applications developed to this specification need to be able to deter-
+mine information about the particular API implementation they are using
+
+
+
+Expires: 2 December 1999                                        [Page 8]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+both at compile time and during execution.
+
+
+8.1.  Retrieving Information at Compile Time
+
+All conformant implementations MUST include the following five defini-
+tions in a header file so compile time tests can be done by LDAP
+software developers:
+
+   #define LDAP_API_VERSION     level
+   #define LDAP_VERSION_MIN     min-version
+   #define LDAP_VERSION_MAX     max-version
+   #define LDAP_VENDOR_NAME     "vend-name"
+   #define LDAP_VENDOR_VERSION  vend-version
+
+where:
+
+     "level" is replaced with the RFC number given to this C LDAP API
+     specification when it is published as a standards track RFC.
+
+     min-version is replaced with the lowest LDAP protocol version sup-
+     ported by the implementation.
+
+     max-version is replaced with the highest LDAP protocol version sup-
+     ported by the implementation.  This should be 3.
+
+     "vend-name" is replaced with a text string that identifies the
+     party that supplies the API implementation.
+
+     "vend-version" is a supplier-specific version number multiplied
+     times 100.
+
+Note that the LDAP_VENDOR_NAME macro may be defined as "" if no vendor
+name is available and the LDAP_VENDOR_VERSION macro may be defined as 0
+if no vendor-specific version information is available.
+
+For example, if this specification is published as RFC 88888, Netscape
+Communication's version 4.0 implementation that supports LDAPv2 and v3
+might include macro definitions like these:
+
+   #define LDAP_API_VERSION     88888      /* RFC 88888 compliant */
+   #define LDAP_VERSION_MIN     2
+   #define LDAP_VERSION_MAX     3
+   #define LDAP_VENDOR_NAME     "Netscape Communications Corp."
+   #define LDAP_VENDOR_VERSION  400        /* version 4.0 */
+
+and application code can test the C LDAP API version level using a
+construct such as this one:
+
+
+
+Expires: 2 December 1999                                        [Page 9]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   #if (LDAP_API_VERSION >= 88888)
+           /* use features supported in RFC 88888 or later */
+   #endif
+
+Until such time as this document is published as an RFC, implementations
+should use the value 2000 plus the revision number of this draft for
+LDAP_API_VERSION.  For example, the correct value for LDAP_API_VERSION
+for revision 03 of this draft is 2003.
+
+Documents that extend this specification SHOULD define a macro of the
+form:
+
+   #define LDAP_API_FEATURE_x level
+
+where "x" is replaced with a name (textual identifier) for the feature
+and "level" is replaced with the number of the RFC that specifies the
+API extension.  The name SHOULD NOT begin with the string "X_".
+
+For example, if C LDAP API extensions for Transport Layer Security [9]
+were published in RFC 99999, that RFC might require conformant implemen-
+tations to define a macro like this:
+
+   #define LDAP_API_FEATURE_TLS 99999
+
+
+Private or experimental API extensions may be indicated by defining a
+macro of this same form where "x" (the extension's name) begins with the
+string "X_" and "level" is replaced with a integer number that is
+specific to the extension.
+
+
+8.2.  Retrieving Information During Execution
+
+The ldap_get_option() call (described in greater detail later in this
+document) can be used during execution in conjunction with an option
+parameter value of LDAP_OPT_API_INFO (0x00) to retrieve some basic
+information about the API and about the specific implementation being
+used.  The ld parameter to ldap_get_option() can be either NULL or a
+valid LDAP session handle which was obtained by calling ldap_init().
+The optdata parameter to ldap_get_option() MUST be the address of an
+LDAPAPIInfo structure which is defined as follows:
+
+   typedef struct ldapapiinfo {
+       int  ldapai_info_version;     /* version of this struct (1) */
+       int  ldapai_api_version;      /* revision of API supported */
+       int  ldapai_protocol_version; /* highest LDAP version supported */
+       char **ldapai_extensions;     /* names of API extensions */
+       char *ldapai_vendor_name;     /* name of supplier */
+
+
+
+Expires: 2 December 1999                                       [Page 10]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+       int  ldapai_vendor_version;   /* supplier-specific version times 100 */
+   } LDAPAPIInfo;
+
+In addition, API implementations MUST include the following macro defin-
+ition:
+
+   #define LDAP_API_INFO_VERSION    1
+
+Note that the ldapai_info_version field of the LDAPAPIInfo structure
+should be set to the value LDAP_API_INFO_VERSION (1) before calling
+ldap_get_option() so that it can be checked for consistency.  All other
+fields are set by the ldap_get_option() function.
+
+The members of the LDAPAPIInfo structure are:
+
+ldapai_info_version
+          A number that identifies the version of the LDAPAPIInfo struc-
+          ture.  This should be set to the value LDAP_API_INFO_VERSION
+          (1) before calling ldap_get_option().  If the value received
+          is not recognized by the API implementation, the
+          ldap_get_option() function sets ldapai_info_version to a valid
+          value that would be recognized, sets the ldapai_api_version to
+          the correct value, and returns an error without filling in any
+          of the other fields in the LDAPAPIInfo structure.
+
+ldapai_api_version
+          A number that matches that assigned to the C LDAP API RFC sup-
+          ported by the API implementation.  This should match the value
+          of the LDAP_API_VERSION macro defined earlier.
+
+ldapai_protocol_version
+          The highest LDAP protocol version supported by the implementa-
+          tion.  For example, if LDAPv3 is the highest version supported
+          then this field will be set to 3.
+
+ldapai_extensions
+          A NULL-terminated array of character strings that lists the
+          names of the API extensions supported by the LDAP API imple-
+          mentation.  These names will typically match the textual iden-
+          tifiers that appear in the "x" portion of the
+          LDAP_API_FEATURE_x macros described above, although the pre-
+          cise value MUST be defined by documents that specify C LDAP
+          API extensions.  If no API extensions are supported, this
+          field will be set to NULL.  The caller is responsible for
+          disposing of the memory occupied by this array by passing it
+          to ldap_value_free() which is described later in this docu-
+          ment.  To retrieve more information about a particular exten-
+          sion, the ldap_get_option() call can be used with an option
+
+
+
+Expires: 2 December 1999                                       [Page 11]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+          parameter value of LDAP_OPT_API_FEATURE_INFO (0x15).  The opt-
+          data parameter to the ldap_get_option() MUST be the address of
+          an LDAPAPIFeatureInfo structure which is defined as follows:
+
+             typedef struct ldap_apifeature_info {
+                 int   ldapaif_info_version; /* version of this struct (1) */
+                 char  *ldapaif_name;        /* name of supported feature */
+                 int   ldapaif_version;      /* revision of supported feature */
+             } LDAPAPIFeatureInfo;
+
+          In addition, API implementations MUST include the following
+          macro definition:
+
+             #define LDAP_FEATURE_INFO_VERSION    1
+
+          Note that the ldapaif_info_version field of the LDAPAPI-
+          FeatureInfo structure should be set to the value
+          LDAP_FEATURE_INFO_VERSION (1) and the ldapaif_name field
+          should be set to the extension name string as described below
+          before ldap_get_option() is called.  The call will fill in the
+          ldapaif_version field of the LDAPAPIFeatureInfo structure.
+
+   The members of the LDAPAPIFeatureInfo structure are:
+
+   ldapaif_info_version
+             A number that identifies the version of the LDAPAPI-
+             FeatureInfo structure.  This should be set to the value
+             LDAP_FEATURE_INFO_VERSION (1) before calling
+             ldap_get_option().  If the value received is not recognized
+             by the API implementation, the ldap_get_option() function
+             sets ldapaif_info_version to a valid value that would be
+             recognized and returns an error without filling in the
+             ldapaif_version field in the LDAPAPIFeatureInfo structure.
+
+   ldapaif_name
+             The name of an extension, as returned in the
+             ldapai_extensions array of the LDAPAPIInfo structure and as
+             specified in the document that describes the extension.
+
+   ldapaif_version
+             This field will be set as a result of calling
+             ldap_get_option().  It is a number that matches that
+             assigned to the C LDAP API extension RFC supported for this
+             extension.  For private or experimental API extensions, the
+             value is extension-specific.  In either case, the value of
+             ldapaxi_ext_version should be identical to the value of the
+             LDAP_API_FEATURE_x macro defined for the extension
+             (described above).
+
+
+
+Expires: 2 December 1999                                       [Page 12]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+9.  LDAP Error Codes
+
+Many of the LDAP API routines return LDAP error codes, some of which
+indicate local errors and some of which may be returned by servers.  All
+of the LDAP error codes returned will be positive integers.  Supported
+error codes are (hexadecimal values are given in parentheses after the
+constant):
+
+           LDAP_SUCCESS (0x00)
+           LDAP_OPERATIONS_ERROR (0x01)
+           LDAP_PROTOCOL_ERROR (0x02)
+           LDAP_TIMELIMIT_EXCEEDED (0x03)
+           LDAP_SIZELIMIT_EXCEEDED (0x04)
+           LDAP_COMPARE_FALSE (0x05)
+           LDAP_COMPARE_TRUE (0x06)
+           LDAP_STRONG_AUTH_NOT_SUPPORTED (0x07)
+           LDAP_STRONG_AUTH_REQUIRED (0x08)
+           LDAP_REFERRAL (0x0a)                            -- new in LDAPv3
+           LDAP_ADMINLIMIT_EXCEEDED (0x0b)                 -- new in LDAPv3
+           LDAP_UNAVAILABLE_CRITICAL_EXTENSION (0x0c)      -- new in LDAPv3
+           LDAP_CONFIDENTIALITY_REQUIRED (0x0d)            -- new in LDAPv3
+           LDAP_SASL_BIND_IN_PROGRESS (0x0e)               -- new in LDAPv3
+           LDAP_NO_SUCH_ATTRIBUTE (0x10)
+           LDAP_UNDEFINED_TYPE (0x11)
+           LDAP_INAPPROPRIATE_MATCHING (0x12)
+           LDAP_CONSTRAINT_VIOLATION (0x13)
+           LDAP_TYPE_OR_VALUE_EXISTS (0x14)
+           LDAP_INVALID_SYNTAX (0x15)
+           LDAP_NO_SUCH_OBJECT (0x20)
+           LDAP_ALIAS_PROBLEM (0x21)
+           LDAP_INVALID_DN_SYNTAX (0x22)
+           LDAP_IS_LEAF (0x23)                             -- not used in LDAPv3
+           LDAP_ALIAS_DEREF_PROBLEM (0x24)
+           LDAP_INAPPROPRIATE_AUTH (0x30)
+           LDAP_INVALID_CREDENTIALS (0x31)
+           LDAP_INSUFFICIENT_ACCESS (0x32)
+           LDAP_BUSY (0x33)
+           LDAP_UNAVAILABLE (0x34)
+           LDAP_UNWILLING_TO_PERFORM (0x35)
+           LDAP_LOOP_DETECT (0x36)
+           LDAP_NAMING_VIOLATION (0x40)
+           LDAP_OBJECT_CLASS_VIOLATION (0x41)
+           LDAP_NOT_ALLOWED_ON_NONLEAF (0x42)
+           LDAP_NOT_ALLOWED_ON_RDN (0x43)
+           LDAP_ALREADY_EXISTS (0x44)
+           LDAP_NO_OBJECT_CLASS_MODS (0x45)
+           LDAP_RESULTS_TOO_LARGE (0x46)                   -- reserved for CLDAP
+           LDAP_AFFECTS_MULTIPLE_DSAS (0x47)               -- new in LDAPv3
+
+
+
+Expires: 2 December 1999                                       [Page 13]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+           LDAP_OTHER (0x50)
+           LDAP_SERVER_DOWN (0x51)
+           LDAP_LOCAL_ERROR (0x52)
+           LDAP_ENCODING_ERROR (0x53)
+           LDAP_DECODING_ERROR (0x54)
+           LDAP_TIMEOUT (0x55)
+           LDAP_AUTH_UNKNOWN (0x56)
+           LDAP_FILTER_ERROR (0x57)
+           LDAP_USER_CANCELLED (0x58)
+           LDAP_PARAM_ERROR (0x59)
+           LDAP_NO_MEMORY (0x5a)
+           LDAP_CONNECT_ERROR (0x5b)
+           LDAP_NOT_SUPPORTED (0x5c)
+           LDAP_CONTROL_NOT_FOUND (0x5d)
+           LDAP_NO_RESULTS_RETURNED (0x5e)
+           LDAP_MORE_RESULTS_TO_RETURN (0x5f)
+           LDAP_CLIENT_LOOP (0x60)
+           LDAP_REFERRAL_LIMIT_EXCEEDED (0x61)
+
+
+10.  Performing LDAP Operations
+
+This section describes each LDAP operation API call in detail. All func-
+tions take a "session handle," a pointer to an LDAP structure containing
+per-connection information.  Many routines return results in an LDAPMes-
+sage structure. These structures and others are described as needed
+below.
+
+
+10.1.  Initializing an LDAP Session
+
+ldap_init() initializes a session with an LDAP server. The server is not
+actually contacted until an operation is performed that requires it,
+allowing various options to be set after initialization.
+
+        LDAP *ldap_init(
+                const char      *hostname,
+                int             portno
+        );
+
+Use of the following routine is deprecated:
+
+        LDAP *ldap_open(
+                const char      *hostname,
+                int             portno
+        );
+Unlike ldap_init(), ldap_open() attempts to make a server connection
+before returning to the caller.
+
+
+
+Expires: 2 December 1999                                       [Page 14]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+Parameters are:
+
+hostname Contains a space-separated list of hostnames or dotted strings
+         representing the IP address of hosts running an LDAP server to
+         connect to. Each hostname in the list can include an optional
+         port number which is separated from the host itself with a
+         colon (:) character.  The hosts will be tried in the order
+         listed, stopping with the first one to which a successful con-
+         nection is made.
+
+   Note: A suitable representation for including a literal IPv6[11]
+   address in the hostname parameter is desired, but has not yet been
+   determined or implemented in practice.
+
+portno   Contains the TCP port number to connect to. The default LDAP
+         port of 389 can be obtained by supplying the constant
+         LDAP_PORT.  If a host includes a port number then this parame-
+         ter is ignored.
+
+ldap_init() and ldap_open() both return a "session handle," a pointer to
+an opaque structure that should be passed to subsequent calls pertaining
+to the session. These routines return NULL if the session cannot be ini-
+tialized in which case the operating system error reporting mechanism
+can be checked to see why the call failed.
+
+Note that if you connect to an LDAPv2 server, one of the LDAP bind calls
+described below must be completed before other operations can be per-
+formed on the session.  LDAPv3 does not require that a bind operation be
+completed before other operations can be performed.
+
+The calling program can set various attributes of the session by calling
+the routines described in the next section.
+
+
+10.2.  LDAP Session Handle Options
+
+The LDAP session handle returned by ldap_init() is a pointer to an
+opaque data type representing an LDAP session. In RFC 1823 this data
+type was a structure exposed to the caller, and various fields in the
+structure could be set to control aspects of the session, such as size
+and time limits on searches.
+
+In the interest of insulating callers from inevitable changes to this
+structure, these aspects of the session are now accessed through a pair
+of accessor functions, described below.
+
+ldap_get_option() is used to access the current value of various
+session-wide parameters. ldap_set_option() is used to set the value of
+
+
+
+Expires: 2 December 1999                                       [Page 15]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+these parameters.  Note that some options are READ-ONLY and cannot be
+set; it is an error to call ldap_set_option() and attempt to set a
+READ-ONLY option.
+
+Note that if automatic referral following is enabled (the default), any
+connections created during the course of following referrals will
+inherit the options associated with the session that sent the original
+request that caused the referrals to be returned.
+
+           int ldap_get_option(
+                   LDAP            *ld,
+                   int             option,
+                   void            *outvalue
+           );
+
+           int ldap_set_option(
+                   LDAP            *ld,
+                   int             option,
+                   const void      *invalue
+           );
+
+           #define LDAP_OPT_ON     ((void *)1)
+           #define LDAP_OPT_OFF    ((void *)0)
+
+
+Parameters are:
+
+ld     The session handle.  If this is NULL, a set of global defaults is
+       accessed.  New LDAP session handles created with ldap_init() or
+       ldap_open() inherit their characteristics from these global
+       defaults.
+
+option The name of the option being accessed or set. This parameter
+       should be one of the following constants, which have the indi-
+       cated meanings.  After the constant the actual hexadecimal value
+       of the constant is listed in parentheses.
+
+
+   LDAP_OPT_API_INFO (0x00)
+      Type for invalue parameter: not applicable (option is READ-ONLY)
+
+      Type for outvalue parameter: LDAPAPIInfo *
+
+      Description:
+           Used to retrieve some basic information about the LDAP API
+           implementation at execution time.  See the section "Retriev-
+           ing Information About the API Implementation" above for more
+           information.  This option is READ-ONLY and cannot be set.
+
+
+
+Expires: 2 December 1999                                       [Page 16]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+      LDAP_OPT_DESC (0x01)
+         Type for invalue parameter: not applicable (option is READ-
+         ONLY)
+
+         Type for outvalue parameter: int *
+
+         Description:
+              The underlying socket descriptor corresponding to the pri-
+              mary LDAP connection.  This option is READ-ONLY and cannot
+              be set.
+
+      LDAP_OPT_DEREF (0x02)
+         Type for invalue parameter: int *
+
+         Type for outvalue parameter: int *
+
+         Description:
+              Determines how aliases are handled during search. It can
+              have one of the following values: LDAP_DEREF_NEVER (0x00),
+              LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or
+              LDAP_DEREF_ALWAYS (0x03).  The LDAP_DEREF_SEARCHING value
+              means aliases should be dereferenced during the search but
+              not when locating the base object of the search. The
+              LDAP_DEREF_FINDING value means aliases should be derefer-
+              enced when locating the base object but not during the
+              search.
+
+      LDAP_OPT_SIZELIMIT (0x03)
+         Type for invalue parameter: int *
+
+         Type for outvalue parameter: int *
+
+         Description:
+              A limit on the number of entries to return from a search.
+              A value of LDAP_NO_LIMIT (0) means no limit.
+
+      LDAP_OPT_TIMELIMIT (0x04)
+         Type for invalue parameter: int *
+
+         Type for outvalue parameter: int *
+
+         Description:
+              A limit on the number of seconds to spend on a search. A
+              value of LDAP_NO_LIMIT (0) means no limit.  This value is
+              passed to the server in the search request only; it does
+              not affect how long the C LDAP API implementation itself
+              will wait locally for search results.  The timeout parame-
+              ter passed to ldap_search_ext_s() or ldap_result() -- both
+
+
+
+Expires: 2 December 1999                                       [Page 17]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+              of which are described later in this document -- can be
+              used to specify both a local and server side time limit.
+
+      LDAP_OPT_REFERRALS (0x08)
+         Type for invalue parameter: void * (LDAP_OPT_ON or
+         LDAP_OPT_OFF)
+
+         Type for outvalue parameter: int *
+
+         Description:
+              Determines whether the LDAP library automatically follows
+              referrals returned by LDAP servers or not. It can be set
+              to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF; any
+              non-NULL pointer value passed to ldap_set_option() enables
+              this option.  When reading the current setting using
+              ldap_get_option(), a zero value means off and any non-zero
+              value means on.
+
+      LDAP_OPT_RESTART (0x09)
+         Type for invalue parameter: void * (LDAP_OPT_ON or
+         LDAP_OPT_OFF)
+
+         Type for outvalue parameter: int *
+
+         Description:
+              Determines whether LDAP I/O operations should automati-
+              cally be restarted if they abort prematurely. It should be
+              set to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF;
+              any non-NULL pointer value passed to ldap_set_option()
+              enables this option.  When reading the current setting
+              using ldap_get_option(), a zero value means off and any
+              non-zero value means on. This option is useful if an LDAP
+              I/O operation may be interrupted prematurely, for example
+              by a timer going off, or other interrupt.
+
+      LDAP_OPT_PROTOCOL_VERSION (0x11)
+         Type for invalue parameter: int *
+
+         Type for outvalue parameter: int *
+
+         Description:
+              This option indicates the version of the LDAP protocol
+              used when communicating with the primary LDAP server. It
+              must be one of the constants LDAP_VERSION2 (2) or
+              LDAP_VERSION3 (3).  If no version is set the default is
+              LDAP_VERSION2 (2).
+
+      LDAP_OPT_SERVER_CONTROLS (0x12)
+
+
+
+Expires: 2 December 1999                                       [Page 18]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+         Type for invalue parameter: LDAPControl **
+
+         Type for outvalue parameter: LDAPControl ***
+
+         Description:
+              A default list of LDAP server controls to be sent with
+              each request.  See the Working With Controls section
+              below.
+
+      LDAP_OPT_CLIENT_CONTROLS (0x13)
+         Type for invalue parameter: LDAPControl **
+
+         Type for outvalue parameter: LDAPControl ***
+
+         Description:
+              A default list of client controls that affect the LDAP
+              session.  See the Working With Controls section below.
+
+      LDAP_OPT_API_FEATURE_INFO (0x15)
+         Type for invalue parameter: not applicable (option is READ-
+         ONLY)
+
+         Type for outvalue parameter: LDAPAPIFeatureInfo *
+
+         Description:
+              Used to retrieve version information about LDAP API
+              extended features at execution time.  See the section
+              "Retrieving Information About the API Implementation"
+              above for more information.  This option is READ-ONLY and
+              cannot be set.
+
+      LDAP_OPT_HOST_NAME (0x30)
+         Type for invalue parameter: char *
+
+         Type for outvalue parameter: char **
+
+         Description:
+              The host name (or list of hosts) for the primary LDAP
+              server.  See the definition of the hostname parameter to
+              ldap_init() for the allowed syntax.
+
+      LDAP_OPT_ERROR_NUMBER (0x31)
+         Type for invalue parameter: int *
+
+         Type for outvalue parameter: int *
+
+         Description:
+              The code of the most recent LDAP error that occurred for
+
+
+
+Expires: 2 December 1999                                       [Page 19]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+              this session.
+
+      LDAP_OPT_ERROR_STRING (0x32)
+         Type for invalue parameter: char *
+
+         Type for outvalue parameter: char **
+
+         Description:
+              The message returned with the most recent LDAP error that
+              occurred for this session.
+
+
+   outvalue The address of a place to put the value of the option. The
+            actual type of this parameter depends on the setting of the
+            option parameter.  For outvalues of type char ** and LDAP-
+            Control **, a copy of the data that is associated with the
+            LDAP session ld is returned; callers should dispose of the
+            memory by calling ldap_memfree() or ldap_controls_free().
+
+   invalue  A pointer to the value the option is to be given. The actual
+            type of this parameter depends on the setting of the option
+            parameter. The data associated with invalue is copied by the
+            API implementation to allow callers of the API to dispose of
+            or otherwise change their copy of the data after a success-
+            ful call to ldap_set_option().  If a value passed for
+            invalue is invalid or cannot be accepted by the implementa-
+            tion, ldap_set_option() should return -1 to indicate an
+            error.
+
+Both ldap_get_option() and ldap_set_option() return 0 if successful and
+-1 if an error occurs.
+
+Standards track documents that extend this specification and specify new
+options MUST use values for option macros that are between 0x1000 and
+0x3FFF inclusive.  Private and experimental extensions MUST use values
+for the option macros that are between 0x4000 and 0x7FFF inclusive.  All
+values below 0x1000 and above 0x7FFF that are not defined in this docu-
+ment are reserved and MUST NOT be used.
+
+
+10.3.  Working With Controls
+
+LDAPv3 operations can be extended through the use of controls.  Controls
+may be sent to a server or returned to the client with any LDAP message.
+These controls are referred to as server controls.
+
+The LDAP API also supports a client-side extension mechanism through the
+use of client controls. These controls affect the behavior of the LDAP
+
+
+
+Expires: 2 December 1999                                       [Page 20]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+API only and are never sent to a server.  A common data structure is
+used to represent both types of controls:
+
+           typedef struct ldapcontrol {
+                   char            *ldctl_oid;
+                   struct berval   ldctl_value;
+                   char            ldctl_iscritical;
+           } LDAPControl, *PLDAPControl;
+
+The fields in the ldapcontrol structure have the following meanings:
+
+ldctl_oid        The control type, represented as a string.
+
+ldctl_value      The data associated with the control (if any).  To
+                 specify a zero-length value, set ldctl_value.bv_len to
+                 zero and ldctl_value.bv_val to a zero-length string.
+                 To indicate that no data is associated with the con-
+                 trol, set ldctl_value.bv_val to NULL.
+
+ldctl_iscritical Indicates whether the control is critical of not. If
+                 this field is non-zero, the operation will only be car-
+                 ried out if the control is recognized by the server
+                 and/or client.  Note that the LDAP unbind and abandon
+                 operations have no server response, so clients SHOULD
+                 NOT mark server controls critical when used with these
+                 two operations.
+
+Some LDAP API calls allocate an ldapcontrol structure or a NULL-
+terminated array of ldapcontrol structures.  The following routines can
+be used to dispose of a single control or an array of controls:
+
+           void ldap_control_free( LDAPControl *ctrl );
+           void ldap_controls_free( LDAPControl **ctrls );
+
+A set of controls that affect the entire session can be set using the
+ldap_set_option() function (see above).  A list of controls can also be
+passed directly to some LDAP API calls such as ldap_search_ext(), in
+which case any controls set for the session through the use of
+ldap_set_option() are ignored. Control lists are represented as a NULL-
+terminated array of pointers to ldapcontrol structures.
+
+Server controls are defined by LDAPv3 protocol extension documents; for
+example, a control has been proposed to support server-side sorting of
+search results [7].
+
+One client control is defined in this document (described in the follow-
+ing section).  Other client controls may be defined in future revisions
+of this document or in documents that extend this API.
+
+
+
+Expires: 2 December 1999                                       [Page 21]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+10.3.1.  A Client Control That Governs Referral Processing
+
+As described previously in the section "LDAP Session Handle Options,"
+applications can enable and disable automatic chasing of referrals on a
+session-wide basic by using the ldap_set_option() function with the
+LDAP_OPT_REFERRALS option.  It is also useful to govern automatic refer-
+ral chasing on per-request basis.  A client control with an OID of
+1.2.840.113556.1.4.616 exists to provide this functionality.
+
+   /* OID for referrals client control */
+   #define LDAP_CONTROL_REFERRALS              "1.2.840.113556.1.4.616"
+
+   /* Flags for referrals client control value */
+   #define LDAP_CHASE_SUBORDINATE_REFERRALS    0x00000020
+   #define LDAP_CHASE_EXTERNAL_REFERRALS       0x00000040
+
+To create a referrals client control, the ldctl_oid field of an LDAPCon-
+trol structure should be set to LDAP_CONTROL_REFERRALS
+("1.2.840.113556.1.4.616") and the ldctl_value field should be set to a
+4-octet value that contains a set of flags.  The ldctl_value.bv_len
+field should always be set to 4.  The ldctl_value.bv_val field should
+point to a 4-octet integer flags value.  This flags value can be set to
+zero to disable automatic chasing of referrals and LDAPv3 references
+altogether.  Alternatively, the flags value can be set to the value
+LDAP_CHASE_SUBORDINATE_REFERRALS (0x00000020) to indicate that only
+LDAPv3 search continuation references should be automatically chased by
+the API implementation, to the value LDAP_CHASE_EXTERNAL_REFERRALS
+(0x00000040) to indicate that only LDAPv3 referrals should be automati-
+cally chased, or the logical OR of the two flag values (0x00000060) to
+indicate that both referrals and references should be automatically
+chased.
+
+
+10.4.  Authenticating to the directory
+
+The following functions are used to authenticate an LDAP client to an
+LDAP directory server.
+
+The ldap_sasl_bind() and ldap_sasl_bind_s() functions can be used to do
+general and extensible authentication over LDAP through the use of the
+Simple Authentication Security Layer [8].  The routines both take the dn
+to bind as, the method to use, as a dotted-string representation of an
+OID identifying the method, and a struct berval holding the credentials.
+The special constant value LDAP_SASL_SIMPLE (NULL) can be passed to
+request simple authentication, or the simplified routines
+ldap_simple_bind() or ldap_simple_bind_s() can be used.
+
+           int ldap_sasl_bind(
+
+
+
+Expires: 2 December 1999                                       [Page 22]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                   LDAP                    *ld,
+                   const char              *dn,
+                   const char              *mechanism,
+                   const struct berval     *cred,
+                   LDAPControl             **serverctrls,
+                   LDAPControl             **clientctrls,
+                   int                     *msgidp
+           );
+
+           int ldap_sasl_bind_s(
+                   LDAP                    *ld,
+                   const char              *dn,
+                   const char              *mechanism,
+                   const struct berval     *cred,
+                   LDAPControl             **serverctrls,
+                   LDAPControl             **clientctrls,
+                   struct berval           **servercredp
+           );
+
+           int ldap_simple_bind(
+                   LDAP                    *ld,
+                   const char              *dn,
+                   const char              *passwd
+           );
+
+           int ldap_simple_bind_s(
+                   LDAP                    *ld,
+                   const char              *dn,
+                   const char              *passwd
+           );
+
+   The use of the following routines is deprecated:
+
+           int ldap_bind( LDAP *ld, const char *dn, const char *cred,
+                   int method );
+
+           int ldap_bind_s( LDAP *ld, const char *dn, const char *cred,
+                   int method );
+
+           int ldap_kerberos_bind( LDAP *ld, const char *dn );
+
+           int ldap_kerberos_bind_s( LDAP *ld, const char *dn );
+
+Parameters are:
+
+ld           The session handle.
+
+dn           The name of the entry to bind as.
+
+
+
+Expires: 2 December 1999                                       [Page 23]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+mechanism    Either LDAP_SASL_SIMPLE (NULL) to get simple authentica-
+             tion, or a text string identifying the SASL method.
+
+cred         The credentials with which to authenticate. Arbitrary
+             credentials can be passed using this parameter. The format
+             and content of the credentials depends on the setting of
+             the mechanism parameter.
+
+passwd       For ldap_simple_bind(), the password to compare to the
+             entry's userPassword attribute.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_sasl_bind() call succeeds.
+
+servercredp  This result parameter will be filled in with the creden-
+             tials passed back by the server for mutual authentication,
+             if given. An allocated berval structure is returned that
+             should be disposed of by calling ber_bvfree().  NULL may be
+             passed to ignore this field.
+
+Additional parameters for the deprecated routines are not described.
+Interested readers are referred to RFC 1823.
+
+The ldap_sasl_bind() function initiates an asynchronous bind operation
+and returns the constant LDAP_SUCCESS if the request was successfully
+sent, or another LDAP error code if not.  See the section below on error
+handling for more information about possible errors and how to interpret
+them.  If successful, ldap_sasl_bind() places the message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the bind.
+
+The ldap_simple_bind() function initiates a simple asynchronous bind
+operation and returns the message id of the operation initiated.  A sub-
+sequent call to ldap_result(), described below, can be used to obtain
+the result of the bind. In case of error, ldap_simple_bind() will return
+-1, setting the session error parameters in the LDAP structure appropri-
+ately.
+
+The synchronous ldap_sasl_bind_s() and ldap_simple_bind_s() functions
+both return the result of the operation, either the constant
+LDAP_SUCCESS if the operation was successful, or another LDAP error code
+if it was not. See the section below on error handling for more informa-
+tion about possible errors and how to interpret them.
+
+
+
+
+Expires: 2 December 1999                                       [Page 24]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+Note that if an LDAPv2 server is contacted, no other operations over the
+connection should be attempted before a bind call has successfully com-
+pleted.
+
+Subsequent bind calls can be used to re-authenticate over the same con-
+nection, and multistep SASL sequences can be accomplished through a
+sequence of calls to ldap_sasl_bind() or ldap_sasl_bind_s().
+
+
+10.5.  Closing the session
+
+The following functions are used to unbind from the directory, close
+open connections, and dispose of the session handle.
+
+           int ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls,
+               LDAPControl **clientctrls );
+
+           int ldap_unbind( LDAP *ld );
+
+           int ldap_unbind_s( LDAP *ld );
+
+Parameters are:
+
+ld           The session handle.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+The ldap_unbind_ext(), ldap_unbind() and ldap_unbind_s() all work syn-
+chronously in the sense that they send an unbind request to the server,
+close all open connections associated with the LDAP session handle, and
+dispose of all resources associated with the session handle before
+returning.  Note, however, that there is no server response to an LDAP
+unbind operation.  All three of the unbind functions return LDAP_SUCCESS
+(or another LDAP error code if the request cannot be sent to the LDAP
+server).  After a call to one of the unbind functions, the session han-
+dle ld is invalid and it is illegal to make any further LDAP API calls
+using ld.
+
+The ldap_unbind() and ldap_unbind_s() functions behave identically.  The
+ldap_unbind_ext() function allows server and client controls to be
+included explicitly, but note that since there is no server response to
+an unbind request there is no way to receive a response to a server con-
+trol sent with an unbind request.
+
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 25]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+10.6.  Searching
+
+The following functions are used to search the LDAP directory, returning
+a requested set of attributes for each entry matched.  There are five
+variations.
+
+           int ldap_search_ext(
+                   LDAP            *ld,
+                   const char      *base,
+                   int             scope,
+                   const char      *filter,
+                   char            **attrs,
+                   int             attrsonly,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   struct timeval  *timeout,
+                   int             sizelimit,
+                   int             *msgidp
+           );
+
+           int ldap_search_ext_s(
+                   LDAP            *ld,
+                   const char      *base,
+                   int             scope,
+                   const char      *filter,
+                   char            **attrs,
+                   int             attrsonly,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   struct timeval  *timeout,
+                   int             sizelimit,
+                   LDAPMessage     **res
+           );
+
+           int ldap_search(
+                   LDAP            *ld,
+                   const char      *base,
+                   int             scope,
+                   const char      *filter,
+                   char            **attrs,
+                   int             attrsonly
+           );
+
+           int ldap_search_s(
+                   LDAP            *ld,
+                   const char      *base,
+                   int             scope,
+                   const char      *filter,
+
+
+
+Expires: 2 December 1999                                       [Page 26]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                   char            **attrs,
+                   int             attrsonly,
+                   LDAPMessage     **res
+           );
+
+           int ldap_search_st(
+                   LDAP            *ld,
+                   const char      *base,
+                   int             scope,
+                   const char      *filter,
+                   char            **attrs,
+                   int             attrsonly,
+                   struct timeval  *timeout,
+                   LDAPMessage     **res
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+base         The dn of the entry at which to start the search.
+
+scope        One of LDAP_SCOPE_BASE (0x00), LDAP_SCOPE_ONELEVEL (0x01),
+             or LDAP_SCOPE_SUBTREE (0x02), indicating the scope of the
+             search.
+
+filter       A character string as described in [3], representing the
+             search filter.  The value NULL can be passed to indicate
+             that the filter "(objectclass=*)" which matches all entries
+             should be used.  Note that if the caller of the API is
+             using LDAPv2, only a subset of the filter functionality
+             described in [3] can be successfully used.
+
+attrs        A NULL-terminated array of strings indicating which attri-
+             butes to return for each matching entry. Passing NULL for
+             this parameter causes all available user attributes to be
+             retrieved.  The special constant string LDAP_NO_ATTRS
+             ("1.1") can be used as the only string in the array to
+             indicate that no attribute types should be returned by the
+             server.  The special constant string LDAP_ALL_USER_ATTRS
+             ("*") can be used in the attrs array along with the names
+             of some operational attributes to indicate that all user
+             attributes plus the listed operational attributes should be
+             returned.
+
+attrsonly    A boolean value that should be zero if both attribute types
+             and values are to be returned, non-zero if only types are
+             wanted.
+
+
+
+Expires: 2 December 1999                                       [Page 27]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+timeout      For the ldap_search_st() function, this specifies the local
+             search timeout value (if it is NULL, the timeout is infin-
+             ite).  For the ldap_search_ext() and ldap_search_ext_s()
+             functions, this specifies both the local search timeout
+             value and the operation time limit that is sent to the
+             server within the search request.  For the
+             ldap_search_ext() and ldap_search_ext_s() functions, pass-
+             ing a NULL value for timeout causes the global default
+             timeout stored in the LDAP session handle (set by using
+             ldap_set_option() with the LDAP_OPT_TIMELIMIT parameter) to
+             be sent to the server with the request but an infinite
+             local search timeout to be used.
+
+sizelimit    For the ldap_search_ext() and ldap_search_ext_s() calls,
+             this is a limit on the number of entries to return from the
+             search.  A value of LDAP_NO_LIMIT (0) means no limit.
+
+res          For the synchronous calls, this is a result parameter which
+             will contain the results of the search upon completion of
+             the call.  If no results are returned, *res is set to NULL.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_search_ext() call succeeds.
+
+There are three options in the session handle ld which potentially
+affect how the search is performed. They are:
+
+LDAP_OPT_SIZELIMIT
+             A limit on the number of entries to return from the search.
+             A value of LDAP_NO_LIMIT (0) means no limit.  Note that the
+             value from the session handle is ignored when using the
+             ldap_search_ext() or ldap_search_ext_s() functions.
+
+LDAP_OPT_TIMELIMIT
+             A limit on the number of seconds to spend on the search. A
+             value of LDAP_NO_LIMIT (0) means no limit.  Note that the
+             value from the session handle is ignored when using the
+             ldap_search_ext() or ldap_search_ext_s() functions.
+
+LDAP_OPT_DEREF
+             One of LDAP_DEREF_NEVER (0x00), LDAP_DEREF_SEARCHING
+             (0x01), LDAP_DEREF_FINDING (0x02), or LDAP_DEREF_ALWAYS
+             (0x03), specifying how aliases should be handled during the
+             search. The LDAP_DEREF_SEARCHING value means aliases should
+
+
+
+Expires: 2 December 1999                                       [Page 28]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+             be dereferenced during the search but not when locating the
+             base object of the search. The LDAP_DEREF_FINDING value
+             means aliases should be dereferenced when locating the base
+             object but not during the search.
+
+The ldap_search_ext() function initiates an asynchronous search opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not.  See the section below on
+error handling for more information about possible errors and how to
+interpret them.  If successful, ldap_search_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the results from the search.  These results
+can be parsed using the result parsing routines described in detail
+later.
+
+Similar to ldap_search_ext(), the ldap_search() function initiates an
+asynchronous search operation and returns the message id of the opera-
+tion initiated.  As for ldap_search_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+bind. In case of error, ldap_search() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_search_ext_s(), ldap_search_s(), and
+ldap_search_st() functions all return the result of the operation,
+either the constant LDAP_SUCCESS if the operation was successful, or
+another LDAP error code if it was not. See the section below on error
+handling for more information about possible errors and how to interpret
+them.  Entries returned from the search (if any) are contained in the
+res parameter. This parameter is opaque to the caller.  Entries, attri-
+butes, values, etc., should be extracted by calling the parsing routines
+described below. The results contained in res should be freed when no
+longer in use by calling ldap_msgfree(), described later.
+
+The ldap_search_ext() and ldap_search_ext_s() functions support LDAPv3
+server controls, client controls, and allow varying size and time limits
+to be easily specified for each search operation.  The ldap_search_st()
+function is identical to ldap_search_s() except that it takes an addi-
+tional parameter specifying a local timeout for the search.  The local
+search timeout is used to limit the amount of time the API implementa-
+tion will wait for a search to complete.  After the local search timeout
+expires, the API implementation will send an abandon operation to abort
+the search operation.
+
+10.7.  Reading an Entry
+
+LDAP does not support a read operation directly. Instead, this operation
+is emulated by a search with base set to the DN of the entry to read,
+scope set to LDAP_SCOPE_BASE, and filter set to "(objectclass=*)" or
+
+
+
+Expires: 2 December 1999                                       [Page 29]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+NULL. attrs contains the list of attributes to return.
+
+
+10.8.  Listing the Children of an Entry
+
+LDAP does not support a list operation directly. Instead, this operation
+is emulated by a search with base set to the DN of the entry to list,
+scope set to LDAP_SCOPE_ONELEVEL, and filter set to "(objectclass=*)" or
+NULL. attrs contains the list of attributes to return for each child
+entry.
+
+10.9.  Comparing a Value Against an Entry
+
+The following routines are used to compare a given attribute value
+assertion against an LDAP entry.  There are four variations:
+
+           int ldap_compare_ext(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *attr,
+                   struct berval   *bvalue
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+           );
+
+           int ldap_compare_ext_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *attr,
+                   struct berval   *bvalue,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls
+           );
+
+           int ldap_compare(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *attr,
+                   const char      *value
+           );
+
+           int ldap_compare_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *attr,
+                   const char      *value
+           );
+
+
+
+Expires: 2 December 1999                                       [Page 30]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+Parameters are:
+
+ld           The session handle.
+
+dn           The name of the entry to compare against.
+
+attr         The attribute to compare against.
+
+bvalue       The attribute value to compare against those found in the
+             given entry. This parameter is used in the extended rou-
+             tines and is a pointer to a struct berval so it is possible
+             to compare binary values.
+
+value        A string attribute value to compare against, used by the
+             ldap_compare() and ldap_compare_s() functions.  Use
+             ldap_compare_ext() or ldap_compare_ext_s() if you need to
+             compare binary values.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_compare_ext() call succeeds.
+
+The ldap_compare_ext() function initiates an asynchronous compare opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not.  See the section below on
+error handling for more information about possible errors and how to
+interpret them.  If successful, ldap_compare_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the compare.
+
+Similar to ldap_compare_ext(), the ldap_compare() function initiates an
+asynchronous compare operation and returns the message id of the opera-
+tion initiated.  As for ldap_compare_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+bind. In case of error, ldap_compare() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_compare_ext_s() and ldap_compare_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_compare_ext() and ldap_compare_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+
+Expires: 2 December 1999                                       [Page 31]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+10.10.  Modifying an entry
+
+The following routines are used to modify an existing LDAP entry.  There
+are four variations:
+
+           typedef struct ldapmod {
+                   int             mod_op;
+                   char            *mod_type;
+                   union {
+                           char            **modv_strvals;
+                           struct berval   **modv_bvals;
+                   } mod_vals;
+           } LDAPMod;
+           #define mod_values      mod_vals.modv_strvals
+           #define mod_bvalues     mod_vals.modv_bvals
+
+           int ldap_modify_ext(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **mods,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+           );
+
+           int ldap_modify_ext_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **mods,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls
+           );
+
+           int ldap_modify(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **mods
+           );
+
+           int ldap_modify_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **mods
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+
+
+Expires: 2 December 1999                                       [Page 32]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+dn           The name of the entry to modify.
+
+mods         A NULL-terminated array of modifications to make to the
+             entry.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_modify_ext() call succeeds.
+
+The fields in the LDAPMod structure have the following meanings:
+
+mod_op       The modification operation to perform. It should be one of
+             LDAP_MOD_ADD (0x00), LDAP_MOD_DELETE (0x01), or
+             LDAP_MOD_REPLACE (0x02).  This field also indicates the
+             type of values included in the mod_vals union. It is logi-
+             cally ORed with LDAP_MOD_BVALUES (0x80) to select the
+             mod_bvalues form. Otherwise, the mod_values form is used.
+
+mod_type     The type of the attribute to modify.
+
+mod_vals     The values (if any) to add, delete, or replace. Only one of
+             the mod_values or mod_bvalues variants should be used,
+             selected by ORing the mod_op field with the constant
+             LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of
+             zero-terminated strings and mod_bvalues is a NULL-
+             terminated array of berval structures that can be used to
+             pass binary values such as images.
+
+For LDAP_MOD_ADD modifications, the given values are added to  the
+entry, creating the attribute if necessary.
+
+For LDAP_MOD_DELETE modifications, the given values are deleted from the
+entry, removing the attribute if no values remain. If the entire attri-
+bute is to  be deleted, the mod_vals field should be set to NULL.
+
+For LDAP_MOD_REPLACE modifications, the attribute will have the listed
+values after the modification, having been created if necessary, or
+removed if the mod_vals field is NULL. All modifications are performed
+in the order in which they are listed.
+
+The ldap_modify_ext() function initiates an asynchronous modify opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not.  See the section below on
+error handling for more information about possible errors and how to
+interpret them.  If successful, ldap_modify_ext() places the message id
+
+
+
+Expires: 2 December 1999                                       [Page 33]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the modify.
+
+Similar to ldap_modify_ext(), the ldap_modify() function initiates an
+asynchronous modify operation and returns the message id of the opera-
+tion initiated.  As for ldap_modify_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+modify. In case of error, ldap_modify() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_modify_ext_s() and ldap_modify_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_modify_ext() and ldap_modify_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+10.11.  Modifying the Name of an Entry
+
+In LDAPv2, the ldap_modrdn(), ldap_modrdn_s(), ldap_modrdn2(), and
+ldap_modrdn2_s() routines were used to change the name of an LDAP entry.
+They could only be used to change the least significant component of a
+name (the RDN or relative distinguished name). LDAPv3 provides the
+Modify DN protocol operation that allows more general name change
+access. The ldap_rename() and ldap_rename_s() routines are used to
+change the name of an entry, and the use of the ldap_modrdn(),
+ldap_modrdn_s(), ldap_modrdn2(), and ldap_modrdn2_s() routines is depre-
+cated.
+
+           int ldap_rename(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn,
+                   const char      *newparent,
+                   int             deleteoldrdn,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+
+           );
+           int ldap_rename_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn,
+                   const char      *newparent,
+
+
+
+Expires: 2 December 1999                                       [Page 34]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                   int             deleteoldrdn,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls
+           );
+
+   Use of the following routines is deprecated.
+
+           int ldap_modrdn(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn
+           );
+           int ldap_modrdn_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn
+           );
+           int ldap_modrdn2(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn,
+                   int             deleteoldrdn
+           );
+           int ldap_modrdn2_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   const char      *newrdn,
+                   int             deleteoldrdn
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+dn           The name of the entry whose DN is to be changed.
+
+newrdn       The new RDN to give the entry.
+
+newparent    The new parent, or superior entry.  If this parameter is
+             NULL, only the RDN of the entry is changed.  The root DN
+             may be specified by passing a zero length string, "".  The
+             newparent parameter should always be NULL when using ver-
+             sion 2 of the LDAP protocol; otherwise the server's
+             behavior is undefined.
+
+deleteoldrdn This parameter only has meaning on the rename routines if
+             newrdn is different than the old RDN. It is a boolean
+             value, if non-zero indicating that the old RDN value(s)
+
+
+
+Expires: 2 December 1999                                       [Page 35]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+             should be removed, if zero indicating that the old RDN
+             value(s) should be retained as non-distinguished values of
+             the entry.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_rename() call succeeds.
+
+The ldap_rename() function initiates an asynchronous modify DN operation
+and returns the constant LDAP_SUCCESS if the request was successfully
+sent, or another LDAP error code if not.  See the section below on error
+handling for more information about possible errors and how to interpret
+them.  If successful, ldap_rename() places the DN message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the rename.
+
+The synchronous ldap_rename_s() returns the result of the operation,
+either the constant LDAP_SUCCESS if the operation was successful, or
+another LDAP error code if it was not.  See the section below on error
+handling for more information about possible errors and how to interpret
+them.
+
+The ldap_rename() and ldap_rename_s() functions both support LDAPv3
+server controls and client controls.
+
+
+10.12.  Adding an entry
+
+The following functions are used to add entries to the LDAP directory.
+There are four variations:
+
+           int ldap_add_ext(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **attrs,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+           );
+
+           int ldap_add_ext_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **attrs,
+                   LDAPControl     **serverctrls,
+
+
+
+Expires: 2 December 1999                                       [Page 36]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                   LDAPControl     **clientctrls
+           );
+
+           int ldap_add(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **attrs
+           );
+
+           int ldap_add_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPMod         **attrs
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+dn           The name of the entry to add.
+
+attrs        The entry's attributes, specified using the LDAPMod struc-
+             ture defined for ldap_modify(). The mod_type and mod_vals
+             fields should be filled in.  The mod_op field is ignored
+             unless ORed with the constant LDAP_MOD_BVALUES, used to
+             select the mod_bvalues case of the mod_vals union.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_add_ext() call succeeds.
+
+Note that the parent of the entry being added must already exist or the
+parent must be empty (i.e., equal to the root DN) for an add to succeed.
+
+The ldap_add_ext() function initiates an asynchronous add operation and
+returns the constant LDAP_SUCCESS if the request was successfully sent,
+or another LDAP error code if not.  See the section below on error han-
+dling for more information about possible errors and how to interpret
+them.  If successful, ldap_add_ext() places the message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the add.
+
+Similar to ldap_add_ext(), the ldap_add() function initiates an asyn-
+chronous add operation and returns the message id of the operation ini-
+tiated.  As for ldap_add_ext(), a subsequent call to ldap_result(),
+
+
+
+Expires: 2 December 1999                                       [Page 37]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+described below, can be used to obtain the result of the add. In case of
+error, ldap_add() will return -1, setting the session error parameters
+in the LDAP structure appropriately.
+
+The synchronous ldap_add_ext_s() and ldap_add_s() functions both return
+the result of the operation, either the constant LDAP_SUCCESS if the
+operation was successful, or another LDAP error code if it was not.  See
+the section below on error handling for more information about possible
+errors and how to interpret them.
+
+The ldap_add_ext() and ldap_add_ext_s() functions support LDAPv3 server
+controls and client controls.
+
+
+
+10.13.  Deleting an entry
+
+The following functions are used to delete a leaf entry from the LDAP
+directory.  There are four variations:
+
+           int ldap_delete_ext(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+           );
+
+           int ldap_delete_ext_s(
+                   LDAP            *ld,
+                   const char      *dn,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls
+           );
+
+           int ldap_delete(
+                   LDAP            *ld,
+                   const char      *dn
+           );
+
+           int ldap_delete_s(
+                   LDAP            *ld,
+                   const char      *dn
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+
+
+Expires: 2 December 1999                                       [Page 38]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+dn           The name of the entry to delete.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_delete_ext() call succeeds.
+
+Note that the entry to delete must be a leaf entry (i.e., it must have
+no children). Deletion of entire subtrees in a single operation is not
+supported by LDAP.
+
+The ldap_delete_ext() function initiates an asynchronous delete opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not.  See the section below on
+error handling for more information about possible errors and how to
+interpret them.  If successful, ldap_delete_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the delete.
+
+Similar to ldap_delete_ext(), the ldap_delete() function initiates an
+asynchronous delete operation and returns the message id of the opera-
+tion initiated.  As for ldap_delete_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+delete. In case of error, ldap_delete() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_delete_ext_s() and ldap_delete_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_delete_ext() and ldap_delete_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+10.14.  Extended Operations
+
+The ldap_extended_operation() and ldap_extended_operation_s() routines
+allow extended LDAP operations to be passed to the server, providing a
+general protocol extensibility mechanism.
+
+           int ldap_extended_operation(
+                   LDAP            *ld,
+                   const char      *requestoid,
+                   struct berval   *requestdata,
+
+
+
+Expires: 2 December 1999                                       [Page 39]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   int             *msgidp
+           );
+
+           int ldap_extended_operation_s(
+                   LDAP            *ld,
+                   const char      *requestoid,
+                   struct berval   *requestdata,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls,
+                   char            **retoidp,
+                   struct berval   **retdatap
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+requestoid   The dotted-OID text string naming the request.
+
+requestdata  The arbitrary data required by the operation (if NULL, no
+             data is sent to the server).
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+msgidp       This result parameter will be set to the message id of the
+             request if the ldap_extended_operation() call succeeds.
+
+retoidp      Pointer to a character string that will be set to an allo-
+             cated, dotted-OID text string returned by the server.  This
+             string should be disposed of using the ldap_memfree() func-
+             tion.  If no OID was returned, *retoidp is set to NULL.
+
+retdatap     Pointer to a berval structure pointer that will be set an
+             allocated copy of the data returned by the server.  This
+             struct berval should be disposed of using ber_bvfree().  If
+             no data is returned, *retdatap is set to NULL.
+
+The ldap_extended_operation() function initiates an asynchronous
+extended operation and returns the constant LDAP_SUCCESS if the request
+was successfully sent, or another LDAP error code if not.  See the sec-
+tion below on error handling for more information about possible errors
+and how to interpret them.  If successful, ldap_extended_operation()
+places the message id of the request in *msgidp. A subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+
+
+
+Expires: 2 December 1999                                       [Page 40]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+extended operation which can be passed to ldap_parse_extended_result()
+to obtain the OID and data contained in the response.
+
+The synchronous ldap_extended_operation_s() function returns the result
+of the operation, either the constant LDAP_SUCCESS if the operation was
+successful, or another LDAP error code if it was not.  See the section
+below on error handling for more information about possible errors and
+how to interpret them.  The retoid and retdata parameters are filled in
+with the OID and data from the response.  If no OID or data was
+returned, these parameters are set to NULL.
+
+The ldap_extended_operation() and ldap_extended_operation_s() functions
+both support LDAPv3 server controls and client controls.
+
+
+11.  Abandoning An Operation
+
+The following calls are used to abandon an operation in progress:
+
+           int ldap_abandon_ext(
+                   LDAP            *ld,
+                   int             msgid,
+                   LDAPControl     **serverctrls,
+                   LDAPControl     **clientctrls
+           );
+
+           int ldap_abandon(
+                   LDAP            *ld,
+                   int             msgid
+           );
+
+
+ld           The session handle.
+
+msgid        The message id of the request to be abandoned.
+
+serverctrls  List of LDAP server controls.
+
+clientctrls  List of client controls.
+
+ldap_abandon_ext() abandons the operation with message id msgid and
+returns the constant LDAP_SUCCESS if the abandon was successful or
+another LDAP error code if not.  See the section below on error handling
+for more information about possible errors and how to interpret them.
+
+ldap_abandon() is identical to ldap_abandon_ext() except that it does
+not accept client or server controls and it returns zero if the abandon
+was successful, -1 otherwise.
+
+
+
+Expires: 2 December 1999                                       [Page 41]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+After a successful call to ldap_abandon() or ldap_abandon_ext(), results
+with the given message id are never returned from a subsequent call to
+ldap_result().  There is no server response to LDAP abandon operations.
+
+
+12.  Obtaining Results and Peeking Inside LDAP Messages
+
+ldap_result() is used to obtain the result of a previous asynchronously
+initiated operation. Note that depending on how it is called,
+ldap_result() may actually return a list or "chain" of result messages.
+The ldap_result() function only returns messages for a single request,
+so for all LDAP operations other than search only one result message is
+expected; that is, the only time the "result chain" may contain more
+than one message is if results from a search operation are returned.
+Once a chain of messages has been returned to the caller, it is no
+longer tied in any caller-visible way to the LDAP request that produced
+it.  Therefore, a chain of messages returned by calling ldap_result() or
+by calling a synchronous search routine will never be affected by subse-
+quent LDAP API calls (except for ldap_msgfree() which is used to dispose
+of a chain of messages).
+
+ldap_msgfree() frees the result messages (possibly an entire chain of
+messages) obtained from a previous call to ldap_result() or from a call
+to a synchronous search routine.
+
+ldap_msgtype() returns the type of an LDAP message.  ldap_msgid()
+returns the message ID of an LDAP message.
+
+           int ldap_result(
+                   LDAP            *ld,
+                   int             msgid,
+                   int             all,
+                   struct timeval  *timeout,
+                   LDAPMessage     **res
+           );
+
+           int ldap_msgfree( LDAPMessage *res );
+
+           int ldap_msgtype( LDAPMessage *res );
+
+           int ldap_msgid( LDAPMessage *res );
+
+Parameters are:
+
+ld       The session handle.
+
+msgid    The message id of the operation whose results are to be
+         returned, or the constant LDAP_RES_ANY (-1) if any result is
+
+
+
+Expires: 2 December 1999                                       [Page 42]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+         desired.
+
+all      Specifies how many messages will be retrieved in a single call
+         to ldap_result().  This parameter only has meaning for search
+         results.  Pass the constant LDAP_MSG_ONE (0x00) to retrieve one
+         message at a time.  Pass LDAP_MSG_ALL (0x01) to request that
+         all results of a search be received before returning all
+         results in a single chain.  Pass LDAP_MSG_RECEIVED (0x02) to
+         indicate that all messages retrieved so far should be returned
+         in the result chain.
+
+timeout  A timeout specifying how long to wait for results to be
+         returned.  A NULL value causes ldap_result() to block until
+         results are available.  A timeout value of zero seconds speci-
+         fies a polling behavior.
+
+res      For ldap_result(), a result parameter that will contain the
+         result(s) of the operation. If no results are returned, *res is
+         set to NULL.  For ldap_msgfree(), the result chain to be freed,
+         obtained from a previous call to ldap_result(),
+         ldap_search_s(), or ldap_search_st().  If res is NULL, nothing
+         is done and ldap_msgfree() returns zero.
+
+Upon successful completion, ldap_result() returns the type of the first
+result returned in the res parameter. This will be one of the following
+constants.
+
+             LDAP_RES_BIND (0x61)
+             LDAP_RES_SEARCH_ENTRY (0x64)
+             LDAP_RES_SEARCH_REFERENCE (0x73)      -- new in LDAPv3
+             LDAP_RES_SEARCH_RESULT (0x65)
+             LDAP_RES_MODIFY (0x67)
+             LDAP_RES_ADD (0x69)
+             LDAP_RES_DELETE (0x6B)
+             LDAP_RES_MODDN (0x6D)
+             LDAP_RES_COMPARE (0x6F)
+             LDAP_RES_EXTENDED (0x78)              -- new in LDAPv3
+
+ldap_result() returns 0 if the timeout expired and -1 if an error
+occurs, in which case the error parameters of the LDAP session handle
+will be set accordingly.
+
+ldap_msgfree() frees the result structure pointed to by res and returns
+the type of the message it freed.  If res is NULL, nothing is done and
+the value zero is returned.
+
+ldap_msgtype() returns the type of the LDAP message it is passed as a
+parameter. The type will be one of the types listed above, or -1 on
+
+
+
+Expires: 2 December 1999                                       [Page 43]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+error.
+
+ldap_msgid() returns the message ID associated with the LDAP message
+passed as a parameter.
+
+
+13.  Handling Errors and Parsing Results
+
+The following calls are used to extract information from results and
+handle errors returned by other LDAP API routines.  Note that
+ldap_parse_sasl_bind_result() and ldap_parse_extended_result() must typ-
+ically be used in addition to ldap_parse_result() to retrieve all the
+result information from SASL Bind and Extended Operations respectively.
+
+           int ldap_parse_result(
+                   LDAP            *ld,
+                   LDAPMessage     *res,
+                   int             *errcodep,
+                   char            **matcheddnp,
+                   char            **errmsgp,
+                   char            ***referralsp,
+                   LDAPControl     ***serverctrlsp,
+                   int             freeit
+           );
+
+           int ldap_parse_sasl_bind_result(
+                   LDAP            *ld,
+                   LDAPMessage     *res,
+                   struct berval   **servercredp,
+                   int             freeit
+           );
+
+           int ldap_parse_extended_result(
+                   LDAP            *ld,
+                   LDAPMessage     *res,
+                   char            **retoidp,
+                   struct berval   **retdatap,
+                   int             freeit
+           );
+
+           char *ldap_err2string( int err );
+
+   The use of the following routines is deprecated.
+
+           int ldap_result2error(
+                   LDAP            *ld,
+                   LDAPMessage     *res,
+                   int             freeit
+
+
+
+Expires: 2 December 1999                                       [Page 44]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+           );
+
+           void ldap_perror( LDAP *ld, const char *msg );
+
+Parameters are:
+
+ld           The session handle.
+
+res          The result of an LDAP operation as returned by
+             ldap_result() or one of the synchronous API operation
+             calls.
+
+errcodep     This result parameter will be filled in with the LDAP error
+             code field from the LDAPMessage message.  This is the indi-
+             cation from the server of the outcome of the operation.
+             NULL may be passed to ignore this field.
+
+matcheddnp   In the case of a return of LDAP_NO_SUCH_OBJECT, this result
+             parameter will be filled in with a DN indicating how much
+             of the name in the request was recognized. NULL may be
+             passed to ignore this field.  The matched DN string should
+             be freed by calling ldap_memfree() which is described later
+             in this document.
+
+errmsgp      This result parameter will be filled in with the contents
+             of the error message field from the LDAPMessage message.
+             The error message string should be freed by calling
+             ldap_memfree() which is described later in this document.
+             NULL may be passed to ignore this field.
+
+referralsp   This result parameter will be filled in with the contents
+             of the referrals field from the LDAPMessage message, indi-
+             cating zero or more alternate LDAP servers where the
+             request should be retried.  The referrals array should be
+             freed by calling ldap_value_free() which is described later
+             in this document.  NULL may be passed to ignore this field.
+
+serverctrlsp This result parameter will be filled in with an allocated
+             array of controls copied out of the LDAPMessage message.
+             The control array should be freed by calling
+             ldap_controls_free() which was described earlier.
+
+freeit       A boolean that determines whether the res parameter is
+             disposed of or not.  Pass any non-zero value to have these
+             routines free res after extracting the requested informa-
+             tion.  This is provided as a convenience; you can also use
+             ldap_msgfree() to free the result later.  If freeit is
+             non-zero, the entire chain of messages represented by res
+
+
+
+Expires: 2 December 1999                                       [Page 45]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+             is disposed of.
+
+servercredp  For SASL bind results, this result parameter will be filled
+             in with the credentials passed back by the server for
+             mutual authentication, if given. An allocated berval struc-
+             ture is returned that should be disposed of by calling
+             ber_bvfree().  NULL may be passed to ignore this field.
+
+retoidp      For extended results, this result parameter will be filled
+             in with the dotted-OID text representation of the name of
+             the extended operation response.  This string should be
+             disposed of by calling ldap_memfree().  NULL may be passed
+             to ignore this field.
+
+retdatap     For extended results, this result parameter will be filled
+             in with a pointer to a struct berval containing the data in
+             the extended operation response.  It should be disposed of
+             by calling ber_bvfree(). NULL may be passed to ignore this
+             field.
+
+err          For ldap_err2string(), an LDAP error code, as returned by
+             ldap_parse_result() or another LDAP API call.
+
+Additional parameters for the deprecated routines are not described.
+Interested readers are referred to RFC 1823.
+
+All three of the ldap_parse_*_result() routines skip over messages of
+type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERENCE when looking
+for a result message to parse.  They return the constant LDAP_SUCCESS if
+the result was successfully parsed and another LDAP error code if not.
+Note that the LDAP error code that indicates the outcome of the opera-
+tion performed by the server is placed in the errcodep
+ldap_parse_result() parameter.  If a chain of messages that contains
+more than one result message is passed to these routines they always
+operate on the first result in the chain.
+
+ldap_err2string() is used to convert a numeric LDAP error code, as
+returned by one of the three ldap_parse_*_result() routines, or one of
+the synchronous API operation calls, into an informative zero-terminated
+character string message describing the error.  It returns a pointer to
+static data.
+
+
+14.  Stepping Through a List of Results
+
+The ldap_first_message() and ldap_next_message() routines are used to
+step through the list of messages in a result chain returned by
+ldap_result().  For search operations, the result chain may actually
+
+
+
+Expires: 2 December 1999                                       [Page 46]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+include referral messages, entry messages, and result messages.
+ldap_count_messages() is used to count the number of messages returned.
+The ldap_msgtype() function, described above, can be used to distinguish
+between the different message types.
+
+           LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res );
+
+           LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *msg );
+
+           int ldap_count_messages( LDAP *ld, LDAPMessage *res );
+
+Parameters are:
+
+ld     The session handle.
+
+res    The result chain, as obtained by a call to one of the synchronous
+       search routines or ldap_result().
+
+msg    The message returned by a previous call to ldap_first_message()
+       or ldap_next_message().
+
+ldap_first_message() and ldap_next_message() will return NULL when no
+more messages exist in the result set to be returned.  NULL is also
+returned if an error occurs while stepping through the entries, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+ldap_count_messages() returns the number of messages contained in a
+chain of results. It can also be used to count the number of messages
+that remain in a chain if called with a message, entry, or reference
+returned by ldap_first_message(), ldap_next_message(),
+ldap_first_entry(), ldap_next_entry(), ldap_first_reference(),
+ldap_next_reference().
+
+
+15.  Parsing Search Results
+
+The following calls are used to parse the entries and references
+returned by ldap_search() and friends. These results are returned in an
+opaque structure that should only be accessed by calling the routines
+described below. Routines are provided to step through the entries and
+references returned, step through the attributes of an entry, retrieve
+the name of an entry, and retrieve the values associated with a given
+attribute in an entry.
+
+
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 47]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+15.1.  Stepping Through a List of Entries or References
+
+The ldap_first_entry() and ldap_next_entry() routines are used to step
+through and retrieve the list of entries from a search result chain.
+The ldap_first_reference() and ldap_next_reference() routines are used
+to step through and retrieve the list of continuation references from a
+search result chain.  ldap_count_entries() is used to count the number
+of entries returned. ldap_count_references() is used to count the number
+of references returned.
+
+           LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
+
+           LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
+
+           LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *res );
+
+           LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *ref );
+
+           int ldap_count_entries( LDAP *ld, LDAPMessage *res );
+
+           int ldap_count_references( LDAP *ld, LDAPMessage *res );
+
+Parameters are:
+
+ld     The session handle.
+
+res    The search result, as obtained by a call to one of the synchro-
+       nous search routines or ldap_result().
+
+entry  The entry returned by a previous call to ldap_first_entry() or
+       ldap_next_entry().
+
+ref    The reference returned by a previous call to
+       ldap_first_reference() or ldap_next_reference().
+
+ldap_first_entry(), ldap_next_entry(), ldap_first_reference() and
+ldap_next_reference() all return NULL when no more entries or references
+exist in the result set to be returned.  NULL is also returned if an
+error occurs while stepping through the entries or references, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+ldap_count_entries() returns the number of entries contained in a chain
+of entries. It can also be used to count the number of entries that
+remain in a chain if called with a message, entry or reference returned
+by ldap_first_message(), ldap_next_message(), ldap_first_entry(),
+ldap_next_entry(), ldap_first_reference(), ldap_next_reference().
+
+
+
+
+Expires: 2 December 1999                                       [Page 48]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+ldap_count_references() returns the number of references contained in a
+chain of search results. It can also be used to count the number of
+references that remain in a chain.
+
+
+15.2.  Stepping Through the Attributes of an Entry
+
+The ldap_first_attribute() and ldap_next_attribute() calls are used to
+step through the list of attribute types returned with an entry.
+
+           char *ldap_first_attribute(
+                   LDAP            *ld,
+                   LDAPMessage     *entry,
+                   BerElement      **ptr
+           );
+
+           char *ldap_next_attribute(
+                   LDAP            *ld,
+                   LDAPMessage     *entry,
+                   BerElement      *ptr
+           );
+
+           void ldap_memfree( char *mem );
+
+Parameters are:
+
+ld     The session handle.
+
+entry  The entry whose attributes are to be stepped through, as returned
+       by ldap_first_entry() or ldap_next_entry().
+
+ptr    In ldap_first_attribute(), the address of a pointer used inter-
+       nally to keep track of the current position in the entry. In
+       ldap_next_attribute(), the pointer returned by a previous call to
+       ldap_first_attribute().  The BerElement type itself is an opaque
+       structure that is described in more detail later in this document
+       in the section "Encoded ASN.1 Value Manipulation".
+
+mem    A pointer to memory allocated by the LDAP library, such as the
+       attribute type names returned by ldap_first_attribute() and
+       ldap_next_attribute, or the DN returned by ldap_get_dn().  If mem
+       is NULL, nothing is done.
+
+ldap_first_attribute() and ldap_next_attribute() will return NULL when
+the end of the attributes is reached, or if there is an error, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+
+
+
+Expires: 2 December 1999                                       [Page 49]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+Both routines return a pointer to an allocated buffer containing the
+current attribute name. This should be freed when no longer in use by
+calling ldap_memfree().
+
+ldap_first_attribute() will allocate and return in ptr a pointer to a
+BerElement used to keep track of the current position. This pointer
+should be passed in subsequent calls to ldap_next_attribute() to step
+through the entry's attributes. After a set of calls to
+ldap_first_attribute() and ldap_next_attribute(), if ptr is non-NULL, it
+should be freed by calling ber_free( ptr, 0 ). Note that it is very
+important to pass the second parameter as 0 (zero) in this call, since
+the buffer associated with the BerElement does not point to separately
+allocated memory.
+
+The attribute type names returned are suitable for passing in a call to
+ldap_get_values() and friends to retrieve the associated values.
+
+
+15.3.  Retrieving the Values of an Attribute
+
+ldap_get_values() and ldap_get_values_len() are used to retrieve the
+values of a given attribute from an entry. ldap_count_values() and
+ldap_count_values_len() are used to count the returned values.
+ldap_value_free() and ldap_value_free_len() are used to free the values.
+
+           char **ldap_get_values(
+                   LDAP            *ld,
+                   LDAPMessage     *entry,
+                   const char      *attr
+           );
+
+           struct berval **ldap_get_values_len(
+                   LDAP            *ld,
+                   LDAPMessage     *entry,
+                   const char      *attr
+           );
+
+           int ldap_count_values( char **vals );
+
+           int ldap_count_values_len( struct berval **vals );
+
+           void ldap_value_free( char **vals );
+
+           void ldap_value_free_len( struct berval **vals );
+
+Parameters are:
+
+ld     The session handle.
+
+
+
+Expires: 2 December 1999                                       [Page 50]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+entry  The entry from which to retrieve values, as returned by
+       ldap_first_entry() or ldap_next_entry().
+
+attr   The attribute whose values are to be retrieved, as returned by
+       ldap_first_attribute() or ldap_next_attribute(), or a caller-
+       supplied string (e.g., "mail").
+
+vals   The values returned by a previous call to ldap_get_values() or
+       ldap_get_values_len().
+
+Two forms of the various calls are provided. The first form is only
+suitable for use with non-binary character string data. The second _len
+form is used with any kind of data.
+
+ldap_get_values() and ldap_get_values_len() return NULL if no values are
+found for attr or if an error occurs.
+
+ldap_count_values() and ldap_count_values_len() return -1 if an error
+occurs such as the vals parameter being invalid.
+
+Note that the values returned are dynamically allocated and should be
+freed by calling either ldap_value_free() or ldap_value_free_len() when
+no longer in use.
+
+
+15.4.  Retrieving the name of an entry
+
+ldap_get_dn() is used to retrieve the name of an entry.
+ldap_explode_dn() and ldap_explode_rdn() are used to break up a name
+into its component parts. ldap_dn2ufn() is used to convert the name into
+a more "user friendly" format.
+
+           char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
+
+           char **ldap_explode_dn( const char *dn, int notypes );
+
+           char **ldap_explode_rdn( const char *rdn, int notypes );
+
+           char *ldap_dn2ufn( const char *dn );
+
+Parameters are:
+
+ld      The session handle.
+
+entry   The entry whose name is to be retrieved, as returned by
+        ldap_first_entry() or ldap_next_entry().
+
+dn      The dn to explode, such as returned by ldap_get_dn().
+
+
+
+Expires: 2 December 1999                                       [Page 51]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+rdn     The rdn to explode, such as returned in the components of the
+        array returned by ldap_explode_dn().
+
+notypes A boolean parameter, if non-zero indicating that the dn or rdn
+        components should have their type information stripped off
+        (i.e., "cn=Babs" would become "Babs").
+
+ldap_get_dn() will return NULL if there is some error parsing the dn,
+setting error parameters in the session handle ld to indicate the error.
+It returns a pointer to newly allocated space that the caller should
+free by calling ldap_memfree() when it is no longer in use.  Note the
+format of the DNs returned is given by [4].
+
+ldap_explode_dn() returns a NULL-terminated char * array containing the
+RDN components of the DN supplied, with or without types as indicated by
+the notypes parameter. The components are returned in the order they
+appear in the dn.  The array returned should be freed when it is no
+longer in use by calling ldap_value_free().
+
+ldap_explode_rdn() returns a NULL-terminated char * array containing the
+components of the RDN supplied, with or without types as indicated by
+the notypes parameter. The components are returned in the order they
+appear in the rdn.  The array returned should be freed when it is no
+longer in use by calling ldap_value_free().
+
+ldap_dn2ufn() converts the DN into the user friendly format described in
+[5]. The UFN returned is newly allocated space that should be freed by a
+call to ldap_memfree() when no longer in use.
+
+
+15.5.  Retrieving controls from an entry
+
+ldap_get_entry_controls() is used to extract LDAP controls from an
+entry.
+
+
+           int ldap_get_entry_controls(
+                   LDAP            *ld,
+                   LDAPMessage     *entry,
+                   LDAPControl     ***serverctrlsp
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+entry        The entry to extract controls from, as returned by
+             ldap_first_entry() or ldap_next_entry().
+
+
+
+Expires: 2 December 1999                                       [Page 52]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+serverctrlsp This result parameter will be filled in with an allocated
+             array of controls copied out of entry. The control array
+             should be freed by calling ldap_controls_free().  If ser-
+             verctrlsp is NULL, no controls are returned.
+
+ldap_get_entry_controls() returns an LDAP error code that indicates
+whether the reference could be successfully parsed (LDAP_SUCCESS if all
+goes well).
+
+
+
+15.6.  Parsing References
+
+ldap_parse_reference() is used to extract referrals and controls from a
+SearchResultReference message.
+
+
+           int ldap_parse_reference(
+                   LDAP            *ld,
+                   LDAPMessage     *ref,
+                   char            ***referralsp,
+                   LDAPControl     ***serverctrlsp,
+                   int             freeit
+           );
+
+Parameters are:
+
+ld           The session handle.
+
+ref          The reference to parse, as returned by ldap_result(),
+             ldap_first_reference(), or ldap_next_reference().
+
+referralsp   This result parameter will be filled in with an allocated
+             array of character strings.  The elements of the array are
+             the referrals (typically LDAP URLs) contained in ref.  The
+             array should be freed when no longer in used by calling
+             ldap_value_free().  If referralsp is NULL, the referral
+             URLs are not returned.
+
+serverctrlsp This result parameter will be filled in with an allocated
+             array of controls copied out of ref. The control array
+             should be freed by calling ldap_controls_free().  If ser-
+             verctrlsp is NULL, no controls are returned.
+
+freeit       A boolean that determines whether the ref parameter is
+             disposed of or not.  Pass any non-zero value to have this
+             routine free ref after extracting the requested informa-
+             tion.  This is provided as a convenience; you can also use
+
+
+
+Expires: 2 December 1999                                       [Page 53]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+             ldap_msgfree() to free the result later.
+
+ldap_parse_reference() returns an LDAP error code that indicates whether
+the reference could be successfully parsed (LDAP_SUCCESS if all goes
+well).
+
+
+16.  Encoded ASN.1 Value Manipulation
+
+This section describes routines which may be used to encode and decode
+BER-encoded ASN.1 values, which are often used inside of control and
+extension values.
+
+With the exceptions of two new functions ber_flatten() and ber_init(),
+these functions are compatible with the University of Michigan LDAP 3.3
+implementation of BER.
+
+
+16.1.  General
+
+           struct berval {
+                   ber_len_t       bv_len;
+                   char            *bv_val;
+           };
+
+As defined earlier in the section "Common Data Structures", a struct
+berval contains an arbitrary sequence of bytes and an indication of its
+length.  The bv_len element is an unsigned integer.  The bv_val is not
+necessarily zero-terminated.  Applications may allocate their own berval
+structures.
+
+As defined earlier in the section "Common Data Structures", the BerEle-
+ment structure is an opaque structure:
+
+           typedef struct berelement BerElement;
+
+It contains not only a copy of the encoded value, but also state infor-
+mation used in encoding or decoding.  Applications cannot allocate their
+own BerElement structures.  The internal state is neither thread-
+specific nor locked, so two threads should not manipulate the same
+BerElement value simultaneously.
+
+A single BerElement value cannot be used for both encoding and decoding.
+
+           void ber_bvfree( struct berval *bv );
+
+ber_bvfree() frees a berval returned from this API.  Both the bv->bv_val
+string and the berval itself are freed.  Applications should not use
+
+
+
+Expires: 2 December 1999                                       [Page 54]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+ber_bvfree() with bervals which the application has allocated.
+
+           void ber_bvecfree( struct berval **bv );
+
+ber_bvecfree() frees an array of bervals returned from this API.  Each
+of the bervals in the array are freed using ber_bvfree(), then the array
+itself is freed.
+
+           struct berval *ber_bvdup( const struct berval *bv );
+
+ber_bvdup() returns a copy of a berval.  The bv_val field in the
+returned berval points to a different area of memory than the bv_val
+field in the argument berval.  The NULL pointer is returned on error
+(e.g. out of memory).
+
+           void ber_free( BerElement *ber, int fbuf );
+
+ber_free() frees a BerElement which is returned from the API calls
+ber_alloc_t() or ber_init().  Each BerElement must be freed by the
+caller.  The second argument fbuf should always be set to 1 to ensure
+that the internal buffer used by the BER functions is freed as well as
+the BerElement container itself.
+
+
+16.2.  Encoding
+
+           BerElement *ber_alloc_t( int options );
+
+ber_alloc_t() constructs and returns BerElement.  The NULL pointer is
+returned on error.  The options field contains a bitwise-or of options
+which are to be used when generating the encoding of this BerElement.
+One option is defined and must always be supplied:
+
+           #define LBER_USE_DER 0x01
+
+When this option is present, lengths will always be encoded in the
+minimum number of octets.  Note that this option does not cause values
+of sets to be rearranged in tag and byte order or default values to be
+removed, so these functions are not sufficient for generating DER output
+as defined in X.509 and X.680.  If the caller takes responsibility for
+ordering values of sets correctly and removing default values, DER out-
+put as defined in X.509 and X.680 can be produced.
+
+Unrecognized option bits are ignored.
+
+The BerElement returned by ber_alloc_t() is initially empty.  Calls to
+ber_printf() will append bytes to the end of the ber_alloc_t().
+
+
+
+
+Expires: 2 December 1999                                       [Page 55]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+           int ber_printf( BerElement *ber, const char *fmt, ... )
+
+The ber_printf() routine is used to encode a BER element in much the
+same way that sprintf() works.  One important difference, though, is
+that state information is kept in the ber argument so that multiple
+calls can be made to ber_printf() to append to the end of the BER ele-
+ment. ber must be a pointer to a BerElement returned by ber_alloc_t().
+ber_printf() interprets and formats its arguments according to the for-
+mat string fmt.  ber_printf() returns -1 if there is an error during
+encoding and a positive number if successful.  As with sprintf(), each
+character in fmt refers to an argument to ber_printf().
+
+The format string can contain the following format characters:
+
+'t'     Tag.  The next argument is a ber_tag_t specifying the tag to
+        override the next element to be written to the ber.  This works
+        across calls.  The integer tag value must contain the tag class,
+        constructed bit, and tag value.  For example, a tag of "[3]" for
+        a constructed type is 0xA3.  All implementations must support
+        tags that fit in a single octet (i.e., where the tag value is
+        less than 32) and they may support larger tags.
+
+'b'     Boolean.  The next argument is an int, containing either 0 for
+        FALSE or 0xff for TRUE.  A boolean element is output.  If this
+        format character is not preceded by the 't' format modifier, the
+        tag 0x01 is used for the element.
+
+'i'     Integer.  The next argument is an int, containing the integer in
+        the host's byte order.  An integer element is output. If this
+        format character is not preceded by the 't' format modifier, the
+        tag 0x02 is used for the element.
+
+'X'     Bitstring.  The next two arguments are a char * pointer to the
+        start of the bitstring, followed by an int containing the number
+        of bits in the bitstring.  A bitstring element is output, in
+        primitive form.  If this format character is not preceded by the
+        't' format modifier, the tag 0x03 is used for the element.
+
+'n'     Null.  No argument is required.  An ASN.1 NULL element is out-
+        put.  If this format character is not preceded by the 't' format
+        modifier, the tag 0x05 is used for the element.
+
+'o'     Octet string.  The next two arguments are a char *, followed by
+        an int with the length of the string.  The string may contain
+        null bytes and need not be zero-terminated.   An octet string
+        element is output, in primitive form.  If this format character
+        is not preceded by the 't' format modifier, the tag 0x04 is used
+        for the element.
+
+
+
+Expires: 2 December 1999                                       [Page 56]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+'s'     Octet string.  The next argument is a char * pointing to a
+        zero-terminated string.  An octet string element in primitive
+        form is output, which does not include the trailing '\0' (null)
+        byte. If this format character is not preceded by the 't' format
+        modifier, the tag 0x04 is used for the element.
+
+'v'     Several octet strings.  The next argument is a char **, an array
+        of char * pointers to zero-terminated strings.  The last element
+        in the array must be a NULL pointer. The octet strings do not
+        include the trailing '\0' (null) byte.  Note that a construct
+        like '{v}' is required to get an actual SEQUENCE OF octet
+        strings.  The 't' format modifier cannot be used with this for-
+        mat character.
+
+'V'     Several octet strings.  A NULL-terminated array of berval *'s is
+        supplied. Note that a construct like '{V}' is required to get an
+        actual SEQUENCE OF octet strings. The 't' format modifier cannot
+        be used with this format character.
+
+'{'     Begin sequence.  No argument is required.  If this format char-
+        acter is not preceded by the 't' format modifier, the tag 0x30
+        is used.
+
+'}'     End sequence.  No argument is required.  The 't' format modifier
+        cannot be used with this format character.
+
+'['     Begin set.  No argument is required.  If this format character
+        is not preceded by the 't' format modifier, the tag 0x31 is
+        used.
+
+']'     End set.  No argument is required.  The 't' format modifier can-
+        not be used with this format character.
+
+Each use of a '{' format character must be matched by a '}' character,
+either later in the format string, or in the format string of a subse-
+quent call to ber_printf() for that BerElement.  The same applies to the
+'[' and ']' format characters.
+
+Sequences and sets nest, and implementations of this API must maintain
+internal state to be able to properly calculate the lengths.
+
+           int ber_flatten( const BerElement *ber, struct berval **bvPtr );
+
+The ber_flatten routine allocates a struct berval whose contents are a
+BER encoding taken from the ber argument. The bvPtr pointer points to
+the returned berval, which must be freed using ber_bvfree().  This rou-
+tine returns 0 on success and -1 on error.
+
+
+
+
+Expires: 2 December 1999                                       [Page 57]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+The ber_flatten API call is not present in U-M LDAP 3.3.
+
+The use of ber_flatten on a BerElement in which all '{' and '}' format
+modifiers have not been properly matched is an error (i.e., -1 will be
+returned by ber_flatten() if this situation is exists).
+
+
+16.3.  Encoding Example
+
+The following is an example of encoding the following ASN.1 data type:
+
+      Example1Request ::= SEQUENCE {
+           s     OCTET STRING, -- must be printable
+           val1  INTEGER,
+           val2  [0] INTEGER DEFAULT 0
+      }
+
+
+      int encode_example1(const char *s,int val1,int val2,struct berval **bvPtr)
+      {
+           BerElement *ber;
+           int rc = -1;
+
+           ber = ber_alloc_t(LBER_USE_DER);
+
+           if (ber == NULL) return -1;
+
+           if (ber_printf(ber,"{si",s,val1) == -1) {
+                   goto done;
+           }
+
+           if (val2 != 0) {
+                   if (ber_printf(ber,"ti",0x80,val2) == -1) {
+                           goto done;
+                   }
+           }
+
+           if (ber_printf(ber,"}") == -1) {
+                   goto done;
+           }
+
+           rc = ber_flatten(ber,bvPtr);
+
+   done:
+           ber_free(ber,1);
+           return rc;
+      }
+
+
+
+
+Expires: 2 December 1999                                       [Page 58]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+16.4.  Decoding
+
+The following two symbols are available to applications.
+
+           #define LBER_ERROR   (ber_tag_t)0xffffffff
+           #define LBER_DEFAULT (ber_tag_t)0xffffffff
+
+           BerElement *ber_init( const struct berval *bv );
+
+The ber_init function constructs a BerElement and returns a new BerEle-
+ment containing a copy of the data in the bv argument.  ber_init returns
+the NULL pointer on error.
+
+           ber_tag_t ber_scanf( BerElement *ber, const char *fmt, ... );
+
+The ber_scanf() routine is used to decode a BER element in much the same
+way that sscanf() works.  One important difference, though, is that some
+state information is kept with the ber argument so that multiple calls
+can be made to ber_scanf() to sequentially read from the BER element.
+The ber argument must be a pointer to a BerElement returned by
+ber_init().  ber_scanf interprets the bytes according to the format
+string fmt, and stores the results in its additional arguments.
+ber_scanf() returns LBER_ERROR on error, and a different value on suc-
+cess.
+
+The format string contains conversion specifications which are used to
+direct the interpretation of the BER element.  The format string can
+contain the following characters:
+
+'a'     Octet string.  A char ** argument should be supplied.  Memory is
+        allocated, filled with the contents of the octet string, zero-
+        terminated, and the pointer to the string is stored in the argu-
+        ment.  The returned value must be freed using ldap_memfree.  The
+        tag of the element must indicate the primitive form (constructed
+        strings are not supported) but is otherwise ignored and dis-
+        carded during the decoding.  This format cannot be used with
+        octet strings which could contain null bytes.
+
+'O'     Octet string.  A struct berval ** argument should be supplied,
+        which upon return points to an allocated struct berval contain-
+        ing the octet string and its length.  ber_bvfree() must be
+        called to free the allocated memory.  The tag of the element
+        must indicate the primitive form (constructed strings are not
+        supported) but is otherwise ignored during the decoding.
+
+'b'     Boolean.  A pointer to an int should be supplied. The int value
+        stored will be 0 for FALSE or nonzero for TRUE.  The tag of the
+        element must indicate the primitive form but is otherwise
+
+
+
+Expires: 2 December 1999                                       [Page 59]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+        ignored during the decoding.
+
+'i'     Integer.  A pointer to an int should be supplied. The int value
+        stored will be in host byte order.  The tag of the element must
+        indicate the primitive form but is otherwise ignored during the
+        decoding.  ber_scanf() will return an error if the integer can-
+        not be stored in an int.
+
+'B'     Bitstring.  A char ** argument should be supplied which will
+        point to the allocated bits, followed by a ber_len_t * argument,
+        which will point to the length (in bits) of the bitstring
+        returned.  ldap_memfree must be called to free the bitstring.
+        The tag of the element must indicate the primitive form (con-
+        structed bitstrings are not supported) but is otherwise ignored
+        during the decoding.
+
+'n'     Null.  No argument is required.  The element is verified to have
+        a zero-length value and is skipped.  The tag is ignored.
+
+'v'     Several octet strings.  A char *** argument should be supplied,
+        which upon return points to an allocated NULL-terminated array
+        of char *'s containing the octet strings.  NULL is stored if the
+        sequence is empty.  ldap_memfree must be called to free each
+        element of the array and the array itself.  The tag of the
+        sequence and of the octet strings are ignored.
+
+'V'     Several octet strings (which could contain null bytes).  A
+        struct berval *** should be supplied, which upon return points
+        to a allocated NULL-terminated array of struct berval *'s con-
+        taining the octet strings and their lengths.  NULL is stored if
+        the sequence is empty. ber_bvecfree() can be called to free the
+        allocated memory.  The tag of the sequence and of the octet
+        strings are ignored.
+
+'x'     Skip element.  The next element is skipped.  No argument is
+        required.
+
+'{'     Begin sequence.  No argument is required.  The initial sequence
+        tag and length are skipped.
+
+'}'     End sequence.  No argument is required.
+
+'['     Begin set.  No argument is required.  The initial set tag and
+        length are skipped.
+
+']'     End set.  No argument is required.
+
+           ber_tag_t ber_peek_tag( const BerElement *ber,
+
+
+
+Expires: 2 December 1999                                       [Page 60]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+               ber_len_t *lenPtr );
+
+ber_peek_tag() returns the tag of the next element to be parsed in the
+BerElement argument.  The length of this element is stored in the
+*lenPtr argument.  LBER_DEFAULT is returned if there is no further data
+to be read.  The ber argument is not modified.
+
+           ber_tag_t ber_skip_tag( BerElement *ber, ber_len_t *lenPtr );
+
+ber_skip_tag() is similar to ber_peek_tag(), except that the state
+pointer in the BerElement argument is advanced past the first tag and
+length, and is pointed to the value part of the next element.  This rou-
+tine should only be used with constructed types and situations when a
+BER encoding is used as the value of an OCTET STRING.  The length of the
+value is stored in *lenPtr.
+
+           ber_tag_t ber_first_element( BerElement *ber,
+                   ber_len_t *lenPtr, char **opaquePtr );
+
+           ber_tag_t ber_next_element( BerElement *ber,
+                   ber_len_t *lenPtr, char *opaque );
+
+ber_first_element() and ber_next_element() are used to traverse a SET,
+SET OF, SEQUENCE or SEQUENCE OF data value. ber_first_element() calls
+ber_skip_tag(), stores internal information in *lenPtr and *opaquePtr,
+and calls ber_peek_tag() for the first element inside the constructed
+value. LBER_DEFAULT is returned if the constructed value is empty.
+ber_next_element() positions the state at the start of the next element
+in the constructed type.  LBER_DEFAULT is returned if there are no
+further values.
+
+The len and opaque values should not be used by applications other than
+as arguments to ber_next_element(), as shown in the example below.
+
+
+16.5.  Decoding Example
+
+The following is an example of decoding an ASN.1 data type:
+
+      Example2Request ::= SEQUENCE {
+           dn    OCTET STRING, -- must be printable
+           scope ENUMERATED { b (0), s (1), w (2) },
+           ali   ENUMERATED { n (0), s (1), f (2), a (3) },
+           size  INTEGER,
+           time  INTEGER,
+           tonly BOOLEAN,
+           attrs SEQUENCE OF OCTET STRING, -- must be printable
+           [0] SEQUENCE OF SEQUENCE {
+
+
+
+Expires: 2 December 1999                                       [Page 61]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+              type  OCTET STRING -- must be printable,
+              crit  BOOLEAN DEFAULT FALSE,
+              value OCTET STRING
+           } OPTIONAL }
+
+      #define TAG_CONTROL_LIST 0xA0L /* context specific cons 0 */
+
+      int decode_example2(struct berval *bv)
+      {
+           BerElement *ber;
+           ber_len_t len;
+           ber_tag_t res;
+           int scope, ali, size, time, tonly;
+           char *dn = NULL, **attrs = NULL;
+           int i,rc = 0;
+
+           ber = ber_init(bv);
+           if (ber == NULL) {
+                   fputs("ERROR ber_init failed\n", stderr);
+                   return -1;
+           }
+
+           res = ber_scanf(ber,"{aiiiib{v}",&dn,&scope,&ali,
+                           &size,&time,&tonly,&attrs);
+
+           if (res == LBER_ERROR) {
+                   fputs("ERROR ber_scanf failed\n", stderr);
+                   ber_free(ber,1);
+                   return -1;
+           }
+
+           /* *** use dn */
+           ldap_memfree(dn);
+
+           for (i = 0; attrs != NULL && attrs[i] != NULL; i++) {
+                   /* *** use attrs[i] */
+                   ldap_memfree(attrs[i]);
+           }
+           ldap_memfree(attrs);
+
+           if (ber_peek_tag(ber,&len) == TAG_CONTROL_LIST) {
+                   char *opaque;
+                   ber_tag_t tag;
+
+                   for (tag = ber_first_element(ber,&len,&opaque);
+                        tag != LBER_DEFAULT;
+                        tag = ber_next_element (ber,&len,opaque)) {
+
+
+
+
+Expires: 2 December 1999                                       [Page 62]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                           ber_len_t tlen;
+                           ber_tag_t ttag;
+                           char *type;
+                           int crit;
+                           struct berval *value;
+
+                           if (ber_scanf(ber,"{a",&type) == LBER_ERROR) {
+                                   fputs("ERROR cannot parse type\n", stderr);
+                                   break;
+                           }
+                           /* *** use type */
+                           ldap_memfree(type);
+
+                           ttag = ber_peek_tag(ber,&tlen);
+                           if (ttag == 0x01) {  /* boolean */
+                                   if (ber_scanf(ber,"b",
+                                                 &crit) == LBER_ERROR) {
+                                           fputs("ERROR cannot parse crit\n",
+                                               stderr);
+                                           rc = -1;
+                                           break;
+                                   }
+                           } else if (ttag == 0x04) { /* octet string */
+                                   crit = 0;
+                           } else {
+                                   fputs("ERROR extra field in controls\n",
+                                       stderr );
+                                   break;
+                           }
+
+                           if (ber_scanf(ber,"O}",&value) == LBER_ERROR) {
+                                   fputs("ERROR cannot parse value\n", stderr);
+                                   rc = -1;
+                                   break;
+                           }
+                           /* *** use value */
+                           ber_bvfree(value);
+                   }
+           }
+
+           ber_scanf(ber,"}");
+
+           ber_free(ber,1);
+
+           return rc;
+       }
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 63]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+17.  Security Considerations
+
+LDAPv2 supports security through protocol-level authentication using
+clear-text passwords.  LDAPv3 adds support for SASL [8] (Simple Authen-
+tication Security Layer) methods.  LDAPv3 also supports operation over a
+secure transport layer using Transport Layer Security TLS [9].  Readers
+are referred to the protocol documents for discussion of related secu-
+rity considerations.
+
+Implementations of this API should be cautious when handling authentica-
+tion credentials.  In particular, keeping long-lived copies of creden-
+tials without the application's knowledge is discouraged.
+
+
+18.  Acknowledgements
+
+Many members of the IETF ASID and LDAPEXT working groups as well as
+members of the Internet at large have provided useful comments and
+suggestions that have been incorporated into this document.  Chris
+Weider deserves special mention for his contributions as co-author of
+earlier revisions of this document.
+
+The original material upon which this specification is based was sup-
+ported by the National Science Foundation under Grant No.  NCR-9416667.
+
+
+19.  Copyright
+
+Copyright (C) The Internet Society (1997-1999). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to oth-
+ers, and derivative works that comment on or otherwise explain it or
+assist in its implementation may be prepared, copied, published and dis-
+tributed, 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 Stan-
+dards 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 INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK
+
+
+
+Expires: 2 December 1999                                       [Page 64]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+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 FIT-
+NESS FOR A PARTICULAR PURPOSE.
+
+
+20.  Bibliography
+
+[1]  The Directory: Selected Attribute Syntaxes.  CCITT, Recommendation
+     X.520.
+
+[2]  M. Wahl, A. Coulbeck, T. Howes, S. Kille, W. Yeong, C. Robbins,
+     "Lightweight Directory Access Protocol (v3): Attribute Syntax
+     Definitions", RFC 2252, December 1997.
+
+[3]  T. Howes, "The String Representation of LDAP Search Filters," RFC
+     2254, December 1997.
+
+[4]  M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol
+     (v3): A UTF-8 String Representation of Distinguished Names", RFC
+     2253, December 1997.
+
+[5]  S. Kille, "Using the OSI Directory to Achieve User Friendly Nam-
+     ing," RFC 1781, March 1995.
+
+[6]  M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
+     (v3)", RFC 2251, December 1997.
+
+[7]  A. Herron, T. Howes, M. Wahl, C. Weider, A. Anantha, "LDAP Control
+     Extension for Server Side Sorting of Search Results", INTERNET-
+     DRAFT <draft-ietf-ldapext-sorting-01.txt>, 7 August 1998.
+
+[8]  J. Meyers, "Simple Authentication and Security Layer (SASL)", RFC
+     2222, October 1997.
+
+[9]  "Lightweight Directory Access Protocol (v3): Extension for Tran-
+     sport Layer Security", INTERNET-DRAFT <draft-ietf-ldapext-ldapv3-
+     tls-04.txt>, November 1998.
+
+[10] "UTF-8, a transformation format of Unicode and ISO 10646", RFC
+     2044, October 1996.
+
+[11] "IP Version 6 Addressing Architecture,", RFC 1884, December 1995.
+
+[12] "Character Mnemonics and Character Sets," RFC 1345, June 1992.
+
+[13] "Programming Languages - C", ANSI/ISO Standard 9899, revised 1997.
+
+
+
+
+Expires: 2 December 1999                                       [Page 65]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+21.  Authors' Addresses
+
+   Mark Smith (document editor)
+   Netscape Communications Corp.
+   501 E. Middlefield Rd., Mailstop MV068
+   Mountain View, CA 94043
+   USA
+   +1 650 937-3477
+   mcs@netscape.com
+
+   Tim Howes
+   Netscape Communications Corp.
+   501 E. Middlefield Rd., Mailstop MV068
+   Mountain View, CA 94043
+   USA
+   +1 650 937-3419
+   howes@netscape.com
+
+   Andy Herron
+   Microsoft Corp.
+   1 Microsoft Way
+   Redmond, WA 98052
+   USA
+   +1 425 882-8080
+   andyhe@microsoft.com
+
+   Mark Wahl
+   Innosoft International, Inc.
+   8911 Capital of Texas Hwy, Suite 4140
+   Austin, TX 78759
+   USA
+   +1 626 919 3600
+   Mark.Wahl@innosoft.com
+
+   Anoop Anantha
+   Microsoft Corp.
+   1 Microsoft Way
+   Redmond, WA 98052
+   USA
+   +1 425 882-8080
+   anoopa@microsoft.com
+
+
+22.  Appendix A - Sample C LDAP API Code
+
+   #include <stdio.h>
+   #include <ldap.h>
+
+
+
+
+Expires: 2 December 1999                                       [Page 66]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   main()
+   {
+           LDAP            *ld;
+           LDAPMessage     *res, *e;
+           int             i, rc;
+           char            *a, *dn;
+           BerElement      *ptr;
+           char            **vals;
+
+           /* open an LDAP session */
+           if ( (ld = ldap_init( "dotted.host.name", LDAP_PORT )) == NULL )
+                   return 1;
+
+           /* authenticate as nobody */
+           if (( rc = ldap_simple_bind_s( ld, NULL, NULL )) != LDAP_SUCCESS ) {
+                   fprintf( stderr, "ldap_simple_bind_s: %s\n",
+                       ldap_err2string( rc ));
+                   ldap_unbind( ld );
+                   return 1;
+           }
+
+           /* search for entries with cn of "Babs Jensen", return all attrs  */
+           if (( rc = ldap_search_s( ld, "o=University of Michigan, c=US",
+               LDAP_SCOPE_SUBTREE, "(cn=Babs Jensen)", NULL, 0, &res ))
+               != LDAP_SUCCESS ) {
+                   fprintf( stderr, "ldap_search_s: %s\n",
+                       ldap_err2string( rc ));
+                   if ( res == NULL ) {
+                           ldap_unbind( ld );
+                           return 1;
+                   }
+           }
+
+           /* step through each entry returned */
+           for ( e = ldap_first_entry( ld, res ); e != NULL;
+               e = ldap_next_entry( ld, e ) ) {
+                   /* print its name */
+                   dn = ldap_get_dn( ld, e );
+                   printf( "dn: %s\n", dn );
+                   ldap_memfree( dn );
+
+                   /* print each attribute */
+                   for ( a = ldap_first_attribute( ld, e, &ptr ); a != NULL;
+                       a = ldap_next_attribute( ld, e, ptr ) ) {
+                           printf( "\tattribute: %s\n", a );
+
+                           /* print each value */
+                           vals = ldap_get_values( ld, e, a );
+
+
+
+Expires: 2 December 1999                                       [Page 67]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+                           for ( i = 0; vals[i] != NULL; i++ ) {
+                                   printf( "\t\tvalue: %s\n", vals[i] );
+                           }
+                           ldap_value_free( vals );
+                           ldap_memfree( a );
+                   }
+                   if ( ptr != NULL ) {
+                           ber_free( ptr, 0 );
+                   }
+           }
+           /* free the search results */
+           ldap_msgfree( res );
+
+           /* close and free connection resources */
+           ldap_unbind( ld );
+
+           return 0;
+   }
+
+
+23.  Appendix B - Namespace Consumed By This Specification
+
+The following 2 prefixes are used in this specification to name func-
+tions:
+   ldap_
+   ber_
+
+The following 6 prefixes are used in this specification to name struc-
+tures, unions, and typedefs:
+   ldap
+   LDAP
+   PLDAP
+   ber
+   Ber
+   timeval
+
+The following 3 prefixes are used in this specification to name #defined
+macros:
+   LDAP
+   LBER_
+   mod_
+
+
+24.  Appendix C - Summary of Requirements for API Extensions
+
+As the LDAP protocol is extended, this C LDAP API will need to be
+extended as well.  For example, an LDAPv3 control extension has already
+been defined for server-side sorting of search results [7].  This
+
+
+
+Expires: 2 December 1999                                       [Page 68]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+appendix summarizes the requirements for extending this API.
+
+24.1.  Compatibility
+
+Extensions to this document should not, by default, alter the behavior
+of any of the APIs specified in this document.  If an extension option-
+ally changes the behavior of any existing C LDAP API function calls, the
+behavior change must be well documented.
+
+24.2.  Style
+
+Extensions to this API should follow the general style and naming con-
+ventions used in this document.  For example, function names should
+start with "ldap_" or "ber_" and consist entirely of lowercase letters,
+digits, and underscore ('_') characters.  More information can be found
+in the preceding appendix called "Namespace Consumed By This Specifica-
+tion."
+
+24.3.  Dependence on Externally Defined Types
+
+Extensions to this API should minimize dependencies on types and macros
+that are defined in system header files and generally use only intrinsic
+types that are part of the C language, types defined in this specifica-
+tion, or types defined in the extension document itself.
+
+24.4.  Compile Time Information
+
+Extensions to this API should conform to the requirements contained in
+the "Retrieving Information at Compile Time" section of this document.
+That is, extensions should define a macro of the form:
+
+   #define LDAP_API_FEATURE_x level
+
+so that applications can detect the presence or absence of the extension
+at compile time and also test the version or level of the extension pro-
+vided by an API implementation.
+
+24.5.  Runtime Information
+
+Extensions to this API should conform to the requirements contained in
+the "Retrieving Information During Execution" section of this document.
+That is, each extension should be given a character string name and that
+name should appear in the ldapai_extensions array field of the LDAPAPI-
+Info structure following a successful call to ldap_get_option() with an
+option parameter value of LDAP_OPT_API_INFO.  In addition, information
+about the extension should be available via a call to ldap_get_option()
+with an option parameter value of LDAP_OPT_API_FEATURE_INFO.
+
+
+
+
+Expires: 2 December 1999                                       [Page 69]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+24.6.  Values Used for Session Handle Options
+
+Extensions to this API that add new session options (for use with the
+ldap_get_option() and ldap_set_option() functions) should meet the
+requirements contained in the last paragraph of the "LDAP Session Handle
+Options" section of this document.  Specifically, standards track docu-
+ments MUST use values for option macros that are between 0x1000 and
+0x3FFF inclusive and private and experimental extensions MUST use values
+for the option macros that are between 0x4000 and 0x7FFF inclusive.
+
+
+25.  Appendix D - Known Incompatibilities with RFC 1823
+
+This appendix lists known incompatibilities between this API specifica-
+tion and the one contained in RFC 1823, beyond the additional API func-
+tions added in support of LDAPv3.
+
+
+25.1.  Opaque LDAP Structure
+
+In RFC 1823, some fields in the LDAP structure were exposed to applica-
+tion programmers.  To provide a cleaner interface and to make it easier
+for implementations to evolve over time without sacrificing binary com-
+patibility with older applications, the LDAP structure is now entirely
+opaque.  The new ldap_set_option() and ldap_get_option() calls can be
+used to manipulate per-session and global options.
+
+
+25.2.  Additional Error Codes
+
+The following new error code macros were introduced to support LDAPv3:
+   LDAP_REFERRAL
+   LDAP_ADMINLIMIT_EXCEEDED
+   LDAP_UNAVAILABLE_CRITICAL_EXTENSION
+   LDAP_CONFIDENTIALITY_REQUIRED
+   LDAP_SASL_BIND_IN_PROGRESS
+   LDAP_AFFECTS_MULTIPLE_DSAS
+   LDAP_CONNECT_ERROR
+   LDAP_NOT_SUPPORTED
+   LDAP_CONTROL_NOT_FOUND
+   LDAP_NO_RESULTS_RETURNED
+   LDAP_MORE_RESULTS_TO_RETURN
+   LDAP_CLIENT_LOOP
+   LDAP_REFERRAL_LIMIT_EXCEEDED
+
+
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 70]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+25.3.  Freeing of String Data with ldap_memfree()
+
+All strings received from the API (e.g., those returned by the
+ldap_get_dn() or ldap_dn2ufn() functions) should be freed by calling
+ldap_memfree() not free().  RFC 1823 did not define an ldap_memfree()
+function.
+
+
+25.4.  Changes to ldap_result()
+
+The meaning of the all parameter to ldap_result has changed slightly.
+Nonzero values from RFC 1823 correspond to LDAP_MSG_ALL (0x01).  There
+is also a new possible value, LDAP_MSG_RECEIVED (0x02).
+
+The result type LDAP_RES_MODDN is now returned where RFC 1823 returned
+LDAP_RES_MODRDN.  The actual value for these two macros is the same
+(0x6D).
+
+
+25.5.  Changes to ldap_first_attribute() and ldap_next_attribute
+
+Each non-NULL return value should be freed by calling ldap_memfree()
+after use.  In RFC 1823, these two functions returned a pointer to a
+per-session buffer, which was not very thread-friendly.
+
+After the last call to ldap_first_attribute() or ldap_next_attribute(),
+the value set in the ptr parameter should be freed by calling ber_free(
+ptr, 0 ).  RFC 1823 did not mention that the ptr value should be freed.
+
+The type of the ptr parameter was changed from void * to BerElement *.
+
+
+25.6.  Changes to ldap_modrdn() and ldap_modrdn_s() Functions
+
+In RFC 1823, the ldap_modrdn() and ldap_modrdn_s() functions include a
+parameter called deleteoldrdn.  This does not match the great majority
+of implementations, so in this specification the deleteoldrdn parameter
+was removed from ldap_modrdn() and ldap_modrdn_s().  Two additional
+functions that support deleteoldrdn and are widely implemented as well
+were added to this specification: ldap_modrdn2() and ldap_modrdn2_s().
+
+
+25.7.  Changes to the berval structure
+
+In RFC 1823, the bv_len element of the berval structure was defined as
+an unsigned long.  In this specification, the type is implementation-
+specific, although it must be an unsigned integral type that is at least
+32 bits in size.  See the appendix "Data Types and Legacy
+
+
+
+Expires: 2 December 1999                                       [Page 71]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+Implementations" for additional considerations.
+
+
+25.8.  API Specification Clarified
+
+RFC 1823 left many things unspecified, including behavior of various
+memory disposal functions when a NULL pointer is presented, requirements
+for header files, values of many macros, and so on.  This specification
+is more complete and generally tighter than the one in RFC 1823.
+
+
+25.9.  Deprecated Functions
+
+A number of functions that are in RFC 1823 are labeled as "deprecated"
+in this specification.  In most cases, a replacement that provides
+equivalent functionality has been defined.  The deprecated functions
+are:
+
+   ldap_bind()
+           Use ldap_simple_bind() or ldap_sasl_bind() instead.
+
+   ldap_bind_s()
+           Use ldap_simple_bind_s() or ldap_sasl_bind_s() instead.
+
+   ldap_kerberos_bind() and ldap_kerberos_bind_s()
+           No equivalent functions are provided.
+
+   ldap_modrdn() and ldap_modrdn2()
+           Use ldap_rename() instead.
+
+   ldap_modrdn_s() and ldap_modrdn2_s()
+           Use ldap_rename_s() instead.
+
+   ldap_open()
+           Use ldap_init() instead.
+
+   ldap_perror()
+           Use ldap_err2string() instead.
+
+   ldap_result2error()
+           Use ldap_parse_result() instead.
+
+
+26.  Appendix E - Data Types and Legacy Implementations
+
+The data types associated with the length of a ber value (ber_len_t) and
+the tag (ber_tag_t) have been defined in this specification as unsigned
+integral types of implementation-specific size.  This was done so that
+
+
+
+Expires: 2 December 1999                                       [Page 72]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+source and binary compatibility of the C LDAP API can be maintained
+across ILP32 environments (where int, long, and pointers are all 32 bits
+in size) and LP64 environments (where ints remain 32 bits but longs and
+pointers grow to 64 bits).
+
+In older implementations of the C LDAP API, such as those based on RFC
+1823, implementors may have chosen to use an unsigned long for these
+types.  If a long data type was used, a port of an application to a 64-
+bit operating system using the LP64 data model would find the size of
+the BER length and tag types used by the C LDAP API to increase.  Also,
+if the legacy implementation had chosen to implement the types as an
+unsigned int, adoption of a specification that mandated use of unsigned
+longs would cause a source incompatibility in an LP64 application.  By
+using an implementation-specific data type, the C LDAP API implementa-
+tion is free to choose the correct data type and the ability to maintain
+source compatibility.
+
+For example, suppose a legacy implementation chose to define the return
+value of ber_skip_tag() as an unsigned long but wishes to have the
+library return a 32-bit quantity in both ILP32 and LP64 data models.
+The following typedefs for ber_tag_t will provide a fixed sized data
+structure while preserving existing ILP32 source -- all without generat-
+ing compiler warnings:
+           #if defined(_LP64)
+               typedef unsigned int ber_tag_t;
+           #else
+               typedef unsigned long ber_tag_t;
+           #endif
+The above assumes that the the preprocessor symbol _LP64 is defined if
+and only if the code is being compiled in an LP64 environment.  Similar
+code can be used to define an appropriate ber_len_t type.
+
+
+27.  Appendix F - Changes Made Since Last Document Revision
+
+The previous version of this document was draft-ietf-ldapext-ldap-c-
+api-02.txt, dated 23 February, 1999.  This appendix lists all of the
+changes made to that document to produce this one.
+
+27.1.  API Changes
+
+   Types: added the ber_len_t and ber_tag_t implementation-specific
+   unsigned integral data types to support source and binary compatibil-
+   ity between ILP32 and LP64 environments.  Changes were made to the
+   "Common Data Structures" and "Encoded ASN.1 Value Manipulation" sec-
+   tions of this document.
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 73]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+27.2.  Editorial Changes
+
+   General: Added Appendix E - Data Types and Legacy Implementations;
+   moved list of recent document changes to Appendices F and G.
+
+   "Retrieving Information During Execution" section: removed misplaced
+   ldapai_vendor_name and ldapai_vendor_version from the LDAPAPI-
+   FeatureInfo structure description.
+
+   "Extended Operations" section: changed the names of the "requestoid"
+   and "requestdata" parameters in the function prototypes to match the
+   parameter descriptions.  The old names were "exoid" and "exdata."
+
+   Appendix D - "Appendix D - Known Incompatibilities with RFC 1823 ":
+   Added note about changes to the berval structure.
+
+
+28.  Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api-
+01.txt
+
+The version of this document that preceded draft-ietf-ldapext-ldap-c-
+api-02.txt was draft-ietf-ldapext-ldap-c-api-01.txt, dated 7 August
+1998.  This appendix lists all of the changes made to that document to
+produce draft-ietf-ldapext-ldap-c-api-02.txt.
+
+
+28.1.  API Changes
+
+   General: added the 'const' keyword to function prototypes where
+   appropriate.
+
+   Added two new sections that specify additional features and require-
+   ments for API implementors:
+      "Header File Requirements"
+      "A Client Control That Governs Referral Processing"
+
+
+   LDAP_VERSION_MAX, LDAP_VENDOR_NAME, and LDAP_VENDOR_VERSION macros.
+   Corrected LDAP_API_VERSION example code to use >= instead of >.
+   Added note about what value to use for LDAP_API_VERSION prior to pub-
+   lication of this draft as an RFC (2000 + draft revision number).
+
+   "Retrieving Information During Execution" section: added
+   LDAP_API_INFO_VERSION macro and clarified the text to explain the
+   behavior when there is a mismatch between LDAPAPIInfo structure ver-
+   sions.  Added LDAP_OPT_API_FEATURE_INFO to allow applications to
+   retrieve version information about API extended features.
+
+
+
+
+Expires: 2 December 1999                                       [Page 74]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   "LDAP Session Handle Options" section:  Added macro definitions for
+   LDAP_OPT_ON and LDAP_OPT_OFF and changed the "invalue" type for
+   Boolean options from "int" to "void *".  For consistency, we now
+   require that applications dispose of "char *" and "LDAPControl *"
+   values that are returned.  Added note about which option value ranges
+   are to be used for various purposes.
+
+   "Closing the session" section: added new function ldap_unbind_ext()
+   to allow controls to be used with unbind operations.
+
+   "Searching" section: added requirement that *res be set to NULL by
+   synchronous calls that fail to return any results.
+
+   "Modifying the Name of an Entry" section: added function prototypes
+   for ldap_modrdn2() and ldap_modrdn2_s() and corrected the ones for
+   ldap_modrdn() and ldap_modrdn_s() to match the most widely imple-
+   mented APIs.
+
+   "Obtaining Results and Peeking Inside LDAP Messages" section: added
+   requirement that "*res" be set to NULL when ldap_result() fails to
+   return any results.  Added requirement that ldap_msgfree() accept a
+   NULL "res" parameter.
+
+   "Stepping Through the Attributes of an Entry" section:  added
+   requirement that ldap_memfree() accept a NULL "mem" parameter.
+
+   "Encoded ASN.1 Value Manipulation - Encoding" section: added note
+   that implementations may support tags with a value larger than 32
+   (but this is not required).
+
+   "Encoded ASN.1 Value Manipulation - Decoding" section: changed the
+   LBER_ERROR and LBER_DEFAULT macros to end in "UL" instead of "L"
+   since all the functions that return these two values return an
+   "unsigned long" value.
+
+
+28.2.  Editorial changes
+
+
+   Removed section: "Appendix - Outstanding Issues."
+
+   Added two new editorial sections:
+      "Appendix - Summary of Requirements for API Extensions"
+      "Appendix - Known Incompatibilities with RFC 1823".
+
+   General: replaced all occurrences of "LDAP C API" with "C LDAP API"
+   for consistency.
+
+
+
+
+Expires: 2 December 1999                                       [Page 75]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   "Status of Memo" section: added a statement that this document is in
+   full conformance with all provisions of Section 10 of RFC2026.  Also
+   revised the text about the Internet Draft current and shadow direc-
+   tories to match the latest I-D guidelines.
+
+   Document authors: removed Chris Weider from the list of authors (at
+   his own request) and added an explicit mention of him in the "Ack-
+   nowledgements" section.  Updated Mark Wahl's company affiliation in
+   document preface.  Added "(document editor)" after Mark Smith's name
+   in the "Authors' Addresses" section.
+
+   Copyright: updated the year to 1999.
+
+   "Introduction" section: expanded the sentence that mentioned the sam-
+   ple code appendix to mention all of the appendices.
+
+   "Overview of LDAP API Use" section: numbered the four simple steps
+   for using the API. Added mention of the referrals client control.
+   Clarified the text on character sets.  Replaced mention of
+   ldap_bind() with ldap_sasl_bind() because the former is deprecated.
+   Added note that this API is designed for use in environments where
+   the 'int' type is at least 32 bits in size.
+
+   "Common Data Structures" section: added definition of BerElement so
+   it is defined before it is used.  Added reference back to "Header
+   File Requirements" for "struct timeval" related considerations.
+
+   "Initializing an LDAP Session" section: moved note about ldap_open()
+   attempting to make a server connection closer to the ldap_open()
+   function prototype.  Added note that using literal IPv6 addresses in
+   the "hostname" parameter is not yet supported.
+
+   "LDAP Session Handle Options" section: replaced one instance of
+   "Formerly" with "In RFC 1823."  Added note about inheritance of
+   options when automatic referral following is enabled.  Added
+   LDAP_OPT_API_INFO and LDAP_OPT_API_FEATURE_INFO for completeness (not
+   previously included in this section).  Replaced erroneous references
+   to the "Using Controls" section with references to the "Working With
+   Controls" section.  In the text describing the LDAP_OPT_HOST_NAME
+   option, added a reference to the "hostname" parameter of ldap_init()
+   for the syntax of the option value.  Clarified that ldap_set_option()
+   makes a copy of the "invalue" data.
+
+   "Working With Controls" section: added a note to remind the reader
+   that server controls that are marked critical should not be used with
+   unbind and abandon operations since those two operations have no
+   server response.
+
+
+
+
+Expires: 2 December 1999                                       [Page 76]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   "Closing the session" section: made it clear that all open connec-
+   tions associated with a session handle are closed when any of the
+   unbind API functions are called.
+
+   "Searching" section: added note that only a subset of the filter
+   functionality is available when communicating with an LDAPv2 server.
+   Clarified text to explain when a local timeout is used and when it is
+   not.
+
+   "Abandoning An Operation" section: removed some redundant text from
+   the paragraph that explains the differences between ldap_abandon()
+   and ldap_abandon_ext().
+
+   "Obtaining Results and Peeking Inside LDAP Messages" section: clari-
+   fied that ldap_result() only returns messages for one request at a
+   time.
+
+   "Handling Errors and Parsing Results" section: replace a few
+   occurrences of LDAPResult with LDAPMessage (there is no type called
+   LDAPResult).  Changed the names of the "resultoidp" and "resultdatap"
+   parameters to "retoidp" and "retdatap" to avoid confusion with LDAP
+   result messages.
+
+   "Stepping Through a List of Entries or References" section: added "or
+   References" to the section name to better reflect its contents.
+   Added missing description of "ref" parameter.  Added mention of
+   ldap_first_reference() and ldap_next_reference() in sentence about
+   function return values.
+
+   "Stepping Through the Attributes of an Entry" section:  added forward
+   reference for BerElement type.
+
+   "Parsing References" section: in the description of the "ref" parame-
+   ter, changed the phrase "these routines" to the more accurate "this
+   routine."
+
+   "Encoded ASN.1 Value Manipulation - General" section: changed text to
+   make sense given that the definition of BerElement now appears first
+   in the "Common Data Structures" section.
+
+   "Encoded ASN.1 Value Manipulation - Encoding" section: Changed the
+   style of function prototypes to better match the rest of the docu-
+   ment.  Corrected a typo in the ber_bvdup() description ("as the"
+   replaced with "than the").  Changed "null" to "NULL" where appropri-
+   ate to be consistent with use elsewhere in the document.  Removed
+   mention of sequences from the discussion of the LBER_USE_DER option.
+   Fixed some truncated sentences (by adding some missing '\' characters
+   to the nroff document source).
+
+
+
+Expires: 2 December 1999                                       [Page 77]
+
+
+C LDAP API        C LDAP Application Program Interface       2 June 1999
+
+
+   "Encoded ASN.1 Value Manipulation - Encoding Example" section:  sim-
+   plified the error handling in the example code through the use of a
+   'goto' statement.
+
+   "Encoded ASN.1 Value Manipulation - Decoding" section: Changed the
+   style of function prototypes to better match the rest of the docu-
+   ment.  Changed "null" to "NULL" and "null-terminated" to "zero-
+   terminated" where appropriate to be consistent with use elsewhere in
+   the document.  Fixed a typo (the text now says "an allocated" instead
+   of "a allocated.").  Clarified the description of the 'n' format
+   character for ber_scanf().
+
+   "Encoded ASN.1 Value Manipulation - Decoding Example" section:
+   changed code to not define a macro that begins with "LDAP" since that
+   prefix is reserved for the API.  Removed an extra 'i' from the format
+   string used in the first call to ber_scanf().  Changed error report-
+   ing code to send messages to stderr instead of stdout.  Changed
+   declaration of "res" local variable from "int" to "unsigned long" and
+   corrected one test of the ber_scanf() return value to test against
+   LBER_ERROR instead of -1.  Fixed improperly rendered strings (by
+   adding '\' characters to the nroff source for this document so that
+   '\t' and '\n' are correctly rendered).
+
+   "Acknowledgements" section: added the mention of Chris Weider.
+   Rephrased the text that gives credit to the National Science Founda-
+   tion (it now says "The original material upon which this specifica-
+   tion is based was supported by ..." instead of "This original
+   material upon which this revision is based was based upon work sup-
+   ported by ..."
+
+   In the "Bibliography" section:  Added a reference to RFC 1345 and
+   ANSI/ISO C.  Updated the LDAPv3 TLS and Sorting references to point
+   to the latest revisions of those documents.
+
+   "Appendix - Sample C LDAP API Code": added #include <stdio.h> to the
+   sample code.  Changed the code to demonstrate good error handling by
+   freeing all memory and calling ldap_unbind() before returning.
+   Replaced calls to exit() with return statements.  Fixed improperly
+   rendered strings (by adding '\' characters to the nroff source for
+   this document so that '\t' and '\n' are correctly rendered).
+
+
+
+
+
+
+
+
+
+
+
+Expires: 2 December 1999                                       [Page 78]
+
+