1  LDAP
   LDAP is the C language application programming interface (API)
   for the Lightweight Directory Access Protocol (LDAP). This
   API supports Version 3 of the LDAP API (LDAPv3), and includes
   support for controls, information hiding, and thread safety. It
   is available on OpenVMS Alpha only.
 

2  Introduction
         The C LDAP API is designed to be powerful, yet simple
   to use. It defines compatible synchronous and asynchronous
   interfaces to LDAP to support a wide variety of applications.
 

3  Overview_of_the_LDAP_Model
   LDAP is the lightweight directory access protocol, which is based
   on a client-server model. In this model, 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
   information about some object (for example, 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 attribute (for example, ASCII
   characters or a jpeg photograph) and how those values behave
   during directory operations (for example, whether case is
   significant during comparisons).

   Entries may be organized in a tree structure, usually based on
   political, geographical, or 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
   the following:

   cn=Barbara Jensen, o=University of Michigan, c=US

   Operations are provided to authenticate, search for and retrieve
   information, modify information, and add and delete entries from
   the tree.
 

3  Overview_of_LDAP_API_Use
   An application generally uses the C LDAP API in four simple
   steps.

   o  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.

   o  Authenticate to the LDAP server. The ldap_bind() function
      supports a variety of authentication methods.

   o  Perform some LDAP operations and obtain some results. The
      ldap_search() function returns results that can be parsed
      by ldap_parse_result(), ldap_first_entry(),  and ldap_next_
      entry().

   o  Close the session. The ldap_unbind() function closes the
      connection.

   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 functions return an
   indication of the outcome of the operation (for example, the
   constant LDAP_SUCCESS or some other error code). The asynchronous
   functions make available to the caller the message id of the
   operation initiated. 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
   LDAPMessage. Functions are provided to parse this structure,
   step through entries and attributes returned. Functions are also
   provided to interpret errors.

   LDAPv3 servers may return referrals to other servers. By default,
   implementations of this API will attempt to follow referrals
   automatically for the application. This behavior can be disabled
   globally (using the ldap_set_option() call) or on a per-request
   basis through the use of a server control.

   As in the LDAPv3 protocol, all DNs and string values that are
   passed into or produced by the C LDAP API are represented as
   UTF-8 characters. Conversion functions are described in Encoded
   ASN.1.

   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 LDAPv3 features
   will need to use the ldap_set_option() call with a LDAP_OPT_
   PROTOCOL_VERSION switch set to Version 3.

   The file LDAP_EXAMPLE.C in SYS$EXAMPLES contains an example
   program that demonstrates how to use the LDAP API on OpenVMS.
 

3  LDAP_API_Use_on_OpenVMS_Systems
   This release of the LDAP API provides support for client
   applications written in C or C++.

   In order to use the LDAP API, a program must use an include
   statement of the form:

   #include <ldap.h>

   The LDAP.H header file includes prototypes and data structures
   for all of the functions that are available in the LDAP API.

   The shareable image LDAP$SHR.EXE includes run-time support for
   LDAP applications. This shareable image resides in SYS$LIBRARY
   and should be included in the library IMAGELIB.OLB, which means
   that no special action is necessary to link or run your programs.
   For example:

     $ type myprog.c

     /* A not very useful program */
     #include <stdio.h>
     #include <ldap.h>
     void main(int argc, char *argv[])
     {
       LDAP *ld;
       if (argc != 2) {
         printf("usage: %s <hostname>\n",argv[0]);
         return;
       }
       ld = ldap_init(argv[1],LDAP_PORT);
       if (ld != NULL) {
         printf("ldap_init returned 0x%p\n",ld);
       } else {
         printf("ldap_init failed\n");
       }
     }

     $ cc myprog
     $ link myprog
     $ myprog :== $mydisk:[mydir]myprog.exe
     $ myprog fred
     ldap_init returned 0xA6748
     $
 

3  64-bit_Addressing_Support
   OpenVMS Alpha provides support for 64-bit virtual memory
   addressing. Applications that are built using a suitable compiler
   may take advantage of the 64-bit virtual address space to map and
   access large amounts of data.
 

4  Background
   The OpenVMS LDAP API supports both 32- and 64-bit client
   applications. In order to allow this, separate entry points are
   provided in the library for those functions that are sensitive to
   pointer size.

   When a user module is compiled, the header file LDAP.H determines
   the pointer size in effect and uses the C preprocessor to map
   the function names into the appropriate library entry point. This
   mapping is transparent to the user application and is effected by
   setting the /POINTER_SIZE qualifier at compilation time.

   For LDAP API users, switching between different pointer sizes
   should need only a recompilation-no code changes are necessary.

   This means that programs using the specification for the C LDAP
   API, as described in the Internet Engineering Task Force (IETF)
   documentation, can be built on OpenVMS with either 32-bit or
   64-bit pointer size, without having to change the source code.
 

4  Implementation
   The OpenVMS LDAP library uses 64-bit pointers internally and is
   capable of dealing with data structures allocated by the caller
   from 64-bit address space.

   Applications that use 32-bit pointers will use the 32-bit
   function entry points in the library. This means they can pass
   arguments that are based on 32-bit pointers and can assume that
   any pointers returned by the library will be 32-bit safe.

   While the mapping performed by LDAP.H is designed to be
   transparent, there may be occasions where it is useful (for
   example in debugging) to understand the consequences of having
   both 32- and 64-bit support in the same library.
 

5  Library_Symbol_Names
   The symbols exported by the LDAP$SHR OpenVMS run-time library
   differ from those specified in the IETF C LDAP API specification.

   The header file LDAP.H maps user references to LDAP API function
   names to the appropriate LDAP$SHR symbol name. Therefore, any
   application wishing to use the OpenVMS LDAP API must include the
   version of LDAP.H that ships with OpenVMS.

   All of the functions in the OpenVMS LDAP library are prefixed
   with the facility code "LDAP$".

   For those functions where the caller's pointer size is
   significant, the name of the 64-bit entry point will have a "_
   64" suffix, while the name of the 32-bit jacket will have a "_32"
   suffix. Functions that are not sensitive to pointer size have no
   special suffix.

   For example, the function ldap_modify() is sensitive to the
   caller's pointer size (because one of its arguments is an
   array of pointers). Therefore, the library exports symbols for
   LDAP$LDAP_MODIFY_64 and LDAP$LDAP_MODIFY_32. For the function
   ldap_simple_bind(), which is not sensitive to the caller's
   pointer size, a single entry point, LDAP$LDAP_SIMPLE_BIND, exists
   in the library.

   Because OpenVMS imposes a 31-character limit on the length of
   symbol names, certain functions in the library have names which
   are abbreviated versions of the public API name. For example,
   in the case of the function ldap_parse_sasl_bind_result(), the
   library provides two entry points, namely LDAP$LDAP_PRS_SASL_
   BIND_RES_32 and LDAP$LDAP_PRS_SASL_BIND_RES_64.
 

5  LDAP_Data_Structures
   The LDAP API defines various data structures which are used to
   pass information to and from a client application. Some of these
   structures are opaque; that is, their internal layout is not
   visible to a client application. In such cases, the API may
   return a pointer to such a structure, but the only use of such
   a pointer to a client application is as a parameter to subsequent
   library calls.

   Some structures are public. Their contents are defined by the
   API, and client applications may allocate and manipulate such
   structures or use them as parameters to LDAP functions.

   All data structures used by the API are defined with "natural"
   alignment; that is, each member of a data structure will be
   aligned on an address boundary appropriate to its type.

   Opaque Data Structures

   The following data structures are opaque. Applications should
   not make any assumptions about the contents or size of such data
   structures.

       typedef struct ldap
               LDAP;

       typedef struct ldapmsg
               LDAPMessage;

       typedef struct berelement
               BerElement;

   Public Data Structures

   The following data structures are described in the IETF documents
   relating to the LDAP API, and definitions are provided for
   them in LDAP.H. Applications may allocate and manipulate such
   structures, as well as use them in calls to the LDAP API.

       typedef struct berval { .. }
               BerValue;

       typedef struct ldapapiinfo { .. }
               LDAPAPIInfo;

       typedef struct ldap_apifeature_info { .. }
               LDAPAPIFeatureInfo;

       typedef struct ldapcontrol { .. }
               LDAPControl;

       typedef struct ldapmod { .. }
               LDAPMod;

   Note that the pointer size in effect at compilation time
   determines the layout of data structures, which themselves
   contain pointer fields. Since all of the public data structures
   listed here contain one or more pointers, their size and layout
   will differ depending on the pointer size.

   For example, in the case of the structure berval, the API
   provides the following definition:

    struct berval {
         ber_len_t      bv_len;
         char           *bv_val;
    } BerValue;

   (where ber_len_t is equivalent on OpenVMS to an unsigned 32-bit
   integer).

   The following code would therefore work correctly regardless of
   pointer size:

        #include <ldap.h>
        .
        .
        .
          char       *buff;
          BerValue   val;
        .
        .
        .
          buff = (char *)malloc(255);
        .
        .
        .
          val.bv_len = 255;
          val.bv_val = buff;
        .
        .
        .
 

4  Mixing_Pointer_Sizes
   Two modules that include LDAP.H can be compiled with different
   pointer sizes and linked together. While each module may use the
   LDAP API on its own, it may not be possible for both modules to
   share LDAP-related data.

   None of the public LDAP data structures is directly compatible
   between 32- and 64-bit modules. For example, a BerValue that
   has been allocated by a 32-bit module does not have the same
   layout as a BerValue which a 64-bit module expects to see, and
   consequently cannot be exchanged between two such modules without
   some sort of data conversion taking place.

   Opaque data structures (such as LDAP *) have only a single
   structure definition inside the library, and so pointers to such
   structures may be exchanged between 32- and 64-bit callers. Note
   that these structures are allocated only by the library itself,
   and, in the case of a 64-bit caller, these structures may be
   allocated in 64-bit space. So while the LDAP handle returned to
   a 32-bit caller of ldap_init() could safely be used by a 64-bit
   module, the reverse may not be true.
 

3  Multithreading_Support
   The OpenVMS LDAP API may be used by a multi-threaded application.
   Two of the functions in the library, ldap_perror() and ldap_
   result2error(), are not thread-safe.
 

2  Data_Structures
   The following are definitions of some data structures that are
   common to several LDAP API functions.

   typedef struct ldap LDAP;

   typedef struct berelement BerElement;

   typedef struct ldapmsg LDAPMessage;

   typedef struct berval {
       ber_len_t       bv_len;
       char            *bv_val;
   } BerValue;

   struct timeval;

   The LDAP structure is an opaque data type that represents an LDAP
   session. Typically, this corresponds to a connection to a single
   server, but it may encompass several server connections in LDAPv3
   referrals.

   The LDAPMessage structure is an opaque data type that is used
   to return entry, reference, result, and error information. An
   LDAPMessage structure may represent the beginning of a list or a
   chain of messages that contain a series of entries, references,
   and result messages that are returned by LDAP operations, such
   as search. LDAP API functions, such as ldap_parse_result(), that
   operate on message chains which may contain more than one result
   message, always operate on the first result message in the chain.
   See Results for more information.

   The BerElement structure is an opaque data type that is used to
   hold data and state information about encoded data.

   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.

   All memory that is allocated by a function in this C LDAP API
   and returned to the caller should be disposed of by calling the
   appropriate free function provided by this API.

   Memory that is allocated outside of the C LDAP API must not be
   disposed of using a function provided by this API.

   The following is a complete list of free functions that are used
   to dispose of allocated memory:

      ber_bvecfree()

      ber_bvfree()

      ber_free()

      ldap_control_free()

      ldap_controls_free()

      ldap_memfree()

      ldap_msgfree()

      ldap_value_free()

      ldap_value_free_len()
 

2  Error_Codes
   Many of the LDAP API functions 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; those between 0x00 and 0x50 are returned from the
   LDAP server, those above 0x50 are generated by the API itself.
   Supported error codes are as follows (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 CLDA

        LDAP_AFFECTS_MULTIPLE_DSAS (0x47)        -- new in LDAPv3

        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)
 

2  Initializing
   The ldap_init() function 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 function is deprecated.

           LDAP *ldap_open(
                 const char    *hostname,
                 int           portno);

   Unlike ldap_init(), the ldap_open()  function attempts to make a
   server connection before returning to the caller. A more complete
   description can be found in RFC 1823.

   Parameters are as follows:

   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 are tried in the order listed, stopping with
              the first one to which a successful connection is
              made. Note that only ldap_open() attempts to make the
              connection before returning to the caller. ldap_init()
              does not connect to the LDAP server.
   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 parameter is ignored.

   The ldap_init() and ldap_open()  functions both return a session
   handle, a pointer to an opaque structure that should be passed
   to subsequent calls pertaining to the session. These functions
   return NULL if the session cannot be initialized, 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 LDAP Version 2 server, one of the
   ldap_bind() calls must be completed before other operations can
   be performed 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 functions described in the Session Handles help
   topic.
 

2  Session_Handles
   The LDAP session handle returned by ldap_init() is a pointer
   to an opaque data type representing an LDAP session. Formerly,
   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.

   To insulate callers from inevitable changes to this structure,
   these aspects of the session are now accessed through a pair of
   accessor functions.

   The ldap_get_option() function is used to access the current
   value of various session-wide parameters. The ldap_set_option()
   function is used to set the value of 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.

           int ldap_get_option(
                   LDAP            *ld,
                   int             option,
                   void            *outvalue
           );

           int ldap_set_option(
                   LDAP            *ld,
                   int             option,
                   const void      *invalue
           );

   Parameters are as follows:

   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 indicated meanings. After the constant,
              the actual hexadecimal value of the constant is listed
              in parentheses.
              LDAP_OPT_DESC      Type for invalue parameter: not
              (0x01)             applicable (option is read-only).
                                 Type for outvalue parameter: int *

                                 Description: The underlying socket
                                 descriptor corresponding to the
                                 primary LDAP connection. This
                                 option is read-only and cannot
                                 be set.
              LDAP_OPT_DEREF     Type for invalue parameter: int *
              (0x02)             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 dereferenced when
                                 locating the base object but not
                                 during the search.
              LDAP_OPT_          Type for invalue parameter: int *
              SIZELIMIT (0x03)   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_          Type for invalue parameter: int *
              TIMELIMIT (0x04)   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.
              LDAP_OPT_          Type for invalue parameter: int
              REFERRALS (0x08)   (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. It can be set to one of
                                 the constants LDAP_OPT_ON (1) or
                                 LDAP_OPT_OFF (0).
              LDAP_OPT_RESTART   Type for invalue parameter: int
              (0x09)             (LDAP_OPT_ON or LDAP_OPT_OFF)
                                 Type for outvalue parameter: int *

                                 Description: Determines whether
                                 LDAP I/O operations should
                                 automatically be restarted if they
                                 abort prematurely. It should be
                                 set to one of the constants LDAP_
                                 OPT_ON or LDAP_OPT_OFF. This option
                                 is useful if an LDAP I/O operation
                                 is interrupted prematurely, (for
                                 example, by a timer going off) or
                                 other interrupt.
              LDAP_OPT_          Type for invalue parameter: int *
              PROTOCOL_VERSION   Type for outvalue parameter: int *
              (0x11)
                                 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_   Type for invalue parameter:
              CONTROLS (0x12)    LDAPControl **
                                 Type for outvalue parameter:
                                 LDAPControl ***

                                 Description: A default list of LDAP
                                 server controls to be sent with
                                 each request. See Controls for more
                                 information.
              LDAP_OPT_CLIENT_   Type for invalue parameter:
              CONTROLS (0x13)    LDAPControl **
                                 Type for outvalue parameter:
                                 LDAPControl ***

                                 Description: A default list of
                                 client controls that affect the
                                 LDAP session. See Controls for more
                                 information.
              LDAP_OPT_HOST_     Type for invalue parameter: char *
              NAME (0x30)        Type for outvalue parameter: char
                                 **

                                 Description: The host name (or
                                 list of host) for the primary LDAP
                                 server.
              LDAP_OPT_ERROR_    Type for invalue parameter: int *
              NUMBER (0x31)      Type for outvalue parameter: int *

                                 Description: The code of the most
                                 recent LDAP error that occurred for
                                 this session.
              LDAP_OPT_ERROR_    Type for invalue parameter: char *
              STRING (0x32)      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 LDAPControl **, a pointer to 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 constants LDAP_OPT_ON and
              LDAP_OPT_OFF can be given for options that have on or
              off settings.

              Both ldap_get_option() and ldap_set_option() return 0
              if successful and -1 if an error occurs.
 

2  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 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 control, set ldctl_value.bv_
                  val to NULL.
   ldctl_         Indicates whether the control is critical or not.
   iscritical     If this field is non-zero, the operation will only
                  be carried out if the control is recognized by the
                  server and/or client.

   Some LDAP API calls allocate an ldapcontrol structure or a
   NULL-terminated array of ldapcontrol structures. The following
   functions 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. 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
   paging of search results. No client controls are currently
   implemented in this version of the API.
 

2  Authenticating
   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.
   The functions 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 functions ldap_simple_bind() or
   ldap_simple_bind_s() can be used.

     int ldap_sasl_bind(
             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 functions is deprecated:

        int ldap_bind( LDAP *ld, char *dn, char *cred, int method );

        int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method );

   Parameters are as follows:

   ld             The session handle.
   dn             The name of the entry to bind as.
   mechanism      Either LDAP_SASL_SIMPLE (NULL) to get simple
                  authentication, 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
                  credentials 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 functions are not
   described. See the RFC 1823 documentation for more information.

   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
   Errors 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() 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 subsequent call to ldap_result() 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 appropriately.

   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 Errors for more information
   about possible errors and how to interpret them.

   Note that if an LDAP Version 2 server is contacted, no other
   operations over the connection should be attempted before a bind
   call has successfully completed.

   Subsequent bind calls can be used to reauthenticate over the
   same connection, and multistep SASL sequences can be accomplished
   through a sequence of calls to ldap_sasl_bind() or ldap_sasl_
   bind_s().
 

2  Closing
   The following functions are used to unbind from the directory,
   close the connection, and dispose of the session handle.

           int ldap_unbind( LDAP *ld );
           int ldap_unbind_s( LDAP *ld );

   Parameter is as follows:

   ld    The session handle.

   The ldap_unbind() and ldap_unbind_s()  functions both work
   synchronously, unbinding from the directory, closing the
   connection, and freeing up the ld structure before returning.
   There is no server response to an unbind operation. The ldap_
   unbind() function returns LDAP_SUCCESS (or another LDAP error
   code if the request cannot be sent to the LDAP server). After a
   call to ldap_unbind() or ldap_unbind_s(),  the session handle ld
   is invalid and it is illegal to make any further LDAP API calls
   using ld.
 

2  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,
                   char                      **attrs,
                   int                       attrsonly,
                   LDAPMessage               **res
           );

           int ldap_search_st(
                   LDAP                      *ld,
                   char                      *base,
                   int                       scope,
                   char                      *filter,
                   char                      **attrs,
                   int                       attrsonly,
                   struct timeval            *timeout,
                   LDAPMessage               **res
              );

   Parameters are as follows:

   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 representing the search filter.
                  The value NULL can be passed to indicate that the
                  filter (objectclass=*) that matches all entries
                  should be used.
   attrs          A NULL-terminated array of strings indicating
                  which attributes 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 element 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 either zero if both
                  attribute types and values are to be returned or
                  non-zero if only types are wanted.
   timeout        For the ldap_search_st() function, this specifies
                  the local search timeout value (if it is NULL,
                  the timeout is infinite). 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,
                  passing a NULL value for timeout causes the global
                  default timeout stored in the LDAP session handle
                  to be used (set using ldap_set_option() with the
                  LDAP_OPT_TIMELIMIT parameter).
   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.
   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 that potentially
   affect how the search is performed. They are as follows:

   LDAP_OPT_        A limit on the number of entries to return from
   SIZELIMIT        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_        A limit on the number of seconds to spend on
   TIMELIMIT        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 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
   operation and returns either the constant LDAP_SUCCESS if the
   request was successfully sent or another LDAP error code if
   not. See Errors 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() can be used to obtain the results from the search.
   These results can be parsed using the result parsing functions
   described in Errors.

   Similar to ldap_search_ext(), the ldap_search()  function
   initiates an asynchronous search operation and returns the
   message id of the operation initiated. As for ldap_search_ext(),
   a subsequent call to ldap_result() can be used to obtain the
   result of the search. In case of error, ldap_search() will return
   -1, setting the session 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 Errors 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,
   attributes, and values should be extracted by calling the parsing
   functions. The results contained in res should be freed when no
   longer in use by calling ldap_msgfree().

   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 additional parameter specifying a local
   timeout for the search. The local search timeout is used to
   limit the amount of time the API implementation will wait for
   a search to complete. After the local search timeout the search
   operation will return LDAP_TIMEOUT if the search result has not
   been removed.
 

3  Reading_and_Listing_the_Children_of_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 NULL. The attrs parameter contains the list
   of attributes to return.

   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. The attrs parameter contains the
   list of attributes to return for each child entry.
 

2  Attribute_Value
   The following functions 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,
                   const struct berval               *bvalue
                   LDAPControl                       **serverctrls,
                   LDAPControl                       **clientctrls,
                   int                               *msgidp
           );

           int ldap_compare_ext_s(
                   LDAP                              *ld,
                   const char                        *dn,
                   const char                        *attr,
                   const 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
           );

   Parameters are as follows:

   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 functions 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
   operation and returns either the constant LDAP_SUCCESS if the
   request was successfully sent, or another LDAP error code if not.
   See Errors 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() 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 operation initiated. As for ldap_compare_ext(),
   a subsequent call to ldap_result() can be used to obtain the
   result of the compare. In case of error, ldap_compare() will
   return -1, setting the session 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 constants LDAP_COMPARE_TRUE or LDAP_COMPARE_FALSE if the
   operation was successful, or another LDAP error code if it was
   not. See Errors for more information about possible errors and
   how to interpret them.

   The ldap_compare_ext() and ldap_compare_ext_s()  functions
   support LDAPv3 server controls and client controls.
 

2  Modifying_Entry
   The following functions 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 as follows:

   ld             The session handle.
   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
              logically 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. The mod_values field 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 attribute 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
   operation and returns the constant LDAP_SUCCESS if the request
   was successfully sent, or another LDAP error code if not. See
   Errors for more information about possible errors and how to
   interpret them. If successful, ldap_modify_ext() places the
   message id of the request in *msgidp. A subsequent call to ldap_
   result() 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 operation initiated. As for ldap_modify_ext(),
   a subsequent call to ldap_result() can be used to obtain the
   result of the modify. In case of error, ldap_modify() will return
   -1, setting the session 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 Errors for more information about possible errors and how to
   interpret them.

   The ldap_modify_ext() and ldap_modify_ext_s()  functions support
   LDAPv3 server controls and client controls.
 

2  Modifying_Name
   In LDAP Version 2, the ldap_modrdn() and ldap_modrdn_s()
   functions 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()  functions
   are used to change the name of an entry, and the use of the ldap_
   modrdn() and ldap_modrdn_s()  functions is deprecated.

           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,
                   int                               deleteoldrdn,
                   LDAPControl                       **serverctrls,
                   LDAPControl                       **clientctrls
           );

   Use of the following functions is deprecated.

           int ldap_modrdn(
                   LDAP                              *ld,
                   char                              *dn,
                   char                              *newrdn,
                   int                               deleteoldrdn
           );

           int ldap_modrdn_s(
                   LDAP                              *ld,
                   char                              *dn,
                   char                              *newrdn,
                   int                               deleteoldrdn
           );

   Parameters are as follows:

   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 Version 2 of the
                  LDAP protocol; otherwise the server's behavior is
                  undefined.
   deleteoldrdn   This parameter only has meaning on the rename
                  functions if newrdn is different than the old
                  RDN. It is a boolean value. If it is non-zero,
                  it indicates that the old RDN value(s) should
                  be removed. If it is zero, it indicates 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
   Errors 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() 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 Errors
   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.
 

2  Adding_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,
                   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 as follows:

   ld             The session handle.
   dn             The name of the entry to add.
   attrs          The entry's attributes, specified using the
                  LDAPMod structure 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 (that is, equal to the root DN) for
   an add to succeed.

   The ldap_add_ext() function initiates an asynchronous add
   operation and returns either the constant LDAP_SUCCESS if the
   request was successfully sent or another LDAP error code if not.
   See Errors 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()
   can be used to obtain the result of the add.

   Similar to ldap_add_ext(), the ldap_add()  function initiates
   an asynchronous add operation and returns the message id of the
   operation initiated. As for ldap_add_ext(), a subsequent call
   to ldap_result() 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 Errors 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.
 

2  Deleting_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 as follows:

   ld             The session handle.
   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 (that is, 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
   operation and returns either the constant LDAP_SUCCESS if the
   request was successfully sent or another LDAP error code if not.
   See Errors 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() 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 operation initiated. As for ldap_delete_ext(),
   a subsequent call to ldap_result() can be used to obtain the
   result of the delete. In case of error, ldap_delete() will return
   -1, setting the session 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 Errors for more information
   about possible errors and how to interpret them.

   The ldap_delete_ext() and ldap_delete_ext_s()  functions support
   LDAPv3 server controls and client controls.
 

2  Extensions
   The ldap_extended_operation() and ldap_extended_operation_s()
   functions 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,
                   const struct berval                *request data,
                   LDAPControl                        **serverctrls,
                   LDAPControl                        **clientctrls,
                   int                                *msgidp
           );

           int ldap_extended_operation_s(
                   LDAP                               *ld,
                   const char                         *requestoid,
                   const struct berval                *request data,
                   LDAPControl                        **serverctrls,
                   LDAPControl                        **clientctrls,
                   char                               **retoidp,
                   struct berval                      **retdatap
           );

   Parameters are as follows:

   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 allocated, dotted- OID text string returned
                  by the server. This string should be disposed of
                  using the ldap_memfree() function. If no OID was
                  returned, *retoidp is set to NULL.
   retdatap       Pointer to a berval structure pointer that will be
                  set to 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 either the constant LDAP_SUCCESS
   if the request was successfully sent or another LDAP error code
   if not. See Errors 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() can be used to obtain the result of the
   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 Errors 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.
 

2  Abandoning
   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
           );

   Parameters are as follows:

   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.

   The ldap_abandon_ext() function abandons the operation with
   message id msgid and returns either the constant LDAP_SUCCESS
   if the abandon was successful or another LDAP error code if not.
   See Errors for more information about possible errors and how to
   interpret them.

   The ldap_abandon() function 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 and does
   not support LDAPv3 server controls or client controls.

   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.
 

2  Results
   The ldap_result() function 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. 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 function will never be affected
   by subsequent LDAP API calls (except for ldap_msgfree(), which is
   used to dispose of a chain of messages).

   The ldap_msgfree() function 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 function.

   The ldap_msgtype() function returns the type of an LDAP message.
   The ldap_msgid() function 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 as follows:

   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 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
                  results 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 specifies a polling
                  behavior.
   res            For ldap_result(), a result parameter that will
                  contain the result(s) of the operation. For ldap_
                  msgfree(), the result chain to be freed, obtained
                  from a previous call to ldap_result(), ldap_
                  search_s(), or ldap_search_st().

   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

   The ldap_result() function 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.

   The ldap_msgfree() function frees the result structure pointed to
   by res and returns the type of the message it freed.

   The ldap_msgtype() function 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 error.

   The ldap_msgid() function returns the message ID associated with
   the LDAP message passed as a parameter.
 

2  Errors
   The following calls are used to extract information from results
   and handle errors returned by other LDAP API functions. Note that
   ldap_parse_sasl_bind_result() and ldap_parse_extended_result()
   must typically 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                               **resultoidp,
                   struct berval                      **resultdata,
                   int                                freeit
           );

           char *ldap_err2string( int err );

   The use of the following functions is deprecated.

           int ldap_result2error(
                   LDAP                               *ld,
                   LDAPMessage                        *res,
                   int                                freeit
           );

           void ldap_perror( LDAP *ld, const char *msg );

   Parameters are as follows:

   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 result.
                  This is the indication 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().
   errmsgp        This result parameter will be filled in with the
                  contents of the error message field from the
                  LDAPMessage result. The error message string
                  should be freed by calling ldap_memfree(). 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 result, indicating zero or more
                  alternate LDAP servers where the request should
                  be retried. The referrals array should be freed by
                  calling ldap_value_free(). 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 result. The control array should be
                  freed by calling ldap_controls_free().
   freeit         A boolean that determines whether or not the res
                  parameter is disposed of. Pass any non-zero value
                  to have these functions free res after extracting
                  the requested information. This option 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 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 structure is returned that should
                  be disposed of by calling ber_bvfree(). NULL may
                  be passed to ignore this field.
   resultoidp     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.
   resultdatap    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 functions are not
   described. See RFC 1823 for more information.

   All three of the ldap_parse_*_result() functions skip over
   messages of type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_
   REFERENCE when looking for a result message to parse. They return
   either the constant LDAP_SUCCESS if the result was successfully
   parsed or another LDAP error code if not. Note that the LDAP
   error code that indicates the outcome of the operation 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 functions, they always operate
   on the first result in the chain.

   The ldap_err2string() function is used to convert a numeric LDAP
   error code, as returned by either one of the three ldap_parse_*_
   result() functions 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.
 

3  Stepping_Through_a_List_of_Results
   The ldap_first_message() and ldap_next_message()  functions 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 include referral messages, entry messages,
   and result messages. The ldap_count_messages() function is used
   to count the number of messages returned. The ldap_msgtype()
   function can be used to distinguish between the different message
   types.

    LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res );
    LDAPMessage *ldap_next_message ( LDAP *ld, LDAPMesage *msg );
    int ldap_count_messages( LDAP *ld, LDAPMessage *res );

   Parameters are as follows:

   ld    The session handle.
   res   The result chain, as obtained by a call to one of the
         synchronous search functions or ldap_result().
   msg   The message returned by a previous call to ldap_first_
         message()  or ldap_next_message().

   The ldap_first_message() and ldap_next_message()  functions 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 indicate the error.

   The ldap_count_messages() function 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().
 

2  Search_Results
   The following calls are used to parse the entries and references
   returned by ldap_search(). These results are returned in an
   opaque structure that should only be accessed by calling the
   functions. Functions 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.
 

3  Stepping_Through_a_List_of_Entries
   The ldap_first_entry() and ldap_next_entry()  functions are
   used to step through and retrieve the list of entries from a
   search result chain. The ldap_first_reference() and ldap_next_
   reference() functions are used to step through and retrieve the
   list of continuation references from a search result chain. The
   ldap_count_entries() function is used to count the number of
   entries returned. The ldap_count_references() function 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 as follows:

   ld    The session handle.
   res   The search result, as obtained by a call to one of the
         synchronous search functions or ldap_result().
   entry The entry returned by a previous call to ldap_first_
         entry()  or ldap_next_entry().

   The ldap_first_entry() and ldap_next_entry()  functions will
   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, in which case the
   error parameters in the session handle ld will be set to indicate
   the error.

   The ldap_count_entries() function 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().

   The ldap_count_references() function 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.
 

3  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 as follows:

   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
         internally 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().
   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().

   The ldap_first_attribute() and ldap_next_attribute()  functions
   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 indicate the error.

   Both functions 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().

   The ldap_first_attribute() function 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() to retrieve the associated values.
 

3  Retrieving_the_Values_of_an_Attribute
   The ldap_get_values() and ldap_get_values_len()  functions are
   used to retrieve the values of a given attribute from an entry.
   The ldap_count_values() and ldap_count_values_len()  functions
   are used to count the returned values. The ldap_value_free() and
   ldap_value_free_len() functions are used to free the values.

           char **ldap_get_values(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   char            *attr
           );

           struct berval **ldap_get_values_len(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   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 as follows:

   ld    The session handle.
   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 (for example, "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.

   The ldap_get_values() and ldap_get_values_len()  functions return
   NULL if no values are found for attr or if an error occurs.

   The ldap_count_values() and ldap_count_values_len()  functions
   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.
 

3  Retrieving_the_Name_of_an_Entry
   The ldap_get_dn() function is used to retrieve the name of an
   entry. The ldap_explode_dn() and ldap_explode_rdn()  functions
   are used to break up a name into its component parts. The ldap_
   dn2ufn() function 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 as follows:

   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().
   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").

   The ldap_get_dn() function 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.

   The ldap_explode_dn() function 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().

   The ldap_explode_rdn() function 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().

   The ldap_dn2ufn() function converts the DN into the user friendly
   format. The UFN returned is newly allocated space that should be
   freed by a call to ldap_memfree() when no longer in use.
 

3  Retrieving_Controls_from_an_Entry
   The ldap_get_entry_controls() function is used to extract LDAP
   controls from an entry.

     int ldap_get_entry_controls(
             LDAP                                    *ld,
             LDAPMessage                             *entry,
             LDAPControl                             ***serverctrlsp
     );

   Parameters are as follows:

   ld             The session handle.
   entry          The entry to extract controls from, as returned by
                  ldap_first_entry() or ldap_next_entry().
   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 serverctrlsp is NULL,
                  no controls are returned.

   The ldap_get_entry_controls() function returns an LDAP error code
   that indicates whether the reference could be successfully parsed
   (LDAP_SUCCESS if all goes well).
 

3  Parsing_References
   The ldap_parse_reference() function 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 as follows:

   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 serverctrlsp is NULL,
                  no controls are returned.
   freeit         A boolean that determines whether or not the ref
                  parameter is disposed of. Pass any non-zero value
                  to have these functions free ref after extracting
                  the requested information. This option is provided
                  as a convenience; you can also use ldap_msgfree()
                  to free the result later.

   The ldap_parse_reference() function returns an LDAP error code
   that indicates whether the reference could be successfully parsed
   (LDAP_SUCCESS if all goes well).
 

2  Encoded_ASN.1
   LDAP contains functions that may be used to encode and decode
   BER-encoded ASN.1 values, which are often used inside of control
   and extension values.

   The following additional integral types are defined for use in
   manipulation of BER encoded ASN.1 values:

   typedef unsigned long ber_tag_t; /* for BER tags */

   typedef long     ber_int_t; /* for BER ints, enums, and Booleans */

   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.

           typedef struct berval {
                   ber_len_t            bv_len;
                   char                 *bv_val;
           } BerValue;

   A struct berval contains a sequence of bytes and an indication
   of its length. The bv_val is not null terminated. A bv_len must
   always be a nonnegative number. Applications may allocate their
   own berval structures.

           typedef struct berelement {
                /* opaque */
           } BerElement;

   The BerElement structure contains not only a copy of the encoded
   value, but also state information 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 );

   The ber_bvfree() function frees a berval returned from this
   API. Both the bv->bv_val string and the berval itself are freed.
   Applications should not use ber_bvfree() with bervals which the
   application has allocated.

           void ber_bvecfree ( struct berval **bv );

   The ber_bvecfree() function 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 (struct berval *bv );

   The ber_bvdup() function returns a copy of a berval. The bv_val
   field in the returned berval points to a different area of memory
   as the bv_val field in the argument berval. The null pointer is
   returned on error (for example, out of memory).

           void ber_free ( BerElement *ber, int fbuf );

   The ber_free() function 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.
 

3  Encoding
   The following is an example of encoding:

           BerElement *ber_alloc_t(int options);

   The ber_alloc_t() function 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 and sequences to be rearranged in
   tag and byte order, 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 and
   sequences correctly, DER output 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
   BerElement.

           int ber_printf(BerElement *ber, char *fmt, ... )

   The ber_printf() function 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 element. BER must be a pointer to a BerElement
   returned by ber_alloc_t(). The ber_printf()  function interprets
   and formats its arguments according to the format string fmt.
   The ber_printf() function 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 value must contain the tag class,
         constructed bit, and tag value. The tag value must fit in
         a single octet (tag value is less than 32). For example, a
         tag of "[3]" for a constructed type is 0xA3.
   b     Boolean. The next argument is a ber_int_t, 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.
   e     Enumerated. The next argument is a ber_int_t, containing
         the enumerated value in the host's byte order. An
         enumerated element is output. If this format character
         is not preceded by the 't' format modifier, the tag 0x0A is
         used for the element.
   i     Integer. The next argument is a ber_int_t, 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.
   B     Bitstring. The next two arguments are a char * pointer
         to the start of the bitstring, followed by a ber_len_t
         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
         output. 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 a ber_len_t with the length of the string. The string
         may contain null bytes and need not by 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.
   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' 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 leading SEQUENCE OF octet
         strings. The 't' format modifier cannot be used with this
         format character.
   V     Several octet strings. A NULL-terminated array of struct
         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
         character 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
         cannot 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 subsequent call to ber_printf() for that BerElement.
   The same applies to the '[' and ']'.

   Sequences and sets nest, and implementations of this API must
   maintain internal state to be able to properly calculate the
   lengths.

           int ber_flatten (BerElement *ber, struct berval **bvPtr);

   The ber_flatten() function 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 function returns 0 on success and -1 on
   error.

   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 (that
   is, -1 will be returned by ber_flatten() if this situation is
   exists).
 

3  Decoding
   The following two symbols are available to applications.

           #define LBER_ERROR   0xffffffffL
           #define LBER_DEFAULT 0xffffffffL

           BerElement *ber_init (struct berval *bv);

   The ber_init() function constructs a BerElement and returns a new
   BerElement containing a copy of the data in the bv argument. The
   ber_init() function returns the null pointer on error.

           ber_tag_t ber_scanf (BerElement *ber, char *fmt, ... );

   The ber_scanf() function 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(). The ber_
   scanf() function interprets function the bytes according to
   the format string fmt, and stores the results in its additional
   arguments. The ber_scanf() function returns LBER_ERROR on error,
   and a different value on success.

   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,
         null- terminated, and the pointer to the string is stored
         in the argument. 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 discarded 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 a allocated struct
         berval containing the octet string and its length. The
         ber_bvfree()  function 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 a ber_int_t should be supplied. The
         value stored will be 0 for FALSE or nonzero for TRUE. The
         tag of the element must indicate the primitive form but is
         otherwise ignored during the decoding.
   e     Enumerated 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. The ber_scanf()
         function will return an error if the enumerated value
         cannot be stored in a ber_int_t.
   i     Integer. A pointer to a ber_int_t should be supplied. The
         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. The ber_scanf()  function will
         return an error if the integer cannot be stored in a ber_
         int_t.
   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
         bit-string returned. The ldap_memfree()  function must be
         called to free the bit-string. The tag of the element must
         indicate the primitive form (constructed bitstrings are not
         supported) but is otherwise ignored during the decoding.
   n     Null. No argument is required. The element is simply
         skipped if it is recognized as a zero-length element. The
         tag is ignored.
   v     Several octet strings. A char *** argument should be
         supplied, which upon return points to a allocated null-
         terminated array of char *'s containing the octet strings.
         NULL is stored if the sequence is empty. The ldap_
         memfree()  function 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 containing the octet strings and their
         lengths. NULL is stored if the sequence is empty. The ber_
         bvecfree()  function 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 (BerElement *ber, ber_len_t *lenPtr);

   The ber_peek_tag() function 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);

   The ber_skip_tag() function 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 function 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);

   The ber_first_element() and ber_next_element()  functions are
   used to traverse a SET, SET OF, SEQUENCE or SEQUENCE OF data
   value. The ber_first_element() function 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. The ber_next_element() function 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(). (Refer to the HP
   OpenVMS Utility Routines Manual for an example of this usage.)
 

2  Using_SSL
   Secure Sockets Layer (SSL) is the open standard security protocol
   for the secure transfer of sensitive information over the
   Internet.

   You can establish HP SSL for OpenVMS Alpha on an LDAP session
   if the server supports such sessions. SSL uses X.509 public key
   technology to provide the following security functions:

   o  Integrity and confidentiality of the LDAP dialog

      This is the most common use of HP SSL. The bytes sent over the
      wire are encrypted.

   o  Authentication of the client

      Some servers use SSL to authenticate the client and make
      access control decisions based on the client identity. In
      this case, the client must have access to its private key and
      its certificate. The client certificate subject is a DN.

   o  Authentication of the server

      It might be important for the client to verify the identity
      of the server to which it is talking. In this case, the client
      must have access to the appropriate certification authority
      (CA) public keys.

   There are several versions of SSL: SSLv2 (2.0), SSLv3 (3.0), and
   TLSv1 (3.1). TLS is the latest Internet standard. It does not
   require the use of RSA algorithms. Usually the client specifies
   the highest version it supports, and the server negotiates
   downward, if necessary. The client library supports all the
   versions listed here.

   You can establish SSL over LDAP two different ways:

   o  LDAPS

      This older, de facto standard uses a separate TCP/IP port
      (usually 636) specifically for SSL over LDAP. In this case,
      the second parameter to the ldap_tls_start() function must be
      set to zero.

   o  StartTLS

      This proposed Internet standard uses a regular LDAP port
      (usually 389) and requires the client to request the use
      of SSL. In this case, the second parameter to the ldap_tls_
      start() function must be set to 1.
 

3  HP_SSL_Certificate_Options
   The following session-handle options are specific to SSL and can
   be set by the ldap_set_option() function:

   o  LDAP_OPT_TLS_CERT_REQUIRED (0x7001) void *

      Set to LDAP_OPT_ON if the client library requires a server
      certificate to be present the next time the ldap_tls_start()
      function is called. The default value is LDAP_OPT_OFF; a
      server certificate is not required.

   o  LDAP_OPT_TLS_VERIFY_REQUIRED (0x7002) void *

      Set to LDAP_OPT_ON if the client library requires that a
      server certificate path be validated the next time the ldap_
      tls_start() function is called. The default value is LDAP_OPT_
      OFF; the server certificate, if any, is not verified.

   o  LDAP_OPT_TLS_CERT_FILE (0x7003) char *

      Set to the name of a file containing the client's certificate
      for use by the ldap_tls_start() function.

   o  LDAP_OPT_TLS_PKEY_FILE (0x7004) char *

      Set to the name of a file containing the client's private key
      for use by the ldap_tls_start() function.

   o  LDAP_OPT_TLS_CA_FILE (0x7005) char *

      Set to the name of a file containing CA public keys used for
      validation of the server by the ldap_tls_start() function.

   o  LDAP_OPT_TLS_CA_PATH (0x7006) char *

      Set to the name of a directory on disk containing CA public
      key files used for validation of the server by the ldap_tls_
      start() function.

   o  LDAP_OPT_TLS_VERSION (0x7007) int *

      Set to the desired SSL protocol version. This option takes one
      of the following values:

          1: TLSv1 only
         20: SSLv2 only
         23: SSLv2 or SSLv3
         30: SSLv3 only (default)
         31: TLSv1 only

   If LDAP_OPT_TLS_VERIFY_REQUIRED is set to ON, either the LDAP_
   OPT_TLS_CA_FILE or the LDAP_OPT_TLS_CA_PATH option must be set.

   If client authentication is required, both LDAP_OPT_TLS_CERT_FILE
   and LDAP_OPT_TLS_PKEY_FILE must be set.
 

3  Obtaining_a_Key_Pair
   In order for TLS to authenticate a client, the client must have
   a private key and a certificate. Obtain these from either a
   Certification Authority or a self-sign program. A self-sign
   program is included in the Open Source Security for OpenVMS
   product.