User:MarkCraig: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(Last chapter formatted)
(Moved the Mozilla LDAP SDK Programmer's Guide to its own page)
Line 1: Line 1:
My name's Mark Craig. I used to work for Sun Microsystems, leading the Directory Services documentation effort.<br>
My name's Mark Craig. I used to work for Sun Microsystems, leading the Directory Services documentation effort.


----
In mid 2007, Sun donated code and documentation for version 6 of the LDAP C SDK. The doc also covers the LDAP Java SDK. In February 2011, I wikified the DocBook SGML version as the [[Mozilla LDAP SDK Programmer's Guide]].
 
Trying the rich text editor with and HTML version of the LDAP&nbsp;C SDK guide that Rich Megginson uploaded after I worked with Sun legal to get it licensed Creative Commons. Finally getting back to this after about 4 years...<br>
 
= LDAP C SDK Programmer's Guide<br>  =
 
Copyright © 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
 
This ''Programmer's Guide'' shows you how to create LDAP client applications in the C language to connect to LDAP servers. This guide also shows you how to perform standard LDAP operations.
 
License - The contents of this document are subject to the terms of the Creative Commons Attribution-ShareAlike 2.5 license or any later version (the "License"). You may not use this document except in compliance with the License.
 
See the License for the specific language governing permissions and limitations under the License. The full text of the License is provided at the end of this document.
 
Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved. Portions copyright 1999 Netscape Communications Corporations. All rights reserved.
 
Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product that is described in this document. In particular, and without limitation, these intellectual property rights may include one or more U.S. patents or pending patent applications in the U.S. and in other countries.
 
U.S. Government Rights - Commercial software. Government users are subject to the Sun Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its supplements.
 
This distribution may include materials developed by third parties.
 
Parts of the product may be derived from Berkeley BSD systems, licensed from the University of California. UNIX is a registered trademark in the U.S. and in other countries, exclusively licensed through X/Open Company, Ltd.
 
Sun, Sun Microsystems, the Sun logo, Java, Solaris, JavaBeans, JavaScript and the SunTone Certified logo are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
 
All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the U.S. and other countries. Products bearing SPARC trademarks are based upon architecture developed by Sun Microsystems, Inc.
 
Mozilla, Netscape, and Netscape Navigator are trademarks or registered trademarks of Netscape Communications Corporation in the United States and other countries.
 
Products covered by and information contained in this service manual are controlled by U.S. Export Control laws and may be subject to the export or import laws in other countries. Nuclear, missile, chemical biological weapons or nuclear maritime end uses or end users, whether direct or indirect, are strictly prohibited. Export or reexport to countries subject to U.S. embargo or to entities identified on U.S. export exclusion lists, including, but not limited to, the denied persons and specially designated nationals lists is strictly prohibited.
 
DOCUMENTATION IS PROVIDED AS IS AND ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
 
Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, Etats-Unis. Tous droits rservs. Certaines parties copyright 1999 Netscape Communications Corporations. Tous droits rservs.
 
Sun Microsystems, Inc. dtient les droits de proprit intellectuelle relatifs la technologie incorpore dans le produit qui est dcrit dans ce document. En particulier, et ce sans limitation, ces droits de proprit intellectuelle peuvent inclure un ou plusieurs brevets amricains ou des applications de brevet en attente aux Etats-Unis et dans d'autres pays.
 
Cette distribution peut comprendre des composants dvelopps par des tierces parties.
 
Des parties de ce produit pourront tre drives des systmes Berkeley BSD licencis par l'Universit de Californie. UNIX est une marque dpose aux Etats-Unis et dans d'autres pays et licencie exclusivement par X/Open Company, Ltd.
 
Sun, Sun Microsystems, le logo Sun, Java, Solaris, JavaBeans, JavaScript et le logo SunTone Certified sont des marques de fabrique ou des marques dposes de Sun Microsystems, Inc. aux Etats-Unis et dans d'autres pays.
 
Toutes les marques SPARC sont utilises sous licence et sont des marques de fabrique ou des marques dposes de SPARC International, Inc. aux Etats-Unis et dans d'autres pays. Les produits portant les marques SPARC sont bass sur une architecture dveloppe par Sun Microsystems, Inc.
 
Mozilla, Netscape, et Netscape Navigator sont des marques de Netscape Communications Corporation aux Etats-Unis et dans d'autres pays.
 
Les produits qui font l'objet de ce manuel d'entretien et les informations qu'il contient sont regis par la legislation americaine en matiere de controle des exportations et peuvent etre soumis au droit d'autres pays dans le domaine des exportations et importations. Les utilisations finales, ou utilisateurs finaux, pour des armes nucleaires, des missiles, des armes biologiques et chimiques ou du nucleaire maritime, directement ou indirectement, sont strictement interdites. Les exportations ou reexportations vers des pays sous embargo des Etats-Unis, ou vers des entites figurant sur les listes d'exclusion d'exportation americaines, y compris, mais de maniere non exclusive, la liste de personnes qui font objet d'un ordre de ne pas participer, d'une facon directe ou indirecte, aux exportations des produits ou des services qui sont regi par la legislation americaine en matiere de controle des exportations et la liste de ressortissants specifiquement designes, sont rigoureusement interdites.
 
LA DOCUMENTATION EST FOURNIE EN L'ETAT ET TOUTES AUTRES CONDITIONS, DECLARATIONS ET GARANTIES EXPRESSES OU TACITES SONT FORMELLEMENT EXCLUES, DANS LA MESURE AUTORISEE PAR LA LOI APPLICABLE, Y COMPRIS NOTAMMENT TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE MARCHANDE, A L'APTITUDE A UNE UTILISATION PARTICULIERE OU A L'ABSENCE DE CONTREFACON.<br>
 
== Preface<br>  ==
 
This ''Programmer's Guide'' shows you how to create LDAP client applications in the C language to connect to LDAP servers. This guide also shows you how to perform standard LDAP operations.<br>
 
=== Who Should Use This Book  ===
 
This guide is intended for developers creating directory client applications.
 
*Directory Server functionality
*Developing programs in the C programming language
*Specifications for LDAP and related protocols, such as DSML v2
*Internet and World Wide Web technologies<br>
 
=== Before You Read This Book  ===
 
Before developing directory client applications, install the [https://wiki.mozilla.org/LDAP_C_SDK LDAP&nbsp;C SDK].<br>
 
=== Additional Recommended Reading  ===
 
*LDAP Programming with Java by Weltman and Dabhura (ISBN 0-201-65758-96)
*LDAP Programming, Management and Integration by Donley (ISBN 1930110405)
*LDAP: Programming Directory-Enabled Applications with Lightweight Directory Access Protocol by Howes and Smith (ISBN 1-57870-000-00)
*Understanding and Deploying LDAP Directory Services by Howes, et al. (ISBN 1-57870-070-10)
*RFC 2251, Lightweight Directory Access Protocol (v3)
*RFC 2252, Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions
*RFC 2253, Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
*RFC 2254, The String Representation of LDAP Search Filters
*RFC 2255, The LDAP URL Format
*RFC 2256, A Summary of the X.500(96) User Schema for use with LDAPv3
*RFC 2829, Authentication Methods for LDAP
*RFC 2830, Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security
*RFC 2849, The LDAP Data Interchange Format (LDIF) - Technical Specification
*RFC 3377, Lightweight Directory Access Protocol (v3): Technical Specification<br>
 
=== Related Reading  ===
 
The SLAMD Distributed Load Generation Engine (SLAMD) is a Java™ application that is designed to stress test and analyze the performance of network-based applications. It was originally developed by Sun Microsystems, Inc. to benchmark and analyze the performance of LDAP directory servers. SLAMD is available as an open source application under the Sun Public License, an OSI-approved open source license. To obtain information about SLAMD, go to [http://www.slamd.com/ http://www.slamd.com/]. SLAMD is also available as a java.net project. See [https://slamd.dev.java.net/ https://slamd.dev.java.net/].
 
Java Naming and Directory Interface (JNDI) technology supports accessing the Directory Server using LDAP and DSML v2 from Java applications. For information about JNDI, see [http://java.sun.com/products/jndi/ http://java.sun.com/products/jndi/]. The ''JNDI Tutorial'' contains detailed descriptions and examples of how to use JNDI. This tutorial is at [http://java.sun.com/products/jndi/ http://java.sun.com/products/jndi/tutorial/].<br>
 
== Understanding LDAP<br>  ==
 
Lightweight Directory Access Protocol (LDAP) is the Internet directory protocol. Developed at the University of Michigan at Ann Arbor in conjunction with the Internet Engineering Task Force, LDAP is a protocol for accessing and managing directory services.<br>
 
=== How Directory Services Work  ===
 
A directory consists of entries that contain descriptive information. For example, a directory might contain entries that describe people or network resources, such as printers or fax machines.
 
The descriptive information is stored in the attributes of the entry. Each attribute describes a specific type of information. For example, attributes that describe a person might include her name, also referred to as her common name (CN), telephone number, and email address.
 
The entry for Barbara Jensen might have the following attributes:
<pre>cn: Barbara Jensen
mail: babs@example.com
telephoneNumber: 555-1212
roomNumber: 3995
</pre>
An attribute can have more than one value. For example, a person might have two common names, both a formal name and also a nickname:
<pre>cn: Barbara Jensen
cn: Babs Jensen
mail: babs@example.com
telephoneNumber: 555-1212
roomNumber: 3995
</pre>
Attributes can also contain binary data. For example, a person's attributes might include her photo in JPEG format, a recording of her voice as an audio file, or her SSL certificate.
 
A ''directory service'' is a distributed database application for managing the entries and attributes in a directory. A directory service also makes the entries and attributes available to users and other applications.
 
Directory Server is an example of a directory service. For example, a user might use the directory service to look up someone's telephone number. Another application might use the directory service to retrieve a list of email addresses.
 
LDAP is a protocol that defines a directory service and access to that service. LDAP is based on a client-server model. LDAP servers provide the directory service. LDAP clients use the directory service to access entries and attributes.
 
Directory Server is an example of an LDAP server that manages and provides information about users and organizational structures. Examples of LDAP clients include Identity Manager, Access Manager, Solaris™ naming services, Messaging Server, Portal Server, NameFinder, and the Mozilla mail client. Such clients use Directory Server to find, update, and add information about users.<br>
 
=== How LDAP Servers Organize Directories  ===
 
Because LDAP is intended to be a global directory service, data is organized hierarchically, starting at a root and branching down into individual entries.
 
At the top level of the hierarchy, entries represent larger organizations. Under larger organizations in the hierarchy, you might find entries for smaller organizations. The hierarchy might end with entries for individual people, or resources, as shown in the following figure.<br>
 
[[Image:Hierovrw.png|Hierarchy of Entries in a Directory]]<br>
 
Each entry is uniquely identified by a ''distinguished name'' (DN). A DN includes a relative distinguished name (RDN), that uniquely identifies the entry at that hierarchical level. For example, <tt>bjensen</tt> and <tt>kjensen</tt> are different user IDs that identify different entries at the same level. Following the RDN is a path of names that trace the entry back to the root of the tree, such as <tt>ou=People,dc=example,dc=com</tt>. <tt>DC</tt> is short for domain component. The full DN for this example would be <tt>uid=bjensen,ou=People,dc=example,dc=com</tt>. Here, <tt>uid</tt> is the user ID of the entry. <tt>ou</tt> is short for organizational unit.
 
The data stored in a directory can be distributed among several LDAP servers. For example, one LDAP server at Example.com might contain entries representing North American organizational units and employees, while another LDAP server might contain entries representing European organizational units and employees.
 
Some LDAP servers are set up to refer requests to other LDAP servers. For example, if the LDAP server at Example.com receives a request for information about an employee in a Pacific Rim branch, that server can refer the request to the LDAP server at the Pacific Rim branch. In this way, LDAP servers can appear to be a single source of directory information. Even if an LDAP server does not contain the information you request, the server can refer you to another server that does contain the information.<br>
 
=== How LDAP Clients and Servers Work  ===
 
In the LDAP client-server model, LDAP servers such as Directory Server make information about people, organizations, and resources accessible to LDAP clients. LDAP defines operations that clients use to search and update the directory.
 
*Search for and retrieve entries from the directory
*Add new entries to the directory
*Update entries in the directory
*Delete entries from the directory
*Rename entries in the directory
 
For example, to update an entry, an LDAP client submits the distinguished name of the entry with updated attribute information to the LDAP server. The LDAP server uses the distinguished name to find the entry. The server then performs a modify operation to update the entry in the directory.
 
To perform any of these LDAP operations, an LDAP client needs to establish a connection with an LDAP server. The LDAP protocol specifies the use of TCP/IP port number 389, although servers can run on other ports.
 
The LDAP protocol also defines a simple method for authentication. LDAP servers can be set up to restrict permissions to the directory. Before an LDAP client can perform an operation on an LDAP server, the client must authenticate to the server. Clients typically authenticate by supplying a distinguished name and password. If the user identified by the distinguished name does not have permission to perform the operation, the server does not execute the operation.<br>
 
=== Understanding LDAP v3  ===
 
RFC 4511 specifies LDAP version 3. Use this version of the protocol when writing new client applications.
 
Many LDAP servers continue to support LDAP version 2 for use with legacy clients. This version of the protocol is specified in RFC 1777.
 
Clients and servers can specify ''controls'' that extend the functionality of an LDAP operation.
 
Clients can request that the server perform ''extended operations'', operations not included in the list of standard LDAP operations.
 
Clients can use ''Simple Authentication and Security Layer'' (SASL) mechanisms to authenticate to the directory. SASL is specified in RFC 4422.
 
Servers, known as ''Directory System Agents'' (DSAs), have ''DSA-specific entries'' (DSEs). DSEs provide information about the versions of the LDAP protocol that the server supports. DSEs also provide a list of the controls, extended operations, and SASL mechanisms supported by the server. Finally, DSEs specify the naming contexts of the server. Naming contexts are portions of the directory information tree managed by the server.
 
Servers make their ''schemas'', which define the object classes, attributes, syntaxes, and matching rules enforced by the directory, available to clients through the root DSE.
 
Both client and server applications can support data in UTF-8. ''UTF-8'' is a transformation format of the Universal Character Set standard. UTF-8 is specified in RFC 3269. With UTF-8, clients can request and receive data that is tagged with language information.<br>
 
== Choosing a Client SDK  ==
 
This chapter discusses software development kits to help you select the appropriate directory SDK for your particular situation.
 
=== Java Naming and Directory Interface  ===
 
Java Naming and Directory Interface (JNDI) technology supports directory access through LDAP and DSML v2 from Java™ applications, and is part of the Java platform. With JNDI, you can build powerful, portable, directory-enabled applications that do not depend on classes outside the Java platform.
 
JNDI provides an abstract model that lets you access not only directories, but also naming services in general, including DNS, RMI, COS, and file systems.
 
For information about JNDI, see [http://java.sun.com/products/jndi/ http://java.sun.com/products/jndi/]. The JNDI Tutorial contains descriptions and examples of how to use JNDI. The tutorial is at [http://java.sun.com/products/jndi/tutorial/ http://java.sun.com/products/jndi/tutorial/].
 
=== Directory SDK for C  ===
 
Directory SDK for C lets you access LDAP directories from C and C++ applications. Directory SDK for C applications depend on Directory SDK for C libraries, which are available on a wide range of platforms.
 
Directory SDK for C was the subject of Internet-Draft work but never became a standard API. Directory SDK for C closely follows LDAP v3, providing support for core LDAP operations and for LDAP v3 extensions and widely used controls. Directory SDK for C offers a rich API to the C and C++ developer familiar with the LDAP model. Directory Server relies on Directory SDK for C.
 
This document demonstrates how to use Directory SDK for C. Directory SDK for C code is published in open source form as part of the Mozilla Directory SDK project.<br>
 
=== Directory SDK for Java  ===
 
Directory SDK for Java lets you access LDAP directories from Java applications, but it is not part of the Java platform.
 
Although not a standard API, Directory SDK for Java closely follows LDAP v3 idioms. Directory SDK for Java provides a rich set of interfaces to the Java developer familiar with the LDAP model.
 
This document demonstrates how to use Directory SDK for Java. Directory SDK for Java code is published in open source form as part of the Mozilla Directory SDK project.<br>
 
=== Operating System libldap Library  ===
 
The native LDAP library on Solaris™ systems provides essentially the same API as Directory SDK for C. Many Directory SDK for C need only be recompiled to work with libldap.
 
The LDAP library is sometimes not compatible with libldap on many GNU/Linux distributions. Many GNU/Linux distributions provide OpenLDAP support by default.<br>
 
=== Support for Other Programming Languages  ===
 
Support for directory access is available in a number of contexts where you do not choose to use the C or Java languages.
 
For example, Perl has the PerLDAP module and the Net::LDAP collection of modules. Python has the python-ldap package. PHP can be compiled with LDAP support. Ruby has the Ruby/LDAP extension module. In many cases, you can choose the language that fits the task and find that LDAP support is available.<br>
 
== Best Practices for Writing Client Applications<br>  ==
 
The section covers what to keep in mind when creating and debugging LDAP&nbsp;client applications.<br>
 
=== Specify LDAP v3  ===
 
With JNDI, you could use LDAP v3 as shown here.
<pre>import java.util.Hashtable;
import javax.naming.ldap.InitialLdapContext;
 
Hashtable env = new Hashtable();
env.put("java.naming.ldap.version", "3");
InitialLdapContext ctx = new InitialLdapContext(env, null);
</pre>
With Directory SDK for C, you could use LDAP v3 as shown here.
<pre>#include "ldap.h"
 
int version = LDAP_VERSION3;
ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version );
</pre>
Directory SDK for C uses LDAP v3 by default.
 
With Directory SDK for Java, you could use LDAP v3 as shown here.
<pre>import netscape.ldap.LDAPConnection;
 
LDAPConnection ld = new LDAPConnection();
ld.setOption(LDAPv3.PROTOCOL_VERSION, new Integer(3));
</pre>
=== Authenticate Correctly  ===
 
Your SDK uses terminology that is slightly different from LDAP v3. In LDAP v3, you connect, then you bind and perform LDAP operations, then you unbind and disconnect. The bind is the authentication operation in LDAP. Your application can hold onto a connection but change the authentication credentials by using the bind operation again.
 
Some directories do not allow anonymous access, even for reads. When you build your application, keep the option that allows users to authenticate to the directory. Furthermore, the information sent across the network can be sensitive. You can protect sensitive data by allowing the application to secure the connection by using Secure Sockets Layer (SSL) or Start Transport Layer Security (TLS).
 
If your application needs to authenticate, obtain a regular account to authenticate with the directory, rather than using the directory superuser account such as <tt>cn=Directory Manager</tt>. When you authenticate as directory superuser, you often bypass normal access control mechanisms. Bypassing normal access control renders auditing directory access more difficult.
 
When authenticating, have your application use SSL or SASL DIGEST MD5 to avoid sending passwords over the network in clear text. Furthermore, when using password-based authentication, have your application check password policy controls, especially to determine when a password must be renewed.
 
=== Limit Connection Overhead  ===
 
A new connection requires system resources. The LDAP model allows you to reuse connections by binding again with a different identity on the same connection. Thus, you can avoid the costs of new connections, particularly negotiated connections such as connections that use SSL, by reusing connections. Your application can use a pool of connections, rebinding when necessary. Your application can alternatively use the proxy authorization control to remain authenticated as the application but perform operations on behalf of a particular user.
 
When establishing a connection, your application can provide alternate server host names and port numbers to facilitate failover that is transparent to the application. You can also set time limits for LDAP operations to avoid getting blocked.
 
When finished with a connection, your application should perform an unbind.
 
=== Handle Potential Inactivity Timeouts  ===
 
Most network equipment can use timeouts to drop stale connections, ensuring the equipment keeps a maximum number of connections that are available.
 
If your application pools connections or opens connections for persistent search, than guard against timeouts that drop those connections. Use the connections occasionally to reset inactivity timers present in the network.
 
Alternatively, if you have control over the connection, consider disabling inactivity time outs for your applications that need to keep persistent connections open. Load balancers and proxy software often use inactivity timeouts.
 
=== Retrieve Entries Intelligently  ===
 
Directory Server typically responds quickly to requests for entries. Yet, Directory Server can respond most quickly when your application asks it to do only necessary work. If you need to read only a few attributes in an entry, request each attribute explicitly. Avoid reading the entire entry, then parsing the entire entry to obtain the required data.
 
Furthermore, when you do request attributes in an entry, retrieve all the required attributes at once. Each new request involves a new operation on the server.
 
If any of the attributes that you require are operational attributes, you must request those attributes specifically. Such attributes are identifiable in directory schema by their USAGE, which is directoryOperation or dsaOperation.
 
When retrieving entries and attributes, recognize that you might not have access to all the attributes that exist.
 
=== Write Simple, Conforming LDAP Filters  ===
 
The best filters use attributes that are indexed according to the way the attributes are indexed. For example, if <tt>employeeNumber</tt> is indexed for equality, your filter should be an equality filter such as <tt>(employeeNumber=123456)</tt>. Do not use a substring filter instead.
 
Avoid deeply nested complex filters when you can. When you must use complex filters, place the most specific filters first to narrow the list of candidate entries the directory must check. For best results, use not, <tt>!</tt>, only with and, <tt>&amp;</tt>, for example <tt>(&amp;(cn=Barbara)(!(sn=Jensen)))</tt>. When you use not with or in a filter, the directory must construct a candidate list of everything except what your filter specifies.
 
=== Performing Specific Modifications  ===
 
Modifications are atomic on the entry to which the modifications apply. When modifying multivalued attributes, delete and replace specific values. Do not replace an entire list of multiple values to change only a few values. Replacing specific values is particularly good practice when the changes must be replicated across a set of servers.
 
Moreover, when you have large values to store in an attribute, store a reference to the data instead of storing the data object.
 
=== Trust Result Codes  ===
 
Directory Server trades tight consistency across replica servers for very high performance, availability, and scalability. By allowing loose consistency of data across sets of replica servers, Directory Server instances can respond very quickly to your application. Yet, data replication is not instantaneous. A short but detectable delay can ensue after a server returns success for a write operation, but before the effects are seen on other replicas.
 
Therefore, when your application receives a result code from Directory Server to indicate that an operation was successful, your application should trust the result code. When application requests are balanced across replicas, reading from another replica might result in errors due to a slight delay in replication.<br>
 
=== Limit Dealings With Groups and Roles  ===
 
When you want to know whether an account belongs to a group or a role, read only the necessary attribute values. Do not read the entire list of group members.
 
#Read the URL from the group definition.
#Examine the host, DN, and scope of the URL.
#Apply the filter part of the URL to the entry for the account.
 
For roles, compare the DN of the role to the nsRole attribute of the entry for the account, such as <tt>(nsrole=cn=management,ou=people,dc=example,dc=com)</tt>. You can then retrieve all the values of the nsRole attribute for the account.
 
=== Read the DSE  ===
 
The root DSE is the entry that is retrieved by <tt>ldapsearch -b "" -s base "(objectclass=*)"</tt>. The root DSE describes server capabilities. The root DSE contains information about supported LDAP protocol versions, naming contexts (suffixes), LDAP v3 controls, LDAP v3 extensions, and authentication mechanisms. The root DSE can contain information about the server version.
 
Some directory administrators protect access to the root DSE. Yet, applications might read the root DSE to confirm that the server in fact supports functionality required by applications.
 
=== Use Resource-Intensive Features Sparingly  ===
 
Directories offer powerful features that can nevertheless place a heavy load on the server. Two such features are persistent search, and server-side sorting.
 
Persistent search lets you start a search that does not stop when complete, but instead allows you to receive updates when entries are modified. To provide this feature, the server must handle your search when anything happens to an entry in its scope.
 
Server-side sorting requires that the server sort the entries that are returned during a search. Instead of returning entries as quickly as possible, the server must therefore get the list to return, and sort the list.
 
=== Avoid Hard Coding Certain Information  ===
 
The container entry for a subtree might be not be identical on different directories. Rather than hard code the container entry throughout your application, locate the container entry. Then navigate beneath the container entry in the tree.
 
Object classes and attribute types for the same information can also differ from directory to directory. Use configuration files, properties files, or other easily modifiable variables rather than hard coding object class and attribute type identifiers into your application.
 
Be aware as well that object class and attribute type identifiers are not case-sensitive in LDAP. Your application should therefore recognize that <tt>inetOrgPerson</tt> and <tt>inetorgperson</tt> are equivalent, as are <tt>isMemberOf</tt> and <tt>ismemberof</tt>.
 
=== Define Schemas Only When Necessary  ===
 
Schemas define the object classes and attribute types that are recognized by the directory. If your application can use a standard schema, use the standard schema. Directory Server contains schemas that define numerous standard object classes, and attribute types.
 
*Extend existing object classes by using AUXILIARY classes.
*Create new attributes rather than redefining existing attributes.
*Other applications might depend on existing attributes to keep their existing semantics.
*Obtain new object identifiers for the schema elements you define, rather than reusing existing object identifiers.
*Obtain new names for the schema elements you define, rather than reusing existing names.
*Update Directory Server schema over LDAP if you can.
 
=== Handle Referrals  ===
 
LDAP v3 allows directories that are unable to handle your request to refer your application to other directories. Your application should follow those referrals.
 
When following referrals, realize that authentication procedures might not be exactly the same on different directories. Also, directories that refer to each other could potentially cause a referral loop. With Directory SDK for C and Directory SDK for Java, you can limit referral hops to prevent your application from being referred endlessly from one directory to another directory. The JNDI interface enables you to follow referrals automatically.
 
=== Treat a Directory as a Directory  ===
 
A directory is typically a repository for identity data, and for information that you expect to keep for awhile and read often. You might typically find relational databases better adapted to hold transient data such as session keys and presence information, or voluminous accumulated data such as application logs.<br>
 
=== Check Result Codes  ===
 
When an LDAP request from your application fails on the server, the server sends back a result code, and possibly an explanatory message. Your application should check the result codes, and for explanatory messages. Common failure result codes include the following, which are expressed as decimal values. Others result codes are defined as well.
 
1<br>LDAP operations error. The server encountered an error while processing your request.
 
32<br>No such object. The entry is not present on the server. Also, no referral is defined for the entry.
 
49<br>Invalid credentials. Your application failed to authenticate properly.
 
53<br>LDAP unwilling to perform. The directory does not support the request. Alternatively, the directory is not currently in a state in which to complete your request. For example, the directory might be in read-only mode when your application requests a modification.
 
65<br>Object class violation. Your write request would cause an entry to no longer conform to the schema defined for the directory.
 
68<br>Already exists. Your application is requesting to add an entry that has the same DN as an entry already present in the directory.
 
RFC 4511 defines LDAP error codes.
 
=== Check Server Log Files  ===
 
Directory Server logs messages related to server operation in its logs/errors file. If you have access to this file, you might find useful troubleshooting information there.
 
When debugging your application against Directory Server, you can adjust the log level, as well. See the server documentation for instructions.
 
=== Inspect Network Packets  ===
 
Although LDAP is not a textual protocol, tools such as snoop, ethereal, and tcpdump can decode the packets, sometimes providing you with important debugging information.<br>
 
== About Directory SDK for C<br>  ==
 
This section introduces the LDAP&nbsp;C SDK.<br>
 
=== Overview of Directory SDK for C  ===
 
Directory SDK for C includes the C libraries for the LDAP API as well as sample code that demonstrates how to call many functions. The APIs are defined by the header files that declare all of the functions, data types, and code values in the SDK. You use the functions in this API to write C or C++ client applications that take full advantage of server capabilities.
 
The APIs are built around core functions of the LDAP v2 and v3 standards. Therefore, the APIs can be used to interact with any conforming LDAP server. This API conforms to the standard that is proposed in ''The C LDAP Application Programming Interface''.<br>
 
==== LDAP API  ====
 
RFC 4511, Lightweight Directory Access Protocol (v3), defines a set of operations to access data in an LDAP v3 compliant directory server. The functionality implemented in Directory SDK for C closely follows these operations because a C API is defined for each operation.
 
*Search for and retrieve a list of entries.
*Add new entries to the database.
*Update existing directory entries.
*Delete entries.
*Rename entries.
 
For example, if you are writing an email application, you can use the functions in the API to retrieve email addresses from an LDAP server.
 
==== Synchronous and Asynchronous Operations  ====
 
The API functions allow you to perform LDAP operations synchronously or asynchronously. The only differences between these two options are in the calling convention. The LDAP exchanges are identical.
 
*Call a synchronous function to wait for the operation to complete before receiving the return value of a function.
*Call an asynchronous function to perform other work while waiting for an operation to complete. Your application must then poll for results.
 
For more information, see Synchronous Examples, and Asynchronous Examples. TODO LINKS<br>
 
=== Files Provided With Directory SDK for C  ===
 
Directory SDK for C includes a number of sample files, headers, libraries, and tools. This section helps you to locate the files. All locations are relative to the directory where the software is installed, which depends on your operating system.<br>
 
{| cellspacing="1" cellpadding="1" border="1" summary="Directory SDK for C Content"
|+ Directory SDK for C Content
|-
! scope="col" | Directory Location<br>
! scope="col" | Description<br>
|-
| <tt>etc/</tt><br>
| Contains miscellaneous files for you to use.<br>
|-
| <tt>examples/</tt><br>
| Contains sample source code and Makefiles for LDAP clients. See the README file in this directory for more information.<br>
|-
| <tt>include/</tt><br>
| Contains the header files. You must include the files in this directory in your client source files.<br>
|-
| <tt>include-nspr/</tt><br>
| Contains Netscape Portable Runtime (NSPR) header files. NSPR provides a platform-neutral API for systemlevel and libcstyle functions.<br>
|-
| <tt>include-private/</tt><br>
| Contains private header files that are not documented in this guide.<br>
|-
| <tt>lib/</tt><br>
| Contains the C library files. The specific library used is dependent on the type of application you are building.<br>
|-
| <tt>lib-private/</tt><br>
| Contains private header files that are not documented in this guide.<br>
|-
| <tt>tools/</tt><br>
| Contains the LDAP command-line tools. To use these applications, you must ensure that the tools can find the LDAP API shared library or dynamic link library.<br>
|}
 
==== Directory SDK for C Header Files  ====
 
The following table describes Directory SDK for C header files that are in the <tt>include/</tt> directory.
 
'''Note:''' All locations are relative to the directory where the software is installed, which depends on your operating system.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Directory SDK for C Header Files"
|+ Directory SDK for C Header Files
|-
! scope="col" | Header File<br>
! scope="col" | Description<br>
|-
| <tt>disptmpl.h</tt><br>
| A header file related to the templates (<tt>ldaptemplates.conf</tt>).<br>
|-
| <tt>lber.h</tt><br>
| Contains prototypes for the standard Basic Encoding Rules (BER) functions, structures, and defines.<br>
|-
| <tt>ldap-deprecated.h</tt><br>
| Contains deprecated functions that should not be used.<br>
|-
| <tt>ldap-extension.h</tt><br>
| Contains functions, structures, and defines that extend the standard LDAP C API specification.<br>
|-
| <tt>ldap-platform.h</tt><br>
| A private header file that contains platform-specific definitions, which allow abstraction from the underlying system.<br>
|-
| <tt>ldap-standard.h</tt><br>
| Contains the standard LDAP functions, structures, and defines.<br>
|-
| <tt>ldap-to-be-deprecated.h</tt><br>
| Contains functions, structures, and defines that might be deprecated in future releases.<br>
|-
| <tt>ldap.h</tt><br>
| This base header contains LDAP functions, structures, and defines to mirror the latest LDAP C API specifications. Includes: <tt>ldap-deprecated.h</tt>, <tt>ldap-extension.h</tt>, <tt>ldap-standard.h</tt>, <tt>ldap-to-be-deprecated.h</tt><br>
|-
| <tt>ldap_ssl.h</tt><br>
| Contains prototypes for LDAP over SSL functions, structures, and defines.<br>
|-
| <tt>ldappr.h</tt><br>
| Contains prototypes for the functions, structures, and defines that are contained in the Netscape Portable Runtime (NSPR) API.<br>
|-
| <tt>srchpref.h</tt><br>
| A header file related to the search preferences (<tt>ldapsearchprefs.conf</tt>).<br>
|}
 
===== ldap.h Header File  =====
 
To make use of the Directory SDK for C functions, include the ldap.h header file in your C source files as shown in this line of code:<br>
<pre>#include "ldap.h"</pre>
===== lber.h Header File =====
 
lber.h is included in ldap-standard.h. You do not need to include the header explicitly. Basic Encoding Rules (BER) is a simple tag-value scheme to encode requests and decode results.
 
===== ldap_ssl.h Header File =====
 
If you are calling LDAP over SSL functions, you also need to include the ldap_ssl.h header file, as follows:
<pre>#include "ldap_ssl.h"
</pre>
===== ldappr.h Header File =====
 
To make use of the Netscape Portable Runtime (NSPR) API with your LDAP applications, you must include the ldappr.h file. The NSPR is a set of platform-neutral APIs that provides system functions such as threads, thread synchronization, I/O, interval timing, and atomic operations. This header file contains prototypes for functions that tie the LDAP libraries to NSPR. You include the header file as follows:
<pre>#include "ldappr.h"
</pre>
For more information about NSPR, see the ldappr.h header file and the Netscape Portable Runtime project page at [http://www.mozilla.org/projects/nspr/ http://www.mozilla.org/projects/nspr/].<br>
 
==== Miscellaneous Files  ====
 
Directory SDK for C includes the sample files described in the following table. Sample files can be retrieved when using certain APIs. Sample files are located in the <tt>etc/</tt> directory. All locations are relative to the directory where the software is installed, which depends on your operating system.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Sample Configuration Files"
|+ Sample Configuration Files
|-
! scope="col" | File Name<br>
! scope="col" | Description<br>
|-
| <tt>ldapfilter.conf</tt><br>
| This filter configuration file can be used in context with <tt>ldap_init_getfilter()</tt>.<br>
|-
| <tt>ldapfriendly</tt><br>
| This file is used to map the twoletter country codes to their full names by <tt>ldap_friendly_name()</tt>.<br>
|-
| <tt>ldapsearchprefs.conf</tt><br>
| This configuration file was used in context with a deprecated function.<br>
|-
| <tt>ldaptemplates.conf</tt><br>
| This configuration file was used in context with a deprecated function.<br>
|}
 
==== Directory SDK for C Libraries  ====
 
Directory SDK for C includes several different libraries. A library is a set of ready-made functions that are linked into a program. Directory SDK for C uses ''shared'' libraries. Shared libraries are dynamically loaded into memory when needed, reducing the size of the executable.
 
===== Library Naming Conventions  =====
 
Libraries on different systems have different naming conventions. The following table shows the Directory SDK for C naming conventions.<br>
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Library Naming Convention by Operating System"
|+ Library Naming Convention by Operating System
|-
! scope="col" | Operating System<br>
! scope="col" | Static Library Name<br>
! scope="col" | Shared Library Name<br>
|-
| Solaris and Red Hat systems<br>
| lib''libraryname''.a<br>
| lib''libraryname''.so.versionnumber<br>
|-
| HP-UX systems<br>
| lib''libraryname''.a<br>
| lib''libraryname''.sl<br>
|-
| Windows systems<br>
| ns''libraryname''.lib<br>
| ns''libraryname''.dll<br>
|}
 
On UNIX® systems, the shared library file name can be fully qualified by prefixing path information.<br>
 
===== Installed Shared Libraries  =====
 
The following table describes the installed libraries that are in the lib/ directory. All locations are relative to the directory where the software is installed, which depends on your operating system.<br>
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Shared Libraries"
|+ Shared Libraries
|-
! scope="col" | UNIX Library<br>
! scope="col" | Windows Library<br>
! scope="col" | Description<br>
|-
| <tt>libldap60.so</tt><br>
| <tt>nsldap32v60.dll</tt><br>
| LDAP library<br>
|-
| <tt>libprldap60.so</tt><br>
| <tt>nsldappr32v60.dll</tt><br>
| LDAP library built with NSPR.<br>This library requires the <tt>libnspr4.so</tt> library in the <tt>lib-private/</tt> directory.<br>
|-
| <tt>libssldap60.so</tt><br>
| <tt>nsldapssl32v60.dll</tt><br>
| LDAP library that is built with support for the Secure Sockets Layer protocol.<br>This library depends on the <tt>libnss3.so</tt> and <tt>libnspr4.so</tt> libraries in the <tt>lib-private/</tt> directory.<br>
|}
 
===== Directory SDK for C Dependencies<br>  =====
 
*Netscape Portable Runtime (NSPR) provides core cross-platform functions.<br>
*Netscape Security Services (NSS) provides encryption, cryptographic, Secure Sockets Layer (SSL), and Public Key Infrastructure (PKI) support.<br>
*Simple Authentication and Security Layer (SASL) provides support for applications that require SASL.
 
==== LDAP Tools  ====
 
Directory SDK for C includes several utilities to help you work with LDAP data sets. These utilities are installed in the <tt>tools/</tt> directory. For details on each tool described in the following table, see the corresponding man pages. A list of options can be retrieved by typing the tool name at the command line.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Directory SDK for C LDAP Tools"
|+ Directory SDK for C LDAP Tools
|-
! scope="col" | Command<br>
! scope="col" | Description<br>
|-
| <tt>ldapcmp</tt><br>
| Compares the contents of a single LDAP entry or subtree in two directories.<br>
|-
| <tt>ldapcompare</tt><br>
| Compares an attribute value against the contents of a given LDAP entry.<br>
|-
| <tt>ldapdelete</tt><br>
| Deletes existing LDAP entries.<br>
|-
| <tt>ldapmodify</tt><br>
| Edits the contents of an LDAP directory, either by adding new entries or modifying existing ones.<br>
|-
| <tt>ldappasswd</tt><br>
| Changes user passwords on LDAP entries.<br>
|-
| <tt>ldapsearch</tt><br>
| Issues search requests to an LDAP directory, then displays the result as LDAP Data Interchange Format (LDIF) text.<br>
|}
 
=== Compiling Applications with Directory SDK for C  ===
 
When compiling applications, you must include the header files and link to the libraries required. Information about including the header files is in Directory SDK for C Header Files. Linking to shared libraries is covered in this section. Directory SDK for C is qualified to work with C compilers.
 
'''Note:''' Directory SDK for C is not guaranteed to work with C++ compilers.<br>
 
==== Compiling on UNIX Platforms  ====
 
When compiling clients on UNIX platforms, specify link options correctly to link the application to the appropriate shared libraries. See the Makefile in the <tt>examples/</tt> directory for details on compiling your applications on UNIX platforms.
 
==== Compiling on Windows Systems With Directory SDK for C  ====
 
*<tt>_CONSOLE</tt> if you are writing a console application
*<tt>_WINDOWS</tt> if you are writing a standard Windows GUI application
 
==== Linking Dependencies  ====
 
When you run LDAP clients, you must ensure that the operating system can find the shared libraries that support the functions called by your application. Generally, these files are referred to as runtime libraries. Any of the following options ensure that the operating system can find the shared libraries.
 
*Make sure that the shared library file, such as <tt>libldap60.so</tt>, is in a location specified by environment variables.
*On some platforms, clients can be complied with flags that let you set the runtime path to load libraries as an environment variable.
**On Solaris™ and Red Hat systems, you can use the <tt>LD_LIBRARY_PATH</tt> environment variable if you use the <tt>-Wl,+s+b</tt> flag when compiling and linking.
**On HP-UX system, use the <tt>SHLIB_PATH</tt> environment variable.
*#The directory from which the application loaded
*#The current directory
*#The Windows system directory, typically <tt>winnt\system32\</tt><br>To avoid potential conflicts, do not copy the DLL to this directory
*#The directories listed in the PATH environment variable
*Use a link flag that specifies the path where the executable can find the library. For example, on Solaris systems, you can use the <tt>-R</tt> flag to specify the path where the executable can find the library.<br>See the Makefile in the <tt>examples/</tt> directory for examples of additional settings for compiling and linking your LDAP client. Different platforms might require different sets of define statements.<br>
 
=== Sample Programs for Directory SDK for C  ===
 
Directory SDK for C includes several examples that demonstrate the use of the functions that the SDK provides. The examples are located in the <tt>examples/</tt> directory. The example code is designed to run against the LDAP v3 compliant Directory Server. Furthermore, the example code is designed to work with sample data that has been properly loaded. For details on the source files, refer to the <tt>README</tt> in the <tt>examples/</tt> directory.
 
The samples use synchronous LDAP calls and their asynchronous counterparts. Because synchronous LDAP calls are more straightforward than their asynchronous counterparts, look at the synchronous examples first.
 
==== Synchronous Examples  ====
 
The synchronous calls block the calling process until all results have been returned. As these programs usually rely on event loops, the programs are not appropriate for use with clients that implement a GUI in a single-threaded environment. However, these sample programs do work with command-line clients and CGI programs.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Synchronous Example Programs"
|+ Synchronous Example Programs
|-
! scope="col" | Example Source<br>
! scope="col" | Description<br>
|-
| <tt>authzid.c</tt><br>
| Shows how to use the authorization ID control, which allows you to get the authorization ID for an LDAP operation.<br>
|-
| <tt>compare.c</tt><br>
| Shows how to use ldap_compare_s(), which allows you to test if a particular value is contained in an attribute of an entry.<br>
|-
| <tt>crtfilt.c</tt><br>
| Shows how to use the ldap_create_filter() function to generate LDAP filters.<br>
|-
| <tt>csearch.c</tt><br>
| Like search.c, but enables an in-memory cache.<br>
|-
| <tt>effright.c</tt><br>
| Shows how to use the get effective rights control, which allows you to determine access rights to entries and their attributes.<br>
|-
| <tt>getattrs.c</tt><br>
| Retrieves specific attributes from an entry.<br>
|-
| <tt>getfilt.c</tt><br>
| Shows how to use the ldap_getfilter*() family of functions, which generate LDAP filters that are based on an arbitrary search string provided by a user.<br>
|-
| <tt>modattrs.c</tt><br>
| Shows how to use ldap_modify_s() to replace and add to values in an attribute.<br>
|-
| <tt>modrdn.c</tt><br>
| Shows how to use ldap_modrdn2_s() to change the relative distinguished name (RDN) of an entry.<br>
|-
| <tt>pwdextop.c</tt><br>
| Shows how to use the LDAP password modify extended operation to change a password.<br>
|-
| <tt>pwdpolicy.c</tt><br>
| Shows how to use the password policy control. This control allows you to retrieve information about the password policy that applies to the user binding to the directory.<br>
|-
| <tt>rdentry.c</tt><br>
| Shows how to use ldap_search_s() to retrieve a particular entry from the directory.<br>
|-
| <tt>realattr.c</tt><br>
| Shows how to use the control to retrieve only real attributes during a search.<br>
|-
| <tt>search.c</tt><br>
| Shows how to use ldap_search_s() to search for all entries that have an attribute value that exactly matches what you search for.<br>
|-
| <tt>srvrsort.c</tt><br>
| Shows how to use server-side sorting in conjunction with the ldap_search_ext_s() function.<br>
|-
| <tt>ssearch.c</tt><br>
| Like ssnoauth.c, but includes certificate-based authentication.<br>
|-
| <tt>ssnoauth.c</tt><br>
| Like search.c, but the search is done over an SSL-protected TCP connection.<br>
|-
| <tt>starttls.c</tt><br>
| Shows how to use the Start TLS extended operation.<br>
|-
| <tt>userstatus.c</tt><br>
| Shows how to use the account status control to retrieve information about the account of the user binding to the directory.<br>
|-
| <tt>virtattr.c</tt><br>
| Shows how to use the control to retrieve only virtual attributes during a search.<br>
|-
| <tt>whoami.c</tt><br>
| Shows how to use the Who am I? extended operation to retrieve the authorization ID.<br>
|}
 
==== Asynchronous Examples  ====
 
These examples use the asynchronous LDAP calls. You begin an operation. You then periodically poll to see if any results have been returned.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Asynchronous Example Programs"
|+ Asynchronous Example Programs
|-
! scope="col" | Example Source<br>
! scope="col" | Description<br>
|-
| <tt>add.c</tt><br>
| Adds an entry to the directory.<br>
|-
| <tt>asearch.c</tt><br>
| Initiates a search for entries, printing the results on arrival.<br>
|-
| <tt>del.c</tt><br>
| Deletes an entry from the directory.<br>
|-
| <tt>nsprio.c</tt><br>
| Like asearch. but uses the PerLDAP routines to incorporate the Netscape Portable Runtime (NSPR) API.<br>
|-
| <tt>ppolicy.c</tt><br>
| Attempts to bind to the directory and reports back any password expiration information received. This program demonstrates how clients can process password policy information.<br>
|-
| <tt>psearch.c</tt><br>
| Shows how to use Persistent Search, an LDAP v3 extension, to monitor a directory for changes.<br>
|}
 
== Getting Started With Directory SDK for C  ==
 
This section shows how to create a first client application.
 
=== Sample Directory Client Code  ===
 
The following sample source code is for a command-line program that retrieves the full name, last name, email address, and telephone number of Barbara Jensen.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
/* Adjust these setting for your own LDAP server */
#define HOSTNAME "localhost"
#define PORT_NUMBER  LDAP_PORT
#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
 
int
main( int argc, char **argv )
{
  LDAP        *ld;
  LDAPMessage  *result, *e;
  BerElement  *ber;
  char        *a;
  char        **vals;
  int          i, rc;
 
  /* Get a handle to an LDAP connection. */
  /* To get the handle on an IPv6 network, use prldap_init() instead. */
  if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
 
  /* Bind anonymously to the LDAP server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string(rc));
    return( 1 );
  }
 
  /* Search for the entry. */
  if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
    "(objectclass=*)", NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
    LDAP_NO_LIMIT, &amp;result ) )&nbsp;!= LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string(rc));
    return( 1 );
  }
 
  /* Since we are doing a base search, there should be only
    one matching entry.  */
  e = ldap_first_entry( ld, result );
  if ( e&nbsp;!= NULL ) {
    printf( "\nFound&nbsp;%s:\n\n", FIND_DN );
 
    /* Iterate through each attribute in the entry. */
    for ( a = ldap_first_attribute( ld, e, &amp;ber );
      a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
 
      /* For each attribute, print the attribute name and values. */
      if ((vals = ldap_get_values( ld, e, a))&nbsp;!= NULL ) {
        for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
          printf( "%s:&nbsp;%s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber&nbsp;!= NULL ) {
      ber_free( ber, 0 );
    }
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}</pre>
=== Compiling Directory SDK for C Client Applications  ===
 
The method used to compile the source code depends on the operating system on which you run the application. The following sections include instructions for compiling on UNIX and Windows systems.
 
==== Compiling Programs on UNIX Systems  ====
 
The Directory SDK for C <tt>examples/</tt> directory contains a UNIX Makefile. You can modify the Makefile to compile the sample by adjusting the flags in the file. The Makefile assumes that the Directory SDK for C header files are located in the <tt>../include/</tt> directory.
 
==== Compiling Programs on Windows Systems  ====
 
*If you are using Microsoft development tools, create a new project workspace for a console application. Then add the source file to the project.
*Set your options to include <tt>lib\</tt> as one of the directories for library files, and <tt>include\</tt> as one of the directories for include files.
*Link to <tt>nsldap32v60.lib</tt>, the LDAP API import library for Windows.
 
=== Running the Client  ===
 
Before running the sample client, make sure that your LDAP server is set up with the entry the sample attempts to find. Unless you change the source code in Example 51, the entry would be for the full name, last name, email address, and telephone number of Barbara Jensen.
 
==== Running Programs on UNIX Systems  ====
 
If you have linked the client on a UNIX platform, the client requires the SDK library file. Make sure to set your <tt>LD_LIBRARY_PATH</tt> to locate the <tt>libldap60.so</tt> library file and its dependencies.
 
As an alternative, when linking the file, specify the option that identifies the library directories that the runtime linker should search for. For example, on Solaris systems use the <tt>-R</tt> option to specify the location of the <tt>libldap60.so</tt> file.
 
==== Running Programs on Windows Systems  ====
 
If you have linked the client with the <tt>nsldap32v60.lib</tt> library on a Windows system, copy the Directory SDK for C DLL files to one of the following directories:
 
*The directory where the application was loaded
*The current directory
*The Windows system directory, such as <tt>winnt\system32\</tt>
*The Windows directory
*The directories listed in the PATH environment variable
 
== What's New In Directory SDK for C  ==
 
This section compares the current version of Directory SDK for C API with the previous version.
 
=== Deprecated and Changed Directory SDK for C Features  ===
 
This section covers the following changes and deprecated features in this release. Where possible, Directory SDK for C provides replacement features for deprecated features.
 
==== liblber API  ====
 
The Basic Encoding Rules library, liblber, changed for portability reasons and to comply with ''The C LDAP Application Program Interface'' Internet draft. In particular, according to section 17.1., ''BER Data Structures and Types'', the following structures have changed.
<pre>The following additional integral types are defined for use in manipula-
tion of BER encoded ASN.1 values:
 
typedef &lt;impl_tag_t&gt; ber_tag_t;    /* for BER tags */
typedef &lt;impl_int_t&gt; ber_int_t;    /* for BER ints, enums, and Booleans */
typedef &lt;impl_unit_t&gt; ber_uint_t;  /* unsigned equivalent of ber_uint_t */
typedef &lt;impl_slen_t&gt; ber_slen_t;  /* signed equivalent of ber_len_t */
 
Note that the actual definition for these four integral types is imple-
mentation specific; that is, `&lt;impl_tag_t&gt;', `&lt;impl_int_t&gt;',
`&lt;impl_uint_t&gt;', and `&lt;impl_slen_t&gt;' MUST each be replaced with an
appropriate implementation-specific type.</pre>
Programs that do not use the liblber API directly need not be changed. You can continue to build and use those applications as before.
 
If, however, your programs call the liblber API directly, you must change your application code to reflect the type definitions in <tt>include/lber.h</tt>. Compilers typically issue type mismatch warnings when compiling old code that has not been fixed.
 
==== File Layout  ====
 
The file layout has changed. All files are unpacked in a base directory that is named according to the platform and to the operating system of the binary distribution. The file layout is covered in the section on Files Provided With Directory SDK for C.
 
==== IPv6 Support  ====
 
IPv6 support is provided by means of the NSPR library. Therefore, to use LDAP over IPv6, use prldap_init instead of ldap_init.
 
==== NSS and NSPR Version Updates  ====
 
This version of Directory SDK for C uses NSS 3.11and NSPR 4.6. Both components are included in binary form for your convenience.
 
==== NSS Security Tools  ====
 
NSS security tools, used to maintain NSS databases so your application can do LDAP over SSL, are not delivered with Directory SDK for C.
 
For access to NSS security tools, refer to the [http://www.mozilla.org/projects/security/pki/nss/tools/ NSS security tools project].<br>
 
=== New Directory SDK for C Features<br>  ===
 
This section covers additional features provided in this release.<br>
 
==== LDAP Version 3 Default  ====
 
Directory SDK for C now uses LDAP v3 by default. You can therefore use LDAP v3 features in your applications even if you do not specifically set the version to 3.
 
==== Supported Controls  ====
 
This version of Directory SDK for C adds support for developing client applications, including more than 10 LDAP v3 controls.
 
For instructions on using controls supported by Directory SDK for C, see ''LDAP Controls With Directory SDK for C''.<br>
 
==== Supported Extended Operations  ====
 
This version of Directory SDK for C adds support for developing client applications that use the following extended operations.
 
===== LDAP Password Modify Extended Operation  =====
 
The LDAP Password Modify extended operation lets your client application modify a user password through LDAP. A user can modify his password even if the password is not stored as an attribute in the directory, the user is not identified by a DN, or the user does not have an entry in the directory. The LDAP Password Modify extended operation is defined in RFC 3062.
 
The extended operation has identifier <tt>1.3.6.1.4.1.4203.1.11.1</tt>.
 
===== Start TLS Extended Operation  =====
 
The Start TLS extended operation lets your client application connect to a nonsecure port, and then request transport layer security.
 
The extended operation has identifier <tt>1.3.6.1.4.1.1466.20037</tt>.
 
===== Who Am I? Extended Operation  =====
 
The “Who am I?” extended operation lets your client application determine the authorization identity that the server currently associates with your client.
 
The extended operation has identifier <tt>1.3.6.1.4.1.4203.1.11.3</tt>.
 
For instructions on using extended operations supported by Directory SDK For C, see ''Extended Operations With Directory SDK for C''.
 
==== Additional Directory SDK for C Examples  ====
 
More sample code is provided in the <tt>examples/</tt> directory. The additional samples demonstrate newly supported controls and extended operations.
 
== Writing an LDAP Client With Directory SDK for C  ==
 
With Directory SDK for C, you can write a new application. You can also enable an existing application to interact with a Lightweight Directory Access Protocol (LDAP) server. This chapter explains how to connect to an LDAP server, authenticate, request operations, and disconnect from the server.
 
=== Designing an LDAP Client With Directory SDK for C  ===
 
The following procedure outlines a typical process for communicating with an LDAP server.
 
'''To Communicate With an LDAP Server'''
 
#Initialize an LDAP session.<br>See Initializing an LDAP Session With Directory SDK for C for details.
#Bind to the LDAP server, if necessary.<br>See Binding and Authenticating to an LDAP Server With Directory SDK for C for details.
#Perform LDAP operations, such as searching the directory or modifying entries in the directory.<br>See Performing LDAP Operations With Directory SDK for C for details.
#Close the connection to the LDAP server when finished.<br>See Closing the Connection to an LDAP Server With Directory SDK for C for details.
 
This sample source code shows a client that requests an LDAP search operation from a server. The LDAP server runs on the local system on port 389. The client searches the directory for entries with the last name Jensen (<tt>sn=Jensen</tt>), and prints the distinguished name (DN) of any matching entry.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
/* Specify the search criteria here. */
#define HOSTNAME "localhost"
#define PORTNUMBER 389
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
 
int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMessage  *result, *e;
  char          *dn;
  int          version, rc;
  /* Print out an informational message. */
  printf( "Connecting to host&nbsp;%s at port&nbsp;%d...\n\n", HOSTNAME,
    PORTNUMBER );
 
  /* STEP 1: Get a handle to an LDAP connection and
    set any session preferences. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
 
  /* Use the LDAP_OPT_PROTOCOL_VERSION session preference to specify
    that the client is an LDAPv3 client. */
  version = LDAP_VERSION3;
  ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &amp;version );
 
  /* STEP 2: Bind to the server.
    In this example, the client binds anonymously to the server
    (no DN or credentials are specified). */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string(rc));
    return( 1 );
  }
 
  /* Print out an informational message. */
  printf( "Searching the directory for entries\n"
    " starting from the base DN&nbsp;%s\n"
    " within the scope&nbsp;%d\n"
    " matching the search filter&nbsp;%s...\n\n",
    BASEDN, SCOPE, FILTER );
 
  /* STEP 3: Perform the LDAP operations.
    In this example, a simple search operation is performed.
    The client iterates through each of the entries returned and
    prints out the DN of each entry. */
  rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0,
    NULL, NULL, NULL, 0, &amp;result );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string(rc));
    return( 1 );
  }
  for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
      e = ldap_next_entry( ld, e ) ) {
    if ( (dn = ldap_get_dn( ld, e ))&nbsp;!= NULL ) {
      printf( "dn:&nbsp;%s\n", dn );
      ldap_memfree( dn );
    }
  }
  ldap_msgfree( result );
 
  /* STEP 4: Disconnect from the server. */
  ldap_unbind( ld );
  return( 0 );
}
...</pre>
=== Initializing an LDAP Session With Directory SDK for C  ===
 
Before connecting to an LDAP server, you must initialize a session. As part of this process, you create an LDAP structure that contains information about the LDAP server and session. You then pass this LDAP structure, usually as a pointer, to all subsequent functions in order to identify the LDAP server with which you are working. Sample code for initializing an LDAP session is provided in Example Session Initialization.
 
'''Note:''' If you plan to connect to the LDAP server over the Secure Sockets Layer (SSL) protocol, the procedure for initializing an LDAP session is different. For details, see SSL Connections With Directory SDK for C.<br>
 
==== Specifying a Single LDAP Server  ====
 
To initialize an LDAP session, call ldap_init(), or prldap_init() for IPv6 support, with the host name and port number of the LDAP server. If the server is using the default port 389 for the LDAP server, pass LDAP_PORT as the value for the defport parameter as shown here.<br>
<pre>...
LDAP *ld
...
ld = ldap_init( "directory.example.com", LDAP_PORT );
</pre>
If successful, ldap_init(), or prldap_init(), returns a connection handle to the LDAP server. A connection handle is a pointer to the LDAP structure that contains information about the connection. You must pass this pointer to the API for connecting, authenticating, and performing LDAP operations on a server. For example, when you search the directory, you pass the connection handle as a parameter to provide a context for the connection.
 
'''Note:''' The initialization function does not open a connection to the LDAP server. The actual opening of a connection occurs when the first operation is attempted.
 
==== Specifying a List of LDAP Servers  ====
 
When initializing the LDAP session, you can also specify a list of LDAP servers for which you want to attempt connections. If the first LDAP server in the list does not respond, the client attempts to connect to the next server in the list. To specify a list of LDAP servers, pass a space-delimited list of the host names as the first argument to the ldap_init() or prldap_init() function. In the following example, the LDAP client attempts to connect to the LDAP server on ld1.example.com, port 389. If that server does not respond, the client attempts to connect to the LDAP server on ld2.example2.com, port 389. If that server does not respond, the client uses the server on ld3.example.com, port 389.<br>
<pre>...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example2.com
  ld3.example.com", LDAP_PORT );
</pre>
If any servers do not use the default LDAP port, use the host:port format to specify the server name and port number. In the following example, that means ld1.example.com, port 389. If that server does not respond, the client attempts to connect to the LDAP server on ld2.example.com, port 1389.<br>
<pre>...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com:1389",
  LDAP_PORT );
</pre>
==== Example Session Initialization  ====
 
The following example initializes a session with an LDAP server, specifying a list of LDAP servers to try: ldap.example.com:389 and directory.example.com:1389. The example also sets a session preference that identifies the client as an LDAP v3 client. This session initialization code uses the prldap_init function, which works on IPv6 networks. Notice that prldap_init does not connect to the LDAP server right away.
 
After you initialize a session with an LDAP server, you can set session preferences. For information, see Setting Session Preferences With Directory SDK for C.
<pre>#include &lt;stdio.h&gt;
#include "ldappr.h"
#include "ldap.h"
...
LDAP *ld;
int ldap_default_port, version;
 
/* Specify list of LDAP servers that you want to try connecting to. */
char *ldap_host = "ldap.example.com directory.example.com:1389";
 
/* If the LDAP server is running on the standard LDAP port (port 389),
* you can use LDAP_PORT to identify the port number. */
ldap_default_port = LDAP_PORT;
...
/* Initialize the session with the LDAP servers. */
if ( ( ld = prldap_init( ldap_host, ldap_default_port, NULL ) ) == NULL ) {
  perror( "prldap_init" );
  return( 1 );
}
 
/* Specify the LDAP version supported by the client. */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &amp;version );
 
...
/* Subsequent calls pass ld as argument to identify the LDAP server. */
 
...</pre>
==== Setting Session Preferences With Directory SDK for C  ====
 
With Directory SDK for C, you can set preferences for your client that you want applied to all LDAP sessions. To get or set the value of a preference, call the ldap_get_option() or ldap_set_option() functions respectively.
 
*The option parameter identifies the option that you want to get or set.
*The value parameter is either a pointer to a place to put the value to get, or a pointer to the value to set.
 
You can set a preference for all connections by passing NULL as the first argument, not an LDAP structure that specifies the connection.<br>
 
===== Reconnecting Automatically  =====
 
If communication with the LDAP server is interrupted, the server returns LDAP_SERVER_DOWN. If you want your client to continue to attempt communication with the server, you can set the LDAP_OPT_RECONNECT preference for the session. Once set, if your connection is lost, the client attempts another bind with the same authentication to reestablish the connection.
 
The following example shows that to set the reconnect preference, call the ldap_set_option() function and pass LDAP_OPT_RECONNECT as the value of the option parameter. To resume LDAP I/O operations automatically, set the optdata parameter to LDAP_OPT_ON. This setting specifies the same connection handle that can be used to reconnect to the server.<br>
<pre>ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON );
</pre>
To avoid resuming I/O operations, you would set the optdata parameter to LDAP_OPT_OFF. This setting specifies that you want to create a new connection handle to connect to the server. By default, the optdata parameter is set to LDAP_OPT_OFF. Both LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void *).<br>
 
==== Specifying the LDAP Version of Your Client  ====
 
If you plan to call functions that use LDAP v3 features such as controls or extended operations, set the protocol version to LDAP v3. By default, clients built with Directory SDK for C identify themselves to LDAP servers as LDAP v3 clients, but that was not the case with previous versions.
 
To specify the LDAP version supported by your client, call the ldap_set_option() function and set the LDAP_OPT_PROTOCOL_VERSION option to the value 3.<br>
<pre>...
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
...
</pre>
After setting this option, as part of the authentication process, your client sends the supported LDAP version number to the server. By setting the version, you allow the server to determine whether or not to enable LDAP v3 features.
 
LDAP v3 allows you to perform LDAP operations without first binding to the server. An LDAP v3 server assumes that the client is LDAP v3 compliant if the client issues non-bind operations before the client issues a bind.
 
==== Setting Connection Timeout  ====
 
Clients that use Directory SDK for C can control the TCP/IP level timeout. When the TCP/IP timeout option is not set, an attempt to connect to a server blocks until the connection completes or the system times out. By using the LDAP_X_OPT_CONNECT_TIMEOUT option, you can adjust how long to wait for a connection.
 
You specify the timeout as an int number of milliseconds, then call the ldap_set_option() function, passing the LDAP_X_OPT_CONNECT_TIMEOUT option.<br>
 
The following example sets the connection timeout to one second.
<pre>int timeout = 1000; /* 1000 milliseconds == 1 second */
ldap_set_option( ld, LDAP_X_OPT_CONNECT_TIMEOUT, timeout );
</pre>
*LDAP_X_IO_TIMEOUT_NO_WAIT<br>Return immediately if the server cannot be reached.
*LDAP_X_IO_TIMEOUT_NO_TIMEOUT<br>Wait indefinitely for the server to connect.
 
By passing NULL as the first parameter to the ldap_set_option() function, you can set the default timeout for all connections used by your application.<br>
 
=== Binding and Authenticating to an LDAP Server With Directory SDK for C  ===
 
When connecting to the LDAP server, your client might need to send a bind request.
 
*You want to authenticate to the server to add or modify entries in a directory that requires authentication as a user with certain access privileges.
*You are connecting to an LDAP v2 server. LDAP v2 servers typically require clients to bind before any operations can be performed.
*LDAP version of the client
*Method of authentication to use
*DN that the client is attempting to authenticate as
*Credentials to be used for authentication
 
LDAP clients can also bind anonymously to the LDAP server if, for example, the server is configured not to require authentication for a simple directory search.<br>
 
==== Using Simple Authentication With Directory SDK for C  ====
 
*ldap_simple_bind_s() is a synchronous function for use if you want to wait for the bind operation to complete before the function returns.<br>
*ldap_simple_bind() is an asynchronous function for use if you do not want to wait for the bind operation to complete. With this function, you can perform other work while periodically checking for the results of the bind operation.<br>
 
For more information about the differences between the types of functions, see Synchronous and Asynchronous Functions.<br>
 
===== Performing a Synchronous Authentication Operation  =====
 
If you want to wait for the bind operation to complete before continuing, call ldap_simple_bind_s(). This function returns LDAP_SUCCESS if the operation completed successfully, or an LDAP result code if a problem occurred. See ldap_simple_bind_s() in ldap_simple_bind_s() for a list of result codes returned.
 
If you specify a DN but no password, your client binds to the server anonymously. If you want a NULL password to be rejected as incorrect, you must write code to perform the check before you call ldap_simple_bind_s().
 
The following example uses the synchronous ldap_simple_bind_s() function to authenticate user Barbara Jensen to the LDAP server.
<pre>&lt;#include stdio.h&gt;
#include "ldap.h"
 
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define BIND_PW "hifalutin"
 
LDAP      *ld;
int      rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
}
 
/* Print out an informational message. */
printf( "Binding to server&nbsp;%s:%d\n", HOSTNAME, PORTNUMBER );
printf( "as the DN&nbsp;%s ...\n", BIND_DN );
 
/* Bind to the LDAP server. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf(stderr, "ldap_simple_bind_s:&nbsp;%s\n\n", ldap_err2string(rc));
  return( 1 );
} else {
  printf( "Bind operation successful.\n" );
}
 
...
/* If you want, you can perform LDAP operations here. */
...
 
/* Disconnect from the server when done. */
ldap_unbind( ld );
return( 0 );
...</pre>
===== Performing an Asynchronous Authentication Operation  =====
 
If you want to perform other work in parallel while waiting for the bind operation to complete, call ldap_simple_bind(). This function sends an LDAP bind request to the server and returns a message ID identifying the bind operation. To see if your client has received the results of the bind operation, call the ldap_result() function with the message ID. If your client has received the results, ldap_result() passes back the information in an LDAPMessage structure. To retrieve error information from LDAPMessage, you can pass the message ID to the ldap_parse_result() function. ldap_parse_result() gets the LDAP result code of the operation and any error messages sent back from the server. This function also retrieves any controls sent back.
 
If you specify a DN but no password, your client binds to the server anonymously. If you want a NULL password to be rejected as incorrect, you need to write code to perform the check before you call ldap_simple_bind().
 
The following example uses the asynchronous ldap_simple_bind function() to authenticate user Barbara Jensen to the LDAP server.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
void do_other_work();
int global_counter = 0;
...
 
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define BIND_PW "hifalutin"
 
...
LDAP            *ld;
LDAPMessage    *res;
int            msgid = 0, rc = 0, parse_rc = 0, finished = 0;
char            *matched_msg = NULL, *error_msg = NULL;
char            **referrals;
LDAPControl    **serverctrls;
struct timeval  zerotime;
 
/* Specify the timeout period for ldap_result(),
  which specifies how long the function should block when waiting
  for results from the server. */
zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
 
/* Print out an informational message. */
printf( "Binding to server&nbsp;%s:%d\n", HOSTNAME, PORTNUMBER );
printf( "as the DN&nbsp;%s ...\n", BIND_DN );
 
/* Send an LDAP bind request to the server. */
msgid = ldap_simple_bind( ld, BIND_DN, BIND_PW );
 
/* If the returned message ID is less than zero, an error occurred. */
if ( msgid  0  ) {
  rc = ldap_get_lderrno( ld, NULL, NULL );
  fprintf(stderr, "ldap_simple_bind&nbsp;:&nbsp;%s\n", ldap_err2string(rc));
  ldap_unbind( ld );
  return( 1 );
}
 
/* Check to see if the bind operation completed. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  /* If ldap_result() returns -1, error occurred. */
  case -1:
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return ( 1 );
 
    /* If ldap_result() returns 0, the timeout (specified by the
      timeout argument) has been exceeded before the client received
      the results from the server. Continue calling ldap_result()
      to poll for results from the server. */
  case 0:
    break;
 
  default:
    /* The client has received the result of the bind operation. */
    finished = 1;
 
    /* Parse this result to determine if the operation was successful.
      Note that a non-zero value is passed as the last parameter,
      which indicates that the LDAPMessage structure res should be
      freed when done.  (No need to call ldap_msgfree().) */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
    /* Check the results of the operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_simple_bind:&nbsp;%s\n",
        ldap_err2string( rc ) );
 
      /* If the server sent an additional error message,
        print it out. */
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
 
      /* If an entry specified by a DN could not be found,
        the server may also return the portion of the DN
        that identifies an existing entry. */
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
      ldap_unbind( ld );
      return( 1 );
    } else {
      printf( "Bind operation successful.\n" );
      printf( "Counted to&nbsp;%d while waiting for bind op.\n",
        global_counter );
    }
    break;
  }
  /* Do other work here while waiting for results from the server. */
  if (&nbsp;!finished ) {
    do_other_work();
  }
}
 
...
/* If you want, you can perform LDAP operations here. */
...
 
/* Disconnect from the server when done. */
ldap_unbind( ld );
return( 0 );
...
/* Function that does work while waiting for results from the server. */
void do_other_work() {
  global_counter++;
}
...</pre>
===== Binding Anonymously With Directory SDK for C  =====
 
In some cases, you do not need to authenticate to the LDAP server. For example, if users are performing a search that has no special access permissions, you need not authenticate before performing the search. To bind as an anonymous user, call ldap_simple_bind() or ldap_simple_bind_s(), and pass NULL values for the who and passwd parameters.
<pre>rc = ldap_simple_bind_s( ld, NULL, NULL );
</pre>
With LDAP v2, the client is required to send a bind request, even when binding anonymously. That is, bind without specifying a name or password. With LDAP v3, the client is no longer required to bind to the server if the client does not need to authenticate.
 
==== Performing LDAP Operations With Directory SDK for C  ====
 
After initializing a session with a server and completing the authentication process, you can perform LDAP operations. The LDAP operations include searching the directory, adding new entries, updating existing entries, and removing entries. The following lists LDAP operations and the functions that you can call to perform the operations.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Functions for Performing LDAP Operations"
|+ Functions for Performing LDAP Operations
|-
! scope="col" | To Perform This Operation<br>
! scope="col" | Call This API Function<br>
|-
| Search for entries<br>
| ldap_search_ext(), ldap_search_ext_s()<br>
|-
| Determine an attribute value<br>
| ldap_compare_ext(), ldap_compare_ext_s()<br>
|-
| Add entries<br>
| ldap_add_ext(), ldap_add_ext_s()<br>
|-
| Modify entries<br>
| ldap_modify_ext(), ldap_modify_ext_s()<br>
|-
| Delete entries<br>
| ldap_delete_ext(), ldap_delete_ext_s()<br>
|-
| Change DN of entries<br>
| ldap_rename_ext(), ldap_rename_ext_s()<br>
|}
 
Most LDAP operations can be performed synchronously or asynchronously. The functions with names that end in _s are synchronous. The remaining ones are asynchronous. For more information about the distinction between the functions, see Synchronous and Asynchronous Operations.
 
Closing the Connection to an LDAP Server With Directory SDK for C
 
When you have finished performing all necessary LDAP operations, you need to close the connection to the LDAP server. After you close the connection, you can no longer use the LDAP structure because the structure is freed from memory.
 
*ldap_unbind()
*ldap_unbind_s()
*ldap_unbind_ext()
 
Both ldap_unbind() and ldap_unbind_s() are identical synchronous functions. These functions use different names so that each function has a corresponding authentication function, ldap_simple_bind() and ldap_simple_bind_s(), to close the server connection.
 
The ldap_unbind_ext() function allows you to include explicitly both server and client controls in your unbind request. However, as the server does not respond to an unbind request, you cannot receive a response from a server control attached to your unbind request.
 
The following example closes the current connection with the LDAP server.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP      *ld;
int      rc;
...
/* After completing your LDAP operations with the server, close
  the connection. */
rc = ldap_unbind( ld );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_unbind:&nbsp;%s\n", ldap_err2string( rc ) );
}
...</pre>
== Using the LDAP C API  ==
 
This section covers features of the LDAP C API to use when writing an LDAP client application with Directory SDK for C.
 
=== Synchronous and Asynchronous Functions  ===
 
You can perform most operations with ''synchronous'' or with ''asynchronous'' functions. For example, to search the directory, you can call either the synchronous ldap_search_ext_s() function or the asynchronous ldap_search_ext() function. In general, all synchronous functions have names that end with _s.
 
The difference between the synchronous and asynchronous functions is the calling convention. The LDAP exchanges are identical.<br>
 
==== Calling Synchronous Functions  ====
 
When you call a synchronous function, your client waits for the operation to complete before executing any subsequent lines of code. Synchronous functions return LDAP_SUCCESS when they are successful. Synchronous functions return an LDAP error code when they are not successful. The following example deletes the entry in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;
...
/* Perform an LDAP delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
 
  /* If the server cannot find an entry with the specified DN,
    it may send back the portion of the DN that matches an
    existing entry.*/
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
} else {
  printf( "%s deleted successfully.\n", DELETE_DN );
}
...</pre>
To see other sample programs that call synchronous functions, view the source files in the <tt>examples/</tt> directory.<br>
 
==== Calling Asynchronous Functions  ====
 
When you call an asynchronous function, your client does not need to wait for the operation to complete. The client can continue performing other tasks, such as initiating other LDAP operations, while the asynchronous operation is executing. An asynchronous function passes back a unique message ID to identify the operation being performed. You can pass this message ID to the ldap_result() function to check the status of the operation. The following sections explain how to call an asynchronous function and how to check the results of the operation. To see other sample programs that call asynchronous functions, view the source files in the examples/ directory.
 
===== Verifying that an LDAP Request Was Sent  =====
 
Asynchronous functions return an LDAP result code indicating whether or not the LDAP request was successfully sent to the server. If the function returns LDAP_SUCCESS, the function has successfully sent the request to the server. The following example sends an LDAP delete request to the server and checks if the result was sent successfully. The example uses the asynchronous ldap_delete_ext() function.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
/* Change these as needed. */
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
...
LDAP      *ld;
int        rc, msgid;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  /* If the request was not sent successfully,
    print an error message and return. */
  fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...</pre>
===== Retrieving the Server Response  =====
 
If the request was sent successfully, the function passes the message ID of the LDAP operation back to the client. Use the message ID to determine if the server has sent back results for this operation. Call ldap_result(), passing the message ID as a parameter.<br>
 
*-1 indicates that an error occurred.
*0 indicates that the timeout period has been exceeded and that the server has not yet sent a response back to your client.
*Any other value indicates that the server has sent a response for the requested operation back to your client. The ldap_result() parameter passes back a pointer to an LDAPMessage structure.
**An LDAP result code that specifies the result of the operation you requested
**An additional error message sent back from the server<br>This information is optional.
**If the server cannot find the entry specified by a DN, the portion that identifies an existing entry.
**A set of referrals, if the servers directory does not contain the requested entries<br>The server must be configured to return referrals.
**A set of server response controls that apply to the operation you requested<br>
 
You can specify a timeout period to wait for results from the server.<br>
 
====== Polling Loop  ======
 
You can set up a loop to poll for results while doing other work. The following example defines a function that does other work while waiting for the server to send a response back to your client.<br>
<pre>int global_counter = 0;
void do_other_work()
{
  global_counter++;
}
</pre>
====== while Loop  ======
 
This example sets up a while() loop to call your function when you are not checking for the servers response.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage      *res;
LDAPControl      **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int              rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;
 
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
...
/* Poll the server for the results of the LDAP operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
 
  /* Check to see if a result was received. */
  switch ( rc ) {
  case -1:
    .../* An error occurred. */...
  case 0:
    /* The timeout period specified by zerotime was exceeded, meaning
      the server has still not yet sent the results of the delete
      operation back to the client. Break out of this switch statement,
      and continue calling ldap_result() to poll for results. */
  default:
    finished = 1;
    .../* Your client received a response from the server. */...
  }
 
  /* Do other work while waiting. This is called if ldap_result()
    returns 0 (before you continue to top of the loop and call
    ldap_result() again). */
  if (&nbsp;!finished ) {
    do_other_work();
  }
  ...
}
...</pre>
===== Getting Information From a Server Response  =====
 
To get information from the server response, call ldap_parse_result() as shown here.
<pre>LDAP_API(int) LDAP_CALL
ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep,
  char **matcheddnp, char **errmsgp, char ***referralsp,
  LDAPControl ***serverctrlsp, int freeit );</pre>
*errcodep holds the LDAP result code of the operation that the server finished processing.<br>
*errmsgp is an additional error message that the server can send to your client.
*matcheddnp is the portion of the DN that matches an existing entry. The portion of the DN is used when the server is not able to find an entry for the DN that you specified.<br>
*referralsp is a set of referrals sent back to your client. The set of referrals is sent if you requested an entry that is not part of the DIT managed by the server. The server must be configured to refer clients to other LDAP servers.<br>
*serverctrlsp is a set of server response controls that apply to the operation.<br>
 
When processing LDAP search operations, the server can send back individual entries, individual search references, chains of entries, and chains of search references.
 
The following example retrieves error information from an LDAPMessage structure returned by ldap_result().
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage      *res;
LDAPControl      **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int              rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;
 
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
rc = ldap_result( ld, msgid, 0, zerotime, res );
 
/* Check to see if a result was received. */
switch ( rc ) {
case -1:
  ...
case 0:
  ...
default:
  ...
  /* Call ldap_parse_result() to get information from the results
    received from the server. */
  parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
    error_msg, referrals, serverctrls, 1 );
 
  /* Make sure the results were parsed successfully. */
  if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
      ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
 
  /* Check the results of the LDAP operation. */
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf(stderr, "Error:&nbsp;%s\n", ldap_err2string(rc));
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    /* If the server returned the portion of the DN
      that identifies an existing entry, print it out. */
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
  } else {
    printf( "Operation completed successfully" );
  }
}
...</pre>
====== Freeing an LDAPMessage Structure  ======
 
When you are done, call ldap_msgfree() to free the LDAPMessage structure unless the structure is part of a chain of results. The result code returned by this function is not the same as the result code of the operation, errcodep. This operation returns a result code that indicates the type of operation to which the freed LDAPMessage structure is a response.
 
If you pass a non-zero value for the freeit parameter of ldap_result(), the structure is automatically freed after the information is retrieved.
 
===== Canceling an Operation in Progress  =====
 
If you need to cancel an LDAP operation, call ldap_abandon_ext(). The function returns LDAP_SUCCESS if successful, or an LDAP result code if an error occurs. After you cancel an operation, you cannot retrieve the results of that operation. Thus, calling ldap_result() does not return any results.
 
===== Sample Code to Call an Asynchronous Function  =====
 
The following example calls ldap_delete_ext() to delete an entry in the directory, and ldap_result() within a loop to poll the results of the delete.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
void do_other_work();
int global_counter = 0;
...
/* Change these as needed. */
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
...
LDAP              *ld;
LDAPMessage      *res;
LDAPControl      **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int              rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;
 
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Poll the server for the results of the delete operation. */
while (&nbsp;!finished ) {
  /* Call ldap_result() to get the results of the delete operation.
    ldap_result() blocks for the time specified by the timeout argument
    (set to zerotime here) while waiting for the result from the server. */
  rc = ldap_result( ld, msgid, 0, zerotime, res );
 
  /* Check to see if a result was received. */
  switch ( rc ) {
  case -1:
    /* If ldap_result() returned -1, an error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
 
  case 0:
    /* The timeout period specified by zerotime was exceeded, meaning
      the server has still not yet sent the results of the delete
      operation back to the client. Break out of this switch statement,
      and continue calling ldap_result() to poll for results. */
    break;
 
  default:
    /* ldap_result() got the results of the delete operation
      from the server. No need to keep polling. */
    finished = 1;
 
    /* Call ldap_parse_result() to get information from the results
      received from the server. Note the last argument is a non-zero
      value. This means after the function retrieves information from
      the LDAPMessage structure, the structure is freed.
      (You do not need to call ldap_msgfree() to free the structure.)*/
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the LDAP delete operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf(stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string(rc));
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      /* Print the portion of a specified DN that matches an
        existing entry, if returned by the server. */
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
    } else {
      printf( "%s deleted successfully.\n"
        "Counted to&nbsp;%d while waiting for the delete operation.\n",
        DELETE_DN, global_counter );
    }
  }
 
  /* Do other work while waiting for the results of the
    delete operation. */
  if (&nbsp;!finished ) {
    do_other_work();
  }
}
ldap_unbind( ld );
return 0;
...
 
/* Perform other work while polling for results. */
void
do_other_work()
{
  global_counter++;
}
...</pre>
=== Retrieving SDK Information  ===
 
You can get information about the particular version of Directory SDK for C that you are using by calling the ldap_get_option() function:
<pre>ldap_get_option(..., LDAP_OPT_API_INFO, ...);</pre>
The retrieved information can include the version of the SDK or the highest version of the LDAP that the SDK supports. This example shows how to use this function to retrieve version information.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
main()
{
 
LDAPAPIInfo        ldapi;
LDAPAPIFeatureInfo  fi;
int                i;
int                rc;
LDAP                *ld;
 
memset( ldapi, 0, sizeof(ldapi));
ldapi.ldapai_info_version = LDAP_API_INFO_VERSION;
 
if ((rc = ldap_get_option( ld, LDAP_OPT_API_INFO, ldapi))&nbsp;!= 0) {
        printf("Error: ldap_get_option (rc:&nbsp;%d)\n", rc);
        exit(0);
}
 
printf("LDAP Library Information -\n"
        "    Highest supported protocol version:&nbsp;%d\n"
        "    LDAP API revision:                &nbsp;%d\n"
        "    API vendor name:                  &nbsp;%s\n"
        "    Vendor-specific version:          &nbsp;%.2f\n",
        ldapi.ldapai_protocol_version, ldapi.ldapai_api_version,
        ldapi.ldapai_vendor_name,
        (float)ldapi.ldapai_vendor_version / 100.0 );
 
if ( ldapi.ldapai_extensions&nbsp;!= NULL ) {
        printf("    LDAP API Extensions:\n");
 
        for ( i = 0; ldapi.ldapai_extensions[i]&nbsp;!= NULL; i++ )  {
            printf("      &nbsp;%s", ldapi.ldapai_extensions[i] );
            fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
            fi.ldapaif_name = ldapi.ldapai_extensions[i];
            fi.ldapaif_version = 0;
 
            if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, fi )
                  &nbsp;!= 0 ) {
                printf("Error: ldap_get_option( NULL,"
                      " LDAP_OPT_API_FEATURE_INFO, ... ) for&nbsp;%s failed"
                      " (Feature Info version:&nbsp;%d)\n",
                      fi.ldapaif_name, fi.ldapaif_info_version );
            } else {
                printf(" (revision&nbsp;%d)\n", fi.ldapaif_version);
            }
        }
    }
  printf("\n");
}</pre>
=== Managing Memory  ===
 
Several of the SDK functions allocate memory when called. When you have finished working with data allocated by these functions, you should free the memory. The following shows some of the functions that allocate memory and the corresponding functions you use to free the memory when done.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Functions to Allocate and Free Memory"
|+ Functions to Allocate and Free Memory
|-
! scope="col" | Function to Free Memory<br>
! scope="col" | Type of Memory Freed<br>
|-
| ldap_unbind(), ldap_unbind_s()<br>
| Frees LDAP structures allocated by ldap_init() or prldap_init().<br>
|-
| ldap_msgfree()<br>
| Frees LDAPMessage structures allocated by ldap_result() or ldap_search_ext_s().<br>
|-
| ldap_ber_free()<br>
| Frees BerElement structures allocated by ldap_first_attribute().<br>
|-
| ldap_value_free()<br>
| Frees char ** arrays and structures allocated by ldap_get_values().<br>
|-
| ldap_value_free_len()<br>
| Frees arrays of berval structures allocated by ldap_get_values_len().<br>
|-
| ber_bvfree()<br>
| Frees berval structures allocated by ldap_extended_operation_s(), ldap_parse_extended_result(), ldap_parse_sasl_bind_result(), and ldap_sasl_bind_s().<br>
|-
| ldap_free_friendlymap()<br>
| Frees FriendlyMap structures allocated by ldap_friendly_name().<br>
|-
| ldap_free_urldesc()<br>
| Frees LDAPURLDesc structures allocated by ldap_url_parse().<br>
|-
| ldap_getfilter_free()<br>
| Frees LDAPFiltDesc structures allocated by ldap_init_getfilter() or ldap_init_getfilter_buf().<br>
|-
| ldap_mods_free()<br>
| Frees LDAPMod** arrays and structures allocated by functions that you call when you add or modify entries.<br>
|-
| ldap_free_sort_keylist()<br>
| Frees LDAPsortkey** arrays that you allocate by calling ldap_create_sort_keylist().<br>
|-
| ldap_control_free()<br>
| Frees LDAPControl structures that you allocate by calling ldap_create_sort_control() or ldap_create_persistentsearch_control().<br>
|-
| ldap_controls_free()<br>
| Frees LDAPControl** arrays and structures that you allocate by calling ldap_get_entry_controls(), ldap_parse_result(), or ldap_parse_reference().<br>
|-
| ldap_memfree()<br>
| Frees any other types of memory that you allocate. This function is a general function for freeing memory.<br>
|}
 
=== Reporting Errors  ===
 
In LDAP, the success or failure of an operation is specified by a result code sent back to the client. A result code of zero (0) normally indicates that the operation was successful, whereas a nonzero result code usually indicates that an error occurred.
 
==== Setting Error Codes  ====
 
When an LDAP operation is performed, the error information from the operation is specified in the LDAP structure. If you want to set error codes and error information in the LDAP structure, call the ldap_set_lderrno() function. This example sets the LDAP_PARAM_ERROR error code in an LDAP structure.<br>
<pre>#include "ldap.h"
...
LDAP *ld;
char *errmsg = "Invalid parameter";
...
if ( ldap_my_function()&nbsp;!= LDAP_SUCCESS ) {
&nbsp;&nbsp;  ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
&nbsp;&nbsp;  return( 1 );
}
...
</pre>
==== Getting Information About an Error  ====
 
When an error occurs in an LDAP operation, the server sends an LDAP result code for the error back to the client. The server also sends a message with any additional information about the error.
 
*If you are calling asynchronous functions, you can get the information from the LDAPMessage structure that represents the result the server returns.<br>
*Sometimes, you do not have an LDAPMessage structure. For example, you might be calling functions that do not interact with the server. When you do not have a message ID, get error information from the LDAP connection handle.<br>
 
===== Getting Information From an LDAPMessage Structure  =====
 
If you have requested the operation through an asynchronous function, get the result by calling the ldap_result() function. This function passes the result as an LDAPMessage structure. You can get information from this structure by calling the ldap_parse_result() function whose prototype is shown here.<br>
<pre>LDAP_API(int) LDAP_CALL ldap_parse_result( LDAP *ld,
  LDAPMessage *res, int *errcodep, char **matcheddnp,
  char **errmsgp, char ***referralsp,
  LDAPControl ***serverctrlsp, int freeit );
</pre>
*The LDAP result code is the errcodep argument.
*Additional information from the server is passed back as the errmsgp argument.
*When the server cannot find an entry from a DN, the portion of the DN that identifies an entry is passed as the matcheddnp argument.<br>
 
You can also get the error message that describes the LDAP result code by using the ldap_err2string() function.
 
The following example gets and prints information about an error returned from the server.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage      *res;
int              msgid = 0, rc = 0, parse_rc = 0, finished = 0;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
LDAPControl      **serverctrls;
struct timeval    zerotime;
...
while (&nbsp;!finished ) {
  /* Check to see if the server returned a result. */
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  ...
  default:
    /* The client has received the result of the LDAP operation. */
    finished = 1;
 
    /* Parse this result to determine if the operation was successful. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
 
    /* Verify that the result was parsed correctly. */
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result error:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
 
      /* Print the error message corresponding to the result code. */
      fprintf( stderr, "Error:&nbsp;%s\n",
        ldap_err2string( rc ) );
 
      /* If the server sent an additional message, print it out. */
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
 
      /* If the server cannot find an entry with the specified DN,
        it may send back the portion of the DN that matches
        an existing entry. */
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
 
      /* Disconnect and return. */
      ldap_unbind( ld );
      return( 1 );
    }
...</pre>
===== Getting Information From an LDAP Structure  =====
 
Sometimes, you do not get an LDAPMessage structure. For example, when you call functions that do not interact with the server, get error information from the connection handle. You can get information about the last error that has occurred by calling the ldap_get_lerrno() function whose prototype is shown here.
<pre>LDAP_API(int) LDAP_CALL ldap_get_lderrno(LDAP *ld,
  char **m, char **s);</pre>
*The LDAP result code is returned by this function.
*Additional information from the server is passed back as the s argument.
*When the server cannot find an entry from a DN, the portion of the DN that identifies an entry is passed as the m argument.
 
If you do not need to use the parameters returned by the ldap_get_lerrno function, set the parameters to NULL:
<pre>ldap_get_lderrno( ld, NULL, NULL );</pre>
The following example gets and prints information about an error from an LDAP structure.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP    *ld;
char*    *error_msg = NULL, *matched_msg = NULL;
int      rc;
...
rc = ldap_get_lderrno( ld, matched_msg, error_msg );
fprintf( stderr, "ldap_result error:&nbsp;%s\n", ldap_err2string( rc ) );
if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
  fprintf( stderr, "%s\n", error_msg );
}
 
/* If the server cannot find an entry with the specified DN,
  it may send back the portion of the DN that matches
  an existing entry. */
if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
  fprintf( stderr,
    "Part of the DN that matches an existing entry:&nbsp;%s\n",
    matched_msg );
}
...</pre>
===== Getting the Error Message From an Error Code  =====
 
If you have an error code, you can retrieve its corresponding error message using the ldap_err2string function. The function returns a pointer to the error message. The pointer returned by this function is a pointer to static data. Do not free this string.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
int      rc;
...
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "Error:&nbsp;%s\n", ldap_err2string( rc ) );
}
...</pre>
==== Receiving the Matching Portion of a DN  ====
 
If the server cannot find an entry specified by a DN, the server can return the portion of the DN that identifies an existing entry. According to LDAP v3, if a server returns an LDAP_NO_SUCH_OBJECT, LDAP_ALIAS_PROBLEM, LDAP_INVALID_DN_SYNTAX, or LDAP_ALIAS_DEREF_PROBLEM result code, the LDAP server should also send back the portion of the DN that matches an entry that is closest to the requested entry.
 
For example, suppose that the LDAP server processes a request to modify the entry with the DN <tt>uid=bjensen,ou=Contractors,dc=example,dc=com</tt> but that entry does not exist in the directory. If <tt>ou=Contractors,dc=example,dc=com</tt> does exist, the server sends this portion of the DN with the result code LDAP_NO_SUCH_OBJECT. If <tt>ou=Contractors,dc=example,dc=com</tt> does not exist, but <tt>dc=example,dc=com</tt> does, the server sends <tt>dc=example,dc=com</tt> back to the client. The server also returns the result code LDAP_NO_SUCH_OBJECT. Basically, the server removes one DN component at a time, until the server can find a DN that identifies an existing entry.
 
==== Printing Error Messages  ====
 
To print the error message that describes the last error that occurred, call the ldap_get_lerrno() function. The following prints a message if a function fails to delete an entry in the server.
<pre>#include "ldap.h"
...
int lderr;
char * errmsg;
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
...
if ( ldap_delete_s( ld, dn )&nbsp;!= LDAP_SUCCESS ) {
  lderr = ldap_get_lderrno (ld, NULL, errmsg);
  if ( errmsg,&nbsp;!= NULL ) {
    fprintf(stderr, "ldap_delete_s:&nbsp;%s\n", errmsg );
    ldap_memfree( errmsg );
  }
  return( 1 );
}
...</pre>
The client also prints the following message if the client does not have access permissions to delete the entry:
<pre>ldap_delete_s: Insufficient access</pre>
=== Handling Referrals With Directory SDK for C  ===
 
When a server receives a request for a DN, that DN might not be in its directory tree. The server can refer clients to another server that might contain the DN. The reference that the client receives is called a ''referral''.
 
Consider an LDAP server that has a directory that starts under <tt>dc=example,dc=com</tt>.
 
*If the server is not configured to send a referral, the server sends back an LDAP_NO_SUCH_OBJECT result code.
*If the server is configured to refer you to another LDAP server, the server sends a referral back to your client. The referral consists of the result code, LDAP_PARTIAL_RESULTS for LDAP v2 clients, or LDAP_REFERRAL for LDAP v3 clients, and one or more LDAP URLs. For LDAP v2 clients, the URLs are included in the error message that the server sends to the client. For LDAP v3 clients, the URLs are included in a separate section of the result.
*If your client handles referrals automatically, the client connects to the LDAP server specified in the referral. The client then requests the operation from that server. The client binds anonymously to that server.
*If your client does not handle referrals automatically, your client returns the result code sent from the server, LDAP_PARTIAL_RESULTS or LDAP_REFERRAL. You can get the LDAP URLs from the result by calling the ldap_parse_result() function.
 
By default, clients built with Directory SDK for C follow referrals automatically.<br>
 
==== Searching References and Referrals  ====
 
A concept that is similar to a referral is a ''search reference''. A search reference is an entry with the object class referral. The ref attribute of this object class contains an LDAP URL that identifies another LDAP server. When your client searches a subtree of a directory that contains search references, the server returns a mix of matching entries and search references.
 
*If your client handles referrals automatically, Directory SDK for C retrieves each search reference, binds to the server identified in the reference, and then retrieves the entry.
*If your client does not handle referrals automatically, Directory SDK for C adds the search reference to the chain of search results. The search reference is a message of the type LDAP_RES_SEARCH_REFERENCE. You can get the search references from a chain of results by calling the ldap_first_reference() and ldap_next_reference() functions. You can also call the ldap_first_message() and ldap_next_message() functions to get each message in the search results, and then call the ldap_msgtype() function to determine if the message is of the type LDAP_RES_SEARCH_REFERENCE.
 
See the ldap_ssl.h header file for information about specifying a DN and password for binding to a server for a referral.<br>
 
==== Enabling or Disabling Referral Handling With Directory SDK for C  ====
 
By default, clients built with Directory SDK for C automatically follow referrals to other servers. To change the way referrals are handled, call the ldap_set_option() function and pass LDAP_OPT_REFERRALS as the value of the option parameter.
 
*To prevent the client from automatically following referrals, set the optdata parameter to LDAP_OPT_OFF.
*If you want the client to automatically follow referrals again, set the optdata parameter to LDAP_OPT_ON.
 
Both LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void *). You can pass these parameters directly to the function as shown in the following example. The parameter prevents the client from automatically following referrals to other LDAP servers.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP    *ld;
int    rc;
char    *host = "localhost";
...
/* Initialize a session with the LDAP server ldap.example.com:389. */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
 
/* Never follow referrals. */
if ( ldap_set_option( ld,
                      LDAP_OPT_REFERRALS,
                      LDAP_OPT_OFF)&nbsp;!=
    LDAP_SUCCESS ) {
  rc = ldap_get_lderrno( ld, NULL, NULL );
  fprintf( stderr, "ldap_set_option:&nbsp;%s\n",
    ldap_err2string( rc );
  return( 1 );
}
...</pre>
==== Limiting Referral Hops With Directory SDK for C  ====
 
You can specify the maximum number of referral hops that should be followed in a sequence of referrals. The maximum setting is called the referral hop limit. You can specify the limit as a preference for the connection. You can also specify the limit as a search constraint for a specific search operation. For example, LDAP server 1 refers your client to server 2, server 2 to server 3, and then server 3 to server 4. Your client is being referred three times. With a limit of two referral hops, your client would not follow the referral to server 4, as the third referral exceeds the limit. If the referral hop limit is exceeded, the client returns the result code LDAP_REFERRAL_LIMIT_EXCEEDED.
 
To set the referral hop limit, pass LDAP_OPT_REFERRAL_HOP_LIMIT as the value of the option parameter. Also, pass the maximum number of hops as the value of the optdata parameter. By default, the maximum number of hops is 5.
 
==== Binding for Referrals  ====
 
If the session setup specifies that the client always follows referrals, the LDAP server that the client connects to can refer the client to another server. By default, the client binds anonymously when following referrals. No user name or password is specified. The following sections explain how to set up your client to authenticate with a DN and with corresponding credentials.
 
===== How Referral Binding Works  =====
 
To authenticate to the referred LDAP server, define a rebind function of the type LDAP_REBINDPROC_CALLBACK. The rebind function gets the DN and password to be used for authentication. Then, you specify that your function should be used if binding to other servers when following referrals.
 
#The LDAP server sends a referral back to the client.<br>The referral contains an LDAP URL that identifies another LDAP server.
#The client calls the rebind() function, specified by the LDAP_OPT_REBIND_FN option, passing 0 as the freeit argument.
#The rebind() function sets the dnp, passwdp, and authmethodp arguments.
#*The dnp argument points to the DN used to authenticate to the new LDAP server.
#*The passwdp argument points to the credentials for this DN.
#*The authmethodp argument points to the method of authentication that is used, such as LDAP_AUTH_SIMPLE.
#If successful, the rebind() function returns LDAP_SUCCESS, and referral processing continues.<br>If any other value is returned, referral processing stops, and that value is returned as the result code for the original LDAP request.
#The client gets the DN, the credentials, and the authentication method from the arguments of the rebind() function. The client uses this information to authenticate to the new LDAP server.
#The client calls the rebind() function again, passing 1 as the freeit argument.
#The rebind() function frees any memory that was allocated earlier to specify the DN and credentials.
 
===== Defining the Rebind Function  =====
 
*If freeit is 0, do the following:
**Set dnp to point to the DN to be used for authentication.
**Set passwdp to point to the credentials to be used for authentication.
**Set authmethodp to point to the method of authentication to be used, such as LDAP_AUTH_SIMPLE.
**Alternatively, you can also make use of the arg argument, a pointer to the argument specified in the ldap_set_rebind_proc() function. If successful, the function returns LDAP_SUCCESS. Otherwise, the function returns the appropriate LDAP error code.
*If freeit is 1, free any memory that you allocated to create the DN and credentials.
 
The following code defines the rebind() function. The list defines the parameters of the rebind() function. LDAP_CALL and LDAP_CALLBACK set up calling conventions. The structures are defined in the lber.h header file.
<pre>int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp,
  char **passwdp, int *authmethodp, int freeit, void *arg );</pre>
*ld: Pointer to the connection handle to the LDAP server.
*dnp: Pointer to the DN of the user or entity who wants to perform the LDAP operations. Your function needs to set this value.
*passwdp: Pointer to the user password. Your function needs to set this value.
*authmethodp: Pointer to the method of authentication. Your function needs to set this value.
*freeit: Specifies whether or not to free the memory allocated by the previous rebindproc() function call in the event that this function is called more than once. If freeit is set to a nonzero value, your function should free the memory allocated by the previous call.
*arg: Pointer to data that can be passed to your function.
 
===== Registering the Rebind Function  =====
 
*Call ldap_set_rebind_proc(), specifying your function and any data that you want passed as an argument.
*Call ldap_set_option() to set the LDAP_OPT_REBIND_FN option to your function. Use the LDAP_OPT_REBIND_ARG option to specify any arguments to pass to your rebind() function.
 
=== Creating an In-Memory Cache  ===
 
Directory SDK for C includes functions that allow you to create an in-memory cache of search results for your client. Then, when sending a search request and receiving results, the results would be cached. The next time your client issues the same search request, the results are read from the cache. To set up a cache for your connection, complete the following procedure.
 
'''To Set Up an In-Memory Cache'''
 
#Call the ldap_memcache_init() function to create a new LDAPMemCache structure.<br>The structure is the cache. Pass the pointer to this structure for subsequent operations.
#Call the ldap_memcache_set function() to associate the cache with an LDAP structure, which is a connection handle.<br>When a search request is cached, the search criteria are used as the key to the item in the cache. If you run the same search again, the results are read from the cache. If you alter the criteria, your client gets the results from the server rather than the cache. For example, you can specify to return all attributes instead of just the uid attribute.<br>The cache periodically checks for expired items. The cache mechanism removes expired items from the cache.
#When you write a multithreaded application, set up a separate thread to keep the cache up to date.<br>To keep the cache updated, call the ldap_memcache_update() function.
#If you want to remove items from the cache or flush the cache, call the ldap_memcache_flush() function.
#When you are done working with the cache, call the ldap_memcache_destroy() function.
<pre>#include "ldap.h"
...
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
...
LDAP          *ld;
LDAPMemCache  *dircache;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
...
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
...
/* Create an in-memory cache. */
rc = ldap_memcache_init( 0, 0, NULL, NULL, dircache );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_memcache_init:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Associate the cache with the connection. */
rc = ldap_memcache_set( ld, dircache );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_memcache_set:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...</pre>
=== Handling Failover  ===
 
While performing an LDAP operation, if the LDAP client loses the connection with the server, the SDK returns an LDAP_SERVER_DOWN or LDAP_CONNECT_ERROR result code.
 
*Free the current connection handle. Then create a new connection handle.<br>
*Use the reconnect option, LDAP_OPT_RECONNECT, to connect to the server again with the same connection handle.<br>You can use this option if you do not want to free the connection handle, for example, if multiple threads are sharing the same connection handle.<br>
 
==== Creating a New Connection Handle  ====
 
Call the ldap_unbind() or ldap_unbind_s() function to free the existing connection handle, which is an LDAP structure. Then call ldap_init() or prldap_init() to initialize a new connection as shown in the following example.
 
The disadvantage of this approach is the need to free the connection handle, which can make sharing connection handles between threads difficult.
<pre>#include "ldap.h"
...
LDAP *ld;
int tries = 0, rc = 0;
...
do {
  /* Call a function that performs an LDAP operation
  (my_ldap_request_function() can be any of these functions,
  such as ldap_search_ext_s()) */
  rc = my_ldap_request_function( ld );
 
  /* Check to see if the connection was lost. */
  if ( rc&nbsp;!= LDAP_SERVER_DOWN  rc&nbsp;!= LDAP_CONNECT_ERROR ) {
    return( rc ); /* Return result code. */
  }
 
  /* If the connection was lost, free the handle. */
  ldap_unbind( ld );
 
  /* Create a new connection handle and attempt to bind again. */
  /* Use prldap_init() for IPv6 support. */
  if (( ld = ldap_init( hostlist, port ))&nbsp;!= NULL ) {
    ldap_simple_bind_s();
 
    /* Perform any other initialization
    work on the connection handle. */
  }
} while ( ld&nbsp;!= NULL  ++tries  2 );
...</pre>
==== Using the Reconnect Option  ====
 
To reconnect to the server without freeing the connection handle, for example, if multiple threads need to share the same connection handle, call the ldap_set_option() function to set the LDAP_OPT_RECONNECT option to LDAP_OPT_ON. Call this function immediately after calling ldap_init() or prldap_init() as shown in the following example:
<pre>#include "ldap.h"
...
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
...
LDAP *ld;
...
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
 
/* Set the reconnect option. */
if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) == 0 ) {
  /* success */
  } else {
  /* failure */
}
...</pre>
If after setting this option, the connection to the server has been lost, the SDK returns an LDAP_CONNECT_ERROR or LDAP_SERVER_DOWN result code to your client. When you receive this result code, call the ldap_simple_bind_s() function. This function reestablishes a connection to one of the hosts specified in the ldap_init() or prldap_init() function call. If your client is able to reconnect with the server, ldap_simple_bind_s() issues a bind request to the server and returns the result. The following example attempts to reconnect to the server if the client is disconnected.
<pre>#include "ldap.h"
...
LDAP *ld;
int tries = 0, rc = 0;
...
do {
  /* Call a function that performs an LDAP operation
  (my_ldap_request_function() can be any of these functions,
  such as ldap_search_ext_s()) */
  rc = my_ldap_request_function( ld );
 
  /* Check to see if the connection was lost. */
  if ( rc&nbsp;!= LDAP_SERVER_DOWN  rc&nbsp;!= LDAP_CONNECT_ERROR ) {
    return( rc ); /* Return the result code. */
  }
 
  /* If the connection was lost, call
  ldap_simple_bind_s() to reconnect. */
  if ( ldap_simple_bind_s( ld, dn, passwd )&nbsp;!= LDAP_SUCCESS ) {
    /* failure -- could not reconnect */
    /* remember that ld as bad */
    return( rc );
  }
} while ( ++tries  2 );</pre>
== Searching the Directory With Directory SDK for C  ==
 
This chapter explains how to use the LDAP C API to search the directory and to retrieve entries.<br>
 
Directory SDK for C provides functions that allow you to search a directory and to retrieve results from the server. For example, you can send a search request by calling the synchronous ldap_search_ext_s() function or the asynchronous ldap_search_ext() function and the server sends back matching results.
 
*Directory entries found by the search<br>
*Search references found within the scope of the search<br>A ''search reference'' is a reference to another LDAP server.
*An LDAP result code that specifies the result of the search operation<br>'''Note:''' To receive search references from LDAP v3 servers, you must identify your client as LDAP v3 enabled. If you do not, the server returns the LDAP error code LDAP_PARTIAL_RESULTS, and a set of referrals. See Specifying the LDAP Version of Your Client for details.
*If you are retrieving the results sequentially, call ldap_result(). This function returns each result, an LDAPMessage structure, and determines the type of result. A result can be either an entry or a search reference.
*If you are retrieving a chain of results, you can call ldap_first_message() and ldap_next_message() to iterate through the results in the chain.
*If you are just interested in entries, you can call ldap_first_entry() and ldap_next_entry().
*If you are just interested in search references, you can call ldap_first_reference() and ldap_next_reference().
*To get an entry from a result, an LDAPMessage structure, call ldap_parse_entry().
*To get a search reference from a result, an LDAPMessage structure, call ldap_parse_reference().
*To get the LDAP result code for the search operation from a result, an LDAPMessage structure, call ldap_parse_result().
 
'''Tip:''' To access data from entries found by the search, you need to follow this general process in your code.
 
#Get each entry in the results.
#Get the attributes from each entry.
#Get the values from each attribute.<br>
 
=== Sending a Search Request With Directory SDK for C<br>  ===
 
To search the directory, call ldap_search_ext_s() or ldap_search_ext. ldap_search_ext_s() is a synchronous function that blocks other work until all results have been received from the server. The function is declared as shown here.<br>
<pre>LDAP_API(int) LDAP_CALL ldap_search_ext_s( LDAP *ld, const char *base,
  int scope, const char *filter, char **attrs, int attrsonly,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct timeval *timeoutp, int sizelimit, LDAPMessage **res );
</pre>
ldap_search_ext() is an asynchronous function that sends an LDAP search request to the server. You can do other work while checking to see if the server has returned any results. The function is declared as shown here.<br>
<pre>LDAP_API(int) LDAP_CALL ldap_search_ext( LDAP *ld, const char *base,
  int scope, const char *filter, char **attrs, int attrsonly,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct timeval *timeoutp, int sizelimit, int *msgidp );
</pre>
Sample code for sending a search request can be found in Sending Search Request Using Directory SDK for C.<br>
 
==== Search Parameters for Directory SDK for C  ====
 
For either of the functions ldap_search_ext_s() or ldap_search_ext(), you specify the search criteria by using the parameters as detailed in the following list.<br>
 
*''base'': Specifies the starting point in the directory, or the base DN, where the search begins. For example, to search entries under dc=example,dc=com, the base DN is dc=example,dc=com. See Specifying the Base DN and the Scope With Directory SDK for C.
*''scope'': Specifies which entries to search. The search can address the base DN only, entries one level under the base DN, or all entries under the base DN. See Specifying the Base DN and the Scope With Directory SDK for C.
*''filter'': Specifies a search filter by defining what to search for. A search filter can be as simple as find entries with the last name of Jensen or as complex as find entries that belong to Dept. #17 and whose first names start with the letter F. See Specifying a Search Filter With Directory SDK for C.
*''attrsattrsonly'': Specify what to return. Options are the type of information to return, and the attributes to retrieve. Also, options include whether to return only attribute types, or both types and values. You can also specify to return the names of attributes only, and not the values, by passing a nonzero value for the attrsonly argument. See Specifying the Attributes to Retrieve With Directory SDK for C.
*''serverctrlsclientctrls'': Specify the LDAP v3 controls that are associated with this search operation. For details on LDAP v3 controls, see Chapter16, LDAP Controls With Directory SDK for C.
*''timeoutpsizelimit'': Specify search constraints that you want applied to the search. For example, you can specify a different timeout period or maximum number of results from the values already defined for the current session. See Setting Search Preferences With Directory SDK for C.<br>
 
==== Specifying the Base DN and the Scope With Directory SDK for C  ====
 
When sending a search request, you need to specify the base DN and the search scope to identify the entries that you want searched. The base DN, the root argument, is the DN of the entry that serves as the starting point for the search.
 
*LDAP_SCOPE_SUBTREE searches the base entry and all entries at all levels under the base entry.
*LDAP_SCOPE_ONELEVEL searches all entries one level under the base entry. The base entry is not included in the search. Use this setting if you just want to list the entries under a given entry.
*LDAP_SCOPE_BASE searches only the base entry. Use this setting if you just want to read the attributes of the base entry.<br>
 
==== Specifying a Search Filter With Directory SDK for C  ====
 
When you search the directory, you use a search filter to define the search. The following example illustrates the search filter syntax:
 
(''attribute operator value'')
<pre>(cn=Barbara Jensen)</pre>
Compare the syntax to the example. You see that <tt>cn</tt> is the attribute, that <tt>=</tt> is the operator, and that <tt>Barbara Jensen</tt> is the value. The filter finds entries with the common name Barbara Jensen. For a list of valid attributes for your search filter, see the LDAP schema for the directory server you are using. For a list of valid operators that you can use in your search filter, see the following list.
 
*=<br>Returns entries whose attribute is equal to the value.<br>(cn=Barbara Jensen) finds the entry with RDN cn=Barbara Jensen.
*&gt;=<br>Returns entries whose attribute is greater than or equal to the value.<br>(sn &gt;= jensen) finds all entries with surname (SN) from jensen to the end of the alphabetical list.
*=<br>Returns entries whose attribute is less than or equal to the value.<br>(sn = jensen) finds all entries with SN from the beginning of the alphabetical list to jensen.
*=*<br>Returns entries that have a value set for that attribute.<br>(sn =*) finds all entries that have the sn attribute.
*~=<br>Returns entries whose attribute value approximately matches the specified value. Typically, the algorithm matches words that sound alike.<br>(sn ~= jensen) finds entries with sn = jensen but also sn = jansen.
 
With boolean operators and with parentheses, you can combine different sets of conditions into one filter. The following shows boolean search filter syntax for combining filters, and a simple example:
 
(''boolean-operator''(''filter1'')(''filter2'')(''...''))
<pre>(|(sn=Jensen)(sn=Johnson))</pre>
The example uses the boolean or operator, <tt>|</tt>, to signify a search for all entries with the last name Jensen or the last name Johnson. The following list describes the valid boolean operators that you can use in your search filter.
 
*&amp;<br>Returns entries that match all specified filter criteria.
*|<br>Returns entries that match one or more of the filter criteria.
*!<br>Returns entries for which the filter is not true. You can only apply this operator to a single filter. For example: You can use:<br><pre>(!(filter))</pre><br>You cannot use:<br><pre>(!(filter1)(filter2))</pre>
 
You can also include wildcard characters, *, to search for entries that start with, contain, or end with a given value. For example, you can use this filter to search for all entries whose names begin with the letter F:
<pre>(givenName=F*)</pre>
When comparing values with letters, the value of the letter a is less than the value z. For example, the following filter finds all entries with last names beginning with a through Jensen:
<pre>(sn=jensen)</pre>
==== Specifying the Attributes to Retrieve With Directory SDK for C  ====
 
With the attrs argument, you can retrieve all attributes in the entries returned by the search. Alternatively, you can specify the attributes from the search results.
 
*To return selected attributes, pass an array of the attribute names as the attrs argument.<br>For example, to return only email addresses and phone numbers, pass the NULL terminated array {"mail", "telephoneNumber", NULL} as the attrs argument.
*To return all attributes in an entry, pass NULL as the attrs argument.
*To return no attributes from an entry, pass LDAP_NO_ATTRS as the attrs argument.<br>
 
===== Sorting Attributes  =====
 
If you plan to sort the results on your client, you need to return the attributes that you plan to use for sorting. For example, if you plan to sort by email address, make sure that the mail attribute is returned in the search results.
 
===== Operational Attributes  =====
 
Some attributes are used by servers for administering the directory. For example, the creatorsName attribute specifies the DN of the user who added the entry. These attributes are called operational attributes.
 
Servers do not normally return operational attributes in search results unless you specify the attributes by name. For example, you can pass NULL for the attrs argument to retrieve all of the attributes in entries found by the search. When you pass this value, the operational attribute creatorsName is not returned to your client. You need to explicitly specify the creatorsName attribute in the attrs argument. You can retrieve all attributes in an entry, as well as selected operational attributes. Pass a NULL terminated array that contains LDAP_ALL_USER_ATTRS. Also, pass the names of the operational attributes as the attrs argument. The following list shows operational attributes and explains the meaning of their values.<br>
 
*createTimestamp:&nbsp;The time that the entry was added to the directory
*modifyTimestamp: The time that the entry was last modified
*creatorsName: DN of the user who added the entry to the directory
*modifiersName: DN of the user who last modified the entry
*subschemaSubentry: DN of the subschema entry, which controls the schema for this entry<br>
 
==== Setting Search Preferences With Directory SDK for C  ====
 
For a given search, you can specify the maximum number of results to be returned. Alternatively, you can specify the maximum amount of time to wait for a search.
 
*To specify an infinite time limit, in other words, no limit, create a timeval structure with tv_sec = tv_usec = 0. Then pass a pointer to the structure as the timeoutp argument.
*To use the time limit specified by the LDAP_OPT_TIMELIMIT option for this connection, pass NULL as the timeoutp argument.
*To specify an infinite size limit, in other words, no limit, pass LDAP_NO_LIMIT as the sizelimit argument.
*To use the size limit specified by the LDAP_OPT_SIZELIMIT option for this connection, pass NULL as the sizelimit argument.
*To specify preferences for all searches under the current connection, call ldap_set_option and set the LDAP_OPT_SIZELIMIT and LDAP_OPT_TIMELIMIT options.<br>If you do not want to specify a limit, in other words, no limit, set the value of each option to LDAP_NO_LIMIT.<br>'''Note:''' The LDAP server administrator might already have configured time limits and size constraints that you cannot override.
 
The following example sets these session preferences so that a search returns no more than 100 entries, and takes no more than 30 seconds.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP *ld;
int max_ret, max_tim;
char *host = "ldap.example.com";
...
/* Initialize a session with the LDAP server ldap.example.com:389. */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
 
/* Set the maximum number of entries returned. */
max_ret = 100;
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, (void *)max_ret );
 
 
/* Set the maximum number of seconds to wait. */
max_tim = 30;
ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *)max_tim );
...</pre>
=== Getting the Search Results With Directory SDK for C  ===
 
The directory entries found by the search. In other words, those entries that match the search criteria.
 
*Any search references found within the scope of the search. A search reference is a reference to another LDAP server.
*An LDAP result code that specifies the result of the search operation.<br>'''Note:''' Because results are represented as a chain, do not free individual LDAPMessage structures within the chain. When you are done working with the results, free the chain, rather than the individual structures. If you free individual LDAPMessage structures from memory, you might lose all of the results.
*To get each entry and each search reference in the result, call ldap_first_message() and ldap_next_message(). Both of these functions return a pointer to an LDAPMessage structure that represents an entry, search reference, or LDAP result code. You can get the count of the structures in the chain by calling ldap_count_messages().
*If you want to retrieve just the entries from the chain, call ldap_first_entry() and ldap_next_entry(). Both of these functions return a pointer to an LDAPMessage structure that represents an entry. You can get the count of the entries in the chain by calling ldap_count_entries().
*If you want to retrieve just the search references from the chain, call ldap_first_reference() and ldap_next_reference(). Both of these functions return a pointer to an LDAPMessage structure that represents a search reference. You can get the count of the search references in the chain by calling ldap_count_references().
 
==== Getting Results Synchronously  ====
 
If you call ldap_search_ext_s() to search the directory synchronously, the function blocks processes until all results have been received. The function then returns a chain of results in the result parameter, a handle to an LDAPMessage structure. The following example prints the values of all attributes in the entries returned by a synchronous search.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
int
main( int argc, char **argv )
{
    LDAP          *ld;
    LDAPMessage    *res, *msg;
  LDAPControl      **serverctrls;
    BerElement    *ber;
    char          *a, *dn, *matched_msg = NULL, *error_msg = NULL;
    char          **vals, **referrals;
    int            version, i, rc, parse_rc, msgtype, num_entries = 0,
                    num_refs = 0;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
  version = LDAP_VERSION3;
  if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version )&nbsp;!=
        LDAP_SUCCESS ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
    /* Bind to the server anonymously. */
    rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Perform the search operation. */
    rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER,
        NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, res );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
              "Part of the DN that matches an existing entry:&nbsp;%s\n",
              matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    num_entries = ldap_count_entries( ld, res );
  num_refs = ldap_count_references( ld, res );
  /* Iterate through the results. An LDAPMessage structure sent back from
      a search operation can contain either an entry found by the search,
      a search reference, or the final result of the search operation. */
  for ( msg = ldap_first_message( ld, res );
        msg&nbsp;!= NULL;
        msg = ldap_next_message( ld, msg ) ) {
    /* Determine what type of message was sent from the server. */
    msgtype = ldap_msgtype( msg );
    switch( msgtype ) {
    /* If the result was an entry found by the search, get and print the
      attributes and values of the entry. */
    case LDAP_RES_SEARCH_ENTRY:
      /* Get and print the DN of the entry. */
      if (( dn = ldap_get_dn( ld, res ))&nbsp;!= NULL ) {
        printf( "dn:&nbsp;%s\n", dn );
        ldap_memfree( dn );
      }
      /* Iterate through each attribute in the entry. */
      for ( a = ldap_first_attribute( ld, res, ber );
      a&nbsp;!= NULL; a = ldap_next_attribute( ld, res, ber ) ) {
        /* Get and print all values for each attribute. */
        if (( vals = ldap_get_values( ld, res, a ))&nbsp;!= NULL ) {
          for ( i = 0; vals[ i ]&nbsp;!= NULL; i++ ) {
            printf( "%s:&nbsp;%s\n", a, vals[ i ] );
          }
          ldap_value_free( vals );
        }
        ldap_memfree( a );
      }
      if ( ber&nbsp;!= NULL ) {
        ber_free( ber, 0 );
      }
      printf( "\n" );
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      /* The server sent a search reference encountered during the
        search operation. */
      /* Parse the result and print the search references.
        Ideally, rather than print them out, you would follow the
        references. */
      parse_rc = ldap_parse_reference( ld, msg, referrals, NULL, 0 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
        "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      if ( referrals&nbsp;!= NULL ) {
        for ( i = 0; referrals[ i ]&nbsp;!= NULL; i++ ) {
          printf( "Search reference:&nbsp;%s\n\n", referrals[ i ] );
        }
        ldap_value_free( referrals );
      }
      break;
    case LDAP_RES_SEARCH_RESULT:
      /* Parse the final result received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, msg, rc,
        matched_msg, error_msg, NULL, serverctrls, 0 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP search operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
      } else {
        printf( "Search completed successfully.\n"
          "Entries found:&nbsp;%d\n"
          "Search references returned:&nbsp;%d\n",
          num_entries, num_refs );
      }
 
      break;
 
    default:
      break;
    }
  }
    /* Disconnect when done. */
    ldap_unbind( ld );
    return( 0 );
}</pre>
==== Getting Results Asynchronously  ====
 
If you use the asynchronous function ldap_search_ext(), you first need to call ldap_result() to determine if the server sent back any results.
<pre>LDAP_API(int) LDAP_CALL ldap_result( LDAP *ld, int msgid, int all,
  struct timeval *timeout, LDAPMessage **result );</pre>
You can specify how you want to get asynchronous results.
 
To get the results individually as the client receives the results from the server, pass LDAP_MSG_ONE as the all argument.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
LDAPMessage    *res;
int        msgid, rc, parse_rc, finished = 0;
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send the LDAP search request. */
rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL,
  NULL, LDAP_NO_LIMIT, msgid );
...
/* Poll the server for the results of the search operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    ...
  case 0:
    /* The timeout period specified by zerotime was exceeded. */
    ...
  case LDAP_RES_SEARCH_ENTRY:
    /* The server sent one of the entries found by the search. */
    ...
  case LDAP_RES_SEARCH_REFERENCE:
    /* The server sent a search reference .*/
    ...
  case LDAP_RES_SEARCH_RESULT:
    /* Parse the final result received from the server. */
    ...
  }
...
}
...</pre>
*To get the results all at once, in other words, to block processes until all results are received, pass LDAP_MSG_ALL as the all argument.
*To get the results received thus far, pass LDAP_MSG_RECEIVED as the all argument.
 
If you specify either LDAP_MSG_ALL or LDAP_MSG_RECEIVED, the function passes back a chain of search results as the result argument. If you specify LDAP_MSG_ONE, the function passes back a single search result as the result argument. The function normally returns the type of the first search result. When the function returns the type, as only one result is returned, the function returns the type of that result.
 
The following example prints the values of all attributes in the entries returned by an asynchronous search.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
int
main( int argc, char **argv )
{
    LDAP          *ld;
    LDAPMessage    *res;
    BerElement    *ber;
  LDAPControl      **serverctrls;
    char          *a, *dn, *matched_msg = NULL, *error_msg = NULL;
    char          **vals, **referrals;
    int          version, i, msgid, rc, parse_rc, finished = 0,
                  num_entries = 0, num_refs = 0;
    struct        timeval  zerotime;
    zerotime.tv_sec = zerotime.tv_usec = 0L;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
  version = LDAP_VERSION3;
  if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version )&nbsp;!=
      LDAP_SUCCESS ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
    /* Bind to the server anonymously. */
    rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    /* If the server cannot find an entry,
      print the portion of the DN that matches
      an existing entry. */
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Send the LDAP search request. */
    rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER,
          NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
    }
    /* Poll the server for the results of the search operation.
    Passing LDAP_MSG_ONE indicates that you want to receive
    the entries one at a time, as they come in.  If the next
    entry that you retrieve is NULL, there are no more entries. */
    while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
    /* The server can return three types of results back to the client,
      and the return value of ldap_result() indicates the result type:
      LDAP_RES_SEARCH_ENTRY identifies an entry found by the search,
      LDAP_RES_SEARCH_REFERENCE identifies a search reference returned
      by the server, and LDAP_RES_SEARCH_RESULT is the last result
      sent from the server to the client after the operation completes.
      You need to check for each of these types of results. */
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that the server has still not yet sent the
        results of the search operation back to your client.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for results. */
      break;
    case LDAP_RES_SEARCH_ENTRY:
      /* The server sent one of the entries found by the search
        operation. Print the DN, attributes, and values of the entry. */
      /* Keep track of the number of entries found. */
      num_entries++;
      /* Get and print the DN of the entry. */
      if (( dn = ldap_get_dn( ld, res ))&nbsp;!= NULL ) {
        printf( "dn:&nbsp;%s\n", dn );
        ldap_memfree( dn );
      }
      /* Iterate through each attribute in the entry. */
      for ( a = ldap_first_attribute( ld, res, ber );
      a&nbsp;!= NULL; a = ldap_next_attribute( ld, res, ber ) ) {
        /* Get and print all values for each attribute. */
        if (( vals = ldap_get_values( ld, res, a ))&nbsp;!= NULL ) {
          for ( i = 0; vals[ i ]&nbsp;!= NULL; i++ ) {
            printf( "%s:&nbsp;%s\n", a, vals[ i ] );
          }
          ldap_value_free( vals );
        }
        ldap_memfree( a );
      }
      if ( ber&nbsp;!= NULL ) {
        ber_free( ber, 0 );
      }
      printf( "\n" );
      ldap_msgfree( res );
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      /* The server sent a search reference encountered during the
        search operation. */
      /* Keep track of the number of search references returned from
        the server. */
      num_refs++;
      /* Parse the result and print the search references.
        Ideally, rather than print them out, you would follow the
        references. */
      parse_rc = ldap_parse_reference( ld, res, referrals, NULL, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      if ( referrals&nbsp;!= NULL ) {
        for ( i = 0; referrals[ i ]&nbsp;!= NULL; i++ ) {
          printf( "Search reference:&nbsp;%s\n\n", referrals[ i ] );
        }
        ldap_value_free( referrals );
      }
      break;
    case LDAP_RES_SEARCH_RESULT:
      /* Parse the final result received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      finished = 1;
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                  error_msg, NULL, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP search operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext:&nbsp;%s\n", ldap_err2string(rc) );
        ldap_get_lderrno( ld, matched_msg, error_msg );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
      } else {
        printf( "Search completed successfully.\n"
          "Entries found:&nbsp;%d\n"
          "Search references returned:&nbsp;%d\n"
          "Counted to&nbsp;%d while waiting for the search operation.\n",
          num_entries, num_refs, global_counter );
      }
 
      break;
 
    default:
      break;
    }
 
    /* Do other work here while waiting for the search operation
      to complete. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
    /* Disconnect when done. */
    ldap_unbind( ld );
    return( 0 );
}
/*
* Perform other work while polling for results.  This doesn't do
* anything useful, but it could.
*/
static void
do_other_work()
{
    global_counter++;
}</pre>
==== Determining Search Result Types  ====
 
To determine what type of result was returned, call the ldap_msgtype() function.
 
*LDAP_RES_SEARCH_ENTRY indicates that the result is an entry that is found in the search. You can pass the LDAPMessage structure that represents the entry to ldap_get_dn() to get the DN of the entry. You can pass the structure to ldap_first_attribute() and ldap_next_attribute() to get the attributes of the entry.
*LDAP_RES_SEARCH_REFERENCE indicates that the result is a search reference that is found within the scope of the search. You can pass the LDAPMessage structure representing the search reference to the ldap_parse_reference() function to get the referrals, LDAP URLs, to other servers.<br>To receive search references from an LDAP v3 server, you must identify your client as LDAP v3 enabled. If not, the server returns the error code LDAP_PARTIAL_RESULTS and a set of referrals.
*LDAP_RES_SEARCH_RESULT indicates that the result is the final data sent by the server to indicate the end of the LDAP search operation. You can pass the LDAPMessage structure that represents the result to the ldap_parse_result() function to get the LDAP result code for the search operation. For a list of possible result codes for an LDAP search operation, see the ldap_search_ext_s(3ldap) man page.
 
This example retrieves each result in a chain. The example then determines its type.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
LDAPMessage    *res, *msg;
BerElement    *ber;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc, msgtype, num_entries = 0, num_refs = 0;
...
/* Perform the search operation. */
rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL,
  NULL, LDAP_NO_LIMIT, res );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  /* If the server cannot find an entry and returns the portion of
    the DN that can find an entry, print it out. */
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
  ldap_unbind_s( ld );
  return( 1 );
}
...
num_entries = ldap_count_entries( ld, res );
num_refs = ldap_count_references( ld, res );
...
/* Iterate through the results. */
for ( msg = ldap_first_message( ld, res ); msg&nbsp;!= NULL;
  msg = ldap_next_message( ld, msg ) ) {
 
  /* Determine what type of message was sent from the server. */
  msgtype = ldap_msgtype( msg );
  switch( msgtype ) {
  case LDAP_RES_SEARCH_ENTRY:
    /* The result is an entry. */
    ...
  case LDAP_RES_SEARCH_REFERENCE:
    /* The result is a search reference. */
    ...
  case LDAP_RES_SEARCH_RESULT:
    /* The result is the final result sent by the server. */
    ...
  }
...
}
...</pre>
==== Getting Distinguished Names for Each Entry  ====
 
Because the DN of an entry differentiates the entry from other entries, you might want to access the DN in search results. You might also want to parse the name into its individual components. The SDK provides functions for both of these tasks.
 
===== Getting the Distinguished Name of an Entry  =====
 
To get the DN of an entry, call the ldap_get_dn() function. When finished with the DN, free the DN from memory by calling the ldap_memfree() function.
<pre>#include stdio.h&gt;
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result, *e;
char *dn;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result )&nbsp;!=
    LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* For each matching entry found, print the name of the entry.*/
for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
      e = ldap_next_entry( ld, e ) ) {
  if ( ( dn = ldap_get_dn( ld, e ) )&nbsp;!= NULL ) {
    printf( "dn:&nbsp;%s\n", dn );
    /* Free the memory used for the DN when done */
    ldap_memfree( dn );
  }
}
/* Free the result from memory when done. */
ldap_msgfree( result );</pre>
===== Getting the Components of a Distinguished Name  =====
 
If you want to access individual components of a DN or relative DN, call the ldap_explode_dn() or ldap_explode_rdn() function, respectively. Both functions return a NULL terminated array that contains the components of the DN. When you are done working with this array, free the array by calling the ldap_value_free() function.
 
You can also specify whether or not you want the attribute names included in the array, by using the notypes parameter.
 
Set notypes to 0 if you want to include attribute names, as in this function call:
<pre>ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 )</pre>
This function then returns this array:
<pre>{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL }</pre>
Set notypes to 1 if you do not want to include the attribute names in the array, as in this function call:
<pre>ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 )</pre>
This function then returns this array:
<pre>{ "bjensen", "People", "example.com", NULL }</pre>
==== Getting Attribute Types From an Entry  ====
 
To retrieve the type, also called the name, of the first attribute in an entry, call the ldap_first_attribute() function. To get the type of the next attribute, call the ldap_next_attribute() function.
 
''Note:'' Operational attributes such as creatorsName and modifyTimestamp are not normally returned in search results. You must explicitly specify operational attibutes by type in the search request. For more details, see Operational Attributes.
 
When you are finished iterating through the attributes, you need to free the BerElement structure allocated by the ldap_first_attribute() function, if the structure is not NULL. To free this structure, call the ldap_ber_free() function. You should also free the attribute type returned by the ldap_first_attribute() function. To free the attribute type, call the ldap_memfree() function. The following example shows how to do this.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP        *ld;
LDAPMessage  *result, *e;
BerElement  *ber;
char        *a;
char        *my_searchbase = "dc=example,dc=com";
char        *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
      NULL, 0, result )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
 
/* Retrieve the attributes of the entry. */
  for (a = ldap_first_attribute(ld, e, ber); a&nbsp;!= NULL;
        a = ldap_next_attribute(ld, e, ber)){
    ...
    /* Code to get and manipulate attribute values */
    ...
    }
    ldap_memfree( a );
  }
  /* Free the BerElement structure from memory when done. */
  if ( ber&nbsp;!= NULL ) {
    ldap_ber_free( ber, 0 );
  }
...</pre>
==== Getting the Values of an Attribute  ====
 
The values of an attribute are represented by a NULL terminated array. If the attribute contains string data, such as a name or phone number, the values are a list of strings. If the attribute contains binary data, the values are a list of berval structures, such as JPEG files or audio files. Use the following guidelines to retrieve the values of an attribute:
 
*To get the values of an attribute that contains string data, call the ldap_get_values() function. The ldap_get_values function returns a NULL terminated array of strings that represent the value of the attribute.
*To get the values of an attribute that contains binary data, call the ldap_get_values_len() function. The ldap_get_values_len function returns a NULL terminated array of berval structures that represent the value of the attribute.
*To get the number of values in an attribute, call either the ldap_count_values() or ldap_count_values_len() function. Both functions return the number of values in the attribute.
 
When you have finished working with the values of the attribute, you need to free the values from memory. To free the values, call ldap_free_value() or ldap_free_value_len(). The following example gets, then prints the values of an attribute in an entry. The function assumes that all attributes have string values.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP          *ld;
LDAPMessage  *result, *e;
BerElement    *ber;
char          *a;
char          **vals;
char          *my_searchbase = "dc=example,dc=com";
char          *my_filter = "(sn=Jensen)";
int i;
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result )&nbsp;!=
    LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
 
/* Get the first matching attribute. */
a = ldap_first_attribute( ld, e, ber );
 
/* Get the values of the attribute. */
if ( ( vals = ldap_get_values( ld, e, a ) )&nbsp;!= NULL ) {
  for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
    /* Print the name of the attribute and each value */
    printf( "%s:&nbsp;%s\n", a, vals[i] );
  }
  /* Free the attribute values from memory when done. */
  ldap_value_free( vals );
}
...</pre>
The following example gets the first value of the jpegPhoto attribute and saves the JPEG data to a file.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
struct berval photo_data;
struct berval **list_of_photos;
FILE *out;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result )&nbsp;!=
    LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
 
/* Find the jpegPhoto attribute. */
a = ldap_first_attribute( ld, e, ber );
while ( strcasecmp( a, "jpegphoto" )&nbsp;!= 0 ) {
  a = ldap_next_attribute( ld, e, ber );
}
 
/* Get the value of the attribute. */
if ( ( list_of_photos = ldap_get_values_len( ld, e, a ) )&nbsp;!=
      NULL ) {
  /* Prepare to write the JPEG data to a file */
  if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) {
    perror( "fopen" );
    return( 1 );
  }
  /* Get the first JPEG. */
  photo_data = *list_of_photos[0];
  /* Write the JPEG data to a file */
  fwrite( photo_data.bv_val, photo_data.bv_len, 1, out );
  fclose( out );
  /* Free the attribute values from memory when done. */
  ldap_value_free_len( list_of_photos );
}
...</pre>
==== Getting Referrals From Search References  ====
 
A search reference returned from the server contains one or more referrals, which are LDAP URLs that identify other LDAP servers. To retrieve these referrals, you need to call the ldap_parse_reference() function. The following example gets and prints the referrals from a search reference.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP          *ld;
LDAPMessage  *msg;
char          **referrals;
int          i, rc, parse_rc;
...
parse_rc = ldap_parse_reference( ld, msg, referrals, NULL, 0 );
if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
    ldap_err2string( parse_rc ) );
  ldap_unbind( ld );
  return( 1 );
}
if ( referrals&nbsp;!= NULL ) {
  for ( i = 0; referrals[ i ]&nbsp;!= NULL; i++ ) {
    printf( "Search reference:&nbsp;%s\n\n", referrals[ i ] );
  }
  ldap_value_free( referrals );
}
...</pre>
=== Sorting the Search Results With Directory SDK for C  ===
 
Directory SDK for C offers functions to sort entries and values in the search results. You can either specify that the server return sorted results or you can sort entries on your client.
 
==== Server-Side Sorting  ====
 
To sort results on the server, you need to send a server-side sorting control with the search request. For details, see Using the Server-Side Sorting Control With Directory SDK for C for details.
 
==== Client-Side Sorting  ====
 
First, you need to retrieve the attributes that you plan to use for sorting. For example, you might plan to sort the results by email address. Make sure that the mail attribute is one of the attributes returned in the search.
 
===== Sorting Entries by an Attribute  =====
 
To sort the search results by a particular attribute, call the ldap_sort_entries() function. If you do not specify an attribute for sorting, that is, if you pass NULL for the attr parameter, the entries are sorted by DN.
 
This example sorts entries by the roomNumber attribute.
<pre>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *sortby = "roomNumber";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result )&nbsp;!=
    LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* Sort the results by room number, using strcasecmp. */
if ( ldap_sort_entries(ld, result, sortby, strcasecmp)&nbsp;!=
    LDAP_SUCCESS ){
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}
...</pre>
===== Sorting Entries by Multiple Attributes  =====
 
To sort the search results by multiple attributes, call the ldap_multisort_entries() function. If you do not specify a set of attributes for sorting, the entries are sorted by DN. To sort entries by DN, pass NULL for the attr parameter.
 
This example sorts entries first by the roomNumber attribute, then by the telephoneNumber attribute.
<pre>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include "ldap.h"
LDAP *ld;
LDAPMessage *res;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *attrs[2];
attrs[0] = "roomNumber";
attrs[1] = "telephoneNumber";
attrs[2] = NULL;
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, res )&nbsp;!=
    LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
 
/* Sort the results, using strcasecmp. */
if ( ldap_multisort_entries(ld,res,attrs, strcasecmp)&nbsp;!=
    LDAP_SUCCESS ){
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}</pre>
===== Sorting the Values of an Attribute  =====
 
You can also sort the values of a particular attribute. To sort the values, call the ldap_sort_strcasecmp() function. In this function, the comparison function must pass parameters of the type char **. You should use the ldap_sort_strcasecmp() function, rather than a function like strcasecmp(), which passes parameters of the type char *. The following example sorts the values of attributes before printing the values.
<pre>#include stdio.h&gt;
#include string.h&gt;
#include "ldap.h"
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
    if ( ( vals = ldap_get_values( ld, e, a ) )&nbsp;!= NULL ) {
      /* Sort the values of the attribute */
      if ( ldap_sort_values(ld, vals, strcasecmp))&nbsp;!=
          LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_sort_values" );
        return( 1 );
      }
      /* Print the values of the attribute. */
      for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
        printf( "%s:&nbsp;%s\n", a, vals[i] );
      }
      /* Free the values from memory. */
      ldap_value_free( vals );
    }
...</pre>
=== Freeing the Search Results With Directory SDK for C  ===
 
The results of the search are returned in an LDAPMessage structure. After you are done working with the search results, you should free this structure from memory. To free the search results, call the ldap_msgfree() function, which returns the type of the last message freed from memory.
 
=== Examples of Search Operations With Directory SDK for C  ===
 
This section contains sample code for various search operations.
 
==== Reading an Entry With a Search  ====
 
You can use the search functions to read a specific entry in the directory. To read an entry, set the starting point of the search to the entry. Also, set the scope of the search to LDAP_SCOPE_BASE, specifying (objectclass=*) as the search filter, as shown in the following example.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORT_NUMBER  LDAP_PORT
#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
    LDAP  *ld;
    LDAPMessage  *result, *e;
    BerElement  *ber;
    char  *a;
    char  **vals;
    int    i, rc;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind anonymously to the LDAP server. */
    if ( ( rc = ldap_simple_bind_s( ld, NULL, NULL ) )&nbsp;!=
        LDAP_SUCCESS ) {
    fprintf( stderr,
              "ldap_simple_bind_s:&nbsp;%s\n",
              ldap_err2string( rc ) );
    return( 1 );
    }
    /* Search for the entry. */
    if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
                                  "(objectclass=*)", NULL, 0, NULL,
                                  NULL, LDAP_NO_LIMIT,
                                  LDAP_NO_LIMIT, result ) )&nbsp;!=
          LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    return( 1 );
    }
    /* Since this is a base search, there should be only one
      matching entry.  */
    e = ldap_first_entry( ld, result );
  if ( e&nbsp;!= NULL ) {
    printf( "\nFound&nbsp;%s:\n\n", FIND_DN );
    /* Iterate through each attribute in the entry. */
    for ( a = ldap_first_attribute( ld, e, ber );
      a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      /* For each attribute, print the attribute name and values. */
      if ((vals = ldap_get_values( ld, e, a))&nbsp;!= NULL ) {
        for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
          printf( "%s:&nbsp;%s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber&nbsp;!= NULL ) {
      ber_free( ber, 0 );
    }
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}</pre>
==== Listing Subentries With a Search  ====
 
You can use the search functions to list the subentries under a specific entry in the directory. To list the subentries, set the starting point of the search to the entry. Also, set the scope of the search to LDAP_SCOPE_ONELEVEL. The following lists all entries one level under the <tt>dc=example,dc=com</tt> entry in the directory hierarchy.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
LDAP        *ld;
LDAPMessage *result, *e;
BerElement  *ber;
char        *a, *dn;
char        **vals;
char        *my_searchbase = "dc=example,dc=com";
char        *my_filter = "(objectclass=*)"
 
/* Search one level under the starting point. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_ONELEVEL, my_filter,
      NULL, 0, result )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
/* For each matching entry, print the entry name and its attributes. */
for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
      e = ldap_next_entry( ld, e ) ) {
  if ( ( dn = ldap_get_dn( ld, e ) )&nbsp;!= NULL ) {
    printf( "dn:&nbsp;%s\n", dn );
    ldap_memfree( dn );
  }
  for ( a = ldap_first_attribute( ld, e, ber ); a&nbsp;!= NULL;
      a = ldap_next_attribute( ld, e, ber ) ) {
    if ( ( vals = ldap_get_values( ld, e, a ) )&nbsp;!= NULL ) {
      for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
        printf( "%s:&nbsp;%s\n", a, vals[i] );
      }
      ldap_value_free( vals );
    }
    ldap_memfree( a );
  }
  if ( ber&nbsp;!= NULL ) {
    ldap_ber_free( ber, 0 );
  }
  printf( "\n" );
}
ldap_msgfree( result );
...</pre>
==== Sending Search Request Using Directory SDK for C  ====
 
The following sample code shows how to search for all entries with the last name (surname) Jensen in the example.com organization.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
int      msgid, rc;
...
/* Send the search request. */
rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL,
  NULL, NULL, LDAP_NO_LIMIT, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_search_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...</pre>
== Using Filter Configuration Files With Directory SDK for C  ==
 
This section explains how to use LDAP C API functions to work with filter configuration files.
 
=== Understanding Filter Configuration Files for Directory SDK for C  ===
 
Filter configuration files can help simplify the process of selecting the appropriate filter for a search request. A filter configuration file contains a list of filters that you can load and use in your searches. You might be writing a client that allows users to search the directory. Use different search filters tailored for specific types of search criteria.
 
For example, if the user wants to search for the email address bjensen@example.com, you might want to use this search filter:
<pre>(mail=bjensen@example.com)
</pre>
Similarly, suppose the search term entered by the user contains numbers, as in 555-1212. In this case, you might want to use this search filter:
<pre>(telephoneNumber=555-1212)
</pre>
Rather than write code to find and select the appropriate filter, you can include the filters in a filter configuration file. For example, the following section of a filter configuration file specifies one filter for telephone numbers and two filters for email addresses. The telephone number filter is used if the search criteria contain one or more numbers. The email filters are used if the search criteria contain an at sign, @.
<pre>"people"
  "^[0-9][0-9-]*$"          " "
  "(telephoneNumber=*%v))"  "phone number ends with"
  "@"    " "  "(mail=%v)"    "email address is"
  "(mail=%v*)"              "email address starts with"</pre>
You should specify the filters in the order that you want the filters to be used. For example, if you want to apply the (mail=%v) filter before the (mail=%v*) filter, make sure that the filters appear in that order.
 
==== Syntax for Filter Configuration Files  ====
 
A filter configuration file has the following format. The variables are discussed in the following sections.
<pre>''tag''
  ''pattern1''    ''delimiters''    ''filter1-1''  ''desc1-1''  [''scope'']
  ''filter1-2''  ''desc1-2''                          [''scope'']
  ''pattern2''    ''delimiters''    ''filter2-1''  ''desc2-1''  [''scope'']</pre>
===== Tag for Filter Groups  =====
 
A ''tag'' identifies a group of filters. You can use different tags to distinguish filters for different types of objects. For example, you can use one tag to represent filters for person entries, another tag to represent filters for organization entries, and so on.
<pre>"people"
    (filters for searching "person" entries)
"organization"
    (filters for "organization" entries)</pre>
When you call functions like ldap_getfirstfilter() to retrieve a filter, you can specify a tag, or part of a tag, as a parameter. The tag narrows the list of filters that the function can retrieve.
 
===== Patterns to Select Filters  =====
 
''pattern1'' and ''pattern2'' are regular expressions used to determine which filter is selected, based on the search criteria. For example, if you specify <tt>"^[0-9]"</tt> as the pattern for a filter, the filter is selected for all search criteria that begin with a number.<br>
<pre>"people"
  "^[0-9]" </pre>
===== Delimiters for Fields  =====
 
Delimiters specifies the delimiters used to distinguish one field from another field within the search criteria. For example, if the search criteria consist of a city name and a state abbreviation separated by a comma, specify a comma as the delimiter.
 
===== Filter Lists  =====
 
''filter1-1'', ''filter1-2'', and ''filter2-1'' are filters. Use&nbsp;%v to represent the search criteria. For example, to search email addresses, use the filter <tt>(mail=%v)</tt>. During runtime, if the search criteria bjensen@example.com is entered, the filter becomes <tt>(mail=bjensen@example.com)</tt>.
 
The search criteria might consist of a number of delimited fields. For example, the criteria might have a last name, first name format such as Jensen, Barbara. Use&nbsp;%v1,&nbsp;%v2, ,&nbsp;%vn to represent the different fields within the search criteria as shown here:
<pre>"people"
  "^[A-Z]*,"      ","    ((sn=%v1)(givenName=%v2))</pre>
In this example, the delimiter is a comma. The word before the delimiter replaces&nbsp;%v1 in the filter. The word after the delimiter replaces&nbsp;%v2 in the filter. If the user searches for Jensen, Barbara , the resulting filter is as follows:
 
((sn=Jensen)(givenName=Barbara)) You can also specify ranges of fields. For example, to specify the values in the first three fields, use&nbsp;%v1-3. To specify values from the third field to the last field, use&nbsp;%v3-. To specify the value in the last field, use&nbsp;%v$.
 
===== Descriptions of Filters  =====
 
''desc1-1'', ''desc1-2'', and ''desc2-1'' are phrases that briefly describe the filters.
 
==== Filter Parameters<br>  ====
 
Filter specifications in the configuration file support the following parameters:
 
*%v<br>Insert the search criterion as is in place of&nbsp;%v.<br>For example, if the filter specification is (mail=%v), entering bjensen results in the filter (mail=bjensen).
*%v$<br>Insert the last word of the search criterion as is in place of&nbsp;%v.<br>For example, if the filter specification is (sn=%v$), entering Barbara Jensen results in the filter (sn=Jensen).
*%v''N''<br>Insert the Nth word of the criteria in place of&nbsp;%v, where N is a single digit between 1 and 9.<br>For example, if the filter specification is (sn=%v2), entering Barbara Jensen results in the filter (sn=Jensen).
*%v''M-N''<br>Insert the sequence of the Mth through Nth words of the criteria in place of&nbsp;%v. Here, M and N are single digits between 1 and 9.<br>For example, if the filter specification is (cn=%v1-2), entering Barbara Jensen results in the filter (cn=Barbara Jensen).
*%v''N-''<br>Insert the sequence of the Nth through last words of the criteria in place of&nbsp;%v. Here, N is a single digit between 1 and 9.<br>For example, if the filter specification is (cn=%v2-), entering Ms. Barbara Jensen results in the filter (cn=Barbara Jensen).<br>
 
=== Loading Filter Configuration Files With Directory SDK for C<br>  ===
 
To load a filter configuration file, call the ldap_init_getfilter() function. You can also read the filter configuration file from a buffer in memory by calling the ldap_init_getfilter_buf() function. Both functions return a pointer to an LDAPFiltDesc structure, which contains information about the filter. If an error occurs, both functions return NULL.
 
==== Retrieving Filters  ====
 
After loading a filter configuration file into memory, you can retrieve filters based on the search criteria. For example, the search criteria might be an email address, (bjensen@example.com). Have your client automatically search for this value in the mail attribute of person entries.
 
To retrieve the first filter that matches the search criteria, call the ldap_getfirstfilter() function. To get the next filter that matches the search criteria, call the ldap_getnextfilter() function. Both functions return a pointer to an LDAPFiltInfo structure, which contains information about the filter, as shown here.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
LDAP          *ld;
LDAPMessage  *result, *e;
BerElement    *ber;
char          *a, *dn;
char          **vals;
int i;
LDAPFiltDesc *ldfp;
LDAPFiltInfo *ldfi;
char buf[ 80 ]; /* contains the search criteria */
int found;
 
/* Load the filter configuration file into an LDAPFiltDesc structure. */
if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) {
  perror( "Cannot open filter configuration file" );
}
 
/* Select a filter to use when searching for the value in buf.
Use filters under the "people" tag in the filter configuration file. */
found = 0;
for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf ); ldfi&nbsp;!= NULL;
  ldfi = ldap_getnextfilter( ldfp ) ) {
 
  /* Use the selected filter to search the directory. */
  if ( ldap_search_s( ld, "dc=example,dc=com", ldfi-&gt;lfi_scope,
  ldfi-&gt;lfi_filter, NULL, 0, result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  } else {
 
    /* Once a filter gets results back, stop iterating through
    the different filters. */
    if ( ( found = ldap_count_entries( ld, result ) &gt; 0 ) ) {
      break;
    } else {
      ldap_msgfree( result );
    }
  }
}
 
if ( found == 0 ) {
  printf( "No matching entries found.\n" );
} else {
  printf( "Found&nbsp;%d match%s where&nbsp;%s \"%s\"\n\n", found,
  found == 1&nbsp;? ""&nbsp;: "es", ldfi-&gt;lfi_desc, buf );
}
 
ldap_msgfree( result );
ldap_getfilter_free( ldfp );</pre>
Suppose that the search criteria is bjensen@example.com and that the client application finds a single matching entry. Then the application prints the following output:
<pre>Found 1 match where email address is bjensen@example.com</pre>
=== Filter Prefixes and Suffixes for Directory SDK for C  ===
 
If you need to apply a filter to all searches, add a filter prefix and suffix to all filters. Do not add the criteria to all filters. The prefix is automatically added to any filter retrieved through the ldap_getfirstfilter() and ldap_getnextfilter() functions. The required suffix ) needed to balance the number of parentheses is also added. For example, suppose you use this filter in a filter configuration file:
<pre>(cn=Babs Jensen)</pre>
You can retrieve this filter by using ldap_getfirstfilter() or ldap_getnextfilter(). These functions get a filter that constrains your client searches to person entries for the defined filter:
<pre>((objectClass=person)(cn=Babs Jensen))</pre>
To add a prefix and suffix automatically to all filters retrieved from the filter configuration file, call the ldap_set_filter_additions() function. The following example adds the prefix <tt>((objectClass=person)</tt> and the suffix <tt>)</tt> to each filter retrieved.
<pre>#include "ldap.h"
 
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
char *prefix = "((objectClass=person)";
char *suffix = ")";
 
lfdp = ldap_init_getfilter( filter_file );
ldap_setfilteraffixes( lfdp, prefix, suffix );</pre>
=== Freeing Filters From Memory With Directory SDK for C  ===
 
When you complete your search, free the LDAPFiltDesc structure from memory. To free LDAPFiltDesc, call the ldap_getfilter_free() function as shown here.
<pre>#include "ldap.h"
 
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
 
/* Read the filter configuration file into an LDAPFiltDesc structure. */
lfdp = ldap_init_getfilter( filter_file );
 
/* Retrieve filters and perform searches. */
 
/* Free the configuration file (the LDAPFiltDesc structure). */
ldap_getfilter_free( lfdp );</pre>
=== Creating Filters Programmatically With Directory SDK for C  ===
 
You can build your own filters by calling the ldap_create_filter() function. The following example builds the filter (mail=bjensen@example.com).
<pre>char buf[LDAP_FILT_MAXSIZ];
char *pattern = "(%a=%v);
char *attr = "mail";
char *value = "bjensen@example.com";
 
ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL, NULL, attr,
    value, NULL );</pre>
== Adding, Updating, and Deleting Entries With Directory SDK for C  ==
 
This section explains how to use LDAP C API functions to add, update, delete, and rename entries.
 
=== Specifying Entry Information With Directory SDK for C  ===
 
The type of attribute that you are working with. For example, the sn attribute or the telephoneNumber attribute.
 
*The values that you are adding, or replacing in the attribute.
*The operation that you are performing when modifying an existing entry. In other words, determine whether you are adding, modifying, or deleting the attribute in the existing entry.
*To specify this information, you use an LDAPMod structure as shown here.
<pre>typedef struct ldapmod {
  int mod_op;
  char *mod_type;
  union {
    char **modv_strvals;
    struct berval **modv_bvals;
  } mod_vals;
#define mod_values        mod_vals.modv_strvals
#define mod_bvalues      mod_vals.modv_bvals
} LDAPMod;</pre>
The following list details the fields in the LDAPMod data structure.
 
*mod_op
**LDAP_MOD_ADD adds a value to the attribute.
**LDAP_MOD_DELETE removes a value from the attribute.
**LDAP_MOD_REPLACE replaces all existing values of the attribute.<br>Furthermore, if you specify binary values in the mod_bvalues field, use the bitwise or operator, |, to combine LDAP_MOD_BVALUES with the operation type:<br><tt>mod-&gt;mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES</tt><br>If you are using the structure to add a new entry, you can specify 0 for the mod_op field, unless you are adding binary values and need to specify LDAP_MOD_BVALUES.
*mod_type<br>Attribute type that you want to add, delete, or replace, such as sn or telephoneNumber.
*mod_values<br>Pointer to a NULL terminated array of string values for the attribute.
*mod_bvalues<br>Pointer to a NULL terminated array of berval structures for the attribute.
 
The following precautions pertain to entry modifications and the fields detailed in this list.<br>
 
*If you specify LDAP_MOD_DELETE in the mod_op field to remove all values in an attribute, the attribute is removed from the entry.
*If you specify LDAP_MOD_DELETE in the mod_op field and NULL in the mod_values field, the attribute is removed from the entry.
*If you specify LDAP_MOD_REPLACE in the mod_op field and NULL in the mod_values field, the attribute is removed from the entry.
*If you specify LDAP_MOD_REPLACE in the mod_op field, but the attribute does not exist in the entry, the attribute is added to the entry.
*If you specify LDAP_MOD_ADD in the mod_op field, but the attribute does not exist in the entry, the attribute is added to the entry.
 
If you allocate memory for the structures yourself, free the structures when you finish by calling the ldap_mods_free() function.
 
=== Adding an Entry With Directory SDK for C<br>  ===
 
The following procedure provides the general steps for adding a new entry to the directory.
 
'''To Add a New Entry'''
 
#Use the LDAPMod structure to specify the name and values of each attribute.
#Create an array of LDAPMod structures to represent the attributes in the entry.
#Call the ldap_add_ext() or ldap_add_ext_s() function, passing in the array of LDAPMod structures and a distinguished name (DN) for the entry.
#Call the ldap_mods_free function to free any LDAPMod structures that you allocated.<br>
 
==== Specifying Values for Attributes  ====
 
You can specify a value for an attribute in three ways. You can specify a single value. You can specify multiple values. You can add binary data as the value of an attribute.
 
===== Specifying a Single Value in an Attribute  =====
 
To specify a value in an attribute, set the mod_op, mod_type, and mod_values fields in an LDAPMod structure. This example sets up the structure for the sn attribute.<br>
<pre>#include "ldap.h"
 
LDAPMod attribute1;
char *sn_values[] = { "Jensen", NULL };
 
attribute1.mod_op = 0;
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
</pre>
Because you are specifying an attribute for a new entry, rather than for an existing entry, you can set the mod_op field to 0. For an existing entry, the mod_op field identifies the type of change you are making to the entry.
 
===== Specifying Multiple Values in an Attribute  =====
 
If an attribute has more than one value, specify the values in the mod_values array. This example specifies two values for the cn attribute.<br>
<pre>#include "ldap.h"
 
LDAPMod attribute2, attribute3;
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
char *objectClass_values[] = { "top", "person",
  "organizationalPerson", "inetOrgPerson", NULL };
 
attribute2.mod_op = 0;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_op = 0;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
</pre>
===== Specifying Binary Data as the Value of an Attribute  =====
 
If the attribute contains binary data rather than string values, specify the data in a berval structure similar to this.<br>
<pre>struct berval {
  unsigned long bv_len;
  char *bv_val;
}
</pre>
The berval structure fields and field descriptions are as follows:
 
''bv_len'': The length of the data
 
''bv_val'': A pointer to the binary data<br>
 
After creating the berval structures for the binary data, you may use the structures.
 
'''To Use berval Structures'''
 
#Add the berval structures to the mod_bvalues field in the LDAPMod structure.
#Use the bitwise or operator, |, to combine the value of the mod_op field with LDAP_MOD_BVALUES.<br>When adding a new entry, you set the mod_op field to LDAP_MOD_BVALUES because the mod_op field is 0 in this case.<br>For example, suppose the file my_photo.jpg contains a JPEG photograph of Barbara Jensen. The following example sets the jpegPhoto attribute to the JPEG data of the photograph.
<pre>#include &lt;stdio.h&gt;
#include &lt;sys/stat.h&gt;
#include "ldap.h"
 
char *photo_data;
FILE *fp;
struct stat st;
LDAPMod attribute4;
struct berval photo_berval;
struct berval *jpegPhoto_values[2];
/* Get information about the JPEG file, including its size. */
if ( stat( "my_photo.jpg", st )&nbsp;!= 0 ) {
  perror( "stat" );
  return( 1 );
}
 
/* Open the JPEG file and read it into memory. */
if ( ( fp = fopen( "my_photo.jpg", "rb" ) ) == NULL ) {
  perror( "fopen" );
  return( 1 );
}
if ( ( ( photo_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
      ( fread ( photo_data, st.st_size, 1, fp )&nbsp;!= 1 ) ) {
  perror( photo_data&nbsp;? "fread"&nbsp;: "malloc" );
  return( 1 );
}
 
fclose( fp );
 
attribute4.mod_op = LDAP_MOD_BVALUES;
attribute4.mod_type = "jpegPhoto";
photo_berval.bv_len = st.st_size;
photo_berval.bv_val = photo_data;
jpegPhoto_values[0] = photo_berval;
jpegPhoto_values[1] = NULL;
attribute4.mod_values = jpegPhoto_values;</pre>
==== Specifying Attributes in the Entry  ====
 
After specifying values for attributes in LDAPMod structures, as described in Specifying Values for Attributes, you need to construct an array of these structures. You then pass a pointer to this array as a parameter to the function for creating a new entry.
 
Make sure you create LDAPMod structures for all required attributes in the new entry.
 
The following example creates an array of LDAPMod structures.
 
<br>
<pre>#include "ldap.h"
LDAPMod *list_of_mods[5]
LDAPMod attribute1, attribute2, attribute3, attribute4;
 
/* Code for filling the LDAPMod structures with values */
 
list_of_mods[0] = attribute1;
list_of_mods[1] = attribute2;
list_of_mods[2] = attribute3;
list_of_mods[3] = attribute4;
list_of_mods[4] = NULL;</pre>
==== Adding the Entry to the Directory  ====
 
*The synchronous ldap_add_ext_s() function
*The asynchronous ldap_add_ext() function
 
If you have allocated LDAPMod structures yourself, you should free the structures when you are done. Call the ldap_mods_free() function to free LDAPMod structures.
 
===== Synchronous Add Operation  =====
 
If you want to wait for the results of the add operation to complete before continuing, call the synchronous ldap_add_ext_s() function. This function sends an LDAP add request to the server. The function also blocks other work until the server sends the results of the operation back to your client. The ldap_add_ext_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.
 
The following example calls the synchronous ldap_add_ext_s() function to add the user William Jensen to the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
 
LDAP        *ld;
LDAPMod      **mods;
char        *matched_msg = NULL, *error_msg = NULL;
int        rc;
 
/* Perform the add operation. */
rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_add_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
} else {
  printf( "%s added successfully.\n", NEW_DN );
}</pre>
The following sample program calls the synchronous ldap_add_ext_s() function to add a new user to the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define  NUM_MODS 5
int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMod        **mods;
  char          *matched_msg = NULL, *error_msg = NULL;
    int          i, rc;
  char *object_vals[] = { "top", "person", "organizationalPerson",
    "inetOrgPerson", NULL };
 
char *cn_vals[] = { "William B Jensen", "William Jensen", "Bill Jensen",
    NULL };
    char *sn_vals[] = { "Jensen", NULL };
    char *givenname_vals[] = { "William", "Bill", NULL };
    char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind to the server as the Directory Manager. */
    rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Construct the array of LDAPMod structures representing the attributes
    of the new entry. */
    mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
    if ( mods == NULL ) {
    fprintf( stderr, "Cannot allocate memory for mods array\n" );
    exit( 1 );
    }
    for ( i = 0; i  NUM_MODS; i++ ) {
    if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
      fprintf( stderr, "Cannot allocate memory for mods element\n" );
      exit( 1 );
    }
    }
    mods[ 0 ]-&gt;mod_op = 0;
    mods[ 0 ]-&gt;mod_type = "objectclass";
    mods[ 0 ]-&gt;mod_values = object_vals;
    mods[ 1 ]-&gt;mod_op = 0;
    mods[ 1 ]-&gt;mod_type = "cn";
    mods[ 1 ]-&gt;mod_values = cn_vals;
    mods[ 2 ]-&gt;mod_op = 0;
    mods[ 2 ]-&gt;mod_type = "sn";
    mods[ 2 ]-&gt;mod_values = sn_vals;
    mods[ 3 ]-&gt;mod_op = 0;
    mods[ 3 ]-&gt;mod_type = "givenname";
    mods[ 3 ]-&gt;mod_values = givenname_vals;
    mods[ 4 ]-&gt;mod_op = 0;
    mods[ 4 ]-&gt;mod_type = "telephonenumber";
    mods[ 4 ]-&gt;mod_values = telephonenumber_vals;
    mods[ 5 ] = NULL;
    /* Perform the add operation. */
    rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_add_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    } else {
    printf( "%s added successfully.\n", NEW_DN );
  }
  ldap_unbind_s( ld );
  for ( i = 0; i  NUM_MODS; i++ ) {
    free( mods[ i ] );
  }
  free( mods );
  return 0;
}</pre>
===== Asynchronous Add Operation  =====
 
If you want to perform other work while waiting for the entry to be added, call the asynchronous ldap_add_ext() function. This function sends an LDAP add request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.
 
The ldap_add_ext() function passes back a message ID identifying the add operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the add operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.
 
The following example calls the asynchronous ldap_add_ext() function to add the user William Jensen to the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
 
 
LDAP          *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char          *matched_msg = NULL, *error_msg = NULL;
char          **referrals;
int            i, rc, parse_rc, msgid, finished = 0;
 
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Send the LDAP add request. */
rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_add_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Poll the server for the results of the add operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the add operation. */
    finished = 1;
 
    /* Parse the result to determine the result of
      the add operation. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the LDAP add operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_add_ext:&nbsp;%s\n", ldap_err2string( rc ) );
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
    } else {
      printf( "%s added successfully.\n", NEW_DN );
    }
  }
}</pre>
The following sample program calls the asynchronous ldap_add_ext() function to add a new user to the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
void free_mods( LDAPMod **mods );
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define  NUM_MODS 5
int
main( int argc, char **argv )
{
    LDAP      *ld;
    LDAPMessage    *res;
    LDAPMod      **mods;
  LDAPControl    **serverctrls;
  char          *matched_msg = NULL, *error_msg = NULL;
  char          **referrals;
    int        i, rc, parse_rc, msgid, finished = 0;
    struct timeval  zerotime;
    char *object_vals[] = { "top", "person", "organizationalPerson",
                            "inetOrgPerson", NULL };
    char *cn_vals[] = { "William B Jensen", "William Jensen",
                        "Bill Jensen", NULL };
    char *sn_vals[] = { "Jensen", NULL };
    char *givenname_vals[] = { "William", "Bill", NULL };
    char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
    zerotime.tv_sec = zerotime.tv_usec = 0L;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind to the server as the Directory Manager. */
    rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Construct the array of LDAPMod structures representing the attributes
    of the new entry. */
    mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
    if ( mods == NULL ) {
    fprintf( stderr, "Cannot allocate memory for mods array\n" );
    exit( 1 );
    }
    for ( i = 0; i  NUM_MODS; i++ ) {
    if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
      fprintf( stderr, "Cannot allocate memory for mods element\n" );
      exit( 1 );
    }
    }
    mods[ 0 ]-&gt;mod_op = 0;
    mods[ 0 ]-&gt;mod_type = "objectclass";
    mods[ 0 ]-&gt;mod_values = object_vals;
    mods[ 1 ]-&gt;mod_op = 0;
    mods[ 1 ]-&gt;mod_type = "cn";
    mods[ 1 ]-&gt;mod_values = cn_vals;
    mods[ 2 ]-&gt;mod_op = 0;
    mods[ 2 ]-&gt;mod_type = "sn";
    mods[ 2 ]-&gt;mod_values = sn_vals;
    mods[ 3 ]-&gt;mod_op = 0;
    mods[ 3 ]-&gt;mod_type = "givenname";
    mods[ 3 ]-&gt;mod_values = givenname_vals;
    mods[ 4 ]-&gt;mod_op = 0;
    mods[ 4 ]-&gt;mod_type = "telephonenumber";
    mods[ 4 ]-&gt;mod_values = telephonenumber_vals;
    mods[ 5 ] = NULL;
    /* Send the LDAP add request. */
    rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_add_ext:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    free_mods( mods );
    return( 1 );
    }
    /* Poll the server for the results of the add operation. */
    while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      free_mods( mods );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that the server has still not yet sent the
        results of the add operation back to your client.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for results. */
      break;
    default:
      /* The function has retrieved the results of the add operation
        from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc =
        ldap_parse_result( ld, res, rc, matched_msg,
                          error_msg, referrals, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        free_mods( mods );
        return( 1 );
      }
      /* Check the results of the LDAP add operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_add_ext:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
      } else {
        printf( "%s added successfully.\n"
          "Counted to&nbsp;%d while waiting for the add operation.\n",
          NEW_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the add operation. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  free_mods( mods );
  return 0;
}
/*
* Free a mods array.
*/
void
free_mods( LDAPMod **mods )
{
    int i;
    for ( i = 0; i  NUM_MODS; i++ ) {
  free( mods[ i ] );
    }
    free( mods );
}
 
/*
* Perform other work while polling for results.
* This doesn't do anything useful, but it could.
*/
void
do_other_work()
{
    global_counter++;
}</pre>
=== Modifying an Entry With Directory SDK for C  ===
 
The following procedure provides the general steps for modifying an entry.
 
'''To Modify an Entry'''
 
#Use the LDAPMod structure to specify a change to an attribute.
#Create an array of LDAPMod structures that represent the changes that need to be made.
#Call the ldap_modify_ext() or ldap_modify_ext_s() function, passing in the array of LDAPMod structures and the DN of the entry that you want modified.
#Call the ldap_mods_free() function to free any LDAPMod structures that you allocated.
 
==== Types of Modifications  ====
 
You can modify an entry in various ways. The following sections explain the types of modifications.
 
===== Replacing the Values of an Attribute  =====
 
*Set the mod_type field to the attribute type that you want to change, such as telephoneNumber.
*Set the mod_values field to the new values of the attribute.
*Set the value of the mod_op field to LDAP_MOD_REPLACE.
 
The following code specifies a change that replaces the values of the telephoneNumber attribute.
<pre>#include "ldap.h"
LDAPMod attribute1;
char *telephoneNumber_values[] = { "+1 800 555 1212", NULL };
attribute1.mod_type = "telephoneNumber";
attribute1.mod_op = LDAP_MOD_REPLACE;
attribute1.mod_values = telephoneNumber_values;
</pre>
*Use the mod_bvalues field rather than the mod_values field.
*Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.<br>
 
'''Note:''' If you specify an attribute that does not exist in the entry, the attribute is added to the entry.
 
You can set a NULL value for the attribute either by setting the mod_values field to NULL or by setting the mod_bvalues field to NULL. When the mod_op field also contains LDAP_MOD_BVALUES, the attribute is removed from the entry.<br>
 
===== Removing Values From an Attribute  =====
 
*Set the mod_type field to the attribute type that contains the values to remove such as facsimileTelephoneNumber.
*Set the mod_values field to the values that you want removed from the attribute.
*Set the value of the mod_op field to LDAP_MOD_DELETE.<br>The following code specifies the removal of one of the values of the facsimileTelephoneNumber attribute in the entry.
<pre>include "ldap.h"
LDAPMod attribute2;
char *fax_values[] = { "+1 800 555 1212", NULL };
attribute2.mod_type = "facsimileTelephoneNumber";
attribute2.mod_op = LDAP_MOD_DELETE;
attribute2.mod_values = fax_values;</pre>
*Use the mod_bvalues field rather than the mod_values field.
*Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.
 
'''Note:'''&nbsp;If you remove all values from the attribute, the attribute is removed from the entry.
 
You can set a NULL value for the attribute either by setting the mod_values field to NULL, or by setting the mod_bvalues field to NULL. When the mod_op field then contains LDAP_MOD_BVALUES, the attribute is removed from the entry.
 
===== Adding Values to an Attribute  =====
 
*Set the mod_type field to the attribute type that you want to add values to, such as audio.
*Set the mod_values field to the new values of the attribute.
*Set the value of the mod_op field to LDAP_MOD_ADD.
*Use the mod_bvalues field rather than the mod_values field, and put the values in berval structures.
*Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.
 
If the attribute does not already exist in the entry, the attribute is added to the entry.
 
The following code adds values to the audio attribute of an entry.
<pre>#include &lt;stdio.h&gt;
#include &lt;sys/stat.h&gt;
#include "ldap.h"
 
char *audio_data;
FILE *fp;
struct stat st;
LDAPMod attribute3;
struct berval audio_berval;
struct berval *audio_values[2];
 
/* Get information about the audio file, including its size. */
if ( stat( "my_sounds.au", st )&nbsp;!= 0 ) {
  perror( "stat" );
  return( 1 );
}
 
/* Open the audio file and read it into memory. */
if ( ( fp = fopen( "my_sounds.au", "rb" ) ) == NULL ) {
  perror( "fopen" );
  return( 1 );
}
 
if ( ( ( audio_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
      ( fread ( audio_data, st.st_size, 1, fp )&nbsp;!= 1 ) ) {
  perror( audio_data&nbsp;? "fread"&nbsp;: "malloc" );
  return( 1 );
}
 
fclose( fp );
attribute3.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
attribute3.mod_type = "audio";
audio_berval.bv_len = st.st_size;
audio_berval.bv_val = audio_data;
audio_values[0] = audio_berval;
audio_values[1] = NULL;
attribute3.mod_values = audio_values;</pre>
===== Removing an Attribute With Directory SDK for C  =====
 
*Remove all values from the attribute.
*Set the mod_op field to LDAP_MOD_REPLACE or LDAP_MOD_DELETE, and specify NULL for the mod_values field.
 
===== Adding an Attribute With Directory SDK for C  =====
 
If you add or replace values in an attribute that does not yet exist in the entry, the attribute is added to the entry.
 
==== Creating an Array of Changes  ====
 
After specifying the changes to attribute values in LDAPMod structures, you need to construct an array of these structures. You pass a pointer to this array as a parameter to the function for modifying the entry. The following example creates an array of LDAPMod structures.
<pre>#include "ldap.h"
 
LDAPMod *list_of_mods[4]
LDAPMod attribute1, attribute2, attribute3;
 
/* Code for filling the LDAPMod structures with values */
 
list_of_mods[0] = attribute1;
list_of_mods[1] = attribute2;
list_of_mods[2] = attribute3;
list_of_mods[3] = NULL;</pre>
==== Modifying an Entry in the Directory With Directory SDK for C  ====
 
*The synchronous ldap_modify_ext_s() function
*The asynchronous ldap_modify_ext() function
 
===== Synchronous Modify Operation  =====
 
If you want to wait for the results of the modify operation to complete before continuing, call the synchronous ldap_modify_ext_s() function. The function sends a modify request to the server. Also, the function blocks all work until the server sends the results of the operation back to your client. The function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.
 
The following example calls the synchronous ldap_modify_ext_s() function to modify the entry for the user William Jensen in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
 
LDAP      *ld;
LDAPMod  *mods[ 3 ];
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;
 
/* Perform the modify operation. */
rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_modify_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
} else {
  printf( "%s modified successfully.\n", MODIFY_DN );
}
ldap_unbind_s( ld );</pre>
The following sample program calls the synchronous ldap_modify_ext_s() function to modify a user entry in the directory. The program replaces the values of the mail attribute and adds a description attribute to the entry.
<pre>#include &lt;stdio.h&gt;
#include &lt;time.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP        *ld;
  LDAPMod      mod0, mod1;
  LDAPMod      *mods[ 3 ];
  char        *matched_msg = NULL, *error_msg = NULL;
  char        *vals0[ 2 ], *vals1[ 2 ];
  time_t      now;
  char        buf[ 128 ];
  int          rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Construct the array of LDAPMod structures representing the
  changes that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
mail attribute with the value "wbj@example.com". */
  mod0.mod_op = LDAP_MOD_REPLACE;
  mod0.mod_type = "mail";
  vals0[0] = "wbj@example.com";
  vals0[1] = NULL;
  mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the
  description attribute. If this attribute does not yet exist,
  the attribute ia added to the entry. */
  mod1.mod_op = LDAP_MOD_ADD;
  mod1.mod_type = "description";
  time( now );
  sprintf( buf, "This entry was modified with the modattrs program on&nbsp;%s",
  ctime( now ));
/* Get rid of \n which ctime put on the end of the time string */
  if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
    buf[ strlen( buf ) - 1 ] = '\0';
  }
  vals1[ 0 ] = buf;
  vals1[ 1 ] = NULL;
  mod1.mod_values = vals1;
  mods[ 0 ] = mod0;
  mods[ 1 ] = mod1;
  mods[ 2 ] = NULL;
/* Perform the modify operation. */
  rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_modify_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
  } else {
    printf( "%s modified successfully.\n", MODIFY_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}</pre>
===== Asynchronous Modify Operation  =====
 
If you want to perform other work in parallel while waiting for the entry to be modified, call the asynchronous ldap_modify_ext() function. This function sends a modify request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.
 
The ldap_modify_ext() function passes back a message ID identifying the modify operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the modify operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.
 
The following example calls the asynchronous ldap_modify_ext() function to modify the entry for the user William Jensen in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
 
LDAP      *ld;
LDAPMessage    *res;
LDAPMod      *mods[ 3 ];
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;
 
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Send the LDAP modify request. */
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_modify_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Poll the server for the results of the modify operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the
      modify operation. */
    finished = 1;
 
    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the LDAP modify operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_modify_ext:&nbsp;%s\n",
        ldap_err2string( rc ) );
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
      }
    } else {
      printf( "%s modified successfully.\n", MODIFY_DN );
    }
  }
}
ldap_unbind( ld );</pre>
The following sample program calls the asynchronous ldap_modify_ext() function to modify a user entry in the directory. The program replaces the values of the mail attribute and adds a description attribute to the entry.
<pre>#include &lt;stdio.h&gt;
#include &lt;time.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMessage    *res;
  LDAPMod        mod0, mod1;
  LDAPMod        *mods[ 3 ];
  LDAPControl    **serverctrls;
  char          *matched_msg = NULL, *error_msg = NULL;
  char          **referrals;
  char          *vals0[ 2 ], *vals1[ 2 ];
  time_t      now;
  char      buf[ 128 ];
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Construct the array of LDAPMod structures representing the changes
  that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
  mail attribute with the value "wbj@example.com". */
  mod0.mod_op = LDAP_MOD_REPLACE;
  mod0.mod_type = "mail";
  vals0[0] = "wbj@example.com";
  vals0[1] = NULL;
  mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the description
  attribute.  If this attribute does not yet exist, the attribute ia added
  to the entry. */
  mod1.mod_op = LDAP_MOD_ADD;
  mod1.mod_type = "description";
  time( now );
  sprintf( buf,
          "This entry was modified with the modattrs program on&nbsp;%s",
          ctime( now ));
/* Get rid of \n which ctime put on the end of the time string */
  if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
    buf[ strlen( buf ) - 1 ] = '\0';
  }
  vals1[ 0 ] = buf;
  vals1[ 1 ] = NULL;
  mod1.mod_values = vals1;
  mods[ 0 ] = mod0;
  mods[ 1 ] = mod1;
  mods[ 2 ] = NULL;
/* Send the LDAP modify request. */
  rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_modify_ext:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the modify operation. */
  while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that the server has still not yet sent the
        results of the modify operation back to your client.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for results. */
      break;
    default:
      /* The function has retrieved the results of the modify
        operation from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                  error_msg, referrals, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP add operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_modify_ext:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
      } else {
        printf( "%s modified successfully.\n"
          "Counted to&nbsp;%d while waiting for the modify operation.\n",
          MODIFY_DN, global_counter );
      }
    }
/* Do other work while waiting for the results of the modify operation. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
 
/*
* Perform other work while polling for results.  This doesn't do anything
* useful, but it could.
*/
void
do_other_work()
{
  global_counter++;
}</pre>
=== Deleting an Entry With Directory SDK for C  ===
 
*The synchronous ldap_delete_ext_s() function
*The asynchronous ldap_delete_ext() function<br>
 
==== Synchronous Delete Operation  ====
 
If you want to wait for the results of the delete operation to complete before continuing, call the synchronous ldap_delete_ext_s() function. This function sends a delete request to the server. The function also blocks all other processes until the server sends the results of the operation back to your client. The ldap_delete_ext_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.
 
The following example calls the synchronous ldap_delete_ext_s function to remove the entry for user William Jensen from the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
 
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int      rc;
 
/* Perform the delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
} else {
  printf( "%s deleted successfully.\n", DELETE_DN );
}
ldap_unbind_s( ld );</pre>
The following sample program calls the synchronous ldap_delete_ext_s() function to delete a user entry from the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the delete operation. */
  rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_delete_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
  } else {
    printf( "%s deleted successfully.\n", DELETE_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}</pre>
==== Asynchronous Delete Operation  ====
 
If you want to perform other work in parallel while waiting for the entry to be deleted, call the asynchronous ldap_delete_ext() function. This function sends a delete request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, an LDAP result code if an error occurred.
 
The ldap_delete_ext() function passes back a message ID identifying the delete operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the delete operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.
 
The following example calls the asynchronous ldap_delete_ext() function to remove the user William Jensen from the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
 
LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;
 
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Send the LDAP delete request. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Poll the server for the results of the delete operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
      break;
  default:
    /* The function has retrieved the results of the
      delete operation. */
      finished = 1;
 
    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
    /* Check the results of the LDAP delete operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n",
        ldap_err2string( rc ) );
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
    } else {
      printf( "%s deleted successfully.\n", DELETE_DN );
    }
  }
}
ldap_unbind( ld );</pre>
The following sample program calls the asynchronous ldap_delete_ext() function to delete a user entry from the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Send the LDAP delete request. */
  rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the delete operation. */
  while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that the server has still not yet sent the
        results of the delete operation back to your client.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for results. */
      break;
    default:
  /* The function has retrieved the results of the delete operation
    from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                  error_msg, referrals, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP delete operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_delete_ext:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
        }
      } else {
        printf( "%s deleted successfully.\n"
          "Counted to&nbsp;%d while waiting for the delete operation.\n",
          DELETE_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the
      delete operation. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
* Perform other work while polling for results.  This
* doesn't do anything useful, but it could.
*/
void
do_other_work()
{
    global_counter++;
}</pre>
=== Changing the DN of an Entry With Directory SDK for C  ===
 
*The synchronous ldap_rename_s() function
*The asynchronous ldap_rename() function
 
For both functions, you can choose to delete the attribute that represents the old relative distinguished name (RDN). You can also change the location of the entry in the directory tree.
 
==== Synchronous Renaming Operation  ====
 
If you want to wait for the results of the modify DN operation to complete before continuing, call the synchronous ldap_rename_s() function. This function sends a modify DN request to the server. The function also blocks other work until the server sends the results of the operation back to your client. The ldap_rename_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.
 
The following calls the synchronous ldap_rename_s() function to change the RDN of the entry for the user William Jensen in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
 
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;
 
/* Perform the modify DN operation. */
rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_rename_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
} else {
  printf( "%s renamed successfully.\n", OLD_DN );
}
ldap_unbind_s( ld );</pre>
==== Asynchronous Renaming Operation  ====
 
If you want to perform other work in parallel while waiting for the entry to be renamed, call the asynchronous ldap_rename() function. This function sends a modify DN request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.
 
The ldap_rename() function passes back a message ID identifying the modify DN operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the modify DN operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.
 
The following example calls the asynchronous ldap_rename() function to change the RDN of the user William Jensen in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
 
LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;
 
/* Timeout period for the ldap_result() function to wait
  for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Send the LDAP modify DN request. */
rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, msgid );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_rename:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
 
/* Poll the server for the results of the modify DN operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the
      modify DN operation. */
    finished = 1;
 
    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the LDAP modify DN operation. */
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_rename:&nbsp;%s\n", ldap_err2string( rc ) );
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
    } else {
      printf( "%s renamed successfully.\n", OLD_DN );
    }
  }
}
ldap_unbind( ld );</pre>
==== Deleting the Attribute From the Old RDN  ====
 
Both ldap_rename and ldap_rename_s() have a deleteoldrdn parameter that allows you to remove the old RDN from the entry. For example, suppose an entry has the following values for the cn attribute:
<pre>cn: Barbara Jensen
cn: Babs Jensen</pre>
Then the following function adds the second name and removes the first:
<pre>ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 1 );</pre>
The function adds Barbie Jensen to the list of values. The function removes the Barbara Jensen value. The resulting entry has the following values:
<pre>cn: Barbie Jensen
cn: Babs Jensen</pre>
Suppose 0 is passed for the deleteoldrdn parameter instead of 1:
<pre>ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 0 );</pre>
The Barbara Jensen value is not removed from the entry. The resulting entry has the following values:
<pre>cn: Barbie Jensen
cn: Babs Jensen
cn: Barbara Jensen</pre>
==== Changing the Location of the Entry  ====
 
Both ldap_rename() and ldap_rename_s() have a newparent parameter that allows you to specify a new location for the entry in the directory tree. For example, if you pass <tt>ou=Contractors,dc=example,dc=com</tt> as the newparent parameter when renaming the entry <tt>uid=bjensen,ou=People,dc=example,dc=com</tt>, the entry is moved under <tt>ou=Contractors,dc=example,dc=com</tt>. The new DN for the entry is <tt>uid=bjensen,ou=Contractors,dc=example,dc=com</tt>.
 
'''Note:''' Some LDAP servers do not support this feature. When you specify this argument, a server might return the LDAP result code LDAP_UNWILLING_TO_PERFORM, with the error message <tt>Server does not support moving of entries.</tt>
 
===== Synchronous Relocation of an Entry  =====
 
The following example calls the synchronous ldap_rename_s() function to change the RDN of a user entry in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the modify DN operation. */
  rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_rename_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
  } else {
    printf( "%s renamed successfully.\n", OLD_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}</pre>
===== Asynchronous Relocation of an Entry  =====
 
The following example calls the asynchronous ldap_rename() function to change the RDN of a user entry in the directory.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "dougy4444"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Send the LDAP modify DN request. */
  rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_rename:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the modify DN operation. */
  while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that the server has still not yet sent the
        results of the modify DN operation back to your client.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for results. */
      break;
    default:
  /* The function has retrieved the results of the modify DN operation
        from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
        error_msg, referrals, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP modify DN operation. */
      if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_rename:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
      } else {
        printf( "%s renamed successfully.\n"
          "Counted to&nbsp;%d while waiting for the modify DN operation.\n",
          OLD_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the
      modify DN operation. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
* Perform other work while polling for results.  This doesn't do
* anything useful, but it could.
*/
void
do_other_work()
{
    global_counter++;
}</pre>
== Comparing Attribute Values With Directory SDK for C  ==
 
This section describes how to compare the value of an attribute in an entry against a specified value.<br>
 
=== Functions for Comparing Attribute Values With Directory SDK for C  ===
 
Directory SDK for C has functions to determine if an attribute contains a certain string or binary value.
 
*The synchronous ldap_compare_s() function
*The asynchronous ldap_compare() function
*The synchronous ldap_compare_ext_s() function
*The asynchronous ldap_compare_ext() function<br>
 
=== Performing Synchronous Comparison Operations With Directory SDK for C  ===
 
You can wait for the results of the compare operation to complete before continuing. Call the synchronous ldap_compare_ext_s() function to compare values in berval structures or the synchronous ldap_compare_s() function to compare string values. These functions send a compare request to the server and block work until the server sends the results of the operation back to your client.
 
*LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
*LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.
 
An error code indicates that a problem has occurred during the operation.
 
The following example calls the synchronous ldap_compare_s() function to determine if an entry has the value bjensen@example.com in the mail attribute.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
...
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int      rc;
...
/* Perform the compare operation. */
rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
switch( rc ) {
case LDAP_COMPARE_TRUE:
  printf( "%s has the value&nbsp;%s in the&nbsp;%s attribute.\n", COMPARE_DN,
    COMPARE_VALUE, COMPARE_ATTR );
  break;
case LDAP_COMPARE_FALSE:
  printf( "%s does not have the value&nbsp;%s in the&nbsp;%s attribute.\n",
    COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
  break;
default:
  fprintf( stderr, "ldap_compare_s:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry:&nbsp;%s\n",
      matched_msg );
  }
  break;
}
ldap_unbind_s( ld );
...</pre>
The following sample program calls the synchronous ldap_compare_s() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
 
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind anonymously to the server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the compare operation. */
  rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
  switch( rc ) {
  case LDAP_COMPARE_TRUE:
    printf( "%s has the value&nbsp;%s in the&nbsp;%s attribute.\n",
      COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
    break;
  case LDAP_COMPARE_FALSE:
    printf( "%s does not have the value&nbsp;%s in the&nbsp;%s attribute.\n",
      COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
    break;
  default:
    fprintf( stderr, "ldap_compare_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry:&nbsp;%s\n",
        matched_msg );
    }
    break;
  }
  ldap_unbind_s( ld );
  return 0;
}</pre>
=== Performing Asynchronous Comparison Operations With Directory SDK for C  ===
 
You can perform other work in parallel while waiting for the comparison to complete. Call the asynchronous ldap_compare_ext() function to compare values in berval structures or the asynchronous ldap_compare function to compare string values. These functions send a compare request to the server and return an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.
 
Both functions pass back a message ID identifying the compare operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in the message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the compare operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.
 
*LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
*LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.
 
An error code indicates that a problem occurred during the operation.
 
The following example calls the asynchronous ldap_compare() function to determine if an entry has the value bjensen@example.com in the mail attribute.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
...
LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send the LDAP compare request. */
msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
if ( msgid  0 ) {
  fprintf( stderr, "ldap_compare:&nbsp;%s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
/* Poll the server for the results of the LDAP compare operation. */
while (&nbsp;!finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
 
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
 
  case 0:
      /* The timeout period specified by zerotime was exceeded, so
        call ldap_result() again and continue to poll for the
        results. */
    break;
 
  default:
    /* The client has received the results of the
      LDAP compare operation from the server. */
    finished = 1;
 
    /* Parse the results received from the server.*/
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result:&nbsp;%s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
 
    /* Check the results of the LDAP compare operation. */
    switch ( rc ) {
    case LDAP_COMPARE_TRUE:
      printf( "%s has the value&nbsp;%s in the&nbsp;%s attribute.\n",
        COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
      break;
    case LDAP_COMPARE_FALSE:
      printf( "%s does not have the value&nbsp;%s in the&nbsp;%s attribute.\n",
        COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
      break;
    default:
      fprintf( stderr, "ldap_compare:&nbsp;%s\n", ldap_err2string( rc ) );
      if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry:&nbsp;%s\n",
          matched_msg );
      }
      break;
    }
  }
}
...</pre>
The following sample program calls the asynchronous ldap_compare() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind anonymously to the server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, NULL, error_msg );
    if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
  /* Send the LDAP compare request. */
  msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
  if ( msgid  0 ) {
    fprintf( stderr, "ldap_compare:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the LDAP compare operation. */
  while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
        This means that your client has not yet received the
        results of the LDAP compare operation.
        Break out of this switch statement, and continue calling
        ldap_result() to poll for the results. */
      break;
    default:
      /* The client has received the results of the
        LDAP compare operation from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
        argument is a non-zero value, which indicates that the
        LDAPMessage structure will be freed when done.  (No need
        to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                  error_msg, referrals, serverctrls, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "ldap_parse_result:&nbsp;%s\n",
                ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP compare operation. */
      switch ( rc ) {
      case LDAP_COMPARE_TRUE:
        printf( "%s has the value&nbsp;%s in the&nbsp;%s attribute.\n"
          "Counted to&nbsp;%d while waiting for the compare operation.\n",
          COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
        break;
      case LDAP_COMPARE_FALSE:
        printf( "%s does not have the value&nbsp;%s in the&nbsp;%s attribute.\n"
          "Counted to&nbsp;%d while waiting for the compare operation.\n",
          COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
        break;
      default:
        fprintf( stderr, "ldap_compare:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( error_msg&nbsp;!= NULL  *error_msg&nbsp;!= '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg&nbsp;!= NULL  *matched_msg&nbsp;!= '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry:&nbsp;%s\n",
            matched_msg );
        }
        break;
      }
    }
    /* Do other work while waiting for the results of the
      compare operation. */
    if (&nbsp;!finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
* Perform other work while polling for results.  This
* doesn't do anything useful, but it could.
*/
void
do_other_work()
{
    global_counter++;
}</pre>
== LDAP URLs With Directory SDK for C  ==
 
This section describes how to use LDAP URLs to search and retrieve data from the directory.
 
=== Checking an LDAP URL With Directory SDK for C  ===
 
To determine whether a URL is an LDAP URL, call the ldap_is_ldap_url() function. This function returns a nonzero value if the URL is an LDAP URL. If the URL is not an LDAP URL, the function returns 0. The following example determines if a URL is an LDAP URL.<br>
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
char *my_url = "ldap://ldap.example.com/dc=example,dc=com";
...
if ( ldap_is_ldap_url( my_url )&nbsp;!= 0 ) {
printf( "%s is an LDAP URL.\n", my_url );
} else {
printf( "%s is not an LDAP URL.\n", my_url );
}
...
</pre>
ldap_is_ldap_url() determines whether a URL is an LDAP URL. To verify that an LDAP URL complies with the LDAP URL syntax, you should call the ldap_url_parse() function as detailed in Getting the Components of an LDAP URL With Directory SDK for C.<br>
 
=== Getting the Components of an LDAP URL With Directory SDK for C  ===
 
To retrieve the individual components of an LDAP URL, call ldap_url_parse(). This function returns the LDAP URL components in an LDAPURLDesc structure as shown in this example.<br>
<pre>typedef struct ldap_url_desc {
  char *lud_host;
  int lud_port;
  char *lud_dn;
  char **lud_attrs;
  int lud_scope;
  char *lud_filter;
  unsigned long lud_options;
} LDAPURLDesc;
</pre>
The following list describes the structure's fields.<br>
 
*lud_host: The name of the host in the URL.
*lud_port: The number of the port in the URL.
*lud_dn: The distinguished name in the URL.
*lud_attrs:&nbsp;A pointer to a NULL terminated array of the attributes specified in the URL.
*lud_scope:<br>LDAP_SCOPE_BASE specifies a search of the base entry.<br>LDAP_SCOPE_ONELEVEL specifies a search of all entries one level under the base entry, not including the base entry.<br>LDAP_SCOPE_SUBTREE specifies a search of all entries at all levels under the base entry, including the base entry.
*lud_filter: Search filter included in the URL.
*lud_options: Options. If LDAP_URL_OPT_SECURE, indicates that the protocol is ldaps:// instead of ldap://.<br>
 
The following example parses an LDAP URL.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
char *my_url =
  "ldap://ldap.example.com:1389/dc=example,dc=com?
  cn,mail,telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) )&nbsp;!= 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL missing trailing slash after host or port\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "Components of the URL:\n" );
printf( "Host name:&nbsp;%s\n", ludpp-&gt;lud_host );
printf( "Port number:&nbsp;%d\n", ludpp-&gt;lud_port );
if ( ludpp-&gt;lud_dn&nbsp;!= NULL ) {
  printf( "Base entry:&nbsp;%s\n", ludpp-&gt;lud_dn );
} else {
  printf( "Base entry: Root DN\n" );
}
if ( ludpp-&gt;lud_attrs&nbsp;!= NULL ) {
  printf( "Attributes returned: \n" );
  for ( i=0; ludpp-&gt;lud_attrs[i]&nbsp;!= NULL; i++ ) {
    printf( "\t%s\n", ludpp-&gt;lud_attrs[i] );
  }
} else {
  printf( "No attributes returned.\n" );
}
printf( "Scope of the search: " );
switch( ludpp-&gt;lud_scope ) {
  case LDAP_SCOPE_BASE:
    printf( "base\n" );
    break;
  case LDAP_SCOPE_ONELEVEL:
    printf( "one\n" );
    break;
  case LDAP_SCOPE_SUBTREE:
    printf( "sub\n" );
    break;
  default:
    printf( "Unknown scope\n" );
}
printf( "Filter:&nbsp;%s\n", ludpp-&gt;lud_filter );
...</pre>
This code prints each component of the URL as shown in the following example.
<pre>Components of the URL:
Host name: ldap.example.com
Port number: 1389
Base entry: dc=example,dc=com
Attributes returned:
  cn
  mail
  telephoneNumber
Scope of the search: sub
Filter: (sn=Jensen)</pre>
=== Freeing the Components of an LDAP URL With Directory SDK for C  ===
 
When you have finished working with the components of an LDAP URL, you should free the LDAPURLDesc structure from memory by calling the ldap_free_urldesc() function. The following example parses an LDAP URL. The example then frees the LDAPURLDesc structure from memory, after verifying that the LDAP URL is valid.
<pre>#include stdio.h&gt;
#include "ldap.h"
...
char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,
                telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) )&nbsp;!= 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL does not contain a distinguished name\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "URL is a valid LDAP URL\n" );
ldap_free_urldesc( ludpp );
...</pre>
=== Processing an LDAP URL With Directory SDK for C  ===
 
To process an LDAP URL search request, call one of the following functions:
 
*ldap_url_search_s() is a synchronous function that completes the search operation before returning. Call this function if you need to wait for the operation to finish before continuing other work. The function returns LDAP_SUCCESS if the operation completed successfully. If an error occurred, the function returns an error code.
*ldap_url_search_st() is a synchronous function that allows a certain amount of time for the completion of the search operation. Call this function to wait for the operation to complete, and to set a timeout period for the operation.
*ldap_url_search() is an asynchronous function that initiates the search operation but does not wait for the operation to complete. Call this function if you want to perform other work in parallel while waiting for the operation to complete. The function returns a message ID identifying the search operation. To determine whether the operation is completed or still in progress, call the ldap_result() function.<br>
 
After the operation is completed, call the ldap_result2error() function to determine if the operation was successful. If the operation completed successfully, the ldap_result2error() function returns LDAP_SUCCESS. If an error occurred, the function returns an error code.<br>
 
The following example processes a search request from an LDAP URL.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result;
char *my_url = "ldap://ldap.example.com/dc=example,dc=com?cn,mail,
                telephoneNumber?sub?(sn=Jensen)";
/* Process the search request in the URL. */
if ( ldap_url_search_s( ld, my_url, 0, result )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_url_search_s" );
  return( 1 );
}</pre>
== Getting Server Information With Directory SDK for C  ==
 
This section explains how to access and modify information about your LDAP server over the LDAP protocol.<br>
 
=== Reading DSEs With Directory SDK for C  ===
 
A DSA-specific entry, ''DSE'', contains information specific to the server. In a directory tree, the root of the tree is the root DSE. The root DSE is not part of any naming context. For example, the root DSE is superior to dc=example,dc=com in the directory tree.
 
The root DSE is specified as part of LDAP v3. Note that LDAP v2 servers do not necessarily have a root DSE.
 
*The naming contexts of this server, such as dc=example,dc=com
*URLs of alternate servers to contact if this server is unavailable
*The versions of LDAP supported by this server, version 2 or version 3
*The LDAP v3 controls supported by the server<br>
*The SASL mechanisms supported by the server<br>
*The LDAP v3 extended operations supported by the server<br>
 
The following list describes root DSE attributes and explains the meaning of their values.<br>
 
*namingContexts: The naming contexts supported by this server, such dc=example,dc=com.
*altServer: LDAP URLs that identify other servers to contact if this server is unavailable.
*supportedExtension: The object identifiers (OIDs) of the LDAP v3 extended operations supported by this server.<br>If this attribute is not in the root DSE, the server does not support any extended operations.
*supportedControl: The OIDs of the LDAP v3 controls supported by this server.<br>If this attribute is not in the root DSE, the server does not support any LDAP v3 controls.
*supportedSASLMechanisms: The names of the SASL mechanisms supported by the server.<br>If this attribute is not in the root DSE, the server does not support any SASL mechanisms.
*supportedLDAPVersion: The value of this attribute is the version of LDAP supported by this server, such as 2 or 3.<br>
 
'''To Get the Root DSE'''
 
#Initialize an LDAP session by calling the ldap_init() or prldap_init() function.
#Turn off automatic referral handling by calling the ldap_set_option() function and setting the LDAP_OPT_REFERRALS option to LDAP_OPT_OFF.
#Search the directory with the following criteria:
##Set the search scope to a base search.
##Specify an empty string for the base DN.
##Use the search filter <tt>(objectclass=*)</tt>.
#Check the results of the search.<br>If the server returns a result code, such as LDAP_OPERATIONS_ERROR, LDAP_PROTOCOL_ERROR, LDAP_REFERRAL, or LDAP_NO_SUCH_OBJECT, the LDAP server probably does not support LDAP v3.
 
The following example gets the root DSE for a server and prints the values of the root DSE attributes. The function assumes that you are passing in a valid connection handle, an LDAP structure, you have created by calling ldap_init() or prldap_init(). The function returns 0 if successful or 1 if an error occurred.
<pre>int printdse( LDAP *ld )
{
  int rc, i;
  char *matched_msg = NULL, *error_msg = NULL;
  LDAPMessage  *result, *e;
  BerElement  *ber;
  char    *a;
  char    **vals;
  char    *attrs[3];
  /* Verify that the connection handle is valid. */
  if ( ld == NULL ) {
    fprintf( stderr, "Invalid connection handle.\n" );
    return( 1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF )&nbsp;!= 0 ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option:&nbsp;%s\n", ldap_err2string( rc ) );
    return( 1 );
  }
  /* Search for the root DSE. */
  attrs[0] = "supportedControl";
  attrs[1] = "supportedExtension";
  attrs[2] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
                          attrs, 0, NULL, NULL, NULL, 0, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
    with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    printf( "LDAP server returned result code&nbsp;%d (%s).\n"
      "This server does not support the LDAPv3 protocol.\n",
      rc, ldap_err2string( rc ) );
    return( 1 );
  /* If any other value is returned, an error must have occurred. */
  default:
    fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    return( 1 );
  }
  /* Since only one entry should have matched, get that entry. */
  e = ldap_first_entry( ld, result );
  if ( e == NULL ) {
    fprintf( stderr, "ldap_search_ext_s: Unable to get root DSE.\n");
    ldap_memfree( result );
    return( 1 );
  }
 
  /* Iterate through each attribute in the entry. */
  for ( a = ldap_first_attribute( ld, e, ber );
    a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
 
    /* Print each value of the attribute. */
    if ((vals = ldap_get_values( ld, e, a))&nbsp;!= NULL ) {
      for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
        printf( "%s:&nbsp;%s\n", a, vals[i] );
      }
 
      /* Free memory allocated by ldap_get_values(). */
      ldap_value_free( vals );
    }
 
    /* Free memory allocated by ldap_first_attribute(). */
    ldap_memfree( a );
  }
 
  /* Free memory allocated by ldap_first_attribute(). */
  if ( ber&nbsp;!= NULL ) {
    ber_free( ber, 0 );
  }
 
  printf( "\n" );
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}</pre>
=== Determining LDAP v3 Support With Directory SDK for C  ===
 
You can determine what version an LDAP server supports by getting the supportedLDAPVersion attribute from the root DSE. This attribute could contain the value 2 or 3.
 
You do not need to authenticate or bind before searching the directory. Unlike LDAP v2, LDAP v3 states that clients do not need to bind to the server before performing LDAP operations.
 
The following example connects to an LDAP server. The example code then determines whether the server supports LDAP v3.
<pre>/* Function for determining if the LDAP server supports LDAPv3.
  This function returns 1 if the server supports LDAPv3 or
  0 if the server does not support LDAPv3.
*/
int
check_version( char *hostname, int portnum )
{
  LDAP    *ld;
  int    i, rc, v3supported = 0;
  LDAPMessage  *result, *e;
  BerElement  *ber;
  LDAPControl  **serverctrls = NULL, **clntctrls = NULL;
  char    *a, *dn;
  char    **vals;
  char    *attrs[2];
  char    *filter = "(objectClass=*)";
  /* Check arguments */
  if (&nbsp;!hostname ||&nbsp;!hostname[0] ||&nbsp;!portnum ) {
    printf( "Error: hostname or port number not specified\n" );
    return( -1 );
  }
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( hostname, portnum )) == NULL ) {
    perror( "ldap_init" );
    return( -1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF)&nbsp;!=
      LDAP_SUCCESS) {
    ldap_perror( ld, "ldap_set_option" );
    return( -1 );
  }
  /* Search for the root DSE and get the supportedLDAPVersion attribute. */
  attrs[0] = "supportedLDAPVersion";
  attrs[1] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, filter, attrs, 0,
    serverctrls, clntctrls, NULL, 0, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
    with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( 0 );
    break;
  /* If an different result code is returned, an error may have
    occurred (for example, the server may be down. */
  default:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( -1 );
    break;
  }
  /* Get the values of the supportedLDAPVersion attribute in the entry. */
  if (( e = ldap_first_entry( ld, result ))&nbsp;!= NULL 
      ( a = ldap_first_attribute( ld, e, ber ))&nbsp;!= NULL 
      (vals = ldap_get_values( ld, e, a))&nbsp;!= NULL ) {
    for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
      if (&nbsp;!strcmp( "3", vals[i] ) ) {
        v3supported = 1;
        break;
      }
    }
    /* Free any memory allocated. */
    ldap_value_free( vals );
    ldap_memfree( a );
    if ( ber&nbsp;!= NULL ) {
      ber_free( ber, 0 );
    }
  }
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  /* Free the ld structure. */
  ldap_unbind_s( ld );
  /* Return a value indicating whether or not LDAPv3 is supported. */
  return( v3supported );
}
...</pre>
=== Getting Schema Information With Directory SDK for C  ===
 
In LDAP v3, an entry can specify the schema that defines the object classes, attributes, and matching rules used by the directory. This entry is called the subschema entry. To find the DN of the subschema entry, get the subschemaSubentry operational attribute from the root DSE or any entry.
 
*objectClasses specifies the object class definitions in the schema. Each value of this attribute is an object class that is known to the server.
*attributeTypes specifies the attribute type definitions in the schema. Each value of this attribute is an attribute type that is known to the server.
*matchingRules specifies the matching rule definitions in the schema. Each value of this attribute is a matching rule that is known to the server.
*matchingRuleUse specifies the use of a matching rule in the schema. This rule specifies the attributes that can be used with this extensible matching rule. Each value of this attribute is a matching rule use description.
 
For information about the format of the attribute values, see RFC 4517, ''Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions''.<br>
 
== SSL Connections With Directory SDK for C<br>  ==
 
This chapter describes the process of enabling an LDAP client to connect to an LDAP server over the Secure Sockets Layer (SSL) protocol.<br>
 
=== How SSL Works With Directory SDK for C  ===
 
The primary goal of the SSL protocol is to provide privacy and reliability between two communicating applications.
 
'''Note:''' SSL is not supported on all LDAP servers.<br>SSL communication must take place on a separate TCP port unless the server supports Start TLS.
 
When an LDAP client connects to an LDAP server over SSL, the server identifies itself by sending a certificate to the client. The client needs to determine whether or not the certificate authority (CA) that issued the certificate is trusted. The client therefore searches a certificate database for the certificate of the CA. If the client cannot find the certificate, the client refuses to connect to the server. If the certificate is marked ''not trusted'', the client also refuses to connect to the server.
 
The LDAP server can also request that the client send a certificate to authenticate itself. This part of the process is called ''certificate-based client authentication''. If the client receives a request for a certificate from the server, the client retrieves its certificate from the certificate database. The client sends the certificate to the server for authentication. After receiving the clients certificate, the LDAP server determines whether or not the CA that issued the certificate is trusted. If the server cannot find the CA certificate in the certificate database, the server refuses to authenticate the client. If the CA certificate is marked as ''not trusted'', the server also refuses to authenticate the client. If the CA is trusted, the server uses the certificate subject name to determine whether the client has access to perform the requested operation.
 
*Your client has access to a certificate database. The function call uses this certificate database to determine if the client can trust the certificate sent from the server.<br>Different certificate database versions can be incompatible, which might result in database errors.
**The certificate of the CA that issued the servers certificate
**If the CAs are organized in a hierarchy, the certificate of any of the CAs in the hierarchy
**The certificate of the LDAP server
*The CA certificate is marked as trusted in the certificate database.
**A client certificate in the certificate database issued by a CA that is trusted by the LDAP server
**A public-private key pair in a key file
*Set the session option for communicating with the server over SSL.<br>
*Start transport layer security by using the Start TLS extended operation.<br>
*Replace the default I/O functions with your own I/O functions for communicating over SSL.<br>
*Enable your client to send certificates to authenticate itself.<br>
 
=== Connecting to a Server Over SSL With Directory SDK for C  ===
 
To enable your LDAP client to connect to an LDAP server with SSL, you need to perform the following procedure.
 
'''To Initialize a Client SSL Connection by Using ldapssl_init()'''
 
#Initialize your client by calling one of the following functions:
#*Call ldapssl_client_init() if you do not plan to use certificate-based client authentication.
#*Call ldapssl_clientauth_init() if you plan to use certificate-based client authentication.
#*Call ldapssl_advclientauth_init().<br>If you use certificate-based client authentication, you need to specify the path of the security module database, or to specify the method to verify the server certificate.<br>You must initialize your client before initializing the LDAP session. The process of initializing the client opens the certificate database.
#Initialize an LDAP session with the secure server by calling the ldapssl_init() function.<br>For an alternative way to accomplish this step, see Alternative to ldapssl_init().
 
This example initializes a client to connect to a secure LDAP server over SSL.
<pre>if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* get a handle to an LDAP connection */
if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL {
  perror( "ldapssl_init" );
  return( 1 );
}
...
/* Client can now perform LDAP operations on the secure LDAP server. */
...</pre>
==== Alternative to ldapssl_init()  ====
 
As an alternative to calling the ldapssl_init() function, you can use the following procedure.
 
'''To Initialize a Client SSL Connection (Alternative Method Using ldap_init())'''
 
#After initializing your client, initialize an LDAP session with the server by calling the standard initialization function ldap_init().
#Install the standard SSL I/O functions by calling ldapssl_install_routines().
#Set the SSL option in the LDAP structure by calling ldap_set_option().
 
This example prepares a client to connect to a secure LDAP server over SSL using ldap_init().
<pre>if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* Initialize LDAP session. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, LDAPS_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
 
/* Load SSL routines */
if ( ldapssl_install_routines( ld )&nbsp;!= 0 ) {
  ldap_perror( ld, "ldapssl_install_routines" );
  return( 1 );
}
/* Set up option in LDAP struct for using SSL */
if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON )&nbsp;!= 0 ) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
/* Client can now perform LDAP operations on the secure LDAP server. */
...</pre>
=== Handling Errors With Directory SDK for C  ===
 
After calling any of the SSL initialization functions, you can convert SSL-specific error codes to text strings by calling ldapssl_err2string(). The ldapssl_err2string() function provides support for special SSL error messages that are not handled by the normal error conversion routine ldap_err2string().
 
=== Starting Transport Layer Security With Directory SDK for C  ===
 
RFC 4513, ''Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms'', describes the extended operation. Start TLS allows you to connect to a nonsecure port, and then request transport layer security.
 
'''To Use Start TLS'''
 
Initialize your client with ldapssl_client_init().
 
#The process of initializing the client opens the certificate database.
#Get a handle to an LDAP connection.
#Request Start TLS with ldap_start_tls_s().
#Authenticate to the directory to perform additional operations.
 
This example connects and uses Start TLS, then requests the Who am I? extended operation. The example relies on a certificate database directory, <tt>/local/examples/alias/</tt>.
<pre>/*
* Use the Start TLS extended operation.
*/
 
#include "examples.h"
#include &lt;ldap_ssl.h&gt;
 
/*
* Path to certificate database for SSL
*/
#define CERT_DB_PATH    "/local/examples/alias/"
 
int
main( int argc, char **argv )
{
    int            version;
    LDAP            *ld;
    int            rc;
    char            *authzid;
 
    /* Initialize access to the certificate database. */
    if ( ldapssl_client_init( CERT_DB_PATH, NULL )&nbsp;!= 0 ) {
        fprintf( stderr, "ldapssl_client_init failed\n" );
        fprintf( stderr, "certificate database path:&nbsp;%s\n", CERT_DB_PATH );
        return( 1 );
    }
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
        fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
        return( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Request Start TLS. */
    if ( ldap_start_tls_s( ld, NULL, NULL )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_start_tls_s" );
        return( 1 );
    }
    printf( "Start TLS operation successful.\n" );
 
    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Examine my authorization ID. */
    if ( (rc = ldap_whoami_s( ld, NULL, NULL, authzid ) )
        &nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_whoami_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    printf( "Authorization ID:&nbsp;%s\n", authzid );
 
    ldap_unbind( ld );
    return( 0 );
}</pre>
To troubleshoot Start TLS problems, call the PR_GetError() function. This function gives you access to many Network Security Services (NSS) errors further documented in the [http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html Mozilla.org SSL Reference].
 
=== Installing Your Own SSL I/O Functions With Directory SDK for C ===
 
The ldapssl_init() and ldapssl_install_routines() functions both set up the session to use the standard SSL I/O functions provided with Directory SDK for C. If you want to use your own SSL I/O functions, use the ldap_x_ext_io_fns() structure.
 
'''To Install Your Own SSL I/O Functions'''
 
#Create an ldap_x_ext_io_fns structure, and set the fields to point to your I/O functions.
#Call ldap_set_option to point to that structure.
<pre>if (ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, my_io_struct) != 0 ) {
&nbsp;&nbsp;    ldap_perror( ld, "ldap_set_option" );
&nbsp;&nbsp;    return( 1 );
}
</pre>
=== Using Certificate-Based Client Authentication With Directory SDK for C ===
 
Some LDAP servers can be configured to use certificate-based client authentication. The server requests that your client send a certificate to identify itself. Use the following procedure to configure your client to use certificates for authentication.
 
'''To Use Certificate-Based Client Authentication'''
 
#Initialize your LDAP client by calling either ldapssl_clientauth_init() or ldapssl_advclientauth_init(), not ldapssl_client_init().<br>Use ldapssl_advclientauth_init() if you want to specify the path of a security module database, or to specify the method used to verify the server certificate.<br>You can use one of these functions to initialize your client even if you do not plan to use certificate-based client authentication. The functions are equivalent to ldapssl_client_init().
#Initialize an LDAP session with the secure server by calling ldapssl_init().
#Enable your client to authenticate with the secure server by calling ldapssl_enable_clientauth().
#Perform a Simple Authentication and Security Layer (SASL) bind operation by using the mechanism EXTERNAL. This mechanism indicates to the directory server that certificates should be used to authenticate clients.<br>With Directory Server, if you perform a SASL bind operation, but the server cannot find the corresponding directory entry for a client certificate, the server returns an LDAP_INVALID_CREDENTIALS result code with the error message Client Certificate Mapping Failed.<br>
 
== LDAP Controls With Directory SDK for C<br>  ==
 
This section explains how LDAP controls work and how to use them.<br>
 
=== How LDAP Controls Work With Directory SDK for C  ===
 
LDAP v3, as documented in RFC 4511, allows clients and servers to use controls as a mechanism for extending an LDAP operation. A control is a way to specify additional information as part of a request and a response. For example, a client can send a control to a server as part of a search request. The control indicates that the server should sort the search results before sending the results back to the client.
 
Servers can also send controls back to clients. For example, Directory Server can send a control back to a client to indicate that the client password has expired, or that the password is going to expire.
 
*A unique object identifier (OID) as defined by the creator of the control<br>The OID identifies the control.
*An indication of whether or not the control is critical to the operation
*Optional data related to the control<br>For example, the server-side sort control needs the attributes that would be used for sorting search results.
*If the server supports the control, and if the control is appropriate, the server should make use of the control when performing the operation.
**If the control is marked as critical to the operation, the server should not perform the operation. Instead, the server should return the result code LDAP_UNAVAILABLE_CRITICAL_EXTENSION.
**If the control is not marked as critical to the operation, the server should ignore the control and perform the operation.
 
If you plan to use a control, make sure that the server supports the control.
 
=== Using Controls in the LDAP API  ===
 
Server controls can be included in requests sent by clients and in responses sent by servers.
 
Client controls affect the behavior of the SDK only and are never sent to the server.
 
In the SDK, a control is represented by an LDAPControl structure.
 
*ldctl_oid specifies the OID of the control.
*ldctl_value contains a berval structure that contains data that is associated with the control.
*ldctl_iscritical specifies whether or not the control is critical to the operation. LDAP_OPT_ON indicates that the control is critical. LDAP_OPT_OFF indicates that the control is not critical.
 
The following shows the LDAPControl structure definition.
<pre>typedef struct ldapcontrol {
  char                *ldctl_oid;
  struct berval      ldctl_value;
  char                ldctl_iscritical;
} LDAPControl;</pre>
You can allocate space for the control, then create the control yourself. You can also call a function to create the control. For example, you can call the ldap_create_sort_control() function to create a server-side sorting control. To include a control in a request, call one of the LDAP v3 API functions, which are functions with names that end with _ext() and _ext_s(). These functions allow you to pass in an array of server controls and an array of client controls.
 
You can also include controls in a request by specifying the array of controls in the LDAP_OPT_SERVER_CONTROLS option. However, these controls are sent to the server with every request. If the control is specific to a certain type of operation, you should use functions with names that end with _ext() and _ext_s() instead.
 
To retrieve any controls included in a servers response, call the ldap_parse_result() function. You can then retrieve data from the returned controls yourself by checking the fields of the LDAPControl structure or by calling additional functions such as ldap_parse_sort_control().
 
After working with a control, or with an array of controls, free the controls from memory. Call ldap_control_free() or ldap_controls_free() function.
 
=== Determining the Controls Supported by the Server With Directory SDK for C  ===
 
According to LDAP v3, servers should list any controls that the server supports in the supportedControl attribute in the root DSE.
 
The following list shows OIDs for server controls that might be referenced in the supportedControl attribute.<br>
 
*1.2.840.113556.1.4.473, 1.2.840.113556.1.4.474: Server-Side Sort (LDAP_CONTROL_SORTREQUEST, LDAP_CONTROL_SORTRESPONSE)<br>
*1.3.6.1.4.1.42.2.27.8.5.1: Password Policy (LDAP_CONTROL_PASSWD_POLICY)<br>
*1.3.6.1.4.1.42.2.27.9.5.2: Get Effective Rights Request (LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST)<br>
*1.3.6.1.4.1.42.2.27.9.5.8: Account Availability (LDAP_CONTROL_ACCOUNT_USABLE)<br>
*2.16.840.1.113730.3.4.2: Manage DSA IT (LDAP_CONTROL_MANAGEDSAIT)<br>
*2.16.840.1.113730.3.4.3: Persistent Search (LDAP_CONTROL_PERSISTENTSEARCH)<br>
*2.16.840.1.113730.3.4.7: Entry Change Notification (LDAP_CONTROL_ENTRYCHANGE)<br>
*2.16.840.1.113730.3.4.4: Password Expired (LDAP_CONTROL_PWEXPIRED)<br>
*2.16.840.1.113730.3.4.5: Password Expiring (LDAP_CONTROL_PWEXPIRING)<br>
*2.16.840.1.113730.3.4.9, 2.16.840.1.113730.3.4.10: Virtual List View (LDAP_CONTROL_VLVREQUEST, LDAP_CONTROL_VLVRESPONSE)<br>
*2.16.840.1.113730.3.4.12, 2.16.840.1.113730.3.4.18: Proxied Authorization (LDAP_CONTROL_PROXYAUTH, LDAP_CONTROL_PROXIEDAUTH)<br>
*2.16.840.1.113730.3.4.15, 2.16.840.1.113730.3.4.16: Authorization Identity Bind Request (LDAP_CONTROL_AUTHZID_RES, LDAP_CONTROL_AUTHZID_REQ)<br>Also known as LDAP_CONTROL_AUTH_RESPONSE, LDAP_CONTROL_AUTH_REQUEST.<br>
*2.16.840.1.113730.3.4.17: Real Attributes Only Request (LDAP_CONTROL_REAL_ATTRS_ONLY)<br>
*2.16.840.1.113730.3.4.19: Virtual Attributes Only Request (LDAP_CONTROL_VIRTUAL_ATTRS_ONLY)<br>
 
The following sample command-line program searches for the root DSE. The program then prints the values of the supportedControl attribute.
<pre>#include "ldap.h"
static char *usage = "Usage: listctrl -h hostname -p portnumber\n";
 
/* Associate OIDs of known controls with descriptions. */
struct oid2desc {
  char  *oid;
  char  *desc;
};
static struct oid2desc oidmap[] = {
  {LDAP_CONTROL_ACCOUNT_USABLE, "Account availability control"}
  {LDAP_CONTROL_AUTH_REQUEST, "Authorization bind identity request"}
  {LDAP_CONTROL_AUTH_RESPONSE, "Authorization bind identity response"}
  {LDAP_CONTROL_ENTRYCHANGE, "Entry change notification control"}
  {LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, "Get effective rights control"}
  {LDAP_CONTROL_MANAGEDSAIT, "Manage DSA IT control"}
  {LDAP_CONTROL_PASSWD_POLICY, "Password policy control"}
  {LDAP_CONTROL_PERSISTENTSEARCH, "Persistent search control"}
  {LDAP_CONTROL_PROXIEDAUTH, "Proxied authorization (version 2) control"}
  {LDAP_CONTROL_PROXYAUTH, "Proxied authorization (version 1) control"}
  {LDAP_CONTROL_PWEXPIRED, "Password expired control"}
  {LDAP_CONTROL_PWEXPIRING, "Password expiring control"}
  {LDAP_CONTROL_REAL_ATTRS_ONLY, "Real attributes only control"}
  {LDAP_CONTROL_SORTREQUEST, "Server-side sort request control"}
  {LDAP_CONTROL_SORTRESPONSE, "Server-side sort response control"}
  {LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, "Virtual attributes only control"}
  {LDAP_CONTROL_VLVREQUEST, "Virtual list view request control"}
  {LDAP_CONTROL_VLVRESPONSE, "Virtual list view response control"}
  {NULL, NULL}
};
 
int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMessage  *result, *e;
  char          *hostname = NULL;
  char          **vals;
  char          *attrs[2];
  int          i, j, c, portnumber = LDAP_PORT, rc;
  LDAPControl  **serverctrls = NULL, **clntctrls = NULL;
  /* Parse the command line arguments. */
  while ( ( c = getopt( argc, argv, "h:p:" ) )&nbsp;!= -1 ) {
    switch ( c ) {
    case 'h':
      hostname = strdup( optarg );
      break;
    case 'p':
      portnumber = atoi( optarg );
      break;
    default:
      printf( "Unsupported option:&nbsp;%c\n", c );
      printf( usage );
      exit( 1 );
    }
  }
  /* By default, connect to localhost at port 389. */
  if ( hostname == NULL || hostname[0] == NULL ) {
      hostname = "localhost";
  }
  /* Initialize the connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( hostname, portnumber )) == NULL ) {
      perror( "ldap_init" );
      return( 1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF )
  &nbsp;!= LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_set_option" );
      return( 1 );
  }
  /* Search for the root DSE and retrieve only the
    supportedControl attribute. */
  attrs[ 0 ] = "supportedControl";
  attrs[ 1 ] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
    attrs, 0, serverctrls, clntctrls, NULL, NULL, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
    with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    printf( "LDAP server&nbsp;%s:%d returned result code&nbsp;%d (%s).\n"
    "This server does not support the LDAPv3 protocol.\n",
    hostname, portnumber, rc, ldap_err2string( rc ) );
    return( 1 );
    break;
  /* If any other value is returned, an error must have occurred. */
  default:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( 1 );
    break;
  }
  /* Get the root DSE from the results.
    Since there is only one root DSE, there
    should be only one entry in the results. */
  e = ldap_first_entry( ld, result );
  /* Get and print the values of the supportedControl attribute. */
  if (e&nbsp;!= NULL
    (vals = ldap_get_values(ld, e, "supportedControl"))&nbsp;!= NULL ) {
    printf( "\nControls Supported by&nbsp;%s:%d\n", hostname, portnumber );
    printf( "==================================================\n" );
    for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
      printf( "%s\n", vals[i] );
      for ( j = 0; oidmap[j].oid&nbsp;!= NULL; j++ ) {
        if (&nbsp;!strcmp( vals[i], oidmap[j].oid )) {
          printf( "\t%s\n", oidmap[j].desc );
        }
      }
    }
    /* Free the values allocated by ldap_get_values(). */
    ldap_value_free( vals );
    printf( "\n" );
  }
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}</pre>
=== Using the Server-Side Sorting Control With Directory SDK for C  ===
 
The control with OID 1.2.840.113556.1.4.473, or LDAP_CONTROL_SORTREQUEST as defined in the ldap.h header file, is a server-side sorting control. When you send a search request with this control to the server, the server should sort the results before sending the results back to you.
 
The server-side sorting control is described in RFC 2891.
 
==== Specifying the Sort Order With Directory SDK for C  ====
 
To specify the sort order of the results, call the ldap_create_sort_keylist function to create a sort key list from a string in the following format:
<pre>[-]''attr-name''[:''matching-rule-oid'']
</pre>
*''attr-name'' is the name of the attribute to sort by.<br>You can specify a space-delimited list of attribute names.
*''matching-rule-oid'' is the optional OID of a matching rule that you want to use for sorting.<br>
<pre>sn -givenname
</pre>
*The minus sign indicates that the results should be sorted in reverse order for that attribute. For example, the following string specifies that results should be sorted by last name, sn, first in ascending order. If multiple entries have the same last name, these entries are sorted by first name, givenname, in descending order.
 
Pass this string to ldap_create_sort_keylist() to create a sort key list, which is an array of LDAPsortkey structures. You can use this technique to create the server-side sorting control.<br>
 
==== Creating the Server-Side Sorting Control With Directory SDK for C  ====
 
Next, to create the server-side sorting control, you pass the sort key list, the array of LDAPsortkey structures, to the ldap_create_sort_control() function. The function passes back a newly created sort control, an LDAPControl structure that you can include in a search request.
 
You can specify whether or not the control is critical to the search operation. If the control is marked as critical, but the server cannot sort the results, the server should not send back any entries. See Interpreting the Results of Sorting With Directory SDK for C for more information about the ramifications of marking the control as critical.
 
After you call the ldap_create_sort_control() function and create the control, free the array of LDAPsortkey structures by calling ldap_free_sort_keylist(). When you are done receiving sorted results from the server, free the LDAPControl structure by calling ldap_control_free().
 
==== Performing a Search With Directory SDK for C  ====
 
For the server to sort the results, add the newly created server-side sorting control to a NULL terminated array of LDAPControl structures. Pass this array to the ldap_search_ext() function or the ldap_search_ext_s() function. The server returns a result for the search operation. The server also returns a response control. The response control indicates the success or failure of the sort. To determine if sort was successful, use the following procedure.
 
'''To Search With a Sort Request for Directory SDK for C'''
 
#Call ldap_parse_result() to parse the result of the search operation.<br>The function retrieves any response controls sent back from the server.<br>Response controls are passed back in a NULL terminated array of LDAPControl structures.
#Pass this array of structures as an argument to ldap_parse_sort_control() to retrieve the LDAP result code for the sorting operation.<br>If the sorting operation fails, the server can also return the name of the attribute that caused the failure. The ldap_parse_sort_control() function also retrieves this name, if available.
#Free the array by calling the ldap_controls_free() function when you are done parsing the array of response controls.
#The server can return the following result codes.
#*LDAP_SUCCESS: The results were sorted successfully.
#*LDAP_OPERATION_ERROR: An internal server error occurred.
#*LDAP_TIMELIMIT_EXCEEDED: The maximum time allowed for a search was exceeded before the server finished sorting the results.
#*LDAP_STRONG_AUTH_REQUIRED: The server refused to send back the sorted search results because the server requires you to use a stronger authentication method.
#*LDAP_ADMINLIMIT_EXCEEDED: The server retrieved too many entries to sort.
#*LDAP_NO_SUCH_ATTRIBUTE: The sort key list specifies an attribute that does not exist.
#*LDAP_INAPPROPRIATE_MATCHING: The sort key list specifies a matching rule that is not recognized or appropriate.
#*LDAP_INSUFFICIENT_ACCESS: The server did not send the sorted results because the client has insufficient access rights.
#*LDAP_BUSY: The server is too busy to sort the results.
#*LDAP_UNWILLING_TO_PERFORM: The server is unable to sort the results.
#*LDAP_OTHER: This general result code indicates that the server failed to sort the results for a reason other than the ones listed previously.
 
==== Interpreting the Results of Sorting With Directory SDK for C  ====
 
The following table shows the kinds of results to expect from the LDAP server under different situations.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Server Responses to Sorting Controls"
|+ Server Responses to Sorting Controls
|-
! scope="col" | Does the server support the sort control?
! scope="col" | Is the sort control marked as critical?
! scope="col" | Other Conditions
! scope="col" | Results From LDAP Server
|-
| Server does not support the sort control.
| Control is marked as critical.
| Not applicable
| The server does not send back any entries.
|-
| &nbsp;
| Control is not marked as critical.
| &nbsp;
| The server ignores the sorting control. Instead, the server returns the entries unsorted.
|-
| Server does support the sort control.
| Control is marked as critical.
| The server cannot sort the results by using the specified sort key list.
| The server does not send back any entries. The server sends back the sorting response control. The response control specifies the result code of the sort attempt and optionally the attribute type that caused the error.
|-
| &nbsp;
| Control is not marked as critical.
| &nbsp;
| The server returns the entries unsorted. The server sends back the sorting response control. The response control specifies the result code of the sort attempt and optionally the attribute type that caused the error.
|-
| &nbsp;
| Not applicable, might or might not be marked as critical.
| The server successfully sorted the entries.
| The server sends back the sorted entries. The server sends back the sorting response control. The response control specifies the result code of the sort attempt, LDAP_SUCCESS.
|-
| &nbsp;
| &nbsp;
| The search failed for any reason.
| The server sends back a result code for the search operation. The server does not send back the sorting response control.
|}
 
==== Server-Side Sorting Control Sample Program for Directory SDK for C  ====
 
The following sample program uses the server-side sorting control to get a list of all users in the directory. The list is sorted in ascending order by last name, then in descending order by first name.
<pre>#include &lt;stdio.h&gt;
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER 389
int
main( int argc, char **argv )
{
  LDAP        *ld;
  LDAPMessage  *result, *e;
  char        *attrfail, *matched = NULL, *errmsg = NULL;
  char        **vals, **referrals;
  int          rc, parse_rc, version;
  unsigned long    rcode;
  LDAPControl      *sortctrl = NULL;
  LDAPControl      *requestctrls[ 2 ];
  LDAPControl      **resultctrls = NULL;
  LDAPsortkey      **sortkeylist;
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER ) ) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  version = LDAP_VERSION3;
  ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
  /* Create a sort key list that specifies the sort order of the results.
    Sort the results by last name first, then by first name. */
  ldap_create_sort_keylist( sortkeylist, "sn -givenname" );
  /* Create the sort control. */
  rc = ldap_create_sort_control( ld, sortkeylist, 1, sortctrl );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr,
            "ldap_create_sort_control:&nbsp;%s\n",
            ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  requestctrls[ 0 ] = sortctrl;
  requestctrls[ 1 ] = NULL;
  /* Search for all entries in Sunnyvale */
  rc = ldap_search_ext_s( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE,
    "(mail=*example.com*)", NULL, 0, requestctrls,
    NULL, NULL, 0, result );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  parse_rc = ldap_parse_result( ld, result, rc, matched,
              errmsg, referrals, resultctrls, 0 );
  if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr,
            "ldap_parse_result:&nbsp;%s\n",
            ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    if ( errmsg&nbsp;!= NULL  *errmsg&nbsp;!= '\0' ) {
      fprintf( stderr, "%s\n", errmsg );
    }
    ldap_unbind( ld );
    return( 1 );
  }
  parse_rc =
    ldap_parse_sort_control( ld, resultctrls, rcode, attrfail );
  if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr,
            "ldap_parse_sort_control:&nbsp;%s\n",
            ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
 
  if ( rcode&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "Sort error:&nbsp;%s\n", ldap_err2string( rcode ) );
    if ( attrfail&nbsp;!= NULL  *attrfail&nbsp;!= '\0' ) {
      fprintf( stderr, "Bad attribute:&nbsp;%s\n", attrfail );
    }
    ldap_unbind( ld );
    return( 1 );
  }
  /* for each entry print out name + all attrs and values */
  for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
      e = ldap_next_entry( ld, e ) ) {
    if ((vals = ldap_get_values( ld, e, "sn"))&nbsp;!= NULL ) {
      if ( vals[0]&nbsp;!= NULL ) {
        printf( "%s", vals[0] );
      }
      ldap_value_free( vals );
    }
    if ((vals = ldap_get_values( ld, e, "givenname"))&nbsp;!= NULL ) {
      if ( vals[0]&nbsp;!= NULL ) {
        printf( "\t%s", vals[0] );
      }
      ldap_value_free( vals );
    }
    printf( "\n" );
  }
  ldap_msgfree( result );
  ldap_free_sort_keylist( sortkeylist );
  ldap_control_free( sortctrl );
  ldap_controls_free( resultctrls );
  ldap_unbind( ld );
  return( 0 );
}</pre>
=== Using the Persistent Search Control With Directory SDK for C  ===
 
The control OID 2.16.840.1.113730.3.4.3, LDAP_CONTROL_PERSISTENTSEARCH as defined in the ldap.h header file, is the persistent search control. A ''persistent search'' is an ongoing search operation that allows your LDAP client to get notification of changes to the directory.
 
The persistent search control is described in the Internet Draft ''Persistent Search: A Simple LDAP Change Notification Mechanism''.
 
To use persistent searching for change notification, you create a persistent search control that specifies the types of changes that you want to track. You include the control in a search request. When an entry in the directory changes, the server determines if the entry matches the search criteria in your request. The server also determines if the change is the type of change that you are tracking. If both of these conditions are true, the server sends the entry to your client.
 
To create a persistent search control, call ldap_create_persistentsearch_control() as shown here.<br>
<pre>int ldap_create_persistentsearch_control( LDAP *ld,
  int changetypes, int changesonly, int return_echg_ctls,
  char ctl_iscritical, LDAPControl **ctrlp );
</pre>
*changetypes specifies the type of change you want to track.
**LDAP_CHANGETYPE_ADD indicates that you want to track added entries.
**LDAP_CHANGETYPE_DELETE indicates that you want to track deleted entries.
**LDAP_CHANGETYPE_MODIFY indicates that you want to track modified entries.
**LDAP_CHANGETYPE_MODDN indicates that you want to track renamed entries.
**LDAP_CHANGETYPE_ANY indicates that you want to track all changes to entries.
*changesonly indicates whether or not you want the server to return all entries that initially matched the search criteria. Use 0 to return all entries, or non zero to return only the entries that change.
*return_echg_ctls indicates whether or not you want entry change notification controls included with every modified entry returned by the server. Use a non zero value to return entry change notification controls.
 
You can use this control in conjunction with an entry change notification control.
 
The ldap_create_persistentsearch_control() function passes back an LDAPControl structure that represents the control in the ctrlp parameter. You can add the newly created control to a NULL terminated array of LDAPControl structures. Pass this array to the ldap_search_ext() function.
 
To end the persistent search, call the ldap_abandon_ext() function. Alternatively, call the ldap_unbind() function to disconnect from the server.
 
The example provided in <tt>examples/psearch.c</tt> shows how to perform a persistent search.<br>
 
=== Using the Entry Change Notification Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.7, LDAP_CONTROL_ENTRYCHANGE as defined in the ldap.h header file, is the entry change notification control. This control contains additional information about the change to the entry. The information includes the type of change, and the change number, which corresponds to an item in the servers change log. If the entry was renamed, the control also contains the old DN of the entry in the change log.
 
You use this control in conjunction with a persistent search control. You can specify the preference for returning entry change notification controls. The server then includes an entry change notification control with each entry found by the search. To retrieve and parse an entry change notification control included with an entry, follow this procedure.
 
'''To Use Entry Change Notification With Directory SDK for C'''
 
#Pass the LDAPMessage structure that represents an entry to the ldap_get_entry_controls() function.
#Pass the entry change notification control to the ldap_parse_entrychange_control() function.<br>
 
=== Using the Virtual List View Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.9, LDAP_CONTROL_VLVREQUEST as defined in the ldap.h header file, is a virtual list view control. When you send a search request with this control and a server-side sorting control, the server should sort the results. The server should then return the specified subset of entries back to your client.
 
The virtual list view control is described in the Internet Draft, ''LDAP Extensions for Scrolling View Browsing of Search Results''.<br>
 
=== Using the Manage DSA IT Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.2, LDAP_CONTROL_MANAGEDSAIT as defined in the ldap.h header file, is the manage DSA IT control. You can use this control to manage search references in the directory. To create this control, create an LDAPControl structure and set the ldctl_oid field to 2.16.840.1.113730.3.4.2.
 
When you add this control to the array of LDAPControl structures for ldap_search_ext() or ldap_modify_ext(), the server treats search references as ordinary entries. Rather than returning a reference to you, the server returns the entry that contains the reference. This mechanism allows your client application to manage search references in the directory.
 
The manage DSA IT control is described in RFC 2891.<br>
 
=== Using Password Policy Controls With Directory SDK for C  ===
 
Directory Server offers three password policy response controls sent back to a client that performs a bind operation. The server also offers an account availability control that does not require a bind to return status about a client account.<br>
 
==== Using Password Policy Expiration Controls With Directory SDK for C  ====
 
*The control with OID 2.16.840.1.113730.3.4.4, LDAP_CONTROL_PWEXPIRED, is the expired password control.<br>This control serves when the server requires users to change passwords when first logging in, and after password reset. After the first login, and after password reset, the server sends this control to indicate that the client needs to change the password immediately. At this point, the only operation that the client can perform is to change the users password. If the client requests any other operation, the server sends back an LDAP_UNWILLING_TO_PERFORM result code with an expired password control.
*The control with OID 2.16.840.1.113730.3.4.5, LDAP_CONTROL_PWEXPIRING, is the password expiration warning control.<br>This control is used if the server is configured to expire user passwords after a certain amount of time. The server sends this control back to the client if the client binds with a password that is to expire soon . The ldctl_value field of the LDAPControl structure specifies the number of seconds before the password expires.
 
'''To Use Password Policy Expiration Controls With Directory SDK for C'''
 
#Call ldap_simple_bind() to send a request for an asynchronous bind operation.
#Call ldap_result() to get the results of the operation.
#Call ldap_parse_result() to parse the result.<br>The function retrieves the server response controls from the result as an array of LDAPControl structures.<br>
#Check the ldctl_oid field to determine the OID of the control and the ldctl_value field for any data that is included in the control.<br>
 
=== Using the Account Availability Control With Directory SDK for C  ===
 
Directory Server offers an account availability control that does not require a bind to return status about a client account. The account availability control is assigned OID 1.3.6.1.4.1.42.2.27.9.5.8, LDAP_CONTROL_ACCOUNT_USABLE. This control allows the client to read information about an account without having to bind as the user having that account.
 
'''To Use the Account Availability Control With Directory SDK for C'''
 
#Allocate an LDAPuserstatus structure to hold the values for the account status.
#Create an account status control with ldap_create_userstatus_control().
#Read the entry for which you want account status, passing in the control as part of the search.
#Get the controls on the entry that the search returns.
#Pass the LDAPuserstatus structure to ldap_parse_userstatus_control() to fill the structure.
#Read account status information from the LDAPuserstatus structure.<br>
 
This example displays status for Barbara Jensen's account.
<pre>/*
* Get account status using the account status control.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    LDAPuserstatus  *status;
    int            version;
    LDAP            *ld;
    int            rc;
    LDAPControl    *status_ctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    LDAPMessage    *result;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl    **resultctrls = NULL;
    LDAPMessage    *msg;
    LDAPControl    **ectrls = NULL;
 
    /* Allocate the LDAPuserstatus structure. */
    if (&nbsp;!( status = (LDAPuserstatus*)malloc(sizeof(LDAPuserstatus)) ) ) {
        perror("malloc");
        return ( 1 );
    }
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
            return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Create an account status control. */
    rc = ldap_create_userstatus_control( ld, 1, status_ctrl );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_userstatus_control:&nbsp;%s\n",
                ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = status_ctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Authenticate to the directory as a user. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Read the account entry using the control. */
    rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE,
        "(objectclass=*)", NULL, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
 
    /* Show the account status. */
    rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
 
    for ( msg = ldap_first_message( ld, result );
          msg&nbsp;!= NULL;
          msg = ldap_next_message ( ld, msg) ) {
        if ( ldap_msgtype( msg )&nbsp;!= LDAP_RES_SEARCH_ENTRY ) continue;
        if ( ldap_get_entry_controls( ld, msg, ectrls )&nbsp;!= LDAP_SUCCESS ) {
            ldap_perror ( ld, "ldap_get_entry_controls" );
        } else {
            rc = ldap_parse_userstatus_control( ld, ectrls, status );
            if ( rc&nbsp;!= LDAP_SUCCESS ) {
                fprintf( stderr,
                    "ldap_parse_userstatus_control:&nbsp;%s\n",
                    ldap_err2string( rc ) );
            } else {
                printf( "DN:&nbsp;%s\n", ENTRYDN );
                if ( LDAP_US_ACCOUNT_USABLE == status-&gt;us_available ) {
                    printf( " Account is usable:\tY\n" );
                } else {
                    printf( " Account is usable:\tN\n" );
                }
                printf( " Password expires in:\t%ld s\n",
                    status-&gt;us_expire );
                if ( LDAP_US_ACCOUNT_INACTIVE == status-&gt;us_inactive ) {
                    printf( " Account is locked:\tY\n" );
                } else {
                    printf( " Account is locked:\tN\n" );
                }
                if ( LDAP_US_ACCOUNT_RESET == status-&gt;us_reset ) {
                    printf( " Password was reset:\tY\n" );
                } else {
                    printf( " Password was reset:\tN\n" );
                }
                if ( LDAP_US_ACCOUNT_EXPIRED == status-&gt;us_expired ) {
                    printf( " Password has expired:\tY\n" );
                } else {
                    printf( " Password has expired:\tN\n" );
                }
                printf( " Grace logins left:\t%d\n",
                    status-&gt;us_remaining );
                printf( " Account unlocks in:\t%d s\n",
                    status-&gt;us_seconds );
            }
        }
    }
   
    ldap_msgfree( result );
    ldap_control_free( status_ctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}</pre>
==== Using the Password Policy Control With Directory SDK for C  ====
 
Directory Server offers a password policy control to retrieve information about the password policy that applies to the account used to bind to the server. The password policy control is assigned OID 1.3.6.1.4.1.42.2.27.8.5.1, LDAP_CONTROL_PASSWD_POLICY.
 
'''To Use the Password Policy Control With Directory SDK for C'''
 
#Allocate an LDAPpwdpolicy structure to hold the values for the account status.
#Create a password policy control with ldap_create_pwdpolicy_control().
#Bind sending the password policy control.
#Perform a bind, a modify, an add, a compare, or an extended operation, getting the result controls.
#Pass the LDAPpwdpolicy structure to ldap_parse_pwdpolicy_control() to fill the structure.
#Read password policy information from the LDAPpwdpolicy structure.<br>
 
This example displays the password policy that governs Barbara Jensen's account retrieved during the bind operation.
<pre>/*
* Get password policy information using the password policy control.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    LDAPpwdpolicy  *policy;
    int            version;
    LDAP            *ld;
    int            rc;
    LDAPControl    *pwpctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    int            msgid;
    LDAPMessage    *result;
    int            parse_rc;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl    **resultctrls = NULL;
 
    /* Allocate the LDAPpwdpolicy structure. */
    if (&nbsp;!( policy = (LDAPpwdpolicy*)malloc(sizeof(LDAPpwdpolicy) ) ) ) {
        perror("malloc");
        return ( 1 );
    }
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
            return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Create a password policy control. */
    rc = ldap_create_pwdpolicy_control( ld, 1, pwpctrl);
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_pwdpolicy_control:&nbsp;%s\n",
                ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = pwpctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Use the password policy control for the bind. */
    rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, pwpctrl );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_set_option" );
        return ( 1 );
    }
 
    /* Authenticate to the directory, checking for result controls. */
    msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW );
    if ( msgid  0 ) {
        fprintf( stderr, "ldap_simple_bind:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( errmsg&nbsp;!= NULL  errmsg&nbsp;!= '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
        ldap_unbind( ld );
        return ( 1 );
    }
 
    rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, result );
    if ( rc  0 ) {
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    parse_rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_simple_bind:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( errmsg&nbsp;!= NULL  errmsg&nbsp;!= '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
    }
    if ( resultctrls == NULL ) {
        fprintf( stderr, "No pwp result control from server.\n" );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    /* Show the password policy information. */
    parse_rc = ldap_parse_pwdpolicy_control( ld, resultctrls, policy );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_pwdpolicy_control:&nbsp;%s\n",
            ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    printf( "DN:&nbsp;%s\n", ENTRYDN );
    switch ( policy-&gt;pp_warning ) {
    case LDAP_PP_WARNING_NONE:
        printf( " No warnings\n" );
        break;
    case LDAP_PP_WARNING_EXP:
        printf( " Password expires in:&nbsp;%d s\n", policy-&gt;pp_warning_info );
        break;
    case LDAP_PP_WARNING_GRACE:
        printf( " Grace logins left:&nbsp;%d", policy-&gt;pp_warning_info );
        break;
    default: printf( " Unrecognized password policy warning\n" ); break;
    }
    switch ( policy-&gt;pp_error ) {
    case LDAP_PP_ERROR_NONE:
        printf( " No errors\n" );
        break;
    case LDAP_PP_ERROR_EXPIRED:
        printf( " Password has expired, and must be reset.\n" );
        break;
    case LDAP_PP_ERROR_LOCKED:
        printf( " Account is locked.\n" );
        break;
    case LDAP_PP_ERROR_MUSTCHANGE:
        printf( " Password has been reset, and must be changed.\n" );
        break;
    case LDAP_PP_ERROR_NOTMOD:
        printf( " This user may not change the password.\n" );
        break;
    case LDAP_PP_ERROR_OLDPASSWD:
        printf( " Old password must be supplied for this operation.\n" );
        break;
    case LDAP_PP_ERROR_NOQUALITY:
        printf( " Password does not pass quality check.\n" );
        break;
    case LDAP_PP_ERROR_TOOSHORT:
        printf( " Password is too short.\n" );
        break;
    case LDAP_PP_ERROR_MINAGE:
        printf( " Password is too new to be modified already.\n" );
        break;
    case LDAP_PP_ERROR_INHISTORY:
        printf( " Password has already been used.\n" );
        break;
    default: printf( " Unrecognized password policy error\n" ); break;
    }
 
    ldap_msgfree( result );
    ldap_control_free( pwpctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}</pre>
=== Using the Proxied Authorization Control With Directory SDK for C  ===
 
Proxied authorization is an extension to LDAP v3 that allows a bound client to assume the identity of another directory entity without rebinding. The rebind allows the client to perform operations as if it were bound as the proxied directory entity. All directory access, including read, write, search, compare, delete, and add operations, is supported by proxied authorization. For example, suppose a client is bound as <tt>uid=bjensen,ou=Engineering,dc=example,dc=com</tt>. The user bjensen does not have the right to search the <tt>ou=Marketing,dc=example,dc=com</tt> tree. However, <tt>uid=lboyd,ou=Marketing,dc=example,dc=com</tt> does have rights to search the Marketing tree, and lboyd grants proxy rights to bjensen. In this case, bjensen can bind as herself, assume the identity of lboyd, and then search the Marketing tree.
 
This feature is intended as a performance and administrative benefit for certain types of directory usage. Specifically, applications that allow many clients to access directory data without rebinding as another directory entity might use this feature.
 
==== Proxy Right for Directory SDK for C  ====
 
Proxied authorization adds an additional access right: proxy. If an entry grants the proxy right, then the entity to which that right is granted can assume the identity of the granting entity. For example, to allow uid=bjensen the right to proxy as uid=lboyd, add the Proxy Right access control instruction (ACI) as shown in the following example. This ACI allows bjensen to assume the identity of lboyd for all directory operations. The ACI gives bjensen permission to do to the directory whatever lboyd has permission to do.
<pre>aci: (target = "ldap:///uid=lboyd,ou=Marketing,dc=example,dc=com")
(targetattr=*)
(version 3.0; aci "grant bjensen the right to proxy as lboyd";
  allow(proxy)
  userdn="ldap:///uid=bjensen,ou=Engineering,dc=example,dc=com";)</pre>
==== Proxy Authorization Control With Directory SDK for C  ====
 
To support proxy authorization, an extension to LDAP v3, the proxy authorization control has been added to Directory SDK for C in the form of the ldap_create_proxyauth_control() function. You use this function to create the control that allows a bound entity to assume the identity of another directory entry.
 
Proxy authorization is an optional LDAP server feature. Proxy authorization might not be supported on all LDAP servers. You should call the proxy authorization control function only when interacting with LDAP servers that support this LDAP v3 extension. You can check on the support of this control by looking at the root DSE supportedControl attribute. For example, the following command uses the ldapsearch utility to display the root DSE:
<pre>$ ldapsearch -h localhost -p 389 -b "" -s base "(objectclass=*)"</pre>
For the control to work, the server to connect to must support the server control for Proxy Authorization, OID 2.16.840.1.113730.3.4.12. This control is LDAP_CONTROL_PROXYAUTH as defined in the ldap.h header file.
 
==== Proxy Authorization Sample Program for Directory SDK for C  ====
 
The following sample program creates an LDAP connection, sets the Proxy Authorization control, binds to the directory, and then performs a search operation using the Proxy Authorization control.
<pre>#include "ldap.h"
 
int            version;
LDAP          *ld;
LDAPControl    *requestctrls[ 2 ];
LDAPControl    *pactrl = NULL;
 
/* Customize the following host and bind information for your site. */
int        port=389;
char      *host="directory.example.com";
char      *baseDN="dc=example,dc=com";
 
/* Proxied auth specific information.
  proxyDN is the entity that will be proxied.
  bindDN and bindpw is for the bind entity that will use the proxyDN. */
char            *proxyDN = "uid=lboyd,ou=marketing,dc=example,dc=com";
char            *bindDN = "uid=bjensen,ou=engineering,dc=example,dc=com";
char            *bindpw = "password";
 
/* Do general LDAP init stuff */
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( host, port ) ) == NULL ) {
        printf("ldap_init did not return a conn handle.\n");
        return;
        }
/* set version to ldap version 3 */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
 
/* authenticate to the directory */
if ( ldap_simple_bind_s( ld, bindDN, bindpw )&nbsp;!= LDAP_SUCCESS ) {
        printf("ldap_simple_bind_s failed");
        return (-1);
}
 
/* create the Proxy Authorization control */
if ( ldap_create_proxyauth_control( ld, proxyDN, 1, pactrl ) ) {
  printf("ldap_create_proxyauth_control failed.\n");
  if ( ldap_unbind( ld )&nbsp;!= LDAP_SUCCESS ) {
        printf("ldap_unbind failed\n");
  }
  return(-1);
}
 
requestctrls[ 0 ] = pactrl;
requestctrls[ 1 ] = NULL;
 
/* Perform the search using the control */
printf("Searching for&nbsp;%s with the proxy auth control.\n", proxyDN);
if ( ldap_search_ext_s( ld, proxyDN, LDAP_SCOPE_SUBTREE, "(objectclass=*)",
        NULL, 0, requestctrls, NULL, NULL, LDAP_NO_LIMIT, results )&nbsp;!=
        LDAP_SUCCESS ) {
                printf("ldap_search_ext failed.\n");
                printf("Something is wrong with proxied auth.\n");
} else {
        print_search_results(ld, results);
}</pre>
=== Using the Authorization Identity Bind Request Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.16, LDAP_CONTROL_AUTHZID_REQ, is the authorization identity bind request control. This control lets you request the authorization ID when binding to the server.
 
'''To Retrieve the Authorization ID'''
 
Directory Server supports the authorization identity bind request and response controls defined in RFC 3829. The server also allows you to retrieve the authorization identity value as a string.
 
#Create an authorization identity request control using the ldap_create_authzid_control() function.
#Bind sending the authorization identity request control.
#Read the authorization identity from the response control using the ldap_parse_authzid_control() function.<br>
 
This example gets the authorization ID for Barbara Jensen.
<pre>/*
* Get the authorization ID for an operation.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    int            version;
    LDAP            *ld;
    int            rc;
    LDAPControl    *authzidctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    int            msgid;
    LDAPMessage    *result;
    int            parse_rc;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl    **resultctrls = NULL;
    char            *authzid;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
            return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Create a authorization ID control. */
    rc = ldap_create_authzid_control( ld, 1, authzidctrl );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_authzid_control:&nbsp;%s\n",
                ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = authzidctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Use the authorization ID control for the bind. */
    rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, authzidctrl );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_set_option" );
        return ( 1 );
    }
 
    /* Authenticate to the directory, checking for result controls. */
    msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW );
    if ( msgid  0 ) {
        fprintf( stderr, "ldap_simple_bind:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( errmsg&nbsp;!= NULL  errmsg&nbsp;!= '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
        ldap_unbind( ld );
        return ( 1 );
    }
 
    rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, result );
    if ( rc  0 ) {
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    parse_rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_simple_bind:&nbsp;%s\n", ldap_err2string( rc ) );
        if ( errmsg&nbsp;!= NULL  errmsg&nbsp;!= '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
    }
    if ( resultctrls == NULL ) {
        fprintf( stderr, "No result control from server.\n" );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    /* Show the authorization ID. */
    parse_rc = ldap_parse_authzid_control( ld, resultctrls, authzid );
    if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_authzid_control:&nbsp;%s\n",
            ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
 
    printf( "DN:      &nbsp;%s\n", ENTRYDN );
    printf( "Authz ID:&nbsp;%s\n", authzid );
 
    ldap_msgfree( result );
    ldap_control_free( authzidctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}</pre>
=== Using the Get Effective Rights Request Control With Directory SDK for C  ===
 
The control with OID 1.3.6.1.4.1.42.2.27.9.5.2, LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, is the get effective rights request control. This control lets you request information about the effective access rights a user has, by performing a search for the aclRights and aclRightsInfo attributes.
 
'''To Get Effective Rights'''
 
#Create a get effective rights request control using the ldap_create_geteffectiveRights_control function.
#Perform a search with the control, requesting the aclRights and aclRightsInfo attributes.
#Read the values of the attributes for the effective rights information.<br>
 
This example gets effective rights for Kirsten Vaughan.
<pre>/*
* Get effective rights for another user.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    int            version;
    LDAP            *ld;
    int            rc;
    LDAPControl    *gerctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    char            *authzid;
    char            **attrlist;
    LDAPMessage    *result;
    LDAPMessage    *entry;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int            i;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
            return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Authenticate to the directory as a user. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Create a get effective rights control. */
    authzid = "dn: uid=kvaughan,ou=people,dc=example,dc=com";
    if (&nbsp;!( attrlist = (char**)malloc(sizeof(char * [ 2 ]) ) ) ) {
        perror( "malloc" );
        ldap_unbind( ld );
        return ( 1 );
    }
    attrlist[ 0 ] = "aclRights";
    attrlist[ 1 ] = NULL;
    rc = ldap_create_geteffectiveRights_control( ld, authzid,
        (const char **)attrlist, 1, gerctrl );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_geteffectiveRights_control:&nbsp;%s\n",
                ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = gerctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Read an entry using the control. */
    rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE,
        "(objectclass=*)", attrlist, 0, requestctrls,
        NULL, NULL, 0, result );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
 
    /* Examine the entry for effective rights. */
    printf( "Bind DN: &nbsp;%s\n", ENTRYDN );
    printf( "Authz ID:&nbsp;%s\n", authzid );
    printf( "***Rights***\n" );
    for ( entry = ldap_first_entry( ld, result );
          entry&nbsp;!= NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr&nbsp;!= NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) )&nbsp;!= NULL) {
                for ( i = 0; vals[i]&nbsp;!= NULL; ++i ) {
                    printf( "%s:&nbsp;%s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber&nbsp;!= NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );
 
    ldap_msgfree( result );
    ldap_control_free( gerctrl );
    ldap_unbind( ld );
    return( 0 );
}</pre>
When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to the following. Lines are wrapped for readability.
<pre>Bind DN:  uid=bjensen, ou=People, dc=example,dc=com
Authz ID: dn: uid=kvaughan,ou=people,dc=example,dc=com
***Rights***
aclRights;entryLevel: add:1,delete:1,read:1,write:1,proxy:0
aclRights;attributeLevel;: search:1,read:1,compare:1,write:1,
selfwrite_add:1,selfwrite_delete:1,proxy:0
aclRights;attributeLevel;dn: uid=kvaughan,ou=people,dc=example,dc=com:
search:1,read:1,compare:1,write:1,selfwrite_add:1,selfwrite_delete:1,
proxy:0
aclRights;attributeLevel;@c&nbsp;: search:1,read:1,compare:1,write:1,
selfwrite_add:1,selfwrite_delete:1,proxy:0</pre>
See your server documentation for information about aclRights and aclRightsInfo values.
 
=== Using the Real Attributes Only Request Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.17, LDAP_CONTROL_REAL_ATTRS_ONLY, is the real attributes only request control. This control lets you convey to the server to return only real attributes, attributes that are stored by the directory, during a search.<br>
 
'''To Retrieve Only Real Attributes'''
 
#Create an LDAPControl structure with the OID defined using LDAP_CONTROL_REAL_ATTRS_ONLY.
#Pass the control in to the server with the search request.
#Free the control when finished.<br>
 
This example relies on sample data from Example-roles.ldif.
<pre>/*
* Use the control to get only real attributes.
* First load suffix data from Example-roles.ldif.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    LDAPControl    *ctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    char            **attrlist;
    int            version;
    LDAP            *ld;
    char            *target;
    int            rc;
    LDAPMessage    *result;
    LDAPMessage    *entry;
    char            *dn;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int            i;
 
    /* Prepare a real attributes only request control. */
    if (&nbsp;!(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) {
        perror( "malloc" );
        return( 1 );
    }
    ctrl-&gt;ldctl_oid = strdup( LDAP_CONTROL_REAL_ATTRS_ONLY );
    ctrl-&gt;ldctl_iscritical = 1;
    requestctrls[ 0 ] = ctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Create a list of attributes to retrieve. */
    if (&nbsp;!( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) {
        perror( "malloc" );
        return ( 1 );
    }
    attrlist[ 0 ] = "cn";              /* Real attribute */
    attrlist[ 1 ] = "nsrole";          /* Virtual attribute */
    attrlist[ 2 ] = NULL;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
        fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
        return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Authenticate to the directory to read an entry. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Read an entry using the control. */
    target = "uid=kvaughan,ou=people,dc=example,dc=com";
    rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)",
        attrlist, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
 
    /* Examine the results. */
    for ( entry = ldap_first_entry( ld, result );
          entry&nbsp;!= NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        if ( (dn = ldap_get_dn( ld, entry ))&nbsp;!= NULL ) {
            printf( "dn:&nbsp;%s\n", dn );
            ldap_memfree( dn );
        }
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr&nbsp;!= NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) )&nbsp;!= NULL) {
                for ( i = 0; vals[i]&nbsp;!= NULL; ++i ) {
                    printf( "%s:&nbsp;%s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber&nbsp;!= NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );
 
    ldap_msgfree( result );
    ldap_control_free( ctrl );
    ldap_unbind( ld );
    return( 0 );
}</pre>
When you compile and run this sample program against Directory Server with a suffix that contains data from Example-roles.ldif, the server produces output similar to this:
<pre>dn: uid=kvaughan, ou=People, dc=example,dc=com
cn: Kirsten Vaughan</pre>
=== Using the Virtual Attributes Only Request Control With Directory SDK for C  ===
 
The control with OID 2.16.840.1.113730.3.4.19, LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, is the virtual attributes only request control. This control lets you convey to the server to return only virtual attributes during a search. Virtual attribute values are not stored by the directory, but instead are generated on request.<br>
 
'''To Retrieve Only Virtual Attributes'''
 
#Create an LDAPControl structure with the OID defined using LDAP_CONTROL_VIRTUAL_ATTRS_ONLY.
#Pass the control in to the server with the search request.
#Free the control when finished.<br>
 
This example relies on sample data from Example-roles.ldif.
<pre>/*
* Use the control to get only virtual attributes.
* First load suffix data from Example-roles.ldif.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    LDAPControl    *ctrl = NULL;
    LDAPControl    *requestctrls[ 2 ];
    char            **attrlist;
    int            version;
    LDAP            *ld;
    char            *target;
    int            rc;
    LDAPMessage    *result;
    LDAPMessage    *entry;
    char            *dn;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int            i;
 
    /* Prepare a virtual attributes only request control. */
    if (&nbsp;!(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) {
        perror( "malloc" );
        return( 1 );
    }
    ctrl-&gt;ldctl_oid = strdup( LDAP_CONTROL_VIRTUAL_ATTRS_ONLY );
    ctrl-&gt;ldctl_iscritical = 1;
    requestctrls[ 0 ] = ctrl;
    requestctrls[ 1 ] = NULL;
 
    /* Create a list of attributes to retrieve. */
    if (&nbsp;!( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) {
        perror( "malloc" );
        return ( 1 );
    }
    attrlist[ 0 ] = "cn";              /* Real attribute */
    attrlist[ 1 ] = "nsrole";          /* Virtual attribute */
    attrlist[ 2 ] = NULL;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
        fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
        return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Authenticate to the directory to read an entry. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Read an entry using the control. */
    target = "uid=kvaughan,ou=people,dc=example,dc=com";
    rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)",
        attrlist, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
 
    /* Examine the results. */
    for ( entry = ldap_first_entry( ld, result );
          entry&nbsp;!= NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        if ( (dn = ldap_get_dn( ld, entry ))&nbsp;!= NULL ) {
            printf( "dn:&nbsp;%s\n", dn );
            ldap_memfree( dn );
        }
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr&nbsp;!= NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) )&nbsp;!= NULL) {
                for ( i = 0; vals[i]&nbsp;!= NULL; ++i ) {
                    printf( "%s:&nbsp;%s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber&nbsp;!= NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );
 
    ldap_msgfree( result );
    ldap_control_free( ctrl );
    ldap_unbind( ld );
    return( 0 );
}</pre>
When you compile and run this sample program against Directory Server with a suffix that contains data from Example-roles.ldif, the server produces output similar to this:
<pre>dn: uid=kvaughan, ou=People, dc=example,dc=com
nsrole: cn=directory administrators,dc=example,dc=com
nsrole: cn=hr managers,dc=example,dc=com</pre>
 
== SASL Authentication With Directory SDK for C  ==
 
This section describes the process of using a Simple Authentication and Security Layer (SASL) mechanism to authenticate an LDAP client to an LDAP server.
 
=== Understanding SASL and Directory SDK for C  ===
 
The ability to authenticate to an LDAP server with a SASL mechanism is a feature that is new to LDAP v3. LDAP v2 servers do not support this method of authentication.
 
SASL is described in RFC 4422, ''Simple Authentication and Security Layer (SASL)''.<br>
 
=== Determining Supported SASL Mechanisms With Directory SDK for C  ===
 
To determine the SASL mechanisms supported by an LDAP v3 server, get the root DSE of the server, and check the supportedSASLMechanisms attribute. The values of this attribute are the names of the SASL mechanisms supported by the server.
 
If the root DSE does not have a supportedSASLMechanisms attribute, the server does not support any SASL mechanisms.<br>
 
=== Authenticating Using SASL With Directory SDK for C  ===
 
*The synchronous ldap_sasl_bind_s() function
*The asynchronous ldap_sasl_bind() function<br>If you call the asynchronous function ldap_sasl_bind(), you need to call the ldap_result() and ldap_parse_sasl_bind_result() functions to get the result of the SASL bind operation.
 
Authentication with a SASL mechanism can take one or more roundtrips between your client and the server. The server might send a number of challenges to the client. You might need to call ldap_sasl_bind_s() several times, or ldap_sasl_bind(), ldap_result(), and ldap_parse_sasl_bind_result() several times in order to respond to each server challenge.
 
Before calling the function to perform a SASL bind operation, make sure to specify that your client is LDAP v3 compliant. If you do not, an LDAP_NOT_SUPPORTED result code is returned.
 
==== Synchronous SASL Bind Operation  ====
 
If you want to wait for the results of the SASL bind operation to complete before continuing, call the synchronous ldap_sasl_bind_s() function. This function sends a SASL bind request to the server. This function blocks other work until the server sends the results of the operation back to your client.
 
*LDAP_SUCCESS if your client has successfully authenticated.
*LDAP_SASL_BIND_IN_PROGRESS if the server sends a challenge to your client. If you receive this result code, check the servercredp argument for the berval structure that contains the servers challenge. Call the ldap_sasl_bind function again to send a response to that challenge.
*An LDAP error code if a problem occurred or if authentication failed. See the ldap_sasl_bind_s() function documentation for a list of the possible result codes.
 
==== Asynchronous SASL Bind Operation  ====
 
If you want to perform other work in parallel while waiting for the SASL bind operation to complete, use the following procedure.
 
'''To Bind Asynchronously Over SASL'''
 
#Call the asynchronous ldap_sasl_bind() function to send an LDAP SASL bind request.<br>This function returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred while sending the request. The function also sets the msgidp argument to point to a message ID identifying the SASL bind operation.
#Call the ldap_result() function, passing in this message ID to determine whether the server sent a response for this operation to your client.<br>The ldap_result() function uses the message ID to determine if the server sent a SASL bind response. The function passes back the response in an LDAPMessage structure.
#Call the ldap_parse_sasl_bind_result() function to parse the LDAPMessage structure and retrieve information from the servers response.<br>If the server sent a challenge to your client, the challenge is specified in the berval structure passed back as the servercredp argument.
#Call the ldap_get_lderrno function to get the LDAP result code for the operation.
#*LDAP_SUCCESS if your client successfully authenticated to the server.
#*LDAP_SASL_BIND_IN_PROGRESS if the server sent a challenge to your client.<br>If the server returned an LDAP_SASL_BIND_IN_PROGRESS result code, check the servercredp argument for the berval structure that contains the servers challenge.
#*An LDAP error code if a problem occurred or if authentication failed.<br>See the ldap_sasl_bind() function documentation for a list of result codes that the server can return for this operation.
#If the result code is LDAP_SASL_BIND_IN_PROGRESS and if the server passed back another challenge, determine the response to that challenge by calling the ldap_sasl_bind() function again to send that response to the server.<br>You can call ldap_result() and ldap_parse_sasl_bind_result() again to get the next challenge sent from the server, if the result is again LDAP_SASL_BIND_IN_PROGRESS.
 
This example shows an LDAP client that authenticates using the SASL mechanism that is named <tt>babsmechanism</tt>.
<pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;time.h&gt;
#include "ldap.h"
 
int
main( int argc, char **argv )
{
    LDAP        *ld;
    LDAPMod    mod0;
    LDAPMod    mod1;
    LDAPMod    *mods[ 3 ];
    char        *vals0[ 2 ];
    char        *vals1[ 2 ];
    time_t      now;
    char        buf[ 128 ];
    struct berval  cred;
    struct berval  *servcred;
    int        version;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( "localhost", 389 )) == NULL ) {
      perror( "ldap_init" );
      return( 1 );
    }
    /* Set the LDAP protocol version supported by the client
      to 3. (By default, this is set to 2. SASL authentication
      is part of version 3 of the LDAP protocol.) */
    version = LDAP_VERSION3;
    ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    /* authenticate */
    cred.bv_val = "magic";
    cred.bv_len = sizeof( "magic" ) - 1;
    if ( ldap_sasl_bind_s( ld, "uid=bjensen,ou=people,dc=example,dc=com",
                          "babsmechanism", cred, NULL, NULL,
                          servcred )&nbsp;!= LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_sasl_bind_s" );
      return( 1 );
    }
    /* get and print the credentials returned by the server */
    printf( "Server credentials:&nbsp;%s\n", servcred-&gt;bv_val );
    /* construct the list of modifications to make */
    mod0.mod_op = LDAP_MOD_REPLACE;
    mod0.mod_type = "mail";
    vals0[0] = "babs@example.com";
    vals0[1] = NULL;
    mod0.mod_values = vals0;
    mod1.mod_op = LDAP_MOD_ADD;
    mod1.mod_type = "description";
    time( now );
    sprintf( buf, "This entry was modified with the modattrs program on&nbsp;%s",
      ctime( now ));
    /* Get rid of \n which ctime put on the end of the time string */
    if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
      buf[ strlen( buf ) - 1 ] = '\0';
    }
    vals1[ 0 ] = buf;
    vals1[ 1 ] = NULL;
    mod1.mod_values = vals1;
    mods[ 0 ] = mod0;
    mods[ 1 ] = mod1;
    mods[ 2 ] = NULL;
    /* make the change */
    if ( ldap_modify_s(ld, "uid=bjensen,ou=people,dc=example,dc=com", mods)
    &nbsp;!= LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_modify_s" );
      return( 1 );
    }
    ldap_unbind( ld );
    printf( "modification was successful\n" );
    return( 0 );
}</pre>
== Extended Operations With Directory SDK for C  ==
 
This section explains LDAP v3 extended operations. It also explains how to use the extended operations supported by your LDAP server.
 
=== How Extended Operations Work With Directory SDK for C  ===
 
Extended operations are part of LDAP v3. Each extended operation is identified by an object identifier (OID). LDAP clients can request the operation by sending an extended operation request.
 
*The OID of the extended operation that should be performed
*Data specific to the extended operation
 
The server receives the request, then performs the extended operation. The server sends back a response to the client that contains an OID, and any additional data.
 
To use extended operations, both the server and the client must understand the specific extended operation to be performed. From the LDAP server perspective, Directory Server supports a server plug-in interface that you can use to add support for extended operations.<br>
 
=== Determining the Extended Operations Supported With Directory SDK for C  ===
 
To determine the extended operations supported by the server, get the root DSE of the server, and check the supportedExtension attribute. The values of this attribute are the OIDs of the extended operations supported by this server. If the root DSE does not have a supportedExtension attribute, the server does not support any extended operations.<br>
 
=== Performing an Extended Operation With Directory SDK for C  ===
 
*The synchronous ldap_extended_operation_s() function
*The asynchronous ldap_extended_operation() function
 
Both of these functions allow you to specify the OID of the extended operation and the data that you want applied to the operation.
 
Before calling the function to perform an LDAP extended operation, make sure to specify that your client is using version 3 of LDAP. If you do not, an LDAP_NOT_SUPPORTED result code is returned.
 
==== Synchronous Extended Operation  ====
 
If you want to wait for the results of an LDAP extended operation to complete before continuing, call the synchronous ldap_extended_operation_s() function. This function sends a SASL bind request to the server. The server blocks other work until the server sends the results of the operation back to your client.
 
ldap_extended_operation_s() returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred. See the documentation for the ldap_extended_operation_s() function for a list of the possible result codes.<br>
 
==== Asynchronous Extended Operation  ====
 
If you want to perform other work in parallel while waiting for an LDAP extended operation to complete, perform the following procedure.
 
'''To Perform an Asynchronous Extended Operation'''
 
#Call the asynchronous ldap_extended_operation() function to send an LDAP extended operation request.<br>This function returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred while sending the request. The function also sets the msgidp argument to point to a message ID identifying the extended operation. To determine whether the server sent a response to your client for this operation, call the ldap_result() function and pass in this message ID. The function passes back the response in an LDAPMessage structure.
#Call the ldap_parse_extended_result() function to parse the LDAPMessage structure and retrieve information from the servers response.<br>If the server sent an OID of an extended operation to your client, the OID is passed back as the retoidp argument. If the server sent data to your client, the data is specified in the berval structure passed back as the retdatap argument.
#Call the ldap_get_lderrno() function to get the LDAP result code for the operation.<br>The function returns an LDAP_SUCCESS result code if the extended operation was performed successfully, or an LDAP error code if a problem occurred. See the documentation for the ldap_extended_operation() function for a list of result codes that the server can return for this operation.<br>
 
This example client requests an asynchronous extended operation from the server with OID 1.2.3.4.
<pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;time.h&gt;
#include "ldap.h"
 
/* Name and port of the LDAP server you want to connect to. */
#define MY_HOST "localhost"
#define MY_PORT  389
/* DN of user (and password of user) who you want to authenticate as */
#define MGR_DN  "cn=Directory Manager"
#define MGR_PW  "23skidoo"
int
main( int argc, char **argv )
{
    /* OID of the extended operation that you are requesting */
    const char    *oidrequest = "1.2.3.4";
    char          *oidresult;
    struct berval  valrequest;
    struct berval  *valresult;
    LDAP          *ld;
    int rc, version;
    /* Set up the value that you want to pass to the server */
    printf( "Setting up value to pass to server...\n" );
    valrequest.bv_val = "My Value";
    valrequest.bv_len = strlen( "My Value" );
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    printf( "Getting the handle to the LDAP connection...\n" );
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Set the LDAP protocol version supported by the client
      to 3. (By default, this is set to 2. Extended operations
      are part of version 3 of the LDAP protocol.) */
    ldap_get_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    printf( "Resetting version&nbsp;%d to 3.0...\n", version );
    version = LDAP_VERSION3;
    ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    /* Authenticate to the directory as the Directory Manager */
    printf( "Binding to the directory...\n" );
    if ( ldap_simple_bind_s( ld, MGR_DN, MGR_PW )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Initiate the extended operation */
    printf( "Initiating the extended operation...\n" );
    if ( ( rc = ldap_extended_operation_s( ld, oidrequest, valrequest,
                  NULL, NULL, oidresult, valresult ) )&nbsp;!=
        LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_extended_operation failed: " );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Get the OID and the value from the result returned by the server. */
    printf( "Operation successful.\n" );
    printf( "\tReturned OID:&nbsp;%s\n", oidresult );
    printf( "\tReturned value:&nbsp;%s\n", valresult-&gt;bv_val );
    /* Disconnect from the server. */
    ldap_unbind( ld );
    return 0;
}</pre>
=== Performing an LDAP Password Modify Extended Operation With Directory SDK for C  ===
 
RFC 3062, ''LDAP Password Modify Extended Operation'', describes the extended operation, which is particularly useful for changing expired passwords.
 
'''To Perform an LDAP Password Modify Extended Operation'''
 
#Get a connection to the directory that uses LDAP version 3.
#Authenticate to the directory.
#*As an administrator, to be able to reset an expired user password if you do not have the old password
#*Anonymously to reset an expired password if you have the old password
#*As the user herself to change the password that has not yet expired
#Modify the password with the synchronous function ldap_passwd_s() or the asynchronous function ldap_passwd() and use ldap_parse_passwd() or ldap_parse_passwd_result() to examine the results.<br>
 
This example changes a password using ldap_passwd_s().
<pre>/*
* Use the password modify extended operation to change a password.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    int            version;
    LDAP            *ld;
    char            *target;
    int            rc;
    struct berval  userid;
    struct berval  oldpasswd;
    struct berval  newpasswd;
    struct berval  genpasswd;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
        fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
        return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Change the password using the extended operation. */
    userid.bv_val = ENTRYDN;
    userid.bv_len = strlen(userid.bv_val);
 
    oldpasswd.bv_val = ENTRYPW;
    oldpasswd.bv_len = strlen(oldpasswd.bv_val);
 
    newpasswd.bv_val = "ChangeMe!";
    newpasswd.bv_len = strlen(newpasswd.bv_val);
 
    rc = ldap_passwd_s(
        ld, userid, oldpasswd, newpasswd, genpasswd, NULL, NULL );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_passwd_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    } else {
        printf( "Successfully changed password for&nbsp;%s\n", userid.bv_val );
    }
 
    ldap_unbind( ld );
    return( 0 );</pre>
When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to this:
<pre>Successfully changed password for uid=bjensen, ou=People, dc=example,dc=com</pre>
=== Using Start TLS With Directory SDK for C  ===
 
RFC 4513, ''Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms'', describes the extended operation. Start TLS allows you to connect on a non secure port, and then request transport layer security.
 
See Starting Transport Layer Security With Directory SDK for C for an example of how to use Start TLS.<br>
 
=== Performing a Who Am I? Extended Operation With Directory SDK for C  ===
 
The Who am I? extended operation allows you to retrieve the authorization identity that is associated with a connection.
 
This method can involve less code than the standard authorization identity controls that are described in Using the Authorization Identity Bind Request Control With Directory SDK for C.
 
'''To Perform a Who Am I? Extended Operation'''
 
#Get a connection to the directory that uses LDAP version 3.
#Use ldap_whoami() and ldap_parse_whoami_result(), or use ldap_whoami_s(), to retrieve the authorization identity.
 
This example retrieves authorization identity by using ldap_whoami_s().
<pre>/*
* Use the Who Am I? extended operation.
*/
 
#include "examples.h"
 
int
main( int argc, char **argv )
{
    int            version;
    LDAP            *ld;
    int            rc;
    char            *authzid;
 
    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
        &nbsp;!= 0 ) {
        fprintf( stderr,
                "ldap_set_option protocol version to&nbsp;%d failed\n",
                version );
        return ( 1 );
    }
 
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }
 
    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }
 
    /* Examine my authorization ID. */
    rc = ldap_whoami_s( ld, NULL, NULL, authzid );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_whoami_s:&nbsp;%s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    printf( "Authorization ID:&nbsp;%s\n", authzid );
 
    ldap_unbind( ld );
    return( 0 );
}</pre>
When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to this:
<pre>Authorization ID: dn:uid=bjensen,ou=people,dc=example,dc=com</pre>
== Writing Multithreaded Clients With Directory SDK for C  ==
 
This section shows how to write multithreaded LDAP client applications.
 
The Directory SDK for C APIs are thread-safe. By default, the APIs use POSIX thread-safe primitives. Therefore, unless you specify your own thread functions, standard best practices for POSIX threading apply.
 
=== Specifying Thread Functions With Directory SDK for C  ===
 
You can write a multithreaded client with different threads accessing the same LDAP structure. Use the POSIX thread API. Alternatively, set up the session defining your own structures such that threads do not interfere with data of other threads.
 
The LDAP_OPT_THREAD_FN_PTRS session option lets you set up an ldap_thread_fns structure. The structure identifies the functions that are called in multithreaded environments. For example, the structure can define functions to lock critical sections of code and to handle errors. As this structure lets you specify these functions, you can use Directory SDK for C in different types of threading environments.
 
==== Setting Up the ldap_thread_fns Structure  ====
 
You can write a multithreaded client in which different threads use the same LDAP connection. Set up the ldap_thread_fns structure. Then identify the functions that you want to use in the ldap_thread_fns structure.
<pre>struct ldap_thread_fns {
  LDAP_TF_MUTEX_ALLOC_CALLBACK  *ltf_mutex_alloc;
  LDAP_TF_MUTEX_FREE_CALLBACK    *ltf_mutex_free;
  LDAP_TF_MUTEX_LOCK_CALLBACK    *ltf_mutex_lock;
  LDAP_TF_MUTEX_UNLOCK_CALLBACK  *ltf_mutex_unlock;
  LDAP_TF_GET_ERRNO_CALLBACK    *ltf_get_errno;
  LDAP_TF_SET_ERRNO_CALLBACK    *ltf_set_errno;
  LDAP_TF_GET_LDERRNO_CALLBACK  *ltf_get_lderrno;
  LDAP_TF_SET_LDERRNO_CALLBACK  *ltf_set_lderrno;
  void    *ltf_lderrno_arg;
};</pre>
The fields of the ldap_thread_fns structure are described in the following list.
 
*''*ltf_mutex_alloc'': Function pointer for allocating a mutex. This function is called by the client when needed if the function pointer is not NULL.
*''*ltf_mutex_free'': Function pointer for freeing a mutex. This function is called by the client when needed if the function pointer is not NULL.
*''*ltf_mutex_lock'': Function pointer for locking critical sections of code. This function is called by the client when needed if the function pointer is not NULL.
*''*ltf_mutex_unlock'': Function pointer for unlocking critical sections of code. This function is called by the client when needed if the function pointer is not NULL.
*''*ltf_get_errno'': Function pointer for getting the value of the errno variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined. The error structure has a value for each thread, rather than a global value for the entire process. This redefinition is done at compile time. The libldap library does not know what method your code and your threading environment use to get the value of errno for each thread. The library therefore calls this function to return the value of errno.
*''*ltf_set_errno'': Function pointer for setting the value of the errno variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined. The error structure has a value for each thread, rather than a global value for the entire process. This redefinition is done at compile time. The libldap library does not know what method your code and your threading environment use to get the value of errno for each thread. The library therefore calls this function to set the value of errno.
*''*ltf_get_lderrno'': Function pointer for getting error values from calls to functions in the libldap library. This function is called by the client when needed if the function pointer is not NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure.
*''*ltf_set_lderrno'': Function pointer for setting error values from calls to functions in the libldap library. This function is called by the client when needed if the function pointer is not NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure.
*''*ltf_lderrno_arg'': Additional parameter passed to the functions for getting and setting error values from calls to functions in the libldap library. *ltf_get_lderrno and *ltf_set_lderrno identify these functions.
 
==== Setting Up the ldap_extra_thread_fns Structure  ====
 
Directory SDK for C provides a structure, ldap_extra_thread_fns, that specifies additional thread functions for locking. The structure also specifies thread functions for semaphores, which are protected variables. The ldap_extra_thread_fns structure is defined as follows.
<pre>struct ldap_extra_thread_fns {
  LDAP_TF_MUTEX_TRYLOCK_CALLBACK  *ltf_mutex_trylock;
  LDAP_TF_SEMA_ALLOC_CALLBACK    *ltf_sema_alloc;
  LDAP_TF_SEMA_FREE_CALLBACK      *ltf_sema_free;
  LDAP_TF_SEMA_WAIT_CALLBACK      *ltf_sema_wait;
  LDAP_TF_SEMA_POST_CALLBACK      *ltf_sema_post;
  LDAP_TF_THREADID_CALLBACK      *ltf_threadid_fn;
};</pre>
Directory SDK for C supports only the LDAP_TF_TREADID_CALLBACK *ltf_threadid_fn function. You use this function callback in a multithreaded application to improve the performance of thread locking. The supported function must return an identifier that is unique to the calling thread, like pthread_self() does. If any of the other extra thread callback functions are set, the extra functions are ignored.
 
==== Setting Session Options  ====
 
After you set up the ldap_thread_fns structure, associate the structure with the current session. Call the ldap_set_option() function and pass LDAP_OPT_THREAD_FN_PTRS as the value of the option parameter. Pass a pointer to the ldap_thread_fns structure as the value of the optdata parameter.
<pre>#include &lt;stdio.h&gt;
#include &lt;malloc.h&gt;
#include &lt;errno.h&gt;
#include &lt;pthread.h&gt;
#include "ldap.h"
 
struct ldap_thread_fns tfns;
...
  /* Set up the ldap_thread_fns structure with pointers
    to the functions that you want called */
  memset( tfns, '\0', sizeof(struct ldap_thread_fns) );
 
  /* Specify the functions that you want called */
 
  /* Call the my_mutex_alloc() function whenever mutexes
    need to be allocated */
  tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc;
 
  /* Call the my_mutex_free() function whenever mutexes
    need to be destroyed */
  tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free;
 
  /* Call the pthread_mutex_lock() function whenever a
    thread needs to lock a mutex. */
  tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock;
 
  /* Call the pthread_mutex_unlock() function whenever a
    thread needs to unlock a mutex. */
  tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock;
 
  /* Call the get_errno() function to get the value of errno */
  tfns.ltf_get_errno = get_errno;
 
  /* Call the set_errno() function to set the value of errno */
  tfns.ltf_set_errno = set_errno;
 
  /* Call the get_ld_error() function to get error values from
    calls to functions in the libldap library */
  tfns.ltf_get_lderrno = get_ld_error;
 
  /* Call the set_ld_error() function to set error values for
    calls to functions in the libldap library */
  tfns.ltf_set_lderrno = set_ld_error;
 
  /* Dont pass any extra parameter to the functions for
    getting and setting libldap function call errors */
  tfns.ltf_lderrno_arg = NULL;
...
/* Set the session option that specifies the functions to call for
    multi-threaded clients */
if (ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) tfns)&nbsp;!= 0) {
  ldap_perror( ld, "ldap_set_option: thread pointers" );
}
...</pre>
If you also set up the ldap_extra_thread_fns structure, associate the structure with the current session. Call the ldap_set_option() function, passing LDAP_OPT_EXTRA_THREAD_FN_PTRS as the value of the option parameter. Also pass a pointer to the ldap_extra_thread_fns structure as the value of the optdata parameter.
 
=== POSIX Thread Client Application With Directory SDK for C  ===
 
The following example which uses pthreads (POSIX threads) on Solaris systems, is the source code for a multithreaded client. The client connects to a specified LDAP server. The client then creates several threads to perform multiple search and update operations simultaneously on the directory.
<pre>#include &lt;stdio.h&gt;
#include &lt;malloc.h&gt;
#include &lt;errno.h&gt;
#include &lt;pthread.h&gt;
#include &lt;synch.h&gt;
#include "ldap.h"
 
/* Authentication and search information. */
#define NAME        "cn=Directory Manager"
#define PASSWORD    "rtfm11111"
#define BASE        "dc=example,dc=com"
#define SCOPE        LDAP_SCOPE_SUBTREE
 
/* Function declarations */
static void *search_thread();
static void *modify_thread();
static void *add_thread();
static void *delete_thread();
static void set_ld_error();
static int  get_ld_error();
static void set_errno();
static int  get_errno();
static void tsd_setup();
 
/* Linked list of LDAPMessage structs for search results. */
typedef struct ldapmsgwrapper {
    LDAPMessage      *lmw_messagep;
    struct ldapmsgwrapper  *lmw_next;
} ldapmsgwrapper;
 
LDAP    *ld;
pthread_key_t  key;
 
main( int argc, char **argv )
{
  pthread_attr_t  attr;
  pthread_t  search_tid, search_tid2, search_tid3, search_tid4;
  pthread_t  modify_tid, add_tid, delete_tid;
  void    *status;
  struct ldap_thread_fns  tfns;
  struct ldap_extra_thread_fns extrafns;
  int rc;
 
  /* Check command-line syntax. */
  if ( argc&nbsp;!= 3 ) {
    fprintf( stderr, "usage:&nbsp;%s host&gt; port&gt;\n", argv[0] );
    exit( 1 );
  }
 
  /* Create a key. */
  if ( pthread_key_create( key, free )&nbsp;!= 0 ) {
    perror( "pthread_key_create" );
  }
  tsd_setup();
 
  /* Initialize the LDAP session. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) {
    perror( "ldap_init" );
    exit( 1 );
  }
 
  /* Set the function pointers for dealing with mutexes
    and error information. */
  memset( tfns, '\0', sizeof(struct ldap_thread_fns) );
  tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc;
  tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free;
  tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock;
  tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock;
  tfns.ltf_get_errno = get_errno;
  tfns.ltf_set_errno = set_errno;
  tfns.ltf_get_lderrno = get_ld_error;
  tfns.ltf_set_lderrno = set_ld_error;
  tfns.ltf_lderrno_arg = NULL;
 
  /* Set up this session to use those function pointers. */
  rc = ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) tfns );
  if ( rc  0 ) {
    fprintf( stderr,
            "ldap_set_option (LDAP_OPT_THREAD_FN_PTRS):&nbsp;%s\n",
            ldap_err2string( rc ) );
    exit( 1 );
  }
 
  /* Set the function pointers for working with semaphores. */
  memset( extrafns, '\0', sizeof(struct ldap_extra_thread_fns) );
  extrafns.ltf_mutex_trylock = (int (*)(void *)) = null;
  extrafns.ltf_sema_alloc = (void *(*)(void)) = null;
  extrafns.ltf_sema_free = (void (*)(void *)) = null;
  extrafns.ltf_sema_wait = (int (*)(void *)) = null;
  extrafns.ltf_sema_post = (int (*)(void *)) = null;
  extrafns.ltf_threadid_fn = (void * (*)(void) )pthread_self;
  /* Set up this session to use those function pointers. */
  rc = ldap_set_option( ld,
                        LDAP_OPT_EXTRA_THREAD_FN_PTRS,
                        (void *) extrafns );
  if ( rc  0 ) {
    fprintf( stderr,
            "ldap_set_option (LDAP_OPT_EXTRA_THREAD_FN_PTRS):&nbsp;%s\n",
            ldap_err2string( rc ) );
    exit( 1 );
  }
 
  /* Attempt to bind to the server. */
  rc = ldap_simple_bind_s( ld, NAME, PASSWORD );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s:&nbsp;%s\n", ldap_err2string( rc ) );
    exit( 1 );
  }
 
  /* Initialize the attribute. */
  if ( pthread_attr_init( attr )&nbsp;!= 0 ) {
    perror( "pthread_attr_init" );
    exit( 1 );
  }
 
  /* Specify that the threads are joinable. */
  pthread_attr_setdetachstate( attr, PTHREAD_CREATE_JOINABLE );
 
  /* Create seven threads: one for adding, one for modifying,
    one for deleting, and four for searching. */
  if (pthread_create(search_tid, attr, search_thread, "1")&nbsp;!= 0) {
    perror( "pthread_create search_thread" );
    exit( 1 );
  }
  if (pthread_create(modify_tid, attr, modify_thread, "2")&nbsp;!= 0) {
    perror( "pthread_create modify_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid2, attr, search_thread, "3")&nbsp;!= 0) {
    perror( "pthread_create search_thread2" );
    exit( 1 );
  }
  if (pthread_create(add_tid, attr, add_thread, "4" )&nbsp;!= 0) {
    perror( "pthread_create add_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid3, attr, search_thread, "5")&nbsp;!= 0) {
    perror( "phread_create search_thread3" );
    exit( 1 );
  }
  if (pthread_create(delete_tid, attr, delete_thread, "6")&nbsp;!= 0) {
    perror( "pthread_create delete_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid4, attr, search_thread, "7")&nbsp;!= 0) {
    perror( "pthread_create search_thread4" );
    exit( 1 );
  }
 
  /* Wait until these threads exit. */
  pthread_join( modify_tid, status );
  pthread_join( add_tid, status );
  pthread_join( delete_tid, status );
  pthread_join( search_tid, status );
  pthread_join( search_tid2, status );
  pthread_join( search_tid3, status );
  pthread_join( search_tid4, status );
}
 
/* Thread for searching the directory.
  The results are not printed out. */
static void *
search_thread( char *id )
{
  LDAPMessage  *res;
  LDAPMessage  *e;
  char    *a;
  char    **v;
  char    *dn;
  BerElement  *ber;
  int    i, rc, parse_rc, msgid, finished;
  int    num_entries, num_refs;
  void    *tsd;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
 
  printf( "Starting search_thread&nbsp;%s.\n", id );
  tsd_setup();
  /* Continually search the directory. */
  for (&nbsp;;; ) {
    printf( "Thread&nbsp;%s: Searching...\n", id );
    finished = 0;
    num_entries = 0;
    num_refs = 0;
    rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)",
      NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
    if ( rc&nbsp;!= LDAP_SUCCESS ) {
      fprintf( stderr, "Thread&nbsp;%s error: ldap_search:&nbsp;%s\n",
        id, ldap_err2string( rc ) );
      continue;
    }
 
    /* Iterate through the results.  In this example,
      don't print out all the results.  (It's easier
      to see the output from the other threads this way.) */
    while (&nbsp;!finished ) {
      rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
      switch ( rc ) {
      case -1:
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
        finished = 1;
        break;
      case 0:
        break;
      /* Keep track of the number of entries found. */
      case LDAP_RES_SEARCH_ENTRY:
        num_entries++;
        break;
      /* Keep track of the number of search references. */
      case LDAP_RES_SEARCH_REFERENCE:
        num_refs++;
        break;
      case LDAP_RES_SEARCH_RESULT:
        finished = 1;
        parse_rc = ldap_parse_result( ld, res, rc,
                    NULL, NULL, NULL, NULL, 1 );
        if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
          fprintf( stderr,
                  "Thread&nbsp;%s error: can't parse result code.\n",
                  id );
          break;
        } else {
          if ( rc&nbsp;!= LDAP_SUCCESS ) {
            fprintf( stderr,
                    "Thread&nbsp;%s error: ldap_search:&nbsp;%s\n",
                    id, ldap_err2string( rc ) );
          } else {
            printf( "Thread&nbsp;%s: Got&nbsp;%d results and&nbsp;%d references.\n",
                    id, num_entries, num_refs );
          }
        }
        break;
      default:
        break;
      }
    }
  }
}
 
/* Thread for modifying directory entries.
This thread searches for entries and randomly selects entries from
the search results for modification. */
static void *
modify_thread( char *id )
{
  LDAPMessage      *res;
  LDAPMessage      *e;
  int              i, modentry, num_entries, msgid, rc, parse_rc, finished;
  LDAPMod          mod;
  LDAPMod          *mods[2];
  char            *vals[2];
  char            *dn;
  ldapmsgwrapper  *list, *lmwp, *lastlmwp;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
 
  printf( "Starting modify_thread&nbsp;%s.\n", id );
  tsd_setup();
  rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)",
    NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    fprintf( stderr, "Thread&nbsp;%s error: Modify thread: "
    "ldap_search_ext:&nbsp;%s\n", id, ldap_err2string( rc ) );
    exit( 1 );
  }
  list = lastlmwp = NULL;
  finished = 0;
  num_entries = 0;
  while (&nbsp;!finished ) {
    rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
    switch ( rc ) {
    case -1:
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result:&nbsp;%s\n", ldap_err2string( rc ) );
      exit( 1 );
      break;
    case 0:
      break;
 
    /* Keep track of the number of entries found. */
    case LDAP_RES_SEARCH_ENTRY:
      num_entries++;
      if (( lmwp = (ldapmsgwrapper *)
        malloc( sizeof( ldapmsgwrapper ))) == NULL ) {
        fprintf( stderr, "Thread&nbsp;%s: Modify thread: Cannot malloc\n", id );
        exit( 1 );
      }
      lmwp-&gt;lmw_messagep = res;
      lmwp-&gt;lmw_next = NULL;
      if ( lastlmwp == NULL ) {
        list = lastlmwp = lmwp;
      } else {
        lastlmwp-&gt;lmw_next = lmwp;
      }
      lastlmwp = lmwp;
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      break;
    case LDAP_RES_SEARCH_RESULT:
      finished = 1;
      parse_rc = ldap_parse_result( ld, res, rc, NULL, NULL,
                                    NULL, NULL, 1 );
      if ( parse_rc&nbsp;!= LDAP_SUCCESS ) {
        fprintf( stderr,
                "Thread&nbsp;%s error: can't parse result code.\n",
                id );
        exit( 1 );
      } else {
        if ( rc&nbsp;!= LDAP_SUCCESS ) {
          fprintf( stderr,
                  "Thread&nbsp;%s error: ldap_search:&nbsp;%s\n",
                  id, ldap_err2string( rc ) );
        } else {
          printf( "Thread&nbsp;%s: Got&nbsp;%d results.\n", id, num_entries );
        }
      }
      break;
    default:
      break;
    }
  }
 
  /* Set up the modifications to be made. */
  mods[0] = mod;
  mods[1] = NULL;
  vals[0] = "bar";
  vals[1] = NULL;
 
  /* Modify randomly selected entries. */
  for (&nbsp;;; ) {
 
    /* Randomly select the entries. */
    modentry = rand()&nbsp;% num_entries;
    for ( i = 0, lmwp = list; lmwp&nbsp;!= NULL  i  modentry;
        i++, lmwp = lmwp-&gt;lmw_next ) {
      /* Keep iterating. */
    }
    if ( lmwp == NULL ) {
      fprintf( stderr,
          "Thread&nbsp;%s: Modify thread could not find entry&nbsp;%d of&nbsp;%d\n",
          id, modentry, num_entries );
      continue;
    }
    e = lmwp-&gt;lmw_messagep;
    printf( "Thread&nbsp;%s: Modify thread picked entry&nbsp;%d of&nbsp;%d\n",
            id, i, num_entries );
 
    /* Perform the modification. */
    dn = ldap_get_dn( ld, e );
    mod.mod_op = LDAP_MOD_REPLACE;
    mod.mod_type = "description";
    mod.mod_values = vals;
    printf( "Thread&nbsp;%s: Modifying (%s)\n", id, dn );
    rc = ldap_modify_ext_s( ld, dn, mods, NULL, NULL );
            if ( rc&nbsp;!= LDAP_SUCCESS ) {
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_modify_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    }
    free( dn );
  }
}
 
/* Thread for adding directory entries.
  This thread randomly generates DNs for entries and attempts to
  add them to the directory. */
static void *
add_thread( char *id )
{
  LDAPMod  mod[5];
  LDAPMod  *mods[6];
  char  dn[BUFSIZ], name[40];
  char  *cnvals[2], *snvals[2], *ocvals[3];
  int  i, rc;
 
  printf( "Starting add_thread&nbsp;%s.\n", id );
  tsd_setup();
 
  /* Set up the entry to be added. */
  for ( i = 0; i  5; i++ ) {
    mods[i] = mod[i];
  }
  mods[5] = NULL;
  mod[0].mod_op = 0;
  mod[0].mod_type = "cn";
  mod[0].mod_values = cnvals;
  cnvals[1] = NULL;
  mod[1].mod_op = 0;
  mod[1].mod_type = "sn";
  mod[1].mod_values = snvals;
  snvals[1] = NULL;
  mod[2].mod_op = 0;
  mod[2].mod_type = "objectclass";
  mod[2].mod_values = ocvals;
  ocvals[0] = "top";
  ocvals[1] = "person";
  ocvals[2] = NULL;
  mods[3] = NULL;
 
  /* Randomly generate DNs and add entries. */
  for (&nbsp;;; ) {
    sprintf( name, "%d", rand() );
    sprintf( dn, "cn=%s, " BASE, name );
    cnvals[0] = name;
    snvals[0] = name;
    printf( "Thread&nbsp;%s: Adding entry (%s)\n", id, dn );
    rc = ldap_add_ext_s( ld, dn, mods, NULL, NULL );
            if ( rc&nbsp;!= LDAP_SUCCESS ) {
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_add_ext_s:&nbsp;%s\n", ldap_err2string( rc ) );
    }
  }
}
 
/* Thread for deleting directory entries.
This thread randomly selects entries for deletion. */
static void *
delete_thread( char *id )
{
  LDAPMessage  *res;
  char    dn[BUFSIZ], name[40];
 
  printf( "Starting delete_thread&nbsp;%s.\n", id );
  tsd_setup();
 
  /* Randomly select entries for deletion. */
  for (&nbsp;;; ) {
    sprintf( name, "%d", rand() );
    sprintf( dn, "cn=%s, " BASE, name );
    printf( "Thread&nbsp;%s: Deleting entry (%s)\n", id, dn );
    if ( ldap_delete_ext_s( ld, dn, NULL, NULL )&nbsp;!= LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_delete_ext_s" );
    }
  }
}
 
/* Function for allocating a mutex. */
static void *
my_mutex_alloc( void )
{
  pthread_mutex_t  *mutexp;
  if ( (mutexp = malloc( sizeof(pthread_mutex_t) ))&nbsp;!= NULL ) {
    pthread_mutex_init( mutexp, NULL );
  }
  return( mutexp );
}
 
/* Function for freeing a mutex. */
static void
my_mutex_free( void *mutexp )
{
  pthread_mutex_destroy( (pthread_mutex_t *) mutexp );
  free( mutexp );
}
 
/* Error structure. */
struct ldap_error {
  int  le_errno;
  char  *le_matched;
  char  *le_errmsg;
};
 
/* Function to set up thread-specific data. */
static void
tsd_setup()
{
  void  *tsd;
  tsd = pthread_getspecific( key );
  if ( tsd&nbsp;!= NULL ) {
    fprintf( stderr, "tsd non-null!\n" );
    pthread_exit( NULL );
  }
  tsd = (void *) calloc( 1, sizeof(struct ldap_error) );
  pthread_setspecific( key, tsd );
}
 
/* Function for setting an LDAP error. */
static void
set_ld_error( int err, char *matched, char *errmsg, void *dummy )
{
  struct ldap_error *le;
  le = pthread_getspecific( key );
  le-&gt;le_errno = err;
  if ( le-&gt;le_matched&nbsp;!= NULL ) {
    ldap_memfree( le-&gt;le_matched );
  }
  le-&gt;le_matched = matched;
  if ( le-&gt;le_errmsg&nbsp;!= NULL ) {
    ldap_memfree( le-&gt;le_errmsg );
  }
  le-&gt;le_errmsg = errmsg;
}
 
/* Function for getting an LDAP error. */
static int
get_ld_error( char **matched, char **errmsg, void *dummy )
{
  struct ldap_error *le;
  le = pthread_getspecific( key );
  if ( matched&nbsp;!= NULL ) {
    *matched = le-&gt;le_matched;
  }
  if ( errmsg&nbsp;!= NULL ) {
    *errmsg = le-&gt;le_errmsg;
  }
  return( le-&gt;le_errno );
}
 
/* Function for setting errno. */
static void
set_errno( int err )
{
  errno = err;
}
 
/* Function for getting errno. */
static int
get_errno( void )
{
  return( errno );
}</pre>
== Directory SDK for C Data Type Reference  ==
 
This section contains reference material for the public data types and structures of Directory SDK for C. The first subsections detail the data types of the grouped into task categories. The last subsection is an alphabetical listing of the same information.
 
=== Conventions  ===
 
The following sections detail certain conventions and concepts used in Directory SDK for C.
 
==== Typographical Conventions  ====
 
The following table lists the typographical conventions used in the names of data types and structures.<br>
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Typographical Conventions in Data Types and Structures"
|+ Typographical Conventions in Data Types and Structures
|-
! scope="col" | Convention
! scope="col" | Description of Use
|-
| <tt>LeadingCaps</tt>
| Data structures needed to pass values to and from functions of Directory SDK For C. For consistency, use this <tt>typedef</tt> name for these structures, not their literal <tt>struct</tt> name.
|-
| <tt>ALL_CAPS</tt>
| Names of callback function prototypes which you can implement for extended functionality in your client application.
|-
| <tt>fns suffix</tt>
| Structures which hold the function pointers for callback functions, grouped by task.
|}
 
==== Deprecated Structures  ====
 
A deprecated API is one you should no longer use for new development, and should begin to phase out for applications you maintain. Deprecated interfaces may disappear in the major version following their deprecation.
 
=== Structure Summary by Task  ===
 
In the following sections the structures defined by Directory SDK For C are grouped into task categories.
 
==== BER Structures  ====
 
The structures listed in the following table represent data encoded using the Basic Encoding Rules (BER). The <tt>lber.h</tt> header file contains many other type definitions; the ones listed here are those likely to be handled directly. All others are used internally by the various functions of Directory SDK For C.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="BER Structures"
|+ BER Structures
|-
! scope="col" | Structure
! scope="col" | Description
|-
| berval
| berval represents binary data encoded using BER.
|-
| BerElement
| BerElement indicates the current position during a traversal of an attribute list.
|}
 
==== Structures for the Core API  ====
 
The structures listed in the following table are used by the core functions of Directory SDK For C. These structures are used directly as argument or return types by functions that provide the core functionality.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Core API Structures"
|+ Core API Structures
|-
! scope="col" | Structure
! scope="col" | Description
|-
| LDAP
| LDAP represents a connection handle to the LDAP server.
|-
| LDAPMessage
| LDAPMessage represents the results of an LDAP operation, a chain of search results, an entry in the search results, or a search reference in the search results.
|-
| LDAPMod
| LDAPMod specifies changes to an attribute in an directory entry.
|-
| LDAPControl
| LDAPControl represents a client or server control associated with an LDAP operation.
|-
| LDAPAPIInfo
| LDAPAPIInfo represents information about the version of Directory SDK For C being implemented
|-
| LDAPAPIFeatureInfo
| LDAPAPIFeatureInfo represents information about the extended features.
|}
 
==== Structures for API Extensions  ====
 
The structures listed in the following table are needed for extensions to the standard API within Directory SDK For C. These structures are used directly as arguments or return types by the functions that provide the extended functionality.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="API Extension Structures"
|+ API Extension Structures
|-
! scope="col" | Structure
! scope="col" | Description
|-
| LDAPsortkey
| LDAPsortkey represents a server control used to specify that the server should sort the search results before sending them back to the client.
|-
| LDAPVirtualList
| LDAPVirtualList specifies the information that can be used to create a virtual list view control.
|-
| LDAPURLDesc
| LDAPURLDesc represents the components of an LDAP URL.
|-
| LDAPFiltInfo
| LDAPFiltInfo represents information about a filter in a filter configuration file.
|-
| LDAPFiltDesc
| LDAPFiltDesc is a type of structure returned when you call ldap_init_getfilter to load a filter configuration file.
|-
| FriendlyMap
| FriendlyMap represents the mapping between a list of standard attribute names and their user friendly counterparts.
|-
| LDAPMemCache
| LDAPMemCache represents an in-memory, client-side cache.
|-
| LDAPpwdpolicy
| LDAPpwdpolicy represents password policy information concerning an entry.
|-
| LDAPuserstatus
| LDAPuserstatus represents account availability information.
|}
 
'''Note:''' This prototype for a callback function retrieves authentication information when automatically following referrals to other servers.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Referral Binding Data Type"
|+ Referral Binding Data Type
|-
! scope="col" | Data Type
! scope="col" | Description
|-
| LDAP_REBINDPROC_CALLBACK
| Retrieves authentication information when following referrals to other servers.
|}
 
==== Client-Side Sorting Callbacks  ====
 
The prototype structures listed in the following table are extensions to Directory SDK For C that implement client side sorting of entries.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Client-side Sorting Structures"
|+ Client-side Sorting Structures
|-
! scope="col" | Data Type
! scope="col" | Description
|-
| LDAP_KEYGEN_CALLBACK
| Function prototype that generates the sorting key for each entry to be sorted, usually by extracting a value out of an entry.
|-
| LDAP_KEYCMP_CALLBACK
| Function prototype to compare 2 keys (for ordering).
|-
| LDAP_KEYFREE_CALLBACK
| Function prototype that frees the memory allocated during the <tt>KEYGEN</tt> callback.
|-
| LDAP_CMP_CALLBACK
| Function prototype to sort a specified set of entries.
|-
| LDAP_VALCMP_CALLBACK
| Function prototype to sort a specified set of values.
|}
 
==== Extended I/O Control  ====
 
The following table lists the prototypes and structures used in the extended I/O control, an extension to the standard API.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Structures and Prototypes for Extended I/O Functionality"
|+ Structures and Prototypes for Extended I/O Functionality
|-
! scope="col" | Data Type
! scope="col" | Description
|-
| ldap_x_ext_io_fns
| This structure holds extended I/O function pointers.
|-
| LDAP_X_PollFD
| An LDAP file descriptor similar to that of poll().
|-
| LDAP_X_EXTIOF_CONNECT_CALLBACK
| Function prototype for a callback that opens a socket connection.
|-
| LDAP_X_EXTIOF_CLOSE_CALLBACK
| Function prototype for a callback that closes a socket connection.
|-
| LDAP_X_EXTIOF_POLL_CALLBACK
| Function prototype for a callback that surveys a server about a particular event.
|-
| LDAP_X_EXTIOF_NEWHANDLE_CALLBACK
| Function prototype for a callback that defines a new session handle.
|-
| LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK
| Function prototype for a callback that disposes of a session handle.
|-
| ldap_x_hostlist_status
| This structure holds utility functions for parsing space-separated host lists.
|}
 
==== Memory Management Control  ====
 
The prototypes and structures listed in theh following table are used in memory management control, an extension to the standard API. They allow you to specify your own memory allocation mechanisms and functions.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Memory Management Data Types"
|+ Memory Management Data Types
|-
! scope="col" | Data Type
! scope="col" | Description
|-
| ldap_memalloc_fns
| This structure holds the memory allocation callback functions.
|-
| LDAP_MALLOC_CALLBACK LDAP_CALLOC_CALLBACKLDAP_REALLOC_CALLBACK LDAP_FREE_CALLBACK
| These callbacks allow developers to specify their own memory allocation mechanisms.
|}
 
==== Thread Signaling Controls  ====
 
The prototypes and structures listed in the following table are used in the thread signaling control, an extension to the standard API.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Thread Signaling Control Data Types"
|+ Thread Signaling Control Data Types
|-
! scope="col" | Data Type
! scope="col" | Description
|-
| ldap_thread_fns
| Structure that contains a set of pointers to functions you want to use when writing a multithreaded client.
|-
| LDAP_TF_MUTEX_ALLOC_CALLBACK
| Function prototype for allocating a mutex.
|-
| LDAP_TF_MUTEX_FREE_CALLBACK
| Function prototype freeing a mutex.
|-
| LDAP_TF_MUTEX_LOCK_CALLBACK
| Function prototype for locking critical sections of code.
|-
| LDAP_TF_MUTEX_UNLOCK_CALLBACK
| Function prototype for unlocking critical sections of code.
|-
| LDAP_TF_GET_ERRNO_CALLBACK
| Function prototype for getting the value of the <tt>errno</tt> variable.
|-
| LDAP_TF_SET_ERRNO_CALLBACK
| Function prototype for setting the value of the <tt>errno</tt> variable.
|-
| LDAP_TF_GET_LDERRNO_CALLBACK
| Function prototype for getting error values from calls to functions in the <tt>libldap</tt> library.
|-
| LDAP_TF_SET_LDERRNO_CALLBACK
| Function prototype for setting error values from calls to functions in the <tt>libldap</tt> library.
|-
| ldap_extra_thread_fns
| Structure that contains a set of pointers to additional functions you want to use when writing a multithreaded client.
|-
| LDAP_TF_MUTEX_TRYLOCK_CALLBACK
| Function prototype for attempting to lock a mutex.
|-
| LDAP_TF_SEMA_ALLOC_CALLBACK
| Function prototype for allocating a semaphore.
|-
| LDAP_TF_SEMA_FREE_CALLBACK
| Function prototype for freeing a semaphore.
|-
| LDAP_TF_SEMA_WAIT_CALLBACK
| Function prototype for waiting for the value of a semaphore to be greater than 0.
|-
| LDAP_TF_SEMA_POST_CALLBACK
| Function prototype for incrementing the value of a semaphore.
|-
| LDAP_TF_THREADID_CALLBACK
| Function prototype to return an identifier that is unique to the calling thread.
|}
 
==== Deprecated and Outdated Types  ====
 
Deprecated types are those being dropped from the standard or from the extensions to Directory SDK For C. They are not guaranteed to be defined in future versions of the API. However, all of these types are still defined in this version for backwards compatibility. The following table lists the deprecated prototypes.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Deprecated Data Types and Their Replacements"
|+ Deprecated Data Types and Their Replacements
|-
! scope="col" | Data Type
! scope="col" | Replacement
|-
| LDAP_CANCELPROC_CALLBACK
| Provides a way to be cancel a process, for example, by a user or because some other condition occurs.
|-
| ldap_cache_fns<br>LDAP_CF_BIND_CALLBACK<br>LDAP_CF_UNBIND_CALLBACK<br>LDAP_CF_SEARCH_CALLBACK<br>LDAP_CF_COMPARE_CALLBACK<br>LDAP_CF_ADD_CALLBACK<br>LDAP_CF_DELETE_CALLBACK<br>LDAP_CF_MODIFY_CALLBACK<br>LDAP_CF_MODRDN_CALLBACK<br>LDAP_CF_RESULT_CALLBACK<br>LDAP_CF_FLUSH_CALLBACK
| ldap_cache_fns is a deprecated structure and the <tt>typedef</tt> declarations associated with it have also been deprecated.
|-
| LDAPVersion
| Replaced by the LDAPAPIInfo type which is returned by the ldap_get_option function using the <tt>LDAP_OPT_API_INFO</tt> option.
|}
 
While not officially deprecated, other data types are outdated because they have superseded by new types. Outdated types may become deprecated in future releases of Directory SDK For C. The following table lists the outdated types and the newer types which implement the same functionality.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Outdated Types and Their New Equivalents"
|+ Outdated Types and Their New Equivalents
|-
! scope="col" | Old Data Type
! scope="col" | New, Equivalent Data Type
|-
| LDAPHostEnt<br>LDAP_DNSFN_GETHOSTBYNAME<br>LDAP_DNSFN_GETHOSTBYADDR<br>ldap_dns_fns
| The DNS resolver callbacks are an outdated extension to the API. The new way of specifying host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK prototype.
|-
| LDAP_IOF_CLOSE_CALLBACK<br>LDAP_IOF_CONNECT_CALLBACK<br>LDAP_IOF_IOCTL_CALLBACK<br>LDAP_IOF_READ_CALLBACK<br>LDAP_IOF_SELECT_CALLBACK<br>LDAP_IOF_SOCKET_CALLBACK<br>LDAP_IOF_SSL_ENABLE_CALLBACK<br>LDAP_IOF_WRITE_CALLBACK<br>ldap_io_fns
| Replaced by the types for extended I/O functionality detailed in the section on Extended I/O Control.
|}
 
=== Structures Alphabetically  ===
 
The following sections detail the structures and controls of Directory SDK For C in alphabetical order.
 
==== berval  ====
 
<tt>berval</tt> is a structure that represents binary data encoded using simplified Basic Encoding Rules (BER).
 
===== Description  =====
 
Use a <tt>berval</tt> structure when working with attributes that contain binary data (such as a graphic or audio file). The data and the size of the data are both included in a <tt>berval</tt> structure.
<pre>typedef struct berval {
  unsigned long bv_len;
  char *bv_val;
};</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="berval Field Descriptions"
|+ berval Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>bv_len</tt>
| The length of the data in bytes.
|-
| <tt>bv_val</tt>
| A pointer to the binary data itself.
|}
 
==== BerElement  ====
 
The <tt>BerElement</tt> structure represents data encoded using the Basic Encoding Rules (BER).
 
===== Description  =====
 
You use this opaque data type to keep track of the current attribute during the traversal of an attribute list. Calling the ldap_first_attribute() function allocates memory for a <tt>BerElement</tt> structure and initializes it to select the values of the first attribute in the entry.
 
Subsequently, ldap_next_attribute() is called to obtain the name of each remaining attribute and set <tt>BerElement</tt> to select their values. Once <tt>BerElement</tt> has been set to select an attribute's values, ldap_get_values() can be used to obtain all of them from the buffer.
 
When you are done reading the attributes, you need to free the <tt>BerElement</tt> structure from memory by calling the ldap_ber_free() function. (A <tt>BerElement</tt> structure can also be allocated by calling the ber_alloc_t or the ber_init function. In these cases, free the memory allocated to the <tt>BerElement</tt> structure by using the ber_free() function.)
 
'''Note:''' The <tt>BerElement</tt> definition is not completely exposed in <tt>lber.h</tt> because the fields within the structure are not intended to be accessible to clients.
 
==== FriendlyMap  ====
 
<tt>FriendlyMap</tt> represents the mapping between a list of standard attribute names and their user-friendly counterparts. For example, you can represent the list of two-letter state codes (CA, IA) with their corresponding state names (California, Iowa), or map Country ISO codes to the full country names, in a <tt>FriendlyMap</tt> structure.
 
'''Note:'''
 
*ldap_friendly_name allocates() a <tt>FriendlyMap</tt> structure and reads a list of standard attribute names and their user friendly counterparts from a file.
*ldap_free_friendlymap() frees the memory allocated for a <tt>FriendlyMap</tt> structure.
 
==== LDAP  ====
 
<tt>LDAP</tt> is an opaque data type representing a connection with the LDAP server. It is initialized through a call to either the ldap_init() or ldapssl_init() function.
 
<tt>LDAP</tt> maintains the state of an LDAP session for the duration of the connection. When you call functions that perform LDAP operations on an LDAP server (for example, ldap_search_ext() to search the directory or ldap_modify_ext() to update an entry), you need to pass a pointer to this connection handle.
 
With the <tt>LDAP</tt> structure, you can also:
 
*Call the ldap_get_option() and ldap_set_option() functions to view or modify the properties of the connection.
*Call the ldap_unbind() or ldap_unbind_s() function to close the connection and free the <tt>LDAP</tt> structure.
 
'''Note:''' <tt>LDAP</tt> is not completely defined in <tt>ldap-standard.h</tt> because the fields within the structure are not intended to be accessible to clients.
 
==== LDAPAPIFeatureInfo  ====
 
<tt>LDAPAPIFeatureInfo</tt> is a structure that represents information about the extended features of Directory SDK For C. &lt;title&gt;LDAPAPIFeatureInfo Definition
<pre>#define LDAP_FEATURE_INFO_VERSION
typedef struct ldap_apifeature_info {
  int  ldapaif_info_version;      /* version of this struct (1) */
  char  *ldapaif_name;              /* name of supported feature */
  int  ldapaif_version;            /* revision of supported feature */
} LDAPAPIFeatureInfo;</pre>
The <tt>LDAPAPIFeatureInfo</tt> structure can be retrieved by using a sequence like the one displayed below.
<pre>LDAPAPIFeatureInfo ldfi;
ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW";
if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &amp;ldfi ) == 0 )</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPAPIFeatureInfo Structure Parameters"
|+ LDAPAPIFeatureInfo Structure Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ldapaif_info_version</tt>
| Specifies the version number of the <tt>LDAPAPIFeatureInfo</tt> structure. This must be set to <tt>LDAP_FEATURE_INFO_VERSION</tt> before call to ldap_get_option() is performed.
|-
| <tt>ldapaif_name</tt>
| Pointer to <tt>NULL</tt> terminated string that specifies the name of the supported feature.
|-
| <tt>ldapaif_version</tt>
| Specifies the version number of the supported feature.
|}
 
==== LDAPAPIInfo  ====
 
<tt>LDAPAPIInfo</tt> is a structure that represents information about the API and supported extensions.
<pre>#define LDAP_API_INFO_VERSION
typedef struct ldapapiinfo {
  int  ldapai_info_version;    /* version of LDAPAPIInfo (1) */
  int  ldapai_api_version;      /* revision of API supported */
  int  ldapai_protocol_version; /* highest LDAP version supported */
  char **ldapai_extensions;    /* names of API extensions */
  char *ldapi_vendor_name;      /* name of supplier */
  int  ldapai_vendor_version;  /* supplier-specific version x 100 */
} LDAPAPIInfo;</pre>
The <tt>LDAPAPIInfo</tt> structure can be retrieved by using a sequence like the one displayed in the following example.
<pre>LDAPAPIInfo ldai;
ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
if ( ldap_get_option( NULL, LDAP_OPT_API_INFO, &amp;ldia ) == 0 ) ...</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPAPIInfo Structure Parameters"
|+ LDAPAPIInfo Structure Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ldapai_info_version</tt>
| Specifies the version number of the <tt>LDAPAPIInfo</tt> structure. This must be set to <tt>LDAP_API_INFO_VERSION</tt> before a call to ldap_get_option is performed.
|-
| <tt>ldapai_api_version</tt>
| Specifies the version number of the API that is supported.
|-
| <tt>ldapai_protocol_version</tt>
| Specifies the latest LDAP version supported by the LDAP library.
|-
| <tt>ldapai_extensions</tt>
| Points to a <tt>NULL</tt> terminated array of character strings that names the supported LDAP extensions. If none are supported, this field is set to <tt>NULL</tt>. The application is responsible for freeing this memory by calling the ldap_value_free function.
|-
| <tt>ldapai_vendor_name</tt>
| Pointer to a NULL-terminated string that contains the vendor's name. Call the ldap_memfree function to free the memory.
|-
| <tt>ldapai_vendor_version</tt>
| Specifies the vendor’s version of the LDAP libraries.
|}
 
==== ldap_cache_fns  ====
 
<tt>ldap_cache_fns</tt> is a deprecated structure. The following are also deprecated:
 
*LDAP_CF_ADD_CALLBACK
*LDAP_CF_BIND_CALLBACK
*LDAP_CF_COMPARE_CALLBACK
*LDAP_CF_DELETE_CALLBACK
*LDAP_CF_FLUSH_CALLBACK
*LDAP_CF_MODIFY_CALLBACK
*LDAP_CF_MODRDN_CALLBACK
*LDAP_CF_RESULT_CALLBACK
*LDAP_CF_SEARCH_CALLBACK
*LDAP_CF_UNBIND_CALLBACK
 
===== See Also  =====
 
See the ldap_memcache_*() functions for current usage.
 
==== LDAP_CALLOC_CALLBACK  ====
 
This callback function prototype of ldap_memalloc_fns() represents memory allocation.
 
===== See Also  =====
 
ldap_memalloc_fns
 
==== LDAP_CANCELPROC_CALLBACK  ====
 
This callback function prototype is deprecated.
 
===== See Also  =====
 
ldap_ufn_search_c, ldap_ufn_search_ct
 
==== LDAP_CF_ADD_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_BIND_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_COMPARE_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_DELETE_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_FLUSH_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_MODIFY_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_MODRDN_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_RESULT_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_SEARCH_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CF_UNBIND_CALLBACK  ====
 
This callback function prototype of ldap_cache_fns is deprecated.
 
==== LDAP_CMP_CALLBACK  ====
 
<tt>LDAP_CMP_CALLBACK</tt> specifies the prototype for a comparison callback function used when sorting values. If you define a function with this prototype and specify it when calling ldap_sort_entries() or ldap_multisort_entries(), it will be called by your LDAP client to sort a specified set of entries.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_CMP_CALLBACK)(const char*, const char*);</pre>
===== See Also  =====
 
ldap_sort_entries(), ldap_multisort_entries()
 
==== LDAPControl  ====
 
<tt>LDAPControl</tt> represents a client or server control associated with an LDAP operation. If set as a server control, it is sent to the server along with operation requests; if set as a client control, it is interpreted locally by the client.
 
Controls are part of the LDAP v3. You can use a control to extend the functionality of an LDAP operation. There are two basic types of controls described in the LDAP v3:
 
*''Server controls'' are controls that are sent from the client to the server along with an LDAP request. (In some cases, a server can include a control in the response it sends back to the client.) For example, you can include a server control in a search request to specify that you want the server to sort the search results before sending them back.
*''Client controls'' are controls that can extend the client but are never sent to the server. As a general example, you might be able to pass a client control to an LDAP API function, which might parse the control and use the data that you’ve specified in the control.
 
Directory SDK For C does not currently support any client controls.
<pre>typedef struct ldapcontrol {
  char *ldctl_oid;
  struct berval ldctl_value;
  char ldctl_iscritical;
} LDAPControl;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPControl Field Descriptions"
|+ LDAPControl Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>ldctl_oid</tt>
| Object identifier (OID) of the control.
|-
| <tt>ldctl_value</tt>
| berval structure containing data associated with the control. If you want to specify a zero-length value, set <tt>ldctl_value.bv_len</tt> to <tt>0</tt> and <tt>ldctl_value.bv_val</tt> to a zero-length string. To indicate that no data is associated with the control, set <tt>ldctl_value.bv_val</tt> to <tt>NULL</tt>.
|-
| <tt>ldctl_iscritical</tt>
| Specifies whether or not the control is critical to the operation. This field can have one of the following values:
*A non-zero value specifies that the control is critical to the operation.
*<tt>0</tt> specifies that the control is not critical to the operation.
 
|}
 
==== LDAP_DNSFN_GETHOSTBYADDR  ====
 
<tt>LDAP_DNSFN_GETHOSTBYADDR</tt> specifies the prototype for a callback function equivalent to the gethostbyaddr_r() function available on some UNIX platforms.
 
'''Note:''' If you define a function with this prototype and set it in the ldap_dns_fns structure, your function will be called by the SDK on behalf of your LDAP client if it needs to get the host name of the LDAP server to which it is connected.
 
In this version of Directory SDK For C, the functions of the API never call this function, and your implementation will never be executed. Therefore, its implementation is optional.
<pre>typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK
  LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type,
  LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
  void *extradata );</pre>
==== LDAP_DNSFN_GETHOSTBYNAME  ====
 
<tt>LDAP_DNSFN_GETHOSTBYNAME</tt> specifies the prototype for a callback function equivalent to the gethostbyname_r() function available on some UNIX platforms.
 
'''Note:''' If you define a function with this prototype and set it in the <tt>ldap_dns_fns</tt> structure, your function will be called by Directory SDK For C on behalf of your LDAP client to get the host entry for the LDAP server when connecting to the server.
<pre>typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK
  LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type,
  LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
  void *extradata );</pre>
==== ldap_dns_fns  ====
 
<tt>ldap_dns_fns</tt> contains a set of pointers to DNS functions and is equivalent to the gethostbyname_r() and gethostbyaddr_r() functions available on some UNIX platforms.
 
'''Note:''' While not officially deprecated, the functionality of this structure is superseded by the extended I/O functions. The new way of specifying host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK prototype.
 
===== Description  =====
 
You can use this structure if you want Directory SDK For C to call these functions when looking up the host name or IP address for the LDAP server. For example, you could use this to call versions of the DNS functions that are safe for use in a multithreaded application. The function must have the prototype specified by LDAP_DNSFN_GETHOSTBYADDR.
 
If <tt>NULL</tt>, the standard built-in OS routine is used. After you set the fields in this structure, you can register the functions for use by calling the ldap_set_option function and setting the <tt>LDAP_OPT_DNS_FN_PTRS</tt> option to this structure.
<pre>struct ldap_dns_fns {
  void *lddnsfn_extradata;
  int lddnsfn_bufsize;
  LDAP_DNSFN_GETHOSTBYNAME *lddnsfn_gethostbyname;
  LDAP_DNSFN_GETHOSTBYADDR *lddnsfn_gethostbyaddr;
};</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_dns_fns Field Descriptions"
|+ ldap_dns_fns Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>lddnsfn_extradata</tt>
| Value passed in the <tt>extradata</tt> argument of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME function calls.
|-
| <tt>lddnsfn_bufsize</tt>
| Specifies the size of the buffer that you want passed to your DNS callback function. Your LDAP client passes this value as the <tt>buflen</tt> argument of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME function calls.
|-
| <tt>lddnsfn_gethostbyname</tt>
| Function pointer for getting the host entry for the LDAP server. This function is called by the client when connecting to the server if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_DNSFN_GETHOSTBYNAME. If <tt>NULL</tt>, the standard built-in OS routine is used.
|-
| <tt>lddnsfn_gethostbyaddr</tt>
| Function pointer for getting the host name of the LDAP server. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>.
|}
 
==== ldap_extra_thread_fns  ====
 
The <tt>ldap_extra_thread_fns</tt> structure contains a set of pointers to additional functions that you can use when writing a multithreaded client. Your client calls these functions when getting results from the LDAP structure.
<pre>struct ldap_extra_thread_fns {
  LDAP_TF_MUTEX_TRYLOCK_CALLBACK  *ltf_mutex_trylock;
  LDAP_TF_SEMA_ALLOC_CALLBACK    *ltf_sema_alloc;
  LDAP_TF_SEMA_FREE_CALLBACK      *ltf_sema_free;
  LDAP_TF_SEMA_WAIT_CALLBACK      *ltf_sema_wait;
  LDAP_TF_SEMA_POST_CALLBACK      *ltf_sema_post;
  LDAP_TF_THREADID_CALLBACK      *ltf_threadid_fn;
};</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_extra_thread_fns Field Descriptions"
|+ ldap_extra_thread_fns Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>ltf_mutex_trylock</tt>
| Function pointer for attempting to lock a mutex. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_MUTEX_TRYLOCK_CALLBACK.
|-
| <tt>ltf_sema_alloc</tt>
| Function pointer for allocating a semaphore. This finction is called by the client if needed when the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_SEMA_ALLOC_CALLBACK.
|-
| <tt>ltf_sema_free</tt>
| Function pointer for freeing a semaphore. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_SEMA_FREE_CALLBACK.
|-
| <tt>ltf_sema_wait</tt>
| Function pointer for waiting for the value of a semaphore to be greater than 0. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_SEMA_WAIT_CALLBACK.
|-
| <tt>ltf_sema_post</tt>
| Function pointer for incrementing the value of a semaphore. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_SEMA_POST_CALLBACK.
|-
| <tt>ltf_threadid_fn</tt>
| Function pointer that is called to retrieve the unique identifier for the calling thread. If this is <tt>NULL</tt>, it is not used. An example of a similar function in the POSIX threads standard is pthread_self(). The function must have the prototype specified by LDAP_TF_THREADID_CALLBACK.
|}
 
==== LDAPFiltDesc  ====
 
<tt>LDAPFiltDesc</tt> is a structure that is returned when you call ldap_init_getfilter() to load a filter configuration file.
 
'''Note:''' The <tt>LDAPFiltDesc</tt> definition is not completely exposed in <tt>ldap-extension.h</tt> because the fields within the structure are not intended to be accessible to clients.
 
===== Description  =====
 
After calling the ldap_init_getfilter() function, use the pointer to the returned <tt>LDAPFiltDesc</tt> structure in subsequent calls to get information about filters in the filter configuration file.
 
==== LDAPFiltInfo  ====
 
<tt>LDAPFiltInfo</tt> represents information about a filter in the filter configuration file.
 
===== Description  =====
 
When you call the ldap_getfirstfilter() or ldap_getnextfilter() functions to get a filter from the filter configuration file, they return a pointer to an <tt>LDAPFiltInfo</tt> structure containing the information about the filter.
<pre>typedef struct ldap_filt_info {
  char *lfi_filter;
  char *lfi_desc;
  int lfi_scope;
  int lfi_isexact;
  struct ldap_filt_info *lfi_next;
} LDAPFiltInfo;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPFilterInfo Field Descriptions"
|+ LDAPFilterInfo Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>lfi_filter</tt>
| The filter, for example <tt>(cn=d*)</tt>.
|-
| <tt>lfi_desc</tt>
| Description of the filter, also the fifth field in the filter configuration file.
|-
| <tt>lfi_scope</tt>
| The scope of the filter, also the sixth field in the filter configuration file, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> specifies that the search will be restricted to the current DN.
*<tt>LDAP_SCOPE_ONELEVEL</tt> specifies that the search will be restricted to the entries at the level beneath the current DN.
*<tt>LDAP_SCOPE_SUBTREE</tt> specifies that the search will encompass entries at all levels beneath the current DN. If the scope of the filter is not specified in the filter configuration file, the scope is <tt>LDAP_SCOPE_SUBTREE</tt> by default.
 
|-
| <tt>lfi_isexact</tt>
| Specifies whether or not the filter is an exact filter, where an exact filter contains no wildcard characters and does not match words that sound alike:
*<tt>0</tt> specifies that the filter is not an exact filter.
*<tt>1</tt> specifies that the filter is an exact filter.
 
|-
| <tt>lfi_next</tt>
| Pointer to the <tt>LDAPFiltInfo</tt> structure representing the next filter in the filter list.
|}
 
The following example prints out information about a filter.
<pre>LDAPFiltInfo *lfip;
/* Print out the filter */
printf( "Filter:\t%s\n", lfdp-&gt;lfd_filter );
printf( "Description:\t%s\n", lfdp-&gt;lfd_desc );</pre>
For example, in the filter configuration file, if the first filter that applies to the value <tt>@</tt> is:
<pre>"@" " " "(mail=%v)" "email address is" "onelevel"</pre>
The code prints out:
<pre>Filter: (mail=@)
Description: email address is</pre>
==== LDAP_FREE_CALLBACK  ====
 
This callback function prototype of ldap_memalloc_fns is used to free allocated memory.
 
===== See Also  =====
 
ldap_memalloc_fns
 
==== LDAPHostEnt  ====
 
The <tt>LDAPHostEnt</tt> structure represents an entry for a host found by a domain name server.
 
'''Note:''' This type is similar to the <tt>hostent</tt> structure returned by functions such as gethostbyname_r() on UNIX systems.
 
If you are writing your own DNS functions for use by the client, they should return the host entry in this type of structure.
 
The fields in this structure should point to addresses within the buffer that is passed to the DNS callback (referenced in the LDAP callback function). This buffer contains the host data. The pointers in the hostent structure returned by the function point to the data in this buffer.
<pre>typedef struct LDAPHostEnt {
  char *ldaphe_name;
  char **ldaphe_aliases;
  int ldaphe_addrtype;
  int ldaphe_length;
  char **ldaphe_addr_list;
} LDAPHostEnt;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPHostEnt Field Descriptions"
|+ LDAPHostEnt Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>ldaphe_name</tt>
| Canonical name of the host
|-
| <tt>ldaphe_aliases</tt>
| List of aliases for this host
|-
| <tt>ldaphe_addrtype</tt>
| Address type of the host
|-
| <tt>ldaphe_length</tt>
| Length of the address
|-
| <tt>ldaphe_addr_list</tt>
| List of addresses for this host as returned by the name server
|}
 
===== See Also  =====
 
LDAP_DNSFN_GETHOSTBYADDR, LDAP_DNSFN_GETHOSTBYNAME
 
==== LDAP_IOF_CLOSE_CALLBACK  ====
 
<tt>LDAP_IOF_CLOSE_CONNECT_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard close() system call.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_CLOSE_CALLBACK )( LBER_SOCKET );</pre>
==== LDAP_IOF_CONNECT_CALLBACK  ====
 
<tt>LDAP_IOF_CONNECT_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard connect() network I/O function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_CONNECT_CALLBACK )( LBER_SOCKET,
  struct sockaddr *, int );</pre>
==== LDAP_IOF_IOCTL_CALLBACK  ====
 
<tt>LDAP_IOF_IOCTL_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard ioctl() system call.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_IOCTL_CALLBACK)( LBER_SOCKET, int, ... );</pre>
==== LDAP_IOF_READ_CALLBACK  ====
 
<tt>LDAP_IOF_READ_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard read() I/O function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_READ_CALLBACK)( LBER_SOCKET, void *, int );</pre>
==== LDAP_IOF_SELECT_CALLBACK  ====
 
<tt>LDAP_IOF_SELECT_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard select() I/O function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SELECT_CALLBACK)( int, fd_set *, fd_set *,
  fd_set *, struct timeval * );</pre>
==== LDAP_IOF_SOCKET_CALLBACK  ====
 
<tt>LDAP_IOF_SOCKET_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard socket() network I/O function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef LBER_SOCKET (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SOCKET_CALLBACK)( int, int, int );</pre>
==== LDAP_IOF_SSL_ENABLE_CALLBACK  ====
 
<tt>LDAP_IOF_SSL_ENABLE_CALLBACK</tt> specifies the prototype for a callback function equivalent to the ssl_enable() function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SSL_ENABLE_CALLBACK )( LBER_SOCKET );</pre>
==== LDAP_IOF_WRITE_CALLBACK  ====
 
<tt>LDAP_IOF_WRITE_CALLBACK</tt> specifies the prototype for a callback function equivalent to the standard write() I/O function.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK LDAP_IOF_WRITE_CALLBACK)
  ( LBER_SOCKET, const void *, int );</pre>
==== ldap_io_fns  ====
 
The <tt>ldap_io_fns</tt> structure contains a set of pointers to input/output functions that you want used with SDK. You need to set up this structure if you want to connect to the LDAP server using a Secure Sockets Layer (SSL).
<pre>struct ldap_io_fns {
  LDAP_IOF_READ_CALLBACK *liof_read;
  LDAP_IOF_WRITE_CALLBACK *liof_write;
  LDAP_IOF_SELECT_CALLBACK *liof_select;
  LDAP_IOF_SOCKET_CALLBACK *liof_socket;
  LDAP_IOF_IOCTL_CALLBACK *liof_ioctl;
  LDAP_IOF_CONNECT_CALLBACK *liof_connect;
  LDAP_IOF_CLOSE_CALLBACK *liof_close;
  LDAP_IOF_SSL_ENABLE_CALLBACK *liof_ssl_enable;
};</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_io_fns Field Descriptions"
|+ ldap_io_fns Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>liof_read</tt>
| Function pointer to the equivalent of the standard <tt>read()</tt> I/O function. The function must have the prototype specified by LDAP_IOF_READ_CALLBACK.
|-
| <tt>liof_write</tt>
| Function pointer to the equivalent of the standard <tt>write()</tt> I/O function. The function must have the prototype specified by LDAP_IOF_WRITE_CALLBACK.
|-
| <tt>liof_select</tt>
| Function pointer to the equivalent of the standard <tt>select()</tt> I/O function. The function must have the prototype specified by LDAP_IOF_SELECT_CALLBACK.
|-
| <tt>liof_socket</tt>
| Function pointer to the equivalent of the standard <tt>socket()</tt> network I/O function. The function must have the prototype specified by LDAP_IOF_SOCKET_CALLBACK.
|-
| <tt>liof_ioctl</tt>
| Function pointer to the equivalent of the standard <tt>ioctl()</tt> system call. The function must have the prototype specified by LDAP_IOF_IOCTL_CALLBACK.
|-
| <tt>liof_connect</tt>
| Function pointer to the equivalent of the standard <tt>connect()</tt> network I/O function. The function must have the prototype specified by LDAP_IOF_CONNECT_CALLBACK.
|-
| <tt>liof_close</tt>
| Function pointer to the equivalent of the standard <tt>close()</tt> system call. The function must have the prototype specified by LDAP_IOF_CLOSE_CALLBACK.
|-
| <tt>liof_ssl_enable</tt>
| Function pointer to the equivalent of the <tt>ssl_enable()</tt> function. The function must have the prototype specified by LDAP_IOF_SSL_ENABLE_CALLBACK.
|}
 
===== LDAP_KEYCMP_CALLBACK  =====
 
<tt>LDAP_KEYCMP_CALLBACK</tt> specifies the prototype for a callback function to sort a specified set of entries.
 
===== Definition  =====
 
If you define a function with this prototype and specify it when calling ldap_keysort_entries(), the function will be called by your LDAP client to sort a specified set of entries.
 
===== See Also  =====
 
ldap_keysort_entries
 
==== LDAP_KEYFREE_CALLBACK  ====
 
<tt>LDAP_KEYFREE_CALLBACK</tt> specifies the prototype for a callback function that frees a sorting key.
 
===== Description  =====
 
ldap_keysort_entries() requires a function pointer that matches the signature defined by this type.
 
==== LDAP_KEYGEN_CALLBACK  ====
 
<tt>LDAP_KEYGEN_CALLBACK</tt> specifies the prototype for a callback function that generates a key for sorting.
 
===== Description  =====
 
ldap_keysort_entries() requires a function pointer that matches the signature defined by this type.
 
==== LDAP_MALLOC_CALLBACK  ====
 
This callback function prototype of ldap_memalloc_fns represents memory allocation.
 
===== See Also  =====
 
ldap_memalloc_fns
 
==== ldap_memalloc_fns  ====
 
<tt>ldap_memalloc_fns</tt> is a structure representing callback functions for memory allocation. These are global and can not be set on a per-LDAP session handle basis. Install your own functions by making a call similar to the one detailed in the following example.
<pre>ldap_set_option(NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &amp;memalloc_fns);</pre>
===== See Also  =====
 
*LDAP_MALLOC_CALLBACK
*LDAP_CALLOC_CALLBACK
*LDAP_REALLOC_CALLBACK
*LDAP_FREE_CALLBACK
 
==== LDAPMemCache  ====
 
<tt>LDAPMemCache</tt> is a type of structure representing an in-memory, client-side cache. You can create a cache and specify the following information:
 
*The maximum size of the cache.
*The maximum amount of time to keep an item in the cache.
*A set of base DNs for the search requests that you want to cache (optional).
*A set of functions to ensure the thread-safety of the cache.
 
To use a cache, you need to associate it with a connection handle (and LDAP structure). Before a search request is sent to the server, the cache is checked to determine if the same request was made before. If an earlier request was cached, the search results are retrieved from the cache.
 
'''Note:''' The cache uses the search criteria as the key to cached items. Search requests with different criteria are cached as separate items. For example, suppose you send a search request specifying that you just want to retrieve the <tt>uid</tt> attribute. Your client caches the result of that search. If you send a similar search request specifying that you want to retrieve all attributes instead of just the <tt>uid</tt>, the result cached from the previous search are not used.
 
The cache uses a combination of the following information as the key to a cached item:
 
*The host name and port number of the LDAP server that you are searching.
*The DN to which you are currently authenticated.
 
From the search criteria, the base DN, scope, filter, attributes to be returned, and an indication of whether to return attribute types only or attribute types and values.
 
===== Related Functions  =====
 
The following table lists functions related to the <tt>LDAPMemCache</tt> structure.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions for LDAPMemCache Structure"
|+ Functions for LDAPMemCache Structure
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_memcache_init()
| Creates an <tt>LDAPMemCache</tt> structure and initialize the caching mechanism.
|-
| ldap_memcache_set()
| Associates an <tt>LDAPMemCache</tt> structure with a connection handle (an LDAP structure).
|-
| ldap_memcache_get()
| Returns the <tt>LDAPMemCache</tt> structure that is associated with a connection handle (an LDAP structure).
|-
| ldap_memcache_update()
| Forces the cache to remove expired items.
|-
| ldap_memcache_flush()
| Removes entries from the cache.
|-
| ldap_memcache_destroy()
| Frees the memory used by the cache and frees the <tt>LDAPMemCache</tt> structure.
|}
 
===== LDAPMessage  =====
 
<tt>LDAPMessage</tt> is a structure representing the results of an LDAP operation such as a chain of search results, an entry in the search results, or a search reference in the search results.
 
'''Note:''' Calling the ldap_search_ext_s() or ldap_search_ext() followed by the ldap_result function creates an <tt>LDAPMessage</tt> structure to represent the chain of results from the search. Calling the ldap_first_entry() or ldap_next_entry() function creates an <tt>LDAPMessage</tt> structure to represent an entry in the search results. Calling ldap_first_reference() or ldap_next_reference() creates an <tt>LDAPMessage</tt> structure to represent a search reference in the search results. To free the <tt>LDAPMessage</tt> structure, call the ldap_msgfree() routine.
 
==== LDAPMod  ====
 
<tt>LDAPMod</tt> is a structure that you use to specify changes to an attribute in a directory entry.
 
===== Description  =====
 
Before you call the ldap_add_ext(), ldap_add_ext_s(), ldap_modify_ext(), or ldap_modify_ext_s() functions to add or modify an entry in the directory, you need to fill <tt>LDAPMod</tt> structures with the attribute values that you intend to add or change.
<pre>typedef struct ldapmod {
  int mod_op;
  char *mod_type;
  union {
  char **modv_strvals;
  struct berval **modv_bvals;
  } mod_vals;
  #define mod_values mod_vals.modv_strvals
  #define mod_bvalues mod_vals.modv_bvals
} LDAPMod;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPMod Field Descriptions"
|+ LDAPMod Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>mod_op</tt>
| The operation to be performed on the attribute and the type of data specified as the attribute values. This field can have one of the following values:
*<tt>LDAP_MOD_ADD</tt> adds a value to the attribute.
*<tt>LDAP_MOD_DELETE</tt> removes the value from the attribute.
*<tt>LDAP_MOD_REPLACE</tt> replaces all existing values of the attribute.
 
In addition, if you are specifying binary values in the <tt>mod_bvalues</tt> field, you should use the bitwise <tt>OR</tt> operator ( <tt>&#124;</tt> ) to combine <tt>LDAP_MOD_BVALUES</tt> with the operation type. For example: <tt>mod-&gt;mod_op = LDAP_MOD_ADD &#124; LDAP_MOD_BVALUES</tt> Note the following caveats when defining:
 
*If you specify <tt>LDAP_MOD_DELETE</tt> and remove all values in an attribute, the attribute is removed from the entry.
*If you specify <tt>LDAP_MOD_DELETE</tt> and <tt>NULL</tt> in the <tt>mod_values</tt> field, the attribute is removed from the entry.
*If you specify <tt>LDAP_MOD_REPLACE</tt> and <tt>NULL</tt> in the <tt>mod_values</tt> field, the attribute is removed from the entry.
*If you specify <tt>LDAP_MOD_REPLACE</tt> and the attribute does not exist in the entry, the attribute is added to the entry.
*If you specify <tt>LDAP_MOD_ADD</tt> and the attribute does not exist in the entry, the attribute is added to the entry. Also, if you are using the structure to add a new entry, you can specify <tt>0</tt> for the <tt>mod_op</tt> field, unless you are adding binary values and need to specify <tt>LDAP_MOD_BVALUES</tt>.
 
|-
| <tt>mod_type</tt>
| The attribute type that you want to add, delete, or replace the values of such as <tt>sn</tt> or <tt>telephoneNumber</tt>.
|-
| <tt>mod_values</tt>
| A pointer to a <tt>NULL</tt> terminated array of string values for the attribute.
|-
| <tt>mod_bvalues</tt>
| A pointer to a <tt>NULL</tt> terminated array of berval structures for the attribute.
|}
 
If you have allocated memory for the structures yourself, you should free them when finished by calling the ldap_mods_free() function.
 
===== Example  =====
 
The following example sets up an <tt>LDAPMod</tt> structure to change the email address of a user’s entry to <tt>bjensen@example.com</tt>.
<pre>LDAP *ld;
LDAPMod attribute1;
LDAPMod *list_of_attrs[2];
char *mail_values[] = { "bjensen@example.com", NULL };
char *dn;
...
/* Identify the entry that you want changed */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Specify that you want to replace the value of an attribute */
attribute1.mod_op = LDAP_MOD_REPLACE;
/* Specify that you want to change the value of the mail attribute */
attribute1.mod_type = "mail";
/* Specify the new value of the mail attribute */
attribute1.mod_values = mail_values;
/* Add the change to the list of attributes that you want changed */
list_of_attrs[0] = &amp;attribute_change;
list_of_attrs[1] = NULL;
/* Update the entry with the change */
if ( ldap_modify_s( ld, dn, list_of_attrs )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modify_s" );
  return( 1 );
}
...</pre>
==== LDAPpwdpolicy  ====
 
An LDAPpwdpolicy structure holds values concerning the password policy governing a user account.
 
You fill this structure by passing it to the ldap_parse_pwdpolicy_control() function.
 
===== LDAPpwdpolicy Description  =====
 
An LDAPpwdpolicy structure has the following definition:
<pre>typedef struct LDAPpwdpolicy {        /* password policy              */
  unsigned int pp_warning;      /* warning status                */
#define LDAP_PP_WARNING_NONE    0x00
#define LDAP_PP_WARNING_EXP      0x01
#define LDAP_PP_WARNING_GRACE    0x02
  int          pp_warning_info;  /* warning information          */
  int          pp_error;        /* error information            */
#define LDAP_PP_ERROR_NONE      -1    /* no error                      */
#define LDAP_PP_ERROR_EXPIRED    0    /* password expired              */
#define LDAP_PP_ERROR_LOCKED    1    /* account locked                */
#define LDAP_PP_ERROR_MUSTCHANGE 2    /* paasword has to be changed    */
#define LDAP_PP_ERROR_NOTMOD    3    /* modification not allowed      */
#define LDAP_PP_ERROR_OLDPASSWD  4    /* must provide old password    */
#define LDAP_PP_ERROR_NOQUALITY  5    /* insufficient password quality */
#define LDAP_PP_ERROR_TOOSHORT  6    /* password too short            */
#define LDAP_PP_ERROR_MINAGE    7    /* min age still in effect      */
#define LDAP_PP_ERROR_INHISTORY  8    /* password in history          */
} LDAPpwdpolicy;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPpwdpolicy Field Descriptions"
|+ LDAPpwdpolicy Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| pp_warning
| Warning code
|-
| pp_warning_info
| If pp_warning is <tt>LDAP_PP_WARNING_EXP</tt>, this holds the number of seconds before the password expires. If pp_warning is <tt>LDAP_PP_WARNING_GRACE</tt>, this holds the number of grace logins remaining.
|-
| pp_error
| One of the following error codes:
*<tt>LDAP_PP_ERROR_NONE</tt>, meaning no errors
*<tt>LDAP_PP_ERROR_EXPIRED</tt>, meaning the password has expired, and must be reset
*<tt>LDAP_PP_ERROR_LOCKED</tt>, meaning the account is locked
*<tt>LDAP_PP_ERROR_MUSTCHANGE</tt>, meaning the password has been reset, and must be changed
*<tt>LDAP_PP_ERROR_NOTMOD</tt>, meaning the user may not change the password
*<tt>LDAP_PP_ERROR_OLDPASSWD</tt>, meaning the old password must be supplied for this operation
*<tt>LDAP_PP_ERROR_NOQUALITY</tt>, meaning the password does not pass the server's password quality check
*<tt>LDAP_PP_ERROR_TOOSHORT</tt>, meaning the password is too short
*<tt>LDAP_PP_ERROR_MINAGE</tt>, meaning the password is too new to be modified, yet
*<tt>LDAP_PP_ERROR_INHISTORY</tt>, meaning the password matches a password stored in the password history, and thus cannot be reused
 
|}
 
===== Memory Concerns  =====
 
You allocate and free space for the LDAPpwdpolicy structure.
 
==== LDAP_REALLOC_CALLBACK  ====
 
This callback function prototype of ldap_memalloc_fns represents memory allocation.
 
===== See Also  =====
 
ldap_memalloc_fns
 
==== LDAP_REBINDPROC_CALLBACK  ====
 
<tt>LDAP_REBINDPROC_CALLBACK</tt> specifies the prototype for a callback function that retrieves authentication information when automatically following referrals to other servers.
 
===== Description  =====
 
If you define a function with this prototype and specify it when calling the ldap_set_rebind_proc() function, the function will be called by your LDAP client.
<pre>typedef int (LDAP_CALL LDAP_CALLBACK
  LDAP_REBINDPROC_CALLBACK)( LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg);</pre>
===== See Also  =====
 
ldap_set_rebind_proc
 
==== LDAPsortkey  ====
 
<tt>LDAPsortkey</tt> represents the criteria to be used by a server control to sort search results before sending the results back to the client.
 
'''Note:''' Controls are part of the LDAP v3 and are used to extend the functionality of an LDAP operation. The two types of controls described in the LDAP v3 are:
 
*''Server controls'' are controls that are sent from the client to the server along with an LDAP request. (In some cases, a server can include a control in the response it sends back to the client.) For example, you can include a server control in a search request to specify that you want the server to sort the search results before sending them back.
*''Client controls'' are controls that can extend the client but that are never sent to the server. As a general example, you might be able to pass a client control to an LDAP API function, which might parse the control and use the data that you have specified in the control. Directory SDK For C does not currently support any client controls.
 
===== Description  =====
<pre>typedef struct LDAPsortkey {
  char *sk_attrtype;
  char *sk_matchruleoid;
  int sk_reverseorder;
} LDAPsortkey;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPsortkey Field Descriptions"
|+ LDAPsortkey Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>sk_attrtype</tt>
| Pointer to a <tt>NULL</tt> terminated string that specifies the name of the attribute that you want to use for sorting.
|-
| <tt>sk_matchruleoid</tt>
| Pointer to a <tt>NULL</tt> terminated string that specifies the object identifier (OID) of the matching rule that you want to use for sorting.
|-
| <tt>sk_reverseorder</tt>
| Specifies whether or not the results are sorted in reverse order. This field can have one of the following values:
*A non-zero value specifies that the results should be sorted in reverse order.
*<tt>0</tt> specifies that the results should be sorted in normal (forward) order.
 
|}
 
As an example, you can use <tt>LDAPsortkey</tt> to specify that you want the server to sort search results by the <tt>roomNumber</tt> attribute.
 
To create an array of <tt>LDAPsortkey</tt> structures, you can call the ldap_create_sort_keylist() function. To free an array of <tt>LDAPsortkey</tt> structures, you can call the ldap_free_sort_keylist() function.
 
==== LDAP_TF_GET_ERRNO_CALLBACK  ====
 
<tt>LDAP_TF_GET_ERRNO_CALLBACK</tt> specifies the prototype for a callback function to get the value of the <tt>errno</tt> variable for a thread.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_GET_ERRNO_CALLBACK) ( void );</pre>
==== LDAP_TF_GET_LDERRNO_CALLBACK  ====
 
<tt>LDAP_TF_GET_LDERRNO_CALLBACK</tt> specifies the prototype for a callback function to retrieve the LDAP result code for an operation.
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function is called when the ldap_get_lderrno() function is called. The arguments of ldap_get_lderrno() are passed to your function, and the value returned by your function is returned by ldap_get_lderrno().
 
'''Note:''' For more details on the arguments and return values that your function must use, see ldap_get_lderrno().
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_GET_LDERRNO_CALLBACK)( char **, char **, void * );</pre>
==== LDAP_TF_SET_ERRNO_CALLBACK  ====
 
<tt>LDAP_TF_SET_ERRNO_CALLBACK</tt> specifies the prototype for a callback function to set the value of the <tt>errno</tt> variable for a thread.
<pre>typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_SET_ERRNO_CALLBACK)( int );</pre>
==== LDAP_TF_SET_LDERRNO_CALLBACK  ====
 
<tt>LDAP_TF_SET_LDERRNO_CALLBACK</tt> specifies the prototype for a callback function to set the LDAP result code for an operation.
 
'''Note:''' For more details on the arguments that your function must use, see ldap_set_lderrno().
 
===== Description  =====
 
If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function is called when the ldap_set_lderrno() function is called. The arguments of ldap_set_lderrno() are passed to your function.
<pre>typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_SET_LDERRNO_CALLBACK)( int, char *, char *, void * );</pre>
==== LDAP_TF_MUTEX_ALLOC_CALLBACK  ====
 
<tt>LDAP_TF_MUTEX_ALLOC_CALLBACK</tt> specifies the prototype for a callback function to allocate a mutex.
 
===== Description  =====
<pre>typedef void *(LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_ALLOC_CALLBACK)( void );</pre>
===== See Also  =====
 
ldap_thread_fns
 
==== LDAP_TF_MUTEX_FREE_CALLBACK  ====
 
<tt>LDAP_TF_MUTEX_FREE_CALLBACK</tt> specifies the prototype for a callback function to free a mutex.
 
===== Description  =====
<pre>typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_FREE_CALLBACK)( void * );</pre>
===== See Also  =====
 
ldap_thread_fns
 
==== LDAP_TF_MUTEX_LOCK_CALLBACK  ====
 
<tt>LDAP_TF_MUTEX_LOCK_CALLBACK</tt> specifies the prototype for a callback function to lock a mutex.
 
===== Description  =====
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_LOCK_CALLBACK)( void * );</pre>
===== See Also  =====
 
ldap_thread_fns
 
==== LDAP_TF_MUTEX_TRYLOCK_CALLBACK  ====
 
This function prototype is not supported in this release of Directory SDK For C.
 
===== LDAP_TF_MUTEX_UNLOCK_CALLBACK  =====
 
<tt>LDAP_TF_MUTEX_UNLOCK_CALLBACK</tt> specifies the prototype for a callback function to unlock a mutex.
 
===== Description  =====
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_UNLOCK_CALLBACK)( void * );</pre>
===== See Also  =====
 
ldap_thread_fns
 
==== LDAP_TF_SEMA_ALLOC_CALLBACK  ====
 
This function prototype is not supported in this release of Directory SDK For C.
 
===== LDAP_TF_SEMA_FREE_CALLBACK  =====
 
This function prototype is not supported in this release of Directory SDK For C.
 
==== LDAP_TF_SEMA_POST_CALLBACK  ====
 
This function prototype is not supported in this release of Directory SDK For C.
 
===== LDAP_TF_SEMA_WAIT_CALLBACK  =====
 
This function prototype is not supported in this release of Directory SDK For C.
 
==== LDAP_TF_THREADID_CALLBACK  ====
 
<tt>LDAP_TF_THREADID_CALLBACK</tt> specifies the prototype for a callback function to return an identifier that is unique to the calling thread, much like the POSIX pthread_self() function does.
 
===== Description  =====
<pre>typedef void *(LDAP_C LDAP_CALLBACK
  LDAP_TF_THREADID_CALLBACK)( void );</pre>
===== See Also  =====
 
ldap_thread_fns
 
==== ldap_thread_fns  ====
 
The <tt>ldap_thread_fns</tt> structure contains a set of pointers to functions that you want to use when write a multithreaded client.
 
===== Description  =====
<pre>struct ldap_thread_fns {
  LDAP_TF_MUTEX_ALLOC_CALLBACK *ltf_mutex_alloc;
  LDAP_TF_MUTEX_FREE_CALLBACK *ltf_mutex_free;
  LDAP_TF_MUTEX_LOCK_CALLBACK *ltf_mutex_lock;
  LDAP_TF_MUTEX_UNLOCK_CALLBACK *ltf_mutex_unlock;
  LDAP_TF_GET_ERRNO_CALLBACK *ltf_get_errno;
  LDAP_TF_SET_ERRNO_CALLBACK *ltf_set_errno;
  LDAP_TF_GET_LDERRNO_CALLBACK *ltf_get_lderrno;
  LDAP_TF_SET_LDERRNO_CALLBACK *ltf_set_lderrno;
  void *ltf_lderrno_arg;
};</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_thread_fns Field Descriptions"
|+ ldap_thread_fns Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>ltf_mutex_alloc</tt>
| Function pointer for allocating a mutex. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_MUTEX_ALLOC_CALLBACK.
|-
| <tt>ltf_mutex_free</tt>
| Function pointer for freeing a mutex. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_MUTEX_FREE_CALLBACK.
|-
| <tt>ltf_mutex_lock</tt>
| Function pointer for locking critical sections of code. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_MUTEX_LOCK_CALLBACK.
|-
| <tt>ltf_mutex_unlock</tt>
| Function pointer for unlocking critical sections of code. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. The function must have the prototype specified by LDAP_TF_MUTEX_UNLOCK_CALLBACK.
|-
| <tt>ltf_get_errno</tt>
| Function pointer for getting the value of the &lt;symbol&gt;errno&lt;/symbol&gt; variable. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. In a threaded environment, <tt>errno</tt> is typically redefined at compile time so that it has a value for each thread, rather than a global value for the entire process. Because the <tt>libldap</tt> library does not know what method your code and threading environment will use to get the value of <tt>errno</tt> for each thread, it calls this function to obtain the value. The function must have the prototype specified by LDAP_TF_GET_ERRNO_CALLBACK.
|-
| <tt>ltf_set_errno</tt>
| Function pointer for setting the value of the &lt;symbol&gt;errno&lt;/symbol&gt; variable. This function is called by the client when needed if the function pointer is not <tt>NULL</tt>. In a threaded environment, <tt>errno</tt> is typically redefined at compile time so that it has a value for each thread, rather than a global value for the entire process. Because the <tt>libldap</tt> library does not know what method your code and threading environment will use to get the value of <tt>errno</tt> for each thread, it calls this function to obtain the value. The function must have the prototype specified by LDAP_TF_SET_ERRNO_CALLBACK.
|-
| <tt>ltf_get_lderrno</tt>
| Function pointer for getting error values from calls to functions in the <tt>libldap</tt> library. This function is called by the client as needed if the function pointer isn’t <tt>NULL</tt>. If this function pointer is not set, the <tt>libldap</tt> library records these errors in fields in the LDAP structure. The function must have the prototype specified by LDAP_TF_GET_LDERRNO_CALLBACK.
|-
| <tt>ltf_set_lderrno</tt>
| Function pointer for setting error values from calls to functions in the <tt>libldap</tt> library. This function is called by the client as needed if the function pointer is not <tt>NULL</tt>. If this function pointer is not set, the <tt>libldap</tt> library records these errors in fields in the LDAP structure. The function must have the prototype specified by LDAP_TF_SET_LDERRNO_CALLBACK.
|-
| <tt>ltf_lderrno_arg</tt>
| Additional parameter passed to the functions for getting and setting error values from calls to functions in the <tt>libldap</tt> library. <tt>(*ltf_get_lderrno)</tt> and <tt>(*ltf_set_lderrno)</tt> identify these functions.
|}
 
==== LDAPURLDesc  ====
 
<tt>LDAPURLDesc</tt> is a structure that represents the components of an LDAP URL.
 
===== Description  =====
 
LDAP URLs have the following syntax:
<pre>ldap://''host'':''port''/''dn''?''attributes''?''scope''?(''filter'')</pre>
Where, for example:
<pre>ldap://ldap.example.com/c=US?o,description?one?(o=Sales)</pre>
Calling the ldap_url_parse() function creates an <tt>LDAPURLDesc</tt> structure with the components of the URL.
<pre>typedef struct ldap_url_desc {
  char *lud_host;
  int lud_port;
  char *lud_dn;
  char **lud_attrs;
  int lud_scope;
  char *lud_filter;
  unsigned long lud_options;
} LDAPURLDesc</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPURLDesc Field Descriptions"
|+ LDAPURLDesc Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>lud_host</tt>
| Name of the host in the URL.
|-
| <tt>lud_port</tt>
| Number of the port in the URL.
|-
| <tt>lud_dn</tt>
| Distinguished name in the URL. This ''base entry'' DN identifies the starting point of the search.
|-
| <tt>lud_attrs</tt>
| Pointer to a <tt>NULL</tt> terminated list of the attributes specified in the URL.
|-
| <tt>lud_scope</tt>
| Integer representing the scope of the search specified in the URL:
*<tt>LDAP_SCOPE_BASE</tt> specifies a search of the base entry.
*<tt>LDAP_SCOPE_ONELEVEL</tt> specifies a search of all entries one level under the base entry (not including the base entry).
*<tt>LDAP_SCOPE_SUBTREE</tt> specified a search of all entries at all levels under the base entry (including the base entry).
 
|-
| <tt>lud_filter</tt>
| Search filter included in the URL.
|-
| <tt>lud_options</tt>
| Options; if <tt>LDAP_URL_OPT_SECURE</tt>, indicates that the protocol is <tt>ldaps://</tt> instead of <tt>ldap://</tt>.
|}
 
For example, suppose you pass the following URL to the ldap_url_parse() function:
<pre>ldap://ldap.example.com:5000/dc=example,dc=com?cn,mail, \
telephoneNumber?sub?(sn=Jensen)</pre>
The resulting <tt>LDAPURLDesc</tt> structure - <tt>ludpp</tt>, in this example -- will contain the values in the following table .
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPURLDesc Parsed URL Values"
|+ LDAPURLDesc Parsed URL Values
|-
! scope="col" | Component
! scope="col" | Value
|-
| <tt>ludpp-&gt;lud_host</tt>
| <tt>ldap.example.com</tt>
|-
| <tt>ludpp-&gt;lud_port</tt>
| <tt>5000</tt>
|-
| <tt>ludpp-&gt;lud_dn</tt>
| <tt>dc=example,dc=com</tt>
|-
| <tt>ludpp-&gt;lud_attrs[0]</tt>
| <tt>cn</tt>
|-
| <tt>ludpp-&gt;lud_attrs[1]</tt>
| <tt>mail</tt>
|-
| <tt>ludpp-&gt;lud_attrs[2]</tt>
| <tt>telephoneNumber</tt>
|-
| <tt>ludpp-&gt;lud_attrs[3]</tt>
| <tt>NULL</tt>
|-
| <tt>ludpp-&gt;lud_scope</tt>
| <tt>LDAP_SCOPE_SUBTREE</tt>
|-
| <tt>ludpp-&gt;lud_filter</tt>
| <tt>(sn=Jensen)</tt>
|}
 
To free the <tt>LDAPURLDesc</tt> structure, call the ldap_free_urldesc() routine.
 
==== LDAPuserstatus  ====
 
An LDAPuserstatus structure holds the values concerning the status of a user account. You fill this structure by passing it to the ldap_parse_userstatus_control() function.
 
===== LDAPuserstatus Description  =====
 
An LDAPuserstatus structure has the following definition:
<pre>typedef struct LDAPuserstatus {    /* user account availability  */
  unsigned int us_available;  /* availability status        */
#define LDAP_US_ACCOUNT_USABLE      0
#define LDAP_US_ACCOUNT_NOT_USABLE  1
  int          us_expire;    /* will expire in seconds      */
  int          us_inactive;  /* boolean inactivation status */
#define LDAP_US_ACCOUNT_ACTIVE      0
#define LDAP_US_ACCOUNT_INACTIVE    1
  int          us_reset;      /* boolean password reset      */
#define LDAP_US_ACCOUNT_NOT_RESET  0
#define LDAP_US_ACCOUNT_RESET      1
  int          us_expired;    /* boolean password expired    */
#define LDAP_US_ACCOUNT_NOT_EXPIRED 0
#define LDAP_US_ACCOUNT_EXPIRED    1
  int          us_remaining;  /* remaining logins            */
  int          us_seconds;    /* will unlock in seconds      */
} LDAPuserstatus;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPuserstatus Field Descriptions"
|+ LDAPuserstatus Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| us_available
| Whether the account is currently usable
|-
| us_expire
| Number of seconds before the password expires <tt>-1</tt> means the password is not set to expire at all.
|-
| us_inactive
| Whether the account is locked
|-
| us_reset
| Whether the password has been reset
|-
| us_expired
| Whether the password has expired
|-
| us_remaining
| Number of remaining grace logins
|-
| us_seconds
| Number of seconds before the server unlocks the account
|}
 
===== Memory Concerns  =====
 
You allocate and free space for the LDAPuserstatus structure.
 
==== LDAP_VALCMP_CALLBACK  ====
 
<tt>LDAP_VALCMP_CALLBACK</tt> specifies the prototype for a callback function to sort a specified set of values.
 
===== Description  =====
 
If you define a function with this prototype and specify it when calling the ldap_sort_strcasecmp() function, the function will be called by your LDAP client.
<pre>typedef int (LDAP_C LDAP_CALLBACK
  LDAP_VALCMP_CALLBACK)(const char**, const char**);</pre>
ldap_sort_values() requires a function pointer that matches the signature defined by this type.
 
ldap_sort_strcasecmp() is a value comparison function defined using this type which can therefore be passed to ldap_sort_values().
 
===== See Also  =====
 
ldap_sort_values(), ldap_sort_strcasecmp()
 
==== LDAPVersion  ====
 
The <tt>LDAPVersion</tt> structure contains version information about Directory SDK For C.
 
Call the ldap_version() function to return a pointer to an <tt>LDAPVersion</tt> structure containing version information.
<pre>typedef struct _LDAPVersion {
  int sdk_version;
  int protocol_version;
  int SSL_version;
  int security_level;
} LDAPVersion;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPVersion Field Definitions"
|+ LDAPVersion Field Definitions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>sdk_version</tt>
| Version number of Directory SDK For C multiplied by 100. For example, the value 600 in this field represents version 6.0.
|-
| <tt>protocol_version</tt>
| Highest supported LDAP protocol version multiplied by 100. For example, the value 300 in this field represents LDAP v3.
|-
| <tt>SSL_version</tt>
| Supported SSL version multiplied by 100. For example, the value 300 in this field represents SSL 3.0).
|-
| <tt>security_level</tt>
| Level of encryption supported in bits. For example, 128 for US domestic or 40 for export. If SSL is not enabled, the value of this field is <tt>LDAP_SECURITY_NONE </tt> .
|}
 
==== LDAPVirtualList  ====
 
<tt>LDAPVirtualList</tt> specifies the information that can be used to create a ''virtual list view'' control.
 
===== Description  =====
 
A ''virtual list view'' control is a LDAP v3 control designed to allow the client to retrieve subsets of search results to display in a ''virtual list box''.
 
A ''virtual list box'' is typically a graphical user interface that displays a long list of entries with a few entries visible.
 
To display the list, the client usually does not retrieve the entire list of entries from the server. Instead, the client just retrieves the subset of entries to be displayed.
 
After you create an <tt>LDAPVirtualList</tt> structure and specify values for its fields, you can create the virtual list view control by calling the function ldap_create_virtuallist_control(). You can pass this control and a server-side sorting control-created by calling the ldap_create_sort_keylist() function and the ldap_create_sort_control() function-to the ldap_search_ext() or ldap_search_ext_s() function.
 
To get the virtual list view response control sent back from the server, call the ldap_parse_result() function to get the list of controls returned by the server, then call the ldap_parse_virtuallist_control() function to retrieve information from the control. End users can display different sections of the list by scrolling up or down.
 
'''Note:''' The object identifier (OID) for this control is OID 2.16.840.1.113730.3.4.9, or <tt>LDAP_CONTROL_VLVREQUEST</tt> as defined in ldap.h. It is supported by Directory Server.
 
The virtual list view control provides the means for your client to request and retrieve certain subsets of a long, sorted list of entries. The control specifies the following information:
 
*The entry in the list that is currently selected.
*The number of entries to be displayed in the list before the selected item.
*The number of entries to be displayed in the list after the selected entry.
 
The currently selected entry can be identified in one of the following ways:
 
*By the index of the entry in the entire list in which case, the control specifies both the offset of the entry and the total number of entries in the list.
*By the value of the entry in which case, the control specifies that value.
 
For example, a virtual list view control might specify that you want to retrieve entries 15 through 24 in a list of 100 results with entry 20 being the selected entry. The control uses the following information to specify this:
 
*The selected entry is the 20th entry from the top—in other words, the index or offset of the entry is 20—of a list of 100.
*Get 5 entries before the selected entry in the list (entries 15 - 19).
*Get 4 entries after the selected entry in the list (entries 21 - 24).
 
As another example, a virtual list view control might specify that you want to retrieve a subset of entries that start with the letter <tt>c</tt> or a later letter in the alphabet. The control might specify the following information:
 
*The selected entry is the first entry that starts with the letter <tt>c</tt>. The size of the list is not relevant in determining the selected entry in this case.
*Get 5 entries before the selected entry in the list.
*Get 4 entries after the selected entry in the list.
<pre>typedef struct ldapvirtuallist {
  unsigned long ldvlist_before_count;
  unsigned long ldvlist_after_count;
  char *ldvlist_attrvalue;
  unsigned long ldvlist_index;
  unsigned long ldvlist_size;
  void *ldvlist_extradata;
} LDAPVirtualList;</pre>
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="LDAPVirtualList Field Descriptions"
|+ LDAPVirtualList Field Descriptions
|-
! scope="col" | Field
! scope="col" | What It Contains
|-
| <tt>ldvlist_before_count</tt>
| Number of entries before the selected entry that you want to retrieve.
|-
| <tt>ldvlist_after_count</tt>
| Number of entries after the selected entry that you want to retrieve.
|-
| <tt>ldvlist_attrvalue</tt>
| Specifies the value that you want to find in the list. The selected entry in the list is the first entry that is greater than or equal to this value. If this field is <tt>NULL</tt>, the <tt>ldvlist_index</tt> and <tt>ldvlist_size</tt> fields are used to determine the selected entry instead.
|-
| <tt>ldvlist_index</tt>
| If the <tt>ldvlist_attrvalue</tt> field is <tt>NULL</tt>, specifies the offset or index of the selected entry in the list. This field is used in conjunction with the <tt>ldvlist_size</tt> field to identify the selected entry.
|-
| <tt>ldvlist_size</tt>
| If the <tt>ldvlist_attrvalue</tt> field is <tt>NULL</tt>, specifies the total number items in the list. This field is used in conjunction with the <tt>ldvlist_index</tt> field to identify the selected entry.
|-
| <tt>ldvlist_extradata</tt>
| Reserved for application-specific use. This data is not used in the virtual list view control.
|}
 
==== LDAP_X_EXTIOF_CLOSE_CALLBACK  ====
 
This specifies the prototype for an extended I/O callback function to close a socket connection.
 
===== Description  =====
<pre>typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CLOSE_CALLBACK )(
  int s, void *arg );</pre>
===== See Also  =====
 
ldap_x_ext_io_fns
 
==== LDAP_X_EXTIOF_CONNECT_CALLBACK  ====
 
This specifies the prototype for an extended I/O callback function to open a socket connection.
 
===== Description  =====
 
<tt>LDAP_X_EXTIOF_CONNECT_CALLBACK</tt> takes a <tt>timeout</tt> parameter whose value in milliseconds can be set by calling ldap_set_option().
<pre>typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CONNECT_CALLBACK )(
  int s, LDAP_X_SockAddr *saddr, int saddr_len,
  int timeout /* milliseconds */, void *arg );</pre>
===== See Also  =====
 
ldap_x_ext_io_fns
 
==== LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK  ====
 
This specifies the prototype for an extended I/O callback function to dispose of a session handle.
 
===== Description  =====
 
<tt>LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK</tt> is called right before the LDAP session handle and its contents are destroyed during ldap_unbind(). The value of the <tt>arg</tt> parameter passed to the callback is always the default one.
<pre>typedef void (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK)(
  LDAP *ld, void *arg );</pre>
===== See Also  =====
 
ldap_x_ext_io_fns
 
==== LDAP_X_EXTIOF_NEWHANDLE_CALLBACK  ====
 
This specifies the prototype for an extended I/O callback function to define a new session handle.
 
===== Description  =====
 
<tt>LDAP_X_EXTIOF_NEWHANDLE_CALLBACK</tt> is called right after the LDAP session handle is created during ldap_init(). The value of the <tt>arg</tt> parameter passed to the callback is always the default one. If the callback returns anything other than LDAP_SUCCESS, the session handle allocation fails.
<pre>typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_NEWHANDLE_CALLBACK)(
  LDAP *ld, void *arg );</pre>
===== See Also  =====
 
ldap_x_ext_io_fns
 
==== ldap_x_ext_io_fns  ====
 
This is a structure to hold extended I/O function pointers.
<pre>struct ldap_x_ext_io_fns {
/* lextiof_size should always be set to LDAP_X_EXTIO_FNS_SIZE */
  int                                    lextiof_size;
  LDAP_X_EXTIOF_CONNECT_CALLBACK          *lextiof_connect;
  LDAP_X_EXTIOF_CLOSE_CALLBACK            *lextiof_close;
  LDAP_X_EXTIOF_READ_CALLBACK            *lextiof_read;
  LDAP_X_EXTIOF_WRITE_CALLBACK            *lextiof_write;
  LDAP_X_EXTIOF_POLL_CALLBACK            *lextiof_poll;
  LDAP_X_EXTIOF_NEWHANDLE_CALLBACK        *lextiof_newhandle;
  LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK    *lextiof_disposehandle;
  void                                    *lextiof_session_arg;
  LDAP_X_EXTIOF_WRITEV_CALLBACK          *lextiof_writev;
};
#define LDAP_X_EXTIO_FNS_SIZE  sizeof(struct ldap_x_ext_io_fns)</pre>
==== LDAP_X_EXTIOF_POLL_CALLBACK  ====
 
This specifies the prototype for an extended I/O callback function to close a socket connection.
 
===== Description  =====
 
The <tt>LDAP_X_EXTIOF_POLL_CALLBACK</tt> interface is provided instead of a standard select() interface. The time out is in milliseconds. The value of the &lt;parameter&gt;arg&lt;/parameter&gt; parameter passed to the callback is always the default one.
<pre>typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_POLL_CALLBACK)(
  LDAP_X_PollFD fds[], int nfds, int timeout /* milliseconds */,
  void *arg );</pre>
===== See Also  =====
 
ldap_x_ext_io_fns, LDAP_X_PollFD
 
==== ldap_x_hostlist_status  ====
 
This structure contains utility functions for parsing space-separated host lists.
 
===== Description  =====
<pre>struct ldap_x_hostlist_status;
LDAP_API(int) LDAP_CALL ldap_x_hostlist_first( const char *hostlist,
  int defport, char **hostp, int *portp /* host byte order */,
  struct ldap_x_hostlist_status **statusp );
  LDAP_API(int) LDAP_CALL ldap_x_hostlist_next( char **hostp,
  int *portp /* host byte order */,
  struct ldap_x_hostlist_status *status
);
LDAP_API(void) LDAP_CALL ldap_x_hostlist_statusfree(
  struct ldap_x_hostlist_status *status );</pre>
==== LDAP_X_PollFD  ====
 
This is a structure to hold the set of file descriptors that will be surveyed for I/O by the LDAP_X_EXTIOF_POLL_CALLBACK.
 
===== Description  =====
<pre>typedef struct ldap_x_pollfd {    /* used by LDAP_X_EXTIOF_POLL_CALLBACK */
  int  lpoll_fd; /* integer file descriptor / socket */
  void *lpoll_arg; /* pointer socket and for use by application */
  short lpoll_events; /* requested event */
  short lpoll_revents; /* returned event */
} LDAP_X_PollFD;</pre>
 
== Directory SDK for C Function Reference  ==
 
This section contains detailed reference material for each public function of Directory SDK for C. Each reference gives a description of the function, and its usage syntax, parameters and return values. In many cases, an example program is also included.
 
=== Typographic Conventions ===
The general purpose of a function is usually given by  its name. The following table lists the
naming conventions used when adding suffixes to function names.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Function Naming Conventions"
|+ Function Naming Conventions
|-
! scope="col" | Suffix
! scope="col" | Description
|-
| <tt>_ext</tt>
| Identifies extended functions introduced for LDAP v3. These functions are augmented through additional parameters, as compared to the functions they replace. As LDAP v3 has become widely adopted, it is recommended you use extended functions whenever possible in your new applications.
|-
| <tt>_s</tt>
| Identifies the synchronous form of functions. A synchronous function will not return until it receives a response from the server, thereby blocking the caller. Similar function names without this suffix are asynchronous, allowing the caller to perform other operations while waiting for a result. The synchronous and asynchronous forms exist only for functions which involve possible delays due to communication with the LDAP server. Functions which do not involve communication do not use this suffix.
|}
 
=== Function Summary by Task ===
 
In the following sections the functions of Directory SDK For C are grouped into task categories.
==== Working with Basic Encoding Rules ====
 
The functions listed in the following table may be used to encode and decode with Basic Encoding Rules (BER). They are often used inside of control and extension values.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Encode and Decode BER"
|+ Functions to Encode and Decode BER
|-
! scope="col" | Function
! scope="col" | Description
|-
| ber_alloc(), ber_alloc_t(), ber_sockbuf_alloc(), ber_special_alloc()
| Allocate new BER elements.
|-
| ber_bvecfree(), ber_bvfree(), ber_free(), ber_sockbuf_free(), ber_sockbuf_free_data()
| Free allocated memory.
|-
| ber_bvdup(), ber_dup()
| Duplicate BER structures.
|-
| ber_init(), ber_init_w_nullchar()
| Construct new structures.
|-
| ber_get_boolean(), ber_get_int, ber_get_next(), ber_get_next_buffer(), ber_get_next_buffer_ext(), ber_get_null(), ber_get_option, ber_get_stringa(), ber_get_stringal(), ber_get_stringb()
| Retrieve miscellaneous information.
|-
| ber_put_bitstring(), ber_put_boolean(), ber_put_enum(), ber_put_int(), ber_put_null(), ber_put_ostring(), ber_put_seq(), ber_put_set(), ber_put_string()
| Write miscellaneous information.
|-
| ber_first_element(), ber_next_element(), ber_peek_tag(), ber_skip_tag()
| Target specific elements and tags.
|-
| ber_set_option(), ber_set_string_translators()
| Set session parameters.
|-
| ber_flatten(), ber_printf(), ber_read(), ber_reset(), ber_scanf(), ber_sockbuf_get_option(), ber_sockbuf_set_option(), ber_start_seq(), ber_start_seq(), ber_start_set(), ber_svecfree(), ber_write()
| Miscellaneous functions.
|}
 
==== Managing LDAP Sessions ====
 
The functions listed in the following table manage the different phases of an LDAP session: initialization, configuration, authentication (binding) and termination (unbinding).
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Manage an LDAP Session"
|+ Functions to Manage an LDAP Session
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_init(), prldap_init() (IPv6)
| Initializes an LDAP session.
|-
| ldapssl_init()
| Initializes an LDAP session over SSL.
|-
| ldapssl_pkcs_init()
| Initializes a thread-safe session over SSL.
|-
| ldap_get_option(), ldap_set_option
| Read and writes the current preference settings for a session.
|-
| ldap_memcache_init(), ldap_memcache_set(), ldap_memcache_get(), ldap_memcache_update(), ldap_memcache_flush(), ldap_memcache_destroy()
| Creates a memory cache and uses it for search results from this session. Manages the data in the cache and frees the memory when the cache is no longer needed. The in-memory cache for search results is an extension to the API.
|-
| ldap_unbind_ext()
| Ends an LDAP session and frees the associated data structures.
|}
 
==== Performing LDAP Operations ====
 
The functions listed in the following table perform LDAP operations on a server and retrieve the results.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Perform Operations on LDAP Server"
|+ Functions to Perform Operations on LDAP Server
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_add_ext() or ldap_add_ext_s()
| Adds a new entry to the directory.
|-
| ldap_modify_ext() or ldap_modify_ext_s()
| Modifies an entry in the directory
|-
| ldap_delete_ext() or ldap_delete_ext_s()
| Deletes an entry from the directory.
|-
| ldap_rename() orldap_rename_s()
| Renames or moves one or more entries.
|-
| ldap_search_ext() or ldap_search_ext_s()
| Searches the directory.
|-
| ldap_compare_ext() or ldap_compare_ext_s()
| Compares a value with the values of an entry's attribute.
|-
| ldap_result()
| Checks the results of an asynchronous operation.
|-
| ldap_abandon_ext()
| Cancels an asynchronous operation.
|-
| ldap_extended_operation() or ldap_extended_operation_s()
| Performs an LDAP v3 extended operation.
|-
| ldap_parse_extended_result()
| Parses the results of an LDAP v3 extended operation.
|-
| ldap_msgfree()
| Frees the memory used by the data structure for the results.
|-
| ldap_simple_bind() or ldap_simple_bind_s()
| Authenticates to an LDAP server using a password.
|-
| ldap_sasl_bind() and ldap_parse_sasl_bind_result() or ldap_sasl_bind_s
| Authenticates to an LDAP server using a SASL mechanism.
|-
| ldap_set_rebind_proc()
| Specifies the function used to get authentication information when following referrals.
|}
 
==== Processing Search Results ====
 
Search results are given as a chain of LDAPMessage structures which can contain both entry messages and search reference messages. The functions listed in the following table retrieve the results of a search operation and process the data structures which are returned.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Process Search Results"
|+ Functions to Process Search Results
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_first_message()
| Gets the first message (an entry or search reference) in a chain of search results.
|-
| ldap_next_message()
| Gets the next message (an entry or search reference) in a chain of search results.
|-
| ldap_count_messages()
| Counts the number of messages (entries and search references) in a chain of search results.
|-
| ldap_msgid()
| Gets the ID number of a message structure containing part of a result.
|-
| ldap_msgtype()
| Determines whether a message structure contains an entry or a search reference.
|-
| ldap_msgfree()
| Frees the memory allocated for search results or other LDAP operation results.
|-
| ldap_first_entry()
| Gets the first entry in a chain of search results.
|-
| ldap_next_entry()
| Gets the next entry in a chain of search results.
|-
| ldap_count_entries()
| Counts the number of entries in a chain of search results.
|-
| ldap_first_reference()
| Gets the first search reference in a chain of search results.
|-
| ldap_next_reference()
| Gets the next search reference in a chain of search results.
|-
| ldap_count_references()
| Counts the number of search references in a chain of search results.
|-
| ldap_parse_reference()
| Extracts the referral strings from a search reference.
|}
 
==== Reading the Contents of an Entry ====
 
The functions listed in the following table are used to access the contents of an entry returned as a search result.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Access Contents of an Entry"
|+ Functions to Access Contents of an Entry
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_get_dn()
| Get the DN for an entry.
|-
| ldap_explode_dn() ldap_explode_rdn()
| Split a DN or relative DN into its components.
|-
| ldap_explode_dns()
| Takes a DNS-style DN and breaks it up into its components.
|-
| ldap_is_dns_dn()
| Determines the style of the DN.
|-
| ldap_dn2ufn()
| Removes cryptic type names to make a DN easier to read.
|-
| ldap_first_attribute()
| Get the name of the first attribute in an entry.
|-
| ldap_next_attribute()
| Get the name of the next attribute in an entry.
|-
| ldap_get_values()
| Get the string values of an attribute.
|-
| ldap_get_values_len()
| Get the binary values of an attribute.
|-
| ldap_count_values()
| Count the string values of an attribute.
|-
| ldap_count_values_len()
| Count the binary values of an attribute.
|-
| ldap_value_free()
| Free the memory allocated for the string values of an attribute.
|-
| ldap_value_free_len()
| Free the memory allocated for the binary values of an attribute.
|}
 
==== Sorting Search Results ====
 
With the functions listed in the following table, your LDAP client can sort the data structures returned
as search results.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Client-side Sorting Functions"
|+ Client-side Sorting Functions
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_sort_entries()
| Sorts search results by DN or by a single attribute.
|-
| ldap_multisort_entries()
| Sorts search results by multiple attributes
|-
| ldap_keysort_entries()
| Sorts search results using key(s).
|-
| ldap_sort_values()
| Sorts the values of an attribute.
|-
| ldap_sort_strcasecmp()
| A case-insensitive comparison function that you can pass to ldap_sort_values().
|}
 
Directory Server and others also provide server-side sorting through LDAP v3 controls.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Server-Side Sorting Functions"
|+ Server-Side Sorting Functions
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_create_sort_keylist()
| Define the criteria for sorting entries by attribute values.
|-
| ldap_free_sort_keylist()
| Free the memory for the sort criteria data structure.
|-
| ldap_create_sort_control()
| Create the sort control structure needed for server-side sorting.
|-
| ldap_control_free()
| Free the memory for the sort control data structure.
|-
| ldap_parse_sort_control()
| Analyze the server&rsquo;s response to the sort control.
|-
| ldap_controls_free()
| Free the memory for the sort control response data structure.
|}
 
==== Working with Search Filters ====
 
The functions listed in the following table retrieve and build filters using a filter configuration file. Use this mechanism to create complex filters to pass to the search functions.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Initialize, Retrieve, and Build Filters"
|+ Functions to Initialize, Retrieve, and Build Filters
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_init_getfilter()
| Read a filter configuration file into memory.
|-
| ldap_init_getfilter_buf()
| Read a filter configuration string from a buffer.
|-
| ldap_getfilter_free()
| Free the filter configuration data structure from memory.
|-
| ldap_set_filter_additions()
| Specify the prefix and suffix to be added to all filters retrieved from the filter configuration.
|-
| ldap_getfirstfilter()
| Retrieve the first matching filter from the filter configuration.
|-
| ldap_getnextfilter()
| Retrieve the next matching filter from the filter configuration.
|-
| ldap_create_filter()
| Build a filter without using the filter configuration file mechanism.
|}
 
==== Using LDAP v3 Controls ====
 
Directory Server and others also provide additional functionality
through LDAP v3 controls. The functions listed in the following table configure LDAP v3
control structures which ask the server to perform advanced operations.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Manage LDAP v3 Controls"
|+ Functions to Manage LDAP v3 Controls
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_create_authzid_control(), ldap_parse_authzid_control()
| Examine the authorization ID used for the operation.
|-
| ldap_create_persistentsearch_control(), ldap_get_entry_controls(), ldap_parse_entrychange_control()
| Track changes to an entry or a set of entries by setting the persistent search control and analyzing the entry change control sent by the server.
|-
| ldap_create_proxiedauth_control()
| Define a proxy authorization control to perform an operation under a different bind DN
|-
| ldap_create_pwdpolicy_control(), ldap_parse_pwdpolicy_control()
| Examine password policy information for an entry.
|-
| ldap_create_sort_keylist(), ldap_free_sort_keylist(), ldap_create_sort_control(), ldap_parse_sort_control()
| Define and send criteria for server-side sorting of search results and check the server&rsquo;s response
|-
| ldap_create_userstatus_control(), ldap_parse_userstatus_control()
| Examine account availability information for an entry.
|-
| ldap_create_virtuallist_control(), ldap_parse_virtuallist_control()
| Use in conjunction with server-side sorting to limit and handle the number of results returned to the client.
|-
| ldap_parse_result()
| Parse an LDAP response from the server to extract the result and the response to the control.
|}
 
==== Using Extensions ====
 
The functions listed in the following table are utility functions for parsing space-separated host
lists. This is useful for implementing an extended I/O CONNECT callback function.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Extensions Provided"
|+ Extensions Provided
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_x_hostlist_first(), ldap_x_hostlist_next(), ldap_x_hostlist_status()
| Utility functions for parsing space-separated host lists.
|}
 
==== Working with LDAP URLs ====
 
The functions listed in the following table interpret LDAP URLs, universal resource locators of the form <tt>ldap://... </tt>.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Interpret LDAP URLs"
|+ Functions to Interpret LDAP URLs
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_is_ldap_url()
| Determine if a URL is an LDAP URL.
|-
| ldap_url_parse()
| Split up an LDAP URL into its components.
|-
| ldap_url_search(), ldap_url_search_s, ldap_url_search_st()
| Perform the search specified by an LDAP URL.
|-
| ldap_free_urldesc()
| Free the memory allocated for a parsed URL.
|}
 
==== Working with UTF-8 Encoding ====
 
The functions listed in the following table work with strings and characters that use UTF-8 encoding.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Handle UTF-8 Encoding"
|+ Functions to Handle UTF-8 Encoding
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_utf8len()
| Function to determine byte length.
|-
| ldap_utf8next()
| Function to get next character.
|-
| ldap_utf8prev()
| Function to get previous character.
|-
| ldap_utf8copy()
| Function to copy a character to a destination.
|-
| ldap_utf8characters()
| Function to return the number of characters.
|-
| ldap_utf8getcc()
| Function moves the pointer to the next character following a UCS-4 character.
|-
| ldap_utf8strtok_r()
| Function moves the pointer to the next character following a UCS-4 character.
|-
| ldap_utf8isalnum(), ldap_utf8isalpha, ldap_utf8isdigit(), ldap_utf8len(), ldap_utf8isspace()
| Functions to determine characteristics of the character.
|}
 
==== Handling Errors ====
 
The functions listed in the following table handle errors returned by the functions.  See ''Directory SDK for C Result Codes'' for a list of all of the error and status
codes used in the Directory SDK For C. You can also find details about possible errors in the reference section for each function.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions for Error Handling"
|+ Functions for Error Handling
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_parse_result()
| Get the error code resulting from an asynchronous LDAP operation.
|-
| ldap_get_lderrno()
| Get information about the last error that occurred.
|-
| ldap_set_lderrno()
| Set information about an error.
|-
| ldap_err2string()
| Get the error message for a specific error code.
|-
| ldapssl_err2string()
| Get the error message for a specific SSL error code.
|}
 
==== Managing Memory ====
 
The functions listed in the following table free memory allocated by the Directory SDK For C functions.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Free Memory"
|+ Functions to Free Memory
|-
! scope="col" | Function
! scope="col" | Description
|-
| ber_bvfree()
| Free the memory allocated for a berval structure.
|-
| ber_free()
| Free the memory of a BerElement structure.
|-
| ldap_control_free()
| Free the memory of an LDAPControl structure.
|-
| ldap_controls_free()
| Free an array of LDAPControl structures.
|-
| ldap_free_friendlymap()
| Free the memory of a FriendlyMap structure
|-
| ldap_free_sort_keylist()
| Free an array of LDAPsortkey structures
|-
| ldap_free_urldesc()
| Free the memory of an LDAPURLDesc structure
|-
| ldap_getfilter_free()
| Free the memory of an LDAPFiltDesc structure.
|-
| ldap_memfree()
| General function for freeing memory of any other data structure
|-
| ldap_mods_free()
| Free an array of LDAPMod structure.
|-
| ldap_msgfree()
| Free the memory of an LDAPMessage structure.
|-
| ldap_value_free()
| Free the memory allocated for the string values of an attribute.
|-
| ldap_value_free_len()
| Free the memory allocated for the binary values of an attribute (an array of berval structures)
|}
 
You may also manage memory directly with the functions in the following table.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Directly Manage Memory"
|+ Functions to Directly Manage Memory
|-
! scope="col" | Function
! scope="col" | Description
|-
| ldap_x_malloc()
| Allocates memory.
|-
| ldap_x_calloc()
| Allocates memory for an array of elements.
|-
| ldap_x_realloc()
| Changes the size of a memory block.
|-
| ldap_x_free()
| Frees a block of memory.
|}
 
==== Working with NSPR ====
 
The functions listed in the following table tie <tt>libldap</tt> into Netscape Portable Runtime, NSPR.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Functions to Work with NSPR"
|+ Functions to Work with NSPR
|-
! scope="col" | Function
! scope="col" | Description
|-
| prldap_get_default_socket_info()
| Gets default socket information.
|-
| prldap_get_session_info()
| Gets application-specific data.
|-
| prldap_get_session_option()
| Gets a session option specific to the <tt>prldap</tt> layer.
|-
| prldap_get_socket_info()
| Gets socket information.
|-
| prldap_init()
| Creates a new NSPR session handle.
|-
| prldap_install_routines()
| Installs NSPR functions for use with LDAP handle.
|-
| prldap_set_default_socket_info()
| Sets default socket information.
|-
| prldap_set_session_info()
| Sets application-specific data.
|-
| prldap_set_session_option()
| Sets a session option specific to the <tt>prldap</tt> layer.
|-
| prldap_set_socket_info()
| Sets socket information.
|}
 
==== Deprecated and Outdated Functions ====
 
The functions listed in first column of the following table should no longer
be used; they have been superseded by the newer functions listed in the second
column. Deprecated functions are those being dropped from the standard or
from extensions to Directory SDK For C. Outdated functions are those which
are not officially deprecated but which have newer, extended functions for
performing the same operation.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Deprecated Functions and Their Replacements"
|+ Deprecated Functions and Their Replacements
|-
! scope="col" | Deprecated Function
! scope="col" | Replacement
|-
| ldap_ber_free()
| Replaced by ber_free().
|-
| ldap_bind(), ldap_bind_s()
| Replaced by ldap_simple_bind() and ldap_simple_bind_s() respectively.
|-
| ldap_build_filter()
| Replaced by ldap_create_filter().
|-
| ldap_cache_flush()
| Replaced by ldap_memcache_*() functions.
|-
| ldap_charray_add(), ldap_charray_dup, ldap_charray_free(), ldap_charray_inlist(), ldap_charray_merge(), ldap_charray_position(), ldap_str2charray()
| None documented to replace these character array functions.
|-
| ldap_create_proxyauth_control()
| Replaced by ldap_create_geteffectiveRights_control().
|-
| ldap_get_lang_values(), ldap_get_lang_values_len()
| Rarely used, no replacement.
|-
| ldap_modrdn()
| Replaced by ldap_modrdn2(), itself outdated by ldap_rename().
|-
| ldap_modrdn_s()
| Replaced by ldap_modrdn2_s(), itself outdated by ldap_rename_s().
|-
| ldap_open()
| Replaced by ldap_init() and one of the bind functions.
|-
| ldap_result2error()
| Replaced by ldap_parse_result().
|-
| ldap_setfilteraffixes()
| Replaced by ldap_set_filter_additions().
|-
| ldap_ufn_search_c(), ldap_ufn_search_ct(), ldap_ufn_search_s(), ldap_ufn_setfilter(), ldap_ufn_setprefix(), ldap_ufn_timeout()
| None documented to replace these user-friendly search functions.
|-
| ldap_version()
| Replaced by ldap_get_option().
|}
 
==== Outdated Standard Functions and Equivalents ====
 
Many LDAP v2 functions are outdated now that LDAP v3 has been widely
adopted. The following table lists
both the outdated function and its new equivalent. Although LDAP v2 functions
remain in the standard specification, you should use the LDAP v3 functions
in any new client applications. Again, for maintenance reasons, the outdated
functions have often been implemented to call the newer function.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Outdated LDAP v2 Functions and New Equivalents"
|+ Outdated LDAP v2 Functions and New Equivalents
|-
! scope="col" | LDAP v2 Functions
! scope="col" | LDAP v3 Equivalent
|-
| ldap_abandon()
| ldap_abandon_ext()
|-
| ldap_add(), ldap_add_s()
| ldap_add_ext(), ldap_add_ext_s()
|-
| ldap_compare(), ldap_compare_s()
| ldap_compare_ext(), ldap_compare_ext_s
|-
| ldap_delete(), ldap_delete_s()
| ldap_delete_ext(), ldap_delete_ext_s
|-
| ldap_modify(), ldap_modify_s()
| ldap_modify_ext(), ldap_modify_ext_s
|-
| ldap_modrdn2(), ldap_modrdn2_s()
| ldap_rename(), ldap_rename_s()
|-
| ldap_search(), ldap_search_s(), ldap_search_st()
| ldap_search_ext(), ldap_search_ext_s, ldap_search_ext_s() - use timeout argument
|-
| ldap_unbind(), ldap_unbind_s()
| ldap_unbind_ext() replaces both forms which are identical besides the suffix.
|}
 
=== Functions Alphabetically  ===
 
This sections lists the functions in alphabetical order.
 
==== ber_alloc()  ====
 
The ber_alloc() function is used to allocate a new Basic Encoding Rules (BER) BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  BerElement* ber_alloc( void );</pre>
===== Parameters  =====
 
This function has no parameters.
 
===== Returns  =====
 
*If successful, a pointer to the newly allocated BerElement structure.
*If unsuccessful, a <tt>NULL</tt> pointer.
 
===== Description  =====
 
ber_alloc() is used to allocate a new BerElement structure for encoding data with the BER.
 
===== See Also  =====
 
ber_printf(), BerElement
 
==== ber_alloc_t()  ====
 
The ber_alloc_t() function constructs and returns a BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  BerElement* ber_alloc_t( int options );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_alloc_t() Function Parameter"
|+ ber_alloc_t() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>options</tt>
| Contains bitwise OR of options to be used when generating the encoding of the BerElement. One option is defined and must always be supplied: <tt>#define LBER_USE_DER 0x01</tt> When this option is present, lengths will always be encoded in the minimum number of octets. This option does not cause values of sets and sequences to be rearranged in tag and byte order, so these functions are not suitable for generating DER output as defined in X.509 and X.680.
|}
 
===== Returns  =====
 
*If successful, a pointer to the newly allocated BerElement structure.
*If unsuccessful, a <tt>NULL</tt> pointer.
 
===== Description  =====
 
This function is the same as ber_alloc() except it has an option.
 
===== See Also  =====
 
ber_printf(), BerElement
 
==== ber_bvecfree()  ====
 
The ber_bvecfree() function frees an array of berval structures.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  void ber_bvecfree( struct berval **bv );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_bvecfree() Function Parameter"
|+ ber_bvecfree() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>bv</tt>
| Pointer to the array that you want to free from memory.
|}
 
===== Description  =====
 
Each berval in the array is freed using ber_bvfree(), and then the array itself is freed.
 
===== See Also  =====
 
ber_bvfree()
 
==== ber_bvdup()  ====
 
The ber_bvdup() function returns a copy of a berval structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  berval* ber_bvdup( const struct berval *bv );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_bvdup() Function Parameter"
|+ ber_bvdup() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>bv</tt>
| Pointer to the berval structure to be duplicated.
|}
 
===== Returns  =====
 
*If successful, a pointer to the newly allocated berval structure.
*If unsuccessful, a <tt>NULL</tt> pointer.
 
===== Description  =====
 
The ber_bvdup() function returns a copy of a berval structure. The data referenced in the structure is also duplicated. The <tt>bv_val</tt> field in the returned berval points to a different area of memory than the <tt>bv_val</tt> field in the argument berval.
 
==== ber_bvfree()  ====
 
The ber_bvfree() function frees a berval structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  void ber_bvfree( struct berval *bv );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_bvfree() Function Parameter"
|+ ber_bvfree() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>bv</tt>
| Pointer to the berval structure that you want to free from memory.
|}
 
===== Description  =====
 
The ber_bvfree() function frees a berval structure from memory. Call this function to free a berval passed back from the ldap_extended_operation_s() , ldap_parse_extended_result(), ldap_sasl_bind_s(), or ldap_parse_sasl_bind_result() functions.
 
===== See Also  =====
 
ldap_extended_operation_s(), ldap_parse_extended_result(), ldap_sasl_bind_s() , ldap_parse_sasl_bind_result()
 
==== ber_dup()  ====
 
The ber_dup() function returns a copy of a BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  BerElement* ber_dup( BerElement *ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_dup() Function Parameter"
|+ ber_dup() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the BerElement to be duplicated.
|}
 
===== Returns  =====
 
*If successful, a pointer to the newly allocated BerElement structure.
*If unsuccessful, a <tt>NULL</tt> pointer.
 
===== Description  =====
 
The ber_dup() function returns a copy of a BerElement structure.
 
==== ber_first_element()  ====
 
The ber_first_element() function is used to return the tag and length of the first element in a set or sequence.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_first_element( BerElement *ber, unsigned long *len,
  char **last );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_first_element() Function Parameters"
|+ ber_first_element() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|-
| <tt>len</tt>
| Pointer to the address of the unsigned long which returns the length of the first element.
|-
| <tt>last</tt>
| Address of the pointer to return the address of the last byte of the element.
|}
 
===== Returns  =====
 
<tt>NULL</tt> pointer is returned on error.
 
===== Description  =====
 
The ber_first_element() function is used to return the tag and length of the first element in a set or sequence. It also returns a magic cookie parameter that should be passed to subsequent calls to ber_next_element() .
 
===== See Also  =====
 
ber_next_element()
 
==== ber_flatten()  ====
 
The ber_flatten() function allocates a berval structure whose contents are taken from a source BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
  int ber_flatten( BerElement *ber, struct berval **bvPtr );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_flatten() Function Parameters"
|+ ber_flatten() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the source BerElement.
|-
| <tt>bvPtr</tt>
| Pointer to the newly allocated berval structure which must be freed using ber_bvfree().
|}
 
===== Returns  =====
 
Returns <tt>0</tt> on success and <tt>-1</tt> on error.
 
===== Description  =====
 
This function is usually used when encoding LDAP v3 controls or extended operations values.
 
===== See Also  =====
 
ber_bvfree()
 
==== ber_free()  ====
 
The ber_free() function frees a BerElement structure previously allocated with ber_alloc() , ber_alloc_t(), ber_init(), or the ldap_first_attribute() and ldap_next_attribute() search functions.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
  void ber_free( BerElement *ber, int freebuf );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_free() Function Parameters"
|+ ber_free() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the BerElement structure that you want to free.
|-
| <tt>freebuf</tt>
| Specifies whether or not to free the buffer in the BerElement structure.
|}
 
===== Description  =====
 
This function frees a BerElement structure, which is used to keep track of the current attribute. When you are done working with the attributes, you should free this structure from memory, if it still exists.
 
'''Note:''' To retrieve attributes from a search result entry, you need to call either the ldap_first_attribute() or ldap_next_attribute() function. When freeing structures allocated by these functions, you should specify <tt>0</tt> for the <tt>freebuf</tt> argument. Otherwise, it should always be set to <tt>1</tt>.
 
===== Example  =====
 
the following example frees the BerElement structure allocated by the ldap_first_attribute() function.
<pre>LDAP *ld;
LDAPMessage *a, *e;
BerElement *ber;
...
for ( a = ldap_first_attribute( ld, e, &amp;ber ); a&nbsp;!= NULL;
  a =ldap_next_attribute( ld, e, ber ) {
    ...
    /* Retrieve the value of each attribute */
    ...
}
/* Free the BerElement when done */
if ( ber&nbsp;!= NULL ) {
  ber_free( ber, 0 );
}
...</pre>
===== See Also  =====
 
ber_alloc(), ber_alloc_t() , ber_init(), ldap_first_attribute(), ldap_next_attribute()
 
==== ber_get_boolean()  ====
 
The ber_get_boolean() function is used to read a boolean value.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_boolean( BerElement *ber,
  int *boolval );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_get_boolean() Function Parameters"
|+ ber_get_boolean() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the BerElement structure that contains the boolean.
|-
| <tt>boolval</tt>
| Specifies the boolean to read.
|}
 
===== Returns  =====
 
The value is returned on success and <tt>LBER_ERROR</tt> (<tt>-1</tt>) on failure.
 
==== ber_get_int()  ====
 
The ber_get_int() function tries to interpret the next element as an integer, returning the result in <tt>num</tt>.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_int( BerElement *ber, int *num );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_get_int() Function Parameters"
|+ ber_get_int() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the BerElement structure that contains the boolean.
|-
| <tt>num</tt>
| Pointer to the result.
|}
 
===== Returns  =====
 
The tag of whatever it finds is returned on success and <tt>LBER_ERROR</tt> (<tt>-1</tt>) on failure.
 
==== ber_get_next()  ====
 
The ber_get_next() function reads the next BER element.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_next( Sockbuf *sb, unsigned long *len,
  BerElement *ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_get_next() Function Parameters"
|+ ber_get_next() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>sb</tt>
| Descriptor (socket or file descriptor) from which to read.
|-
| <tt>len</tt>
| The length of the entire element.
|-
| <tt>ber</tt>
| Pointer to the BerElement structure.
|}
 
===== Description  =====
 
ber_get_next() strips off and returns the leading tag, strips off and returns the length of the entire element, and sets up a pointer to <tt>ber</tt> for subsequent calls to decode the element.
 
==== ber_get_next_buffer()  ====
 
The ber_get_next_buffer() function reads the next BER element from a byte buffer.
 
The ber_get_next_buffer_ext() function reads the next BER element from a byte buffer.
 
'''Note:''' ber_get_next_buffer_ext() is a new version of the ber_get_next_buffer() function. If you are writing a new LDAP client, use ber_get_next_buffer_ext() .
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_next_buffer_ext( void *buffer,
  size_t buffer_size, unsigned long *len, BerElement *ber,
  unsigned long *Bytes_Scanned, Sockbuf *sb );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_get_next_buffer_ext() Function Parameters"
|+ ber_get_next_buffer_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>buffer</tt>
| Pointer to the buffer.
|-
| <tt>buffer_size</tt>
| The size of the buffer.
|-
| <tt>len</tt>
| The length of the entire element.
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|-
| <tt>Bytes_Scanned</tt>
| Returns the number of bytes actually searched through.
|-
| <tt>sb</tt>
| Descriptor (socket or file descriptor) from which to read.
|}
 
==== ber_get_null()  ====
 
The ber_get_null() function is used to read a <tt>NULL</tt> element.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_null( BerElement *ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_get_null() Function Parameter"
|+ ber_get_null() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|}
 
===== Returns  =====
 
Returns the tag of the element it skips over.
 
==== ber_get_option()  ====
 
The ber_get_option() function is used to retrieve information about the API and about the specific implementation being used.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_get_option( BerElement *ber, int option, void *value );</pre>
==== ber_get_stringa()  ====
 
The ber_get_stringa() function is used to allocate memory space into which an octet string is read.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_stringa( BerElement *ber, char **buf );</pre>
==== ber_get_stringal()  ====
 
The ber_get_stringal() function is used to allocate memory space into which an octet string and its length are read.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_stringal( BerElement *ber, struct berval **bv );</pre>
===== Description  =====
 
It takes a berval structure, and returns the result in this parameter.
 
==== ber_get_stringb()  ====
 
The ber_get_stringb() function is used to read an octet string into a preallocated buffer.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_get_stringb( BerElement *ber, char *buf,
  unsigned long *len );</pre>
===== Description  =====
 
The <tt>len</tt> parameter should be initialized to the size of the buffer, and will contain the length of the octet string read upon return. The buffer should be big enough to take the octet string value plus a terminating <tt>NULL</tt> byte.
 
==== ber_init()  ====
 
The ber_init() function constructs a new BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
BerElement * ber_init( const struct berval *bv );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_init() Function Parameter"
|+ ber_init() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>bv</tt>
| Pointer to a berval.
|}
 
===== Returns  =====
 
*If successful, returns a new BerElement containing a copy of the data in the <tt>bv</tt> argument.
*If not, returns a <tt>NULL</tt> pointer.
 
==== ber_init_w_nullchar()  ====
 
The ber_init_w_nullchar() function constructs a new BerElement with a <tt>NULL</tt> character.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_init_w_nullchar( BerElement *ber, int options );</pre>
==== ber_next_element()  ====
 
The ber_next_element() function is used to return the tag and length of the next element in a set or sequence.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_next_element( BerElement *ber, unsigned long *len,
  char *last );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_next_element() Function Parameters"
|+ ber_next_element() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|-
| <tt>len</tt>
| Pointer to the address of the unsigned long which returns the length of the next element.
|-
| <tt>last</tt>
| Address of the pointer to return the address of the last byte of the element.
|}
 
===== Returns  =====
 
<tt>NULL</tt> pointer is returned on error.
 
===== Description  =====
 
The ber_next_element() function is used to return the tag and length of the first element in a set or sequence.
 
===== See Also  =====
 
ber_first_element()
 
==== ber_peek_tag()  ====
 
The ber_peek_tag() function returns the tag of the next element to be parsed in the supplied BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_peek_tag( BerElement *ber, unsigned long *len );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_peek_tag() Function Parameters"
|+ ber_peek_tag() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|-
| <tt>len</tt>
| Pointer to the address of the unsigned long which returns the length of the next element.
|}
 
===== Returns  =====
 
Returns the tag of the next element to be read in the BerElement structure. <tt>LBER_DEFAULT</tt> is returned if there is no further data to be read.
 
==== ber_printf()  ====
 
The ber_printf() function encodes a BER element.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
ber_printf( BerElement *ber, const char *fmt, ... );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_printf() Function Parameters"
|+ ber_printf() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement returned by ber_alloc() or ber_alloc_t().
|-
| <tt>fmt</tt>
| Defines the encoding format string. The format string can contain the following characters:
*<tt>-b</tt> Boolean. An integer parameter should be supplied. A boolean element is output.
*<tt>-i</tt> Integer. An integer parameter should be supplied. An integer element is output.
*<tt>-B</tt> Bitstring. A <tt>char *</tt> pointer to the start of the bitstring is supplied, followed by the number of bits in the bitstring. A bitstring element is output.
*<tt>-n</tt> Null. No parameter is required. A <tt>NULL</tt> element is output.
*<tt>-o</tt> Octet string. A <tt>char *</tt> is supplied, followed by the length of the string pointed to. An octet string element is output.
*<tt>-s</tt> Octet string. A <tt>NULL</tt> terminated string is supplied. An octet string element is output, not including the trailing <tt>NULL</tt> octet.
*<tt>-t</tt> Tag. An <tt>int</tt> specifying the tag to give the next element is provided. This works across calls.
*<tt>-v</tt> Several octet strings. A <tt>NULL</tt> terminated array of char *s is supplied. Note that a construct like '{v}' is required to get an actual sequence of octet strings.
*<tt>-{</tt> Begin sequence. No parameter is required.
*<tt>-</tt>} End sequence. No parameter is required.
*<tt>-[</tt> Begin set. No parameter is required.
*<tt>-]</tt> End set. No parameter is required.
 
|-
| <tt>...</tt>
| Values to be encoded.
|}
 
===== Description  =====
 
State information is kept with the <tt>ber</tt> parameter so multiple calls can be made to ber_printf() to append things to the end of the BerElement. ber_printf() interprets and formats its arguments according to the format string <tt>fmt</tt>. Each character in <tt>fmt</tt> refers to an argument to ber_printf() .
 
===== Returns  =====
 
<tt>-1</tt> if there is an error during encoding.
 
==== ber_put_bitstring()  ====
 
The ber_put_bitstring() function writes a bitstring value to the given BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_bitstring( BerElement *ber, char *str,
  unsigned long bitlen, unsigned long tag );</pre>
===== Description  =====
 
The ber_put_bitstring() function writes <tt>bitlen</tt> bits starting at <tt>str</tt> as a bitstring value to the given BerElement.
 
==== ber_put_boolean()  ====
 
The ber_put_boolean() function writes a boolean value to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_boolean( BerElement *ber, int boolval, unsigned long tag );</pre>
===== Description  =====
 
The boolean value is given by <tt>boolval</tt> to the BerElement.
 
==== ber_put_enum()  ====
 
The ber_put_enum() function writes an enumerated value to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_enum( BerElement *ber, long num, unsigned long tag );</pre>
==== ber_put_int()  ====
 
The ber_put_int() function writes an integer to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_int( BerElement *ber, long num, unsigned long tag );</pre>
==== ber_put_null()  ====
 
The ber_put_null() function writes a writes a <tt>NULL</tt> element to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_null( BerElement *ber, unsigned long tag );</pre>
==== ber_put_ostring()  ====
 
The ber_put_ostring() function writes bytes to a BerElement() as an octet string.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_ostring( BerElement *ber, char *str,
  unsigned long len, unsigned long tag );</pre>
==== ber_put_seq()  ====
 
The ber_put_seq() function puts a sequence to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_seq( BerElement *ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_put_seq() Function Parameter"
|+ ber_put_seq() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|}
 
===== Description  =====
 
The ber_start_seq() function is used to start a sequence in the BerElement. The end of the sequence is marked by the nearest matching call to ber_put_seq().
 
==== ber_put_set()  ====
 
The ber_put_set() function puts a set to a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_set( BerElement *ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_put_set() Function Parameter"
|+ ber_put_set() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|}
 
===== Description  =====
 
The ber_start_set() function is used to start a set in the BerElement. The end of the set is marked by the nearest matching call to ber_put_set().
 
==== ber_put_string()  ====
 
The ber_put_string() function writes a <tt>NULL</tt> terminated string (minus the terminating <tt>0</tt>) to a BerElement as an octet string.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_put_string( BerElement *ber, char *str, unsigned long tag );</pre>
==== ber_read()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
long ber_read( BerElement *ber, char *buf, unsigned long len );</pre>
==== ber_reset()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_reset( BerElement *ber, int was_writing );</pre>
==== ber_scanf()  ====
 
The ber_scanf() function decodes a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_scanf( BerElement *ber, const char *fmt, ... );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_scanf() Function Parameters"
|+ ber_scanf() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement as returned by ber_get_next().
|-
| <tt>fmt</tt>
| Defines the encoding format string. The format string can contain the following characters:
*<tt>-a</tt> Octet string. A <tt>char **</tt> should be supplied. Memory is allocated, filled with the contents of the octet string, <tt>NULL</tt> terminated, and returned in the parameter.
*<tt>-s</tt> Octet string. A <tt>char *</tt> buffer should be supplied, followed by a pointer to an integer initialized to the size of the buffer. Upon return, the <tt>NULL</tt> terminated octet string is put into the buffer, and the integer is set to the actual size of the octet string.
*<tt>-O</tt> Octet string. A <tt>struct ber_val**</tt> should be supplied, which upon return points to a memory allocated <tt>struct berval</tt> containing the octet string and its length. Call ber_bvfree() to free allocated memory.
*<tt>-b</tt> Boolean. A pointer to an integer should be supplied.
*<tt>-i</tt> Integer. A pointer to an integer should be supplied.
*<tt>-B</tt> Bitstring. A <tt>char **</tt> should be supplied which will point to the memory allocated bits, followed by an <tt>unsigned long *</tt>, which will point to the length (in bits) of the bitstring returned.
*<tt>-n</tt> Null. No parameter is required. The element is simply skipped if it is recognized.
*<tt>-v</tt> Sequence of octet strings. A <tt>char***</tt> should be supplied, which upon return points to a memory allocated <tt>NULL</tt> terminated array of <tt>char *</tt>s containing the octet strings. <tt>NULL</tt> is returned if the sequence is empty.
*<tt>-V</tt> Sequence of octet strings with lengths. A <tt>struct berval ***</tt> should be supplied, which upon return points to a memory allocated, <tt>NULL</tt> terminated array of <tt>struct berval *</tt>s containing the octet strings and their lengths. <tt>NULL</tt> is returned if the sequence is empty. ber_bvecfree() can be called to free the allocated memory.
*<tt>-x</tt> Skip element. The next element is skipped.
*<tt>-{</tt> Begin sequence. No parameter is required. The initial sequence tag and length are skipped.
*<tt>-</tt>} End sequence. No parameter is required and no action is taken.
*<tt>-[</tt> Begin set. No parameter is required. The initial set tag and length are skipped.
*<tt>-]</tt> End set. No parameter is required and no action is taken.
 
|-
| <tt>...</tt>
| Values to be encoded.
|}
 
===== Description  =====
 
ber_scanf() reads from <tt>ber</tt>, interprets the bytes according to the format string <tt>fmt</tt>, and stores the results in its additional arguments. The format string contains conversion specifications which are used to direct the interpretation of the BER element.
 
===== See Also  =====
 
ber_printf()
 
==== ber_set_option()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_set_option( BerElement *ber, int option, void *value );</pre>
==== ber_set_string_translators()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_skip_tag( BerElement *ber, unsigned long *len );</pre>
==== ber_skip_tag()  ====
 
The ber_skip_tag() function advances the pointer to a BerElement past the first tag and length to the next tag.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
unsigned long ber_skip_tag( BerElement *ber, unsigned long *len );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ber_skip_tag() Function Parameters"
|+ ber_skip_tag() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to a BerElement.
|-
| <tt>len</tt>
| Pointer to the length of the value to be skipped.
|}
 
===== Description  =====
 
ber_skip_tag() should only be used with constructed types and situations when a BER encoding is used as the value of an octet string.
 
===== See Also  =====
 
ber_peek_tag()
 
==== ber_sockbuf_alloc()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
Sockbuf* ber_sockbuf_alloc( void );</pre>
==== ber_sockbuf_free()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_sockbuf_free( Sockbuf* p );</pre>
==== ber_sockbuf_free_data()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_sockbuf_free_data(Sockbuf *p);</pre>
==== ber_sockbuf_get_option()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_sockbuf_get_option( Sockbuf *sb, int option, void *value );</pre>
==== ber_sockbuf_set_option()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_sockbuf_set_option( Sockbuf *sb, int option, void *value );</pre>
==== ber_special_alloc()  ====
 
The ber_special_alloc() function allocates a BerElement structure plus some extra memory.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void* ber_special_alloc( size_t size, BerElement **ppBer );</pre>
===== Returns  =====
 
Returns a pointer to the BerElement and a pointer to the extra memory.
 
===== Description  =====
 
ber_special_alloc() allocates a ber data buffer within the same block, thus saving a call to calloc later when we read data.
 
==== ber_special_free()  ====
 
The ber_special_free() function frees an allocated BerElement structure.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_special_free( void* buf, BerElement *ber );</pre>
===== See Also  =====
 
ber_special_alloc()
 
==== ber_stack_init()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int LDAP_CALL ber_stack_init(BerElement *ber, int options,
  char * buf, size_t size);</pre>
==== ber_start_seq()  ====
 
The ber_start_seq() function is used to start a sequence in a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_start_seq( BerElement *ber, unsigned long tag );</pre>
===== See Also  =====
 
ber_put_seq()
 
==== ber_start_set()  ====
 
The ber_start_seq() function is used to start a set in a BerElement.
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
int ber_start_set( BerElement *ber, unsigned long tag );</pre>
===== See Also  =====
 
ber_put_set()
 
==== ber_svecfree()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
void ber_svecfree( char **vals );</pre>
==== ber_write()  ====
 
===== Syntax  =====
<pre>#include &lt;lber.h&gt;
long ber_write( BerElement *ber, char *buf,
  unsigned long len, int nosos );</pre>
==== ldap_abandon()  ====
 
The ldap_abandon() function cancels an asynchronous LDAP operation that is in progress.
<pre>#include &lt;ldap.h&gt;
int ldap_abandon( LDAP *ld, int msgid );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_abandon() Function Parameters"
|+ ldap_abandon() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>msgid</tt>
| Message ID of an LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*<tt>-1</tt> if unsuccessful.
 
'''Note:''' The appropriate LDAP error code is also set in the LDAP structure. You can retrieve the error code by calling ldap_get_lderrno(). Some possible codes are:
 
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
Please use the newer version of this function, ldap_abandon_ext().
 
===== Example  =====
 
The following example cancels an ldap_url_search() operation, abandoning the results of the operation.
<pre>LDAP *ld;
char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales";
int msgid;
...
/* Initiate a search operation */
msgid = ldap_url_search( ld, url, 0 );
...
/* Abandon the search operation */
if ( ldap_abandon( ld, msgid )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_abandon" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_abandon_ext()
 
==== ldap_abandon_ext()  ====
 
The ldap_abandon_ext() function cancels an asynchronous LDAP operation that is in progress.
<pre>#include &lt;ldap.h&gt;
int ldap_abandon_ext( LDAP *ld, int msgid,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_abandon_ext() Function Parameters"
|+ ldap_abandon_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>msgid</tt>
| Message ID of an LDAP operation to identify the operation to be cancelled. When you call an asynchronous function such as ldap_search_ext(), the <tt>msgidp</tt> argument returns a pointer to a message ID that uniquely identifies the operation. Thus, when you call ldap_abandon_ext(), your LDAP client is able to send a request specifying the message ID of the operation to be cancelled.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
The ldap_abandon_ext() function cancels an asynchronous LDAP operation that is in progress. For example, if you called ldap_search_ext() to initiate an LDAP search operation on the server, you can call ldap_abandon_ext() to cancel it. When you call ldap_abandon_ext(), the function checks to see if the results of the operation have already been returned. If so, ldap_abandon_ext() deletes the message ID from the queue of pending messages. If the results have not been returned, ldap_abandon_ext() sends a request to abandon the operation. Once cancelled, the results of the operation will not be returned, even if you subsequently call ldap_result() to retrieve them. To identify the operation to be cancelled, specify the message ID of the operation in the <tt>msgid</tt> argument of the ldap_abandon_ext() function.
 
===== Example  =====
 
the following example cancels an ldap_url_search() operation, abandoning the results of the operation. Using ldap_abandon_ext()
<pre>LDAP *ld;
char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales";
int msgid;
LDAPControl **srvrctrls, **clntctrls;
...
/* Initiate a search operation */
msgid = ldap_url_search( ld, url, 0 );
...
/* Abandon the search operation */
if ( ldap_abandon_ext( ld, msgid, srvrctrls, clntctrls )
&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_abandon" );
    return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_add_ext(), ldap_compare_ext() , ldap_delete_ext(), ldap_extended_operation(), ldap_modify_ext(), ldap_rename(), ldap_sasl_bind , ldap_search_ext(), ldap_simple_bind(), ldap_url_search()
 
==== ldap_add()  ====
 
The ldap_add() function adds a new entry to the directory asynchronously.
 
'''Note:''' This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_add_ext() instead.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_add( LDAP *ld, const char *dn, LDAPMod **attrs );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_add() Function Parameters"
|+ ldap_add() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, <tt>o=organization</tt> or <tt>c=country</tt>) must already exist.
|-
| <tt>attrs</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
|}
 
===== Returns  =====
 
The message ID of the ldap_add() operation. Please use the newer version of this function, ldap_add_ext() .
 
===== Example  =====
 
the following example adds a new entry to the directory. Using ldap_add()
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the new entry. Note that "dc=example,dc=com" and
"ou=People,dc=example,dc=com" must already exist in the directory. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* To add a "person" entry, you must specify values for the sn, cn,
and objectClass attributes. (These are required attributes.) */
char *sn_values[] = { "Jensen", NULL };
/* To specify multiple values for an attribute, add the different values
to the array. */
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
/* The object class for a "person" entry is "inetOrgPerson", which is a
subclass of "top", "person", and "organizationalPerson". You should add
all of these classes as values of the objectClass attribute. */
char *objectClass_values[] = { "top", "person", "organizationalPerson",
  "inetOrgPerson", NULL };
...
/* Specify the value and type of each attribute in separate LDAPMod
structures */
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &amp;attribute1;
list_of_attrs[1] = &amp;attribute2;
list_of_attrs[2] = &amp;attribute3;
list_of_attrs[3] = NULL;
...
/* Set up the timeout period for adding the new entry */
tv.tv_sec = tv.tv_usec = 0;
/* Add the user "Barbara Jensen" */
if ( ( msgid = ldap_add( ld, dn, list_of_attrs ) ) == -1 ) {
  ldap_perror( ld, "ldap_add" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &amp;tv, &amp;result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
if (( rc = ldap_result2error( ld, result, 1 ))&nbsp;!= LDAP_SUCCESS ) {
  printf( "Error while adding entry:&nbsp;%s\n", ldap_err2string( rc ));
}
...</pre>
===== See Also  =====
 
ldap_add_ext()
 
==== ldap_add_ext()  ====
 
The ldap_add_ext() function adds a new entry to the directory asynchronously.
 
'''Note: '''ldap_add_ext() is a new version of the ldap_add() function. If you are writing a new LDAP client, use ldap_add_ext().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_add_ext( LDAP *ld, const char *dn, LDAPMod **attrs,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_add_ext() Function Parameters"
|+ ldap_add_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, <tt>o=organization</tt> or <tt>c=country</tt>) must already exist.
|-
| <tt>attrs</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== Description  =====
 
The ldap_add_ext() adds a new entry to the directory.
 
To add a new entry to the directory, you need to specify:
 
*A unique DN identifying the new entry.<br>Use the <tt>dn</tt> argument to specify the DN of the new entry. The parents of the entry should already exist. For example, if you are adding the entry <tt>uid=bjensen,ou=People,dc=example,dc=com</tt> , the entries <tt>ou=People</tt> and <tt>dc=example,dc=com</tt> must already exist in the directory.
*A set of attributes for the new entry.<br>Create an LDAPMod structure for each attribute. Set the <tt>mod_op</tt> field to <tt>0</tt> if the attribute values are string values. To specify values that consist of binary data (such as a sound file or a JPEG file), set the <tt>mod_op</tt> field to <tt>LDAP_MOD_BVALUES</tt>. Create an array of these LDAPMod structures and pass the array as the <tt>attrs</tt> argument. ldap_add_ext() is an asynchronous function; it does not directly return results. In order to get the results of the asynchronous operation, you need to call the ldap_result() and ldap_parse_result() functions. If you want the results to be returned directly by the function, call the synchronous function ldap_add_ext_s(). For a list of possible result codes for an LDAP add operation, see the ldap_add_ext_s() function.
 
===== See Also  =====
 
ldap_add_ext_s(), ldap_result, ldap_parse_result(), LDAPMod
 
==== ldap_add_ext_s()  ====
 
The ldap_add_ext_s() function adds a new entry to the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_add_ext_s() Function Parameters"
|+ ldap_add_ext_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, <tt>o=organization</tt> or <tt>c=country</tt>) must already exist.
|-
| <tt>attrs</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_add_ext_s() function adds a new entry to the directory. To add a new entry to the directory, you need to specify:
 
*A unique DN identifying the new entry.<br>Use the <tt>dn</tt> argument to specify the DN of the new entry. The parents of the entry should already exist. For example, if you are adding the entry <tt>uid=bjensen,ou=People,dc=example,dc=com</tt> , the entries <tt>ou=People</tt> and <tt>dc=example,dc=com</tt> must already exist in the directory.
*A set of attributes for the new entry.<br>Create an LDAPMod structure for each attribute. Set the <tt>mod_op</tt> field to <tt>0</tt> if the attribute values are string values. To specify values that consist of binary data (such as a sound file or a JPEG file), set the <tt>mod_op</tt> field to <tt>LDAP_MOD_BVALUES</tt>. Create an array of these LDAPMod structures and pass the array as the <tt>attrs</tt> argument. ldap_add_ext_s() is a synchronous function; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_add_ext().
 
===== See Also  =====
 
ldap_add_ext(), LDAPMod
 
==== ldap_add_s()  ====
 
The ldap_add_s() function adds a new entry to the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_add_s( LDAP *ld, const char *dn, LDAPMod **attrs );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_add_s() Function Parameters"
|+ ldap_add_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, <tt>o=organization</tt> or <tt>c=country</tt>) must already exist.
|-
| <tt>attrs</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
|}
 
===== Returns  =====
 
See ldap_add_ext_s() for a list of possible return codes.
 
===== Description  =====
 
Please use the newer version of this function, ldap_add_ext_s() .
 
===== Example  =====
 
The following example adds a new entry to the directory.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
/* Distinguished name of the new entry. Note that "dc=example,dc=com" and
"ou=People,dc=example,dc=com" must already exist in the directory. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
/* To add a "person" entry, you must specify values for the sn, cn,
and objectClass attributes. (These are required attributes.) */
char *sn_values[] = { "Jensen", NULL };
/* To specify multiple values for an attribute, add the different values
to the array. */
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
/* The object class for a "person" entry is "inetOrgPerson", which is a
* subclass of "top", "person", and "organizationalPerson". You should add
* all of these classes as values of the objectClass attribute. */
char *objectClass_values[] = { "top", "person", "organizationalPerson",
  "inetOrgPerson", NULL };
...
/* Specify the value and type of each attribute in separate LDAPMod
structures */
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &amp;attribute1;
list_of_attrs[1] = &amp;attribute2;
list_of_attrs[2] = &amp;attribute3;
list_of_attrs[3] = NULL;
...
/* Add the user "Barbara Jensen" */
if ( ldap_add_s( ld, dn, list_of_attrs )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_add_s" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_add_ext_s()
 
==== ldap_ber_free()  ====
 
The ldap_ber_free() function frees a BerElement structure from memory.
 
'''Note:''' This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ber_free() instead. Except in name, the two functions are identical.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_ber_free( BerElement *ber, int freebuf );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_ber_free() Function Parameters"
|+ ldap_ber_free() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ber</tt>
| Pointer to the BerElement structure that you want to free.
|-
| <tt>freebuf</tt>
| Specifies whether or not to free the buffer in the BerElement structure.
|}
 
===== Description  =====
 
Please use the newer version of this function, ber_free().
 
===== See Also  =====
 
ber_free()
 
==== ldap_bind()  ====
<pre>#include &lt;ldap-deprecated.h&gt;
ldap_bind( LDAP *ld, const char *who, const char *passwd, int method );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_bind() Function Parameters"
|+ ldap_bind() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>who</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to <tt>NULL</tt>.
|-
| <tt>passwd</tt>
| Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to <tt>NULL</tt>.
|-
| <tt>method</tt>
| Defines the authentication method to be used. It should be set to <tt>LDAP_AUTH_SIMPLE</tt> to select simple authentication.
|}
 
===== Returns  =====
 
ldap_bind() returns the message ID of the request it initiates.
 
===== Description  =====
 
This is an asynchronous function that authenticates a specified entry to the directory. After a connection is made to an LDAP server using ldap_open(), a bind operation must be performed before other operations can be attempted over the connection.
 
===== See Also  =====
 
ldap_open(), ldap_init(), prldap_init() (IPv6), ldap_bind_s()
 
==== ldap_bind_s()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Use ldap_simple_bind_s() instead.
 
ldap_bind_s() can be used when the authentication method needs to be selected at runtime.
 
===== Syntax  =====
<pre>#include &lt;ldap-deprecated.h&gt;
ldap_bind_s( LDAP *ld, const char *who, const char *cred, int method );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_bind_s() Function Parameters"
|+ ldap_bind_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>who</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to <tt>NULL</tt>.
|-
| <tt>cred</tt>
| Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to <tt>NULL</tt>.
|-
| <tt>method</tt>
| Defines the authentication method to be used. It should be set to <tt>LDAP_AUTH_SIMPLE</tt> to select simple authentication.
|}
 
===== Returns  =====
 
ldap_bind_s() returns an LDAP error indication.
 
===== Description  =====
 
This is a synchronous function that authenticates a specified entry to the directory. After a connection is made to an LDAP server using ldap_open() , a bind operation must be performed before other operations can be attempted over the connection.
 
===== See Also  =====
 
ldap_open(), ldap_init(), prldap_init() (IPv6), ldap_bind()
 
==== ldap_build_filter()  ====
 
See also ldap_create_filter().
 
==== ldap_cache_flush()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Use the <tt>ldap_memcache_*</tt> functions instead.
 
For more specific information, see the header file <tt>ldap-deprecated.h</tt> .
 
===== See Also  =====
 
ldap_memcache_init(), ldap_memcache_set(), ldap_memcache_get(), ldap_memcache_update(), ldap_memcache_flush() , ldap_memcache_destroy()
 
==== ldap_charray_add()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
For more specific information, see the header file <tt>ldap-to-be-deprecated.h</tt>.
 
==== ldap_charray_free()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
For more specific information, see the header file <tt>ldap-to-be-deprecated.h</tt>.
 
==== ldap_charray_merge()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
For more specific information, see the header file <tt>ldap-to-be-deprecated.h</tt>.
 
==== ldap_compare()  ====
 
The ldap_compare() function asynchronously determines if an attribute of an entry contains a specified value.
<pre>#include &lt;ldap.h&gt;
int ldap_compare( LDAP *ld, const char *dn, const char *attr,
  const char *value );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_compare() Function Parameters"
|+ ldap_compare() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry used in the comparison.
|-
| <tt>attr</tt>
| Attribute type that you want to check the value against.
|-
| <tt>value</tt>
| Value that you want to compare against the attribute values.
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_compare() operation.
 
'''Note:''' To check the result of this operation, call ldap_result() and ldap_result2error(). See ldap_compare_ext_s() function for a list of possible result codes for the LDAP compare operation.
 
===== Description  =====
 
Please use the newer version of this function, ldap_compare_ext() .
 
===== Example  =====
 
the following example checks to see if Barbara Jensen has the email address <tt>bjensen@example.com</tt>.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
int msgid;
...
msg_id = ldap_compare( ld, dn, "mail", "bjensen@example.com" );
...</pre>
===== See Also  =====
 
ldap_compare_ext()
 
==== ldap_compare_ext()  ====
 
The ldap_compare_ext() function asynchronously determines if an attribute of an entry contains a specified value.
<pre>#include &lt;ldap.h&gt;
int ldap_compare_ext( LDAP *ld, const char *dn, const char *attr,
  struct berval *bvalue, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_compare_ext() Function Parameters"
|+ ldap_compare_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry used in the comparison.
|-
| <tt>attr</tt>
| Attribute type that you want to check the value against.
|-
| <tt>value</tt>
| Value that you want to compare against the attribute values.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' To check the result of this operation, call ldap_result() and ldap_parse_result().
 
===== Returns  =====
 
For a list of the possible result codes for an LDAP compare operation, see ldap_compare_ext_s().
 
===== Description  =====
 
The ldap_compare_ext() function compares the value of an attribute in an entry against a specified value. Because ldap_compare_ext() is an asynchronous function, it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_compare_ext_s().
 
===== See Also  =====
 
ldap_compare_ext_s(), ldap_result(), ldap_parse_result()
 
==== ldap_compare_ext_s()  ====
 
The ldap_compare_ext_s() function synchronously determines if an attribute of an entry contains a specified value.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_compare_ext_s( LDAP *ld, const char *dn,
  const char *attr, struct berval *bvalue,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_compare_ext_s() Function Parameters"
|+ ldap_compare_ext_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry used in the comparison.
|-
| <tt>attr</tt>
| Attribute type that you want to check the value against.
|-
| <tt>value</tt>
| Value that you want to compare against the attribute values.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_COMPARE_TRUE if the entry contains the attribute value.
*LDAP_COMPARE_FALSE if the entry does not contain the attribute value.
*LDAP_PARAM_ERROR if any of the arguments&nbsp;are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
The ldap_compare_ext_s() function compares the value of an attribute in an entry against a specified value. ldap_compare_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_compare_ext().
 
===== See Also  =====
 
ldap_compare_ext()
 
==== ldap_compare_s()  ====
 
The ldap_compare_s() function synchronously determines if an attribute of an entry contains a specified value.
 
'''Note:''' This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_compare_ext_s() instead.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_compare_s( LDAP *ld, const char *dn,
  const char *attr, const char *value );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_compare_s() Function Parameters"
|+ ldap_compare_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry used in the comparison.
|-
| <tt>attr</tt>
| Attribute type that you want to check the value against.
|-
| <tt>value</tt>
| Value that you want to compare against the attribute values.
|}
 
===== Returns  =====
 
For a list of the possible result codes for an LDAP compare operation, see ldap_compare_ext_s().
 
===== Description  =====
 
Please use the newer version of this function, ldap_compare_ext_s() .
 
===== Example  =====
 
The following example checks to see if Barbara Jensen has the email address <tt>bjensen@example.com</tt>.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
int has_value;
...
has_value = ldap_compare_s( ld, dn, "mail", "bjensen@example.com" );
switch ( has_value ) {
  case LDAP_COMPARE_TRUE:
    printf( "The mail attribute contains bjensen@example.com.\n");
    break;
  case LDAP_COMPARE_FALSE:
    printf( "The mail attribute does not contain bjensen@example.com.\n");
    break;
  default:
    ldap_perror( ld, "ldap_compare_s" );
    return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_compare_ext_s()
 
==== ldap_control_free()  ====
 
The ldap_control_free() function frees an LDAPControl structure from memory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_control_free( LDAPControl *ctrl );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_control_free() Function Parameter"
|+ ldap_control_free() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ctrl</tt>
| Pointer to an LDAPControl structure that you want to free from memory.
|}
 
===== Description  =====
 
The ldap_control_free() function frees an LDAPControl structure from memory. You should call this function to free controls that you create; for example, if you call the ldap_create_sort_control() function.
 
===== See Also  =====
 
ldap_controls_free()
 
==== ldap_controls_free()  ====
 
The ldap_controls_free() function frees an array of LDAPControl structures from memory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_controls_free( LDAPControl **ctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_controls_free() Function Parameter"
|+ ldap_controls_free() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ctrls</tt>
| Pointer to an array of LDAPControl structures that you want to free from memory.
|}
 
===== Description  =====
 
The ldap_controls_free() function frees an array of LDAPControl structures from memory. You should call this function to free arrays of controls that you create or any arrays returned by ldap_parse_result().
 
===== See Also  =====
 
ldap_control_free(), ldap_parse_result()
 
==== ldap_count_entries()  ====
 
The ldap_count_entries() function returns the number of LDAPMessage structures representing directory entries in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_count_entries( LDAP *ld, LDAPMessage *result );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_count_entries() Function Parameters"
|+ ldap_count_entries() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>result</tt>
| Chain of search results, represented by pointer to an LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, the number of LDAPMessage() structures of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> in a chain of search results. If there are no structures of this type, returns <tt>0</tt>.
 
*<tt>-1</tt> if <tt>ld</tt> is not a valid connection handle.
 
===== Description  =====
 
The ldap_count_entries() function returns the number of LDAPMessage structures representing directory entries in a chain of search results. These messages have the type <tt>LDAP_RES_SEARCH_ENTRY</tt> .
 
See the examples under ldap_search_ext() and ldap_search_ext_s().
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_entry(), ldap_next_entry(), ldap_first_entry(), ldap_next_message()
 
==== ldap_count_messages()  ====
 
The ldap_count_messages() function returns the number of LDAPMessage structures in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_count_messages( LDAP *ld, LDAPMessage *res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_count_messages() Function Parameters"
|+ ldap_count_messages() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>result</tt>
| Chain of search results, represented by pointer to an LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*The number of LDAPMessage structures in a chain of search results, if successful. If there are no structures, returns <tt>0</tt>.
*<tt>-1</tt> if <tt>ld</tt> is not a valid connection handle.
 
===== Description  =====
 
The ldap_count_messages() function returns the number of LDAPMessage structures in a chain of search results. The count is the number of search entries plus the number of search references.
 
'''Note:''' If you pass in a pointer to an LDAPMessage structure in the middle of the chain of results, the function counts only between that structure and the last structure in the chain. In this type of situation, the function does not return the count of all structures in the chain.
 
===== Example  =====
 
See the examples under ldap_search_ext() and ldap_search_ext_s().
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_message(), ldap_next_message(), ldap_first_entry(), ldap_next_entry() , ldap_first_reference(), ldap_next_reference()
 
==== ldap_count_references()  ====
 
The ldap_count_references() function returns the number of LDAPMessage structures representing search references in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_count_references( LDAP *ld, LDAPMessage *res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_count_references() Function Parameters"
|+ ldap_count_references() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>result</tt>
| Chain of search results, represented by pointer to an LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*The number of LDAPMessage structures of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt> in a chain of search results, if successful. (If there are no structures of this type, returns <tt>0</tt>.)
*<tt>-1</tt> if <tt>ld</tt> is not a valid connection handle.
 
===== Description  =====
 
The ldap_count_references() function returns the number of LDAPMessage structures representing search references in a chain of search results. These messages have the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.
 
See the examples under ldap_search_ext() and ldap_search_ext_s().
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_reference(), ldap_next_reference()
 
==== ldap_count_values()  ====
 
The ldap_count_values() function returns the number of values in an array of strings. '''Note:''' Use the ldap_count_values_len() function if the array contains berval structures.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_count_values( char **values );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_count_values() Function Parameter"
|+ ldap_count_values() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| values
| Array of values.
|}
 
===== Returns  =====
 
One of the following values:
 
*The number of values in the array, if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Example  =====
 
The following example counts the number of values assigned to an attribute.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *e;
char *a="cn";
char **vals;
int count;
...
/* Get the values of the cn attribute */
vals = ldap_get_values( ld, e, a );
/* Count the values of the attribute */
count = ldap_count_values( vals );
...</pre>
===== See Also  =====
 
ldap_count_values_len(), ldap_get_values()
 
==== ldap_count_values_len()  ====
 
The ldap_count_values_len() function returns the number of values in an array of berval structures.
<pre>#include &lt;ldap.h&gt;
int ldap_count_values_len( struct berval **vals );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_count_values_len() Function Parameter"
|+ ldap_count_values_len() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>values</tt>
| Array of berval structures.
|}
 
===== Returns  =====
 
One of the following values:
 
*The number of values in the array, if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Example  =====
 
The following example counts the number of values assigned to an attribute.
<pre>#include &lt;ldap.h&gt;
LDAP *ld;
LDAPMessage *e;
char *a="jpegPhoto";
struct berval **bvals;
int count;
...
/* Get the values of the jpegPhoto attribute */
bvals = ldap_get_values_len( ld, e, a );
/* Count the values of the attribute */
count = ldap_count_values_len( vals );
...</pre>
===== See Also  =====
 
ldap_count_values(), ldap_get_values_len()
 
==== ldap_create_authzid_control()  ====
 
The ldap_create_authzid_control() function creates a control that requests the authorization ID for a bind operation. This is defined in RFC 3829.
 
'''Note:''' In order for the control to work, the LDAP server that you are connecting to must support the server controls for authorization bind identity (OID <tt>2.16.840.1.113730.3.4.16</tt> or <tt>LDAP_CONTROL_AUTHZID_REQ</tt>, and OID <tt>2.16.840.1.113730.3.4.15</tt> or <tt>LDAP_CONTROL_AUTHZID_RES</tt>).
 
Calling ldap_create_authzid_control() creates an LDAP control that you can pass to the ldap_simple_bind() function to retrieve the authorization ID in the response. You call ldap_parse_authzid_control() function on the controls returned with an entry to retrieve a <tt>char *</tt> containing the authorization ID. When you are done with the search, you should free the control by calling the ldap_control_free() function.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_create_authzid_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_authzid_control() Function Parameters"
|+ ldap_create_authzid_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctl_iscritical
| Specifies whether the control is critical to the operation.
*If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
*If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
 
|-
| ctrlp
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
 
===== See Also  =====
 
ldap_parse_authzid_control()
 
==== ldap_create_filter()  ====
 
The ldap_create_filter() routine constructs an LDAP search filter.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_create_filter( char *buf, unsigned long buflen,
  char *pattern, char *prefix, char *suffix, char *attr,
  char *value, char **valwords );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_filter() Function Parameters"
|+ ldap_create_filter() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>buf</tt>
| Buffer to contain the constructed filter.
|-
| <tt>buflen</tt>
| Size of the buffer.
|-
| <tt>pattern</tt>
| Pattern for the filter.
|-
| <tt>prefix</tt>
| Prefix to prepend to the filter. (<tt>NULL</tt> if not used.)
|-
| <tt>suffix</tt>
| Suffix to append to the filter. (<tt>NULL</tt> if not used.)
|-
| <tt>attr</tt>
| Replaces <tt>%a</tt> in the pattern.
|-
| <tt>value</tt>
| Replaces <tt>%v</tt> in the pattern.
|-
| <tt>valwords</tt>
| Replaces <tt>%vM</tt> through <tt>%vN</tt> in the pattern.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_SIZELIMIT_EXCEEDED if the created filter exceeds the size of the buffer.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
 
===== Example  =====
 
The following example builds the filter <tt>(mail=bjensen@example.com)</tt>.
<pre>char buf[LDAP_FILT_MAXSIZ];
char *pattern = "(%a=%v)";
char *attr = "mail";
char *value = "bjensen@example.com";
...
ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL,
  NULL, attr, value, NULL );
...</pre>
===== See Also  =====
 
ldap_init_getfilter(), ldap_init_getfilter_buf(), ldap_getfirstfilter() , ldap_getnextfilter(), ldap_set_filter_additions()
 
==== ldap_create_geteffectiveRights_control()  ====
 
The ldap_create_geteffectiveRights_control() function allows a user having correct privileges to query about the access rights another identity has on one or more entries in the directory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_create_geteffectiveRights_control( LDAP *ld,
  const char *authzid, const char **attrlist, const char ctl_iscritical,
  LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_geteffectiveRights_control() Function Parameters"
|+ ldap_create_geteffectiveRights_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>authzid</tt>
| The DN of the identity for which you are checking access rights.
|-
| <tt>attrlist</tt>
| List of attributes to return, such as <tt>aclRights</tt> and <tt>aclRightsInfo</tt>.
|-
| <tt>ctl_iscritical</tt>
| Specifies whether the control is critical to the operation. *If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error. *If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
==== ldap_create_persistentsearch_control()  ====
 
The ldap_create_persistentsearch_control() function creates a control that allows your client to perform a search of an LDAP v3 server that continues without termination until your client abandons it.
<pre>#include &lt;ldap.h&gt;
int ldap_create_persistentsearch_control( LDAP *ld,
  int changetypes, int changesonly, int return_echg_ctls,
  char ctl_iscritical, LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_persistentsearch_control() Function Parameters"
|+ ldap_create_persistentsearch_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>changetypes</tt>
| Specifies the types of changes that you want to keep track of. This field can have one or more of the following values:
*<tt>LDAP_CHANGETYPE_ADD</tt> specifies that you want to keep track of entries added to the directory.
*<tt>LDAP_CHANGETYPE_DELETE</tt> specifies that you want to keep track of entries deleted from the directory.
*<tt>LDAP_CHANGETYPE_MODIFY</tt> specifies that you want to keep track of entries that are modified.
*<tt>LDAP_CHANGETYPE_MODDN</tt> specifies that you want to keep track of entries that are renamed.
*<tt>LDAP_CHANGETYPE_ANY</tt> specifies that you want to keep track of all of the above changes to the directory. You can <tt>OR</tt> the values together to specify multiple types.
 
|-
| <tt>changesonly</tt>
| Specifies whether or not you want skip the initial search and only get the latest changes as they occur:
*If non-zero, the initial search is skipped and only entries that have changed after the initial search are returned.
*If <tt>0</tt>, the results of the initial search are returned first.
 
|-
| <tt>return_echg_ctls</tt>
| Specifies whether or not entry controls are included with each entry returned to your client:
*If non-zero, a control is included with each entry.
*If <tt>0</tt>, controls are not included with the entries returned from the server.
 
|-
| <tt>ctl_iscritical</tt>
| Specifies whether the control is critical to the operation.
*If non-zero, the control is critical to the operation. If the server does not support it, the server will return an <tt>LDAP_UNAVAILABLE_CRITICAL_EXTENSION</tt> error.
*If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
 
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred
 
when BER-encoding the control.
 
===== Description  =====
 
The ldap_create_persistentsearch_control() function allows you to perform persistent searches. A ''persistent search'' provides the means to track changes to a set of entries that match the search criteria. After the initial search is performed, the server keeps track of the search criteria and sends back information when any entry that matches the criteria is added, deleted, modified, or renamed. Calling ldap_create_persistentsearch_control() creates an LDAP server control that you can pass to the ldap_search_ext() function.
 
As stated, after you create the control, you can pass it to the LDAP server during a search operation. If you specify that you want “entry change notification” controls sent back (that is, if you specify a non-zero value for the <tt>return_echg_ctls</tt> parameter), the server includes controls with each changed entry it sends back. To retrieve the controls from each entry, call the ldap_get_entry_controls() function. To get data about the changes made to the entry from the control, call the ldap_parse_entrychange_control() function. When you are done with the search, you can cancel the persistent search by calling the ldap_abandon_ext() function. You should also free the control from memory by calling the ldap_control_free() function.
 
===== See Also  =====
 
ldap_search_ext(), ldap_abandon_ext, ldap_get_entry_controls(), ldap_parse_entrychange_control(), ldap_control_free()
 
==== ldap_create_pwdpolicy_control()  ====
 
The ldap_create_pwdpolicy_control() function creates a control that requests information about the status of a user account.
 
'''Note:''' ldap_create_pwdpolicy_control() implements an extension to the LDAP v3 supported by Directory Server. In order for the control to work, the LDAP server that you are connecting to must support the server control for password policy (OID <tt>1.3.6.1.4.1.42.2.27.8.5.1</tt>, or <tt>LDAP_CONTROL_ACCOUNT_USABLE</tt>).
 
Calling ldap_create_pwdpolicy_control() creates an LDAP control that you can pass to the ldap_simple_bind() functions to retrieve password policy information from bind, modify, add, compare, and potentially extended operation responses including password policy response controls. You call ldap_parse_pwdpolicy_control() function on the controls returned with an entry to retrieve a LDAPpwdpolicy structure containing information about the status of the account. When you are done with the search, you should free the control by calling the ldap_control_free() function.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_create_pwdpolicy_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_pwdpolicy_control() Function Parameters"
|+ ldap_create_pwdpolicy_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctl_iscritical
| Specifies whether the control is critical to the operation.
*If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
*If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
 
|-
| ctrlp
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
 
===== See Also  =====
 
ldap_parse_pwdpolicy_control(), LDAPpwdpolicy()
 
==== ldap_create_proxiedauth_control()  ====
 
The ldap_create_proxiedauth_control() function creates an LDAP v3 control that allows a bound entity to assume the identity of another directory entry.
<pre>#include &lt;ldap.h&gt;
int ldap_create_proxiedauth_control( LDAP *ld, char *authzid,
  LDAPControl **ctrlp);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_proxiedauth_control() Function Parameters"
|+ ldap_create_proxiedauth_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>authzid</tt>
| The string representing the identity to assume for the access rights, defined in the format specified by the following Augmented Backus-Naur Form (ABNF) from RFC 4513:&nbsp;; Specific predefined authorization (authz)&nbsp;; id schemes are defined below --&nbsp;; new schemes may be defined in the future. authzId = dnAuthzId / uAuthzId&nbsp;; distinguished-name-based authz id. dnAuthzId = "dn:" dn dn = utf8string&nbsp;; syntax from RFC 4514&nbsp;; unspecified userid, UTF-8 encoded. uAuthzId = "u:" userid userid = utf8string&nbsp;; syntax unspecified
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Description  =====
 
More information on proxy authorization can be found in the ''LDAP'' Proxied Authorization Control Internet Draft''(http://ietfreport.isoc.org/ids/draft-weltman-ldapv3-proxy-12.txt).''
 
'''Note:''' Proxy authorization is an optional feature; it may not be supported on all LDAP servers. In order for the control to work, the server that you are connecting to must support the server control for proxy authorization (OID 2.16.840.1.113730.3.4.18, or LDAP_CONTROL_PROXIEDAUTH, as defined in the ldap-extension.h header file).
 
==== ldap_create_proxyauth_control()  ====
 
The ldap_create_proxyauth_control() function creates an LDAP v3 control that allows a bound entity to assume the identity of another directory entry.
<pre>#include &lt;ldap.h&gt;
int ldap_create_proxyauth_control( LDAP *ld, char *DN,
  char ctl_iscritical, LDAPControl **ctrlp);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_proxyauth_control() Function Parameters"
|+ ldap_create_proxyauth_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>DN</tt>
| String representing the DN of the entry who's identity the client will be assuming.
|-
| <tt>ctl_iscritical</tt>
| Specifies whether the control is critical to the operation.
*If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
*If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
 
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_UNAVAILABLE_CRITICAL_EXTENSION if the server does not support proxy authorization and <tt>ctl_iscritical</tt> is set to a non-zero value.
 
===== See Also  =====
 
ldap_control_free()
 
==== ldap_create_sort_control()  ====
 
The ldap_create_sort_control() function creates a control that specifies the order in which you want search results returned.
 
'''Note:''' This function implements an extension to the LDAP v3. Server-side sorting is an optional feature; it may not be supported on all LDAP servers. Call this function when interacting with LDAP servers that support this LDAP v3 extension.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_create_sort_control( LDAP *ld,
  LDAPsortkey **sortKeyList, const char ctl_iscritical,
  LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_sort_control() Function Parameters"
|+ ldap_create_sort_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>sortKeyList</tt>
| Pointer to an array of LDAPsortkey structures that specify the attribute types or matching rules used for sorting and the order (ascending or descending) in which to sort the results.
|-
| <tt>ctl_iscritical</tt>
| Specifies whether the control is critical to the operation. *If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error. *If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
 
===== Description  =====
 
The ldap_create_sort_control() function allows you to specify the order in which you want to receive data from the server. Calling this function creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions.
 
See also ldap_create_sort_keylist(), ldap_search_ext(), ldap_search_ext_s(), ldap_control_free().
 
==== ldap_create_sort_keylist()  ====
 
The ldap_create_sort_keylist() function creates an array of LDAPsortkey structures from a string representation of a set of sort keys.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_create_sort_keylist(LDAPsortkey ***sortKeyList,
  const char *string_rep);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_sort_keylist() Function Parameters"
|+ ldap_create_sort_keylist() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>sortKeyList</tt>
| Pointer to an array of LDAPsortkey structures that specify the attribute types or matching rules used for sorting and the order (ascending or descending) in which to sort the results.
|-
| <tt>string_rep</tt>
| String representation of a set of sort keys. The value should specify the name of the attribute that you want to sort by. To sort in reverse order, precede the attribute name with a hyphen, <tt>-</tt>. To use a matching rule for sorting, append a colon to the attribute name and specify the object identifier (OID) of a matching rule after the colon. For example:
*<tt>cn</tt> (sorts by the <tt>cn</tt> attribute)
*<tt>-cn</tt> (sorts by the <tt>cn</tt> attribute in reverse order)
*<tt>-cn:1.2.3.4</tt> (sorts by the <tt>cn</tt> attribute in reverse order using the matching rule identified by the OID <tt>1.2.3.4</tt>)
 
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*<tt>-1</tt> if an error occurred.
 
===== Description  =====
 
Calling the ldap_create_sort_keylist() function allows you to create an array of LDAPsortkey structures from a string representation of a set of sort keys. You can then pass the array to the ldap_create_sort_control() function. The string representation specified by the <tt>string_rep</tt> argument should specify the name of the attribute that you want to sort by and how the sort will work. When you are done sorting the results, you should free the array of LDAPsortkey() structures by calling the ldap_free_sort_keylist() function.
 
===== See Also  =====
 
ldap_create_sort_control(), ldap_free_sort_keylist()
 
==== ldap_create_userstatus_control()  ====
 
The ldap_create_userstatus_control() function creates a control that requests information about the status of a user account.
 
'''Note:''' ldap_create_userstatus_control() implements an extension to the LDAP v3 supported by Directory Server. In order for the control to work, the LDAP server that you are connecting to must support the server control for account availability (OID <tt>1.3.6.1.4.1.42.2.27.9.5.8</tt>, or <tt>LDAP_CONTROL_ACCOUNT_USABLE</tt>).
 
Calling ldap_create_userstatus_control() creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions. You call ldap_parse_userstatus_control() function on the controls returned with an entry to retrieve a LDAPuserstatus structure containing information about the status of the account. When you are done with the search, you should free the control by calling the ldap_control_free() function.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_create_userstatus_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_userstatus_control() Function Parameters"
|+ ldap_create_userstatus_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctl_iscritical
| Specifies whether the control is critical to the operation.
*If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
*If <tt>0</tt>, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
 
|-
| ctrlp
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter  was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
 
===== See Also  =====
 
ldap_parse_userstatus_control(), LDAPuserstatus()
 
==== ldap_create_virtuallist_control()  ====
 
The ldap_create_virtuallist_control() function creates a control that requests a subset of search results for use in a virtual list box.
<pre>#include &lt;ldap.h&gt;
int ldap_create_virtuallist_control( LDAP *ld,
  LDAPVirtualList *ldvlistp, LDAPControl **ctrlp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_create_virtuallist_control() Function Parameters"
|+ ldap_create_virtuallist_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>ldvlistp</tt>
| Pointer to an LDAPVirtualList structure that specifies the subset of entries that you want retrieved from the server and the selected entry.
|-
| <tt>ctrlp</tt>
| Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
 
===== Description  =====
 
The ldap_create_virtuallist_control() function allows you to retrieve a subset of entries from the server for use in a virtual list box. To specify the subset of entries that you want to retrieve, create an LDAPVirtualList structure and pass in a pointer to this structure as the <tt>ldvlistp</tt> argument.
 
'''Note:''' In order for the control to work, the LDAP server that you are connecting to must support the server control for sorting search results (OID 2.16.840.1.113730.3.4.9, or <tt>LDAP_CONTROL_VLVREQUEST</tt>, as defined in the <tt>ldap.h</tt> header file).
 
Calling ldap_create_virtuallist_control() creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions. You also need to pass a server-side sorting control to the search functions. You can call ldap_create_sort_keylist() and ldap_create_sort_control() to create a server-side sorting control. When you are done with the search, you should free the control by calling the ldap_control_free() function.
 
===== See Also  =====
 
LDAPVirtualList, ldap_parse_virtuallist_control(), ldap_search_ext() , ldap_search_ext_s(), ldap_control_free()
 
==== ldap_delete()  ====
 
The ldap_delete() function removes an entry from the directory asynchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_delete( LDAP *ld, const char *dn );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_delete() Function Parameters"
|+ ldap_delete() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to remove.
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_delete() operation.
 
'''Note:''' To check the result of this operation, call ldap_result and ldap_result2error(). See ldap_delete_ext_s() for a list of possible result codes for the LDAP delete operation.
 
===== Description  =====
 
Please use the newer version of this function, ldap_delete_ext() .
 
===== Example  =====
 
The following example uses the asynchronous ldap_delete() function to remove the entry for <tt>Barbara Jensen</tt> from the directory.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to delete. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
...
/* Set up the timeout period to wait for the "modify" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Delete the entry */
if ( ( msgid = ldap_delete( ld, dn ) ) == -1 ) {
  ldap_perror( ld, "ldap_delete" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &amp;tv, &amp;result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_delete" );
...</pre>
===== See Also  =====
 
ldap_delete_ext()
 
==== ldap_delete_ext()  ====
 
The ldap_delete_ext() function deletes an entry from the directory asynchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_delete_ext( LDAP *ld, const char *dn,
  LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_delete_ext() Function Parameters"
|+ ldap_delete_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to remove.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' To check the result of this operation, call ldap_result and ldap_result2error(). See ldap_delete_ext_s() for a list of possible result codes for the LDAP delete operation.
 
===== Description  =====
 
The ldap_delete_ext() function deletes an entry from the directory, using the <tt>dn</tt> argument to specify the entry that you want to delete. ldap_delete_ext() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_delete_ext_s() .
 
===== See Also  =====
 
ldap_delete_ext_s(), ldap_result(), ldap_parse_result()
 
==== ldap_delete_ext_s()  ====
 
The ldap_delete_ext_s() function deletes an entry from the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_delete_ext_s( LDAP *ld, const char *dn,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_delete_ext_s() Function Parameters"
|+ ldap_delete_ext_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to remove.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_delete_ext_s() function deletes an entry from the directory, using the <tt>dn</tt> argument to specify the entry that you want to delete. ldap_delete_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_delete_ext() instead.
 
===== See Also  =====
 
ldap_delete_ext()
 
==== ldap_delete_s()  ====
 
The ldap_delete_s() deletes an entry from the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_delete_s(LDAP *ld, const char *dn);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_delete_s() Function Parameters"
|+ ldap_delete_s() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to remove.
|}
 
===== Returns  =====
 
For a list of possible result codes for an LDAP delete operation, see the ldap_delete_ext_s() function.
 
===== Description  =====
 
Please use the newer version of this function, ldap_delete_ext_s() .
 
===== Example  =====
 
The following example uses the synchronous ldap_delete_s() function to delete the entry for <tt>Barbara Jensen</tt> from the directory.
<pre>#include &lt;ldap.h&gt;
LDAP *ld;
/* Distinguished name of the entry that you want to delete. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
...
/* Delete the entry */
if ( ldap_delete_s( ld, dn )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_delete_s" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_delete_ext_s()
 
==== ldap_dn2ufn()  ====
 
The ldap_dn2ufn() function converts a DN into a more user-friendly form by stripping off the cryptic type names.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_dn2ufn( const char *dn );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_dn2ufn() Function Parameter"
|+ ldap_dn2ufn() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>dn</tt>
| The DN that you want converted.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns the DN in its friendlier form.
*If unsuccessful, returns <tt>NULL</tt>.
 
===== Description  =====
 
For more information on user friendly naming (UFN), see RFC 1781,&lt;citetitle&gt; Using the OSI Directory to Achieve User Friendly Naming &lt;/citetitle&gt; (&lt;ulink url="http://www.faqs.org/rfcs/rfc1781.html" type="text_url"&gt;&lt;/ulink&gt;).
 
==== ldap_entry2html()  ====
 
The ldap_entry2html() function writes the HTML representation of an LDAP entry.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_entry2html( LDAP *ld, char *buf, LDAPMessage *entry,
  struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
  writeptype writeproc, void *writeparm, char *eol, int rdncount,
  unsigned long opts, char *urlprefix, char *base );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_entry2html() Function Parameters"
|+ ldap_entry2html() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>buf</tt>
| A pointer to a buffer of size <tt>LDAP_DTMPL_BUFSIZ</tt> or larger. If <tt>NULL</tt>, a buffer is allocated and freed internally.
|-
| <tt>entry</tt>
| Specifies the attribute values to be represented.
|-
| <tt>tmpl</tt>
| Pointer to the display template to be used, usually obtained by calling ldap_oc2template().
|-
| <tt>defattrs</tt>
| A <tt>NULL</tt> terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
|-
| <tt>defvals</tt>
| An array of <tt>NULL</tt> terminated arrays of default values corresponding to the attributes.
|-
| <tt>writeproc</tt>
| Your writeproc() function should be declared as: <tt>int writeproc( writeparm, p, len )</tt> <tt>void *writeparm;</tt> <tt>char *p;</tt> <tt>int len;</tt> where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|-
| <tt>opts</tt>
| Specifies output options. The allowed values are:
*zero (default output)
*<tt>LDAP_DISP_OPT_AUTOLABELWIDTH</tt> which causes the width for labels to be determined based on the longest label in <tt>tmpl</tt>.
*<tt>LDAP_DISP_OPT_HTMLBODYONLY</tt> which instructs the library not to include <tt>&lt;HTML&gt;</tt>, <tt>&lt;HEAD&gt;</tt>, <tt>&lt;TITLE&gt;</tt>, and <tt>&lt;BODY&gt;</tt> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
 
|-
| <tt>urlprefix</tt>
| Starting text to use when constructing an LDAP URL. The default is the string <tt>ldap://</tt>.
|-
| <tt>base</tt>
| The base with which to begin when executing search actions. If <tt>NULL</tt> , search action template items are ignored.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_entry2html() produces an HTML representation of an entry. It behaves exactly like ldap_entry2text() except for the output and the addition of two parameters.
 
===== See Also  =====
 
ldap_entry2text(), ldap_oc2template
 
==== ldap_entry2html_search()  ====
 
The ldap_entry2html_search() function determines the appropriate display template to use by calling ldap_oc2template().
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_entry2html_search( LDAP *ld, char *dn, char *base,
  LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
  char ***defvals, writeptype writeproc, void *writeparm, char *eol,
  int rdncount, unsigned long opts, char *urlprefix );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_entry2html_search() Function Parameters"
|+ ldap_entry2html_search() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to write as HTML.
|-
| <tt>base</tt>
| The base with which to begin when executing search actions. If <tt>NULL</tt> , search action template items are ignored.
|-
| <tt>entry</tt>
| Specifies the attribute values to be represented.
|-
| <tt>tmpllist</tt>
| Pointer to the entire list of templates available, usually obtained by calling ldap_init_templates() or ldap_init_templates_buf(). If <tt>NULL</tt>, will attempt to read a load templates from the default template configuration file.
|-
| <tt>defattrs</tt>
| A <tt>NULL</tt> terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
|-
| <tt>defvals</tt>
| An array of <tt>NULL</tt> terminated arrays of default values corresponding to the attributes.
|-
| <tt>writeproc</tt>
| writeproc() function should be declared as: <tt>int writeproc( writeparm, p, len )</tt> <tt>void *writeparm;</tt> <tt>char *p;</tt> <tt>int len;</tt> where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|-
| <tt>opts</tt>
| Specifies output options. The allowed values are:
*zero (default output)
*<tt>LDAP_DISP_OPT_AUTOLABELWIDTH</tt> which causes the width for labels to be determined based on the longest label in <tt>tmpl</tt>.
*<tt>LDAP_DISP_OPT_HTMLBODYONLY</tt> which instructs the library not to include <tt>&lt;HTML&gt;</tt>, <tt>&lt;HEAD&gt;</tt>, <tt>&lt;TITLE&gt;</tt>, and <tt>&lt;BODY&gt;</tt> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
 
|-
| <tt>urlprefix</tt>
| Starting text to use when constructing an LDAP URL. The default is the string <tt>ldap://</tt>
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_entry2html_search() will call ldap_search_s() to retrieve any attribute values to be displayed. It behaves exactly like ldap_entry2text_search(), except the <tt>urlprefix</tt> parameter is required and HTML is the output.
 
===== See Also  =====
 
ldap_search_s(), ldap_entry2text_search(), ldap_init_templates(), ldap_init_templates_buf(), ldap_entry2text()
 
==== ldap_entry2text()  ====
 
The ldap_entry2text() function writes the text representation of an LDAP entry.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_entry2text( LDAP *ld, char *buf, LDAPMessage *entry,
  struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
  writeptype writeproc, void *writeparm, char *eol, int rdncount,
  unsigned long opts );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_entry2text() Function Parameters"
|+ ldap_entry2text() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>buf</tt>
| A pointer to a buffer of size <tt>LDAP_DTMPL_BUFSIZ</tt> or larger. If <tt>NULL</tt>, a buffer is allocated and freed internally.
|-
| <tt>entry</tt>
| Specifies the attribute values to be represented.
|-
| <tt>tmpl</tt>
| Pointer to the display template to be used, usually obtained by calling ldap_oc2template().
|-
| <tt>defattrs</tt>
| A <tt>NULL</tt> terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
|-
| <tt>defvals</tt>
| An array of <tt>NULL</tt> terminated arrays of default values corresponding to the attributes.
|-
| <tt>writeproc</tt>
| writeproc() function should be declared as: <tt>int writeproc( writeparm, p, len )</tt> <tt>void *writeparm;</tt> <tt>char *p;</tt> <tt>int len;</tt> where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|-
| <tt>opts</tt>
| Specifies output options. The allowed values are:
*zero (default output)
*<tt>LDAP_DISP_OPT_AUTOLABELWIDTH</tt> which causes the width for labels to be determined based on the longest label in <tt>tmpl</tt>.
*<tt>LDAP_DISP_OPT_HTMLBODYONLY</tt> which instructs the library not to include <tt>&lt;HTML&gt;</tt>, <tt>&lt;HEAD&gt;</tt>, <tt>&lt;TITLE&gt;</tt>, and <tt>&lt;BODY&gt;</tt> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
 
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_entry2text() produces a text representation of an entry and writes the text by calling the <tt>writeproc</tt> function. All of the attribute values to be displayed must be present in entry as no interaction with the LDAP server will be performed.
 
===== See Also  =====
 
ldap_entry2html(), ldap_oc2template
 
==== ldap_entry2text_search()  ====
 
The ldap_entry2text_search() function determines the appropriate display template to use by calling ldap_oc2template().
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_entry2text_search( LDAP *ld, char *dn, char *base,
  LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
  char ***defvals, writeptype writeproc, void *writeparm,
  char *eol, int rdncount, unsigned long opts );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_entry2text_search() Function Parameters"
|+ ldap_entry2text_search() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to write.
|-
| <tt>base</tt>
| If <tt>NULL</tt>, the search action template items are ignored. If not <tt>NULL</tt>, it is the search base to use when executing search actions.
|-
| <tt>entry</tt>
| If entry is not <tt>NULL</tt>, it should contain the <tt>objectClass</tt> attribute values for the entry to be displayed. If <tt>NULL</tt>, dn can not be <tt>NULL</tt>, and ldap_entry2text_search() will retrieve the <tt>objectClass</tt> values itself by calling ldap_search_s().
|-
| <tt>tmpllist</tt>
| Pointer to the entire list of templates available, usually obtained by calling ldap_init_templates() or ldap_init_templates_buf(). If <tt>NULL</tt>, will attempt to read a load templates from the default template configuration file.
|-
| <tt>defattrs</tt>
| A <tt>NULL</tt> terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
|-
| <tt>defvals</tt>
| An array of <tt>NULL</tt> terminated arrays of default values corresponding to the attributes.
|-
| <tt>writeproc</tt>
| writeproc() function should be declared as: <tt>int writeproc( writeparm, p, len )</tt> <tt>void *writeparm;</tt> <tt>char *p;</tt> <tt>int len;</tt> where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|-
| <tt>opts</tt>
| Specifies output options. The allowed values are:
*zero (default output)
*<tt>LDAP_DISP_OPT_AUTOLABELWIDTH</tt> which causes the width for labels to be determined based on the longest label in <tt>tmpl</tt>.
*<tt>LDAP_DISP_OPT_HTMLBODYONLY</tt> which instructs the library not to include <tt>&lt;HTML&gt;</tt>, <tt>&lt;HEAD&gt;</tt>, <tt>&lt;TITLE&gt;</tt>, and <tt>&lt;BODY&gt;</tt> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
 
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_entry2text_search() will call ldap_search_s() to retrieve any attribute values to be displayed.
 
===== See Also  =====
 
ldap_entry2html_search(), ldap_oc2template(), ldap_search_s(), ldap_init_templates(), ldap_init_templates_buf()
 
==== ldap_err2string()  ====
 
The ldap_err2string() function returns the corresponding error message for an error code.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_err2string( int err );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_err2string() Function Parameter"
|+ ldap_err2string() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>err</tt>
| Error code that you want interpreted into an error message.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the corresponding error message for the error code.
*If unsuccessful (for example, if the error code is not a valid LDAP API error code), returns <tt>Unknown error</tt>.
 
===== Example  =====
 
The following example sets the variable ''err_msg'' to the error message corresponding to the error code returned by the ldap_simple_bind_s() function.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
char *pw = "hifalutin";
char *err_msg;
...
err_msg = ldap_err2string( ldap_simple_bind_s( ld, dn, pw ) );
...</pre>
===== See Also  =====
 
ldap_get_lderrno(), ldap_perror(), ldap_result2error(), ldap_set_lderrno(), ldapssl_err2string()
 
==== ldap_explode_dn()  ====
 
The ldap_explode_dn() function converts a DN into its component parts.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char ** ldap_explode_dn( const char *dn, int notypes );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_explode_dn() Function Parameters"
|+ ldap_explode_dn() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>dn</tt>
| DN that you want separated into components.
|-
| <tt>notypes</tt>
| Specifies whether or not type names in the DN are returned. This parameter can have the following possible values: *<tt>0</tt> specifies that type names are returned. *A non-zero value specifies that type names are not returned.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a <tt>NULL</tt> terminated array containing the components of the DN.
*If unsuccessful, returns <tt>NULL</tt>.
 
===== Example  =====
 
The following function call:
<pre>ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 );</pre>
returns this array:
<pre>{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL }</pre>
If you change the <tt>notypes</tt> parameter from <tt>0</tt> to <tt>1</tt>:
<pre>ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 );</pre>
The component names are not returned in the array:
<pre>{ "bjensen", "People", "example.com", NULL }</pre>
===== See Also  =====
 
ldap_explode_rdn(), ldap_get_dn()
 
==== ldap_explode_dns()  ====
 
'''Note:''' This function is to be deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
The ldap_explode_dns() function takes a DNS-style DN, breaks it up into its component parts, and returns a <tt>NULL</tt> terminated array. For example, the DN <tt>ldap.example.com</tt> will return <tt>{ "ldap", "example", "com", NULL </tt>}. The result can be freed by calling ldap_value_free().
 
===== Syntax  =====
<pre>#include &lt;ldap-to-be-deprecated.h&gt;
char ** ldap_explode_dns( const char *dn );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_explode_dns() Function Parameter"
|+ ldap_explode_dns() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>dn</tt>
| DN that you want separated into components.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a <tt>NULL</tt> terminated array containing the components of the DN.
*If unsuccessful, returns <tt>NULL</tt>.
 
==== ldap_explode_rdn()  ====
 
The ldap_explode_rdn() function converts a relative distinguished name (RDN) into its component parts.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char ** ldap_explode_rdn( const char *dn, int notypes );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_explode_rdn() Function Parameters"
|+ ldap_explode_rdn() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>dn</tt>
| RDN that you want separated into components.
|-
| <tt>notypes</tt>
| Specifies whether or not type names in the RDN are returned. This parameter can have the following possible values: *<tt>0</tt> specifies that type names are returned. *A non-zero value specifies that type names are not returned.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a <tt>NULL</tt> terminated array containing the components of the RDN.
*If unsuccessful, returns <tt>NULL</tt>.
 
===== Example  =====
 
The following function call:
<pre>ldap_explode_rdn( "ou=Sales + cn=Barbara Jensen", 0 );</pre>
returns this array:
<pre>{ "ou=Sales", "cn=Barbara Jensen", NULL }</pre>
===== See Also  =====
 
ldap_explode_dn(), ldap_get_dn
 
==== ldap_extended_operation()  ====
 
The ldap_extended_operation() function sends a request to the server to perform an extended operation asynchronously.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_extended_operation( LDAP *ld, const char *requestoid,
  struct berval *requestdata, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_extended_operation() Function Parameters"
|+ ldap_extended_operation() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>requestoid</tt>
| Object identifier (OID) of the extended operation that you want the server to perform. After processing an LDAP v3 extended operation, an LDAP server can return an OID and data in the result. To parse the OID and data from the result, call the ldap_parse_extended_result() function.
|-
| <tt>requestdata</tt>
| Pointer to a berval structure containing the data that you want passed to the server to perform the extended operation. The data in the berval is a buffer of the BER encoded data type, usually obtained using the ber_flatten() function.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
The ldap_extended_operation() function sends a request to the server to perform an LDAP v3 extended operation. ldap_extended_operation() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_extended_operation_s().
 
===== See Also  =====
 
ldap_extended_operation_s(), ldap_result(), ldap_parse_extended_result(), ldap_get_lderrno(), ber_flatten()
 
==== ldap_extended_operation_s()  ====
 
The ldap_extended_operation_s() function sends a request to the server to perform an extended operation synchronously.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_extended_operation_s( LDAP *ld, const char *requestoid,
  struct berval *requestdata, LDAPControl **serverctrls,
  LDAPControl **clientctrls, char **retoidp, struct berval **retdatap );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_extended_operation_s() Function Parameters"
|+ ldap_extended_operation_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>requestoid</tt>
| Object identifier (OID) of the extended operation that you want the server to perform.
|-
| <tt>requestdata</tt>
| Pointer to a berval structure containing the data that you want passed to the server to perform the extended operation. The data in the berval is a buffer of the BER encoded data type, usually obtained using the ber_flatten() function.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>retoidp</tt>
| Pointer to the OID returned by the server after performing the extended operation. When done, you can free this by calling the ldap_memfree() function.
|-
| <tt>retdatap</tt>
| Pointer to the pointer for a berval structure containing the data returned by the server after performing the extended operation. When done, you can free this by calling the ber_bvfree() function.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_extended_operation_s() function sends a request to the server to perform an LDAP v3 extended operation. See also ldap_extended_operation(), ber_flatten()
 
==== ldap_first_attribute()  ====
 
The ldap_first_attribute() function returns the name of the first attribute in an entry returned by the ldap_first_entry() , the ldap_next_entry(), or the ldap_result() functions.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_first_attribute( LDAP *ld, LDAPMessage *entry,
  BerElement **ber );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_attribute() Function Parameters"
|+ ldap_first_attribute() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Pointer to the LDAPMessage structure representing the entry returned by the ldap_first_entry() or ldap_next_entry() function.
|-
| <tt>ber</tt>
| Pointer to a BerElement allocated to keep track of its current position. Pass this pointer to subsequent calls to ldap_next_attribute() to step through the entry's attributes.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the pointer to the name of the first attribute in an entry. When you are done using this data, you should free the memory by calling the ldap_memfree() function.
*If unsuccessful, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Example  =====
 
The following example retrieves each attribute for an entry.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)"
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
  my_filter, NULL, 0, &amp;result )&nbsp;!=
  LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
  /* Retrieve the attributes the entry */
  for ( a = ldap_first_attribute( ld, e, &amp;ber ); a&nbsp;!= NULL;
    a = ldap_next_attribute( ld, e, ber ) ) {
      ...
      /* Code to get and manipulate attribute values */
      ...
    }
    ldap_memfree( a );
  }
  /* Free the BerElement from memory when done */
  if ( ber&nbsp;!= NULL ) {
    ldap_ber_free( ber, 0 );
  }
...</pre>
===== See Also  =====
 
ldap_first_entry(), ldap_next_entry(), ldap_next_attribute(), BerElement
 
==== ldap_first_disptmpl()  ====
 
The ldap_first_disptmpl() function returns the first template in a list.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
ldap_first_disptmpl( struct ldap_disptmpl *tmpllist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_disptmpl() Function Parameter"
|+ ldap_first_disptmpl() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Description  =====
 
ldap_first_disptmpl() returns the first template in the list of templates pointed to by the parameter <tt>tmpllistp</tt>. <tt>tmpllistp</tt> is typically obtained by calling ldap_init_templates() .
 
===== See Also  =====
 
ldap_next_disptmpl(), ldap_init_templates(), ldap_init_templates_buf()
 
==== ldap_first_entry()  ====
 
The ldap_first_entry() function returns a pointer to the LDAPMessage structure representing the first directory entry in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_first_entry( LDAP *ld, LDAPMessage *result );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_entry() Function Parameters"
|+ ldap_first_entry() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>result</tt>
| Chain of search results, which are represented by a pointer to the LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns the pointer to the first LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> in the chain of search results.
*If no LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> are in the chain of the search results or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_first_entry() function returns a pointer to the LDAPMessage structure representing the first directory entry in a chain of search results. Search result entries are in messages of the type <tt>LDAP_RES_SEARCH_ENTRY</tt>. You can use this function in conjunction with the ldap_next_entry() function to iterate through the directory entries in a chain of search results. These functions skip over any messages in the chain that do not have the type <tt>LDAP_RES_SEARCH_ENTRY</tt>. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_entry()
 
==== ldap_first_message()  ====
 
The ldap_first_message() function returns a pointer to the first LDAPMessage structure in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_first_message( LDAP *ld, LDAPMessage *res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_message() Function Parameters"
|+ ldap_first_message() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>res</tt>
| Chain of search results, represented by a pointer to the LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns the pointer to the first LDAPMessage structure in the chain of search results.
*If no LDAPMessage structures are in the chain or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_first_message() function returns a pointer to the first LDAPMessage structure in a chain of search results. You can use this function in conjunction with the ldap_next_message() function to iterate through the chain of search results. You can also call the ldap_msgtype() function to determine if each message contains a matching entry, a message of the type <tt>LDAP_RES_SEARCH_ENTRY</tt>, or a search reference, a message of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_message(), ldap_first_entry(), ldap_first_reference()
 
==== ldap_first_reference()  ====
 
The ldap_first_reference() function returns a pointer to the LDAPMessage structure representing the first search reference in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_first_reference(LDAP *ld, LDAPMessage *res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_reference() Function Parameters"
|+ ldap_first_reference() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>res</tt>
| Chain of search results, which are represented by a pointer to the LDAPMessage structure.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the pointer to the first LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt> in the chain of search results.
*If no LDAPMessage structures of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt> are in the chain of the search results or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_first_reference() function returns a pointer to the LDAPMessage structure representing the first search reference in a chain of search results. Search references are in messages of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs. You can use this function in conjunction with the ldap_next_reference function to iterate through the search references in a chain of search results. These functions skip over any messages in the chain that do not have the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.
 
===== See Also  =====
 
ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_reference(), ldap_first_message()
 
==== ldap_first_searchobj()  ====
 
The ldap_first_searchobj() function returns the first search preference configuration from a data structure defined in the list <tt>solist</tt> .
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
ldap_searchobj * ldap_first_searchobj( struct ldap_searchobj *solist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_searchobj() Function Parameter"
|+ ldap_first_searchobj() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| solist
| Pointer to the search preference data structures, typically obtained by calling ldap_init_searchprefs().
|}
 
===== Description  =====
 
<tt>ldap_first_searchobj</tt> provides access to LDAP search preference configuration data. LDAP search preference configurations are typically used by LDAP client programs to specify which attributes a user may search by, the labels for the attributes, and the LDAP filters and scopes associated with those searches.
 
===== See Also  =====
 
ldap_init_searchprefs(), ldap_init_searchprefs_buf()
 
==== ldap_first_tmplcol()  ====
 
The ldap_first_tmplcol() function returns a pointer to the first item within a template.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_tmplitem * ldap_first_tmplcol( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_tmplcol() Function Parameters"
|+ ldap_first_tmplcol() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| The name of the template to be retrieved.
|-
| <tt>row</tt>
| The row in which the item is to be retrieved from.
|}
 
===== Returns  =====
 
*If successful, a pointer to an <tt>ldap_tmplitem</tt> structure.
*A <tt>NULL</tt> pointer on error.
 
===== Description  =====
 
ldap_first_tmplcol() returns a pointer to the first item (in the first column) of the row, defined by <tt>row</tt>, within the template defined by <tt>tmpl</tt>.
 
===== See Also  =====
 
ldap_first_tmplrow(), ldap_next_tmplcol()
 
==== ldap_first_tmplrow()  ====
 
The ldap_first_tmplrow() function returns a pointer to the first row of items in a template.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_tmplitem * ldap_first_tmplrow( struct ldap_disptmpl *tmpl );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_first_tmplrow() Function Parameter"
|+ ldap_first_tmplrow() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| The name of the template to be retrieved.
|}
 
===== Returns  =====
 
*If successful, a pointer to an <tt>ldap_tmplitem</tt> structure.
*A <tt>NULL</tt> pointer on error.
 
===== See Also  =====
 
ldap_next_tmplrow(), ldap_first_tmplcol()
 
==== ldap_free_friendlymap()  ====
 
The ldap_free_friendlymap() function frees the FriendlyMap structures allocated by the ldap_friendly_name() function when no more calls to it are to be made.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_free_friendlymap( FriendlyMap *map );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_free_friendlymap() Function Parameter"
|+ ldap_free_friendlymap() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>map</tt>
| Pointer to the FriendlyMap() mapping structure in memory.
|}
 
===== Example  =====
 
The following example frees memory allocated by the ldap_friendly_name() function.
<pre>#include &lt;ldap.h&gt;
#include &lt;stdio.h&gt;
...
FriendlyMap map = NULL;
char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly";
char *unfriendly_name = "IS";
char *friendly_name;
...
/* Read the ldapfriendly file into the map in memory */
friendly_name = ldap_friendly_name( map_file, unfriendly_name, &amp;map );
printf( "Friendly Name for&nbsp;%s:&nbsp;%s\n", unfriendly_name, friendly_name );
/* Since file is in memory, no need to reference it in subsequent calls */
friendly_name = ldap_friendly_name( NULL, "VI", &amp;map );
printf( "Friendly Name for VI:&nbsp;%s\n", friendly_name );
...
ldap_free_friendlymap( map );
...</pre>
===== See Also  =====
 
ldap_friendly_name(), FriendlyMap()
 
==== ldap_free_searchprefs()  ====
 
The ldap_free_searchprefs() function disposes of the data structures allocated by ldap_init_searchprefs().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_free_searchprefs( struct ldap_searchobj *solist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_free_searchprefs() Function Parameter"
|+ ldap_free_searchprefs() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>solist</tt>
| Pointer to the data structures, typically obtained by calling ldap_init_searchprefs().
|}
 
===== See Also  =====
 
ldap_init_searchprefs(), ldap_init_searchprefs_buf()
 
==== ldap_free_sort_keylist()  ====
 
The ldap_free_sort_keylist() function frees the structures allocated by the ldap_create_sort_keylist() function.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_free_sort_keylist (LDAPsortkey **sortKeyList);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_free_sort_keylist() Function Parameter"
|+ ldap_free_sort_keylist() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>sortKeyList</tt>
| Array of LDAPsortkey structures that you want to free from memory.
|}
 
===== Description  =====
 
The ldap_free_sort_keylist() function frees the array of LDAPsortkey structures allocated by the ldap_create_sort_keylist() function. When done sorting results, call this function to free the memory that you have allocated. This function must be called after the ldap_create_sort_control() function has completed.
 
===== See Also  =====
 
ldap_create_sort_keylist(), ldap_create_sort_control()
 
==== ldap_free_templates()  ====
 
The ldap_free_templates() function disposes of the templates allocated by ldap_init_templates().
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
void ldap_free_templates( struct ldap_disptmpl *tmpllist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_free_templates() Function Parameter"
|+ ldap_free_templates() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Description  =====
 
ldap_free_templates() releases the templates allocated by ldap_init_templates(). Each template defined in the file is an <tt>ldap_disptmpl</tt> structure.
 
==== ldap_free_urldesc()  ====
 
The ldap_free_urldesc() function frees memory allocated by the ldap_url_parse() function.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_free_urldesc( LDAPURLDesc *ludp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_free_urldesc() Function Parameter"
|+ ldap_free_urldesc() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ludp</tt>
| Pointer to a LDAPURLDesc structure.
|}
 
===== Example  =====
 
The following example parses an LDAP URL and then frees the LDAPURLDesc structure from memory after verifying that the LDAP URL is valid.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
char *my_url =
"ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,telephoneNumber?
sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, &amp;ludpp ) )&nbsp;!= 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL does not contain a distinguished name\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "URL is a valid LDAP URL\n" );
ldap_free_urldesc( ludpp );
...</pre>
===== See Also  =====
 
ldap_url_parse()
 
==== ldap_friendly_name()  ====
 
The ldap_friendly_name() function maps a set of standard identifiers to their user-friendly counterparts. For example, you can represent the list of two-letter state codes (CA, IA) with their corresponding state names (California, Iowa), or map country ISO codes to the full country names. '''Note:''' <tt>ldapfriendly</tt>, located in <tt>lib/ldapcsdk/etc</tt>, is a sample file that maps two letter country codes to their full names. It can be used in context with ldap_friendly_name().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_friendly_name( char *filename, char *uname,
  FriendlyMap *map );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_friendly_name() function parameters"
|+ ldap_friendly_name() function parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>filename</tt>
| Name of the file mapping the standard identifiers to the user-friendly names.
|-
| <tt>uname</tt>
| Standard identifier name for which you want to find the user-friendly name.
|-
| <tt>map</tt>
| Pointer to the FriendlyMap() mapping in memory. Initialize this pointer to <tt>NULL</tt> on the first call, then use it during subsequent calls so that the mapping file does not need to be read again.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the user-friendly name for the specified identifier.
*If unsuccessful—for example, if the file cannot be read, if the file is in a bad format, or if the map parameter is set to <tt>NULL</tt>—returns the original identifier (the value passed as the <tt>uname</tt> parameter).
 
===== Description  =====
 
This function relies on the existence of a text file mapping standard identifiers to user-friendly names. The names in the file are tab-delimited. Unfriendly to Friendly Name Mapping File
<pre>&lt;unfriendly_name&gt;        &lt;friendly_name&gt;
AD        Andorra
AE        United Arab Emirates
AF        Afghanistan
AG        Antigua and Barbuda
AI        Anguilla</pre>
===== Example  =====
 
The following example reads in a map of user-friendly names and prints the name corresponding to the standard identifier <tt>IS</tt>.
<pre>#include &lt;ldap.h&gt;
#include &lt;stdio.h&gt;
...
FriendlyMap map = NULL;
char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly";
char *unfriendly_name = "IS";
char *friendly_name;
...
/* Read the ldapfriendly file into the map in memory */
friendly_name = ldap_friendly_name( map_file, unfriendly_name, &amp;map );
printf( "Friendly Name for&nbsp;%s:&nbsp;%s\n", unfriendly_name, friendly_name );
/* Since file is in memory, no need to reference it in subsequent calls */
friendly_name = ldap_friendly_name( NULL, "VI", &amp;map );
printf( "Friendly Name for VI:&nbsp;%s\n", friendly_name );
...</pre>
===== See Also  =====
 
ldap_free_friendlymap(), FriendlyMap()
 
==== ldap_get_dn()  ====
 
The ldap_get_dn() routine returns the DN for an entry in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_get_dn( LDAP *ld, LDAPMessage *entry );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_dn() Function Parameters"
|+ ldap_get_dn() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Pointer to an entry in a chain of search results, as returned by the ldap_first_entry() and ldap_next_entry() functions.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns the DN for the specified entry.
*If unsuccessful, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
You can get an entry from a chain of search results by calling the ldap_first_entry() and ldap_next_entry() functions.
 
===== Example  =====
 
The following example prints the DN for each entry found in a search.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
char *dn;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* For each matching entry found, print out the name of the entry.*/
for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
  e = ldap_next_entry( ld, e ) ) {
    if ( ( dn = ldap_get_dn( ld, e ) )&nbsp;!= NULL ) {
      printf( "dn:&nbsp;%s\n", dn );
      /* Free the memory used for the DN when done */
      ldap_memfree( dn );
    }
}
/* Free the result from memory when done. */
ldap_msgfree( result );
...</pre>
===== See Also  =====
 
ldap_first_entry(), ldap_next_entry(), ldap_get_lderrno()
 
==== ldap_get_entry_controls()  ====
 
The ldap_get_entry_controls() function gets the LDAP controls included with a directory entry in a set of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry,
  LDAPControl ***serverctrlsp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_entry_controls() Function Parameters"
|+ ldap_get_entry_controls() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Pointer to an LDAPMessage structure representing an entry in a chain of search results.
|-
| <tt>serverctrlsp</tt>
| Pointer to an array of LDAPControl structures, which represent the LDAP v3 server controls returned by the server.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
The ldap_get_entry_controls() function retrieves the LDAP v3 controls included in a directory entry in a chain of search results. The LDAP controls are specified in an array of LDAPControl structures with each structure representing one LDAP control. Other controls are returned with results sent from the server. You can call ldap_parse_result() to retrieve those controls.
 
==== ldap_getfilter_free()  ====
 
The ldap_getfilter_free() function frees the memory used by a filter set.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_getfilter_free( LDAPFiltDesc *lfdp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_getfilter_free() Function Parameter"
|+ ldap_getfilter_free() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lfdp</tt>
| Pointer to a LDAPFiltDesc structure.
|}
 
===== Description  =====
 
Once you call ldap_getfilter_free(), the LDAPFiltDesc structure is no longer valid and cannot be used again.
 
===== Example  =====
 
The following example frees the LDAPFiltDesc structure from memory after all searches are completed.
<pre>#include &lt;ldap.h&gt;
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
...
/* Read the filter configuration file into an LDAPFiltDesc structure */
lfdp = ldap_init_getfilter( filter_file );
...
/* Retrieve filters and perform searches */
...
/* Free the configuration file (the LDAPFiltDesc structure) */
ldap_getfilter_free( lfdp );
...</pre>
===== See Also  =====
 
ldap_init_getfilter(), ldap_init_getfilter_buf()
 
==== ldap_getfirstfilter()  ====
 
The ldap_getfirstfilter() function retrieves the first filter that is appropriate for a given value.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPFiltInfo * ldap_getfirstfilter( LDAPFiltDesc *lfdp,
  char *tagpat, char *value );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_getfirstfilter() Function Parameters"
|+ ldap_getfirstfilter() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lfdp</tt>
| Pointer to an LDAPFiltDesc structure.
|-
| <tt>tagpat</tt>
| Regular expression for a tag in the filter configuration.
|-
| <tt>value</tt>
| Value for which to find the first appropriate filter.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a pointer to an LDAPFiltInfo() structure.
*If no more filters can be returned, returns a <tt>NULL</tt>.
*If unsuccessful, returns a <tt>NULL</tt>.
 
===== Example  =====
 
The following example is based on the <tt>getfilt</tt> command-line program example provided with the Directory SDK For C. The program prompts the user to enter search criteria and, based on the criteria entered, it retrieves filters that match the criteria.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
LDAPFiltDesc *ldfp;
LDAPFiltInfo *ldfi;
char buf[ 80 ]; /* Contains the search criteria */
int found;
...
/* Load the filter configuration file into an LDAPFiltDesc structure */
if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) {
  perror( "Cannot open filter configuration file" );
  return( 1 );
}
 
/* Read a string to search for */
printf( "Enter a string to search for: " );
gets( buf );
if ( strlen( buf ) == 0 ) {
  fprintf( stderr, "usage:&nbsp;%s search-string\n", argv[ 0 ]);
  return( 1 );
}
 
/* Select a filter to use when searching for the value in buf */
found = 0;
for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf );
      ldfi&nbsp;!= NULL;
      ldfi = ldap_getnextfilter( ldfp ) ) {
 
  /* Use the selected filter to search the directory */
  if ( ldap_search_s( ld, "dc=example,dc=com, ldfi-&gt;lfi_scope,
  ldfi-&gt;lfi_filter, NULL, 0, result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  } else {
 
    /* Once a filter gets results back, stop iterating through
      the different filters */
    if ( ( found = ldap_count_entries( ld, result ) &gt; 0 ) ) {
      break;
    } else {
      ldap_msgfree( result );
    }
  }
}
 
if ( found == 0 ) {
  printf( "No matching entries found.\n" );
} else {
  printf( "Found&nbsp;%d&nbsp;%s match%s for \"%s\"\n\n", found,
  ldfi-&gt;lfi_desc, found == 1&nbsp;? ""&nbsp;: "es", buf );
}
 
ldap_msgfree( result );
ldap_getfilter_free( ldfp );
...</pre>
===== See Also  =====
 
ldap_init_getfilter(), ldap_init_getfilter_buf(), ldap_getnextfilter()
 
==== ldap_get_lang_values()  ====
<pre>#include &lt;ldap.h&gt;
char ** ldap_get_lang_values( LDAP *ld, LDAPMessage *entry,
  const char *target, char **type );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_lang_values() Function Parameters"
|+ ldap_get_lang_values() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Entry retrieved from the directory.
|-
| <tt>target</tt>
| Attribute type (including an optional language subtype) that you want to retrieve the values of.
|-
| <tt>type</tt>
| Pointer to a buffer that returns the attribute type retrieved by this function.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a <tt>NULL</tt> terminated array of the attribute’s values.
*If unsuccessful or if no such attribute exists in the entry, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
Unlike the ldap_get_values() function, if a language subtype is specified, this function first attempts to find and return values that match that subtype—for example, <tt>cn;lang-en</tt>. If you want to retrieve binary data from an attribute, call the ldap_get_lang_values_len() function.
 
===== See Also  =====
 
ldap_first_entry(), ldap_first_attribute(), ldap_get_lang_values_len() , ldap_get_values(), ldap_next_entry(), ldap_next_attribute()
 
==== ldap_get_lang_values_len()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Please use ldap_get_values_len().
 
The ldap_get_lang_values_len() function returns a <tt>NULL</tt> terminated array of pointers to berval structures, each containing the length and pointer to a binary value of an attribute for a given entry.
 
===== Syntax  =====
<pre>#include &lt;ldap-deprecated.h&gt;
struct berval ** ldap_get_lang_values_len( LDAP *ld,
  LDAPMessage *entry, const char *target, char **type );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_lang_values_len() Function Parameters"
|+ ldap_get_lang_values_len() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Result returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>target</tt>
| Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as <tt>jpegPhoto</tt> or <tt>audio</tt>.
|-
| <tt>type</tt>
| Pointer to a buffer that returns the attribute type retrieved by this function.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a <tt>NULL</tt> terminated array of pointers to berval structures, which, in turn, contain pointers to the attribute’s binary values.
*If unsuccessful or if no such attribute exists in the entry, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
Use the ldap_get_lang_values() routine if the attribute values are string values.
 
===== See Also  =====
 
ldap_first_attribute(), ldap_first_entry(), ldap_get_lang_values(), ldap_next_entry(), ldap_next_attribute()
 
==== ldap_get_lderrno()  ====
 
The ldap_get_lderrno() function gets information about the last error that occurred for an LDAP operation.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_get_lderrno( LDAP *ld, char **m, char **s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_lderrno() Function Parameters"
|+ ldap_get_lderrno() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>m</tt>
| In the event of an LDAP_NO_SUCH_OBJECT error return, this parameter contains the portion of the DN that identifies an existing entry.
|-
| <tt>s</tt>
| The text of the error message.
|}
 
===== Returns  =====
 
The LDAP error code for the last operation.
 
===== Description  =====
 
ldap_get_lderrno() gets information about the last error that occurred for an LDAP operation. You can also call this function to get error codes for functions that do not return errors, such as ldap_next_attribute().
 
===== Example  =====
 
The following example attempts to add a new user to the directory. If the entry identified by a DN does not exist, the server returns the portion of the DN that matches an existing entry; this is the variable matched.
 
<pre>#include &lt;ldap.h&gt;
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
LDAPMod **list_of_attrs;
char *matched;
int rc;
...
if ( ldap_add_s( ld, dn, list_of_attrs )&nbsp;!= LDAP_SUCCESS ) {
  rc = ldap_get_lderrno( ld, &amp;matched, NULL );
  return( rc );
}
...</pre>
 
If no organizational unit named <tt>People</tt> exists, the matched variable is set to <tt>dc=example,dc=com</tt> .
 
===== See Also  =====
 
ldap_err2string(), ldap_perror, ldap_result2error(), ldap_set_lderrno()
 
==== ldap_getnextfilter()  ====
 
The ldap_getnextfilter() function retrieves the next filter that is appropriate for a given value.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPFiltInfo * ldap_getnextfilter( LDAPFiltDesc *lfdp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_getnextfilter() Function Parameter"
|+ ldap_getnextfilter() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lfdp</tt>
| Pointer to an LDAPFiltDesc structure.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a pointer to an LDAPFiltInfo() structure.
*If no more filters can be returned, returns a <tt>NULL</tt>.
*If unsuccessful, returns a <tt>NULL</tt>.
 
===== Description  =====
 
Call this function to get subsequent filters after calling ldap_getfirstfilter().
 
===== Example  =====
 
See the following example.
 
===== See Also  =====
 
ldap_getfirstfilter()
 
==== ldap_get_option()  ====
 
The function ldap_get_option() retrieves session preferences from an LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_get_option( LDAP *ld, int option, void *optdata );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_option() Function Parameters"
|+ ldap_get_option() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>option</tt>
| Option that you want to retrieve. This parameter must be set to one of the option values.
|-
| <tt>optdata</tt>
| Pointer to the buffer in which the value of the option will be put.
|}
 
The following table describes the options that you can retrieve with ldap_get_option().
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Options for the ldap_get_options() Function"
|+ Options for the ldap_get_options() Function
|-
! scope="col" | Option
! scope="col" | Description
|-
| <tt>LDAP_OPT_API_FEATURE_INFO</tt>
| Retrieves information about the revision of a supported LDAP feature. This option is READ-ONLY and cannot be set. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPAPIFeatureInfo*)</tt>.
|-
| <tt>LDAP_OPT_API_INFO</tt>
| Retrieves information about the API implementation at execution time (API version, protocol version, the names of supported API extensions with their vendor name version, etc.). For details on the structure returned, refer to the <tt>ldap.h</tt> header file. This option is READ-ONLY and cannot be set. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPAPIInfo*)</tt>.
|-
| <tt>LDAP_OPT_CLIENT_CONTROLS</tt>
| Pointer to an array of LDAPControl structures representing the LDAP v3 client controls you want sent with every request by default. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPControl***)</tt>.
|-
| <tt>LDAP_OPT_DESC</tt>
| Socket descriptor underlying the main LDAP connection. The <tt>LBER_SOCKET</tt> data type depends on the platform that you are using:
*<tt>int</tt> in UNIX.
*<tt>SOCKET</tt> in Windows. The data type for the <tt>optdata</tt> parameter is <tt>(LBER_SOCKET*)</tt>.
 
|-
| <tt>LDAP_OPT_DEREF</tt>
| Determines how aliases work during a search. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_DEREF_NEVER</tt> specifies that aliases are never dereferenced.
*<tt>LDAP_DEREF_SEARCHING</tt> specifies that aliases are dereferenced when searching under the base object (but not when finding the base object).
*<tt>LDAP_DEREF_FINDING</tt> specifies that aliases are dereferenced when finding the base object (but not when searching under the base object).
*<tt>LDAP_DEREF_ALWAYS</tt> specifies that aliases are always dereferenced when finding and searching under the base object. The data type for the <tt>optdata</tt> parameter is <tt>(int*)</tt>.
 
|-
| <tt>LDAP_OPT_DNS_FN_PTRS</tt>
| DEPRECATED OPTION: Lets you use alternate DNS functions for getting the host entry of the LDAP server. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_dns_fns *)</tt>.
|-
| <tt>LDAP_OPT_ERROR_NUMBER</tt>
| Retrieves the result code for the most recent LDAP error that occurred in this session. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_ERROR_STRING</tt>
| Retrieves the error message returned with the result code for the most recent LDAP error that occurred in this session. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>.
|-
| <tt>LDAP_OPT_EXTRA_THREAD_FN_PTRS</tt>
| Lets you specify the locking and semaphore functions that you want called when getting results from the server. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_extra_thread_fns *)</tt>.
|-
| <tt>LDAP_OPT_HOST_NAME</tt>
| Sets the host name (or list of hosts) for the primary LDAP server. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>.
|-
| <tt>LDAP_OPT_IO_FN_PTRS</tt>
| DEPRECATED OPTION: Lets you use alternate communication stacks. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_io_fns *)</tt>.
|-
| <tt>LDAP_OPT_MATCHED_DN</tt>
| Gets the matched DN value returned with the most recent LDAP error that occurred for this session. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>
|-
| <tt>LDAP_OPT_MEMALLOC_FN_PTRS</tt>
| Gets a pointer to the callback structure which you previously set. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_memalloc_fnsldap_io_fns *)</tt>.
|-
| <tt>LDAP_OPT_PROTOCOL_VERSION</tt>
| Version of the protocol supported by your client. You can specify either <tt>LDAP_VERSION2</tt> or <tt>LDAP_VERSION3.</tt> If no version is set, the default is <tt>LDAP_VERSION2</tt>. In order to use LDAP v3 features, you need to set the protocol version to <tt>LDAP_VERSION3</tt>. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_REBIND_ARG</tt>
| Lets you set the last argument passed to the routine specified by <tt>LDAP_OPT_REBIND_FN</tt>. You can also set this option by calling the ldap_set_rebind_proc() function. The data type for the <tt>optdata</tt> parameter is <tt>(void *)</tt>.
|-
| <tt>LDAP_OPT_REBIND_FN</tt>
| Lets you set the routine to be called when you need to authenticate a connection with another LDAP server (for example, during the course of following a referral). You can also set this option by calling the ldap_set_rebind_proc function. The data type for the <tt>optdata</tt> parameter is <tt>(LDAP_REBINDPROC_CALLBACK *)</tt>.
|-
| <tt>LDAP_OPT_RECONNECT</tt>
| If the connection to the server is lost, determines whether or not the same connection handle should be used to reconnect to the server. By default, this option is off. You handle failover with the following values:
*<tt>LDAP_OPT_ON</tt> specifies that the same connection handle can be used to reconnect to the server.
*<tt>LDAP_OPT_OFF</tt> specifies that you want to create a new connection handle to connect to the server. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_REFERRALS</tt>
| Determines whether or not the client should follow referrals. By default, the client follows referrals. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that the server should follow referrals.
*<tt>LDAP_OPT_OFF</tt> specifies that the server should not follow referrals. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_REFERRAL_HOP_LIMIT</tt>
| Maximum number of referrals the client should follow in a sequence. In other words, the client can only be referred this number of times before it gives up. By default, the maximum number of referrals that the client can follow in a sequence is 5 for the initial connection. This limit does not apply to individual requests that generate multiple referrals in parallel. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_RESTART</tt>
| Determines whether or not LDAP I/O operations should be restarted automatically if they are prematurely aborted. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that I/O operations should be restarted automatically.
*<tt>LDAP_OPT_OFF</tt> specifies that I/O operations should not be restarted automatically. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_SERVER_CONTROLS</tt>
| Pointer to an array of LDAPControl structures representing the LDAP v3 server controls you want sent with every request by default. Typically, since controls are specific to the type of request, you may want to pass the controls using operation-specific functions, such as ldap_add_ext(), instead. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPControl ***)</tt>.
|-
| <tt>LDAP_OPT_SIZELIMIT</tt>
| Maximum number of entries that should be returned by the server in search results. The LDAP server may impose a smaller size limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_SSL</tt>
| Determines whether or not SSL is enabled. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that SSL is enabled.
*<tt>LDAP_OPT_OFF</tt> specifies that SSL is disabled. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_THREAD_FN_PTRS</tt>
| Lets you specify the thread function pointers. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_thread_fns *)</tt>.
|-
| <tt>LDAP_OPT_TIMELIMIT</tt>
| Maximum number of seconds that should be spent by the server when answering a search request. The LDAP server may impose a shorter time limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_X_OPT_EXTIO_FN_PTRS</tt>
| Extended I/O function callback option.
|-
| <tt>LDAP_X_OPT_CONNECT_TIMEOUT</tt>
| Value of a time out (expressed in milliseconds) for non-blocking connect call. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_X_OPT_SOCKBUF</tt>
| Socket buffer structure associated to the LDAP connection.
|}
 
See also ldap_get_option() for details on <tt>LDAP_OPT_X_SASL*</tt> parameters.
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Examples  =====
 
The following example gets the session preference for the maximum number of entries to be returned from search operations.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
int max_ret;
...
/* Get the maximum number of entries returned */
if (ldap_get_option, LDAP_OPT_SIZELIMIT, &amp;max_ret)&nbsp;!= LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_get_option" );
  return( 1 );
}</pre>
This example could also include the following two small sections of code that show how to use the <tt>LDAP_OPT_API_FEATURE_INFO</tt> and the <tt>LDAP_OPT_API_INFO</tt> options, respectively.
<pre>LDAPIIFeatureInfo ldfi;
ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW";
if (ldap_get_option(NULL, LDAP_OPT_API_FEATURE_INFO, &amp;ldfi)==0) {
  /* use the info here */ }
LDAPIInfo ldai;
ldai.ldapiai_info_version = LDAP_API_INFO_VERSION;
if (ldap_get_option( NULL, LDAP_OPT_API_INFO, &amp;ldia ) == 0) {
  /* use the ldai info here */
}</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldap_set_option()
 
==== ldap_get_values()  ====
 
The ldap_get_values() function returns a <tt>NULL</tt> terminated array of an attribute’s string values for a given entry.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char ** ldap_get_values( LDAP *ld, LDAPMessage *entry,
  const char *target );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_values() Function Parameters"
|+ ldap_get_values() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Result returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>target</tt>
| Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as <tt>jpegPhoto</tt> or <tt>audio</tt>.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a <tt>NULL</tt> terminated array of the attribute’s values.
*If unsuccessful or if no such attribute exists in the entry, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
Use the ldap_get_values_len() function if the attribute values are binary.
 
===== Example  =====
 
The following example gets and prints the values of an attribute in an entry. This example assumes that all attributes have string values.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
char **vals;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
int i;
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
/* Get the first matching attribute */
a = ldap_first_attribute( ld, e, &amp;ber );
/* Get the values of the attribute */
if ( ( vals = ldap_get_values( ld, e, a ) )&nbsp;!= NULL ) {
  for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
    /* Print the name of the attribute and each value */
    printf( "%s:&nbsp;%s\n", a, vals[i] );
  }
  /* Free the attribute values from memory when done. */
  ldap_value_free( vals );
}
...</pre>
===== See Also  =====
 
ldap_first_entry(), ldap_first_attribute(), ldap_get_values_len(), ldap_next_entry(), ldap_next_attribute()
 
==== ldap_get_values_len()  ====
 
The ldap_get_values_len() function returns a <tt>NULL</tt> terminated array of pointers to berval structures, each containing the length and pointer to a binary value of an attribute for a given entry.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
struct berval ** ldap_get_values_len( LDAP *ld,
LDAPMessage *entry, const char *target );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_get_values_len() Function Parameters"
|+ ldap_get_values_len() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Result returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>target</tt>
| Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as <tt>jpegPhoto</tt> or <tt>audio</tt>.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a <tt>NULL</tt> terminated array of pointers to berval structures, which in turn contains pointers to the attribute’s binary values.
*If unsuccessful or if no such attribute exists in the entry, returns <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
Use the ldap_get_values() routine if the attribute values are string values.
 
===== Example  =====
 
The following example gets the first value of the <tt>jpegPhoto</tt> attribute and saves the JPEG data to a file.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
struct berval photo_data;
struct berval **list_of_photos;
FILE *out;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, NULL,
  0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
/* Get the value of the jpegPhoto attribute */
if ( ( list_of_photos = ldap_get_values_len( ld, e, "jpegPhoto" ) )&nbsp;!=
  NULL ) {
    /* Prepare to write the JPEG data to a file */
    if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) {
      perror( "fopen" );
      return( 1 );
    }
  /* Get the first JPEG */
  photo_data = *list_of_photos[0];
  /* Write the JPEG data to a file */
  fwrite( photo_data.bv_val, photo_data.bv_len, 1, out );
  fclose( out );
  /* Free the attribute values from memory when done. */
  ldap_value_free_len( list_of_photos );
}
...</pre>
===== See Also  =====
 
ldap_first_entry(), ldap_first_attribute(), ldap_get_values(), ldap_next_entry(), ldap_next_attribute()
 
==== ldap_init()  ====
 
The ldap_init() function initializes a session with an LDAP server and returns an LDAP structure that represents the context of the connection to that server.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP * ldap_init( const char *defhost, int defport );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init() Function Parameters"
|+ ldap_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>defhost</tt>
| Space-delimited list of one or more host names (or IP address in dotted notation, such as "141.211.83.36") of the LDAP servers that you want the LDAP client to connect to. The names can be in ''hostname'':''portnumber'' format (in which case, ''portnumber'' overrides the port number specified by the <tt>defport</tt> argument.
|-
| <tt>defport</tt>
| Default port number of the LDAP server. To specify the standard LDAP port (port 389), use <tt>LDAP_PORT</tt> as the value for this parameter.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a pointer to an LDAP() structure.
*If unsuccessful, returns a <tt>NULL</tt>.
 
===== Description  =====
 
The ldap_init() function initializes a session with an LDAP server by allocating an LDAP structure containing information about the session including the host name and port of the LDAP server, preferences for the session (such as the maximum number of entries to return in a search), and the error code of the last LDAP operation performed. The LDAP structure defaults to LDAP v2. It is highly recommended to set it to LDAP v3 using the ldap_set_option().
<pre>...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com ld3.example.com",
  LDAP_PORT );</pre>
If any of the servers do not use the default port specified by the <tt>defport</tt> argument, use the ''hostname'':''portnumber'' format to specify the server name. In the following example <tt>ld1.example.com</tt>, port <tt>389</tt>. If that server does not respond, the client will attempt to connect to the LDAP server on <tt>ld2.example.com</tt>, port <tt>1389</tt>.
<pre>...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com:1389", LDAP_PORT );</pre>
'''Note:''' If you are connecting to a secure LDAP server over SSL, you should be calling the ldapssl_init() function.
 
===== Example  =====
 
The following example initializes a session with the LDAP server at <tt>ldap.example.com:389</tt>, and sets a session preference that identifies the client as an LDAP v3 client.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
/* Specify the host name of the LDAP server. */
char *ldap_host = "ldap.example.com";
/* Because the LDAP server is running on the standard LDAP port (port 389),
* you can use LDAP_PORT to identify the port number. */
int ldap_port = LDAP_PORT;
...
/* Initialize the session with ldap.example.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( ldap_host, ldap_port ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Specify the LDAP version supported by the client. */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &amp;version );
...
/* Subsequent calls that authenticate to the LDAP server. */
...</pre>
===== See Also  =====
 
prldap_init() (IPv6), ldap_unbind(), ldap_unbind_s() , ldap_simple_bind(), ldap_simple_bind_s()
 
==== ldap_init_getfilter()  ====
 
The ldap_init_getfilter() function reads a valid LDAP filter configuration file (such as <tt>ldapfilter.conf</tt>) and returns a pointer to an LDAPFiltDesc structure.
<pre>#include &lt;ldap.h&gt;
LDAPFiltDesc * ldap_init_getfilter( char *fname );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_getfilter() Function Parameter"
|+ ldap_init_getfilter() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>fname</tt>
| Name of the LDAP filter configuration file to use.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a pointer to an LDAPFiltDesc() structure.
*If unsuccessful (for example, if there is an error reading
 
the file), returns a <tt>NULL</tt>.
 
===== Example  =====
 
The following example loads a filter configuration file named <tt>myfilters.conf</tt> into memory.
<pre>#include &lt;ldap.h&gt;
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
...
lfdp = ldap_init_getfilter( filter_file );
...</pre>
===== See Also  =====
 
ldap_init_getfilter_buf(), ldap_getfilter_free()
 
==== ldap_init_getfilter_buf()  ====
 
The ldap_init_getfilter_buf() function reads LDAP filter configuration information from a buffer and returns a pointer to an LDAPFiltDesc structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPFiltDesc * ldap_init_getfilter_buf(char *buf, long buflen );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_getfilter_buf() Function Parameters"
|+ ldap_init_getfilter_buf() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>buf</tt>
| Buffer containing LDAP filter configuration information.
|-
| <tt>buflen</tt>
| Size of the buffer
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns a pointer to an LDAPFiltDesc() structure.
*If unsuccessful—for example, if there is an error reading the file—returns a <tt>NULL</tt>.
 
===== Example  =====
 
The following example copies the following filter configuration to a buffer in memory and uses this buffer to fill an LDAPFiltDesc structure.
<pre>"ldap-example"
"@"      " "    "(mail=%v)"            "email address"
"(mail=%v*)"            "start of email address"</pre>
Using ldap_init_getfilter()
<pre>#include &lt;string.h&gt;
#include &lt;ldap.h&gt;
...
LDAPFiltDesc *lfdp;
char filtbuf[ 1024 ];
...
/* Create the filter config buffer */
strcpy( filtbuf, "\"ldap-example\"\n" );
strcat( filtbuf, " \"@\"\t\" \"\t\"(mail=%v)\"\t\"email address\"\n" );
strcat( filtbuf, " \t\t\"(mail=%v*)\"\t\"start of email address\"\n" );
lfdp = ldap_init_getfilter( filtbuf, strlen( filtbuf ) );
...</pre>
===== See Also  =====
 
ldap_init_getfilter(), ldap_getfilter_free()
 
==== ldap_init_searchprefs()  ====
 
The ldap_init_searchprefs() function reads a sequence of search preference configurations from a valid LDAP <tt>searchpref</tt> configuration file.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_searchprefs() Function Parameters"
|+ ldap_init_searchprefs() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>file</tt>
| Pointer to a valid LDAP <tt>searchpref</tt> configuration file.
|-
| <tt>solistp</tt>
| Pointer to a list of search preference data structures.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>LDAP_SEARCHPREF_ERR_VERSION</tt>.
*<tt>LDAP_SEARCHPREF_ERR_MEM</tt> if there is a memory allocation problem.
*Upon success, <tt>0</tt> is returned and <tt>solistp</tt> is set to point to a list of search preference data structures.
 
===== Description  =====
 
ldap_init_searchprefs() provides a standard way to access LDAP search preference configuration data.
 
'''Note:''' LDAP search preference configurations are typically used by LDAP client programs to specify which attributes a user may search by, labels for the attributes, and LDAP filters and scopes associated with those searches. Client software presents these choices to a user, who can then specify the type of search to be performed.
 
===== See Also  =====
 
ldap_free_searchprefs(), ldap_init_searchprefs_buf()
 
==== ldap_init_searchprefs_buf()  ====
 
The ldap_init_searchprefs_buf() function reads a sequence of search preference configurations from the parameter, <tt>buf</tt>.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_init_searchprefs_buf( char *buf, long buflen,
  struct ldap_searchobj **solistp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_searchprefs_buf() Function Parameters"
|+ ldap_init_searchprefs_buf() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>buf</tt>
| Pointer to data in the format defined for an LDAP search preference configuration file.
|-
| <tt>buflen</tt>
| The size of <tt>buf</tt>.
|-
| <tt>solistp</tt>
| Pointer to a list of search preference data structures.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>LDAP_SEARCHPREF_ERR_VERSION</tt> if <tt>buf</tt> points to data that is newer than can be handled.
*<tt>LDAP_SEARCHPREF_ERR_MEM</tt> if there is a memory allocation problem.
*Upon success, <tt>0</tt> is returned and <tt>solistp</tt> is set to point to a list of search preference data structures.
 
===== Description  =====
 
ldap_init_searchprefs_buf() reads a sequence of search preference configurations from <tt>buf</tt>. See also ldap_init_searchprefs(), ldap_free_searchprefs()
 
==== ldap_init_templates()  ====
 
The ldap_init_templates() function reads a sequence of templates from a valid LDAP template configuration file.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_templates() Function Parameters"
|+ ldap_init_templates() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>file</tt>
| Pointer to a valid LDAP template configuration file.
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Returns  =====
 
*If successful, <tt>0</tt> is returned and <tt>tmpllistp</tt> is configured.
*Upon error:
**<tt>LDAP_TMPL_ERR_VERSION</tt> if <tt>buf</tt> points to data that is newer than can be handled.
**<tt>LDAP_TMPL_ERR_MEM</tt> if there is a memory allocation problem.
**<tt>LDAP_TMPL_ERR_SYNTAX</tt> if there is a problem with the format of the templates buffer or file.
**<tt>LDAP_TMPL_ERR_FILE</tt> if the file cannot be read.
 
===== Description  =====
 
ldap_init_templates() reads a sequence of templates from a valid LDAP template configuration file. Each template defined in the file is an <tt>ldap_disptmpl</tt> structure.
 
===== See Also  =====
 
ldap_init_templates_buf(), ldap_free_templates()
 
==== ldap_init_templates_buf()  ====
 
The ldap_init_templates_buf() function reads a sequence of templates from a buffer.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_init_templates_buf( char *buf, long buflen,
  struct ldap_disptmpl **tmpllistp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_init_templates_buf() Function Parameters"
|+ ldap_init_templates_buf() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>buf</tt>
| Pointer to data in the format defined for a valid LDAP template configuration file.
|-
| <tt>buflen</tt>
| The size of <tt>buf</tt>.
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Returns  =====
 
If successful, <tt>0</tt> is returned and <tt>tmpllistp</tt> is configured. Upon error:
*<tt>LDAP_TMPL_ERR_VERSION</tt> if <tt>buf</tt> points to data that is newer than can be handled.
*<tt>LDAP_TMPL_ERR_MEM</tt> if there is a memory allocation problem.
*<tt>LDAP_TMPL_ERR_SYNTAX</tt> if there is a problem with the format of the templates buffer or file.
*<tt>LDAP_TMPL_ERR_FILE</tt> if the file cannot be read.
 
===== Description  =====
 
The ldap_init_templates_buf() function reads a sequence of templates from a buffer.
 
===== See Also  =====
 
ldap_init_templates(), ldap_free_templates()
 
==== ldap_is_dns_dn()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
The ldap_is_dns_dn() function determines whether a DN string is of the experimental DNS-style DN (generally in the form of an RFC 822 email address) or the RFC 1779 formatted DN.
 
===== Description  =====
 
This function is specific to LDAP v2 and should not be used when dealing with LDAP v3 servers or data.
 
The ldap_is_ldap_url() function determines whether or not a URL is an LDAP URL.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_is_ldap_url( const char *url );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_is_ldap_url() Function Parameter"
|+ ldap_is_ldap_url() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>url</tt>
| The URL that you want to check.
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>1</tt> if the URL is an LDAP URL.
*<tt>0</tt> if the URL is not an LDAP URL.
 
===== Description  =====
 
The ldap_is_ldap_url() function determines whether or not a URL is an LDAP URL. An LDAP URL is a URL with the protocol set to <tt>ldap://</tt> (or <tt>ldaps://</tt>, if the server is communicating over a SSL connection).
 
===== Example  =====
 
The following example determines if a URL is a LDAP URL.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
char *my_url = "ldap://ldap.sun.com/dc=example,dc=com";
...
if ( ldap_is_ldap_url( my_url )&nbsp;!= 0 ) {
  printf( "%s is an LDAP URL.\n", my_url );
} else {
  printf( "%s is not an LDAP URL.\n", my_url );
}
...</pre>
===== See Also  =====
 
ldap_url_parse()
 
==== ldap_keysort_entries()  ====
 
The ldap_keysort_entries() function is used for sorting entries.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
int ldap_keysort_entries( LDAP *ld, LDAPMessage **chain,
  void *arg, LDAP_KEYGEN_CALLBACK *gen, LDAP_KEYCMP_CALLBACK *cmp,
  LDAP_KEYFREE_CALLBACK *fre );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_keysort_entries() Function Parameter"
|+ ldap_keysort_entries() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>chain</tt>
| Chain of entries returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>arg</tt>
| Pointer to an additional argument that you want to pass.
|-
| <tt>gen</tt>
| Callback used to generate the key(s) for sorting once the compare function has been applied.
|-
| <tt>cmp</tt>
| Comparison function used when sorting the values.
|-
| <tt>fre</tt>
| Callback used to free the key once the compare function has been applied.
|}
 
===== See Also  =====
 
LDAP_KEYGEN_CALLBACK(), LDAP_KEYCMP_CALLBACK(), LDAP_KEYFREE_CALLBACK()
 
==== ldap_memcache_destroy()  ====
 
The ldap_memcache_destroy() function frees an LDAPMemCache structure from memory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_memcache_destroy( LDAPMemCache *cache );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_destroy() Function Parameter"
|+ ldap_memcache_destroy() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>cache</tt>
| Pointer to the LDAPMemCache structure that you want freed from memory.
|}
 
===== Description  =====
 
The ldap_memcache_destroy() function frees the specified LDAPMemCache structure from memory. Call this function after you are done working with a cache.
 
===== See Also  =====
 
ldap_memcache_init()
 
==== ldap_memcache_flush()  ====
 
The ldap_memcache_flush() function flushes items from the specified cache.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_memcache_flush( LDAPMemCache *cache, char *dn,
  int scope );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_flush() Function Parameters"
|+ ldap_memcache_flush() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>cache</tt>
| Pointer to the LDAPMemCache structure that you want to flush entries from.
|-
| <tt>dn</tt>
| Base DN identifying the search requests that you want flushed from the cache. If the base DN of a search request is within the scope specified by this DN and the scope argument, the search request is flushed from the cache. If this argument is NULL, the entire cache is flushed.
|-
| <tt>scope</tt>
| Scope that (together with the <tt>dn</tt> argument) identifies the search requests that you want flushed from the cache. If the base DN of the request is within the scope specified by this argument and the <tt>dn</tt> argument, the request is flushed from the cache. This argument can have one of the following values: *<tt>LDAP_SCOPE_BASE</tt> *<tt>LDAP_SCOPE_ONELEVEL</tt> *<tt>LDAP_SCOPE_SUBTREE</tt>
|}
 
===== Description  =====
 
The ldap_memcache_flush() function flushes search requests from the cache. If the base DN of a search request is within the scope specified by the <tt>dn</tt> and scope arguments, the search request is flushed from the cache. If no DN is specified, the entire cache is flushed.
 
==== ldap_memcache_get()  ====
 
The ldap_memcache_get() function gets the in-memory cache associated with an LDAP connection handle.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_memcache_get( LDAP *ld, LDAPMemCache **cachep );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_get() Function Parameters"
|+ ldap_memcache_get() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>cachep</tt>
| When you call ldap_memcache_get(), it sets this parameter to the pointer to the LDAPMemCache structure associated with the connection handle.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
 
===== Description  =====
 
The ldap_memcache_get() function gets the cache associated with the specified connection handle (LDAP structure). This cache is used by all search requests made through that connection. You can call this function if you want to associate a cache with multiple LDAP connection handles. For example, you can call this function to get the cache associated with one connection, then you can call the ldap_memcache_set() function to associate the cache with another connection.
 
===== See Also  =====
 
ldap_memcache_set()
 
==== ldap_memcache_init()  ====
 
The ldap_memcache_init() function creates an in-memory cache for your LDAP client that you can associate with an LDAP connection.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_memcache_init( unsigned long ttl, unsigned long size,
  char **baseDNs, struct ldap_thread_fns *thread_fns,
  LDAPMemCache **cachep );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_init() Function Parameters"
|+ ldap_memcache_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ttl</tt>
| The maximum amount of time (in seconds) that an item can be cached. If <tt>0</tt>, there is no limit to the amount of time that an item can be cached.
|-
| <tt>size</tt>
| Maximum amount of memory (in bytes) that the cache will consume. If <tt>0</tt>, the cache has no size limit.
|-
| <tt>baseDNs</tt>
| An array of the base DN strings representing the base DNs of the search requests you want cached. If not <tt>NULL</tt>, only the search requests with the specified base DNs will be cached. If <tt>NULL</tt>, all search requests are cached.
|-
| <tt>thread_fns</tt>
| An ldap_thread_fns structure specifying the functions that you want used to ensure that the cache is thread-safe. You should specify this if you have multiple threads that are using the same connection handle and cache. If you are not using multiple threads, pass <tt>NULL</tt> for this parameter.
|-
| <tt>cachep</tt>
| When you call this function, it sets this parameter to the pointer to the newly created LDAPMemCache structure.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SIZELIMIT_EXCEEDED if the initial size of the cache (specified by the size argument) is too small.
 
===== Description  =====
 
The ldap_memcache_init() function creates an in-memory, client-side cache that you can use to cache search requests. The function passes back a pointer to an LDAPMemCache structure, which represents the cache. You should call the ldap_memcache_set() function to associate this cache with an LDAP connection handle (an LDAP structure). The cache uses search criteria as the key to cached items. When you send a search request, the cache checks the search criteria to determine if that request has been cached previously. If the request was cached, the search results are read from the cache. To flush the cache, call the ldap_memcache_flush() function. When you are done with the cache, you can free it from memory by calling the ldap_memcache_destroy() function.
 
'''Note:''' On Windows systems, if the ldap_memcache_init() function returns an LDAP_PARAM_ERROR result code, verify that your client is using the version of the <tt>nsldap32v30.dll</tt> file provided with the Directory SDK For C.
 
===== See Also  =====
 
LDAPMemCache(), ldap_memcache_set() , ldap_memcache_flush(), ldap_memcache_destroy(), ldap_memcache_update()
 
==== ldap_memcache_set()  ====
 
The ldap_memcache_set() function associates an in-memory cache with an LDAP connection handle.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_memcache_set( LDAP *ld, LDAPMemCache *cache );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_set() Function Parameters"
|+ ldap_memcache_set() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>cache</tt>
| Pointer to an LDAPMemCache structure, which represents the cache that you want used for this connection.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_SIZELIMIT_EXCEEDED if the initial size of the cache (specified by the size argument) is too small.
 
===== Description  =====
 
The ldap_memcache_set() function associates a cache (created by calling ldap_memcache_init()) with an LDAP connection handle. You can call this function if you want to associate a cache with multiple LDAP connection handles. For example, you can call the ldap_memcache_get() function to get the cache associated with one connection, then you can call ldap_memcache_set() to associate the cache with another connection. After you call this function, search requests made over the specified LDAP connection will use this cache. Calling the ldap_unbind() function will disassociate the cache from the LDAP connection handle.
 
===== See Also  =====
 
ldap_memcache_init(), ldap_memcache_get()
 
==== ldap_memcache_update()  ====
 
The ldap_memcache_update() function checks the cache for items that have expired and removes them.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_memcache_update( LDAPMemCache *cache );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memcache_update() Function Parameter"
|+ ldap_memcache_update() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>cache</tt>
| Pointer to an LDAPMemCache structure, which represents the cache that you want to updated.
|}
 
===== Description  =====
 
The ldap_memcache_update() function checks the cache for items that have expired and removes them. This check is typically done as part of the way the cache normally works. You do not need to call this function unless you want to update the cache at this point in time.
 
'''Note:''' This function is only useful in a multithreaded application, since it will not return until the cache is destroyed.
 
===== See Also  =====
 
ldap_memcache_flush()
 
==== ldap_memfree()  ====
 
The ldap_memfree() function frees memory allocated by an LDAP API function call.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_memfree( void *p );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_memfree() Function Parameter"
|+ ldap_memfree() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>p</tt>
| Pointer to memory used by the LDAP library.
|}
 
===== Example  =====
 
the following example frees the memory allocated by the ldap_get_dn() function. Using ldap_memfree()
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
char *dn;
LDAPMessage *entry;
...
/* Get the distinguished name (DN) for an entry */
dn = ldap_get_dn( ld, entry );
...
/* When you are finished working with the DN, free the memory allocated. */
ldap_memfree( dn );
...</pre>
===== See Also  =====
 
ldap_free_friendlymap(), ldap_free_urldesc(), ldap_msgfree(), ldap_value_free(), ldap_value_free_len()
 
==== ldap_modify()  ====
 
The ldap_modify() function modifies an existing entry in the directory asynchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modify() Function Parameters"
|+ ldap_modify() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>mods</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_modify() operation. To check the result of this operation, call ldap_result() and ldap_result2error(). For a list of possible result codes for an LDAP modify operation, see ldap_modify_ext_s().
 
===== Description  =====
 
Please use the newer version of this function, ldap_modify_ext() .
 
===== Example  =====
 
The following example uses the asynchronous ldap_modify() function to modify the entry for ''Barbara Jensen'' in the directory. It makes the following changes to the entry:
 
*Adds the <tt>homePhone</tt> attribute.
*Changes the <tt>telephoneNumber</tt> attribute.
*Removes the <tt>facsimileTelephoneNumber</tt> attribute.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to modify. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Values to add or change */
char *homePhone_values[] = { "555-1212", NULL };
char *telephoneNumber_values[] = { "869-5309", NULL };
...
/* Specify each change in separate LDAPMod structures */
attribute1.mod_type = "homePhone";
attribute1.mod_op = LDAP_MOD_ADD;
attribute1.mod_values = homePhone_values;
attribute2.mod_type = "telephoneNumber";
attribute2.mod_op = LDAP_MOD_REPLACE;
attribute2.mod_values = telephoneNumber_values;
attribute3.mod_type = "facsimileTelephoneNumber";
attribute3.mod_op = LDAP_MOD_DELETE;
attribute3.mod_values = NULL;
/* NOTE: When removing entire attributes, you need to specify a NULL value
* for the mod_values field. */
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &amp;attribute1;
list_of_attrs[1] = &amp;attribute2;
list_of_attrs[2] = &amp;attribute3;
list_of_attrs[3] = NULL;
...
/* Set up the timeout period to wait for the "modify" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Change the entry */
if ( ( msgid = ldap_modify( ld, dn, list_of_attrs ) ) == -1 ) {
  ldap_perror( ld, "ldap_modify" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &amp;tv, &amp;result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_modify" );
...</pre>
===== See Also  =====
 
ldap_modify_ext()
 
==== ldap_modify_ext()  ====
 
The ldap_modify_ext() function modifies an existing entry in the directory asynchronously. '''Note:''' ldap_modify_ext() is a new version of the ldap_modify() function. If you are writing a new LDAP client, use ldap_modify_ext().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modify_ext() Function Parameters"
|+ ldap_modify_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>mods</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call ldap_result() and ldap_parse_result().
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== Description  =====
 
The ldap_modify_ext() modifies an entry in the directory asynchronous; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_modify_ext_s() instead. In order to get the results of this LDAP modify operation, you need to call the ldap_result() and the ldap_parse_result() functions. To make changes to an entry to the directory, you need to specify the following information:
 
*A unique DN identifying the new entry
 
Use the <tt>dn</tt> argument to specify the DN of the entry you want to modify.
 
*A set of attributes for the new entry
 
Create an LDAPMod structure for changes that you want to make to an attribute. Create an array of these LDAPMod structures and pass the array as the <tt>mods</tt> argument.
 
===== See Also  =====
 
ldap_modify_ext_s(), ldap_result(), ldap_parse_result(), LDAPMod()
 
==== ldap_modify_ext_s()  ====
 
The ldap_modify_ext_s() modifies an existing entry in the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modify_ext_s() Function Parameters"
|+ ldap_modify_ext_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>mods</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_modify_ext_s() modifies an entry in the directory. ldap_modify_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_modify_ext() instead. To make changes to an entry to the directory, you need to specify the following information:
 
*A unique DN identifying the new entry
 
Use the <tt>dn</tt> argument to specify the DN of the entry that you want to modify.
 
*A set of attributes for the new entry
 
Create an LDAPMod structure for change that you want to make to an attribute. Create an array of these LDAPMod structures and pass the array as the <tt>mods</tt> argument.
 
===== See Also  =====
 
ldap_modify_ext(), LDAPMod
 
==== ldap_modify_s()  ====
 
The ldap_modify_s() function modifies an existing entry in the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modify_s() Function Parameters"
|+ ldap_modify_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>mods</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
|}
 
===== Returns  =====
 
For a list of possible result codes for an LDAP modify operation, see ldap_modify_ext_s().
 
===== Description  =====
 
Use the newer version of this function, ldap_modify_ext_s() .
 
===== Example  =====
 
The following example uses the synchronous ldap_modify_s() function to makes the following changes to the <tt>Barbara Jensen</tt> entry:
 
*Adds the <tt>homePhone</tt> attribute.
*Changes the <tt>telephoneNumber</tt> attribute.
*Removes the <tt>facsimileTelephoneNumber</tt> attribute.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPControl **srvrctrls, **clntctrls;
/* Distinguished name of the entry that you want to modify. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Values to add or change */
char *homePhone_values[] = { "555-1212", NULL };
char *telephoneNumber_values[] = { "869-5309", NULL };
...
/* Specify each change in separate LDAPMod structures */
attribute1.mod_type = "homePhone";
attribute1.mod_op = LDAP_MOD_ADD;
attribute1.mod_values = homePhone_values;
attribute2.mod_type = "telephoneNumber";
attribute2.mod_op = LDAP_MOD_REPLACE;
attribute2.mod_values = telephoneNumber_values;
attribute3.mod_type = "facsimileTelephoneNumber";
attribute3.mod_op = LDAP_MOD_DELETE;
attribute3.mod_values = NULL;
/* NOTE: When removing entire attributes, you need to specify a NULL value
* for the mod_values or mod_bvalues field. */
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &amp;attribute1;
list_of_attrs[1] = &amp;attribute2;
list_of_attrs[2] = &amp;attribute3;
list_of_attrs[3] = NULL;
...
/* Change the entry */
if ( ldap_modify_s( ld, dn, list_of_attrs )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modify_s" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_modify_ext_s()
 
==== ldap_modrdn()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Use ldap_rename() instead.
 
===== ldap_modrdn_s()  =====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Use ldap_rename() instead.
 
The ldap_modrdn2() function changes the relative distinguished name (RDN) of an entry in the directory asynchronously.
 
===== Syntax  =====
<pre>#include &lt;ldap-deprecated.h&gt;
int ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn,
  int deleteoldrdn );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modrdn2() Function Parameters"
|+ ldap_modrdn2() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>newrdn</tt>
| New RDN to assign to the entry.
|-
| <tt>deleteoldrdn</tt>
| If this is a non-zero value, the old RDN is not retained as a value in the modified entry. If <tt>0</tt>, the old RDN is retained as an attribute in the modified entry.
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_modrdn2() operation. To check the result of this operation, call ldap_result() and ldap_result2error(). For a list of possible result codes, see ldap_rename().
 
===== Description  =====
 
Please use the newer version of this function, ldap_rename() .
 
===== Example  =====
 
The following example uses the asynchronous ldap_modrdn2() function to change the RDN of an entry from <tt>uid=bjensen</tt> to <tt>uid=babs</tt>. The code removes the existing RDN <tt>bjensen</tt> from the <tt>uid</tt> attribute of the entry.
<pre>#include &lt;ldap-deprecated.h&gt;
...
LDAP *ld;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to rename. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* New relative distinguished name (RDN) of the entry */
char *rdn = "uid=babs";
...
/* Set up the timeout period to wait for the "modify RDN" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Rename the entry */
if ( ( msgid = ldap_modrdn2( ld, dn, rdn, 1 ) ) == -1 ) {
  ldap_perror( ld, "ldap_modrdn2" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &amp;tv, &amp;result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_modrdn2" );
...</pre>
===== See Also  =====
 
ldap_rename()
 
==== ldap_modrdn2_s()  ====
<pre>#include &lt;ldap-deprecated.h&gt;
int ldap_modrdn2_s( LDAP *ld, const char *dn,
  const char *newrdn, int deleteoldrdn );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_modrdn2_s() Function Parameters"
|+ ldap_modrdn2_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to modify.
|-
| <tt>newrdn</tt>
| New RDN to assign to the entry.
|-
| <tt>deleteoldrdn</tt>
| If this is a non-zero value, the old RDN is not retained as a value in the modified entry. If <tt>0</tt>, the old RDN is retained as an attribute in the modified entry.
|}
 
===== Returns  =====
 
For a list of possible result codes, see ldap_rename_s() .
 
===== Description  =====
 
Please use the newer version of this function, ldap_rename_s() .
 
===== Example  =====
 
The following example uses the synchronous ldap_modrdn2_s() function to change the RDN of an entry from <tt>uid=bjensen</tt> to <tt>uid=babs</tt>. The code removes the existing RDN <tt>babs</tt> from the <tt>uid</tt> attribute of the entry.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
/* Distinguished name of the entry that you want to rename. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* New relative distinguished name (RDN) of the entry */
char *rdn = "uid=babs";
...
/* Rename the entry */
if ( ldap_modrdn2_s( ld, dn, rdn, 1 )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modrdn2_s" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_rename_s()
 
==== ldap_mods_free()  ====
 
The ldap_mods_free() function frees the LDAPMod structures that you’ve allocated to add or modify entries.
 
'''Note:''' You need to call this function only if you’ve allocated memory for these structures yourself. For more information, see the <tt>ldap-extension.h</tt> header file.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_mods_free( LDAPMod **mods, int freemods );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_mods_free() Function Parameters"
|+ ldap_mods_free() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>mods</tt>
| Pointer to a <tt>NULL</tt> terminated array of pointers to LDAPMod structures.
|-
| <tt>freemods</tt>
| If this is a non-zero value, frees the array of pointers as well as the LDAPMod structures. If <tt>0</tt>, just frees the LDAPMod structures.
|}
 
===== Example  =====
 
The following example allocates memory for LDAPMod structures and frees them when done.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
char *dn;
int i, msgid;
LDAPMod **mods;
...
/* Construct the array of values to add */
mods = ( LDAPMod ** ) malloc(( NMODS + 1 ) * sizeof( LDAPMod * ));
if ( mods == NULL ) {
  fprintf( stderr, "Cannot allocate memory for mods array\n" );
}
for ( i = 0; i &lt; NMODS; i++ ) {
  if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL) {
    fprintf( stderr, "Cannot allocate memory for mods element\n" );
    exit( 1 );
  }
}
...
/* Code for filling the structures goes here. */
...
/* Initiate the add operation */
if (( msgid = ldap_add( ld, dn, mods )) &lt; 0 ) {
  ldap_perror( ld, "ldap_add" );
  ldap_mods_free( mods, 1 );
  return( 1 );
}
...</pre>
==== ldap_msgfree()  ====
 
The ldap_msgfree() function frees the memory allocated for a result by ldap_result() or ldap_search_s().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_msgfree( LDAPMessage *lm );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_msgfree() Function Parameter"
|+ ldap_msgfree() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lm</tt>
| Pointer to the result to be freed from memory.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>LDAP_RES_BIND</tt> indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
*<tt>LDAP_RES_SEARCH_ENTRY</tt> indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_REFERENCE</tt> indicates that the LDAPMessage structure contains an LDAP v3 search reference (a referral to another LDAP server) found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_RESULT</tt> indicates that the LDAPMessage structure contains the result of an LDAP search operation.
*<tt>LDAP_RES_MODIFY</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
*<tt>LDAP_RES_ADD</tt> indicates that the LDAPMessage structure contains the result of an LDAP add operation.
*<tt>LDAP_RES_DELETE</tt> indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
*<tt>LDAP_RES_MODRDN</tt> or <tt>LDAP_RES_RENAME</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
*<tt>LDAP_RES_COMPARE</tt> indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
*<tt>LDAP_RES_EXTENDED</tt> indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
*LDAP_SUCCESS if the operation times out.
*<tt>-1</tt> indicates that the <tt>lm</tt> argument is not a pointer to a valid LDAPMessage structure.
*If unsuccessful, returns the LDAP error code for the operation.
 
===== Example  =====
 
The following example frees the results of a search.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *get_attr[] = { "cn", "mail", NULL };
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  get_attr, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
...
/* Free the results when done */
ldap_msgfree( result );
...</pre>
===== See Also  =====
 
ldap_result(), ldap_search_s()
 
==== ldap_msgid()  ====
 
The ldap_msgid() function determines the message ID of a result obtained by calling ldap_result() or ldap_search_s().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_msgid( LDAPMessage *lm );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_msgid() Function Parameter"
|+ ldap_msgid() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lm</tt>
| Pointer to the result to check.
|}
 
===== Returns  =====
 
One of the following values:
 
*The message ID if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Example  =====
 
The following example prints the message ID from the result obtained from a synchronous LDAP search operation.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
...
/* Perform a search */
if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER,
  NULL, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get and print the message ID */
if ( ldap_msgid( result )&nbsp;!= -1 ) {
  printf( "Message ID:&nbsp;%d\n" );
} else {
  printf( "An error occurred.\n" );
}
...</pre>
===== See Also  =====
 
ldap_msgtype(), ldap_result() , ldap_search_s()
 
==== ldap_msgtype()  ====
 
The ldap_msgtype() function determines the type of result obtained by calling ldap_result() or ldap_search_s().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_msgtype( LDAPMessage *lm );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_msgtype() Function Parameter"
|+ ldap_msgtype() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lm</tt>
| Pointer to the LDAPMessage structure to check.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>LDAP_RES_BIND</tt> indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
*<tt>LDAP_RES_SEARCH_ENTRY</tt> indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_REFERENCE</tt> indicates that the LDAPMessage structure contains an LDAP v3 search reference (a referral to another LDAP server) found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_RESULT</tt> indicates that the LDAPMessage structure contains the result of an LDAP search operation.
*<tt>LDAP_RES_MODIFY</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
*<tt>LDAP_RES_ADD</tt> indicates that the LDAPMessage structure contains the result of an LDAP add operation.
*<tt>LDAP_RES_DELETE</tt> indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
*<tt>LDAP_RES_MODRDN</tt> or <tt>LDAP_RES_RENAME</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
*<tt>LDAP_RES_COMPARE</tt> indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
*<tt>LDAP_RES_EXTENDED</tt> indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
*<tt>-1</tt> indicates that the <tt>lm</tt> argument is not a pointer to a valid LDAPMessage structure.
 
===== Example  =====
 
The following example prints the message type for a result obtained from a synchronous LDAP search operation.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
int msgtype;
...
/* Perform a search */
if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER,
  NULL, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get and print the message type */
msgtype = ldap_msgtype( result );
if ( msgtype&nbsp;!= -1 ) {
  printf( "Message type:&nbsp;%d\n", msgtype );
} else {
  printf( "An error occurred.\n" );
}
...</pre>
===== See Also  =====
 
ldap_msgid(), ldap_result() , ldap_search_s()
 
==== ldap_multisort_entries()  ====
 
The ldap_multisort_entries() function sorts a chain of entries retrieved from an LDAP search call (ldap_search_s() or ldap_result()) by either a specified set of attributes in the entries or DN.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_multisort_entries( LDAP *ld, LDAPMessage **chain,
  char **attr, LDAP_CMP_CALLBACK *cmp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_multisort_entries() Function Parameters"
|+ ldap_multisort_entries() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>chain</tt>
| Chain of entries returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>attr</tt>
| Array of attributes to use for sorting the results. If <tt>NULL</tt>, results are sorted by DN.
|-
| <tt>cmp</tt>
| Comparison function used when sorting the values.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>0</tt> if successful.
*<tt>-1</tt> if memory cannot be allocated by this function. (The error code LDAP_NO_MEMORY is set in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.)
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function
 
===== Example  =====
 
The following example sorts entries first by the <tt>roomNumber</tt> attribute, then by the <tt>telephoneNumber</tt> attribute.
<pre>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *attrs[3];
attrs[0] = "roomNumber";
attrs[1] = "telephoneNumber";
attrs[2] = NULL;
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Sort the results, using strcasecmp */
if ( ldap_multisort_entries( ld, &amp;result, attrs, strcasecmp )&nbsp;!=
  LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_multisort_entries" );
    return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_result(), ldap_search_s() , ldap_sort_entries(), LDAP_CMP_CALLBACK()
 
==== ldap_name2template()  ====
 
The ldap_name2template() function obtains a pointer to the correct <tt>ldap_disptmpl</tt> structure.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_disptmpl * ldap_name2template( char *name
  struct ldap_disptmpl *tmpllist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_name2template() Function Parameters"
|+ ldap_name2template() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>name</tt>
| Name of the template.
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Returns  =====
 
*If successful, <tt>0</tt> is returned and <tt>tmpllistp</tt> is configured.
*Upon error:
**<tt>LDAP_TMPL_ERR_VERSION</tt> if <tt>buf</tt> points to data that is newer than can be handled.
**<tt>LDAP_TMPL_ERR_MEM</tt> if there is a memory allocation problem.
**<tt>LDAP_TMPL_ERR_SYNTAX</tt> if there is a problem with the format of the templates buffer or file.
**<tt>LDAP_TMPL_ERR_FILE</tt> if the file cannot be read.
 
===== Description  =====
 
ldap_name2template() obtains a pointer to the correct <tt>ldap_disptmpl</tt> structure. Links to templates can be defined by name.
 
==== ldap_next_attribute()  ====
 
The ldap_next_attribute() function returns the name of the next attribute in an entry returned by ldap_first_entry() or ldap_next_entry().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char * ldap_next_attribute( LDAP *ld, LDAPMessage *entry,
  BerElement *ber);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_attribute() Function Parameters"
|+ ldap_next_attribute() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Pointer to the LDAPMessage structure representing the entry returned by the ldap_first_entry() or ldap_next_entry() function.
|-
| <tt>ber</tt>
| A pointer to a BerElement allocated to keep track of its current position. Pass this pointer to subsequent calls to ldap_next_attribute() to step through the entry's attributes.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the name of the next attribute in an entry. When you are done using this data, you should free the memory by calling the ldap_memfree() function.
*If no more attributes exist in the entry, returns a <tt>NULL</tt> .
*If unsuccessful, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
 
===== Description  =====
 
The ldap_first_attribute() function returns a pointer to a BerElement. You use this pointer with ldap_next_attribute() to iterate through the list of elements. After the last call to ldap_next_element(), you should free the BerElement pointer using ldap_ber_free(). When calling ldap_ber_free(), make sure to specify that the buffer is not freed (pass <tt>0</tt> for the <tt>freebuf</tt> parameter).
 
===== Example  =====
 
See the example under ldap_first_attribute().
 
===== See Also  =====
 
ldap_first_attribute(), ldap_getfirstfilter(), ldap_next_entry()
 
==== ldap_next_disptmpl()  ====
 
The ldap_next_disptmpl() function returns the next template in a list.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_disptmpl * ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
  struct ldap_disptmpl *tmpl );;</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_disptmpl() Function Parameters"
|+ ldap_next_disptmpl() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| Defines a template from the template list tmpllist. A <tt>NULL</tt> pointer is returned if tmpl is the last template in the list.
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures typically obtained by calling ldap_init_templates().
|}
 
===== Returns  =====
 
*If successful, <tt>0</tt> is returned and <tt>tmpllistp</tt> is configured.
*Upon error:
**<tt>LDAP_TMPL_ERR_VERSION</tt> if <tt>buf</tt> points to data that is newer than can be handled.
**<tt>LDAP_TMPL_ERR_MEM</tt> if there is a memory allocation problem.
**<tt>LDAP_TMPL_ERR_SYNTAX</tt> if there is a problem with the format of the templates buffer or file.
**<tt>LDAP_TMPL_ERR_FILE</tt> if the file cannot be read.
 
===== Description  =====
 
ldap_next_disptmpl() returns the template following the previous one in the list of templates pointed to by the parameter <tt>tmpllistp</tt>. <tt>tmpllistp</tt> is typically obtained by calling ldap_init_templates() .
 
===== See Also  =====
 
ldap_first_disptmpl()
 
==== ldap_next_entry()  ====
 
The ldap_next_entry() function returns a pointer to the LDAPMessage structure representing the next directory entry in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_next_entry( LDAP *ld, LDAPMessage *entry );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_entry() Function Parameters"
|+ ldap_next_entry() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>entry</tt>
| Pointer to an LDAPMessage structure in a chain of search results.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the pointer to the next LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> in a chain of search results.
*If no more LDAPMessage structures of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> are in the chain or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_next_entry() function returns a pointer to the LDAPMessage structure representing the next directory entry in a chain of search results. You can use this function in conjunction with the ldap_first_entry() function to iterate through the directory entries in a chain of search results. These functions skip over any messages in the chain that do not have the type <tt>LDAP_RES_SEARCH_ENTRY</tt> as messages containing directory entries have the type <tt>LDAP_RES_SEARCH_ENTRY</tt>.
 
===== See Also  =====
 
ldap_first_entry()
 
==== ldap_next_message()  ====
 
The ldap_next_message() function returns a pointer to the next LDAPMessage structure in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_next_message( LDAP *ld, LDAPMessage *msg );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_message() Function Parameters"
|+ ldap_next_message() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>msg</tt>
| Pointer to an LDAPMessage structure in a chain of search results.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the pointer to the next LDAPMessage structure in a chain of search results.
*If no more LDAPMessage structures are in the chain or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_next_message() function returns a pointer to the next LDAPMessage structure in a chain of search results. You can use this function in conjunction with the ldap_first_message() function to iterate through the chain of search results. You can also call the ldap_msgtype() function to determine if each message contains a matching entry (a message of the type <tt>LDAP_RES_SEARCH_ENTRY</tt> ) or a search reference (a message of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>).
 
===== See Also  =====
 
ldap_first_message(), ldap_msgtype()
 
==== ldap_next_reference()  ====
 
The ldap_next_reference() function returns a pointer to the LDAPMessage structure representing the next search reference in a chain of search results.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAPMessage * ldap_next_reference( LDAP *ld, LDAPMessage *ref );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_reference() Function Parameters"
|+ ldap_next_reference() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>msg</tt>
| Pointer to an LDAPMessage structure in a chain of search results.
|}
 
===== Returns  =====
 
One of the following values:
*If successful, returns the pointer to the next LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt> in a chain of search results.
*If no more LDAPMessage structures of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt> are in the chain or if the function is unsuccessful, returns a <tt>NULLMSG</tt>.
 
===== Description  =====
 
The ldap_next_reference() function returns a pointer to the LDAPMessage structure representing the next search reference in a chain of search results. You can use this function in conjunction with the ldap_first_reference() function to iterate through the search references in a chain of search results. These functions skip over any messages in the chain that do not have the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>. Messages containing search references have the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.
 
===== See Also  =====
 
ldap_first_reference()
 
==== ldap_next_searchobj()  ====
 
The ldap_next_searchobj() function returns the following search preference in a defined list.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
struct ldap_searchobj * ldap_next_searchobj
  ( struct ldap_searchobj *sollist, struct ldap_searchobj *so );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_searchobj() Function Parameters"
|+ ldap_next_searchobj() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>sollist</tt>
| Pointer to a list of data structures, typically obtained by calling ldap_init_searchprefs().
|-
| <tt>so</tt>
| Pointer to the most recent search object returned in the template list <tt>sollist</tt>. The search object returned by ldap_next_searchobj() follows this one.
|}
 
===== Returns  =====
 
*If successful, a pointer to an <tt>ldap_searchobj</tt> structure.
*A <tt>NULL</tt> pointer is returned if <tt>so</tt> is the last entry in the list.
 
===== Description  =====
 
The search object returned by ldap_next_searchobj() follows the one defined by the <tt>so</tt> parameter.
 
===== See Also  =====
 
ldap_init_searchprefs(), ldap_first_searchobj()
 
==== ldap_next_tmplcol()  ====
 
The ldap_next_tmplcol() function returns a pointer to the following item (in the column) within a template.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_tmplitem * ldap_next_tmplcol( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row, struct ldap_tmplitem *col );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_tmplcol() Function Parameters"
|+ ldap_next_tmplcol() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| The name of the template to be retrieved.
|-
| <tt>row</tt>
| The row in which the item is to be retrieved from.
|-
| <tt>col</tt>
| The column in which the item is to be retrieved from.
|}
 
===== Returns  =====
 
*If successful, a pointer to an <tt>ldap_tmplitem</tt> structure.
*A <tt>NULL</tt> pointer on error or if <tt>col</tt> was the last item.
 
===== Description  =====
 
ldap_next_tmplcol() returns a pointer to the next item (in the column) of the row, defined by <tt>row</tt>, within the template defined by <tt>tmpl</tt>.
 
===== See Also  =====
 
ldap_first_tmplcol()
 
==== ldap_next_tmplrow()  ====
 
The ldap_next_tmplrow() function returns a pointer to the following row in a template.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_tmplitem * ldap_next_tmplrow( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_next_tmplrow() Function Parameters"
|+ ldap_next_tmplrow() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| The name of the template to be retrieved.
|-
| <tt>row</tt>
| The row in the template to be retrieved.
|}
 
===== Returns  =====
 
*If successful, a pointer to an <tt>ldap_tmplitem</tt> structure.
*A <tt>NULL</tt> pointer on error.
 
===== Description  =====
 
ldap_next_tmplrow() returns a pointer to the row that follows the one defined by <tt>row</tt> in the template defined by <tt>tmpl</tt> .
 
==== ldap_oc2template()  ====
 
The ldap_oc2template() function obtains a pointer to the correct <tt>ldap_disptmpl</tt> structure.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
struct ldap_disptmpl * ldap_oc2template( char **oclist,
  struct ldap_disptmpl *tmpllist );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_oc2template() Function Parameters"
|+ ldap_oc2template() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>oclist</tt>
| A <tt>NULL</tt> terminated array of strings that contains the values of the <tt>objectClass</tt> attribute of the entry.
|-
| <tt>tmpllistp</tt>
| Pointer to a list of template data structures.
|}
 
===== Returns  =====
 
*Pointer to the first template where all of the object classes listed in one of the template's <tt>dt_oclist</tt> elements are contained in <tt>oclist</tt>.
*A <tt>NULL</tt> pointer if no appropriate template is found.
 
===== Description  =====
 
ldap_oc2template()searches <tt>tmpllist</tt> for the best template to use to display an entry that has a specific set of <tt>objectClass</tt> values.
 
==== ldap_open()  ====
<pre>#include &lt;ldap-deprecated.h&gt;
ldap_open( const char *host, int port );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_open() Function Parameters"
|+ ldap_open() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>host</tt>
| The hostname on which the LDAP server is running. It may contain a blank-separated list of hosts to try to connect to, and each host may optionally be of the form ''host'':''port''. If present, ''port'' overrides the port parameter. Upon successfully making a connection to an LDAP server, ldap_open() returns a pointer to an LDAP structure, which should be passed to subsequent calls ldap_bind(), ldap_search()
|-
| <tt>port</tt>
| The port number to which to connect. If the default IANA-assigned port of 389 is desired, <tt>LDAP_PORT</tt> should be specified as the value of port.
|}
 
===== Description  =====
 
Please use a newer version of this function, ldap_init() or prldap_init() (IPv6).
 
==== ldap_parse_authzid_control()  ====
 
The ldap_parse_authzid_control() function parses the authorization identity bind response control retrieved from the server to extract the authorization ID.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_authzid_control( LDAP *ld,
  LDAPControl **ctrlp, char **authzid );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_authzid_control() Function Parameters"
|+ ldap_parse_authzid_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctrlp
| Pointer to an LDAPControl structure retrieved from the server.
|-
| authzid
| Pointer to string holding the authorization ID.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== See Also  =====
 
ldap_create_authzid_control()
 
==== ldap_parse_entrychange_control()  ====
 
The ldap_parse_entrychange_control() function examines a list of controls returned from a persistent search operation, retrieves an entry change control, and parses that control for information (such as the type of change made to the entry and the change number).
 
'''Note:''' This function implements an extension to the LDAP v3. Entry change notification is an optional feature; it may not be supported on all LDAP servers. Call this function when interacting with LDAP servers that support this LDAP v3 extension.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_parse_entrychange_control( LDAP *ld,
  LDAPControl **ctrls, int *chgtypep, char **prevdnp,
  int *chgnumpresentp, long *chgnump );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_entrychange_control() Function Parameters"
|+ ldap_parse_entrychange_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>ctrlp</tt>
| An array of controls returned by the server. You obtain these controls by calling the ldap_get_entry_controls() function on an entry returned by the server.
|-
| <tt>changetypes</tt>
| Pointer to an integer specifying the type of change made to the entry. This field can have one of the following values:
*<tt>LDAP_CHANGETYPE_ADD</tt> specifies that the entry was added to the directory.
*<tt>LDAP_CHANGETYPE_DELETE</tt> specifies that the entry was deleted from the directory.
*<tt>LDAP_CHANGETYPE_MODIFY</tt> specifies that the entry was modified.
*<tt>LDAP_CHANGETYPE_MODDN</tt> specifies that the DN or RDN of the entry was changed (a modify RDN or modify DN operation was performed).
|-
| <tt>prevdnp</tt>
| Pointer to the previous DN of the entry, if the <tt>changetypes</tt> argument is <tt>LDAP_CHANGETYPE_MODDN</tt>. If the <tt>changetypes</tt> argument has a different value, this argument is set to <tt>NULL</tt>. When done, you can free this by calling the ldap_memfree() function.
|-
| <tt>chgnumpresentp</tt>
| Pointer to an integer specifying whether or not to the change number is included in the control. The parameter can have the following possible values:
*<tt>0</tt> specifies that the change number is not included.
*A non-zero value specifies that the change number is included and is available as the <tt>chgnump</tt> argument.
|-
| <tt>chgnump</tt>
| Pointer to the change number identifying the change made to the entry, if <tt>chgnumpresentp</tt> points to a non-zero value.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_DECODING_ERROR if an error occurred when BER-decoding the control.
 
===== Description  =====
 
The ldap_parse_entrychange_control() function can be called:
*To parse an entry returned from a persistent search operation and retrieve an entry change control.
*After receiving an entry from a persistent search and retrieving the controls from the entry. Call ldap_get_entry_controls() to get the controls.
 
===== See Also  =====
 
ldap_create_persistentsearch_control(), ldap_get_entry_controls()
 
==== ldap_parse_extended_result()  ====
 
The ldap_parse_extended_result() function parses the results of an LDAP extended operation and retrieves the object identifier (OID) and data returned by the server.
<pre>#include &lt;ldap.h&gt;
int ldap_parse_extended_result( LDAP *ld, LDAPMessage *res,
  char **retoidp, struct berval **retdatap, int freeit );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_extended_result() Function Parameters"
|+ ldap_parse_extended_result() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>res</tt>
| Pointer to the LDAPMessage structure containing the results of an LDAP operation.
|-
| <tt>retoidp</tt>
| Pointer to the OID returned by the server after performing the extended operation. When done, you can free this by calling the ldap_memfree() function.
|-
| <tt>retdatap</tt>
| Pointer to the pointer to a berval structure containing the data returned by the server after performing the extended operation. When done, you can free this by calling the ber_bvfree() function.
|-
| <tt>freeit</tt>
| Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the <tt>res</tt> argument). The parameter can have the following possible values: *<tt>0</tt> specifies that the result should not be freed. *A non-zero value specifies that the result should be freed.
|}
 
===== Returns  =====
 
One of the following values, which indicates the result of parsing the server’s response:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function. '''Note:''' This value does not apply to the operation itself.
 
===== Description  =====
 
ldap_parse_extended_result() parses the server’s response to an extended operation. After you call the ldap_extended_operation() and the ldap_result() functions, you can pass the results to ldap_parse_extended_result(). This function gets the following data from the server’s response:
*The extended operation OID received from the server is passed back as the retoidp argument.
*The data received from the server is passed back in the berval structure as the <tt>retdatap</tt> argument.
*The LDAP result code for the LDAP extended operation is placed in the <tt>ld</tt> structure. You can get the result code by calling the ldap_get_lderrno() function. For a list of possible result codes for an LDAP extended operation, see ldap_extended_operation_s() . See also ldap_extended_operation_s(), ldap_get_lderrno().
 
==== ldap_parse_passwd()  ====
 
The ldap_parse_passwd() function lets you examine the result of an LDAP Password Modify extended operation to obtain the password generated by the server when you reset a password without providing a new password value.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_passwd( LDAP *ld, LDAPMessage *result,
  struct berval *genpasswd );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_passwd() Function Parameters"
|+ ldap_parse_passwd() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| result
| Pointer to the message retrieved using the message ID from ldap_passwd().
|-
| genpasswd
| Pointer to the BER value structure to hold the password generated by the server.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_parse_passwd_result()  ====
 
The ldap_parse_passwd_result() function lets you examine the result of an LDAP Password Modify extended operation to obtain the password generated by the server when you reset a password without providing a new password value.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_passwd_result( LDAP *ld, int *msgidp,
  struct timeval *timeout, struct berval *genpasswd );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_passwd_result() Function Parameters"
|+ ldap_parse_passwd_result() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| msgidp
| Pointer to the message ID retrieved using ldap_passwd().
|-
| timeout
| Specifies a maximum interval to wait for the selection to complete. If timeout is a <tt>NULL</tt> pointer, the select blocks indefinitely. To effect a poll, the timeout parameter should be a non-<tt>NULL</tt> pointer, pointing to a zero-valued &lt;structname&gt; timeval&lt;/structname&gt; structure.
|-
| genpasswd
| Pointer to the BER value structure to hold the password generated by the server.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments  are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_parse_pwdpolicy_control()  ====
 
The ldap_parse_pwdpolicy_control() function parses information about the password policy relative to a user account contained in a control returned with a bind, add, modify, or compare result after the ldap_create_userstatus_control() is used to create a request control sent to the server. The ldap_parse_pwdpolicy_control() function populates an LDAPpwdpolicy structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_pwdpolicy_control( LDAP *ld,
  LDAPControl **ctrlp, LDAPpwdpolicy *pp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_pwdpolicy_control() Function Parameters"
|+ ldap_parse_pwdpolicy_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctrlp
| Pointer to an LDAPControl structure retrieved from the server.
|-
| pp
| Pointer to an LDAPpwdpolicy structure to hold the information about password policy.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== See Also  =====
 
ldap_create_pwdpolicy_control(), LDAPpwdpolicy()
 
==== ldap_parse_reference()  ====
 
The ldap_parse_reference() function parses search references from the results received from an LDAP server. '''Note:''' Search references are part of the LDAP v3. When calling this function, make sure that you are working with a server that supports the LDAP v3.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_parse_reference( LDAP *ld, LDAPMessage *ref,
  char ***referralsp, LDAPControl ***serverctrlsp,
  int freeit );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_reference() Function Parameters"
|+ ldap_parse_reference() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>ref</tt>
| Pointer to an LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>.
|-
| <tt>referralsp</tt>
| Pointer to an array of strings representing the referrals found by an LDAP search operation and returned by the server (applicable only if the LDAP operation was a search operation). When done, you can free this by calling the ldap_value_free() function.
|-
| <tt>serverctrlsp</tt>
| Pointer to an array of LDAPControl structures, which represent the LDAP v3 server controls returned by the server. When done, you can free this by calling the ldap_controls_free() function.
|-
| <tt>freeit</tt>
| Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the <tt>res</tt> argument). The parameter can have the following possible values: *<tt>0</tt> specifies that the result should not be freed. *A non-zero value specifies that the result should be freed.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
The ldap_parse_reference() function parses the referral URLs from an LDAPMessage structure of the type <tt>LDAP_RES_SEARCH_REFERENCE</tt>, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.
 
==== ldap_parse_result()  ====
 
The ldap_parse_result() function parses the results of an LDAP operation received from an LDAP server.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_parse_result( LDAP *ld, LDAPMessage *res,
  int *errcodep, char **matcheddnp, char **errmsgp,
  char ***referralsp, LDAPControl ***serverctrlsp, int freeit);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_result() Function Parameters"
|+ ldap_parse_result() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>res</tt>
| Pointer to the LDAPMessage structure containing the results of an LDAP operation.
|-
| <tt>errcodep</tt>
| Pointer to the LDAP result code specifying the result of the operation.
|-
| <tt>matcheddnp</tt>
| Pointer to a string specifying the portion of a DN that finds an existing entry (in cases where the server cannot find the entry specified by a DN). When done, you can free this by calling the ldap_memfree() function.
|-
| <tt>errmsgp</tt>
| Pointer to an additional error message string sent from the server. When done, you can free this by calling the ldap_memfree() function.
|-
| <tt>referralsp</tt>
| Pointer to an array of strings representing the referrals returned by the server. When done, you can free this by calling the ldap_value_free function.
|-
| <tt>serverctrlsp</tt>
| Pointer to an array of LDAPControl structures, which represent the LDAPv3 server controls returned by the server. When done, you can free this by calling the ldap_controls_free() function.
|-
| <tt>freeit</tt>
| Specifies whether or not to automatically free the results of the operation (the LDAPMessage structure specified by the <tt>res</tt> argument). The parameter can have the following possible values:
*<tt>0</tt> specifies that the result should not be freed.
*A non-zero value specifies that the result should be freed.
 
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_NO_RESULTS_RETURNED if the specified LDAPMessage structure does not contain the result of an LDAP operation (for example, if it contains an entry, search reference, or chain of search results instead of the result of an LDAP operation).
*LDAP_MORE_RESULTS_TO_RETURN if the result in the LDAPMessage structure is part of a chain of results and the last result is not included.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
The ldap_parse_result() function parses the results of an LDAP operation (received from an LDAP server) and retrieves:
*The LDAP result code that indicates the result of the LDAP operation (<tt>errcodep</tt>).
*An additional error message (<tt>optional</tt>) sent by the server (<tt>errmsgp</tt>).
*The portion of the DN that finds an entry, if the server is unable to find an entry from a DN that you specify (<tt>matcheddnp</tt>).
*A set of referrals, if the server does not contain the entries that you’ve specified and if the server is configured to refer clients to other servers (<tt>referralsp</tt>).
*A set of server response controls that are relevant to the operation (<tt>serverctrlsp</tt>). Calling this function creates an array of LDAPControl structures that you can pass to subsequent API functions (such as the ldap_parse_sort_control() function.
 
See also ldap_result().
 
==== ldap_parse_sasl_bind_result()  ====
 
The ldap_parse_sasl_bind_result() function parses the results of an LDAP SASL bind operation and retrieves data returned by the server.
 
'''Note:''' SASL authentication is part of the LDAP v3. When calling this function, make sure that you are working with a server that supports the LDAP v3.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *res,
  struct berval **servercredp, int freeit );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_sals_bind_result() Function Parameters"
|+ ldap_parse_sals_bind_result() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>res</tt>
| Pointer to the LDAPMessage structure containing the results of an LDAP operation.
|-
| <tt>servercredp</tt>
| Pointer to a pointer to an berval structure containing any challenge or credentials returned by the server. When done, you can free this by calling the ber_bvfree() function.
|-
| <tt>freeit</tt>
| Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the <tt>res</tt> argument). The parameter can have the following possible values:
*<tt>0</tt> specifies that the result should not be freed.
*A non-zero value specifies that the result should be freed.
 
|}
 
===== Returns  =====
 
One of the following values, which indicates the result of parsing the server’s response:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
After you call the ldap_sasl_bind() function and the ldap_result() function, you can pass the results to ldap_parse_sasl_bind_result() for parsing. This function gets the following data from the server’s response:
*The challenge or credentials sent back from the server are passed back in the berval structure as the <tt>servercredp</tt> argument.
*The LDAP result code for the SASL bind operation is placed in the <tt>ld</tt> structure. You can get the result code by calling the ldap_get_lderrno() function. (If the result code is LDAP_SASL_BIND_IN_PROGRESS , you can call ldap_sasl_bind() again to send a response to the server’s challenge and call ldap_result() and ldap_parse_sasl_bind_result() again to get the next challenge from the server. For a list of possible result codes for an LDAP SASL bind operation, see ldap_sasl_bind().
 
'''Note:''' The LDAP server must support authentication through SASL mechanisms. Directory Server supports a plug-in interface that you can use to add SASL support to the server.
 
===== See Also  =====
 
ldap_sasl_bind(), ldap_get_lderrno
 
==== ldap_parse_sort_control()  ====
 
The parse_sort_control() function parses the result returned from a search operation that used a server control for sorting search results.
<pre>#include &lt;ldap.h&gt;
int ldap_parse_sort_control( LDAP *ld, LDAPControl **ctrls,
  unsigned long *result, char **attribute );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_sort_control() Function Parameters"
|+ ldap_parse_sort_control() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>ctrls</tt>
| An array of controls returned by the server. You obtain these controls by calling the ldap_parse_result() function on the set of results returned by the server.
|-
| <tt>result</tt>
| Pointer to the sort control result code retrieved by this function.
|-
| <tt>attribute</tt>
| If the sorting operation fails, the function sets this to point to the name of the attribute that caused the failure. When done, you can free this by calling the ldap_memfree() function.
|}
 
===== Returns  =====
 
One of the following values, which indicates the result of parsing the server’s response:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
 
===== Description  =====
 
Call the ldap_parse_sort_control() function as part of the process of retrieving sorted search results from a server. First, though, call ldap_result() to get the results, and ldap_parse_result() to parse the server controls from the results.
 
===== See Also  =====
 
ldap_create_sort_control()
 
==== ldap_parse_userstatus_control()  ====
 
The ldap_parse_userstatus_control() function parses information about the status of a user account contained in a control returned with an entry resulting from a search request that included the control created with ldap_create_userstatus_control(). The ldap_parse_userstatus_control() function populates an LDAPuserstatus structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_userstatus_control( LDAP *ld,
  LDAPControl **ctrlp, LDAPuserstatus *us );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_userstatus_control() Function Parameters"
|+ ldap_parse_userstatus_control() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| ctrlp
| Pointer to an LDAPControl structure retrieved with ldap_get_entry_controls().
|-
| us
| Pointer to an LDAPuserstatus structure to hold the information about account status.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== See Also  =====
 
ldap_create_userstatus_control(), LDAPuserstatus()
 
==== ldap_parse_whoami()  ====
 
The ldap_parse_whoami() function retrieves the authorization identity from the result of an asynchronous Who am I? extended operation request.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld,
  LDAPMessage *result, char **authzid );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_whoami() Function Parameters"
|+ ldap_parse_whoami() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| result
| Pointer to the message retrieved using the message ID from ldap_whoami().
|-
| authzid
| Pointer to the string to hold the authorization identity retrieved for the connection.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_parse_whoami_result()  ====
 
The ldap_parse_whoami_result() function retrieves the authorization identity from the result of an asynchronous Who am I? extended operation request.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld, int *msgidp,
  struct timeval *timeout, char **authzid );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_whoami_result() Function Parameters"
|+ ldap_parse_whoami_result() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| ld
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| msgidp
| Pointer to the message ID retrieved using ldap_whoami().
|-
| timeout
| Specifies a maximum interval to wait for the selection to complete. If timeout is a <tt>NULL</tt> pointer, the select blocks indefinitely. To effect a poll, the timeout parameter should be a non-<tt>NULL</tt> pointer, pointing to a zero-valued &lt;structname&gt; timeval&lt;/structname&gt; structure.
|-
| authzid
| Pointer to the string to hold the authorization identity retrieved for the connection.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_parse_virtuallist_control()  ====
 
The ldap_parse_virtuallist_control() function parses the result returned from a search operation that used a server control for virtual list views. '''Note:''' This function implements an extension to the LDAP v3. A ''virtual'' list view''is an optional LDAP server feature that may not be supported'' on all LDAP servers.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_parse_virtuallist_control( LDAP *ld,
  LDAPControl **ctrls, unsigned long *target_posp,
  unsigned long *list_sizep, int *errcodep );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_parse_virtuallist_control() Function Parameters"
|+ ldap_parse_virtuallist_control() Function Parameters
|-
! scope="col" | Parameters
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>ctrls</tt>
| An array of controls returned by the server. You obtain these controls by calling the ldap_parse_result() function on the set of results returned by the server.
|-
| <tt>target_posp</tt>
| Pointer to an unsigned long that is set by the function. The function sets this to the index or offset of the selected entry in the list of entries.
|-
| <tt>list_sizep</tt>
| Pointer to an unsigned long that is set by the function. The function sets this to the number of entries in the total number of entries in the entire list (not just the subset).
|-
| <tt>errcodep</tt>
| Pointer to the sort control result code retrieved by this function.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
*LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== Description  =====
 
The ldap_parse_virtuallist_control() function can be called:
*As part of the process of retrieving a subset of entries from a list when working with a virtual list view box.
*After, calling ldap_result() to get the results, and ldap_parse_result() to parse the server controls from the results.
 
===== See Also  =====
 
ldap_create_virtuallist_control()
 
==== ldap_passwd()  ====
 
The ldap_passwd() asynchronous function allows you to perform an LDAP Password Modify extended operation, as defined in RFC 3062.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_passwd( LDAP *ld, struct berval *userid,
  struct berval *oldpasswd, struct berval *newpasswd,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_passwd() Function Parameters"
|+ ldap_passwd() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>userid</tt>
| DN of the user whose password you want to modify.
|-
| <tt>oldpasswd</tt>
| Old password used before expiration. If the password has not yet expired, this is the current password.
|-
| <tt>newpasswd</tt>
| New password to use after modification
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer to be set to the message ID of the operation. To check the result of this operation, call the ldap_result() and ldap_parse_passwd() function, or ldap_parse_passwd_result() function.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_passwd_s()  ====
 
The ldap_passwd_s() synchronous function allows you to perform an LDAP Password Modify extended operation, as defined in RFC 3062.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_passwd_s( LDAP *ld, struct berval *userid,
  struct berval *oldpasswd, struct berval *newpasswd,
  struct berval *genpasswd, LDAPControl **serverctrls,
  LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_passwd() Function Parameters"
|+ ldap_passwd() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>userid</tt>
| DN of the user whose password you want to modify.
|-
| <tt>oldpasswd</tt>
| Old password used before expiration. If the password has not yet expired, this is the current password.
|-
| <tt>newpasswd</tt>
| New password to use after modification
|-
| <tt>genpasswd</tt>
| New password generated by the server when an expired password is reset, but no <tt>newpasswd</tt> value is provided.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
==== ldap_perror()  ====
<pre>#include &lt;ldap-deprecated.h&gt;
void ldap_perror( LDAP *ld, const char *s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_perror() Function Parameters"
|+ ldap_perror() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>s</tt>
| Optional text to print out before printing the error message.
|}
 
===== Description  =====
 
Use the newer version of this function, ldap_get_lderrno() .
 
===== Example  =====
 
The following example prints out an error message if the search operation cannot complete successfully.
<pre>...
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  get_attr, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_get_lderrno(), ldap_err2string(), ldap_result2error(), ldap_set_lderrno()
 
==== ldap_rename()  ====
 
The ldap_rename() function changes the DN of an entry in the directory asynchronously.
 
'''Note:''' ldap_rename() is a new version of the ldap_modrdn2() function. If you are writing a new LDAP client, you should call ldap_rename().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_rename( LDAP *ld, const char *dn, const char *newrdn,
  const char *newparent, int deleteoldrdn,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_rename() Function Parameters"
|+ ldap_rename() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to rename.
|-
| <tt>newrdn</tt>
| New Relative Distinguished Name (RDN) to assign to the entry.
|-
| <tt>newparent</tt>
| DN of the new parent entry you want to move the entry under. Pass <tt>NULL</tt> if you do not want to move the entry to a different location in the directory tree.
|-
| <tt>deleteoldrdn</tt>
| Specifies whether or not the old RDN is retained as an attribute of the entry. For example, an entry has the following values for the <tt>cn</tt> attribute: <tt>cn: Barbara Jensen</tt> <tt>cn: Babs Jensen</tt><br>If you change the RDN to <tt>cn=Barbie Jensen</tt> and pass <tt>1</tt> as <tt>deleteoldrdn</tt>, the resulting entry has the following values: <tt>cn: Barbie Jensen</tt> <tt>cn: Babs Jensen</tt><br>If instead you pass <tt>0</tt> as <tt>deleteoldrdn</tt>, the <tt>Barbara Jensen</tt> value is not removed from the entry: <tt>cn: Barbie Jensen</tt> <tt>cn: Babs Jensen</tt> <tt>cn: Barbara Jensen</tt><br>So, if this is a non-zero value, the old RDN is not retained as a value in the entry.<br>If <tt>0</tt>, the old RDN is retained as an attribute in the entry.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call the ldap_result() and ldap_parse_result() functions.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== Description  =====
 
The ldap_rename() changes the DN of an entry in the directory and allows you to move the entry under a different parent entry in the directory tree. ldap_rename() is an asynchronous function; it does not directly return results. In order to get the results of the LDAP rename operation, you need to call the ldap_result() function and the ldap_parse_result() function. If you want the results to be returned directly by the function, call the synchronous function ldap_rename_s() instead.
 
===== See Also  =====
 
ldap_rename_s(), ldap_result(), ldap_parse_result()
 
==== ldap_rename_s()  ====
 
The ldap_rename_s() function changes the DN of an entry in the directory synchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_rename_s( LDAP *ld, const char *dn, const char *newrdn,
  const char *newparent, int deleteoldrdn,
  LDAPControl **serverctrls, LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_rename() Function Parameters"
|+ ldap_rename() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the entry to rename.
|-
| <tt>newrdn</tt>
| New Relative Distinguished Name (RDN) to assign to the entry.
|-
| <tt>newparent</tt>
| DN of the new parent entry you want to move the entry under. Pass <tt>NULL</tt> if you do not want to move the entry to a different location in the directory tree.
|-
| <tt>deleteoldrdn</tt>
| Specifies whether or not the old RDN is retained as an attribute of the entry. For example, an entry has the following values for the <tt>cn</tt> attribute: <tt>cn: Barbara Jensen</tt> <tt>cn: Babs Jensen</tt><br>If you change the RDN to <tt>cn=Barbie Jensen</tt> and pass <tt>1</tt> as <tt>deleteoldrdn</tt>, the resulting entry has the following values: <tt>cn: Barbie Jensen</tt> <tt>cn: Babs Jensen</tt><br>If instead you pass <tt>0</tt> as <tt>deleteoldrdn</tt>, the <tt>Barbara Jensen</tt> value is not removed from the entry: <tt>cn: Barbie Jensen</tt> <tt>cn: Babs Jensen</tt> <tt>cn: Barbara Jensen</tt><br>So, if this is a non-zero value, the old RDN is not retained as a value in the entry.<br>If <tt>0</tt>, the old RDN is retained as an attribute in the entry.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAPv3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_rename_s() changes the DN of an entry in the directory and allows you to move the entry under a different parent entry in the directory tree. The function ldap_rename_s() is synchronous; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_rename().
 
===== See Also  =====
 
ldap_rename()
 
==== ldap_result()  ====
 
The function ldap_result() waits for and returns the result of an LDAP operation initiated by one of the asynchronous LDAP API functions.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_result( LDAP *ld, int msgid, int all,
  struct timeval *timeout, LDAPMessage **result );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_result() Function Parameters"
|+ ldap_result() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>msgid</tt>
| Asynchronous functions return a unique message ID. This parameter takes message ID of the operation for which you want the results. To check any operation, pass <tt>LDAP_RES_ANY</tt> as the value of this parameter.
|-
| <tt>all</tt>
| Specifies how the results of a search are returned. This parameter can have the following values:
*<tt>0</tt> specifies that the results are returned one entry at a time, using separate calls to ldap_result().
*A non-zero value specifies that all results are returned at the same time (after the final search result is obtained by the library).
 
|-
| <tt>timeout</tt>
| Specifies a maximum interval to wait for the selection to complete. If timeout is a <tt>NULL</tt> pointer, the select blocks indefinitely. To effect a poll, the <tt>timeout</tt> parameter should be a non-<tt>NULL</tt> pointer, pointing to a zero-valued timeval structure.
|-
| <tt>result</tt>
| Result of the operation. To interpret the results, pass this to the LDAP parsing routines, such as ldap_result2error(), ldap_parse_result(), and ldap_first_entry.
|}
 
===== Returns  =====
 
One of the following values:
*<tt>LDAP_RES_BIND</tt> indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
*<tt>LDAP_RES_SEARCH_ENTRY</tt> indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_REFERENCE</tt> indicates that the LDAPMessage structure contains an LDAPv3 search reference (a referral to another LDAP server) found during an LDAP search operation.
*<tt>LDAP_RES_SEARCH_RESULT</tt> indicates that the LDAPMessage structure contains the result of an LDAP search operation.
*<tt>LDAP_RES_MODIFY</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
*<tt>LDAP_RES_ADD</tt> indicates that the LDAPMessage structure contains the result of an LDAP add operation.
*<tt>LDAP_RES_DELETE</tt> indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
*<tt>LDAP_RES_MODDN</tt> or <tt>LDAP_RES_RENAME</tt> indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
*<tt>LDAP_RES_COMPARE</tt> indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
*<tt>LDAP_RES_EXTENDED</tt> indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
*<tt>-1</tt> indicates that an error occurred. The error code is set in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
*<tt>0</tt> indicates that the operation has timed out.
 
===== See Also  =====
 
ldap_add_ext(), ldap_compare_ext() , ldap_delete_ext(), ldap_modify_ext(), ldap_rename(), ldap_simple_bind(), ldap_url_search()
 
==== ldap_result2error()  ====
<pre>#include &lt;ldap-deprecated.h&gt;
int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_result2error() Function Parameters"
|+ ldap_result2error() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>r</tt>
| Pointer to the LDAPMessage structure representing the results returned by the ldap_result() or ldap_search() function.
|-
| <tt>freeit</tt>
| Specifies whether or not the result should be freed after the error code is extracted. The parameter can have the following possible values:
*<tt>0</tt> specifies that the result should not be freed.
*A non-zero value specifies that the result should be freed.
 
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, sets the error code and other error information in the LDAP structure and returns the error code.
*If unsuccessful, returns LDAP_PARAM_ERROR.
 
===== Example  =====
 
See ldap_result().
 
===== See Also  =====
 
ldap_parse_result(), ldap_get_lderrno(), ldap_err2string(), ldap_result(), ldap_set_lderrno
 
==== ldap_sasl_bind()  ====
 
The ldap_sasl_bind() function authenticates your client to an LDAP server using an Simple Authentication and Security Layer (SASL) mechanism.
 
'''Note:''' The LDAP server must support authentication through SASL. Directory Server supports a server plug-in interface that you can use to add SASL support to the server.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_sasl_bind( LDAP *ld, const char *dn,
  const char *mechanism, const struct berval *cred,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_sasl_bind() Function Parameters"
|+ ldap_sasl_bind() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this to <tt>NULL</tt>.
|-
| <tt>mechanism</tt>
| Name of the SASL mechanism that you want to use for authentication.
|-
| <tt>cred</tt>
| Pointer to the berval structure containing the credentials that you want to use for authentication.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call ldap_result() and ldap_parse_sasl_bind_result() functions.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the SASL bind request was sent successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
 
===== Description  =====
 
The ldap_sasl_bind() function authenticates your client to an LDAP server by using a specified SASL mechanism. ldap_sasl_bind() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_sasl_bind_s(). In order to get the results of the LDAP SASL bind operation, call the ldap_result(), the ldap_parse_sasl_bind_result(), and the ldap_get_lderrno() functions.
 
===== See Also  =====
 
ldap_result(), ldap_parse_sasl_bind_result() , ldap_get_lderrno(), ldap_sasl_bind_s()
 
==== ldap_sasl_bind_s()  ====
 
The ldap_sasl_bind_s() function authenticates your client to an LDAP server synchronously using an SASL mechanism.
<pre>#include &lt;ldap.h&gt;
int ldap_sasl_bind_s( LDAP *ld, const char *dn,
  const char *mechanism, const struct berval *cred,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct berval **servercredp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_sasl_bind_s() Function Parameters"
|+ ldap_sasl_bind_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>dn</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this to <tt>NULL</tt>.
|-
| <tt>mechanism</tt>
| Name of the SASL mechanism that you want to use for authentication.
|-
| <tt>cred</tt>
| Pointer to the berval structure containing the credentials that you want to use for authentication.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>servercredp</tt>
| Pointer to a pointer to an berval structure containing any credentials returned by the server. When done, you can free this by calling the ber_alloc() function.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the SASL bind request was sent successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAPv3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
*LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_sasl_bind_s() function authenticates your client to an LDAP server by using a specified SASL mechanism. It is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_sasl_bind(). After authenticating a client through SASL, an LDAP server can return a set of credentials in the results. The <tt>servercredp</tt> argument points to this value.
 
===== See Also  =====
 
ldap_sasl_bind()
 
==== ldap_search()  ====
 
The ldap_search() function searches the directory asynchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_search( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_search() Function Parameters"
|+ ldap_search() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>base</tt>
| DN of the entry that serves as the starting point for the search. For example, setting base to <tt>dc=example,dc=com</tt> restricts the search to entries at <tt>example.com</tt>.
|-
| <tt>scope</tt>
| Scope of the search, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> searches the entry specified by base.
*<tt>LDAP_SCOPE_ONELEVEL</tt> searches all entries one level beneath the entry specified by base.
*<tt>LDAP_SCOPE_SUBTREE</tt> searches the entry specified by base and all entries at all levels beneath the entry specified by base.
 
|-
| <tt>filter</tt>
| String representation of the filter to apply in the search. You can specify simple filters with the following syntax: <tt>(</tt>''attributetype''<tt>=</tt>''attributevalue''<tt>)</tt>
|-
| <tt>attrs</tt>
| A <tt>NULL</tt> terminated array of attribute types to return from entries that match filter. If you specify a <tt>NULL</tt>, all attributes will be returned.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_search() operation.
 
'''Note:''' To check the result of this operation, call ldap_result and ldap_result2error().
 
See ldap_search_ext_s() for a list of possible result codes.
 
===== Description  =====
 
Please use the newer version of this function, ldap_search_ext() .
 
===== Example  =====
 
The following example searches a directory.
 
<br>
<pre>#include "examples.h"
 
static void do_other_work();
unsigned long global_counter = 0;
 
int
main( int argc, char **argv )
{
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i, rc, finished, msgid;
  int num_entries = 0;
  struct timeval zerotime;
 
  zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* authenticate to the directory as nobody */
if ( ldap_simple_bind_s( ld, NULL, NULL )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  return( 1 );
}
/* search for all entries with surname of Jensen */
if (( msgid = ldap_search( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE,
      MY_FILTER, NULL, 0 )) == -1 ) {
  ldap_perror( ld, "ldap_search" );
  return( 1 );
}
 
/* Loop, polling for results until finished */
finished = 0;
while (&nbsp;!finished ) {
  /*
  * Poll for results.  We call ldap_result with the "all" parameter
  * set to zero. This causes ldap_result() to return exactly one
  * entry if at least one entry is available. This allows us to
  * display the entries as they are received.
  */
  result = NULL;
  rc = ldap_result( ld, msgid, 0, zerotime, result );
  switch ( rc ) {
  case -1:
    /* some error occurred */
    ldap_perror( ld, "ldap_result" );
    return( 1 );
  case 0:
  /* Timeout was exceeded. No entries are ready for retrieval. */
    if ( result&nbsp;!= NULL ) {
      ldap_msgfree( result );
    }
    break;
  default:
  /*
  * Either an entry is ready for retrieval, or all entries have
  * been retrieved.
  */
    if (( e = ldap_first_entry( ld, result )) == NULL ) {
      /* All done */
      finished = 1;
      if ( result&nbsp;!= NULL ) {
        ldap_msgfree( result );
      }
      continue;
      }
    /* for each entry print out name + all attrs and values */
    num_entries++;
    if (( dn = ldap_get_dn( ld, e ))&nbsp;!= NULL ) {
      printf( "dn:&nbsp;%s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
    a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if (( vals = ldap_get_values( ld, e, a ))&nbsp;!= NULL ) {
        for ( i = 0; vals[ i ]&nbsp;!= NULL; i++ ) {
          printf( "%s:&nbsp;%s\n", a, vals[ i ] );
        }
      ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber&nbsp;!= NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
    ldap_msgfree( result );
  }
  /* Do other work here while you are waiting... */
  do_other_work();
}
 
/* All done. Print a summary. */
printf( "%d entries retrieved. I counted to&nbsp;%ld "
      "while waiting.\n", num_entries, global_counter );
ldap_unbind( ld );
return( 0 );
}
 
/*
* Perform other work while polling for results. */
static void
do_other_work()
{
    global_counter++;
}</pre>
===== See Also  =====
 
ldap_search_ext()
 
==== ldap_search_ext()  ====
 
The ldap_search_ext() function searches the directory asynchronously.
<pre>#include &lt;ldap.h&gt;
int ldap_search_ext( LDAP *ld, const char *base, int scope,
  const char *filter, char **attrs, int attrsonly,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct timeval *timeoutp, int sizelimit, int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_search_ext() Function Parameters"
|+ ldap_search_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>base</tt>
| DN of the entry that serves as the starting point for the search. For example, setting base to <tt>dc=example,dc=com</tt> restricts the search to entries at <tt>example.com</tt>.
|-
| <tt>scope</tt>
| Scope of the search, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> searches the entry specified by base.
*<tt>LDAP_SCOPE_ONELEVEL</tt> searches all entries one level beneath the entry specified by base.
*<tt>LDAP_SCOPE_SUBTREE</tt> searches the entry specified by base and all entries at all levels beneath the entry specified by base.
 
|-
| <tt>filter</tt>
| String representation of the filter to apply in the search. You can specify simple filters with the following syntax: <tt>(</tt>''attributetype''<tt>=</tt> ''attributevalue''<tt>)</tt>
|-
| <tt>attrs</tt>
| A <tt>NULL</tt> terminated array of attribute types to return from entries that match filter. If you specify a <tt>NULL</tt>, all attributes will be returned.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>timeoutp</tt>
| Pointer to a <tt>timeval</tt> structure specifying the maximum time to wait for the results of the search. Pass <tt>NULL</tt> to use the default time limit for the current connection. To specify an infinite time limit, set the <tt>tv_sec</tt> and <tt>tv_usec</tt> fields in the <tt>timeval</tt> structure to 0.
|-
| <tt>sizelimit</tt>
| Maximum number of results to return in the search. Pass <tt>-1</tt> to use the default size limit for the current connection.
|-
| <tt>msgidp</tt>
| Pointer to an integer that will be set to the message ID of the LDAP operation.
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the SASL bind request was sent successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
 
===== Description  =====
 
The ldap_search_ext() function searches the directory for matching entries. ldap_search_ext() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_search_ext_s() . You can also use this function to pass LDAP server controls to the server if you want the server to sort the results or if you want to request a persistent search. (See ldap_create_sort_control() and ldap_create_persistentsearch_control() for more information.) In order to get the results of the ldap_search_ext() operation, you need to call the ldap_result() and the ldap_parse_result() functions.
 
===== See Also  =====
 
ldap_search_ext_s(), ldap_result(), ldap_parse_result()
 
==== ldap_search_ext_s()  ====
 
The ldap_search_ext_s() function searches the directory synchronously.
 
'''Note:''' ldap_search_ext_s() is a new version of the ldap_search_s() function. If you are writing a new LDAP client, you should call ldap_search_ext_s().
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
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 *timeoutp, int sizelimit, LDAPMessage **res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_search_ext_s() Function Parameters"
|+ ldap_search_ext_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>base</tt>
| DN of the entry that serves as the starting point for the search. For example, setting base to <tt>dc=example,dc=com</tt> restricts the search to entries at <tt>example.com</tt>.
|-
| <tt>scope</tt>
| Scope of the search, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> searches the entry specified by base.
*<tt>LDAP_SCOPE_ONELEVEL</tt> searches all entries one level beneath the entry specified by base.
*<tt>LDAP_SCOPE_SUBTREE</tt> searches all entries at all levels beneath the entry specified by base.
 
|-
| <tt>filter</tt>
| String representation of the filter to apply in the search. You can specify simple filters with the following syntax: <tt>(</tt>''attributetype''<tt>=</tt>''attributevalue''<tt>)</tt>
|-
| <tt>attrs</tt>
| A <tt>NULL</tt> terminated array of attribute types to return from entries that match filter. If you specify a <tt>NULL</tt>, all attributes will be returned.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>timeoutp</tt>
| Pointer to a <tt>timeval</tt> structure specifying the maximum time to wait for the results of the search.
|-
| <tt>sizelimit</tt>
| Maximum number of results to return in the search.
|-
| <tt>res</tt>
| Results of the search (when the call is completed).
|}
 
===== Returns  =====
 
One of the following values:
*LDAP_SUCCESS if the SASL bind request was sent successfully.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_FILTER_ERROR if an error occurred when parsing and BER-encoding the search filter specified by the filter argument.
*LDAP_TIMEOUT if the search exceeded the time specified by the timeoutp argument.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
*LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
 
The ldap_search_ext_s() searches the directory for matching entries. The function ldap_search_ext_s() is synchronous; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_search_ext(). You can also use &lt;function&gt; ldap_search_ext_s&lt;/function&gt; to pass LDAP server controls to the server if you want the server to sort the results or if you want to request a persistent search. (See ldap_create_sort_control() and ldap_create_persistentsearch_control() for more information.)
 
===== See Also  =====
 
ldap_search_ext()
 
==== ldap_search_s()  ====
 
The ldap_search_s() function searches the directory synchronously. '''Note:''' This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_search_ext_s() instead.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_search_s( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly,
  LDAPMessage **res );</pre>
===== Parameters  =====
 
This function has the parameters listed in ldap_search_s() .
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_search_s() Function Parameters"
|+ ldap_search_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>base</tt>
| DN of the entry that serves as the starting point for the search. For example, setting base to <tt>dc=example,dc=com</tt> restricts the search to entries at <tt>example.com</tt>.
|-
| <tt>scope</tt>
| Scope of the search, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> searches the entry specified by base.
*<tt>LDAP_SCOPE_ONELEVEL</tt> searches all entries one level beneath the entry specified by base.
*<tt>LDAP_SCOPE_SUBTREE</tt> searches all entries at all levels beneath the entry specified by base.
 
|-
| <tt>filter</tt>
| String representation of the filter to apply in the search. You can specify simple filters with the following syntax: <pre>(attributetype=attributevalue)</pre>
|-
| <tt>attrs</tt>
| A <tt>NULL</tt> terminated array of attribute types to return from entries that match filter. If you specify a <tt>NULL</tt>, all attributes will be returned.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|-
| <tt>res</tt>
| Results of the search (when the call is completed).
|}
 
===== Returns  =====
 
For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s().
 
===== Description  =====
 
Use the newer version of this function, ldap_search_ext_s() .
 
===== Example  =====
 
The following example searches the directory for all people whose surname (last name) is <tt>Jensen</tt>.
<pre>#include "examples.h"
 
int main( int argc, char **argv )
{
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i;
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  /* authenticate to the directory as nobody */
  if ( ldap_simple_bind_s( ld, NULL, NULL )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_simple_bind_s" );
    return( 1 );
  }
  /* search for all entries with surname of Jensen */
  if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE,
    MY_FILTER, NULL, 0, result )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  }
  /* for each entry print out name + all attrs and values */
  for ( e = ldap_first_entry( ld, result ); e&nbsp;!= NULL;
  e = ldap_next_entry( ld, e ) ) {
    if ( (dn = ldap_get_dn( ld, e ))&nbsp;!= NULL ) {
      printf( "dn:&nbsp;%s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
    a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if ((vals = ldap_get_values( ld, e, a))&nbsp;!= NULL ) {
        for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
          printf( "%s:&nbsp;%s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber&nbsp;!= NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}</pre>
===== See Also  =====
 
ldap_search_ext_s()
 
==== ldap_search_st()  ====
 
The ldap_search_st() function searches the directory synchronously within a specified time limit.
<pre>#include &lt;ldap.h&gt;
int ldap_search_st( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly,
  struct timeval *timeout, LDAPMessage **res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_search_st() Function Parameters"
|+ ldap_search_st() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>base</tt>
| DN of the entry that serves as the starting point for the search. For example, setting base to <tt>dc=example,dc=com</tt> restricts the search to entries at <tt>example.com</tt>.
|-
| <tt>scope</tt>
| Scope of the search, which can be one of the following values:
*<tt>LDAP_SCOPE_BASE</tt> searches the entry specified by base.
*<tt>LDAP_SCOPE_ONELEVEL</tt> searches all entries one level beneath the entry specified by base.
*<tt>LDAP_SCOPE_SUBTREE</tt> searches all entries at all levels beneath the entry specified by base.
 
|-
| <tt>filter</tt>
| String representation of the filter to apply in the search. You can specify simple filters with the following syntax: <pre>(attributetype=attributevalue)</pre>
|-
| <tt>attrs</tt>
| A <tt>NULL</tt> terminated array of attribute types to return from entries that match filter. If you specify a <tt>NULL</tt>, all attributes will be returned.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*0 specifies that both attribute types and attribute values are returned.
*1 specifies that only attribute types are returned.
 
|-
| <tt>timeout</tt>
| Maximum time to wait for the results of the search.
|-
| <tt>res</tt>
| Results of the search (when the call is completed).
|}
 
===== Returns  =====
 
For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s().
 
===== Description  =====
 
Please use the newer version of this function, ldap_search_ext_s() .
 
===== See Also  =====
 
ldap_search_ext_s()
 
==== ldap_set_filter_additions()  ====
 
The ldap_set_filter_additions() function sets a prefix to be prepended and a suffix to be appended to all filters returned by the ldap_getfirstfilter() and ldap_getnextfilter() function calls.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix,
  char *suffix );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_set_filter_additions() Function Parameters"
|+ ldap_set_filter_additions() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>lfdp</tt>
| Pointer to an LDAPFiltDesc structure.
|-
| <tt>prefix</tt>
| Prefix to prepend to all filters. If <tt>NULL</tt>, no prefix is prepended.
|-
| <tt>suffix</tt>
| Suffix to append to all filters. If <tt>NULL</tt>, no suffix is appended.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*If unsuccessful, returns an LDAP error code.
 
===== Example  =====
 
The following example loads the filter configuration file named <tt>myfilters.conf</tt> into memory and adds the prefix <tt>"(&amp;(objectClass=person)"</tt> and the suffix <tt>")"</tt> to each filter retrieved.
<pre>#include &lt;ldap.h&gt;
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
char *prefix = "(&amp;(objectClass=person)";
char *suffix = ")";
int rc;
...
lfdp = ldap_init_getfilter( filter_file );
rc = ldap_set_filter_additions( ldfp, prefix, suffix );
if ( rc&nbsp;!= LDAP_SUCCESS ) {
  printf( "Error setting filter prefix and suffix\n");
  return( rc );
}
...</pre>
===== See Also  =====
 
ldap_getfirstfilter(), ldap_getnextfilter()
 
==== ldap_setfilteraffixes()  ====
 
'''Note:''' This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility. Use ldap_set_filter_additions() instead.
 
===== See Also  =====
 
ldap_set_filter_additions()
 
==== ldap_set_lderrno()  ====
 
The ldap_set_lderrno() function sets an error code and information about an error in an LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_set_lderrno( LDAP *ld, int e, char *m, char *s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_set_lderrno() Function Parameters"
|+ ldap_set_lderrno() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>e</tt>
| The error code that you want to set.
|-
| <tt>m</tt>
| In the event that an entry for a specified DN cannot be found, set this parameter to the portion of the DN that identifies an existing entry.
|-
| <tt>s</tt>
| The text of the error message that you want associated with this error code.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*If unsuccessful, returns an LDAP error code.
 
===== Description  =====
 
The ldap_set_lderrno() function sets an error code and information about an error in an LDAP structure. You can call this function to set error information that will be retrieved by subsequent ldap_get_lderrno() function calls.
 
===== Example  =====
 
The following example attempts to perform an operation. If the operation fails, the LDAP_PARAM_ERROR error code is placed in the LDAP structure.
<pre>#include &lt;ldap.h&gt;
int rc;
char *errmsg = "Invalid parameter";
...
if ( ldap_my_function()&nbsp;!= LDAP_SUCCESS ) {
  rc = ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
  if ( rc&nbsp;!= LDAP_SUCCESS ) {
    printf( "Error:&nbsp;%d\nError code could not be set.\n", rc );
  }
  return( rc );
}
...</pre>
===== See Also  =====
 
ldap_err2string(), ldap_perror, ldap_result2error()
 
==== ldap_set_option()  ====
 
The function ldap_set_option() sets session preferences in the LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_set_option( LDAP *ld, int option, const void *optdata );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_set_option() Function Parameters"
|+ ldap_set_option() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server. If NULL, you are setting the default options that will apply to any new LDAP connection handles that are subsequently created.
|-
| <tt>option</tt>
| Option that you want to set. See Table 21–182 for available options of this parameter.
|-
| <tt>optdata</tt>
| Pointer to the value of the option that you want to set. Available data types are also listed in the following table.
|}
 
The <tt>option</tt> parameter can have one of the values listed in the following table.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="Options for ldap_set_option()"
|+ Options for ldap_set_option()
|-
! scope="col" | Option
! scope="col" | Description
|-
| <tt>LDAP_OPT_API_FEATURE_INFO</tt>
| Retrieves information about the revision of a supported LDAP feature. This option is READ-ONLY and cannot be set. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPAPIFeatureInfo *)</tt>.
|-
| <tt>LDAP_OPT_API_INFO</tt>
| Retrieves information about the API implementation at execution time (API version, protocol version, the names of supported API extensions with their vendor name version, etc.). For details on the structure returned, refer to the <tt>ldap.h</tt> header file. This option is READ-ONLY and cannot be set. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPAPIInfo *)</tt>.
|-
| <tt>LDAP_OPT_CLIENT_CONTROLS</tt>
| Pointer to an array of LDAPControl structures representing the LDAP v3 client controls you want sent with every request by default. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPControl ***)</tt>.
|-
| <tt>LDAP_OPT_DESC</tt>
| Socket descriptor underlying the main LDAP connection. The <tt>LBER_SOCKET</tt> data type depends on the platform that you are using:
*<tt>int</tt> in UNIX.
*<tt>SOCKET</tt> in Windows. The data type for the <tt>optdata</tt> parameter is <tt>(LBER_SOCKET *)</tt>.
 
|-
| <tt>LDAP_OPT_DEREF</tt>
| Determines how aliases work during a search. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_DEREF_NEVER</tt> specifies that aliases are never dereferenced.
*<tt>LDAP_DEREF_SEARCHING</tt> specifies that aliases are dereferenced when searching under the base object (but not when finding the base object).
*<tt>LDAP_DEREF_FINDING</tt> specifies that aliases are dereferenced when finding the base object (but not when searching under the base object).
*<tt>LDAP_DEREF_ALWAYS</tt> specifies that aliases are always dereferenced when finding and searching under the base object. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_DNS_FN_PTRS</tt>
| DEPRECATED OPTION: Lets you use alternate DNS functions for getting the host entry of the LDAP server. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_dns_fns *)</tt>.
|-
| <tt>LDAP_OPT_ERROR_NUMBER</tt>
| Retrieves the result code for the most recent LDAP error that occurred in this session. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_ERROR_STRING</tt>
| Retrieves the error message returned with the result code for the most recent LDAP error that occurred in this session. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>.
|-
| <tt>LDAP_OPT_EXTRA_THREAD_FN_PTRS</tt>
| Lets you specify the locking and semaphore functions that you want called when getting results from the server. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_extra_thread_fns *)</tt>.
|-
| <tt>LDAP_OPT_HOST_NAME</tt>
| Sets the host name (or list of hosts) for the primary LDAP server. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>.
|-
| <tt>LDAP_OPT_IO_FN_PTRS</tt>
| DEPRECATED OPTION: Lets you use alternate communication stacks. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_io_fns *)</tt>.
|-
| <tt>LDAP_OPT_MATCHED_DN</tt>
| Gets the matched DN value returned with the most recent LDAP error that occurred for this session. The data type for the <tt>optdata</tt> parameter is <tt>(char **)</tt>
|-
| <tt>LDAP_OPT_MEMALLOC_FN_PTRS</tt>
| Gets a pointer to the callback structure which you previously set. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_memalloc_fnsldap_io_fns *)</tt>.
|-
| <tt>LDAP_OPT_PROTOCOL_VERSION</tt>
| Version of the protocol supported by your client. You can specify either <tt>LDAP_VERSION2</tt> or <tt>LDAP_VERSION3</tt>. If no version is set, the default is <tt>LDAP_VERSION2</tt>. In order to use LDAP v3 features, you need to set the protocol version to <tt>LDAP_VERSION3</tt>. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_REBIND_ARG</tt>
| Lets you set the last argument passed to the routine specified by <tt>LDAP_OPT_REBIND_FN</tt>. You can also set this option by calling the ldap_set_rebind_proc() function. The data type for the <tt>optdata</tt> parameter is <tt>(void *)</tt>.
|-
| <tt>LDAP_OPT_REBIND_FN</tt>
| Lets you set the routine to be called when you need to authenticate a connection with another LDAP server (for example, during the course of following a referral). You can also set this option by calling the ldap_set_rebind_proc function. The data type for the <tt>optdata</tt> parameter is <tt>(LDAP_REBINDPROC_CALLBACK *)</tt>.
|-
| <tt>LDAP_OPT_RECONNECT</tt>
| If the connection to the server is lost, determines whether or not the same connection handle should be used to reconnect to the server. By default, this option is off. To handle failover use following values: *<tt>LDAP_OPT_ON</tt> specifies that the same connection handle can be used to reconnect to the server. *<tt>LDAP_OPT_OFF</tt> specifies that you want to create a new connection handle to connect to the server. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_REFERRALS</tt>
| Determines whether or not the client should follow referrals. By default, the client follows referrals. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that the server should follow referrals.
*<tt>LDAP_OPT_OFF</tt> specifies that the server should not follow referrals. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_REFERRAL_HOP_LIMIT</tt>
| Maximum number of referrals the client should follow in a sequence. In other words, the client can only be referred this number of times before it gives up. By default, the maximum number of referrals that the client can follow in a sequence is 5 for the initial connection. This limit does not apply to individual requests that generate multiple referrals in parallel. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_RESTART</tt>
| Determines whether or not LDAP I/O operations should be restarted automatically if they are prematurely aborted. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that I/O operations should be restarted automatically.
*<tt>LDAP_OPT_OFF</tt> specifies that I/O operations should not be restarted automatically. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_SERVER_CONTROLS</tt>
| Pointer to an array of LDAPControl structures representing the LDAP v3 server controls you want sent with every request by default. Typically, since controls are specific to the type of request, you may want to pass the controls using operation-specific functions (such as ldap_add_ext()) instead. The data type for the <tt>optdata</tt> parameter is <tt>(LDAPControl ***)</tt>.
|-
| <tt>LDAP_OPT_SIZELIMIT</tt>
| Maximum number of entries that should be returned by the server in search results. The LDAP server may impose a smaller size limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_OPT_SSL</tt>
| Determines whether or not SSL is enabled. <tt>optdata</tt> can be one of the following values:
*<tt>LDAP_OPT_ON</tt> specifies that SSL is enabled.
*<tt>LDAP_OPT_OFF</tt> specifies that SSL is disabled. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
 
|-
| <tt>LDAP_OPT_THREAD_FN_PTRS</tt>
| Lets you specify the thread function pointers. The data type for the <tt>optdata</tt> parameter is <tt>(struct ldap_thread_fns *)</tt>.
|-
| <tt>LDAP_OPT_TIMELIMIT</tt>
| Maximum number of seconds that should be spent by the server when answering a search request. The LDAP server may impose a shorter time limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_X_OPT_EXTIO_FN_PTRS</tt>
| Extended I/O function callback option.
|-
| <tt>LDAP_X_OPT_CONNECT_TIMEOUT</tt>
| Value of a time out (expressed in milliseconds) for non-blocking connect call. The data type for the <tt>optdata</tt> parameter is <tt>(int *)</tt>.
|-
| <tt>LDAP_X_OPT_SOCKBUF</tt>
| Socket buffer structure associated to the LDAP connection.
|}
 
See also ldap_set_option() for details on <tt>LDAP_OPT_X_SASL*</tt> parameters.
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Example  =====
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
int max_ret = 100, max_tim = 30;
char *host = "ldap.sun.com";
...
/* Initialize a session with the LDAP server ldap.sun.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Set the maximum number of entries returned */
if ( ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &amp;max_ret)&nbsp;!
  LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldap_get_option()
 
==== ldap_set_rebind_proc()  ====
 
The ldap_set_rebind_proc() function sets a ''rebind'', which is called by your client to obtain authentication credentials when following a referral.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_set_rebind_proc( LDAP *ld,
  LDAP_REBINDPROC_CALLBACK *rebindproc, void *arg );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_set_rebind_proc() Function Parameters"
|+ ldap_set_rebind_proc() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>rebindproc</tt>
| Pointer to a function called back to obtain bind credentials when a new server is contacted during an LDAP referral.
|-
| <tt>arg</tt>
| Pointer to an additional argument that you want to pass to the rebind function.
|}
 
===== Description  =====
 
Call ldap_set_rebind_proc() to specify the rebind function. This rebind function is called by the LDAP client when following a referral to a new LDAP server. It is responsible for obtaining the credentials used to authenticate to the new server. For example, suppose LDAP server A sends a referral to your client. The referral points your client to LDAP server B. When automatically following the referral, your client calls the rebind function to obtain a DN and credentials; your client uses these to authenticate to server B. By default, if you do not call ldap_set_rebind_proc() or if you pass <tt>NULL</tt> for the <tt>rebindproc</tt> argument, your client authenticates anonymously when following referrals. The rebind function that you specify with ldap_set_rebind_proc() should have the following prototype:
 
<pre>int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp,
  char **passwdp, int *authmethodp, int freeit, void *arg );</pre>
 
#The LDAP server sends a referral back to the client.
#The client calls the rebind function, passing <tt>0</tt> as the <tt>freeit</tt> argument.
#The rebind function sets the <tt>dnp</tt>, <tt>passwdp</tt>, and <tt>authmethodp</tt> arguments to point to the following information:
#*The <tt>dnp</tt> argument is set to point to the DN to be used to authenticate to the new LDAP server.
#*The <tt>passwdp</tt> argument is set to point to the credentials for this DN.
#*The <tt>authmethodp</tt> argument is set to point to the method of authentication used (for example, <tt>LDAP_AUTH_SIMPLE</tt>).
#If successful, the rebind function returns LDAP_SUCCESS and referral processing continues. (If any other value is returned, referral processing stops, and that value is returned as the result code for the original LDAP request.)
#The client gets the DN, credentials, and authentication method from the arguments of the rebind function and uses this information to authenticate to the new LDAP server.
#The client calls the rebind function again, passing <tt>1</tt> as the <tt>freeit</tt> argument.
#The rebind function frees any memory allocated earlier to specify the DN and credentials.
 
You need to write a rebind function that does the following:
 
*If <tt>freeit</tt> is <tt>0</tt>, set the following pointers:
**Set <tt>dnp</tt> to point to the DN to be used for authentication.
**Set <tt>passwdp</tt> to point to the credentials to be used for authentication.
**Set <tt>authmethodp</tt> to point to the method of authentication used (for example, <tt>LDAP_AUTH_SIMPLE</tt>).
 
You can also make use of the <tt>arg</tt> argument, which is a pointer to the argument specified in the ldap_set_rebind_proc() function. If successful, returns LDAP_SUCCESS. Otherwise, returns the appropriate LDAP error code. If <tt>freeit</tt> is <tt>1</tt>, free any memory that you allocated to create the DN and credentials.
 
After you have defined this function, pass the function name to ldap_set_rebind_proc() to register your rebind function.
 
'''Note:''' In order to use the rebind function, the <tt>LDAP_OPT_REFERRALS</tt> option must be set to <tt>LDAP_OPT_ON</tt>, so that your client automatically follows referrals. This option is set to <tt>LDAP_OPT_ON</tt> by default.
 
===== Example  =====
 
The following example demonstrates how to write and register a rebind function.
<pre>#include "ldap.h"
...
/* Declare your rebind function */
int rebindproc( LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg );
...
int main( int argc, char **argv )
{
  LDAP *ld;
  /* Additional argument to be passed to the rebind function */
  char *testarg = "cn=admin,cn=Administrators,cn=config";
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( "directory.example.com", 389 )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  /* Specify the function used for reauthentication on referrals */
  ldap_set_rebind_proc( ld, rebindproc, (void *)testarg );
  /* Authenticate */
  if ( ldap_simple_bind_s( ld, "uid=bjensen,ou=People,dc=example,dc=com",
      "hifalutin" )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_simple_bind_s" );
    return( 1 );
  }
  ...
  /* Your code to interact with the LDAP server */
  ...
}
...
/* rebindproc is the rebind function responsible for providing the DN,
  credentials, and authentication method used for authenticating the
  client to other Directory Servers.
  The function should set the following arguments:
  - dnp should point to the DN that will be used for authentication.
  - passwdp should point to the credentials used for authentication.
  - authmethodp should point to the method of authentication to be used
  (for example, LDAP_AUTH_SIMPLE).
  The function should return LDAP_SUCCESS if successful or an LDAP
  error code if an error occurs.
  In order to demonstrate how the freeit argument works, this example
  uses strdup() to copy the DN and password.  You can also just copy
  string pointers if the DN and password are already available as
  global variables.
*/
int LDAP_CALL LDAP_CALLBACK rebindproc(
  LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg )
{
  printf( "Rebind function called.\n" );
  switch ( freeit ) {
  /* Your client calls the rebind function with freeit==1 when it needs
    to free any memory you've allocated. */
  case 1:
    printf( "\tFreeing memory.\n" );
    if ( dnp  *dnp ) {
      free( *dnp );
    }
    if ( passwdp  *passwdp ) {
      free( *passwdp );
    }
    break;
  /* Your client calls the rebind function with freeit==0 when it needs
  to get the DN, credentials, and authentication method. */
  case 0:
    printf( "\tGetting DN and credentials.\n" );
    *dnp = strdup( "uid=username,o=OtherServerSuffix" );
    *passwdp = strdup( "23skidoo" );
    *authmethodp = LDAP_AUTH_SIMPLE;
    break;
  default:
    printf( "\tUnknown value of freeit argument:&nbsp;%d\n", freeit );
    break;
  }
  /* If you successfully set the DN and credentials, you should return
    LDAP_SUCCESS.  (Any other return code will stop the client from
    automatically following the referral. */
  return LDAP_SUCCESS;
}</pre>
===== See Also  =====
 
ldap_simple_bind(), ldap_simple_bind_s()
 
==== ldap_simple_bind()  ====
 
The ldap_simple_bind() function synchronously authenticates your client to the LDAP server using a DN and a password.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_simple_bind(LDAP *ld, const char *who, const char *passwd);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_simple_bind() Function Parameters"
|+ ldap_simple_bind() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>who</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to <tt>NULL</tt>.
|-
| <tt>passwd</tt>
| Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to <tt>NULL</tt>.
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_simple_bind() operation. To check the result of this operation, call ldap_result() and ldap_result2error().
 
===== Description  =====
 
The ldap_simple_bind() function authenticates to the LDAP server. It verifies that the password supplied for authentication matches the <tt>userPassword</tt> attribute of the given entry. &lt;function&gt; ldap_simple_bind&lt;/function&gt; is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_simple_bind_s().
 
The following example calls ldap_simple_bind() to authenticate the user <tt>Barbara Jensen</tt> to the directory.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
char *host = "ldap.sun.com";
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
char *pw = "hifalutin";
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Initialize a session with the LDAP server ldap.example.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Attempt to bind with the LDAP server */
msgid = ldap_simple_bind( ld, dn, pw );
 
/* Initialize the value returned by ldap_result() */
rc = 0;
 
/* While the operation is still running, do this: */
while ( rc == 0 ) {
  ... /* do other work while waiting */...
 
  /* Check the status of the LDAP operation */
  rc = ldap_result( ld, msgid, NULL, zerotime, result );
  switch( rc ) {
    /* If -1 was returned, an error occurred */
    case -1:
      ldap_perror( ld, "Error in results: " );
      return( 1 );
    /* If 0 was returned, the operation is still in progress */
    case 0:
      continue;
    /* If any other value is returned, assume we are done */
    default:
      /* Check if the "bind" operation was successful */
      if ( ldap_result2error( result )&nbsp;!= LDAP_SUCCESS ) {
        ldap_perror( ld, "Error binding to server: " );
        return( 1 );
        }
  }
}
...</pre>
===== See Also  =====
 
ldap_simple_bind_s()
 
==== ldap_simple_bind_s()  ====
 
The ldap_simple_bind() function synchronously authenticates your client to the LDAP server using a DN and a password.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_simple_bind_s( LDAP *ld, const char *who, const char *passwd );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_simple_bind_s() Function Parameters"
|+ ldap_simple_bind_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>who</tt>
| DN of the user who wants to authenticate. For anonymous authentication, set this or the <tt>passwd</tt> argument to <tt>NULL</tt>.
|-
| <tt>passwd</tt>
| Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to <tt>NULL</tt>.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
*LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_simple_bind_s() function authenticates to the LDAP server. It verifies that the password supplied for authentication matches the <tt>userPassword</tt> attribute of the given entry. &lt;function&gt; ldap_simple_bind_s&lt;/function&gt; is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_simple_bind() instead.
 
The following example uses the synchronous ldap_simple_bind_s() function to authenticate to the directory as the user <tt>Barbara Jensen</tt>.
 
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
char *host = "ldap.sun.com";
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
char *pw = "hifalutin";
...
/* Initialize a session with the LDAP server ldap.sun.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Attempt to bind with the LDAP server */
if ( ldap_simple_bind_s( ld, dn, pw )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "Authentication failed: " );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_simple_bind()
 
==== ldap_sort_entries()  ====
 
The ldap_sort_entries() function sorts a chain of entries retrieved from an LDAP search call.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_sort_entries( LDAP *ld, LDAPMessage *chain, char *attr,
  LDAP_CMP_CALLBACK *cmp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_sort_entries() Function Parameters"
|+ ldap_sort_entries() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>chain</tt>
| Chain of entries returned by the ldap_result() or ldap_search_s() function.
|-
| <tt>attr</tt>
| Attribute to use when sorting the results. To sort by DN instead of by attribute, use <tt>NULL</tt>.
|-
| <tt>cmp</tt>
| Comparison function used when sorting the values.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*If unsuccessful, returns a <tt>NULL</tt> and sets the appropriate error code in the LDAP structure. To get the error code, call ldap_get_lderrno().
 
===== Description  =====
 
The ldap_sort_entries() function sorts a chain of entries retrieved from an LDAP search call (ldap_search_s() or ldap_result()) either by DN or a specified attribute in the entries.
 
===== Example  =====
 
The following example sorts entries by the <tt>roomNumber</tt> attribute.
<pre>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ldap.h&gt;
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *sortby = "roomNumber";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &amp;result )&nbsp;!=
  LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
/* Sort the results by room number, using strcasecmp */
if ( ldap_sort_entries( ld, &amp;result, sortby, strcasecmp )&nbsp;!=
  LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_multisort_entries(), ldap_result(), ldap_search_s(), LDAP_CMP_CALLBACK()
 
==== ldap_start_tls_s()  ====
 
The ldap_start_tls_s() initiates a Start Transport Layer Security (TLS) operation as defined in RFC 4513. Before using this function, call ldapssl_client_init(), ldapssl_clientauth_init(), or ldapssl_advclientauth_init() to initialize use of the certificate database.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldap_start_tls_s( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_start_tls_s() Function Parameters"
|+ ldap_start_tls_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>serverctrls</tt>
| List of LDAP server controls.
|-
| <tt>clientctrls</tt>
| List of client controls.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_OPERATIONS_ERROR if TLS has already been established.
*LDAP_PROTOCOL_ERROR if TLS is not supported.
*LDAP_REFERRAL if this server does not support TLS, but the server referred to may.
*LDAP_UNAVAILABLE if the server is shutting down, or supports TLS but cannot provide it at this time.
 
==== ldap_sort_strcasecmp()  ====
 
The ldap_sort_strcasecmp() routine compares two strings and ignores any differences in case when comparing uppercase and lowercase characters.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_sort_strcasecmp( const char **a, const char **b );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_sort_strcasecmp() Function Parameters"
|+ ldap_sort_strcasecmp() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>a</tt>
| Pointer to first string to compare
|-
| <tt>b</tt>
| Pointer to second string to compare
|}
 
===== Returns  =====
 
One of the following values:
 
*If <tt>a</tt> is greater than <tt>b</tt>, returns a value greater than <tt>0</tt>.
*If <tt>a</tt> is equal to <tt>b</tt>, returns <tt>0</tt>.
*If <tt>a</tt> is less than <tt>b</tt>, returns a value less than <tt>0</tt>.
 
===== Description  =====
 
The ldap_sort_strcasecmp() routine compares two strings and ignores any differences in case when comparing uppercase and lowercase characters. This function is similar to the C function strcasecmp(). When sorting attribute values with ldap_sort_strcasecmp(), call ldap_sort_strcasecmp() to compare the attribute values.
 
'''Note:''' This function works with ASCII values only. For UTF-8 data, the comparison result is unspecified.
 
===== See Also  =====
 
ldap_sort_strcasecmp(), LDAP_VALCMP_CALLBACK()
 
==== ldap_sort_values()  ====
 
The ldap_sort_values() function sorts an array of values retrieved from an ldap_get_values() call.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_sort_values( LDAP *ld, char **vals,
  LDAP_VALCMP_CALLBACK cmp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_sort_values() Function Parameters"
|+ ldap_sort_values() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>vals</tt>
| The array of values to sort.
|-
| <tt>cmp</tt>
| Comparison function used when sorting the values. In the ldap_sort_strcasecmp() function, the comparison function must pass <tt>char **</tt> parameters. Because of this, you need to use the ldap_sort_strcasecmp() function, rather than a function like strcasecmp().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*If unsuccessful, returns an LDAP error code.
 
===== Example  =====
 
The following example sorts the values of attributes before printing them.
<pre>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
if ( ( vals = ldap_get_values( ld, e, a ) )&nbsp;!= NULL ) {
  /* Sort the values of the attribute */
  if ( ldap_sort_values( ld, vals, strcasecmp ) )&nbsp;!= LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_sort_values" );
    return( 1 );
  }
  /* Print the values of the attribute */
  for ( i = 0; vals[i]&nbsp;!= NULL; i++ ) {
    printf( "%s:&nbsp;%s\n", a, vals[i] );
  }
  /* Free the values from memory */
  ldap_value_free( vals );
}
...</pre>
===== See Also  =====
 
ldap_get_values(), ldap_sort_strcasecmp, LDAP_VALCMP_CALLBACK().
 
==== ldapssl_advclientauth_init()  ====
 
The ldapssl_advclientauth_init() function initialize the secure parts (Security and SSL) of the runtime for use by a client application that may want to do SSL client authentication.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int LDAP_CALL ldapssl_advclientauth_init( char *certdbpath,
  void *certdbhandle, int needkeydb, char *keydbpath,
  void *keydbhandle, int needsecmoddb, char *secmodpath,
  const int sslstrength);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_advclientauth_init() Function Parameters"
|+ ldapssl_advclientauth_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>certdbpath</tt>
| Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, <tt>/usr/mozilla/</tt> ''cert_file_name''<tt>.db</tt>).
|-
| <tt>certdbhandle</tt>
| Pass a <tt>NULL</tt> value for this. (This parameter is not currently used.)
|-
| <tt>needkeydb</tt>
| Specifies whether or not the private key database needs to be opened for use. This parameter can have one of the following values:
*If it is a non-zero value, the function opens the private key database, which is identified by the <tt>keydbpath</tt> argument.
*If <tt>0</tt>, the function does not open the private key database.
 
|-
| <tt>keydbpath</tt>
| Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, <tt>/usr/mozilla/</tt>''key_file_name''<tt>.db</tt>).
|-
| <tt>needsecmoddb</tt>
| Specifies whether or not the security module database file needs to be opened for use. This parameter can have one of the following values:
*If it is a non-zero value, the function opens the security module database, which is identified by the <tt>keydbpath</tt> argument.
*If <tt>0</tt>, the function does not open the security modules database.
 
|-
| <tt>secmodpath</tt>
| Path to the database containing security modules. You can include the database filename in the path (for example, <tt>/usr/mozilla/</tt>''secmod_file_name'' <tt>.db</tt>).
|-
| <tt>sslstrength</tt>
| Specifies how the server certificate is evaluated. It takes one of the following:
*<tt>LDAPSSL_AUTH_WEAK</tt> indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
*<tt>LDAPSSL_AUTH_CERT</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
*<tt>LDAPSSL_AUTH_CNCHECK</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the <tt>cn</tt> attribute is the DNS hostname of the server. If this option is selected, ensure that the <tt>defhost</tt> parameter passed to ldapssl_init() consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the <tt>defport</tt> parameter, and cannot be passed via a ''host'':''port'' option.
 
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Description  =====
 
You can call ldapssl_advclientauth_init() to initialize your client application for SSL and certificate-based client authentication. This function is similar to ldapssl_clientauth_init() and allows you to:
 
*Specify the name and path of a security module database.
*Specify the method used to verify the server’s certificate.
 
'''Note:''' You must call ldapssl_advclientauth_init() before calling ldapssl_init() to connect to the server.
 
===== Example  =====
 
The following example initializes a client before connecting with a secure LDAP server.
<pre>#include &lt;ldap.h&gt;
#include &lt;ldap_ssl.h&gt;
#include &lt;stdio.h&gt;
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_advclientauth_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db",
  NULL, 1, "/u/mozilla/.netscape/
  ''key_file_name''.db", NULL , 1,
  "/u/mozilla/.netscape/
  ''secmod_file_name''.db", LDAPSSL_AUTH_CNCHECK) &lt; 0 ) {
  perror( "ldap_advclientauth_init" );
  return( 1 );
  }
}
...</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldapssl_clientauth_init(), ldapssl_init(), ldapssl_install_routines()
 
==== ldapssl_client_init()  ====
 
The ldapssl_client_init() function initializes the secure parts (Security and SSL) of the runtime for use by your client application to connect to a secure LDAP server over SSL.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldapssl_client_init( const char *certdbpath, void *certdbhandle );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_client_init() Function Parameters"
|+ ldapssl_client_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>certdbpath</tt>
| Specifies the path to the database containing certificates for your client.
|-
| <tt>certdbhandle</tt>
| Pass a <tt>NULL</tt> value for this. (This parameter is not used currently.)
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Description  =====
 
You can call the ldapssl_client_init() function to initialize your client application for SSL. It is only called once and returns <tt>0</tt> if all goes well. If you plan to use certificate-based authentication, you should call either the ldapssl_clientauth_init() or the ldapssl_advclientauth_init() function.
 
The following example initializes a client before connecting with a secure LDAP server.
 
<pre>#include &lt;ldap.h&gt;
#include &lt;ldap_ssl.h&gt;
#include &lt;stdio.h&gt;
 
... /* Initialize client using a certificate database copied from Directory Server. */
if ( ldapssl_client_init( "/local/client/alias/", NULL ) &lt; 0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}</pre>
 
The certdbpath is a path to the file system directory containing the certificate database files. For example:
 
<pre>$ ls /local/client/alias/*.db
/local/client/alias/cert8.db
/local/client/alias/key3.db
/local/client/alias/secmod.db
$</pre>
===== See Also  =====
 
ldap_start_tls_s(), ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines()
 
==== ldapssl_clientauth_init()  ====
 
The ldapssl_clientauth_init() function initializes your client application to connect to a secure LDAP server over SSL and to use certificate-based client authentication.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldapssl_clientauth_init( char *certdbpath, void *certdbhandle,
  int needkeydb, char *keydbpath, void *keydbhandle );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_clientauth_init() Function Parameters"
|+ ldapssl_clientauth_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>certdbpath</tt>
| Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, <tt>/usr/mozilla/</tt> ''cert_file_name''<tt>.db</tt>).
|-
| <tt>needkeydb</tt>
| Specifies whether or not the private key database needs to be opened for use. This parameter can have one of the following values:
*If it is a non-zero value, the function opens the private key database, which is identified by the keydbpath argument.
*If <tt>0</tt>, the function does not open the private key database.
 
|-
| <tt>keydbpath</tt>
| Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, /usr/mozilla/ ''key_file_name''.db).
|-
| <tt>certdbhandle</tt>
| Pass a <tt>NULL</tt> value for this. (This parameter is not currently used.)
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Description  =====
 
You can call the ldapssl_clientauth_init() function to initialize your client application for SSL and certificate-based client authentication. However, if you need to specify the name and path of the security modules database or if you need to specify how the server’s certificate will be verified, you should call the ldapssl_advclientauth_init() function instead.
 
'''Note:''' You must call ldapssl_clientauth_init() before calling ldapssl_init() to connect to the server.
 
===== Example  =====
 
The following example initializes a client before connecting with a secure LDAP server.
<pre>#include &lt;ldap.h&gt;
#include &lt;ldap_ssl.h&gt;
#include &lt;stdio.h&gt;
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_clientauth_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL, 1,
  "/u/mozilla/.netscape/
  ''key_file_name''.db", NULL ) &lt; 0 ) {
  perror( "ldap_clientauth_init" );
  return( 1 );
  }
}
...</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines()
 
==== ldapssl_enable_clientauth()  ====
 
The ldapssl_enable_clientauth() function enables SSL client authentication on the given connection (passed using the <tt>ld</tt> parameter).
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
  char *keypasswd, char *certnickname );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_enable_clientauth() Function Parameters"
|+ ldapssl_enable_clientauth() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>keynickname</tt>
| Pass an empty string, <tt>""</tt>, for this value. (This parameter is not currently used.)
|-
| <tt>keypasswd</tt>
| Password to the encrypted private key database.
|-
| <tt>certnickname</tt>
| Nickname of the certificate that you want to use for client authentication.
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== See Also  =====
 
ldapssl_clientauth_init()
 
==== ldapssl_err2string()  ====
 
The ldapssl_err2string() function returns the corresponding error message for an SSL-specific error code.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
const char * LDAP_CALL ldapssl_err2string ( const int prerrno );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_err2string() Function Parameters"
|+ ldapssl_err2string() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>prerrno</tt>
| The SSL error code that you want interpreted into an error message.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns the corresponding error message for the given error code.
*If unsuccessful (for example, if the error code is not a known SSL error code), returns a pointer to the string <tt>Unknown error.</tt>
 
===== Description  =====
 
ldapssl_err2string() provides support for SSL-specific error messages that are not covered by the regular message routine ldap_err2string(). If any ldapssl_*() function returns an error code that is unknown to ldap_err2string()–it returns <tt>Unknown error</tt>– this function should be called to determine the SSL-specific error message. To check for SSL errors, call ldapssl_err2string() after you call any of the following SSL initialization functions:
 
*ldapssl_client_init()
*ldapssl_clientauth_init()
*ldapssl_advclientauth_init()
*ldapssl_pkcs_init()
 
The errors returned by these functions are usually related to certificate database corruption, missing certificates in a certificate database, client authentication failures, and other general SSL errors.
 
===== See Also  =====
 
ldapssl_client_init(), ldapssl_clientauth_init(), ldapssl_advclientauth_init(), ldapssl_pkcs_init(), ldap_err2string()
 
==== ldapssl_init()  ====
 
The ldapssl_init() function initializes the LDAP library for SSL and installs the I/O routines for SSL.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
LDAP *ldapssl_init( const char *defhost, int defport, int defsecure );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_init() Function Parameters"
|+ ldapssl_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>defhost</tt>
| Connect to this LDAP server, if no other server is specified.
|-
| <tt>defport</tt>
| Connect to this server port, if no other port is specified. To specify the default port 389, use <tt>LDAP_PORT</tt> as the value for this parameter.
|-
| <tt>defsecure</tt>
| Determines whether or not to establish the default connection over SSL. Set this to a non-zero value to establish the default connection over SSL.
|}
 
===== Returns  =====
 
One of the following values:
 
*If successful, returns a pointer to an LDAP() structure, which should be passed to subsequent calls to other LDAP API functions.
*If unsuccessful, returns -1.
 
===== Description  =====
 
ldapssl_init() allocates an LDAP() structure but does not open an initial connection. Before calling this function, call ldapssl_client_init() to initialize your client for SSL.
 
The following example connects your client to a secure LDAP server.
 
<pre>#include &lt;ldap.h&gt;
#include &lt;ldap_ssl.h&gt;
#include &lt;stdio.h&gt;
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_client_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL ) &lt; 0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* get a handle to an LDAP connection */
if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL {
  perror( "ldapssl_init" );
  return( 1 );
}
...
/* Client can now perform LDAP operations on the secure LDAP server */
...</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldapssl_client_init(), ldapssl_install_routines()
 
==== ldapssl_install_routines()  ====
 
The ldapssl_install_routines() function installs the I/O routines that enable SSL over LDAP.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldapssl_install_routines( LDAP *ld );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_install_routines() Function Parameter"
|+ ldapssl_install_routines() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Description  =====
 
You need to call ldapssl_install_routines() in combination with ldap_init() or prldap_init() (IPv6) and ldap_set_option(). As an alternative, you can call ldapssl_init() rather than these three functions.
 
'''Note:''' As is the case with the ldapssl_init() function, you need to call ldapssl_client_init() to initialize your client for SSL before calling ldapssl_install_routines().
 
===== Example  =====
 
The following example connects your client to a secure LDAP server.
<pre>#include &lt;ldap.h&gt;
#include &lt;ldap_ssl.h&gt;
#include &lt;stdio.h&gt;
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_client_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL ) &lt; 0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* Get the handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, 636 )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Load SSL routines */
if ( ldapssl_install_routines( ld )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldapssl_install_routines" );
  return( 1 );
}
/* Set the option to use SSL with the default connection */
if (ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON )&nbsp;!= LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_client_init()
 
==== ldapssl_pkcs_init()  ====
<pre>int ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns);</pre>
===== Description  =====
 
The ldap_pkcs_init() structure sets up callbacks for the security library to obtain required runtime information. It should be used in place of ldapssl_client_init(), ldapssl_clientauth_init(), and ldapssl_advclientauth_init().
 
'''Note:''' The Directory SDK For C uses the Public Key Cryptography Standard (PKCS) API implemented in Network Security Services (NSS) to provide SSL security support. Specifically, NSS implements the security API as defined in the PKCS#11 standard.
 
Because ldap_pkcs_init() is based on the <tt>ldapssl_pkcs_fns</tt> structure, you do not need to know all of the security parameters at initialization, unlike the other SSL initialization functions (ldapssl_*_init()), which require all security parameters to be known at the time of initialization. The following example defines the <tt>ldapssl_pkcs_fns</tt> structure.
<pre>typedef int (LDAP_PKCS_GET_TOKEN_CALLBACK)
  (void *context, char **tokenname);
typedef int (LDAP_PKCS_GET_PIN_CALLBACK)
  (void *context, const char *tokenname, char **tokenpin);
typedef int (LDAP_PKCS_GET_CERTPATH_CALLBACK)
  (void *context, char **certpath);
typedef int (LDAP_PKCS_GET_KEYPATH_CALLBACK)(void *context,
  char **keypath);
typedef int (LDAP_PKCS_GET_MODPATH_CALLBACK)
  (void *context, char **modulepath);
typedef int (LDAP_PKCS_GET_CERTNAME_CALLBACK)
  (void *context, char **certname);
typedef int (LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK)
  (void *context, char **filename);
#define PKCS_STRUCTURE_ID 1
struct ldapssl_pkcs_fns {
  int local_structure_id;
  void *local_data;
  LDAP_PKCS_GET_CERTPATH_CALLBACK *pkcs_getcertpath;
  LDAP_PKCS_GET_CERTNAME_CALLBACK *pkcs_getcertname;
  LDAP_PKCS_GET_KEYPATH_CALLBACK *pkcs_getkeypath;
  LDAP_PKCS_GET_MODPATH_CALLBACK *pkcs_getmodpath;
  LDAP_PKCS_GET_PIN_CALLBACK *pkcs_getpin;
  LDAP_PKCS_GET_TOKEN_CALLBACK *pkcs_gettokenname;
  LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK *pkcs_getdonglefilename;
};</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_pkcs_init() Function Parameters"
|+ ldapssl_pkcs_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>pfns</tt>
| Specifies the <tt>ldap_pkcs_fns</tt> structure for initialization.
|}
 
===== Returns  =====
 
One of the following values:
 
*0 is successful.
*-1 if unsuccessful.
*''n'' (a positive integer) denotes a Netscape Portable Runtime (NSPR) error as returned by the PR_GetError() NSPR function.
 
===== See Also  =====
 
ldapssl_client_init(), ldapssl_clientauth_init(), ldapssl_advclientauth_init()
 
==== ldapssl_serverauth_init()  ====
 
The ldapssl_serverauth_init() function is a server-authentication only version of ldapssl_clientauth_init().
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int ldapssl_serverauth_init(
  const char *certdbpath, void *certdbhandle, const int sslstrength );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_serverauth_init() Function Parameters"
|+ ldapssl_serverauth_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>certdbpath</tt>
| Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db).
|-
| <tt>certdbhandle</tt>
| Pass a <tt>NULL</tt> value for this. (This parameter is not currently used.)
|-
| <tt>sslstrength</tt>
| Specifies how the server certificate is evaluated. It takes one of the following:
*<tt>LDAPSSL_AUTH_WEAK</tt> indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
*<tt>LDAPSSL_AUTH_CERT</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
*<tt>LDAPSSL_AUTH_CNCHECK</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the <tt>cn</tt> attribute is the DNS hostname of the server. If this option is selected, please ensure that the <tt>defhost</tt> parameter passed to ldapssl_init consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the <tt>defport</tt> parameter, and cannot be passed via a ''host'':''port'' option.
 
|}
 
===== Returns  =====
 
One of the following values:
 
*<tt>0</tt> if successful.
*<tt>-1</tt> if unsuccessful.
 
===== Description  =====
 
ldapssl_serverauth_init() is a server-authentication only version of ldapssl_clientauth_init(). This function allows the <tt>sslstrength</tt> parameter to be passed in.
 
===== See Also  =====
 
ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines(), ldapssl_clientauth_init()
 
==== ldapssl_set_strength()  ====
 
The ldapssl_set_strength() sets the SSL strength for an existing SSL-enabled LDAP session handle.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
int LDAP_CALL ldapssl_set_strength( LDAP *ld, int sslstrength );</pre>
===== Parameters  =====
 
'''Note:''' See the description of the <tt>sslstrength</tt> value and note the potential problems that can be caused by passing in wrong host and port name values.
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_set_strength() Function Parameters"
|+ ldapssl_set_strength() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server. If value is <tt>NULL</tt>, the default for the new LDAP session handles is set.
|-
| <tt>sslstrength</tt>
| Specifies how the server certificate is evaluated. It takes one of the following:
*<tt>LDAPSSL_AUTH_WEAK</tt> indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
*<tt>LDAPSSL_AUTH_CERT</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
*<tt>LDAPSSL_AUTH_CNCHECK</tt> indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the <tt>cn</tt> attribute is the DNS hostname of the server. If this option is selected, please ensure that the <tt>defhost</tt> parameter passed to ldapssl_init consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the <tt>defport</tt> parameter, and cannot be passed via a ''host'':''port'' option.
 
|}
 
==== ldapssl_tls_start_s()  ====
 
The ldapssl_tls_start_s() function starts an SSL handshake on a previously established non-secure connection.
 
===== Syntax  =====
<pre>#include &lt;ldap_ssl.h&gt;
LDAP_API(int)  LDAP_CALL ldapssl_tls_start_s( LDAP *ld, int defsecure,
  char *certdbpath, char *keydbpath, char ***referralsp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldapssl_tls_start_s() Function Parameter"
|+ ldapssl_tls_start_s() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>defsecure</tt>
| Determines whether or not to establish the default connection over SSL. Set this to a non-zero value to establish the default connection over SSL.
|-
| <tt>certdbpath</tt>
| Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db).
|-
| <tt>keydbpath</tt>
| Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, <tt>/usr/mozilla/</tt>''key_file_name''<tt>.db</tt>).
|-
| <tt>referralsp</tt>
| Pointer to an array of strings representing the referrals found by an LDAP search operation and returned by the server (applicable only if the LDAP operation was a search operation). When done, you can free this by calling the ldap_value_free() function.
|}
 
===== Description  =====
 
The ldapssl_tls_start_s() function starts an SSL handshake on a previously established non-secure connection.
 
==== ldap_str2charray()  ====
 
This function is deprecated and should not be used. It is included in <tt>ldap-deprecated.h</tt> for backward-compatibility.
 
===== ldap_tmplattrs()  =====
 
The ldap_tmplattrs() function obtains a pointer to the correct <tt>ldap_disptmpl</tt> structure.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
char ** ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
  int exclude, unsigned long syntaxmask );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_tmplattrs() Function Parameters"
|+ ldap_tmplattrs() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>tmpl</tt>
| The name of the template to be retrieved.
|-
| <tt>includeattrs</tt>
| A null terminated array of attributes that should always be included (it may be <tt>NULL</tt> if no extra attributes are required).
|-
| <tt>exclude</tt>
| If <tt>0</tt>, only attributes where the logical AND of the template item syntax id and the syntaxmask is non-zero are included. If non-zero, attributes where the logical AND of the template item syntax id and the syntaxmask is non-zero are excluded.
|-
| <tt>syntaxmask</tt>
| When non-zero, it is used to restrict the attribute set returned.
|}
 
===== Returns  =====
 
*<tt>A NULL</tt> terminated array that contains the
 
names of attributes that need to be retrieved if the template, defined by <tt>tmpl</tt> , is to be used to display an entry.
 
*A <tt>NULL</tt> pointer on error.
 
===== Description  =====
 
The attribute list should be freed using ldap_value_free() .
 
===== See Also  =====
 
ldap_value_free()
 
==== ldap_tmplerr2string()  ====
 
The ldap_templerr2string() function returns a string representation of the error passed in the parameter.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
char * ldap_tmplerr2string( int err );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_tmplerr2string() Function Parameter"
|+ ldap_tmplerr2string() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>err</tt>
| Error returned.
|}
 
==== ldap_ufn_search_c()  ====
 
'''Note:''' This function will be deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
==== ldap_ufn_search_s()  ====
 
'''Note:''' This function will be deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
==== ldap_ufn_setprefix()  ====
 
'''Note:''' This function will be deprecated and should not be used. It is included in <tt>ldap-to-be-deprecated.h</tt> for backward-compatibility.
 
==== ldap_unbind()  ====
 
The ldap_unbind() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_unbind( LDAP *ld );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_unbind() Function Parameter"
|+ ldap_unbind() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|}
 
===== Returns  =====
 
For a list of possible results for an LDAP unbind operation, see ldap_unbind_s().
 
===== Description  =====
 
The ldap_unbind() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions (ldap_unbind() , ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.
 
The following example closes the current connection with the LDAP server.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
...
/* After completing your LDAP operations with the server, close the
connection. */
if ( ldap_unbind( ld )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "Error while unbinding from the directory" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_unbind_s(), ldap_unbind_ext()
 
==== ldap_unbind_s()  ====
 
The ldap_unbind_s() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_unbind_s( LDAP *ld );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_unbind_s() Function Parameter"
|+ ldap_unbind_s() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
===== Description  =====
 
The ldap_unbind_s() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions ( ldap_unbind(), ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.
 
'''Note:''' There is no server response to an LDAP unbind operation. All three of the unbind functions return LDAP_SUCCESS (or another LDAP error code if the request cannot be sent to the LDAP server). After a call to one of the unbind functions, the session handle <tt>ld</tt> is invalid and it is illegal to make any further calls using it.
 
===== Example  =====
 
The following example closes the current connection with the LDAP server.
<pre>#include &lt;ldap.h&gt;
...
LDAP *ld;
...
/* After completing your LDAP operations with the server, close the
connection. */
if ( ldap_unbind_s( ld )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "Error while unbinding from the directory" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_unbind(), ldap_unbind_ext()
 
==== ldap_unbind_ext()  ====
 
The ldap_unbind_ext() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_unbind_ext() Function Parameters"
|+ ldap_unbind_ext() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>serverctrls</tt>
| List of LDAP server controls.
|-
| <tt>clientctrls</tt>
| List of client controls.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
===== Description  =====
 
The ldap_unbind_ext() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions (ldap_unbind(), ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.
 
See also ldap_unbind(), ldap_unbind_s()
 
==== ldap_url_parse()  ====
 
The ldap_url_parse() function parses an LDAP URL into its components.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_url_parse( const char *url, LDAPURLDesc **ludpp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_url_parse() Function Parameters"
|+ ldap_url_parse() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>url</tt>
| The URL that you want to check.
|-
| <tt>ludpp</tt>
| Pointer to a structure containing the components of the URL.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*<tt>LDAP_URL_ERR_NOTLDAP</tt> if the URL does not begin with the <tt>ldap://</tt> or <tt>ldaps:// prefix</tt>.
*<tt>LDAP_URL_ERR_NODN</tt> if the URL missing trailing slash after host or port.
*<tt>LDAP_URL_ERR_BADSCOPE</tt> if the scope within the URL is invalid.
*<tt>LDAP_URL_ERR_MEM</tt> if not enough free memory  is available for this operation.
*<tt>LDAP_URL_ERR_PARAM</tt> if an invalid argument was passed to the function.
 
===== Example  =====
 
The following example parses an LDAP URL and prints out each component of it.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?
                cn,mail,telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) )&nbsp;!= 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL missing trailing slash after host or port\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "Components of the URL:\n" );
printf( "Host name:&nbsp;%s\n", ludpp-&gt;lud_host );
printf( "Port number:&nbsp;%d\n", ludpp-&gt;lud_port );
if ( ludpp-&gt;lud_dn&nbsp;!= NULL ) {
  printf( "Base entry:&nbsp;%s\n", ludpp-&gt;lud_dn );
} else {
  printf( "Base entry: Root DN\n" );
}
if ( ludpp-&gt;lud_attrs&nbsp;!= NULL ) {
  printf( "Attributes returned: \n" );
  for ( i=0; ludpp-&gt;lud_attrs[i]&nbsp;!= NULL; i++ ) {
    printf( "\t%s\n", ludpp-&gt;lud_attrs[i] );
}
} else {
        printf( "No attributes returned.\n" );
}
printf( "Scope of the search: " );
switch( ludpp-&gt;lud_scope ) {
  case LDAP_SCOPE_BASE:
    printf( "base\n" );
    break;
  case LDAP_SCOPE_ONELEVEL:
    printf( "one\n" );
    break;
  case LDAP_SCOPE_SUBTREE:
    printf( "sub\n" );
    break;
  default:
    printf( "Unknown scope\n" );
}
printf( "Filter:&nbsp;%s\n", ludpp-&gt;lud_filter );
...</pre>
===== See Also  =====
 
ldap_free_urldesc()
 
==== ldap_url_parse_no_defaults()  ====
 
The ldap_url_parse_no_defaults() function parses an LDAP URL into its components.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_url_parse_no_defaults( const char *url, LDAPURLDesc **ludpp,
  int dn_required );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_url_parse_no_defaults() Function Parameters"
|+ ldap_url_parse_no_defaults() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>url</tt>
| The URL that you want to check.
|-
| <tt>ludpp</tt>
| Pointer to a structure containing the components of the URL.
|-
| <tt>dn_required</tt>
| Specifies if a DN must be present in the URL. Set to <tt>0</tt>, the DN is not required. Set to <tt>1</tt>, the function will return an error <tt>LDAP_URL_ERR_NODN</tt> if no DN is present.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*<tt>LDAP_URL_ERR_NODN</tt> if a required DN is not present.
*<tt>LDAP_URL_ERR_NOTLDAP</tt> if the URL does not begin with the ldap:// or ldaps:// prefix.
*<tt>LDAP_URL_ERR_NODN</tt> if the URL missing trailing  slash after host or port. 
*<tt>LDAP_URL_ERR_BADSCOPE</tt> if the scope within the URL is invalid.
*<tt>LDAP_URL_ERR_MEM</tt> if not enough free memory is available for this operation.
*<tt>LDAP_URL_ERR_PARAM</tt> if an invalid argument was passed to the function.
 
===== Description  =====
 
The ldap_url_parse_no_defaults() function does not set any default value in the fields that would be absent from the URL (for example, the port number).
 
==== ldap_url_search()  ====
 
The ldap_url_search() function searches the directory asynchronously for matching entries, based on the contents of the URL.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_url_search( LDAP *ld, const char *url, int attrsonly );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_url_search() Function Parameters"
|+ ldap_url_search() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>url</tt>
| LDAP URL specifying a search of the directory.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|}
 
===== Returns  =====
 
Returns the message ID of the ldap_url_search() operation. To check the result of this operation, call ldap_result() and ldap_result2error().
 
===== Description  =====
 
ldap_url_search() searches the directory for matching entries, based on the contents of the URL. ldap_url_search() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_url_search_s().
 
===== Example  =====
 
The following example returns the message ID.
<pre>#include "examples.h"
 
static void do_other_work();
unsigned long global_counter = 0;
 
int
main( int argc, char **argv )
{
  char *my_url = "ldap://ldap.example.com/dc=example,dc=com?
                  cn,mail,telephoneNumber?sub?(sn=Jensen)";
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i, rc, finished, msgid;
  int num_entries = 0;
  struct timeval zerotime;
 
  zerotime.tv_sec = zerotime.tv_usec = 0L;
 
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* authenticate to the directory as nobody */
if ( ldap_simple_bind_s( ld, NULL, NULL )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  return( 1 );
}
/* search for all entries with surname of Jensen */
if (( msgid = ldap_url_search( ld, my_url, 0 )) == -1 ) {
  ldap_perror( ld, "ldap_url_search" );
  return( 1 );
}
 
/* Loop, polling for results until finished */
finished = 0;
while (&nbsp;!finished ) {
  /*
  * Poll for results.  We call ldap_result with the "all" parameter
  * set to zero. This causes ldap_result() to return exactly one
  * entry if at least one entry is available. This allows us to
  * display the entries as they are received.
  */
  result = NULL;
  rc = ldap_result( ld, msgid, 0, zerotime, result );
  switch ( rc ) {
  case -1:
    /* some error occurred */
    ldap_perror( ld, "ldap_result" );
    return( 1 );
  case 0:
  /* Timeout was exceeded. No entries are ready for retrieval. */
    if ( result&nbsp;!= NULL ) {
      ldap_msgfree( result );
    }
    break;
  default:
  /*
  * Either an entry is ready for retrieval, or all entries have
  * been retrieved.
  */
    if (( e = ldap_first_entry( ld, result )) == NULL ) {
      /* All done */
      finished = 1;
      if ( result&nbsp;!= NULL ) {
        ldap_msgfree( result );
      }
      continue;
      }
    /* for each entry print out name + all attrs and values */
    num_entries++;
    if (( dn = ldap_get_dn( ld, e ))&nbsp;!= NULL ) {
      printf( "dn:&nbsp;%s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
    a&nbsp;!= NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if (( vals = ldap_get_values( ld, e, a ))&nbsp;!= NULL ) {
        for ( i = 0; vals[ i ]&nbsp;!= NULL; i++ ) {
          printf( "%s:&nbsp;%s\n", a, vals[ i ] );
        }
      ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber&nbsp;!= NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
    ldap_msgfree( result );
  }
  /* Do other work here while you are waiting... */
  do_other_work();
}
 
/* All done. Print a summary. */
printf( "%d entries retrieved. I counted to&nbsp;%ld "
      "while I was waiting.\n", num_entries,
      global_counter );
ldap_unbind( ld );
return( 0 );
}
 
/*
* Perform other work while polling for results. */
static void
do_other_work()
{
    global_counter++;
}</pre>
===== See Also  =====
 
ldap_url_search_s(), ldap_result(), ldap_result2error()
 
==== ldap_url_search_s()  ====
 
The ldap_url_search_s() function searches the directory synchronously for matching entries, based on the contents of the URL.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_url_search_s( LDAP *ld, const char *url,
  int attrsonly, LDAPMessage **res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_url_search_s() Function Parameters"
|+ ldap_url_search_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>url</tt>
| LDAP URL specifying a search of the directory.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|-
| <tt>res</tt>
| Results of the search (when the call is completed).
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*If unsuccessful, returns the LDAP error code for the operation.
 
===== Description  =====
 
The ldap_url_search_s() function searches the directory for matching entries, based on the contents of the URL. ldap_url_search_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_url_search().
 
===== Example  =====
 
The following example processes a search request from an LDAP URL.
<pre>#include &lt;stdio.h&gt;
#include &lt;ldap.h&gt;
...
LDAP *ld;
LDAPMessage *result;
char *my_url = "ldap://ldap.example.com/dc=example,dc=com?
cn,mail,telephoneNumber?sub?(sn=Jensen)";
...
/* Process the search request in the URL */
if ( ldap_url_search_s( ld, my_url, 0, &amp;result )&nbsp;!= LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_url_search_s" );
  return( 1 );
}
...</pre>
===== See Also  =====
 
ldap_search(), ldap_search_st()
 
==== ldap_url_search_st()  ====
 
The ldap_url_search_st() function searches the directory, synchronously within a specified time limit, for matching entries, based on the contents of the URL.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_url_search_st( LDAP *ld, const char *url, int attrsonly,
  struct timeval *timeout, LDAPMessage **res );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_url_search_st() Function Parameters"
|+ ldap_url_search_st() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>url</tt>
| LDAP URL specifying a search of the directory.
|-
| <tt>attrsonly</tt>
| Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
*<tt>0</tt> specifies that both attribute types and attribute values are returned.
*<tt>1</tt> specifies that only attribute types are returned.
 
|-
| <tt>timeout</tt>
| Maximum time to wait for the results of the search.
|-
| <tt>res</tt>
| Results of the search (when the call is completed).
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
*LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
*LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
*LDAP_FILTER_ERROR if an error occurred when parsing and BER-encoding the search filter specified by the filter argument.
*LDAP_TIMEOUT if the search exceeded the time specified by the <tt>timeoutp</tt> argument.
*LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
 
'''Note:''' Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.
 
===== Description  =====
 
The ldap_url_search_st() function searches the directory for matching entries, based on the contents of the URL. This function works like ldap_url_search_s() and lets you specify a time out period for the search.
 
===== See Also  =====
 
ldap_search(), ldap_search_s()
 
==== ldap_utf8characters()  ====
 
The ldap_utf8characters() function accepts a Unicode string and returns the number of characters.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
size_t ldap_utf8characters( const char* );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8characters() Function Parameter"
|+ ldap_utf8characters() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>char</tt>
| Pointer to a UTF-8 string.
|}
 
===== Returns  =====
 
Returns the number of UTF-8 characters in the <tt>0</tt> terminated array.
 
==== ldap_utf8copy()  ====
 
The ldap_utf8copy() function accepts a Unicode string and copies the characters to a destination.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8copy( char* dst, const char* src );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8copy() Function Parameter"
|+ ldap_utf8copy() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>dst</tt>
| Pointer to a destination for the copied characters.
|-
| <tt>src</tt>
| Pointer to a UTF-8 string to copy.
|}
 
===== Description  =====
 
ldap_utf8copy() copies a character from <tt>src</tt> to <tt>dst</tt>. This function handles any valid UTF-8 character (including <tt>\0</tt> and ASCII).
 
===== Returns  =====
 
The number of characters copied.
 
==== ldap_utf8getcc()  ====
 
The ldap_utf8getcc() function gets one UCS-4 character and moves the pointer to the next character.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
unsigned long ldap_utf8getcc( const char** src );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8getcc() Function Parameter"
|+ ldap_utf8getcc() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>src</tt>
| Pointer to a UCS-4 character.
|}
 
==== ldap_utf8isalnum()  ====
 
The ldap_utf8isalnum() function determines whether the character is an alphanumeric one.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8isalnum( char* s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8isalnum() Function Parameter"
|+ ldap_utf8isalnum() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>s</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8isalpha()  ====
 
The ldap_utf8isalpha() function determines whether the character is a letter.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8isalpha( char* s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8isalpha() Function Parameter"
|+ ldap_utf8isalpha() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>s</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8isdigit()  ====
 
The ldap_utf8isdigit() function determines whether the character is a number.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8isdigit( char* s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8isdigit() Function Parameter"
|+ ldap_utf8isdigit() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>s</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8isspace()  ====
 
The ldap_utf8isspace() function determines whether the character is a space, tab, newline, return or formfeed.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8isspace( char* s );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8isspace() Function Parameter"
|+ ldap_utf8isspace() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>s</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8len()  ====
 
The ldap_utf8len() function accepts a Unicode string and returns the number of bytes it contains.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
int ldap_utf8len( const char* );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8len() Function Parameter"
|+ ldap_utf8len() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>char</tt>
| Pointer to a UTF-8 string.
|}
 
==== ldap_utf8next()  ====
 
The ldap_utf8next() function accepts a character and returns a pointer to the character immediately following it.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char* ldap_utf8next( char* );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8next() Function Parameter"
|+ ldap_utf8next() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>char</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8prev()  ====
 
The ldap_utf8prev() function accepts a character and returns a pointer to the previous character.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char* ldap_utf8prev( char* );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8prev() Function Parameter"
|+ ldap_utf8prev() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>char</tt>
| Pointer to a UTF-8 character.
|}
 
==== ldap_utf8strtok_r()  ====
 
The ldap_utf8strtok_r() function gets the next token from a string.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
char* ldap_utf8strtok_r( char* src, const char* brk, char** next);</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_utf8strtok_r() Function Parameter"
|+ ldap_utf8strtok_r() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>src</tt>
| Pointer to a UTF-8 string from which to extract token.
|-
| <tt>brk</tt>
| Points to a <tt>NULL</tt> terminated set of delimiter characters.
|-
| <tt>next</tt>
| Pointer to the next token.
|}
 
===== Returns  =====
 
Returns a pointer to the next token. If there are no remaining tokens, returns a <tt>NULL</tt> pointer.
 
==== ldap_whoami()  ====
 
The ldap_whoami() function sends an asynchronous Who am I? extended operation request to determine the authorization identity associated with a connection.
 
===== Syntax  =====
<pre>LDAP_API(int) LDAP_CALL ldap_whoami( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_whoami() Function Parameters"
|+ ldap_whoami() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| msgidp
| Pointer to the message ID for this asynchronous call, for use with ldap_parse_whoami_result(), or to retrieve the result for use with ldap_parse_whoami().
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
==== ldap_whoami_s()  ====
 
The ldap_whoami_s() function sends a synchronous Who am I? extended operation request to determine the authorization identity associated with a connection.
 
===== Syntax  =====
<pre>LDAP_API(int) LDAP_CALL ldap_whoami_s( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls, char **authzid );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_whoami_s() Function Parameters"
|+ ldap_whoami_s() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| Pointer to an LDAP structure containing information about the connection to the LDAP server.
|-
| <tt>serverctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify <tt>NULL</tt> for this argument.
|-
| <tt>clientctrls</tt>
| Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify <tt>NULL</tt> for this argument.
|-
| authzid
| Pointer to the string to hold the authorization identity retrieved from the server.
|}
 
===== Returns  =====
 
One of the following values:
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR if any of the arguments are invalid.
*LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
*LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
*LDAP_NO_MEMORY if memory cannot be allocated.
 
==== ldap_vals2html()  ====
 
The ldap_vals2html() function writes the HTML representation of a set of values.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_vals2html( LDAP *ld, char *buf, char **vals, char *label,
  int labelwidth, unsigned long syntaxid, writeptype writeproc,
  void *writeparm, char *eol, int rdncount, char *urlprefix );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_vals2html() Function Parameters"
|+ ldap_vals2html() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The LDAP pointer obtained by a previous call to ldap_open() .
|-
| <tt>buf</tt>
| &nbsp;
|-
| <tt>vals</tt>
| A NULL terminated list of values, usually obtained by a call to ldap_get_values().
|-
| <tt>label</tt>
| A string (usually a friendly form of an LDAP attribute name) shown next to the values.
|-
| <tt>labelwidth</tt>
| Specifies the label margin (the number of blank spaces displayed to the left of the values). If zero is passed, a default label width is used.
|-
| <tt>syntaxid</tt>
| Display template attribute syntax identifier for a list of predefined <tt>LDAP_SYN_...</tt> values.
|-
| <tt>writeproc</tt>
| writeproc() function should be declared as:<br><tt>int writeproc( writeparm, p, len )</tt><br><tt>void *writeparm;</tt><br><tt>char *p;</tt><br><tt>int len;</tt><br>where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|-
| <tt>urlprefix</tt>
| Starting text to use when constructing an LDAP URL. The default is the string <tt>ldap://</tt>
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_vals2html() produces HTML output of a single set of LDAP attribute values.
 
===== See Also  =====
 
ldap_vals2text()
 
==== ldap_vals2text()  ====
 
The ldap_vals2text() function writes the text representation of an LDAP entry.
 
===== Syntax  =====
<pre>#include &lt;disptmpl.h&gt;
int ldap_vals2text( LDAP *ld, char *buf, char **vals, char *label,
  int labelwidth, unsigned long syntaxid, writeptype writeproc,
  void *writeparm, char *eol, int rdncount );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_vals2text() Function Parameters"
|+ ldap_vals2text() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The LDAP pointer obtained by a previous call to ldap_open() .
|-
| <tt>buf</tt>
| &nbsp;
|-
| <tt>vals</tt>
| A <tt>NULL</tt> terminated list of values, usually obtained by a call to ldap_get_values().
|-
| <tt>label</tt>
| A string (usually a friendly form of an LDAP attribute name) shown next to the values.
|-
| <tt>labelwidth</tt>
| Specifies the label margin (the number of blank spaces displayed to the left of the values). If zero is passed, a default label width is used.
|-
| <tt>syntaxid</tt>
| Display template attribute syntax identifier for a list of predefined <tt>LDAP_SYN_...</tt> values.
|-
| <tt>writeproc</tt>
| writeproc() function should be declared as:<br><tt>int writeproc( writeparm, p, len )</tt><br><tt>void *writeparm;</tt><br><tt>char *p;</tt><br><tt>int len;</tt><br>where <tt>p</tt> is a pointer to text to be written and <tt>len</tt> is the length of the text. p is guaranteed to be zero terminated.
|-
| <tt>writeparm</tt>
| A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
|-
| <tt>eol</tt>
| Lines of text are terminated with this string.
|-
| <tt>rdncount</tt>
| Limits the number of components that are displayed for DN attributes.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP error code on error.
 
===== Description  =====
 
ldap_vals2text() produces a text representation of a single set of LDAP attribute values.
 
===== See Also  =====
 
ldap_vals2html()
 
==== ldap_value_free()  ====
 
The ldap_value_free() function frees an array of values from memory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_value_free( char **values );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_value_free() Function Parameter"
|+ ldap_value_free() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>values</tt>
| Array of values.
|}
 
===== Description  =====
 
Use the ldap_value_free_len() function if the values are berval structures.
 
===== Example  =====
 
See the example under ldap_get_values().
 
===== See Also  =====
 
ldap_get_values(), ldap_value_free_len
 
==== ldap_value_free_len()  ====
 
The ldap_value_free_len() function frees an array of berval structures from memory.
 
===== Syntax  =====
<pre>#include &lt;ldap.h&gt;
void ldap_value_free_len( struct berval **values );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_value_free_len() Function Parameter"
|+ ldap_value_free_len() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>values</tt>
| Array of berval structures.
|}
 
===== Description  =====
 
Use the ldap_value_free() function instead of this function if the values are string values.
 
===== Example  =====
 
See the example under ldap_get_values_len().
 
===== See Also  =====
 
ldap_get_values(), ldap_get_values_len
 
==== ldap_version()  ====
<pre>#include &lt;ldap.h&gt;
int ldap_version( LDAPVersion *ver );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_version() Function Parameter"
|+ ldap_version() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ver</tt>
| LDAPVersion structure returning version information. If you only want the SDK version, you can pass <tt>NULL</tt> for this parameter.
|}
 
===== Returns  =====
 
The version number of the Directory SDK For C, multiplied by 100. For example, for version 1.0, the function returns 100.
 
===== See Also  =====
 
ldap_get_option()
 
==== ldap_x_calloc()  ====
 
The ldap_x_calloc() function allocates space for an array of elements.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
void *ldap_x_calloc( size_t nelem, size_t elsize );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_x_calloc() Function Parameters"
|+ ldap_x_calloc() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>nelem</tt>
| Number of elements for which memory is to be allocated.
|-
| <tt>elsize</tt>
| Size of each element.
|}
 
===== Returns  =====
 
*If successful, returns a pointer to the space.
*If there is no available memory, returns a <tt>NULL</tt> pointer.
 
===== See Also  =====
 
ldap_x_free(), ldap_x_malloc() , ldap_x_realloc()
 
==== ldap_x_free()  ====
 
The ldap_x_free() function frees allocated memory.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
void ldap_x_free( void *ptr );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_x_free() Function Parameter"
|+ ldap_x_free() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ptr</tt>
| Pointer to the block of memory to be freed.
|}
 
===== See Also  =====
 
ldap_x_calloc(), ldap_x_malloc(), ldap_x_realloc()
 
==== ldap_x_hostlist_first()  ====
 
The ldap_x_hostlist_first() function returns the first host and port defined in a host list file.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
int ldap_x_hostlist_first( char *hostlist, int defport, char **hostp,
  int *portp, struct ldap_x_hostlist_status **statusp );</pre>
===== Description  =====
 
ldap_x_hostlist_first() parses a space-separated host list (useful for implementing an extended I/O CONNECT callback function) and returns the first host and port defined.
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*If unsuccessful returns a valid LDAP API error code.
 
'''Note:''' A <tt>NULL</tt> or zero-length hostlist causes the host <tt>127.0.0.1</tt> to be returned.
 
===== See Also  =====
 
ldap_x_hostlist_status(), LDAP_X_EXTIOF_CONNECT_CALLBACK(),
 
==== ldap_x_hostlist_next()  ====
 
The ldap_x_hostlist_next() function returns the host and port defined in a host list file following the previous host and port returned.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
int ldap_x_hostlist_next( char **hostp, int *portp,
  struct ldap_x_hostlist_status **statusp );</pre>
===== Description  =====
 
This utility parses a space-separated host list (useful for implementing an extended I/O CONNECT callback function) and returns the host and port defined following the previous host and port returned.
 
===== Returns  =====
 
*LDAP_SUCCESS if successful. If no more
 
hosts are available, <tt>LDAP_SUCCESS</tt> is returned but <tt>hostp</tt> is set to <tt>NULL</tt>.
 
*If unsuccessful returns a valid LDAP API error code.
 
'''Note:''' A <tt>NULL</tt> or zero-length hostlist causes the host <tt>127.0.0.1</tt> to be returned.
 
===== See Also  =====
 
ldap_x_hostlist_status(), LDAP_X_EXTIOF_CONNECT_CALLBACK(),
 
==== ldap_x_hostlist_status()  ====
 
===== See Also  =====
 
ldap_x_hostlist_first(), ldap_x_hostlist_next(), LDAP_X_EXTIOF_CONNECT_CALLBACK()
 
==== ldap_x_hostlist_statusfree()  ====
 
===== See Also  =====
 
ldap_x_hostlist_first(), ldap_x_hostlist_next(), LDAP_X_EXTIOF_CONNECT_CALLBACK()
 
==== ldap_x_malloc()  ====
 
The ldap_x_malloc() function allocates space for an object.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
void *ldap_x_malloc( size_t size );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_x_malloc() Function Parameter"
|+ ldap_x_malloc() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>size</tt>
| Specifies the size for the allocated block of memory.
|}
 
===== See Also  =====
 
ldap_x_free(), ldap_x_calloc() , ldap_x_realloc()
 
==== ldap_x_realloc()  ====
 
The ldap_x_realloc() function changes the size of a block of memory.
 
===== Syntax  =====
<pre>#include &lt;ldap-extension.h&gt;
void *ldap_x_realloc( void *ptr, size_t size );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="ldap_x_realloc() Function Parameter"
|+ ldap_x_realloc() Function Parameter
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ptr</tt>
| Pointer to a block of memory.
|-
| <tt>size</tt>
| Specifies the new size of the block.
|}
 
===== See Also  =====
 
ldap_x_free(), ldap_x_calloc() , ldap_x_malloc()
 
==== prldap_get_default_socket_info()  ====
 
The prldap_get_default_socket_info() function retrieves default socket information.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_get_default_socket_info() Function Parameters"
|+ prldap_get_default_socket_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>fd</tt>
| The session handle returned from prldap_init().
|-
| <tt>soip</tt>
| Pointer to a structure containing socket specific information.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
*LDAP_PARAM_ERROR is returned if <tt>ld</tt> is <tt>NULL</tt>.
 
===== See Also  =====
 
prldap_set_default_socket_info()
 
==== prldap_get_session_info()  ====
 
The prldap_get_session_info() function retrieves application-specific data.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_get_session_info( LDAP *ld, void *sessionarg,
  PRLDAPSessionInfo *seip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_get_session_info() Function Parameters"
|+ prldap_get_session_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The session handle returned from prldap_init(). If <tt>NULL</tt>, the functions are installed as the default functions for all new LDAP handles.
|-
| <tt>seip</tt>
| Pointer to a structure with session information data.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== Description  =====
 
The prldap_get_session_option() function retrieves an option for an LDAP session handle or a session argument that is passed to the <tt>CONNECT</tt> , <tt>POLL</tt>, <tt>NEWHANDLE</tt>, or <tt>DISPOSEHANDLE</tt> extended I/O callbacks.
 
===== See Also  =====
 
prldap_set_session_info()
 
==== prldap_get_session_option()  ====
 
The prldap_get_session_option() function retrieves an option specific to the <tt>prldap</tt> layer.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_get_session_option( LDAP *ld, void *sessionarg,
  int option, ... );</pre>
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== Description  =====
 
The prldap_get_session_option() function retrieves an option for an LDAP session handle or a session argument that is passed to the <tt>CONNECT</tt> , <tt>POLL</tt>, <tt>NEWHANDLE</tt>, or <tt>DISPOSEHANDLE</tt> extended I/O callbacks.
 
===== See Also  =====
 
prldap_set_session_option()
 
==== prldap_get_socket_info()  ====
 
The prldap_get_socket_info() function retrieves socket-specific information based on parameters passed to the extended I/O callback functions.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_get_socket_info( int fd, void *socketarg,
  PRLDAPSocketInfo *soip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_get_socket_info() Function Parameters"
|+ prldap_get_socket_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>fd</tt>
| The session handle returned from prldap_init().
|-
| <tt>soip</tt>
| Pointer to a structure containing socket information data.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== See Also  =====
 
prldap_set_socket_info()
 
==== prldap_init()  ====
 
The prldap_init() function creates a new session handle with Netscape Portable Runtime (NSPR) I/O, threading, support for IPv6, and DNS functions installed.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
LDAP * prldap_init( const char *defhost, int defport, int shared );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_init() Function Parameters"
|+ prldap_init() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>defhost</tt>
| Space-delimited list of one or more host names (or IP address in dotted notation, such as <tt>192.168.0.99</tt>) of the LDAP servers that you want the LDAP client to connect to. The names can be in ''hostname '':''portnumber'' format (in which case, ''portnumber'' overrides the port number specified by the defport argument.
|-
| <tt>defport</tt>
| Default port number of the LDAP server. To specify the standard LDAP port (port 389), use <tt>LDAP_PORT</tt> as the value for this parameter.
|-
| <tt>shared</tt>
| Pass a non-zero value if you plan to use this LDAP handle for more than one thread.
|}
 
===== Returns  =====
 
*Pointer to LDAP session handle if successful.
*<tt>NULL</tt> if an error occurs.
 
===== Description  =====
 
To be able to use LDAP over Internet Protocol, version 6, IPv6, this function should be used rather than ldap_init().
 
===== See Also  =====
 
prldap_install_routines()
 
==== prldap_install_routines()  ====
 
The prldap_install_routines() function installs Netscape Portable Runtime (NSPR) I/O, threading, and DNS functions so they can be used by the LDAP session handle.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_install_routines( LDAP *ld, int shared );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_install_routines() Function Parameters"
|+ prldap_install_routines() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The session handle returned from prldap_init(). If <tt>NULL</tt>, the functions are installed as the default functions for all new LDAP handles.
|-
| <tt>shared</tt>
| Pass a non-zero value if you plan to use this LDAP handle for more than one thread.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== See Also  =====
 
prldap_init()
 
==== prldap_set_default_socket_info()  ====
 
The prldap_set_default_socket_info() function sets default socket information.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_set_default_socket_info() Function Parameters"
|+ prldap_set_default_socket_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>fd</tt>
| The session handle returned from prldap_init().
|-
| <tt>soip</tt>
| Pointer to a structure containing socket specific information.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*LDAP_PARAM_ERROR is returned if <tt>ld</tt> is <tt>NULL</tt>.
*An LDAP API error code if an error occurs.
 
===== See Also  =====
 
prldap_get_socket_info()
 
==== prldap_set_session_info()  ====
 
The prldap_set_session_info() function sets application-specific data.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_set_session_info( LDAP *ld, void *sessionarg,
  PRLDAPSessionInfo *seip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_set_session_info() Function Parameters"
|+ prldap_set_session_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The session handle returned from prldap_init().
|-
| <tt>seip</tt>
| Pointer to a structure containing session information data.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== Description  =====
 
The prldap_set_session_info() function sets application-specific data for an LDAP session handle or a session argument that is passed to the <tt>CONNECT</tt>, <tt>POLL</tt>, <tt>NEWHANDLE</tt>, or <tt>DISPOSEHANDLE</tt> extended I/O callbacks.
 
===== See Also  =====
 
prldap_get_session_info()
 
==== prldap_set_session_option()  ====
 
The prldap_set_session_option() function sets a session option specific to the <tt>prldap</tt> layer.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_set_session_option( LDAP *ld, void *sessionarg,
  int option, ... );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_set_session_option() Function Parameters"
|+ prldap_set_session_option() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>ld</tt>
| The session handle returned from prldap_init().
|-
| <tt>option</tt>
| &nbsp;
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== Description  =====
 
The prldap_set_session_option() function sets an option for an LDAP session handle or a session argument that is passed to the <tt>CONNECT</tt> , <tt>POLL</tt>, <tt>NEWHANDLE</tt>, or <tt>DISPOSEHANDLE</tt> extended I/O callbacks.
 
===== See Also  =====
 
prldap_get_session_option()
 
==== prldap_set_socket_info()  ====
 
The prldap_set_socket_info() function sets socket information.
 
===== Syntax  =====
<pre>#include &lt;ldappr.h&gt;
int prldap_set_socket_info( int fd, void *socketarg,
  PRLDAPSocketInfo *soip );</pre>
===== Parameters  =====
 
{| width="100%" cellspacing="1" cellpadding="1" border="1" summary="prldap_set_socket_info() Function Parameters"
|+ prldap_set_socket_info() Function Parameters
|-
! scope="col" | Parameter
! scope="col" | Description
|-
| <tt>fd</tt>
| The session handle returned from prldap_init().
|-
| <tt>soip</tt>
| Pointer to a structure containing socket information data.
|}
 
===== Returns  =====
 
*LDAP_SUCCESS if successful.
*An LDAP API error code if an error occurs.
 
===== Description  =====
 
The prldap_set_socket_info() function sets socket-specific information based on parameters passed to the extended I/O callback functions. For more information, see the <tt>ldappr.h</tt> header file.
 
===== See Also  =====
 
prldap_get_socket_info()
 
== Directory SDK for C Result Codes  ==
 
This section lists some of the result codes that can be returned by functions in the Directory SDK for C. For ease of use, they are first listed in numerical order, then in alphabetical order.
 
LDAP result codes are extensible; thus, LDAP v3 extensions may define their own error codes, and register them with the Internet Assigned Numbers Authority (IANA). The IANA maintains a [http://www.iana.org/assignments/ldap-parameters list of registered LDAP parameters], including result codes. This list includes what Directory SDK for C currently knows in terms of result codes. More information can be found in RFC 4520, ''Internet Assigned Numbers Authority (IANA) Considerations for the Lightweight Directory Access Protocol (LDAP)''.
 
=== Result Codes Summary in Numerical Order  ===
 
The following table gives the decimal and hexadecimal value of all result codes. Values missing from the sequence are not assigned to a result code.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Numerical Listing of Result Codes"
|+ Numerical Listing of Result Codes
|-
! scope="col" | Decimal
! scope="col" | Hexadecimal
! scope="col" | Defined Name
|-
| 0
| 0x00
| LDAP_SUCCESS
|-
| 1
| 0x01
| LDAP_OPERATIONS_ERROR
|-
| 2
| 0x02
| LDAP_PROTOCOL_ERROR
|-
| 3
| 0x03
| LDAP_TIMELIMIT_EXCEEDED
|-
| 4
| 0x04
| LDAP_SIZELIMIT_EXCEEDED
|-
| 5
| 0x05
| LDAP_COMPARE_FALSE
|-
| 6
| 0x06
| LDAP_COMPARE_TRUE
|-
| 7
| 0x07
| LDAP_STRONG_AUTH_NOT_SUPPORTED
|-
| 8
| 0x08
| LDAP_STRONG_AUTH_REQUIRED
|-
| 9
| 0x09
| LDAP_PARTIAL_RESULTS
|-
| 10
| 0x0a
| LDAP_REFERRAL
|-
| 11
| 0x0b
| LDAP_ADMINLIMIT_EXCEEDED
|-
| 12
| 0x0c
| LDAP_UNAVAILABLE_CRITICAL_EXTENSION
|-
| 13
| 0x0d
| LDAP_CONFIDENTIALITY_REQUIRED
|-
| 14
| 0x0e
| LDAP_SASL_BIND_IN_PROGRESS
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 16
| 0x10
| LDAP_NO_SUCH_ATTRIBUTE
|-
| 17
| 0x11
| LDAP_UNDEFINED_TYPE
|-
| 18
| 0x12
| LDAP_INAPPROPRIATE_MATCHING
|-
| 19
| 0x13
| LDAP_CONSTRAINT_VIOLATION
|-
| 20
| 0x14
| LDAP_TYPE_OR_VALUE_EXISTS
|-
| 21
| 0x15
| LDAP_INVALID_SYNTAX
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 32
| 0x20
| LDAP_NO_SUCH_OBJECT
|-
| 33
| 0x21
| LDAP_ALIAS_PROBLEM
|-
| 34
| 0x22
| LDAP_INVALID_DN_SYNTAX
|-
| 35
| 0x23
| LDAP_IS_LEAF
|-
| 36
| 0x24
| LDAP_ALIAS_DEREF_PROBLEM
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 48
| 0x30
| LDAP_INAPPROPRIATE_AUTH
|-
| 49
| 0x31
| LDAP_INVALID_CREDENTIALS
|-
| 50
| 0x32
| LDAP_INSUFFICIENT_ACCESS
|-
| 51
| 0x33
| LDAP_BUSY
|-
| 52
| 0x34
| LDAP_UNAVAILABLE
|-
| 53
| 0x35
| LDAP_UNWILLING_TO_PERFORM
|-
| 54
| 0x36
| LDAP_LOOP_DETECT
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 60
| 0x3C
| LDAP_SORT_CONTROL_MISSING
|-
| 61
| 0x3D
| LDAP_INDEX_RANGE_ERROR
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 64
| 0x40
| LDAP_NAMING_VIOLATION
|-
| 65
| 0x41
| LDAP_OBJECT_CLASS_VIOLATION
|-
| 66
| 0x42
| LDAP_NOT_ALLOWED_ON_NONLEAF
|-
| 67
| 0x43
| LDAP_NOT_ALLOWED_ON_RDN
|-
| 68
| 0x44
| LDAP_ALREADY_EXISTS
|-
| 69
| 0x45
| LDAP_NO_OBJECT_CLASS_MODS
|-
| 70
| 0x46
| LDAP_RESULTS_TOO_LARGE
|-
| 71
| 0x47
| LDAP_AFFECTS_MULTIPLE_DSAS
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 80
| 0x50
| LDAP_OTHER
|-
| 81
| 0x51
| LDAP_SERVER_DOWN
|-
| 82
| 0x52
| LDAP_LOCAL_ERROR
|-
| 83
| 0x53
| LDAP_ENCODING_ERROR
|-
| 84
| 0x54
| LDAP_DECODING_ERROR
|-
| 85
| 0x55
| LDAP_TIMEOUT
|-
| 86
| 0x56
| LDAP_AUTH_UNKNOWN
|-
| 87
| 0x57
| LDAP_FILTER_ERROR
|-
| 88
| 0x58
| LDAP_USER_CANCELLED
|-
| 89
| 0x59
| LDAP_PARAM_ERROR
|-
| 90
| 0x5a
| LDAP_NO_MEMORY
|-
| 91
| 0x5b
| LDAP_CONNECT_ERROR
|-
| 92
| 0x5c
| LDAP_NOT_SUPPORTED
|-
| 93
| 0x5d
| LDAP_CONTROL_NOT_FOUND
|-
| 94
| 0x5e
| LDAP_NO_RESULTS_RETURNED
|-
| 95
| 0x5f
| LDAP_MORE_RESULTS_TO_RETURN
|-
| 96
| 0x60
| LDAP_CLIENT_LOOP
|-
| 97
| 0x61
| LDAP_REFERRAL_LIMIT_EXCEEDED
|}
 
=== Result Codes Reference in Alphabetical Order  ===
 
The following section contains the detailed reference information for each result code listed in alphabetical order by code name.
 
<tt>LDAP_ADMINLIMIT_EXCEEDED</tt>
 
This result code indicates that the look-through limit on a search operation has been exceeded. The ''look-through limit'' is the maximum number of entries that the server will check when gathering a list of potential search result candidates.
 
'''Note:''' When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN, the server sets an infinite look-through limit.
*If you are not bound as the root DN, the server sets a time limit.
 
<tt>#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* 11 */</tt>
 
----
 
<tt>LDAP_AFFECTS_MULTIPLE_DSAS</tt>
 
This result code indicates that the requested operation needs to be performed on multiple servers, where this operation is not permitted.
 
<tt>#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* 71 */</tt>
 
----
 
<tt>LDAP_ALIAS_DEREF_PROBLEM</tt>
 
This result code indicates that a problem occurred when dereferencing an alias.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_ALIAS_DEREF_PROBLEM 0x24 /* 36 */</tt>
 
----
 
<tt>LDAP_ALIAS_PROBLEM</tt>
 
This result code indicates that the alias is invalid.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_ALIAS_PROBLEM 0x21 /* 33 */</tt>
 
----
 
<tt>LDAP_ALREADY_EXISTS</tt>
 
This result code indicates that the request is attempting to add an entry that already exists in the directory. Directory Server sends this result code back to the client in the following situations:
 
*The request is an add request, and the entry already exists in the directory.
*The request is a modify DN request, and the new DN of the entry already identifies another entry.
*The request is adding an attribute to the schema, and an attribute with the specified name or object identifier (OID) already exists.
 
<tt>#define LDAP_ALREADY_EXISTS 0x44 /* 68 */</tt>
 
----
 
<tt>LDAP_AUTH_UNKNOWN</tt>
 
This result code indicates that an unknown authentication method was specified.
 
'''Note:''' Directory SDK For C library sets this result code if ldap_bind() or ldap_bind_s() are called and an authentication method other than <tt>LDAP_AUTH_SIMPLE</tt> is specified. These functions only allow you to use simple authentication.
 
<tt>#define LDAP_AUTH_UNKNOWN 0x56 /* 86 */</tt>
 
----
 
<tt>LDAP_BUSY</tt>
 
This result code indicates that the server is currently too busy to perform the requested operation.
 
<tt>#define LDAP_BUSY 0x33 /* 51 */</tt>
 
----
 
<tt>LDAP_CLIENT_LOOP</tt>
 
This result code indicates that the LDAP client detected a loop, for example, when following referrals.
 
<tt>#define LDAP_CLIENT_LOOP 0x60 /* 96 */</tt>
 
----
 
<tt>LDAP_COMPARE_FALSE</tt>
 
This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is not present in the specified entry.
 
<tt>#define LDAP_COMPARE_FALSE 0x05 /* 5 */</tt>
 
----
 
<tt>LDAP_COMPARE_TRUE</tt>
 
This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is present in the specified entry.
 
<tt>#define LDAP_COMPARE_TRUE 0x06 /* 6 */</tt>
 
----
 
<tt>LDAP_CONFIDENTIALITY_REQUIRED</tt>
 
This result code indicates that confidentiality is required for the operation.
 
<tt>#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* 13 */</tt>
 
----
 
<tt>LDAP_CONNECT_ERROR</tt>
 
This result code indicates that the LDAP client cannot establish a connection, or has lost the connection, with the LDAP server. Directory SDK For C sets this result code. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.
 
<tt>#define LDAP_CONNECT_ERROR 0x5b /* 91 */</tt>
 
----
 
<tt>LDAP_CONSTRAINT_VIOLATION</tt>
 
This result code indicates that a value in the request does not comply with certain constraints. Directory Server sends this result code back to the client in the following situations:
 
*The request adds or modifies the <tt>userpassword</tt> attribute, and one of the following is true:
**The server is configured to check the password syntax, and the length of the new password is less than the minimum password length.
**The server is configured to check the password syntax, and the new password is the same as one of the values of the <tt>uid</tt>, <tt>cn</tt>, <tt>sn</tt>, <tt>givenname</tt>, <tt>ou</tt>, or <tt>mail</tt> attributes.
**The server is configured to keep a history of previous passwords, and the new password is the same as one of the previous passwords. The request is a bind request, and the user is locked out of the account. (For example, the server can be configured to lock a user out of the account after a given number of failed attempts to bind to the server.)
 
<tt>#define LDAP_CONSTRAINT_VIOLATION 0x13 /* 19 */</tt>
 
----
 
<tt>LDAP_CONTROL_NOT_FOUND</tt>
 
This result code indicates that a requested LDAP control was not found. Directory SDK For C sets this result code when parsing a server response for controls and not finding the requested controls. For example:
 
*ldap_parse_entrychange_control() is called, but no entry change notification control is found in the server’s response.
*ldap_parse_sort_control() is called, but no server-side sorting control is found in the server’s response.
*ldap_parse_virtuallist_control() is called, but no virtual list view response control is found in the server’s response.
 
<tt>#define LDAP_CONTROL_NOT_FOUND 0x5d /* 93 */</tt>
 
----
 
<tt>LDAP_DECODING_ERROR</tt>
 
This result code indicates that the LDAP client encountered an error when decoding the LDAP response received from the server.
 
<tt>#define LDAP_DECODING_ERROR 0x54 /* 84 */</tt>
 
----
 
<tt>LDAP_ENCODING_ERROR</tt>
 
This result code indicates that the LDAP client encountered an error when encoding the LDAP request to be sent to the server.
 
<tt>#define LDAP_ENCODING_ERROR 0x53 /* 83 */</tt>
 
----
 
<tt>LDAP_FILTER_ERROR</tt>
 
This result code indicates that an error occurred when specifying the search filter. Directory SDK For C sets this result code if it cannot encode the specified search filter in an LDAP search request.
 
<tt>#define LDAP_FILTER_ERROR 0x57 /* 87 */</tt>
 
----
 
<tt>LDAP_INAPPROPRIATE_AUTH</tt>
 
This result code indicates that the type of credentials are not appropriate for the method of authentication used. Directory Server sends this result code back to the client if simple authentication is used in a bind request, but the entry has no <tt>userpassword</tt> attribute; also, if <tt>LDAP_SASL_EXTERNAL</tt> is attempted on a non-SSL connection.
 
<tt>#define LDAP_INAPPROPRIATE_AUTH 0x30 /* 48 */</tt>
 
----
 
<tt>LDAP_INAPPROPRIATE_MATCHING</tt>
 
This result code indicates that an extensible match filter in a search request contained a matching rule that does not apply to the specified attribute type.
 
<tt>#define LDAP_INAPPROPRIATE_MATCHING 0x12 /* 18 */</tt>
 
----
 
<tt>LDAP_INDEX_RANGE_ERROR</tt>
 
This result code indicates that the search results exceeded the range specified by the requested offsets. This result code applies to search requests that contain ''virtual list view'' controls.
 
<tt>#define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 */</tt>
 
----
 
<tt>LDAP_INSUFFICIENT_ACCESS</tt>
 
This result code indicates that the client has insufficient access to perform the operation. Check that the user you are authenticating as has the appropriate permissions.
 
<tt>#define LDAP_INSUFFICIENT_ACCESS 0x32 /* 50 */</tt>
 
----
 
<tt>LDAP_INVALID_CREDENTIALS</tt>
 
This result code indicates that the credentials provided in the request are invalid. Directory Server sends this result code back to the client if a bind request contains the incorrect credentials for a user or if a user’s password has already expired.
 
<tt>#define LDAP_INVALID_CREDENTIALS 0x31 /* 49 */</tt>
 
----
 
<tt>LDAP_INVALID_DN_SYNTAX</tt>
 
This result code indicates than an invalid DN has been specified. Directory Server sends this result code back to the client if an add request or a modify DN request specifies an invalid DN. It also sends this code when an <tt>LDAP_SASL_EXTERNAL</tt> bind is attempted but certification to DN mapping fails.
 
<tt>#define LDAP_INVALID_DN_SYNTAX 0x22 /* 34 */</tt>
 
----
 
<tt>LDAP_INVALID_SYNTAX</tt>
 
This result code indicates that the request contains invalid syntax. Directory Server sends this result code back to the client in the following situations:
 
*The server encounters an access control instruction (ACI) with invalid syntax.
*The request attempts to add or modify an <tt>aci</tt> attribute, and the value of the attribute is an ACI with invalid syntax.
*The request is a search request with a substring filter, and the syntax of the filter is invalid.
*The request is a modify request that is attempting to modify the schema, but no values are provided (for example, the request might be attempting to delete all values of the <tt>objectclass</tt> attribute).
 
<tt>#define LDAP_INVALID_SYNTAX 0x15 /* 21 */</tt>
 
----
 
<tt>LDAP_IS_LEAF</tt>
 
This result code indicates that the specified entry is a leaf entry.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_IS_LEAF 0x23 /* 35 */</tt>
 
----
 
<tt>LDAP_LOCAL_ERROR</tt>
 
This result code indicates that an error occurred in the LDAP client, though it may also be returned by Directory Server.
 
<tt>#define LDAP_LOCAL_ERROR 0x52 /* 82 */</tt>
 
----
 
<tt>LDAP_LOOP_DETECT</tt>
 
This result code indicates that the server was unable to perform the requested operation because of an internal loop.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_LOOP_DETECT 0x36 /* 54 */</tt>
 
----
 
<tt>LDAP_MORE_RESULTS_TO_RETURN</tt>
 
This result code indicates that there are more results in the chain of results. The Directory SDK For C sets this result code when the ldap_parse_sasl_bind_result() function is called to retrieve the result code of an operation, and additional result codes from the server are available in the LDAP structure.
 
<tt>#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* 95 */</tt>
 
----
 
<tt>LDAP_NAMING_VIOLATION</tt>
 
This result code indicates that the request violates the structure of the DIT.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_NAMING_VIOLATION 0x40 /* 64 */</tt>
 
----
 
<tt>LDAP_NO_MEMORY</tt>
 
This result code indicates that no memory is available. Directory SDK For C sets this result code if a function cannot allocate memory (for example, when creating an LDAP request or an LDAP control).
 
<tt>#define LDAP_NO_MEMORY 0x5a /* 90 */</tt>
 
----
 
<tt>LDAP_NO_OBJECT_CLASS_MODS</tt>
 
This result code indicates that the request is attempting to modify an object class that should not be modified (for example, a structural object class).
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_NO_OBJECT_CLASS_MODS 0x45 /* 69 */</tt>
 
----
 
<tt>LDAP_NO_RESULTS_RETURNED</tt>
 
This result code indicates that no results were returned from the server. The Directory SDK For C sets this result code when the ldap_parse_result() function is called but no result code is included in the server’s response.
 
<tt>#define LDAP_NO_RESULTS_RETURNED 0x5E /* 94 */</tt>
 
----
 
<tt>LDAP_NO_SUCH_ATTRIBUTE</tt>
 
This result code indicates that the specified attribute does not exist in the entry. Directory Server might send this result code back to the client if, for example, a modify request specifies the modification or removal of a non-existent attribute or if a compare request specifies a non-existent attribute.
 
<tt>#define LDAP_NO_SUCH_ATTRIBUTE 0x10 /* 16 */</tt>
 
----
 
<tt>LDAP_NO_SUCH_OBJECT</tt>
 
This result code indicates that the server cannot find an entry specified in the request. Directory Server sends this result code back to the client if it cannot find a requested entry and it cannot refer your client to another LDAP server.
 
<tt>#define LDAP_NO_SUCH_OBJECT 0x20 /* 32 */</tt>
 
----
 
<tt>LDAP_NOT_ALLOWED_ON_NONLEAF</tt>
 
This result code indicates that the requested operation is allowed only on entries that do not have child entries (''leaf'' entries as opposed to ''branch'' entries). Directory Server sends this result code back to the client if the request is a delete request or a modify DN request and the entry is a parent entry. You cannot delete or move a branch of entries in a single operation.
 
<tt>#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 /* 66 */</tt>
 
----
 
<tt>LDAP_NOT_ALLOWED_ON_RDN</tt>
 
This result code indicates that the requested operation will affect the RDN of the entry. Directory Server sends this result code back to the client if the request is a modify request that deletes attribute values from the entry that are used in the RDN of the entry. (For example, the request removes the attribute value <tt>uid=bjensen</tt> from the entry <tt>uid=bjensen,ou=People,dc=example,dc=com</tt>.)
 
<tt>#define LDAP_NOT_ALLOWED_ON_RDN 0x43 /* 67 */</tt>
 
----
 
<tt>LDAP_NOT_SUPPORTED</tt>
 
This result code indicates that the LDAP client is attempting to use functionality that is not supported. Directory SDK For C sets this result code if the client identifies itself as an LDAP v2 client, and the client is attempting to use functionality available in LDAP v3. For example:
 
*You are passing LDAP controls to a function.
*You are calling ldap_extended_operation() , ldap_extended_operation_s(), or ldap_parse_extended_result() to request an extended operation or to parse an extended response.
*You are calling ldap_rename() or ldap_rename_s(), and you are specifying a new superior DN as an argument.
*You are calling ldap_sasl_bind(), ldap_sasl_bind_s(), or ldap_parse_sasl_bind_result() to request Simple Authentication and Security Layer (SASL) authentication or to parse a SASL bind response.
*You are calling ldap_parse_virtuallist_control() to parse a virtual list control from the server’s response.
 
If you want to use these features, make sure to specify that your LDAP client is an LDAP v3 client.
 
<tt>#define LDAP_NOT_SUPPORTED 0x5c /* 92 */</tt>
 
----
 
<tt>LDAP_OBJECT_CLASS_VIOLATION</tt>
 
This result code indicates that the request specifies a new entry or a change to an existing entry that does not comply with the server’s schema. Directory Server sends this result code back to the client in the following situations:
 
*The request is an add request, and the new entry does not comply with the schema. For example, the new entry does not have all the required attributes, or the entry has attributes that are not allowed in the entry.
*The request is a modify request, and the change will make the entry non compliant with the schema. For example, the change removes a required attribute or adds an attribute that is not allowed.
 
Check the server error logs for more information, and the schema for the type of entry that you are adding or modifying.
 
<tt>#define LDAP_OBJECT_CLASS_VIOLATION 0x41 /* 65 */</tt>
 
----
 
<tt>LDAP_OPERATIONS_ERROR</tt>
 
This is a general result code indicating that an error has occurred. Directory Server might send this code if, for example, memory cannot be allocated on the server. To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_OPERATIONS_ERROR 0x01 /* 1 */</tt>
 
----
 
<tt>LDAP_OTHER</tt>
 
This result code indicates than an unknown error has occurred. This error may be returned by Directory Server when an error occurs that is not better described using another LDAP error code. When this error occurs, check the server's error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_OTHER 0x50 /* 80 */</tt>
 
----
 
<tt>LDAP_PARAM_ERROR</tt>
 
This result code indicates that an invalid parameter was specified. Directory SDK For C sets this result code if a function was called and invalid parameters were specified, for example, if the LDAP structure is <tt>NULL</tt>.
 
<tt>#define LDAP_PARAM_ERROR 0x59 /* 89 */</tt>
 
----
 
<tt>LDAP_PARTIAL_RESULTS</tt>
 
Directory Server sends this result code to LDAP v2 clients to refer them to another LDAP server. When sending this code to a client, the server includes a new line-delimited list of LDAP URLs that identifies another LDAP server. If the client identifies itself as an LDAP v3 client in the request, an LDAP_REFERRAL result code is sent instead of this result code.
 
<tt>#define LDAP_PARTIAL_RESULTS 0x09 /* 9 */</tt>
 
----
 
<tt>LDAP_PROTOCOL_ERROR</tt>
 
This result code indicates that the LDAP client’s request does not comply with the LDAP. Directory Server sends this result code back to the client in the following situations:
 
*The server cannot parse the incoming request.
*The request specifies an attribute type that uses a syntax not supported by the server.
*The request is a SASL bind request, but your client identifies itself as an LDAP v2 client.
*The request is a bind request that specifies an unsupported version of the LDAP. Make sure to specify whether your LDAP client is an LDAP v2 client or an LDAP v3 client.
*The request is an add or a modify request that specifies the addition of an attribute type to an entry, but no values are specified.
*The request is a modify request, and one of the following is true:
**An unknown modify operation is specified (an operation other than <tt>LDAP_MOD_ADD</tt>, <tt>LDAP_MOD_DELETE</tt>, and <tt>LDAP_MOD_REPLACE</tt>).
**No modifications are specified.
*The request is a modify DN request, and one of the following is true:
**The new RDN is not a valid RDN.
**A new superior DN is specified, but your client identifies itself as an LDAP v2 client.
*The request is a search request, and one of the following is true:
**An unknown scope is specified, meaning a scope other than <tt>LDAP_SCOPE_BASE</tt> , <tt>LDAP_SCOPE_ONELEVEL</tt>, or <tt>LDAP_SCOPE_SUBTREE </tt>.
**An unknown filter type is specified.
**The filter type <tt>LDAP_FILTER_GE</tt> or <tt>LDAP_FILTER_LE </tt> is specified, but the type of attribute contains values that cannot be ordered. (For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.)
**The request contains an extensible filter (a filter using matching rules), but your client identifies itself as an LDAP v2 client.
**The request contains an extensible filter (a filter using matching rules), but the matching rule is not supported by the server.
*The request is a search request with a server-side sorting control, and one of the following is true:
**The server does not have a syntax plug-in that supports the attribute used for sorting.
**The syntax plug-in does not have a function for comparing values of the attribute. (This compare function is used for sorting.)
**The type of attribute specified for sorting contains values that cannot be sorted in any order. For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.
**The server encounters an error when creating the sorting response control (the control to be sent back to the client).
**When sorting the results, the time limit or the look-through limit is exceeded. The look-through limit is the maximum number of entries that the server will check when gathering a list of potential search result candidates.
*The request is an extended operation request, and the server does not support the extended operation. In Directory Server, extended operations are supported through extended operation server plug-ins. Make sure that the server is loading a plug-in that supports the extended operation. Check the OID of the extended operation in your LDAP client to make sure that it matches the OID of the extended operation registered in the server plug-in.
*An authentication method other than <tt>LDAP_AUTH_SIMPLE</tt> or <tt>LDAP_AUTH_SASL</tt> is specified.
 
To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_PROTOCOL_ERROR 0x02 /* 2 */</tt>
 
----
 
<tt>LDAP_REFERRAL</tt>
 
This result code indicates that the server is referring the client to another LDAP server. When sending this code to a client, the server includes a list of LDAP URLs that identify another LDAP server. This result code is part of the LDAP v3. For LDAP v2 clients, Directory Server sends an LDAP_PARTIAL_RESULTS result code instead.
 
<tt>#define LDAP_REFERRAL 0x0a /* 10 */</tt>
 
----
 
<tt>LDAP_REFERRAL_LIMIT_EXCEEDED</tt>
 
This result code indicates that the referral hop limit''was exceeded. Directory SDK For C sets this'' result code, when following referrals, if the client is referred to other servers more times than allowed by the ''referral hop limit''.
 
<tt>#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* 97 */</tt>
 
----
 
<tt>LDAP_RESULTS_TOO_LARGE</tt>
 
This result code indicates that the results of the request are too large.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_RESULTS_TOO_LARGE 0x46 /* 70 */</tt>
 
----
 
<tt>LDAP_SASL_BIND_IN_PROGRESS</tt>
 
This result code is used in multi stage SASL bind operations. The server sends this result code back to the client to indicate that the authentication process has not yet completed.
 
<tt>#define LDAP_SASL_BIND_IN_PROGRESS 0x0E /* 14 */</tt>
 
----
 
<tt>LDAP_SERVER_DOWN</tt>
 
This result code indicates that Directory SDK For C cannot establish a connection with, or lost the connection to, the LDAP server. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.
 
<tt>#define LDAP_SERVER_DOWN 0x51 /* 81 */</tt>
 
----
 
<tt>LDAP_SIZELIMIT_EXCEEDED</tt>
 
This result code indicates that the maximum number of search results to return has been exceeded. This limit is specified in the search request. If you specify no size limit, the server will set one. When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN and specify no size limit, the server enforces no size limit at all.
*If you are not bound as the root DN and specify no size limit, the server sets the size limit to the value specified by the <tt>sizelimit</tt> directive in the server’s <tt>slapd.conf</tt> configuration file.
*If the size limit that you specify exceeds the value specified by the <tt>sizelimit</tt> directive in the server’s <tt>slapd.conf </tt> configuration file, the server uses the size limit specified in the configuration file.
 
<tt>#define LDAP_SIZELIMIT_EXCEEDED 0x04 /* 4 */</tt>
 
----
 
<tt>LDAP_SORT_CONTROL_MISSING</tt>
 
This result code indicates that server did not receive a required server-side sorting control. Directory Server sends this result code back to the client if the server receives a search request with a ''virtual list view'' control but no server-side sorting control as the ''virtual list view'' control requires a server-side sorting control.
 
<tt>#define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 */</tt>
 
----
 
<tt>LDAP_STRONG_AUTH_NOT_SUPPORTED</tt>
 
This result code is returned as the result of a bind operation. It indicates that the server does not recognize or support the specified authentication method.
 
<tt>#define LDAP_STRONG_AUTH_NOT_SUPPORTED 0x07 /* 7 */</tt>
 
----
 
<tt>LDAP_STRONG_AUTH_REQUIRED</tt>
 
This result code indicates that a stronger method of authentication is required to perform the operation.
 
<tt>#define LDAP_STRONG_AUTH_REQUIRED 0x08 /* 8 */</tt>
 
----
 
<tt>LDAP_SUCCESS</tt>
 
This result code indicates that the LDAP operation was successful.
 
<tt>#define LDAP_SUCCESS 0x00 /* 0 */</tt>
 
----
 
<tt>LDAP_TIMELIMIT_EXCEEDED</tt>
 
This result code indicates that the time limit on a search operation has been exceeded. The time limit is specified in the search request. If you specify no time limit, the server will set one. When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN and specify no time limit, the server enforces no limit at all.
*If you are not bound as the root DN and specify no time limit, the server sets the time limit.
*If the time limit that you specify exceeds the time limit specified for the server configuration, the server uses the time limit specified in its configuration.
 
<tt>#define LDAP_TIMELIMIT_EXCEEDED 0x03 /* 3 */</tt>
 
----
 
<tt>LDAP_TIMEOUT</tt>
 
This result code indicates that the LDAP client timed out while waiting for a response from the server. Directory SDK For C sets this result code in the LDAP structure if the time-out period (for example, in a search request) has been exceeded and the server has not responded.
 
<tt>#define LDAP_TIMEOUT 0x55 /* 85 */</tt>
 
----
 
<tt>LDAP_TYPE_OR_VALUE_EXISTS</tt>
 
This result code indicates that the request attempted to add an attribute type or value that already exists. Directory Server sends this result code back to the client in the following situations:
 
*The request attempts to add values that already exist in the attribute.
*The request is adding an attribute to the schema of the server, but the OID of the attribute is already used by an object class in the schema.
*The request is adding an object class to the schema of the server, and one of the following occurs:
**The object class already exists.
**The OID of the object class is already used by another object class or an attribute in the schema.
**The superior object class for this new object class does not exist.
 
<tt>#define LDAP_TYPE_OR_VALUE_EXISTS 0x14 /* 20 */</tt>
 
----
 
<tt>LDAP_UNAVAILABLE</tt>
 
This result code indicates that the server is unavailable to perform the requested operation.
 
'''Note:''' At this point, neither Directory SDK For C nor Directory Server return this result code.
 
<tt>#define LDAP_UNAVAILABLE 0x34 /* 52 */</tt>
 
----
 
<tt>LDAP_UNAVAILABLE_CRITICAL_EXTENSION</tt>
 
This result code indicates that the specified control or matching rule is not supported by the server. Directory Server might send back this result code if the request includes an unsupported control or if the filter in the search request specifies an unsupported matching rule.
 
<tt>#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* 12 */</tt>
 
----
 
<tt>LDAP_UNDEFINED_TYPE</tt>
 
This result code indicates that the request specifies an undefined attribute type.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_UNDEFINED_TYPE 0x11 /* 17 */</tt>
 
----
 
<tt>LDAP_UNWILLING_TO_PERFORM</tt>
 
This result code indicates that the server is unwilling to perform the requested operation. Directory Server sends this result code back to the client in the following situations:
 
*The client has logged in for the first time and needs to change its password, but the client is requesting to perform other LDAP operations. In this situation, the result code is accompanied by an expired password control.
*The request is a modify DN request, and a superior DN is specified.
*The database is in read-only mode, and the request attempts to write to the directory.
*The request is a delete request that attempts to delete the root DSE.
*The request is a modify DN request that attempts to modify the DN of the root DSE.
*The request is a modify request to modify the schema entry, and one of the following occurs:
**The operation is <tt>LDAP_MOD_REPLACE</tt>. (The server does not allow you to replace schema entry attributes.)
**The request attempts to delete an object class that is the parent of another object class.
**The request attempts to delete a read-only object class or attribute.
*The server uses a database plug-in that does not implement the operation specified in the request. For example, if the database plug-in does not implement the add operation, sending an add request will return this result code.
 
<tt>#define LDAP_UNWILLING_TO_PERFORM 0x35 /* 53 */</tt>
 
----
 
<tt>LDAP_USER_CANCELLED</tt>
 
This result code indicates that the user cancelled the LDAP operation.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.  
 
<tt>#define LDAP_USER_CANCELLED 0x58 /* 88 */</tt>
 
----
 
<br>

Revision as of 10:13, 8 February 2011

My name's Mark Craig. I used to work for Sun Microsystems, leading the Directory Services documentation effort.

In mid 2007, Sun donated code and documentation for version 6 of the LDAP C SDK. The doc also covers the LDAP Java SDK. In February 2011, I wikified the DocBook SGML version as the Mozilla LDAP SDK Programmer's Guide.