This chapter explains how LDAPv3 extended operations work and how to use the extended operations that are supported by your LDAP server.
Extended operations are part of the LDAPv3 protocol. Each extended operation is identified by an OID.
LDAP clients can request the operation by sending an extended operation request. Within the request, the client specifies:
The server receives the request, and performs the extended operation. The server can send back to the client a response containing:
In order to use extended operations, both the server and the client must understand the specific extended operation to be performed.
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 object identifiers (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.
To perform an extended operation, call one of the following functions:
ldap_extended_operation_s()
function (see "Performing a
Synchronous Extended Operation").
ldap_extended_operation()
function (see "Performing
an Asynchronous Extended Operation").
For more information about the difference between synchronous and asynchronous functions, see "Calling Synchronous and Asynchronous Functions".
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 a LDAP extended operation,
make sure to specify that your client is using version 3 of the LDAP
protocol. If you do not, an LDAP_NOT_SUPPORTED result
code is returned. For details, see "Specifying
the LDAP Version of Your Client".
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 and
blocks until the server sends the results of the operation back to
your client.
The ldap_extended_operation_s() function returns
LDAP_SUCCESS if the operation completed successfully or
an error code if a problem occurred. See the documentation on the
ldap_extended_operation_s()
function for a list of the possible result codes.
If you want to perform other work (in parallel) while waiting an LDAP extended operation to complete, do the following:
ldap_extended_operation()
function.
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.
ldap_result()
function and pass in this message ID.
The ldap_result() function uses
the message ID to determine if the server sent an extended
operation response. The function passes back the response in an
LDAPMessage structure.
ldap_parse_extended_result()
function to parse the
LDAPMessage
structure and retrieve information from the server's response.
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 a data to your client, the
data is specified in the berval
structure passed back as the retdatap argument.
ldap_get_lderrno()
function to get the LDAP result code for the operation. 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 on the return values of the function
ldap_extended_operation_s()
for a list of result codes that the server can return for this
operation.
The following program is an example of an LDAP client that requests an extended operation with the OID 1.2.3.4 from the server.
Code Example 15-1 - Requesting an extended operation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#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 */
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 %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 ) != 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 ) ) != 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: %s\n", oidresult );
printf( "\tReturned value: %s\n", valresult->bv_val );
/* Disconnect from the server. */
ldap_unbind( ld );
return 0;
}